This is page 17 of 43. Use http://codebase.md/taurgis/sfcc-dev-mcp?lines=false&page={x} to view the full context. # Directory Structure ``` ├── .DS_Store ├── .github │ ├── dependabot.yml │ ├── instructions │ │ ├── mcp-node-tests.instructions.md │ │ └── mcp-yml-tests.instructions.md │ ├── ISSUE_TEMPLATE │ │ ├── bug_report.yml │ │ ├── config.yml │ │ ├── documentation.yml │ │ ├── feature_request.yml │ │ └── question.yml │ ├── PULL_REQUEST_TEMPLATE │ │ ├── bug_fix.md │ │ ├── documentation.md │ │ └── new_tool.md │ ├── pull_request_template.md │ └── workflows │ ├── ci.yml │ ├── deploy-pages.yml │ ├── publish.yml │ └── update-docs.yml ├── .gitignore ├── .husky │ └── pre-commit ├── aegis.config.docs-only.json ├── aegis.config.json ├── aegis.config.with-dw.json ├── AGENTS.md ├── ai-instructions │ ├── claude-desktop │ │ └── claude_custom_instructions.md │ ├── cursor │ │ └── .cursor │ │ └── rules │ │ ├── debugging-workflows.mdc │ │ ├── hooks-development.mdc │ │ ├── isml-templates.mdc │ │ ├── job-framework.mdc │ │ ├── performance-optimization.mdc │ │ ├── scapi-endpoints.mdc │ │ ├── security-patterns.mdc │ │ ├── sfcc-development.mdc │ │ ├── sfra-controllers.mdc │ │ ├── sfra-models.mdc │ │ ├── system-objects.mdc │ │ └── testing-patterns.mdc │ └── github-copilot │ └── copilot-instructions.md ├── CHANGELOG.md ├── CONTRIBUTING.md ├── docs │ ├── best-practices │ │ ├── cartridge_creation.md │ │ ├── isml_templates.md │ │ ├── job_framework.md │ │ ├── localserviceregistry.md │ │ ├── ocapi_hooks.md │ │ ├── performance.md │ │ ├── scapi_custom_endpoint.md │ │ ├── scapi_hooks.md │ │ ├── security.md │ │ ├── sfra_client_side_js.md │ │ ├── sfra_controllers.md │ │ ├── sfra_models.md │ │ └── sfra_scss.md │ ├── dw_campaign │ │ ├── ABTest.md │ │ ├── ABTestMgr.md │ │ ├── ABTestSegment.md │ │ ├── AmountDiscount.md │ │ ├── ApproachingDiscount.md │ │ ├── BonusChoiceDiscount.md │ │ ├── BonusDiscount.md │ │ ├── Campaign.md │ │ ├── CampaignMgr.md │ │ ├── CampaignStatusCodes.md │ │ ├── Coupon.md │ │ ├── CouponMgr.md │ │ ├── CouponRedemption.md │ │ ├── CouponStatusCodes.md │ │ ├── Discount.md │ │ ├── DiscountPlan.md │ │ ├── FixedPriceDiscount.md │ │ ├── FixedPriceShippingDiscount.md │ │ ├── FreeDiscount.md │ │ ├── FreeShippingDiscount.md │ │ ├── PercentageDiscount.md │ │ ├── PercentageOptionDiscount.md │ │ ├── PriceBookPriceDiscount.md │ │ ├── Promotion.md │ │ ├── PromotionMgr.md │ │ ├── PromotionPlan.md │ │ ├── SlotContent.md │ │ ├── SourceCodeGroup.md │ │ ├── SourceCodeInfo.md │ │ ├── SourceCodeStatusCodes.md │ │ └── TotalFixedPriceDiscount.md │ ├── dw_catalog │ │ ├── Catalog.md │ │ ├── CatalogMgr.md │ │ ├── Category.md │ │ ├── CategoryAssignment.md │ │ ├── CategoryLink.md │ │ ├── PriceBook.md │ │ ├── PriceBookMgr.md │ │ ├── Product.md │ │ ├── ProductActiveData.md │ │ ├── ProductAttributeModel.md │ │ ├── ProductAvailabilityLevels.md │ │ ├── ProductAvailabilityModel.md │ │ ├── ProductInventoryList.md │ │ ├── ProductInventoryMgr.md │ │ ├── ProductInventoryRecord.md │ │ ├── ProductLink.md │ │ ├── ProductMgr.md │ │ ├── ProductOption.md │ │ ├── ProductOptionModel.md │ │ ├── ProductOptionValue.md │ │ ├── ProductPriceInfo.md │ │ ├── ProductPriceModel.md │ │ ├── ProductPriceTable.md │ │ ├── ProductSearchHit.md │ │ ├── ProductSearchModel.md │ │ ├── ProductSearchRefinementDefinition.md │ │ ├── ProductSearchRefinements.md │ │ ├── ProductSearchRefinementValue.md │ │ ├── ProductVariationAttribute.md │ │ ├── ProductVariationAttributeValue.md │ │ ├── ProductVariationModel.md │ │ ├── Recommendation.md │ │ ├── SearchModel.md │ │ ├── SearchRefinementDefinition.md │ │ ├── SearchRefinements.md │ │ ├── SearchRefinementValue.md │ │ ├── SortingOption.md │ │ ├── SortingRule.md │ │ ├── Store.md │ │ ├── StoreGroup.md │ │ ├── StoreInventoryFilter.md │ │ ├── StoreInventoryFilterValue.md │ │ ├── StoreMgr.md │ │ ├── Variant.md │ │ └── VariationGroup.md │ ├── dw_content │ │ ├── Content.md │ │ ├── ContentMgr.md │ │ ├── ContentSearchModel.md │ │ ├── ContentSearchRefinementDefinition.md │ │ ├── ContentSearchRefinements.md │ │ ├── ContentSearchRefinementValue.md │ │ ├── Folder.md │ │ ├── Library.md │ │ ├── MarkupText.md │ │ └── MediaFile.md │ ├── dw_crypto │ │ ├── CertificateRef.md │ │ ├── CertificateUtils.md │ │ ├── Cipher.md │ │ ├── Encoding.md │ │ ├── JWE.md │ │ ├── JWEHeader.md │ │ ├── JWS.md │ │ ├── JWSHeader.md │ │ ├── KeyRef.md │ │ ├── Mac.md │ │ ├── MessageDigest.md │ │ ├── SecureRandom.md │ │ ├── Signature.md │ │ ├── WeakCipher.md │ │ ├── WeakMac.md │ │ ├── WeakMessageDigest.md │ │ ├── WeakSignature.md │ │ └── X509Certificate.md │ ├── dw_customer │ │ ├── AddressBook.md │ │ ├── AgentUserMgr.md │ │ ├── AgentUserStatusCodes.md │ │ ├── AuthenticationStatus.md │ │ ├── Credentials.md │ │ ├── Customer.md │ │ ├── CustomerActiveData.md │ │ ├── CustomerAddress.md │ │ ├── CustomerCDPData.md │ │ ├── CustomerContextMgr.md │ │ ├── CustomerGroup.md │ │ ├── CustomerList.md │ │ ├── CustomerMgr.md │ │ ├── CustomerPasswordConstraints.md │ │ ├── CustomerPaymentInstrument.md │ │ ├── CustomerStatusCodes.md │ │ ├── EncryptedObject.md │ │ ├── ExternalProfile.md │ │ ├── OrderHistory.md │ │ ├── ProductList.md │ │ ├── ProductListItem.md │ │ ├── ProductListItemPurchase.md │ │ ├── ProductListMgr.md │ │ ├── ProductListRegistrant.md │ │ ├── Profile.md │ │ └── Wallet.md │ ├── dw_extensions.applepay │ │ ├── ApplePayHookResult.md │ │ └── ApplePayHooks.md │ ├── dw_extensions.facebook │ │ ├── FacebookFeedHooks.md │ │ └── FacebookProduct.md │ ├── dw_extensions.paymentrequest │ │ ├── PaymentRequestHookResult.md │ │ └── PaymentRequestHooks.md │ ├── dw_extensions.payments │ │ ├── SalesforceBancontactPaymentDetails.md │ │ ├── SalesforceCardPaymentDetails.md │ │ ├── SalesforceEpsPaymentDetails.md │ │ ├── SalesforceIdealPaymentDetails.md │ │ ├── SalesforceKlarnaPaymentDetails.md │ │ ├── SalesforcePaymentDetails.md │ │ ├── SalesforcePaymentIntent.md │ │ ├── SalesforcePaymentMethod.md │ │ ├── SalesforcePaymentRequest.md │ │ ├── SalesforcePaymentsHooks.md │ │ ├── SalesforcePaymentsMgr.md │ │ ├── SalesforcePaymentsSiteConfiguration.md │ │ ├── SalesforcePayPalOrder.md │ │ ├── SalesforcePayPalOrderAddress.md │ │ ├── SalesforcePayPalOrderPayer.md │ │ ├── SalesforcePayPalPaymentDetails.md │ │ ├── SalesforceSepaDebitPaymentDetails.md │ │ └── SalesforceVenmoPaymentDetails.md │ ├── dw_extensions.pinterest │ │ ├── PinterestAvailability.md │ │ ├── PinterestFeedHooks.md │ │ ├── PinterestOrder.md │ │ ├── PinterestOrderHooks.md │ │ └── PinterestProduct.md │ ├── dw_io │ │ ├── CSVStreamReader.md │ │ ├── CSVStreamWriter.md │ │ ├── File.md │ │ ├── FileReader.md │ │ ├── FileWriter.md │ │ ├── InputStream.md │ │ ├── OutputStream.md │ │ ├── PrintWriter.md │ │ ├── RandomAccessFileReader.md │ │ ├── Reader.md │ │ ├── StringWriter.md │ │ ├── Writer.md │ │ ├── XMLIndentingStreamWriter.md │ │ ├── XMLStreamConstants.md │ │ ├── XMLStreamReader.md │ │ └── XMLStreamWriter.md │ ├── dw_job │ │ ├── JobExecution.md │ │ └── JobStepExecution.md │ ├── dw_net │ │ ├── FTPClient.md │ │ ├── FTPFileInfo.md │ │ ├── HTTPClient.md │ │ ├── HTTPRequestPart.md │ │ ├── Mail.md │ │ ├── SFTPClient.md │ │ ├── SFTPFileInfo.md │ │ ├── WebDAVClient.md │ │ └── WebDAVFileInfo.md │ ├── dw_object │ │ ├── ActiveData.md │ │ ├── CustomAttributes.md │ │ ├── CustomObject.md │ │ ├── CustomObjectMgr.md │ │ ├── Extensible.md │ │ ├── ExtensibleObject.md │ │ ├── Note.md │ │ ├── ObjectAttributeDefinition.md │ │ ├── ObjectAttributeGroup.md │ │ ├── ObjectAttributeValueDefinition.md │ │ ├── ObjectTypeDefinition.md │ │ ├── PersistentObject.md │ │ ├── SimpleExtensible.md │ │ └── SystemObjectMgr.md │ ├── dw_order │ │ ├── AbstractItem.md │ │ ├── AbstractItemCtnr.md │ │ ├── Appeasement.md │ │ ├── AppeasementItem.md │ │ ├── Basket.md │ │ ├── BasketMgr.md │ │ ├── BonusDiscountLineItem.md │ │ ├── CouponLineItem.md │ │ ├── CreateAgentBasketLimitExceededException.md │ │ ├── CreateBasketFromOrderException.md │ │ ├── CreateCouponLineItemException.md │ │ ├── CreateOrderException.md │ │ ├── CreateTemporaryBasketLimitExceededException.md │ │ ├── GiftCertificate.md │ │ ├── GiftCertificateLineItem.md │ │ ├── GiftCertificateMgr.md │ │ ├── GiftCertificateStatusCodes.md │ │ ├── Invoice.md │ │ ├── InvoiceItem.md │ │ ├── LineItem.md │ │ ├── LineItemCtnr.md │ │ ├── Order.md │ │ ├── OrderAddress.md │ │ ├── OrderItem.md │ │ ├── OrderMgr.md │ │ ├── OrderPaymentInstrument.md │ │ ├── OrderProcessStatusCodes.md │ │ ├── PaymentCard.md │ │ ├── PaymentInstrument.md │ │ ├── PaymentMethod.md │ │ ├── PaymentMgr.md │ │ ├── PaymentProcessor.md │ │ ├── PaymentStatusCodes.md │ │ ├── PaymentTransaction.md │ │ ├── PriceAdjustment.md │ │ ├── PriceAdjustmentLimitTypes.md │ │ ├── ProductLineItem.md │ │ ├── ProductShippingCost.md │ │ ├── ProductShippingLineItem.md │ │ ├── ProductShippingModel.md │ │ ├── Return.md │ │ ├── ReturnCase.md │ │ ├── ReturnCaseItem.md │ │ ├── ReturnItem.md │ │ ├── Shipment.md │ │ ├── ShipmentShippingCost.md │ │ ├── ShipmentShippingModel.md │ │ ├── ShippingLineItem.md │ │ ├── ShippingLocation.md │ │ ├── ShippingMethod.md │ │ ├── ShippingMgr.md │ │ ├── ShippingOrder.md │ │ ├── ShippingOrderItem.md │ │ ├── SumItem.md │ │ ├── TaxGroup.md │ │ ├── TaxItem.md │ │ ├── TaxMgr.md │ │ ├── TrackingInfo.md │ │ └── TrackingRef.md │ ├── dw_order.hooks │ │ ├── CalculateHooks.md │ │ ├── OrderHooks.md │ │ ├── PaymentHooks.md │ │ ├── ReturnHooks.md │ │ └── ShippingOrderHooks.md │ ├── dw_rpc │ │ ├── SOAPUtil.md │ │ ├── Stub.md │ │ └── WebReference.md │ ├── dw_suggest │ │ ├── BrandSuggestions.md │ │ ├── CategorySuggestions.md │ │ ├── ContentSuggestions.md │ │ ├── CustomSuggestions.md │ │ ├── ProductSuggestions.md │ │ ├── SearchPhraseSuggestions.md │ │ ├── SuggestedCategory.md │ │ ├── SuggestedContent.md │ │ ├── SuggestedPhrase.md │ │ ├── SuggestedProduct.md │ │ ├── SuggestedTerm.md │ │ ├── SuggestedTerms.md │ │ ├── Suggestions.md │ │ └── SuggestModel.md │ ├── dw_svc │ │ ├── FTPService.md │ │ ├── FTPServiceDefinition.md │ │ ├── HTTPFormService.md │ │ ├── HTTPFormServiceDefinition.md │ │ ├── HTTPService.md │ │ ├── HTTPServiceDefinition.md │ │ ├── LocalServiceRegistry.md │ │ ├── Result.md │ │ ├── Service.md │ │ ├── ServiceCallback.md │ │ ├── ServiceConfig.md │ │ ├── ServiceCredential.md │ │ ├── ServiceDefinition.md │ │ ├── ServiceProfile.md │ │ ├── ServiceRegistry.md │ │ ├── SOAPService.md │ │ └── SOAPServiceDefinition.md │ ├── dw_system │ │ ├── AgentUserStatusCodes.md │ │ ├── Cache.md │ │ ├── CacheMgr.md │ │ ├── HookMgr.md │ │ ├── InternalObject.md │ │ ├── JobProcessMonitor.md │ │ ├── Log.md │ │ ├── Logger.md │ │ ├── LogNDC.md │ │ ├── OrganizationPreferences.md │ │ ├── Pipeline.md │ │ ├── PipelineDictionary.md │ │ ├── RemoteInclude.md │ │ ├── Request.md │ │ ├── RequestHooks.md │ │ ├── Response.md │ │ ├── RESTErrorResponse.md │ │ ├── RESTResponseMgr.md │ │ ├── RESTSuccessResponse.md │ │ ├── SearchStatus.md │ │ ├── Session.md │ │ ├── Site.md │ │ ├── SitePreferences.md │ │ ├── Status.md │ │ ├── StatusItem.md │ │ ├── System.md │ │ └── Transaction.md │ ├── dw_util │ │ ├── ArrayList.md │ │ ├── Assert.md │ │ ├── BigInteger.md │ │ ├── Bytes.md │ │ ├── Calendar.md │ │ ├── Collection.md │ │ ├── Currency.md │ │ ├── DateUtils.md │ │ ├── Decimal.md │ │ ├── FilteringCollection.md │ │ ├── Geolocation.md │ │ ├── HashMap.md │ │ ├── HashSet.md │ │ ├── Iterator.md │ │ ├── LinkedHashMap.md │ │ ├── LinkedHashSet.md │ │ ├── List.md │ │ ├── Locale.md │ │ ├── Map.md │ │ ├── MapEntry.md │ │ ├── MappingKey.md │ │ ├── MappingMgr.md │ │ ├── PropertyComparator.md │ │ ├── SecureEncoder.md │ │ ├── SecureFilter.md │ │ ├── SeekableIterator.md │ │ ├── Set.md │ │ ├── SortedMap.md │ │ ├── SortedSet.md │ │ ├── StringUtils.md │ │ ├── Template.md │ │ └── UUIDUtils.md │ ├── dw_value │ │ ├── EnumValue.md │ │ ├── MimeEncodedText.md │ │ ├── Money.md │ │ └── Quantity.md │ ├── dw_web │ │ ├── ClickStream.md │ │ ├── ClickStreamEntry.md │ │ ├── Cookie.md │ │ ├── Cookies.md │ │ ├── CSRFProtection.md │ │ ├── Form.md │ │ ├── FormAction.md │ │ ├── FormElement.md │ │ ├── FormElementValidationResult.md │ │ ├── FormField.md │ │ ├── FormFieldOption.md │ │ ├── FormFieldOptions.md │ │ ├── FormGroup.md │ │ ├── FormList.md │ │ ├── FormListItem.md │ │ ├── Forms.md │ │ ├── HttpParameter.md │ │ ├── HttpParameterMap.md │ │ ├── LoopIterator.md │ │ ├── PageMetaData.md │ │ ├── PageMetaTag.md │ │ ├── PagingModel.md │ │ ├── Resource.md │ │ ├── URL.md │ │ ├── URLAction.md │ │ ├── URLParameter.md │ │ ├── URLRedirect.md │ │ ├── URLRedirectMgr.md │ │ └── URLUtils.md │ ├── sfra │ │ ├── account.md │ │ ├── address.md │ │ ├── billing.md │ │ ├── cart.md │ │ ├── categories.md │ │ ├── content.md │ │ ├── locale.md │ │ ├── order.md │ │ ├── payment.md │ │ ├── price-default.md │ │ ├── price-range.md │ │ ├── price-tiered.md │ │ ├── product-bundle.md │ │ ├── product-full.md │ │ ├── product-line-items.md │ │ ├── product-search.md │ │ ├── product-tile.md │ │ ├── querystring.md │ │ ├── render.md │ │ ├── request.md │ │ ├── response.md │ │ ├── server.md │ │ ├── shipping.md │ │ ├── store.md │ │ ├── stores.md │ │ └── totals.md │ └── TopLevel │ ├── APIException.md │ ├── arguments.md │ ├── Array.md │ ├── ArrayBuffer.md │ ├── BigInt.md │ ├── Boolean.md │ ├── ConversionError.md │ ├── DataView.md │ ├── Date.md │ ├── Error.md │ ├── ES6Iterator.md │ ├── EvalError.md │ ├── Fault.md │ ├── Float32Array.md │ ├── Float64Array.md │ ├── Function.md │ ├── Generator.md │ ├── global.md │ ├── Int16Array.md │ ├── Int32Array.md │ ├── Int8Array.md │ ├── InternalError.md │ ├── IOError.md │ ├── Iterable.md │ ├── Iterator.md │ ├── JSON.md │ ├── Map.md │ ├── Math.md │ ├── Module.md │ ├── Namespace.md │ ├── Number.md │ ├── Object.md │ ├── QName.md │ ├── RangeError.md │ ├── ReferenceError.md │ ├── RegExp.md │ ├── Set.md │ ├── StopIteration.md │ ├── String.md │ ├── Symbol.md │ ├── SyntaxError.md │ ├── SystemError.md │ ├── TypeError.md │ ├── Uint16Array.md │ ├── Uint32Array.md │ ├── Uint8Array.md │ ├── Uint8ClampedArray.md │ ├── URIError.md │ ├── WeakMap.md │ ├── WeakSet.md │ ├── XML.md │ ├── XMLList.md │ └── XMLStreamError.md ├── docs-site │ ├── .gitignore │ ├── App.tsx │ ├── components │ │ ├── Badge.tsx │ │ ├── BreadcrumbSchema.tsx │ │ ├── CodeBlock.tsx │ │ ├── Collapsible.tsx │ │ ├── ConfigBuilder.tsx │ │ ├── ConfigHero.tsx │ │ ├── ConfigModeTabs.tsx │ │ ├── icons.tsx │ │ ├── Layout.tsx │ │ ├── LightCodeContainer.tsx │ │ ├── NewcomerCTA.tsx │ │ ├── NextStepsStrip.tsx │ │ ├── OnThisPage.tsx │ │ ├── Search.tsx │ │ ├── SEO.tsx │ │ ├── Sidebar.tsx │ │ ├── StructuredData.tsx │ │ ├── ToolCard.tsx │ │ ├── ToolFilters.tsx │ │ ├── Typography.tsx │ │ └── VersionBadge.tsx │ ├── constants.tsx │ ├── index.html │ ├── main.tsx │ ├── metadata.json │ ├── package-lock.json │ ├── package.json │ ├── pages │ │ ├── AIInterfacesPage.tsx │ │ ├── ConfigurationPage.tsx │ │ ├── DevelopmentPage.tsx │ │ ├── ExamplesPage.tsx │ │ ├── FeaturesPage.tsx │ │ ├── HomePage.tsx │ │ ├── SecurityPage.tsx │ │ ├── ToolsPage.tsx │ │ └── TroubleshootingPage.tsx │ ├── postcss.config.js │ ├── public │ │ ├── .well-known │ │ │ └── security.txt │ │ ├── 404.html │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── explain-product-pricing-methods-no-mcp.png │ │ ├── explain-product-pricing-methods.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── llms.txt │ │ ├── robots.txt │ │ ├── site.webmanifest │ │ └── sitemap.xml │ ├── README.md │ ├── scripts │ │ ├── generate-search-index.js │ │ ├── generate-sitemap.js │ │ └── search-dev.js │ ├── src │ │ └── styles │ │ ├── input.css │ │ └── prism-theme.css │ ├── tailwind.config.js │ ├── tsconfig.json │ ├── types.ts │ ├── utils │ │ ├── search.ts │ │ └── toolsData.ts │ └── vite.config.ts ├── eslint.config.js ├── jest.config.js ├── LICENSE ├── package-lock.json ├── package.json ├── README.md ├── scripts │ └── convert-docs.js ├── SECURITY.md ├── server.json ├── src │ ├── clients │ │ ├── base │ │ │ ├── http-client.ts │ │ │ ├── oauth-token.ts │ │ │ └── ocapi-auth-client.ts │ │ ├── best-practices-client.ts │ │ ├── cartridge-generation-client.ts │ │ ├── docs │ │ │ ├── class-content-parser.ts │ │ │ ├── class-name-resolver.ts │ │ │ ├── documentation-scanner.ts │ │ │ ├── index.ts │ │ │ └── referenced-types-extractor.ts │ │ ├── docs-client.ts │ │ ├── log-client.ts │ │ ├── logs │ │ │ ├── index.ts │ │ │ ├── log-analyzer.ts │ │ │ ├── log-client.ts │ │ │ ├── log-constants.ts │ │ │ ├── log-file-discovery.ts │ │ │ ├── log-file-reader.ts │ │ │ ├── log-formatter.ts │ │ │ ├── log-processor.ts │ │ │ ├── log-types.ts │ │ │ └── webdav-client-manager.ts │ │ ├── ocapi │ │ │ ├── code-versions-client.ts │ │ │ ├── site-preferences-client.ts │ │ │ └── system-objects-client.ts │ │ ├── ocapi-client.ts │ │ └── sfra-client.ts │ ├── config │ │ ├── configuration-factory.ts │ │ └── dw-json-loader.ts │ ├── core │ │ ├── handlers │ │ │ ├── abstract-log-tool-handler.ts │ │ │ ├── base-handler.ts │ │ │ ├── best-practices-handler.ts │ │ │ ├── cartridge-handler.ts │ │ │ ├── client-factory.ts │ │ │ ├── code-version-handler.ts │ │ │ ├── docs-handler.ts │ │ │ ├── job-log-handler.ts │ │ │ ├── job-log-tool-config.ts │ │ │ ├── log-handler.ts │ │ │ ├── log-tool-config.ts │ │ │ ├── sfra-handler.ts │ │ │ ├── system-object-handler.ts │ │ │ └── validation-helpers.ts │ │ ├── server.ts │ │ └── tool-definitions.ts │ ├── index.ts │ ├── main.ts │ ├── services │ │ ├── file-system-service.ts │ │ ├── index.ts │ │ └── path-service.ts │ ├── tool-configs │ │ ├── best-practices-tool-config.ts │ │ ├── cartridge-tool-config.ts │ │ ├── code-version-tool-config.ts │ │ ├── docs-tool-config.ts │ │ ├── job-log-tool-config.ts │ │ ├── log-tool-config.ts │ │ ├── sfra-tool-config.ts │ │ └── system-object-tool-config.ts │ ├── types │ │ └── types.ts │ └── utils │ ├── cache.ts │ ├── job-log-tool-config.ts │ ├── job-log-utils.ts │ ├── log-cache.ts │ ├── log-tool-config.ts │ ├── log-tool-constants.ts │ ├── log-tool-utils.ts │ ├── logger.ts │ ├── ocapi-url-builder.ts │ ├── path-resolver.ts │ ├── query-builder.ts │ ├── utils.ts │ └── validator.ts ├── tests │ ├── __mocks__ │ │ ├── docs-client.ts │ │ ├── src │ │ │ └── clients │ │ │ └── base │ │ │ └── http-client.js │ │ └── webdav.js │ ├── base-handler.test.ts │ ├── base-http-client.test.ts │ ├── best-practices-handler.test.ts │ ├── cache.test.ts │ ├── cartridge-handler.test.ts │ ├── class-content-parser.test.ts │ ├── class-name-resolver.test.ts │ ├── client-factory.test.ts │ ├── code-version-handler.test.ts │ ├── code-versions-client.test.ts │ ├── config.test.ts │ ├── configuration-factory.test.ts │ ├── docs-handler.test.ts │ ├── documentation-scanner.test.ts │ ├── file-system-service.test.ts │ ├── job-log-handler.test.ts │ ├── job-log-utils.test.ts │ ├── log-client.test.ts │ ├── log-handler.test.ts │ ├── log-processor.test.ts │ ├── logger.test.ts │ ├── mcp │ │ ├── AGENTS.md │ │ ├── node │ │ │ ├── activate-code-version-advanced.full-mode.programmatic.test.js │ │ │ ├── code-versions.full-mode.programmatic.test.js │ │ │ ├── generate-cartridge-structure.docs-only.programmatic.test.js │ │ │ ├── get-available-best-practice-guides.docs-only.programmatic.test.js │ │ │ ├── get-available-sfra-documents.programmatic.test.js │ │ │ ├── get-best-practice-guide.docs-only.programmatic.test.js │ │ │ ├── get-hook-reference.docs-only.programmatic.test.js │ │ │ ├── get-job-execution-summary.full-mode.programmatic.test.js │ │ │ ├── get-job-log-entries.full-mode.programmatic.test.js │ │ │ ├── get-latest-debug.full-mode.programmatic.test.js │ │ │ ├── get-latest-error.full-mode.programmatic.test.js │ │ │ ├── get-latest-info.full-mode.programmatic.test.js │ │ │ ├── get-latest-job-log-files.full-mode.programmatic.test.js │ │ │ ├── get-latest-warn.full-mode.programmatic.test.js │ │ │ ├── get-log-file-contents.full-mode.programmatic.test.js │ │ │ ├── get-sfcc-class-documentation.docs-only.programmatic.test.js │ │ │ ├── get-sfcc-class-info.docs-only.programmatic.test.js │ │ │ ├── get-sfra-categories.docs-only.programmatic.test.js │ │ │ ├── get-sfra-document.programmatic.test.js │ │ │ ├── get-sfra-documents-by-category.docs-only.programmatic.test.js │ │ │ ├── get-system-object-definition.full-mode.programmatic.test.js │ │ │ ├── get-system-object-definitions.docs-only.programmatic.test.js │ │ │ ├── get-system-object-definitions.full-mode.programmatic.test.js │ │ │ ├── list-log-files.full-mode.programmatic.test.js │ │ │ ├── list-sfcc-classes.docs-only.programmatic.test.js │ │ │ ├── search-best-practices.docs-only.programmatic.test.js │ │ │ ├── search-custom-object-attribute-definitions.full-mode.programmatic.test.js │ │ │ ├── search-job-logs-by-name.full-mode.programmatic.test.js │ │ │ ├── search-job-logs.full-mode.programmatic.test.js │ │ │ ├── search-logs.full-mode.programmatic.test.js │ │ │ ├── search-sfcc-classes.docs-only.programmatic.test.js │ │ │ ├── search-sfcc-methods.docs-only.programmatic.test.js │ │ │ ├── search-sfra-documentation.docs-only.programmatic.test.js │ │ │ ├── search-site-preferences.full-mode.programmatic.test.js │ │ │ ├── search-system-object-attribute-definitions.full-mode.programmatic.test.js │ │ │ ├── search-system-object-attribute-groups.full-mode.programmatic.test.js │ │ │ ├── summarize-logs.full-mode.programmatic.test.js │ │ │ ├── tools.docs-only.programmatic.test.js │ │ │ └── tools.full-mode.programmatic.test.js │ │ ├── README.md │ │ ├── test-fixtures │ │ │ └── dw.json │ │ └── yaml │ │ ├── activate-code-version.docs-only.test.mcp.yml │ │ ├── activate-code-version.full-mode.test.mcp.yml │ │ ├── get_latest_error.test.mcp.yml │ │ ├── get-available-best-practice-guides.docs-only.test.mcp.yml │ │ ├── get-available-best-practice-guides.full-mode.test.mcp.yml │ │ ├── get-available-sfra-documents.docs-only.test.mcp.yml │ │ ├── get-available-sfra-documents.full-mode.test.mcp.yml │ │ ├── get-best-practice-guide.docs-only.test.mcp.yml │ │ ├── get-best-practice-guide.full-mode.test.mcp.yml │ │ ├── get-code-versions.docs-only.test.mcp.yml │ │ ├── get-code-versions.full-mode.test.mcp.yml │ │ ├── get-hook-reference.docs-only.test.mcp.yml │ │ ├── get-hook-reference.full-mode.test.mcp.yml │ │ ├── get-job-execution-summary.full-mode.test.mcp.yml │ │ ├── get-job-log-entries.full-mode.test.mcp.yml │ │ ├── get-latest-debug.full-mode.test.mcp.yml │ │ ├── get-latest-error.full-mode.test.mcp.yml │ │ ├── get-latest-info.full-mode.test.mcp.yml │ │ ├── get-latest-job-log-files.full-mode.test.mcp.yml │ │ ├── get-latest-warn.full-mode.test.mcp.yml │ │ ├── get-log-file-contents.full-mode.test.mcp.yml │ │ ├── get-sfcc-class-documentation.docs-only.test.mcp.yml │ │ ├── get-sfcc-class-documentation.full-mode.test.mcp.yml │ │ ├── get-sfcc-class-info.docs-only.test.mcp.yml │ │ ├── get-sfcc-class-info.full-mode.test.mcp.yml │ │ ├── get-sfra-categories.docs-only.test.mcp.yml │ │ ├── get-sfra-categories.full-mode.test.mcp.yml │ │ ├── get-sfra-document.docs-only.test.mcp.yml │ │ ├── get-sfra-document.full-mode.test.mcp.yml │ │ ├── get-sfra-documents-by-category.docs-only.test.mcp.yml │ │ ├── get-sfra-documents-by-category.full-mode.test.mcp.yml │ │ ├── get-system-object-definition.docs-only.test.mcp.yml │ │ ├── get-system-object-definition.full-mode.test.mcp.yml │ │ ├── get-system-object-definitions.docs-only.test.mcp.yml │ │ ├── get-system-object-definitions.full-mode.test.mcp.yml │ │ ├── list-log-files.full-mode.test.mcp.yml │ │ ├── list-sfcc-classes.docs-only.test.mcp.yml │ │ ├── list-sfcc-classes.full-mode.test.mcp.yml │ │ ├── search-best-practices.docs-only.test.mcp.yml │ │ ├── search-best-practices.full-mode.test.mcp.yml │ │ ├── search-custom-object-attribute-definitions.docs-only.test.mcp.yml │ │ ├── search-custom-object-attribute-definitions.test.mcp.yml │ │ ├── search-job-logs-by-name.full-mode.test.mcp.yml │ │ ├── search-job-logs.full-mode.test.mcp.yml │ │ ├── search-logs.full-mode.test.mcp.yml │ │ ├── search-sfcc-classes.docs-only.test.mcp.yml │ │ ├── search-sfcc-classes.full-mode.test.mcp.yml │ │ ├── search-sfcc-methods.docs-only.test.mcp.yml │ │ ├── search-sfcc-methods.full-mode.test.mcp.yml │ │ ├── search-sfra-documentation.docs-only.test.mcp.yml │ │ ├── search-sfra-documentation.full-mode.test.mcp.yml │ │ ├── search-site-preferences.docs-only.test.mcp.yml │ │ ├── search-site-preferences.full-mode.test.mcp.yml │ │ ├── search-system-object-attribute-definitions.docs-only.test.mcp.yml │ │ ├── search-system-object-attribute-definitions.full-mode.test.mcp.yml │ │ ├── search-system-object-attribute-groups.docs-only.test.mcp.yml │ │ ├── search-system-object-attribute-groups.full-mode.test.mcp.yml │ │ ├── summarize-logs.full-mode.test.mcp.yml │ │ ├── tools.docs-only.test.mcp.yml │ │ └── tools.full-mode.test.mcp.yml │ ├── oauth-token.test.ts │ ├── ocapi-auth-client.test.ts │ ├── ocapi-client.test.ts │ ├── path-service.test.ts │ ├── query-builder.test.ts │ ├── referenced-types-extractor.test.ts │ ├── servers │ │ ├── sfcc-mock-server │ │ │ ├── mock-data │ │ │ │ └── ocapi │ │ │ │ ├── code-versions.json │ │ │ │ ├── custom-object-attributes-customapi.json │ │ │ │ ├── custom-object-attributes-globalsettings.json │ │ │ │ ├── custom-object-attributes-versionhistory.json │ │ │ │ ├── site-preferences-ccv.json │ │ │ │ ├── site-preferences-fastforward.json │ │ │ │ ├── site-preferences-sfra.json │ │ │ │ ├── site-preferences-storefront.json │ │ │ │ ├── site-preferences-system.json │ │ │ │ ├── system-object-attribute-groups-campaign.json │ │ │ │ ├── system-object-attribute-groups-category.json │ │ │ │ ├── system-object-attribute-groups-order.json │ │ │ │ ├── system-object-attribute-groups-product.json │ │ │ │ ├── system-object-attribute-groups-sitepreferences.json │ │ │ │ ├── system-object-attributes-customeraddress.json │ │ │ │ ├── system-object-attributes-product-expanded.json │ │ │ │ ├── system-object-attributes-product.json │ │ │ │ ├── system-object-definition-category.json │ │ │ │ ├── system-object-definition-customer.json │ │ │ │ ├── system-object-definition-customeraddress.json │ │ │ │ ├── system-object-definition-order.json │ │ │ │ ├── system-object-definition-product.json │ │ │ │ ├── system-object-definitions-old.json │ │ │ │ └── system-object-definitions.json │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── README.md │ │ │ ├── scripts │ │ │ │ └── setup-logs.js │ │ │ ├── server.js │ │ │ └── src │ │ │ ├── app.js │ │ │ ├── config │ │ │ │ └── server-config.js │ │ │ ├── middleware │ │ │ │ ├── auth.js │ │ │ │ ├── cors.js │ │ │ │ └── logging.js │ │ │ ├── routes │ │ │ │ ├── ocapi │ │ │ │ │ ├── code-versions-handler.js │ │ │ │ │ ├── oauth-handler.js │ │ │ │ │ ├── ocapi-error-utils.js │ │ │ │ │ ├── ocapi-utils.js │ │ │ │ │ ├── site-preferences-handler.js │ │ │ │ │ └── system-objects-handler.js │ │ │ │ ├── ocapi.js │ │ │ │ └── webdav.js │ │ │ └── utils │ │ │ ├── mock-data-loader.js │ │ │ └── webdav-xml.js │ │ └── sfcc-mock-server-manager.ts │ ├── sfcc-mock-server.test.ts │ ├── site-preferences-client.test.ts │ ├── system-objects-client.test.ts │ ├── utils.test.ts │ ├── validation-helpers.test.ts │ └── validator.test.ts ├── tsconfig.json └── tsconfig.test.json ``` # Files -------------------------------------------------------------------------------- /tests/docs-handler.test.ts: -------------------------------------------------------------------------------- ```typescript import { DocsToolHandler } from '../src/core/handlers/docs-handler.js'; import { HandlerContext } from '../src/core/handlers/base-handler.js'; import { Logger } from '../src/utils/logger.js'; // Mock the SFCCDocumentationClient const mockSFCCDocumentationClient = { getClassDetailsExpanded: jest.fn(), getAvailableClasses: jest.fn(), searchClasses: jest.fn(), searchMethods: jest.fn(), getClassDocumentation: jest.fn(), }; jest.mock('../src/clients/docs-client.js', () => ({ SFCCDocumentationClient: jest.fn(() => mockSFCCDocumentationClient), })); describe('DocsToolHandler', () => { let mockLogger: jest.Mocked<Logger>; let mockDocsClient: typeof mockSFCCDocumentationClient; let context: HandlerContext; let handler: DocsToolHandler; beforeEach(() => { mockLogger = { debug: jest.fn(), log: jest.fn(), error: jest.fn(), timing: jest.fn(), methodEntry: jest.fn(), methodExit: jest.fn(), } as any; // Reset mocks jest.clearAllMocks(); // Use the mock client directly mockDocsClient = mockSFCCDocumentationClient; jest.spyOn(Logger, 'getChildLogger').mockReturnValue(mockLogger); context = { logger: mockLogger, config: null as any, capabilities: { canAccessLogs: false, canAccessOCAPI: false }, }; handler = new DocsToolHandler(context, 'Docs'); }); afterEach(() => { jest.restoreAllMocks(); }); // Helper function to initialize handler for tests that need it const initializeHandler = async () => { await (handler as any).initialize(); }; describe('canHandle', () => { it('should handle docs-related tools', () => { expect(handler.canHandle('get_sfcc_class_info')).toBe(true); expect(handler.canHandle('list_sfcc_classes')).toBe(true); expect(handler.canHandle('search_sfcc_classes')).toBe(true); expect(handler.canHandle('search_sfcc_methods')).toBe(true); expect(handler.canHandle('get_sfcc_class_documentation')).toBe(true); }); it('should not handle non-docs tools', () => { expect(handler.canHandle('get_latest_error')).toBe(false); expect(handler.canHandle('unknown_tool')).toBe(false); }); }); describe('initialization', () => { it('should initialize docs client', async () => { await initializeHandler(); const MockedConstructor = jest.requireMock('../src/clients/docs-client.js').SFCCDocumentationClient; expect(MockedConstructor).toHaveBeenCalled(); expect(mockLogger.debug).toHaveBeenCalledWith('Documentation client initialized'); }); }); describe('disposal', () => { it('should dispose docs client properly', async () => { await initializeHandler(); await (handler as any).dispose(); expect(mockLogger.debug).toHaveBeenCalledWith('Documentation client disposed'); }); }); describe('get_sfcc_class_info tool', () => { beforeEach(async () => { await initializeHandler(); mockDocsClient.getClassDetailsExpanded.mockResolvedValue({ className: 'Product', packageName: 'dw.catalog', description: 'Product class description', constants: [], properties: [ { name: 'ID', type: 'String', description: 'Product ID' }, { name: 'name', type: 'String', description: 'Product name' }, ], methods: [ { name: 'getID', signature: 'getID() : String', description: 'Get product ID' }, { name: 'getName', signature: 'getName() : String', description: 'Get product name' }, ], }); }); it('should handle get_sfcc_class_info with className', async () => { const args = { className: 'Product', expand: true }; const result = await handler.handle('get_sfcc_class_info', args, Date.now()); expect(mockDocsClient.getClassDetailsExpanded).toHaveBeenCalledWith('Product', true, { includeDescription: true, includeConstants: true, includeProperties: true, includeMethods: true, includeInheritance: true, search: undefined, }); expect(result.content[0].text).toContain('Product'); expect(result.content[0].text).toContain('Product class description'); }); it('should handle get_sfcc_class_info with default expand', async () => { const args = { className: 'Customer' }; await handler.handle('get_sfcc_class_info', args, Date.now()); expect(mockDocsClient.getClassDetailsExpanded).toHaveBeenCalledWith('Customer', false, { includeDescription: true, includeConstants: true, includeProperties: true, includeMethods: true, includeInheritance: true, search: undefined, }); }); it('should throw error when className is missing', async () => { const result = await handler.handle('get_sfcc_class_info', {}, Date.now()); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('className must be a non-empty string'); }); it('should handle get_sfcc_class_info with filtering options', async () => { const args = { className: 'Product', includeDescription: false, includeConstants: false, includeProperties: true, includeMethods: false, includeInheritance: false, }; const result = await handler.handle('get_sfcc_class_info', args, Date.now()); expect(mockDocsClient.getClassDetailsExpanded).toHaveBeenCalledWith('Product', false, { includeDescription: false, includeConstants: false, includeProperties: true, includeMethods: false, includeInheritance: false, search: undefined, }); expect(result.content[0].text).toContain('Product'); }); it('should handle get_sfcc_class_info with search parameter', async () => { const args = { className: 'Product', search: 'image' }; const result = await handler.handle('get_sfcc_class_info', args, Date.now()); expect(mockDocsClient.getClassDetailsExpanded).toHaveBeenCalledWith('Product', false, { includeDescription: true, includeConstants: true, includeProperties: true, includeMethods: true, includeInheritance: true, search: 'image', }); expect(result.content[0].text).toContain('Product'); }); it('should handle get_sfcc_class_info with combined filtering and search', async () => { const args = { className: 'Product', expand: true, includeDescription: false, includeMethods: true, includeProperties: false, search: 'price', }; const result = await handler.handle('get_sfcc_class_info', args, Date.now()); expect(mockDocsClient.getClassDetailsExpanded).toHaveBeenCalledWith('Product', true, { includeDescription: false, includeConstants: true, includeProperties: false, includeMethods: true, includeInheritance: true, search: 'price', }); expect(result.content[0].text).toContain('Product'); }); }); describe('list_sfcc_classes tool', () => { beforeEach(async () => { await initializeHandler(); mockDocsClient.getAvailableClasses.mockResolvedValue([ 'Product', 'Customer', 'Order', 'Catalog', ]); }); it('should handle list_sfcc_classes', async () => { const result = await handler.handle('list_sfcc_classes', {}, Date.now()); expect(mockDocsClient.getAvailableClasses).toHaveBeenCalled(); expect(result.content[0].text).toContain('Product'); expect(result.content[0].text).toContain('Customer'); }); }); describe('search_sfcc_classes tool', () => { beforeEach(async () => { await initializeHandler(); mockDocsClient.searchClasses.mockResolvedValue([ 'Product', 'ProductSearchModel', ]); }); it('should handle search_sfcc_classes with query', async () => { const args = { query: 'product' }; const result = await handler.handle('search_sfcc_classes', args, Date.now()); expect(mockDocsClient.searchClasses).toHaveBeenCalledWith('product'); expect(result.content[0].text).toContain('Product'); expect(result.content[0].text).toContain('ProductSearchModel'); }); it('should throw error when query is missing', async () => { const result = await handler.handle('search_sfcc_classes', {}, Date.now()); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('query must be a non-empty string'); }); it('should throw error when query is empty', async () => { const result = await handler.handle('search_sfcc_classes', { query: '' }, Date.now()); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('query must be a non-empty string'); }); }); describe('search_sfcc_methods tool', () => { beforeEach(async () => { await initializeHandler(); mockDocsClient.searchMethods.mockResolvedValue([ { className: 'Product', method: { name: 'getID', signature: 'getID() : String', description: 'Get product ID', }, }, { className: 'Customer', method: { name: 'getID', signature: 'getID() : String', description: 'Get customer ID', }, }, ]); }); it('should handle search_sfcc_methods with methodName', async () => { const args = { methodName: 'getID' }; const result = await handler.handle('search_sfcc_methods', args, Date.now()); expect(mockDocsClient.searchMethods).toHaveBeenCalledWith('getID'); expect(result.content[0].text).toContain('getID'); expect(result.content[0].text).toContain('Product'); }); it('should throw error when methodName is missing', async () => { const result = await handler.handle('search_sfcc_methods', {}, Date.now()); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('methodName must be a non-empty string'); }); }); describe('get_sfcc_class_documentation tool', () => { beforeEach(async () => { await initializeHandler(); mockDocsClient.getClassDocumentation.mockResolvedValue( 'Detailed documentation for Product class with examples and usage patterns.', ); }); it('should handle get_sfcc_class_documentation with className', async () => { const args = { className: 'Product' }; const result = await handler.handle('get_sfcc_class_documentation', args, Date.now()); expect(mockDocsClient.getClassDocumentation).toHaveBeenCalledWith('Product'); expect(result.content[0].text).toContain('Detailed documentation'); }); it('should throw error when className is missing', async () => { const result = await handler.handle('get_sfcc_class_documentation', {}, Date.now()); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('className must be a non-empty string'); }); }); describe('error handling', () => { beforeEach(async () => { await initializeHandler(); }); it('should handle client errors gracefully', async () => { mockDocsClient.getClassDetailsExpanded.mockRejectedValue(new Error('Documentation not found')); const result = await handler.handle('get_sfcc_class_info', { className: 'UnknownClass' }, Date.now()); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Documentation not found'); }); it('should throw error for unsupported tools', async () => { await expect(handler.handle('unsupported_tool', {}, Date.now())) .rejects.toThrow('Unsupported tool'); }); }); describe('timing and logging', () => { beforeEach(async () => { await initializeHandler(); mockDocsClient.getAvailableClasses.mockResolvedValue(['Product', 'Customer']); }); it('should log timing information', async () => { const startTime = Date.now(); await handler.handle('list_sfcc_classes', {}, startTime); expect(mockLogger.timing).toHaveBeenCalledWith('list_sfcc_classes', startTime); }); it('should log execution details', async () => { await handler.handle('list_sfcc_classes', {}, Date.now()); expect(mockLogger.debug).toHaveBeenCalledWith( 'list_sfcc_classes completed successfully', expect.any(Object), ); }); }); }); ``` -------------------------------------------------------------------------------- /docs/TopLevel/XMLList.md: -------------------------------------------------------------------------------- ```markdown ## Package: TopLevel # Class XMLList ## Inheritance Hierarchy - Object - XMLList ## Description An XMLList object is an ordered collection of properties. A XMLList object represents a XML document, an XML fragment, or an arbitrary collection of XML objects. An individual XML object is the same thing as an XMLList containing only that XML object. All operations available for the XML object are also available for an XMLList object that contains exactly one XML object. ## Constructor Summary XMLList(value : Object) Creates a new XMLList object using the specified value. ## Method Summary ### attribute **Signature:** `attribute(attributeName : String) : XMLList` Returns the attribute associated with this XMLList object that is identified by the specified name. ### attributes **Signature:** `attributes() : XMLList` Returns an XMList of the attributes in this XMLList Object. ### child **Signature:** `child(propertyName : Object) : XMLList` Returns the children of the XMLList object based on the specified property name. ### children **Signature:** `children() : XMLList` Returns an XMLList containing the children of this XMLList object, maintaing the sequence in which they appear. ### comments **Signature:** `comments() : XMLList` Returns the properties of the XMLList object that contain comments. ### contains **Signature:** `contains(value : XML) : boolean` Returns true if this XMLList object contains the specified XML object, false otherwise. ### copy **Signature:** `copy() : XMLList` Returns a deep copy of the this XMLList object. ### descendants **Signature:** `descendants() : XMLList` Calls the descendants() method of each XML object in this XMLList object and returns an XMLList containing the results concatenated in order. ### descendants **Signature:** `descendants(name : String) : XMLList` Calls the descendants(name) method of each XML object in this XMLList object and returns an XMLList containing the results concatenated in order. ### elements **Signature:** `elements() : XMLList` Calls the elements() method in each XML object in this XMLList object and returns an XMLList containing the results concatenated in order. ### elements **Signature:** `elements(name : Object) : XMLList` Calls the elements(name) method in each of the XML objects in this XMLList object and returns an XMLList containing the results concatenated in order. ### hasComplexContent **Signature:** `hasComplexContent() : boolean` Returns a Boolean value indicating whether this XMLList object contains complex content. ### hasOwnProperty **Signature:** `hasOwnProperty(prop : String) : boolean` Returns a Boolean value indicating whether this object has the property specified by prop. ### hasSimpleContent **Signature:** `hasSimpleContent() : boolean` Returns a Boolean value indicating whether this XML object contains simple content. ### length **Signature:** `length() : Number` Returns the number of children in this XMLList object. ### normalize **Signature:** `normalize() : XMLList` Puts all text nodes in this XMLList, all the XML objects it contains and the descendents of all the XML objects it contains into a normal form by merging adjacent text nodes and eliminating empty text nodes. ### parent **Signature:** `parent() : Object` Returns the parent of the XMLList object or null if the XMLList object does not have a parent. ### processingInstructions **Signature:** `processingInstructions() : XMLList` Calls the processingInstructions() method of each XML object in this XMLList object and returns an XMList containing the results in order. ### processingInstructions **Signature:** `processingInstructions(name : String) : XMLList` Calls the processingInstructions(name) method of each XML object in this XMLList object and returns an XMList containing the results in order. ### propertyIsEnumerable **Signature:** `propertyIsEnumerable(property : String) : boolean` Returns a Boolean indicating whether the specified property will be included in the set of properties iterated over when this XML object is used in a for..in statement. ### text **Signature:** `text() : XMLList` Calls the text() method of each XML object contained in this XMLList object and returns an XMLList containing the results concatenated in order. ### toString **Signature:** `toString() : String` Returns the String representation of this XMLList object. ### toXMLString **Signature:** `toXMLString() : String` Returns an XML-encoded String representation of the XMLList object by calling the toXMLString method on each property contained within this XMLList object. ### valueOf **Signature:** `valueOf() : XMLList` Returns this XMLList object. ## Constructor Detail ## Method Detail ## Method Details ### attribute **Signature:** `attribute(attributeName : String) : XMLList` **Description:** Returns the attribute associated with this XMLList object that is identified by the specified name. **Parameters:** - `attributeName`: the name of the attribute. **Returns:** the value of the attribute as either an XMLList or an empty XMLList --- ### attributes **Signature:** `attributes() : XMLList` **Description:** Returns an XMList of the attributes in this XMLList Object. **Returns:** an XMList of the attributes in this XMLList Object. --- ### child **Signature:** `child(propertyName : Object) : XMLList` **Description:** Returns the children of the XMLList object based on the specified property name. **Parameters:** - `propertyName`: the property name representing the children of this XMLList object. **Returns:** an XMLList of children that match the property name parameter. --- ### children **Signature:** `children() : XMLList` **Description:** Returns an XMLList containing the children of this XMLList object, maintaing the sequence in which they appear. **Returns:** an XMLList containing the children of this XMLList object. --- ### comments **Signature:** `comments() : XMLList` **Description:** Returns the properties of the XMLList object that contain comments. **Returns:** properties of the XMLList object that contain comments. --- ### contains **Signature:** `contains(value : XML) : boolean` **Description:** Returns true if this XMLList object contains the specified XML object, false otherwise. **Parameters:** - `value`: the object to locate in this XMLList object. **Returns:** true if this XMLList object contains the specified XML object, false otherwise. --- ### copy **Signature:** `copy() : XMLList` **Description:** Returns a deep copy of the this XMLList object. **Returns:** the deep copy of the object. --- ### descendants **Signature:** `descendants() : XMLList` **Description:** Calls the descendants() method of each XML object in this XMLList object and returns an XMLList containing the results concatenated in order. **Returns:** a list of all descendents of the XML objects in this XMLList object. --- ### descendants **Signature:** `descendants(name : String) : XMLList` **Description:** Calls the descendants(name) method of each XML object in this XMLList object and returns an XMLList containing the results concatenated in order. **Parameters:** - `name`: the name of the element to match. To return all descendents, use * as the name parameter. **Returns:** a list of all descendents of the XML objects in this XMLList constrained by the name parameter. --- ### elements **Signature:** `elements() : XMLList` **Description:** Calls the elements() method in each XML object in this XMLList object and returns an XMLList containing the results concatenated in order. --- ### elements **Signature:** `elements(name : Object) : XMLList` **Description:** Calls the elements(name) method in each of the XML objects in this XMLList object and returns an XMLList containing the results concatenated in order. name can be a QName, String, or any other data type that will be converted to a string prior to performing the search for elements of that name. To list all objects use * for the value of name. **Parameters:** - `name`: the name of the elements to return. **Returns:** a list of all elements of the XML objects in this XMLList constrained by the name parameter. --- ### hasComplexContent **Signature:** `hasComplexContent() : boolean` **Description:** Returns a Boolean value indicating whether this XMLList object contains complex content. An XMLList object is considered to contain complex content if it is not empty, contains a single XML item with complex content or contains elements. **Returns:** a Boolean value indicating whether this XMLList object contains complex content. --- ### hasOwnProperty **Signature:** `hasOwnProperty(prop : String) : boolean` **Description:** Returns a Boolean value indicating whether this object has the property specified by prop. **Parameters:** - `prop`: the property to locate. **Returns:** true if the property exists, false otherwise. --- ### hasSimpleContent **Signature:** `hasSimpleContent() : boolean` **Description:** Returns a Boolean value indicating whether this XML object contains simple content. An XMLList object is considered to contain simple content if it is empty, contains a single XML item with simple content or contains no elements. **Returns:** a Boolean value indicating whether this XML object contains simple content. --- ### length **Signature:** `length() : Number` **Description:** Returns the number of children in this XMLList object. **Returns:** the number of children in this XMLList object. --- ### normalize **Signature:** `normalize() : XMLList` **Description:** Puts all text nodes in this XMLList, all the XML objects it contains and the descendents of all the XML objects it contains into a normal form by merging adjacent text nodes and eliminating empty text nodes. **Returns:** the XMLList object containing normailzed objects. --- ### parent **Signature:** `parent() : Object` **Description:** Returns the parent of the XMLList object or null if the XMLList object does not have a parent. **Returns:** the parent of the XMLList object or null if the XMLList object does not have a parent. --- ### processingInstructions **Signature:** `processingInstructions() : XMLList` **Description:** Calls the processingInstructions() method of each XML object in this XMLList object and returns an XMList containing the results in order. **Returns:** an XMLList contaiing the result of calling the processingInstructions() method of each XML object in this XMLList object. --- ### processingInstructions **Signature:** `processingInstructions(name : String) : XMLList` **Description:** Calls the processingInstructions(name) method of each XML object in this XMLList object and returns an XMList containing the results in order. **Parameters:** - `name`: the name representing the processing-instructions you want to retreive. **Returns:** an XMLList containing the result of calling the processingInstructions(name) method of each XML object in this XMLList object. --- ### propertyIsEnumerable **Signature:** `propertyIsEnumerable(property : String) : boolean` **Description:** Returns a Boolean indicating whether the specified property will be included in the set of properties iterated over when this XML object is used in a for..in statement. **Parameters:** - `property`: the property to test. **Returns:** true when the property can be iterated in a for..in statement, false otherwise. --- ### text **Signature:** `text() : XMLList` **Description:** Calls the text() method of each XML object contained in this XMLList object and returns an XMLList containing the results concatenated in order. **Returns:** the concatenated results of calling the text() method of every XML object contained in this XMLList. --- ### toString **Signature:** `toString() : String` **Description:** Returns the String representation of this XMLList object. **Returns:** the String representation of this XMLList object. --- ### toXMLString **Signature:** `toXMLString() : String` **Description:** Returns an XML-encoded String representation of the XMLList object by calling the toXMLString method on each property contained within this XMLList object. **Returns:** an XML-encoded String representation of the XMLList object by calling the toXMLString method on each property contained within this XMLList object. --- ### valueOf **Signature:** `valueOf() : XMLList` **Description:** Returns this XMLList object. **Returns:** this XMLList object. --- ``` -------------------------------------------------------------------------------- /docs-site/utils/toolsData.ts: -------------------------------------------------------------------------------- ```typescript // Centralized metadata for MCP tools. Used by ToolsPage for dynamic rendering. // Keeps descriptive, param, and example prompt info in one place for reuse. export type ToolMode = 'docs' | 'full' | 'both'; export interface ToolParam { name: string; required?: boolean; description: string; } export interface ToolMeta { id: string; // unique id also used as anchor name: string; // tool name as exposed to MCP category: string; mode: ToolMode; // availability description: string; params?: ToolParam[]; examples?: string[]; // example AI prompts or usage tags?: string[]; popular?: boolean; // mark for quick actions } // Helper for brevity const p = (name: string, description: string, required = true): ToolParam => ({ name, description, required }); export const TOOL_CATEGORIES = [ 'Documentation', 'Best Practices', 'SFRA Docs', 'Cartridge Generation', 'Log Analysis', 'System Objects', 'Code Versions' ] as const; export const tools: ToolMeta[] = [ // Documentation (SFCC classes) { id: 'get-sfcc-class-info', name: 'get_sfcc_class_info', category: 'Documentation', mode: 'both', description: 'Detailed information about an SFCC class with filtering and search capabilities: properties, methods, descriptions.', params: [ p('className', "SFCC class (e.g. 'Catalog' or 'dw.catalog.Catalog')"), p('expand', 'Include referenced type details (boolean)', false), p('includeDescription', 'Include class description (boolean, default: true)', false), p('includeConstants', 'Include class constants (boolean, default: true)', false), p('includeProperties', 'Include class properties (boolean, default: true)', false), p('includeMethods', 'Include class methods (boolean, default: true)', false), p('includeInheritance', 'Include inheritance info (boolean, default: true)', false), p('search', 'Filter results by search term (string)', false) ], examples: [ 'Show methods and properties on dw.catalog.Product', 'Show only methods for dw.system.Status class', 'Search for "get" methods in dw.catalog.Product', 'Show dw.order.Order class without description or constants', 'Find "name" related properties and methods in dw.catalog.Product' ], tags: ['api','classes','introspection','filtering','search'], popular: true }, { id: 'search-sfcc-classes', name: 'search_sfcc_classes', category: 'Documentation', mode: 'both', description: 'Search SFCC classes by partial name (single word).', params: [p('query', 'Search term (single word)')], examples: ['Find classes related to price','Search for catalog classes'], tags: ['search'], popular: true }, { id: 'search-sfcc-methods', name: 'search_sfcc_methods', category: 'Documentation', mode: 'both', description: 'Search methods across all SFCC classes.', params: [p('methodName', 'Method name (single word)')], examples: ['Find get methods on system objects','Search for commit methods'], tags: ['methods','search'] }, { id: 'list-sfcc-classes', name: 'list_sfcc_classes', category: 'Documentation', mode: 'both', description: 'List of all available SFCC classes.', examples: ['List all available SFCC classes'] }, { id: 'get-sfcc-class-documentation', name: 'get_sfcc_class_documentation', category: 'Documentation', mode: 'both', description: 'Raw markdown documentation for an SFCC class.', params: [p('className','Exact class name')], examples: ['Get raw docs for dw.system.Logger'] }, // Best Practices { id: 'get-available-best-practice-guides', name: 'get_available_best_practice_guides', category: 'Best Practices', mode: 'both', description: 'List all best practice guides.', examples: ['List available best practice guides'] }, { id: 'get-best-practice-guide', name: 'get_best_practice_guide', category: 'Best Practices', mode: 'both', description: 'Full best practice guide content.', params: [p('guideName','Guide name (cartridge_creation, sfra_client_side_js, sfra_scss, security, performance, etc.)')], examples: ['Open the performance best practice guide'], tags: ['guides'] }, { id: 'search-best-practices', name: 'search_best_practices', category: 'Best Practices', mode: 'both', description: 'Search within all best practice guides.', params: [p('query','Search term')], examples: ['Search best practices for caching'], tags: ['search'] }, { id: 'get-hook-reference', name: 'get_hook_reference', category: 'Best Practices', mode: 'both', description: 'Hook reference tables for OCAPI or SCAPI.', params: [p('guideName','ocapi_hooks | scapi_hooks')], examples: ['List SCAPI hooks for product'] }, // SFRA Docs { id: 'get-available-sfra-documents', name: 'get_available_sfra_documents', category: 'SFRA Docs', mode: 'both', description: 'List all SFRA documents and models.', examples: ['List SFRA docs categories'] }, { id: 'get-sfra-document', name: 'get_sfra_document', category: 'SFRA Docs', mode: 'both', description: 'Full SFRA document (server, request, cart, product-full etc.).', params: [p('documentName','SFRA document name')], examples: ['Show the server module SFRA docs'] }, { id: 'search-sfra-documentation', name: 'search_sfra_documentation', category: 'SFRA Docs', mode: 'both', description: 'Search across SFRA docs.', params: [p('query','Search term')], examples: ['Search SFRA docs for middleware'], tags: ['search'] }, { id: 'get-sfra-categories', name: 'get_sfra_categories', category: 'SFRA Docs', mode: 'both', description: 'List SFRA document categories with counts.' }, { id: 'get-sfra-documents-by-category', name: 'get_sfra_documents_by_category', category: 'SFRA Docs', mode: 'both', description: 'Get SFRA documents for a category.', params: [p('category','core|product|order|customer|pricing|store|other')], examples: ['List all order category SFRA docs'] }, // Cartridge Generation { id: 'generate-cartridge-structure', name: 'generate_cartridge_structure', category: 'Cartridge Generation', mode: 'both', description: 'Generate cartridge directory structure.', params: [p('cartridgeName','Name of cartridge'), p('targetPath','Target path (optional)', false), p('fullProjectSetup','Include project scaffolding (boolean)', false)], examples: ['Generate cartridge named plugin_demo'], tags: ['scaffold'], popular: true }, // Log Analysis (Full Mode) { id: 'get-latest-error', name: 'get_latest_error', category: 'Log Analysis', mode: 'full', description: 'Fetch latest error log entries.', params: [p('date','YYYYMMDD (optional defaults today)', false), p('limit','Number of entries', false)], examples: ['Show last 5 error log entries'], tags: ['logs','errors'], popular: true }, { id: 'get-latest-warn', name: 'get_latest_warn', category: 'Log Analysis', mode: 'full', description: 'Fetch latest warn log entries.', params: [p('date','YYYYMMDD', false), p('limit','Entries', false)] }, { id: 'get-latest-info', name: 'get_latest_info', category: 'Log Analysis', mode: 'full', description: 'Fetch latest info log entries.', params: [p('date','YYYYMMDD', false), p('limit','Entries', false)] }, { id: 'get-latest-debug', name: 'get_latest_debug', category: 'Log Analysis', mode: 'full', description: 'Fetch latest debug log entries.', params: [p('date','YYYYMMDD', false), p('limit','Entries', false)] }, { id: 'search-logs', name: 'search_logs', category: 'Log Analysis', mode: 'full', description: 'Search across logs for a pattern.', params: [p('pattern','Search string'), p('date','YYYYMMDD', false), p('limit','Entries', false), p('logLevel','error|warn|info|debug', false)], examples: ['Search logs for OCAPI 500 errors'], tags: ['search'] }, { id: 'summarize-logs', name: 'summarize_logs', category: 'Log Analysis', mode: 'full', description: 'High level log activity summary.', params: [p('date','YYYYMMDD', false)], examples: ['Summarize today\'s logs'] }, { id: 'list-log-files', name: 'list_log_files', category: 'Log Analysis', mode: 'full', description: 'List available log files with metadata.', examples: ['List available log files'] }, { id: 'get-log-file-contents', name: 'get_log_file_contents', category: 'Log Analysis', mode: 'full', description: 'Fetch specific log file contents.', params: [p('filename','File name'), p('maxBytes','Max bytes', false), p('tailOnly','Tail only boolean', false)], examples: ['Show tail of error log'] }, { id: 'get-latest-job-log-files', name: 'get_latest_job_log_files', category: 'Log Analysis', mode: 'full', description: 'List latest job log files.', params: [p('limit','Number of files', false)], examples: ['List latest 3 job log files'] }, { id: 'get-job-log-entries', name: 'get_job_log_entries', category: 'Log Analysis', mode: 'full', description: 'Get job log entries filtered by level.', params: [p('jobName','Job name', false), p('level','error|warn|info|debug|all', false), p('limit','Entries', false)], examples: ['Get last 10 job log entries'] }, { id: 'search-job-logs', name: 'search_job_logs', category: 'Log Analysis', mode: 'full', description: 'Search job logs for pattern.', params: [p('pattern','Search string'), p('jobName','Job name', false), p('limit','Entries', false), p('level','error|warn|info|debug|all', false)], examples: ['Search job logs for timeout'] }, { id: 'search-job-logs-by-name', name: 'search_job_logs_by_name', category: 'Log Analysis', mode: 'full', description: 'Find job log files by job name.', params: [p('jobName','Partial job name'), p('limit','Files', false)], examples: ['Find job logs for OrderExport'] }, { id: 'get-job-execution-summary', name: 'get_job_execution_summary', category: 'Log Analysis', mode: 'full', description: 'Execution summary for specific job.', params: [p('jobName','Job name')], examples: ['Summarize last execution of DailyFeed job'] }, // System Objects { id: 'get-system-object-definitions', name: 'get_system_object_definitions', category: 'System Objects', mode: 'full', description: 'All system object definitions with pagination support.', params: [p('start','Start index', false), p('count','Max count', false), p('select','Property selector', false)], examples: ['List system object definitions', 'Get first 10 system objects', 'Get system objects starting from index 5'], tags: ['objects'], popular: true }, { id: 'get-system-object-definition', name: 'get_system_object_definition', category: 'System Objects', mode: 'full', description: 'Specific system object metadata.', params: [p('objectType','Object type e.g. Product')], examples: ['Get definition for Product object'] }, { id: 'search-system-object-attribute-definitions', name: 'search_system_object_attribute_definitions', category: 'System Objects', mode: 'full', description: 'Search attributes for a system object.', params: [p('objectType','System object type'), p('searchRequest','Search request body')], examples: ['Search Product attributes for inventory fields'] }, { id: 'search-system-object-attribute-groups', name: 'search_system_object_attribute_groups', category: 'System Objects', mode: 'full', description: 'Search attribute groups for a system object.', params: [p('objectType','System object type'), p('searchRequest','Search request body')], examples: ['List attribute groups for Product object'] }, { id: 'search-site-preferences', name: 'search_site_preferences', category: 'System Objects', mode: 'full', description: 'Search site preferences within a group.', params: [p('groupId','Preference group ID'), p('searchRequest','Search request body')], examples: ['Search site preferences in SitePreferencesMarketing group'] }, { id: 'search-custom-object-attribute-definitions', name: 'search_custom_object_attribute_definitions', category: 'System Objects', mode: 'full', description: 'Search custom object attributes.', params: [p('objectType','Custom object type'), p('searchRequest','Search request body')], examples: ['Search custom object attributes for Global_String'] }, // Code Versions { id: 'get-code-versions', name: 'get_code_versions', category: 'Code Versions', mode: 'full', description: 'List all code versions.', examples: ['List available code versions'], popular: true }, { id: 'activate-code-version', name: 'activate_code_version', category: 'Code Versions', mode: 'full', description: 'Activate a specific code version.', params: [p('codeVersionId','ID of code version')], examples: ['Activate code version int_2025_09'] } ]; export const popularTools = tools.filter(t => t.popular); export const categoriesWithCounts = TOOL_CATEGORIES.map(cat => ({ name: cat, count: tools.filter(t => t.category === cat).length })); ``` -------------------------------------------------------------------------------- /tests/servers/sfcc-mock-server/scripts/setup-logs.js: -------------------------------------------------------------------------------- ```javascript const fs = require('fs'); const path = require('path'); /** * Setup Script for Mock SFCC Log Files * * This script creates a realistic directory structure and log files * that mimic the SFCC WebDAV log system for testing purposes. */ class MockLogGenerator { constructor() { this.baseDir = path.join(__dirname, '../mock-data'); this.logsDir = path.join(this.baseDir, 'logs'); this.jobsDir = path.join(this.logsDir, 'jobs'); // Current date for log file naming this.today = new Date(); this.dateString = this.formatDate(this.today); this.timeString = this.formatTime(this.today); } formatDate(date) { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}${month}${day}`; } formatTime(date) { const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); return `${hours}${minutes}${seconds}`; } formatLogTimestamp(date) { // Format like real SFCC logs: [2025-09-14 12:00:00.000 GMT] const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); const milliseconds = String(date.getMilliseconds()).padStart(3, '0'); return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`; } ensureDirectoryExists(dirPath) { if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); console.log(`📁 Created directory: ${dirPath}`); } } generateErrorLogs() { // Create timestamps with specific ordering - oldest first for proper log file structure const baseTime = new Date(); const timestamps = [ this.formatLogTimestamp(new Date(baseTime.getTime() + 1000)), // 1 second later (oldest) this.formatLogTimestamp(new Date(baseTime.getTime() + 2000)), // 2 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 3000)), // 3 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 4000)), // 4 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 5000)) // 5 seconds later (newest) ]; const errorEntries = [ `[${timestamps[0]} GMT] ERROR PipelineCallServlet|1645761595|Sites-RefArchGlobal-Site|Cart-AddProduct|PipelineCall|nYJXtqnEfz custom [] Custom cartridge error: Unable to connect to external service`, `[${timestamps[1]} GMT] ERROR SystemJobThread|1581553813|sfcc-catalog-import|ImportCatalogStep com.demandware.beehive.core.internal.catalog.CatalogMgr Sites-Site JOB abc123def456 - Product import failed: Invalid category assignment`, `[${timestamps[2]} GMT] ERROR PipelineCallServlet|1050777654|Sites-RefArchGlobal-Site|Page-Include|PipelineCall|V5YDtxRLpL custom [] Customer profile creation failed: Email already exists`, `[${timestamps[3]} GMT] ERROR PipelineCallServlet|1912801078|Sites-RefArchGlobal-Site|Page-Include|PipelineCall|Qq38CuNXpX custom [] Payment authorization failed for order ORDER-000001234`, `[${timestamps[4]} GMT] ERROR SystemJobThread|1645761595|sfcc-download-gdpr-einstein-response-files-for-einstein|DownloadGDPRLogFiles com.demandware.component.transaction.cquotient.feed.s3.S3Store Sites-Site JOB bce341cf01 fd3d5c567c091a16392d5b865e 4815298613491841024 - CQ - AWS S3 Configuration Issue: bucketName is missing.` ]; const errorContent = errorEntries.join('\n') + '\n'; const errorFile = path.join(this.logsDir, `error-blade-${this.dateString}-${this.timeString}.log`); fs.writeFileSync(errorFile, errorContent); console.log(`📄 Created error log: ${errorFile}`); } generateWarnLogs() { // Create timestamps with specific ordering - oldest first for proper log file structure const baseTime = new Date(); const timestamps = [ this.formatLogTimestamp(new Date(baseTime.getTime() + 1000)), // 1 second later (oldest) this.formatLogTimestamp(new Date(baseTime.getTime() + 2000)), // 2 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 3000)), // 3 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 4000)), // 4 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 5000)) // 5 seconds later (newest) ]; const warnEntries = [ `[${timestamps[0]} GMT] WARN PipelineCallServlet|1645761595|Sites-RefArchGlobal-Site|Product-Show|PipelineCall|AbcDef123G custom [] Product inventory low: SKU-789-XYZ has only 2 units remaining`, `[${timestamps[1]} GMT] WARN PipelineCallServlet|1581553813|Sites-RefArchGlobal-Site|Page-Include|PipelineCall|nYJXtqnEfz custom [] Content asset with ID cookie_hint is offline`, `[${timestamps[2]} GMT] WARN PipelineCallServlet|1912801078|Sites-RefArchGlobal-Site|Page-Include|PipelineCall|290fx4tnVR custom [] Content asset with ID cookie_hint is offline`, `[${timestamps[3]} GMT] WARN PipelineCallServlet|1050777654|Sites-RefArchGlobal-Site|Page-Include|PipelineCall|V5YDtxRLpL custom [] Content asset with ID cookie_hint is offline`, `[${timestamps[4]} GMT] WARN PipelineCallServlet|1912801078|Sites-RefArchGlobal-Site|Page-Include|PipelineCall|Qq38CuNXpX custom [] Content asset with ID cookie_hint is offline` ]; const warnContent = warnEntries.join('\n') + '\n'; const warnFile = path.join(this.logsDir, `warn-blade-${this.dateString}-${this.timeString}.log`); fs.writeFileSync(warnFile, warnContent); console.log(`📄 Created warn log: ${warnFile}`); } generateInfoLogs() { // Create timestamps with specific ordering - oldest first for proper log file structure const baseTime = new Date(); const timestamps = [ this.formatLogTimestamp(new Date(baseTime.getTime() + 1000)), // 1 second later (oldest) this.formatLogTimestamp(new Date(baseTime.getTime() + 2000)), // 2 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 3000)), // 3 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 4000)), // 4 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 5000)) // 5 seconds later (newest) ]; const infoEntries = [ `[${timestamps[0]} GMT] INFO SystemJobThread|1581553813|sfcc-process-orders|ProcessOrdersStep com.demandware.beehive.core.internal.job.JobMgr Sites-Site JOB abc123def456 - Job started: ProcessOrders`, `[${timestamps[1]} GMT] INFO PipelineCallServlet|1050777654|Sites-RefArchGlobal-Site|Account-SubmitRegistration|PipelineCall|V5YDtxRLpL custom [] Customer registration completed: customer.id=123456789`, `[${timestamps[2]} GMT] INFO PipelineCallServlet|1912801078|Sites-RefArchGlobal-Site|Order-Confirm|PipelineCall|AbcDef123G custom [] Order created successfully: ORDER-000001234`, `[${timestamps[3]} GMT] INFO SystemJobThread|67038033|sfcc-export-dw-analytics-site-config|ExportDWAnalyticsSiteConfigurationStep Executing step [ExportDWAnalyticsSiteConfigurationStep][5846619] for [Organization]...`, `[${timestamps[4]} GMT] INFO SystemJobThread|67038033|sfcc-export-dw-analytics-site-config Executing job [sfcc-export-dw-analytics-site-config][2664334]...` ]; const infoContent = infoEntries.join('\n') + '\n'; const infoFile = path.join(this.logsDir, `info-blade-${this.dateString}-${this.timeString}.log`); fs.writeFileSync(infoFile, infoContent); console.log(`📄 Created info log: ${infoFile}`); } generateDebugLogs() { // Create timestamps with specific ordering - oldest first for proper log file structure const baseTime = new Date(); const timestamps = [ this.formatLogTimestamp(new Date(baseTime.getTime() + 1000)), // 1 second later (oldest) this.formatLogTimestamp(new Date(baseTime.getTime() + 2000)), // 2 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 3000)), // 3 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 4000)), // 4 seconds later this.formatLogTimestamp(new Date(baseTime.getTime() + 5000)) // 5 seconds later (newest) ]; const debugEntries = [ `[${timestamps[0]} GMT] DEBUG PipelineCallServlet|1912801078|Sites-RefArchGlobal-Site|Account-Show|PipelineCall|290fx4tnVR custom [] Customer session validated: session timeout extended`, `[${timestamps[1]} GMT] DEBUG PipelineCallServlet|1645761595|Sites-RefArchGlobal-Site|Cart-Show|PipelineCall|nYJXtqnEfz custom [] Basket calculation: 3 items, subtotal $149.99`, `[${timestamps[2]} GMT] DEBUG SystemJobThread|1581553813|sfcc-data-replication|DataReplicationStep com.demandware.beehive.core.internal.system.SystemMgr Sites-Site JOB abc123def456 - Data replication sync started`, `[${timestamps[3]} GMT] DEBUG PipelineCallServlet|1050777654|Sites-RefArchGlobal-Site|Search-Show|PipelineCall|V5YDtxRLpL custom [] Search query executed: 'laptop' returned 45 results`, `[${timestamps[4]} GMT] DEBUG PipelineCallServlet|1912801078|Sites-RefArchGlobal-Site|Product-Show|PipelineCall|AbcDef123G custom [] Product cache hit: SKU ABC-123-XYZ` ]; const debugContent = debugEntries.join('\n') + '\n'; const debugFile = path.join(this.logsDir, `debug-blade-${this.dateString}-${this.timeString}.log`); fs.writeFileSync(debugFile, debugContent); console.log(`📄 Created debug log: ${debugFile}`); } generateJobLogs() { // Create job directories and logs const jobs = [ { name: 'ProcessOrders', id: '1234567890', steps: ['ValidateOrdersStep', 'ProcessPaymentsStep', 'UpdateInventoryStep'] }, { name: 'ImportCatalog', id: '0987654321', steps: ['ValidateCatalogStep', 'ImportProductsStep', 'IndexProductsStep'] } ]; jobs.forEach(job => { const jobDir = path.join(this.jobsDir, job.name); this.ensureDirectoryExists(jobDir); const timestamp = this.formatLogTimestamp(new Date()); const jobEntries = [ `[${timestamp} GMT] INFO SystemJobThread|${job.id}|${job.name} Executing job [${job.name}][${job.id}]...` ]; // Add step entries job.steps.forEach(step => { jobEntries.push( `[${timestamp} GMT] INFO SystemJobThread|${job.id}|${job.name}|${step} Executing step [${step}] for [Organization]...`, `[${timestamp} GMT] INFO SystemJobThread|${job.id}|${job.name}|${step} Step [${step}] completed successfully` ); }); jobEntries.push(`[${timestamp} GMT] INFO SystemJobThread|${job.id}|${job.name} Execution of job finished with status [OK].`); const jobContent = jobEntries.join('\n') + '\n'; const jobFile = path.join(jobDir, `Job-${job.name}-${job.id}.log`); fs.writeFileSync(jobFile, jobContent); console.log(`📄 Created job log: ${jobFile}`); }); } run() { console.log('🚀 Starting mock log generation...'); // Ensure directories exist this.ensureDirectoryExists(this.baseDir); this.ensureDirectoryExists(this.logsDir); this.ensureDirectoryExists(this.jobsDir); // Generate all log types this.generateErrorLogs(); this.generateWarnLogs(); this.generateInfoLogs(); this.generateDebugLogs(); this.generateJobLogs(); console.log('✅ Mock log generation completed!'); console.log(`� Logs created in: ${this.logsDir}`); } } // Run the generator if called directly if (require.main === module) { const generator = new MockLogGenerator(); generator.run(); } module.exports = MockLogGenerator; ``` -------------------------------------------------------------------------------- /docs/dw_content/MediaFile.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.content # Class MediaFile ## Inheritance Hierarchy - Object - dw.content.MediaFile ## Description This class represents references to media content (such as images) located within Commerce Cloud Digital or on external systems. Parameter transform: Some methods allow the specification of image transformation parameters. Image transformation is only performed if the Dynamic Imaging Service (DIS) is available for the Commerce Cloud Digital instance, otherwise a standard static content URL is returned. The to-be-transformed image needs to be hosted on Commerce Cloud Digital. Image transformation parameters are specified as JavaScript object literal. They are translated into URL parameters. See Create Image Transformation URLs. Type of transformation Parameters Description Scale an image scaleWidth scaleHeight scaleMode The scaleWidth and scaleHeight parameters are both integers; setting one of these parameters triggers a scaling operation. If both are provided, the one that scales the image less is used to calculate the scale factor. The image is then automatically cropped accord to the second dimension, with a centered position of the cropped area. If the parameter would scale the image larger, only this operation is applied, if the image remains within acceptable pixel dimensions. Note: scaleMode can only be used in combination with scaleHeight and scaleWidth. The scaleMode parameter can be set to cut or fit. The default scaleMode is cut, the behavior of which is explained above. If you specify fit as the scaleMode, the system scales the image into the given box of dimensions while keeping the aspect ratio (possibly resulting in a smaller image in one dimension). Overlay an image imageX imageY imageURI The imageX and imageY parameters are both integers. Valid values for these parameters are 0 or greater. Supported formats are png, jpg, jp2, and gif. The imageURI parameter can be set to the absolute path of the overlaid image. The value of the imageURI parameter must be given in proper URL encoding, and it cannot exceed 400 characters in length. The path may include query string parameters, which supports dynamically generating the overlaid image itself through this service; that is, the overlaid image can itself be a transformed image. If the overlaid image extends over the primary image's boundaries, the overlaid image is cropped so that it fits directly over the primary image. Crop an image cropX cropY cropWidth cropHeight The cropX, cropY, cropWidth, cropHeight parameters are integers. All four parameters must be specified to trigger a cropping operation. Valid values for the cropX and cropY parameters are 0 or greater. If the crop location defined by cropX and cropY is outside the image area, nothing is cropped. Valid values for the cropWidth and cropHeight parameters are 10 or greater. If the cropWidth and cropHeight parameters specify a size that is greater than the original image, the crop area is reduced to the actual image area. If cropWidth and cropHeight are 0 or less, no transformation is applied. Format an image format The format parameter specifies the target format of image. Supported formats are png, jpg, jp2, and gif. If no target format is specified, no format conversion is performed. The attribute value must reference the source image. Source image's format is recognized by the file extension which must be tif, tiff, jpg, jpeg, png, or gif. In the generated URL the file extension of the target format is used in the URL path. This is to make sure the image is loaded from an URL with a matching file extension. The source format is provided as URL parameter. Adjust image compression quality quality The quality parameter specifies a quality setting for jpg and jp2 images, and specifies the compression level for png images. For jpg and jp2 images, you can set values from 1–100 for the highest quality. The default quality is 80. If you're not changing the default quality, you don't need to pass in a value. For png images, the quality setting has no effect on the appearance of the png, since the compression is always lossless. Instead you can use the quality setting to set the zlib compression level and filter-type for PNG images. The tens digit sets the zlib compression level(1-9). The ones digit sets the filter type. If the png setting is not present or set to 0, it uses a default value of 75. If this setting is set to 100, it actually equals the quality setting 90. Adjust Metadata stripping strip The strip parameter specifies if metadata like EXIF and color profiles is stripped from the image during transformation. Valid values for the strip parameter are between true and false. The default is true Change background color bgcolor(color) or bgcolor(color+alpha) The bgcolor parameter specifies the background color for images that support transparency as well as JPEG images when being converted from a format that supports transparency. Optionally, alpha setting for PNG images are also supported. bgcolor expects a 6 digit hexadecimal value of RGB with an optional two hexadecimal characters representing alpha value that determines transparency. FF0000 = Red FF000077 = Red with 50% transparency Alpha values are optional. When the alpha value is omitted, the resulting color is opaque. Alpha values are only valid when the image output format is PNG. Example: The following code var url = product.getImage('thumbnail', 0).getImageURL({scaleWidth: 100, format: 'jpg'}); will produce an image transformation URL like http://<image server host name>/.../on/demandware.static/.../<path to image>/image.jpg?sw=100&sfrm=png. ## Properties ### absURL **Type:** URL (Read Only) An absolute URL to the referenced media file. The protocol for the reference is the current protocol of the current HTTP request. ### alt **Type:** String (Read Only) The alternative text assigned to the media file in current requests locale. If no alternative text was assigned or if no defaulting rule was defined, the method returns null. ### httpsURL **Type:** URL (Read Only) An absolute URL to the referenced media file. The protocol is https. ### httpURL **Type:** URL (Read Only) An absolute URL to the referenced media file. The protocol is http. ### title **Type:** String (Read Only) The title assigned to the media file in current requests locale. If no title was assigned or if no defaulting rule was defined, the method returns null. ### url **Type:** URL (Read Only) An URL to the referenced media file. The returned URL is a relative URL. ### URL **Type:** URL (Read Only) An URL to the referenced media file. The returned URL is a relative URL. ### viewType **Type:** String (Read Only) The view type annotation for the media file. The method returns null, if the media file has no view type annotation. ## Constructor Summary ## Method Summary ### getAbsImageURL **Signature:** `getAbsImageURL(transform : Object) : URL` Returns an URL to the referenced image file. ### getAbsURL **Signature:** `getAbsURL() : URL` Returns an absolute URL to the referenced media file. ### getAlt **Signature:** `getAlt() : String` Returns the alternative text assigned to the media file in current requests locale. ### getHttpImageURL **Signature:** `getHttpImageURL(transform : Object) : URL` Returns an URL to the referenced image file. ### getHttpsImageURL **Signature:** `getHttpsImageURL(transform : Object) : URL` Returns an URL to the referenced image file. ### getHttpsURL **Signature:** `getHttpsURL() : URL` Returns an absolute URL to the referenced media file. ### getHttpURL **Signature:** `getHttpURL() : URL` Returns an absolute URL to the referenced media file. ### getImageURL **Signature:** `getImageURL(transform : Object) : URL` Returns an URL to the referenced image file. ### getTitle **Signature:** `getTitle() : String` Returns the title assigned to the media file in current requests locale. ### getUrl **Signature:** `getUrl() : URL` Returns an URL to the referenced media file. ### getURL **Signature:** `getURL() : URL` Returns an URL to the referenced media file. ### getViewType **Signature:** `getViewType() : String` Returns the view type annotation for the media file. ## Method Detail ## Method Details ### getAbsImageURL **Signature:** `getAbsImageURL(transform : Object) : URL` **Description:** Returns an URL to the referenced image file. Image transformation can be applied to the image. The protocol for the reference is the current protocol of the current HTTP request. Image transformation can only be applied to images that are hosted on Commerce Cloud Digital. **Parameters:** - `transform`: Object with transformation parameters (see class header) **Returns:** an absolute URL to the referenced media file. The protocol for the reference is the current protocol of the current HTTP request. If the referenced media file is hosted externally, an URL to the external file is returned. --- ### getAbsURL **Signature:** `getAbsURL() : URL` **Description:** Returns an absolute URL to the referenced media file. The protocol for the reference is the current protocol of the current HTTP request. **Returns:** an absolute URL to the referenced media file. The protocol for the reference is the current protocol of the current HTTP request. --- ### getAlt **Signature:** `getAlt() : String` **Description:** Returns the alternative text assigned to the media file in current requests locale. If no alternative text was assigned or if no defaulting rule was defined, the method returns null. **Returns:** the alternative text annotated to this media file or null --- ### getHttpImageURL **Signature:** `getHttpImageURL(transform : Object) : URL` **Description:** Returns an URL to the referenced image file. Image transformation can be applied to the image. The protocol is http. Image transformation can only be applied to images that are hosted on Commerce Cloud Digital. **Parameters:** - `transform`: Object with transformation parameters (see class header) **Returns:** an absolute URL to the referenced media file. The protocol is http. If the referenced media file is hosted externally, an URL to the external file is returned. --- ### getHttpsImageURL **Signature:** `getHttpsImageURL(transform : Object) : URL` **Description:** Returns an URL to the referenced image file. Image transformation can be applied to the image. The protocol is https. Image transformation can only be applied to images that are hosted on Commerce Cloud Digital. **Parameters:** - `transform`: Object with transformation parameters (see class header) **Returns:** an absolute URL to the referenced media file. The protocol is https. If the referenced media file is hosted externally, an URL to the external file is returned. --- ### getHttpsURL **Signature:** `getHttpsURL() : URL` **Description:** Returns an absolute URL to the referenced media file. The protocol is https. **Returns:** an absolute URL to the referenced media file. The protocol is https. --- ### getHttpURL **Signature:** `getHttpURL() : URL` **Description:** Returns an absolute URL to the referenced media file. The protocol is http. **Returns:** an absolute URL to the referenced media file. The protocol is http. --- ### getImageURL **Signature:** `getImageURL(transform : Object) : URL` **Description:** Returns an URL to the referenced image file. Image transformation can be applied to the image. Image transformation can only be applied to images that are hosted on Commerce Cloud Digital. **Parameters:** - `transform`: Object with transformation parameters (see class header) **Returns:** an URL to the referenced media file. The returned URL is a relative URL. If the referenced media file is hosted externally, an URL to the external file is returned. --- ### getTitle **Signature:** `getTitle() : String` **Description:** Returns the title assigned to the media file in current requests locale. If no title was assigned or if no defaulting rule was defined, the method returns null. **Returns:** the title annotated to this media file or null --- ### getUrl **Signature:** `getUrl() : URL` **Description:** Returns an URL to the referenced media file. The returned URL is a relative URL. **Deprecated:** Use getURL() instead. **Returns:** an URL to the referenced media file. The returned URL is a relative URL. --- ### getURL **Signature:** `getURL() : URL` **Description:** Returns an URL to the referenced media file. The returned URL is a relative URL. **Returns:** an URL to the referenced media file. The returned URL is a relative URL. --- ### getViewType **Signature:** `getViewType() : String` **Description:** Returns the view type annotation for the media file. The method returns null, if the media file has no view type annotation. **Returns:** the view type annotated to this media file or null --- ``` -------------------------------------------------------------------------------- /docs/dw_campaign/CampaignMgr.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.campaign # Class CampaignMgr ## Inheritance Hierarchy - Object - dw.campaign.CampaignMgr ## Description CampaignMgr provides static methods for managing campaign-specific operations such as accessing promotions or updating promotion line items. ## Properties ### applicablePromotions **Type:** Collection (Read Only) The enabled promotions of active campaigns applicable for the current customer and source code. Note that this method does not return any coupon-based promotions. ## Constructor Summary ## Method Summary ### applyBonusPromotions **Signature:** `static applyBonusPromotions(lineItemCtnr : LineItemCtnr, promotions : Collection) : boolean` This method has been deprecated and should not be used anymore. ### applyOrderPromotions **Signature:** `static applyOrderPromotions(lineItemCtnr : LineItemCtnr, promotions : Collection) : boolean` Applies the applicable order promotions in the specified collection to the specified line item container. ### applyProductPromotions **Signature:** `static applyProductPromotions(lineItemCtnr : LineItemCtnr, promotions : Collection) : boolean` Applies all applicable product promotions in the specified collection to the specified line item container. ### applyShippingPromotions **Signature:** `static applyShippingPromotions(lineItemCtnr : LineItemCtnr, promotions : Collection) : boolean` Applies all applicable shipping promotions in the specified collection to the specified line item container. ### getApplicableConditionalPromotions **Signature:** `static getApplicableConditionalPromotions(product : Product) : Collection` Returns the enabled promotions of active campaigns applicable for the current customer and source code for which the specified product is a qualifiying product. ### getApplicablePromotions **Signature:** `static getApplicablePromotions(product : Product) : Collection` Returns the enabled promotions of active campaigns applicable for the current customer and source code for which the specified product is a discounted product. ### getApplicablePromotions **Signature:** `static getApplicablePromotions(lineItemCtnr : LineItemCtnr) : Collection` Returns the enabled promotions of active campaigns applicable for the current customer, source code and any coupon contained in the specified line item container. ### getApplicablePromotions **Signature:** `static getApplicablePromotions() : Collection` Returns the enabled promotions of active campaigns applicable for the current customer and source code. ### getCampaignByID **Signature:** `static getCampaignByID(id : String) : Campaign` Returns the campaign identified by the specified ID. ### getConditionalPromotions **Signature:** `static getConditionalPromotions(product : Product) : Collection` Returns the enabled promotions of active campaigns for which the specified product is a qualifiying product. ### getPromotion **Signature:** `static getPromotion(couponCode : String) : Promotion` Returns the promotion associated with the specified coupon code. ### getPromotionByCouponCode **Signature:** `static getPromotionByCouponCode(couponCode : String) : Promotion` Returns the promotion associated with the specified coupon code. ### getPromotionByID **Signature:** `static getPromotionByID(id : String) : Promotion` Returns the promotion identified by the specified ID. ### getPromotions **Signature:** `static getPromotions(product : Product) : Collection` Returns the enabled promotions of active campaigns for which the specified product is a discounted product. ## Method Detail ## Method Details ### applyBonusPromotions **Signature:** `static applyBonusPromotions(lineItemCtnr : LineItemCtnr, promotions : Collection) : boolean` **Description:** This method has been deprecated and should not be used anymore. Instead, use PromotionMgr to apply promotions to line item containers. The method does nothing, since bonus promotions are applied as product or order promotions using methods applyProductPromotions(LineItemCtnr, Collection) and applyOrderPromotions(LineItemCtnr, Collection). The method returns 'true' if any the line item container contains any bonus product line items, and otherwise false. **Deprecated:** Use PromotionMgr instead. **Parameters:** - `lineItemCtnr`: Basket or order - `promotions`: Parameter not used, can be null **Returns:** True if line item container contains bonus product line items, else false --- ### applyOrderPromotions **Signature:** `static applyOrderPromotions(lineItemCtnr : LineItemCtnr, promotions : Collection) : boolean` **Description:** Applies the applicable order promotions in the specified collection to the specified line item container. This method has been deprecated and should not be used anymore. Instead, use PromotionMgr to apply promotions to line item containers. Note that the method does also apply any bonus discounts defined as order promotions (see also applyBonusPromotions(LineItemCtnr, Collection)). **Deprecated:** Use PromotionMgr **Parameters:** - `lineItemCtnr`: basket or order - `promotions`: list of all promotions to be applied **Returns:** true if changes were made to the line item container, false otherwise. --- ### applyProductPromotions **Signature:** `static applyProductPromotions(lineItemCtnr : LineItemCtnr, promotions : Collection) : boolean` **Description:** Applies all applicable product promotions in the specified collection to the specified line item container. This method has been deprecated and should not be used anymore. Instead, use PromotionMgr to apply promotions to line item containers. Note that the method does also apply any bonus discounts defined as product promotions (see also applyBonusPromotions(LineItemCtnr, Collection)). **Deprecated:** Use PromotionMgr **Parameters:** - `lineItemCtnr`: basket or order - `promotions`: list of all promotions to be applied **Returns:** true if changes were made to the line item container, false otherwise. --- ### applyShippingPromotions **Signature:** `static applyShippingPromotions(lineItemCtnr : LineItemCtnr, promotions : Collection) : boolean` **Description:** Applies all applicable shipping promotions in the specified collection to the specified line item container. This method has been deprecated and should not be used anymore. Instead, use PromotionMgr to apply promotions to line item containers. **Deprecated:** Use PromotionMgr **Parameters:** - `lineItemCtnr`: basket or order - `promotions`: list of all promotions to be applied **Returns:** true if changes were made to the line item container, false otherwise. --- ### getApplicableConditionalPromotions **Signature:** `static getApplicableConditionalPromotions(product : Product) : Collection` **Description:** Returns the enabled promotions of active campaigns applicable for the current customer and source code for which the specified product is a qualifiying product. As a replacement of this deprecated method, use PromotionMgr.getActiveCustomerPromotions() and PromotionPlan.getProductPromotions(Product). Unlike getApplicableConditionalPromotions(Product), PromotionPlan.getProductPromotions(Product) returns all promotions related to the specified product, regardless of whether the product is qualifying, discounted, or both, and also returns promotions where the product is a bonus product. **Deprecated:** Use PromotionMgr.getActiveCustomerPromotions() and PromotionPlan.getProductPromotions(Product) **Parameters:** - `product`: Qualifying product **Returns:** List of active promotions --- ### getApplicablePromotions **Signature:** `static getApplicablePromotions(product : Product) : Collection` **Description:** Returns the enabled promotions of active campaigns applicable for the current customer and source code for which the specified product is a discounted product. Note that this method does not return any coupon-based promotions. As a replacement of this deprecated method, use PromotionMgr.getActiveCustomerPromotions() and PromotionPlan.getProductPromotions(Product). Unlike getApplicablePromotions(Product), PromotionPlan.getProductPromotions(Product) returns all promotions related to the specified product, regardless of whether the product is qualifying, discounted, or both, and also returns promotions where the product is a bonus product. **Deprecated:** Use PromotionMgr.getActiveCustomerPromotions() and PromotionPlan.getProductPromotions(Product) **Parameters:** - `product`: The product whose promotions are returned. **Returns:** A list of promotions --- ### getApplicablePromotions **Signature:** `static getApplicablePromotions(lineItemCtnr : LineItemCtnr) : Collection` **Description:** Returns the enabled promotions of active campaigns applicable for the current customer, source code and any coupon contained in the specified line item container. Note that although the method has been deprecated, no replacement method is provided. **Deprecated:** There is no replacement for this method. **Parameters:** - `lineItemCtnr`: the basket or order **Returns:** list of all applicable promotion for the given basket or order --- ### getApplicablePromotions **Signature:** `static getApplicablePromotions() : Collection` **Description:** Returns the enabled promotions of active campaigns applicable for the current customer and source code. Note that this method does not return any coupon-based promotions. **Deprecated:** Use PromotionMgr.getActiveCustomerPromotions() and PromotionPlan.getPromotions() **Returns:** List of active promotions --- ### getCampaignByID **Signature:** `static getCampaignByID(id : String) : Campaign` **Description:** Returns the campaign identified by the specified ID. **Deprecated:** Use PromotionMgr.getCampaign(String) **Parameters:** - `id`: Campaign ID **Returns:** Campaign or null if not found --- ### getConditionalPromotions **Signature:** `static getConditionalPromotions(product : Product) : Collection` **Description:** Returns the enabled promotions of active campaigns for which the specified product is a qualifiying product. Note that the method also returns coupon-based promotions. As a replacement of this deprecated method, use PromotionMgr.getActiveCustomerPromotions() and PromotionPlan.getProductPromotions(Product). Unlike getConditionalPromotions(Product), PromotionPlan.getProductPromotions(Product) returns all promotions related to the specified product, regardless of whether the product is qualifying, discounted, or both, and also returns promotions where the product is a bonus product. **Deprecated:** Use PromotionMgr.getActivePromotions() and PromotionPlan.getProductPromotions(Product) **Parameters:** - `product`: The product whose conditional promotions are returned. **Returns:** A list of promotions --- ### getPromotion **Signature:** `static getPromotion(couponCode : String) : Promotion` **Description:** Returns the promotion associated with the specified coupon code. **Deprecated:** Coupons are now related to multiple promotions. Method returns the first promotion associated with the coupon code in case of multiple assigned promotions. **Parameters:** - `couponCode`: The coupon code used to lookup the promotion **Returns:** The resolved promotion object or null if none was found --- ### getPromotionByCouponCode **Signature:** `static getPromotionByCouponCode(couponCode : String) : Promotion` **Description:** Returns the promotion associated with the specified coupon code. **Deprecated:** Coupons are now related to multiple promotions. Method returns the first promotion associated with the coupon in case of multiple assigned promotions **Parameters:** - `couponCode`: Coupon code **Returns:** The associated promotion or null --- ### getPromotionByID **Signature:** `static getPromotionByID(id : String) : Promotion` **Description:** Returns the promotion identified by the specified ID. **Deprecated:** Use PromotionMgr.getPromotion(String) **Parameters:** - `id`: Promotion ID **Returns:** Promotion or null if not found --- ### getPromotions **Signature:** `static getPromotions(product : Product) : Collection` **Description:** Returns the enabled promotions of active campaigns for which the specified product is a discounted product. Note that method does only return promotions based on customer groups or source codes. As a replacement of this deprecated method, use PromotionMgr.getActiveCustomerPromotions() and PromotionPlan.getProductPromotions(Product). Unlike getPromotions(Product), PromotionPlan.getProductPromotions(Product) returns all promotions related to the specified product, regardless of whether the product is qualifying, discounted, or both, and also returns promotions where the product is a bonus product. **Deprecated:** Use PromotionMgr.getActivePromotions() and PromotionPlan.getProductPromotions(Product) **Parameters:** - `product`: Discounted product **Returns:** List of promotions --- ``` -------------------------------------------------------------------------------- /docs/dw_value/Money.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.value # Class Money ## Inheritance Hierarchy - Object - dw.value.Money ## Description Represents money in Commerce Cloud Digital. ## Constants ### NOT_AVAILABLE **Type:** Money Represents that there is no money available. ## Properties ### available **Type:** boolean (Read Only) Identifies if the instance contains settings for value and currency. ### currencyCode **Type:** String (Read Only) The ISO 4217 currency mnemonic (such as 'USD', 'EUR') of the currency the money value relates to. Note a money instance may also describe a price that is 'not available'. In this case the value of this attribute is N/A. ### decimalValue **Type:** Decimal (Read Only) The money as Decimal, null is returned when the money is not available. ### value **Type:** Number (Read Only) The value of the money instance. ### valueOrNull **Type:** Number (Read Only) Return the value of the money instance or null if the Money instance is NOT_AVAILABLE. ## Constructor Summary Money(value : Number, currencyCode : String) Constructs a new money instance with the specified amount for the specified currency. ## Method Summary ### add **Signature:** `add(value : Money) : Money` Returns a Money instance by adding the specified Money object to the current object. ### addPercent **Signature:** `addPercent(percent : Number) : Money` Adds a certain percentage to the money object. ### addRate **Signature:** `addRate(value : Number) : Money` Adds a rate (e.g. ### compareTo **Signature:** `compareTo(other : Money) : Number` Compares two Money values. ### divide **Signature:** `divide(divisor : Number) : Money` Divide Money object by specified divisor. ### equals **Signature:** `equals(other : Object) : boolean` Compares two money values whether they are equivalent. ### getCurrencyCode **Signature:** `getCurrencyCode() : String` Returns the ISO 4217 currency mnemonic (such as 'USD', 'EUR') of the currency the money value relates to. ### getDecimalValue **Signature:** `getDecimalValue() : Decimal` Returns the money as Decimal, null is returned when the money is not available. ### getValue **Signature:** `getValue() : Number` Returns the value of the money instance. ### getValueOrNull **Signature:** `getValueOrNull() : Number` Return the value of the money instance or null if the Money instance is NOT_AVAILABLE. ### hashCode **Signature:** `hashCode() : Number` Calculates the hash code for a money; ### isAvailable **Signature:** `isAvailable() : boolean` Identifies if the instance contains settings for value and currency. ### isOfSameCurrency **Signature:** `isOfSameCurrency(value : Money) : boolean` Identifies if two Money value have the same currency. ### multiply **Signature:** `multiply(factor : Number) : Money` Multiply Money object by specified factor. ### multiply **Signature:** `multiply(quantity : Quantity) : Money` Multiplies the Money object with the given quantity. ### newMoney **Signature:** `newMoney(value : Decimal) : Money` Method returns a new instance of Money with the same currency but different value. ### percentLessThan **Signature:** `percentLessThan(value : Money) : Number` Convenience method. ### percentOf **Signature:** `percentOf(value : Money) : Number` Convenience method. ### prorate **Signature:** `static prorate(dist : Money, values : Money...) : Money[]` Prorates the specified values using the specified discount. ### subtract **Signature:** `subtract(value : Money) : Money` Returns a new Money instance by substracting the specified Money object from the current object. ### subtractPercent **Signature:** `subtractPercent(percent : Number) : Money` Subtracts a certain percentage from the money object. ### subtractRate **Signature:** `subtractRate(value : Number) : Money` Subtracts a rate (e.g. ### toFormattedString **Signature:** `toFormattedString() : String` Returns a string representation of Money according to the regional settings configured for current request locale, for example '$59.00' or 'USD 59.00'. ### toNumberString **Signature:** `toNumberString() : String` Returns a string representation for the numeric value of this money. ### toString **Signature:** `toString() : String` Returns a string representation of this Money object. ### valueOf **Signature:** `valueOf() : Object` According to the ECMA spec returns the "natural" primitve value. ## Constructor Detail ## Method Detail ## Method Details ### add **Signature:** `add(value : Money) : Money` **Description:** Returns a Money instance by adding the specified Money object to the current object. Only objects representing the same currency can be added. If one of the Money values is N/A, the result is N/A. **Parameters:** - `value`: the Money object to add to this Money instance. **Returns:** the Money object representing the sum of the operands. --- ### addPercent **Signature:** `addPercent(percent : Number) : Money` **Description:** Adds a certain percentage to the money object. The percent value is given as true percent value, so for example 10 represent 10%. If this Money is N/A the result is also N/A. **Parameters:** - `percent`: the percent value **Returns:** new Money object with the result of the calculation --- ### addRate **Signature:** `addRate(value : Number) : Money` **Description:** Adds a rate (e.g. 0.05) to the money object. This is typically for example to add a tax rate. **Parameters:** - `value`: the rate to add. **Returns:** a new Money object with rate added. --- ### compareTo **Signature:** `compareTo(other : Money) : Number` **Description:** Compares two Money values. An exception is thrown if the two Money values are of different currency. If one of the Money values represents the N/A value it is treated as 0.0. **Parameters:** - `other`: the money instance to comare against this money instance. **Returns:** the comparison of 0 if the money instances are equal or non-0 if they are different. --- ### divide **Signature:** `divide(divisor : Number) : Money` **Description:** Divide Money object by specified divisor. If this Money is N/A the result is also N/A. **Parameters:** - `divisor`: the divisor. **Returns:** Money object representing division result --- ### equals **Signature:** `equals(other : Object) : boolean` **Description:** Compares two money values whether they are equivalent. **Parameters:** - `other`: the object to compare against this money instance. **Returns:** true if equal, false otherwise. --- ### getCurrencyCode **Signature:** `getCurrencyCode() : String` **Description:** Returns the ISO 4217 currency mnemonic (such as 'USD', 'EUR') of the currency the money value relates to. Note a money instance may also describe a price that is 'not available'. In this case the value of this attribute is N/A. **Returns:** the value of the currency code. --- ### getDecimalValue **Signature:** `getDecimalValue() : Decimal` **Description:** Returns the money as Decimal, null is returned when the money is not available. **Returns:** the money as Decimal --- ### getValue **Signature:** `getValue() : Number` **Description:** Returns the value of the money instance. **Returns:** the value of the money instance. **See Also:** getDecimalValue() --- ### getValueOrNull **Signature:** `getValueOrNull() : Number` **Description:** Return the value of the money instance or null if the Money instance is NOT_AVAILABLE. **Returns:** Value of money instance or null. --- ### hashCode **Signature:** `hashCode() : Number` **Description:** Calculates the hash code for a money; --- ### isAvailable **Signature:** `isAvailable() : boolean` **Description:** Identifies if the instance contains settings for value and currency. **Returns:** true if the instance is initialized with value and currency, false if the state is 'not available'. --- ### isOfSameCurrency **Signature:** `isOfSameCurrency(value : Money) : boolean` **Description:** Identifies if two Money value have the same currency. **Parameters:** - `value`: the Money value passed to be tested **Returns:** true if both instances have the same currency, false otherwise. --- ### multiply **Signature:** `multiply(factor : Number) : Money` **Description:** Multiply Money object by specified factor. If this Money is N/A the result is also N/A. **Parameters:** - `factor`: multiplication factor **Returns:** Money object representing multiplication result. --- ### multiply **Signature:** `multiply(quantity : Quantity) : Money` **Description:** Multiplies the Money object with the given quantity. If this Money is N/A the result is also N/A. **Parameters:** - `quantity`: the quantity to multiply the value by **Returns:** a new Money representing the multiplication result. --- ### newMoney **Signature:** `newMoney(value : Decimal) : Money` **Description:** Method returns a new instance of Money with the same currency but different value. An N/A instance is returned if value is null. **Parameters:** - `value`: as a decimal **Returns:** new Money instance with same currency --- ### percentLessThan **Signature:** `percentLessThan(value : Money) : Number` **Description:** Convenience method. Calculates and returns the percentage off this price represents in relation to the passed base price. The result is generally equal to 100.0 - this.percentOf(value). For example, if this value is $30 and the passed value is $50, then the return value will be 40.0, representing a 40% discount. This method will return null if the compare value is null, this value or the compare value is unavailable, or the compare value equals 0.0. **Parameters:** - `value`: The price to compare to this price **Returns:** The percentage discount this price represents in relation to the passed base price. **See Also:** percentOf(Money) **Throws:** IllegalArgumentException - If the currencies are not comparable. --- ### percentOf **Signature:** `percentOf(value : Money) : Number` **Description:** Convenience method. Calculates and returns the percentage of the passed value this price represents. For example, if this value is $30 and the passed value is $50, then the return value will be 60.0 (i.e. 60%). This method will return null if the compare value is null, this value or the compare value is unavailable, or the compare value equals 0.0. **Parameters:** - `value`: The price to compare to this price **Returns:** The percentage of the compare price this price represents, or null. **Throws:** IllegalArgumentException - If the currencies are not comparable. --- ### prorate **Signature:** `static prorate(dist : Money, values : Money...) : Money[]` **Description:** Prorates the specified values using the specified discount. **Parameters:** - `dist`: the proration discount. - `values`: the values to prorate. **Returns:** the prorated values. --- ### subtract **Signature:** `subtract(value : Money) : Money` **Description:** Returns a new Money instance by substracting the specified Money object from the current object. Only objects representing the same currency can be subtracted. If one of the Money values is N/A, the result is N/A. **Parameters:** - `value`: the Money object to subtract **Returns:** the Money object representing the result of subtraction. --- ### subtractPercent **Signature:** `subtractPercent(percent : Number) : Money` **Description:** Subtracts a certain percentage from the money object. The percent value is given as true percent value, so for example 10 represent 10%. If this Money is N/A the result is also N/A. **Parameters:** - `percent`: the percent value **Returns:** new Money object with the result of the calculation --- ### subtractRate **Signature:** `subtractRate(value : Number) : Money` **Description:** Subtracts a rate (e.g. 0.05) from the money object. This is typically for example to subtract a tax rates. **Parameters:** - `value`: the rate to subtract. **Returns:** a new Money object with rate subtracted. --- ### toFormattedString **Signature:** `toFormattedString() : String` **Description:** Returns a string representation of Money according to the regional settings configured for current request locale, for example '$59.00' or 'USD 59.00'. **Returns:** The formatted String representation of the passed money. In case of an error the string 'N/A' is returned. --- ### toNumberString **Signature:** `toNumberString() : String` **Description:** Returns a string representation for the numeric value of this money. The number is formatted with the decimal symbols of the platforms default locale. **Returns:** a string representation for the numeric value of this money. --- ### toString **Signature:** `toString() : String` **Description:** Returns a string representation of this Money object. **Returns:** a string representation of this Money object. --- ### valueOf **Signature:** `valueOf() : Object` **Description:** According to the ECMA spec returns the "natural" primitve value. Here the value portion of the Money is returned. --- ``` -------------------------------------------------------------------------------- /docs/dw_customer/CustomerAddress.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.customer # Class CustomerAddress ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.customer.CustomerAddress ## Description The Address class represents a customer's address. Note: this class allows access to sensitive personal and private information. Pay attention to appropriate legal and regulatory requirements. ## Properties ### address1 **Type:** String The customer's first address. ### address2 **Type:** String The customer's second address value. ### city **Type:** String The customer's city. ### companyName **Type:** String The customer's company name. ### countryCode **Type:** EnumValue The customer's country code. Commerce Cloud Digital supports two-character country codes per ISO 3166-1 alpha-2. See http://www.iso.org/iso/country_codes/iso_3166-faqs/iso_3166_faqs_general.htm for additional information. ### firstName **Type:** String The customer's first name. ### fullName **Type:** String (Read Only) A concatenation of the customer's first, middle, and last names and its suffix. ### ID **Type:** String The name of the address. ### jobTitle **Type:** String The customer's job title. ### lastName **Type:** String The customer's last name. ### phone **Type:** String The customer's phone number. ### postalCode **Type:** String The customer's postal code. ### postBox **Type:** String The customer's post box. ### salutation **Type:** String The customer's salutation. ### secondName **Type:** String The customer's second name. ### stateCode **Type:** String The customer's state. ### suffix **Type:** String The customer's suffix. ### suite **Type:** String The customer's suite. ### title **Type:** String The customer's title. ## Constructor Summary ## Method Summary ### getAddress1 **Signature:** `getAddress1() : String` Returns the customer's first address. ### getAddress2 **Signature:** `getAddress2() : String` Returns the customer's second address value. ### getCity **Signature:** `getCity() : String` Returns the customer's city. ### getCompanyName **Signature:** `getCompanyName() : String` Returns the customer's company name. ### getCountryCode **Signature:** `getCountryCode() : EnumValue` Returns the customer's country code. ### getFirstName **Signature:** `getFirstName() : String` Returns the customer's first name. ### getFullName **Signature:** `getFullName() : String` Returns a concatenation of the customer's first, middle, and last names and its suffix. ### getID **Signature:** `getID() : String` Returns the name of the address. ### getJobTitle **Signature:** `getJobTitle() : String` Returns the customer's job title. ### getLastName **Signature:** `getLastName() : String` Returns the customer's last name. ### getPhone **Signature:** `getPhone() : String` Returns the customer's phone number. ### getPostalCode **Signature:** `getPostalCode() : String` Returns the customer's postal code. ### getPostBox **Signature:** `getPostBox() : String` Returns the customer's post box. ### getSalutation **Signature:** `getSalutation() : String` Returns the customer's salutation. ### getSecondName **Signature:** `getSecondName() : String` Returns the customer's second name. ### getStateCode **Signature:** `getStateCode() : String` Returns the customer's state. ### getSuffix **Signature:** `getSuffix() : String` Returns the customer's suffix. ### getSuite **Signature:** `getSuite() : String` Returns the customer's suite. ### getTitle **Signature:** `getTitle() : String` Returns the customer's title. ### isEquivalentAddress **Signature:** `isEquivalentAddress(address : Object) : boolean` Returns true if the specified address is equivalent to this address. ### setAddress1 **Signature:** `setAddress1(value : String) : void` Sets the value of the customer's first address. ### setAddress2 **Signature:** `setAddress2(value : String) : void` Sets the customer's second address value. ### setCity **Signature:** `setCity(city : String) : void` Sets the customer's city. ### setCompanyName **Signature:** `setCompanyName(companyName : String) : void` Sets the customer's company name. ### setCountryCode **Signature:** `setCountryCode(countryCode : String) : void` Sets the customer's country code. ### setFirstName **Signature:** `setFirstName(firstName : String) : void` Sets the customer's first name. ### setID **Signature:** `setID(value : String) : void` Sets the address name. ### setJobTitle **Signature:** `setJobTitle(jobTitle : String) : void` Sets the customer's job title. ### setLastName **Signature:** `setLastName(lastName : String) : void` Sets the customer's last name. ### setPhone **Signature:** `setPhone(phoneNumber : String) : void` Sets the customer's phone number. ### setPostalCode **Signature:** `setPostalCode(postalCode : String) : void` Sets the customer's postal code. ### setPostBox **Signature:** `setPostBox(postBox : String) : void` Sets the customer's post box. ### setSaluation **Signature:** `setSaluation(value : String) : void` Sets the customer's salutation. ### setSalutation **Signature:** `setSalutation(value : String) : void` Sets the customer's salutation. ### setSecondName **Signature:** `setSecondName(secondName : String) : void` Sets the customer's second name. ### setStateCode **Signature:** `setStateCode(state : String) : void` Sets the customer's state. ### setSuffix **Signature:** `setSuffix(suffix : String) : void` Sets the customer's suffix. ### setSuite **Signature:** `setSuite(value : String) : void` Sets the customer's suite. ### setTitle **Signature:** `setTitle(title : String) : void` Sets the customer's title. ## Method Detail ## Method Details ### getAddress1 **Signature:** `getAddress1() : String` **Description:** Returns the customer's first address. **Returns:** the first address value. --- ### getAddress2 **Signature:** `getAddress2() : String` **Description:** Returns the customer's second address value. **Returns:** the value of the second address. --- ### getCity **Signature:** `getCity() : String` **Description:** Returns the customer's city. **Returns:** the customer's city. --- ### getCompanyName **Signature:** `getCompanyName() : String` **Description:** Returns the customer's company name. **Returns:** the company name. --- ### getCountryCode **Signature:** `getCountryCode() : EnumValue` **Description:** Returns the customer's country code. Commerce Cloud Digital supports two-character country codes per ISO 3166-1 alpha-2. See http://www.iso.org/iso/country_codes/iso_3166-faqs/iso_3166_faqs_general.htm for additional information. **Returns:** the two-digit country code. --- ### getFirstName **Signature:** `getFirstName() : String` **Description:** Returns the customer's first name. **Returns:** the customer first name. --- ### getFullName **Signature:** `getFullName() : String` **Description:** Returns a concatenation of the customer's first, middle, and last names and its suffix. **Returns:** a concatenation of the customer's first, middle, and last names and its suffix. --- ### getID **Signature:** `getID() : String` **Description:** Returns the name of the address. **Returns:** the address name. --- ### getJobTitle **Signature:** `getJobTitle() : String` **Description:** Returns the customer's job title. **Returns:** the job title. --- ### getLastName **Signature:** `getLastName() : String` **Description:** Returns the customer's last name. **Returns:** the last name. --- ### getPhone **Signature:** `getPhone() : String` **Description:** Returns the customer's phone number. **Returns:** the phone number. --- ### getPostalCode **Signature:** `getPostalCode() : String` **Description:** Returns the customer's postal code. **Returns:** the postal code. --- ### getPostBox **Signature:** `getPostBox() : String` **Description:** Returns the customer's post box. **Returns:** the post box. --- ### getSalutation **Signature:** `getSalutation() : String` **Description:** Returns the customer's salutation. **Returns:** the salutation. --- ### getSecondName **Signature:** `getSecondName() : String` **Description:** Returns the customer's second name. **Returns:** the second name. --- ### getStateCode **Signature:** `getStateCode() : String` **Description:** Returns the customer's state. **Returns:** the state. --- ### getSuffix **Signature:** `getSuffix() : String` **Description:** Returns the customer's suffix. **Returns:** the suffix. --- ### getSuite **Signature:** `getSuite() : String` **Description:** Returns the customer's suite. **Returns:** the suite. --- ### getTitle **Signature:** `getTitle() : String` **Description:** Returns the customer's title. **Returns:** the title. --- ### isEquivalentAddress **Signature:** `isEquivalentAddress(address : Object) : boolean` **Description:** Returns true if the specified address is equivalent to this address. An equivalent address is an address whose core attributes contain the same values. The core attributes are: address1 address2 city companyName countryCode firstName lastName postalCode postBox stateCode **Parameters:** - `address`: the address to test. **Returns:** true if the specified address is equivalent to this address, false otherwise. --- ### setAddress1 **Signature:** `setAddress1(value : String) : void` **Description:** Sets the value of the customer's first address. **Parameters:** - `value`: The value to set. --- ### setAddress2 **Signature:** `setAddress2(value : String) : void` **Description:** Sets the customer's second address value. **Parameters:** - `value`: The value to set. --- ### setCity **Signature:** `setCity(city : String) : void` **Description:** Sets the customer's city. **Parameters:** - `city`: the customer's city to set. --- ### setCompanyName **Signature:** `setCompanyName(companyName : String) : void` **Description:** Sets the customer's company name. **Parameters:** - `companyName`: the name of the company. --- ### setCountryCode **Signature:** `setCountryCode(countryCode : String) : void` **Description:** Sets the customer's country code. Commerce Cloud Digital supports two-character country codes per ISO 3166-1 alpha-2. See http://www.iso.org/iso/country_codes/iso_3166-faqs/iso_3166_faqs_general.htm for additional information. **Parameters:** - `countryCode`: the country code, must be no more than 2 characters or will be truncated. --- ### setFirstName **Signature:** `setFirstName(firstName : String) : void` **Description:** Sets the customer's first name. **Parameters:** - `firstName`: the customer's first name to set. --- ### setID **Signature:** `setID(value : String) : void` **Description:** Sets the address name. **Parameters:** - `value`: the name to use. --- ### setJobTitle **Signature:** `setJobTitle(jobTitle : String) : void` **Description:** Sets the customer's job title. **Parameters:** - `jobTitle`: The jobTitle to set. --- ### setLastName **Signature:** `setLastName(lastName : String) : void` **Description:** Sets the customer's last name. **Parameters:** - `lastName`: The last name to set. --- ### setPhone **Signature:** `setPhone(phoneNumber : String) : void` **Description:** Sets the customer's phone number. The length is restricted to 32 characters. **Parameters:** - `phoneNumber`: The phone number to set. --- ### setPostalCode **Signature:** `setPostalCode(postalCode : String) : void` **Description:** Sets the customer's postal code. **Parameters:** - `postalCode`: The postal code to set. --- ### setPostBox **Signature:** `setPostBox(postBox : String) : void` **Description:** Sets the customer's post box. **Parameters:** - `postBox`: The post box to set. --- ### setSaluation **Signature:** `setSaluation(value : String) : void` **Description:** Sets the customer's salutation. **Deprecated:** Use setSalutation(String) **Parameters:** - `value`: the salutation. --- ### setSalutation **Signature:** `setSalutation(value : String) : void` **Description:** Sets the customer's salutation. **Parameters:** - `value`: the salutation. --- ### setSecondName **Signature:** `setSecondName(secondName : String) : void` **Description:** Sets the customer's second name. **Parameters:** - `secondName`: The second name to set. --- ### setStateCode **Signature:** `setStateCode(state : String) : void` **Description:** Sets the customer's state. **Parameters:** - `state`: The state to set. --- ### setSuffix **Signature:** `setSuffix(suffix : String) : void` **Description:** Sets the customer's suffix. **Parameters:** - `suffix`: The suffix to set. --- ### setSuite **Signature:** `setSuite(value : String) : void` **Description:** Sets the customer's suite. The length is restricted to 32 characters. **Parameters:** - `value`: the suite to set. --- ### setTitle **Signature:** `setTitle(title : String) : void` **Description:** Sets the customer's title. **Parameters:** - `title`: The title to set. --- ``` -------------------------------------------------------------------------------- /docs/dw_catalog/ProductAttributeModel.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.catalog # Class ProductAttributeModel ## Inheritance Hierarchy - Object - dw.catalog.ProductAttributeModel ## Description Class representing the complete attribute model for products in the system. An instance of this class provides methods to access the attribute definitions and groups for the system object type 'Product' and perhaps additional information depending on how the instance is obtained. A ProductAttributeModel can be obtained in one of three ways: ProductAttributeModel(): When the no-arg constructor is used the model represents: the attribute groups of the system object type 'Product' (i.e. the global product attribute groups) and their bound attributes Category.getProductAttributeModel(): When the attribute model for a Category is retrieved, the model represents: the global product attribute groups product attribute groups of the calling category product attribute groups of any parent categories of the calling category Product.getAttributeModel(): When the attribute model for a Product is retrieved, the model represents: the global product attribute groups product attribute groups of the product's classification category product attribute groups of any parent categories of the product's classification category In this case, the model additionally provides access to the attribute values of the product. If the product lacks a classification category, then only the global product attribute group is considered by the model. The ProductAttributeModel provides a generic way to display the attribute values of a product on a product detail page organized into appropriate visual groups. This is typically done as follows: On the product detail page, call Product.getAttributeModel() to get the attribute model for the product. Call getVisibleAttributeGroups() to get the groups that are appropriate for this product and all other products assigned to the same classification category. Iterate the groups, and display each as a "group" in the UI. Call getVisibleAttributeDefinitions(ObjectAttributeGroup) for each group. Iterate and display the attribute names using ObjectAttributeDefinition.getDisplayName(). For each attribute, get the product's display value(s) for that attribute, using getDisplayValue(). This might require custom display logic based on the type of attribute (strings, dates, multi-value attributes, etc). ## Properties ### attributeGroups **Type:** Collection (Read Only) A sorted collection of attribute groups of this model. The groups returned depends on how this model is constructed and what it represents. (See class-level documentation for details). The collection of returned groups is sorted first by scope and secondly by explicit sort order. Global groups always appear before category-specific groups in the list. Groups of parent categories always appear before groups belonging to subcategories. At each scope, groups have an explicit sort order which can be managed within the Business Manager. When there are multiple attribute groups with the same ID, the following rules apply: If this model represents the global product attribute group only (e.g. the no-arg constructor was used), duplicates cannot occur since only one group can be defined with a given ID at that scope. If this model is associated with specific categories (e.g. it is constructed from a product with a classification category), then a category product attribute group might have the same ID as a global product attribute group. In this case, the category group overrides the global one. If a category and one of its ancestor categories both define a product attribute group with the same ID, the sub-category group overrides the parent group. As a result of these rules, this method will never return two attribute groups with the same ID. ### orderRequiredAttributeDefinitions **Type:** Collection (Read Only) An unsorted collection of attribute definitions marked as order-required. Order-required attributes are usually copied into order line items. The returned attribute definitions are sorted according to the explicit sort order defined for the attributes in the group. This is managed by merchant in the Business Manager. ### visibleAttributeGroups **Type:** Collection (Read Only) A sorted collection of visible attribute groups of this model. This method is similar to getAttributeGroups() but only includes attribute groups containing at least one attribute definition that is visible. See getVisibleAttributeDefinitions(ObjectAttributeGroup). ## Constructor Summary ProductAttributeModel() Constructs a product attribute model that is not based on a product nor a category. ## Method Summary ### getAttributeDefinition **Signature:** `getAttributeDefinition(id : String) : ObjectAttributeDefinition` Returns the attribute definition with the given id from the product attribute model. ### getAttributeDefinitions **Signature:** `getAttributeDefinitions(group : ObjectAttributeGroup) : Collection` Returns a sorted collection of attribute definitions for the given attribute group. ### getAttributeGroup **Signature:** `getAttributeGroup(id : String) : ObjectAttributeGroup` Returns the attribute group with the given id from the product attribute model. ### getAttributeGroups **Signature:** `getAttributeGroups() : Collection` Returns a sorted collection of attribute groups of this model. ### getDisplayValue **Signature:** `getDisplayValue(definition : ObjectAttributeDefinition) : Object` Returns the value that the underlying product defines for the given attribute definition in the current locale. ### getOrderRequiredAttributeDefinitions **Signature:** `getOrderRequiredAttributeDefinitions() : Collection` Returns an unsorted collection of attribute definitions marked as order-required. ### getValue **Signature:** `getValue(definition : ObjectAttributeDefinition) : Object` Returns the attribute value for the specified attribute definition. ### getVisibleAttributeDefinitions **Signature:** `getVisibleAttributeDefinitions(group : ObjectAttributeGroup) : Collection` Returns a sorted collection of all visible attribute definitions for the given attribute group. ### getVisibleAttributeGroups **Signature:** `getVisibleAttributeGroups() : Collection` Returns a sorted collection of visible attribute groups of this model. ## Constructor Detail ## Method Detail ## Method Details ### getAttributeDefinition **Signature:** `getAttributeDefinition(id : String) : ObjectAttributeDefinition` **Description:** Returns the attribute definition with the given id from the product attribute model. If attribute definition does not exist, null is returned. **Parameters:** - `id`: the identifier of the attribute definition. **Returns:** attribute definition or null if not exist --- ### getAttributeDefinitions **Signature:** `getAttributeDefinitions(group : ObjectAttributeGroup) : Collection` **Description:** Returns a sorted collection of attribute definitions for the given attribute group. If no attribute definition exist for the group, an empty collection is returned. The returned attribute definitions are sorted according to the explicit sort order defined for the attributes in the group. This is managed by merchant in the Business Manager. **Parameters:** - `group`: the group whose attribute definitions are returned. **Returns:** a sorted collection of ObjectAttributeDefinition instances. --- ### getAttributeGroup **Signature:** `getAttributeGroup(id : String) : ObjectAttributeGroup` **Description:** Returns the attribute group with the given id from the product attribute model. If attribute group does not exist, null is returned. **Parameters:** - `id`: the attribute group identifier. **Returns:** the attribute group or null if not exist --- ### getAttributeGroups **Signature:** `getAttributeGroups() : Collection` **Description:** Returns a sorted collection of attribute groups of this model. The groups returned depends on how this model is constructed and what it represents. (See class-level documentation for details). The collection of returned groups is sorted first by scope and secondly by explicit sort order. Global groups always appear before category-specific groups in the list. Groups of parent categories always appear before groups belonging to subcategories. At each scope, groups have an explicit sort order which can be managed within the Business Manager. When there are multiple attribute groups with the same ID, the following rules apply: If this model represents the global product attribute group only (e.g. the no-arg constructor was used), duplicates cannot occur since only one group can be defined with a given ID at that scope. If this model is associated with specific categories (e.g. it is constructed from a product with a classification category), then a category product attribute group might have the same ID as a global product attribute group. In this case, the category group overrides the global one. If a category and one of its ancestor categories both define a product attribute group with the same ID, the sub-category group overrides the parent group. As a result of these rules, this method will never return two attribute groups with the same ID. **Returns:** collection of all attribute groups. --- ### getDisplayValue **Signature:** `getDisplayValue(definition : ObjectAttributeDefinition) : Object` **Description:** Returns the value that the underlying product defines for the given attribute definition in the current locale. In case the attribute definition defines localized attribute values, the product's value is used as an id to find the localized display value. In case of an Image attribute this method returns a MediaFile instance. In previous versions this method returned a String with the image path. In case of an HTML attribute this method returns a MarkupText instance. In previous versions this method returned a String with the HTML source. **API Versioned:** From version 10.6. In prior versions this method returned a String with the image path or a String with the HTML source **Parameters:** - `definition`: the definition to use. **Returns:** The localized product attribute display value. --- ### getOrderRequiredAttributeDefinitions **Signature:** `getOrderRequiredAttributeDefinitions() : Collection` **Description:** Returns an unsorted collection of attribute definitions marked as order-required. Order-required attributes are usually copied into order line items. The returned attribute definitions are sorted according to the explicit sort order defined for the attributes in the group. This is managed by merchant in the Business Manager. **Returns:** a collection of order-required ObjectAttributeDefinition instances. --- ### getValue **Signature:** `getValue(definition : ObjectAttributeDefinition) : Object` **Description:** Returns the attribute value for the specified attribute definition. If the product does not define a value, null is returned. Note: this method may only be used where the attribute model was created for a specific product; otherwise it will always return null. If the attribute is localized, the value for the current session locale is returned. In case of an Image attribute this method returns a MediaFile instance. In previous versions this method returned a String with the image path. In case of an HTML attribute this method returns a MarkupText instance. In previous versions this method returned a String with the HTML source. **API Versioned:** From version 10.6. In prior versions this method returned a String with the image path or a String with the HTML source. **Parameters:** - `definition`: the attribute definition to use when locating and returning the value. **Returns:** value the value associated with the object attribute definition. --- ### getVisibleAttributeDefinitions **Signature:** `getVisibleAttributeDefinitions(group : ObjectAttributeGroup) : Collection` **Description:** Returns a sorted collection of all visible attribute definitions for the given attribute group. If no visible attribute definition exist for the group, an empty collection is returned. An attribute definition is considered visible if is marked as visible. If the product attribute model is created for a specific product, the product must also define a value for the attribute definition; else the attribute definition is considered as invisible. The returned attribute definitions are sorted according to the explicit sort order defined for the attributes in the group. This is managed by merchant in the Business Manager. **Parameters:** - `group`: the group whose visible attribute definitions are returned. **Returns:** a sorted collection of visible ObjectAttributeDefinition instances. --- ### getVisibleAttributeGroups **Signature:** `getVisibleAttributeGroups() : Collection` **Description:** Returns a sorted collection of visible attribute groups of this model. This method is similar to getAttributeGroups() but only includes attribute groups containing at least one attribute definition that is visible. See getVisibleAttributeDefinitions(ObjectAttributeGroup). **Returns:** sorted collection of visible ObjectAttributeGroup instances. --- ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/get-sfra-document.docs-only.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml description: "Test get_sfra_document tool for retrieving SFRA documentation" tests: # Smoke test - ensure tool is available and accessible - it: "should be available in tools list" request: jsonrpc: "2.0" id: "list-sfra-document-tool" method: "tools/list" params: {} expect: response: jsonrpc: "2.0" id: "list-sfra-document-tool" result: tools: match:arrayContains:name:get_sfra_document stderr: "toBeEmpty" # Valid document tests - Core SFRA classes - it: "should retrieve server document successfully" request: jsonrpc: "2.0" id: "get-server-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "get-server-doc" result: content: - type: "text" text: "match:contains:Class Server" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve request document successfully" request: jsonrpc: "2.0" id: "get-request-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "request" expect: response: jsonrpc: "2.0" id: "get-request-doc" result: content: - type: "text" text: "match:contains:Class Request" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve response document successfully" request: jsonrpc: "2.0" id: "get-response-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "response" expect: response: jsonrpc: "2.0" id: "get-response-doc" result: content: - type: "text" text: "match:contains:Class Response" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve querystring document successfully" request: jsonrpc: "2.0" id: "get-querystring-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "querystring" expect: response: jsonrpc: "2.0" id: "get-querystring-doc" result: content: - type: "text" text: "match:contains:QueryString" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve render document successfully" request: jsonrpc: "2.0" id: "get-render-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "render" expect: response: jsonrpc: "2.0" id: "get-render-doc" result: content: - type: "text" text: "match:contains:render" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" # Product model tests - it: "should retrieve product-full document successfully" request: jsonrpc: "2.0" id: "get-product-full-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "product-full" expect: response: jsonrpc: "2.0" id: "get-product-full-doc" result: content: - type: "text" text: "match:contains:product" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve cart document successfully" request: jsonrpc: "2.0" id: "get-cart-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "cart" expect: response: jsonrpc: "2.0" id: "get-cart-doc" result: content: - type: "text" text: "match:contains:cart" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" # Customer model tests - it: "should retrieve account document successfully" request: jsonrpc: "2.0" id: "get-account-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "account" expect: response: jsonrpc: "2.0" id: "get-account-doc" result: content: - type: "text" text: "match:contains:account" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" # Response format validation tests - it: "should return properly structured JSON content" request: jsonrpc: "2.0" id: "validate-server-structure" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "validate-server-structure" result: content: - type: "text" text: "match:regex:\\{[\\s\\S]*title[\\s\\S]*sections[\\s\\S]*content[\\s\\S]*\\}" isError: false stderr: "toBeEmpty" - it: "should include document metadata" request: jsonrpc: "2.0" id: "validate-metadata" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "validate-metadata" result: content: - type: "text" text: "match:regex:[\\s\\S]*type[\\s\\S]*category[\\s\\S]*filename[\\s\\S]*lastModified[\\s\\S]*" isError: false stderr: "toBeEmpty" - it: "should include sections array" request: jsonrpc: "2.0" id: "validate-sections" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "validate-sections" result: content: - type: "text" text: "match:regex:[\\s\\S]*sections[\\s\\S]*\\[[\\s\\S]*\\][\\s\\S]*" isError: false stderr: "toBeEmpty" - it: "should include comprehensive content" request: jsonrpc: "2.0" id: "validate-content-detail" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "validate-content-detail" result: content: - type: "text" text: "match:regex:[\\s\\S]*Description[\\s\\S]*Method Summary[\\s\\S]*Method Detail[\\s\\S]*" isError: false stderr: "toBeEmpty" # Error handling tests - it: "should handle nonexistent document gracefully" request: jsonrpc: "2.0" id: "error-nonexistent" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "nonexistent-document" expect: response: jsonrpc: "2.0" id: "error-nonexistent" result: content: - type: "text" text: "match:contains:not found" isError: true stderr: "toBeEmpty" - it: "should handle empty document name" request: jsonrpc: "2.0" id: "error-empty-name" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "" expect: response: jsonrpc: "2.0" id: "error-empty-name" result: content: - type: "text" text: "match:regex:(Error|not found|invalid)" isError: true stderr: "toBeEmpty" - it: "should handle invalid document name characters" request: jsonrpc: "2.0" id: "error-invalid-chars" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "invalid/document/name" expect: response: jsonrpc: "2.0" id: "error-invalid-chars" result: content: - type: "text" text: "match:regex:(Error|not found|invalid)" isError: true stderr: "toBeEmpty" - it: "should handle missing documentName parameter" request: jsonrpc: "2.0" id: "error-missing-param" method: "tools/call" params: name: "get_sfra_document" arguments: {} expect: response: jsonrpc: "2.0" id: "error-missing-param" result: content: - type: "text" text: "match:regex:(Error|required|missing|documentName|non-empty string)" isError: true stderr: "toBeEmpty" # Case sensitivity tests - it appears the tool is case-insensitive - it: "should handle case variations for document names" request: jsonrpc: "2.0" id: "case-insensitive-upper" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "SERVER" expect: response: jsonrpc: "2.0" id: "case-insensitive-upper" result: content: - type: "text" text: "match:contains:Class Server" isError: false stderr: "toBeEmpty" - it: "should handle mixed case document names" request: jsonrpc: "2.0" id: "case-insensitive-mixed" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "Server" expect: response: jsonrpc: "2.0" id: "case-insensitive-mixed" result: content: - type: "text" text: "match:contains:Class Server" isError: false stderr: "toBeEmpty" # Content quality tests - it: "should provide meaningful content for server document" request: jsonrpc: "2.0" id: "content-quality-server" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "content-quality-server" result: content: - type: "text" text: "match:regex:[\\s\\S]*middleware[\\s\\S]*routing[\\s\\S]*HTTP[\\s\\S]*" isError: false stderr: "toBeEmpty" - it: "should provide meaningful content for request document" request: jsonrpc: "2.0" id: "content-quality-request" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "request" expect: response: jsonrpc: "2.0" id: "content-quality-request" result: content: - type: "text" text: "match:regex:[\\s\\S]*HTTP[\\s\\S]*session[\\s\\S]*customer[\\s\\S]*" isError: false stderr: "toBeEmpty" # Additional model document tests - it: "should retrieve billing document successfully" request: jsonrpc: "2.0" id: "get-billing-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "billing" expect: response: jsonrpc: "2.0" id: "get-billing-doc" result: content: - type: "text" text: "match:contains:billing" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve shipping document successfully" request: jsonrpc: "2.0" id: "get-shipping-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "shipping" expect: response: jsonrpc: "2.0" id: "get-shipping-doc" result: content: - type: "text" text: "match:contains:shipping" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" # Edge case tests - it: "should handle document names with hyphens" request: jsonrpc: "2.0" id: "hyphen-document" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "product-full" expect: response: jsonrpc: "2.0" id: "hyphen-document" result: content: - type: "text" text: "match:type:string" isError: false stderr: "toBeEmpty" - it: "should handle very long nonexistent document names" request: jsonrpc: "2.0" id: "long-nonexistent" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "this-is-a-very-long-document-name-that-definitely-does-not-exist-anywhere" expect: response: jsonrpc: "2.0" id: "long-nonexistent" result: content: - type: "text" text: "match:regex:(Error|not found)" isError: true stderr: "toBeEmpty" ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/get-sfra-document.full-mode.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml description: "Test get_sfra_document tool for retrieving SFRA documentation" tests: # Smoke test - ensure tool is available and accessible - it: "should be available in tools list" request: jsonrpc: "2.0" id: "list-sfra-document-tool" method: "tools/list" params: {} expect: response: jsonrpc: "2.0" id: "list-sfra-document-tool" result: tools: match:arrayContains:name:get_sfra_document stderr: "toBeEmpty" # Valid document tests - Core SFRA classes - it: "should retrieve server document successfully" request: jsonrpc: "2.0" id: "get-server-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "get-server-doc" result: content: - type: "text" text: "match:contains:Class Server" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve request document successfully" request: jsonrpc: "2.0" id: "get-request-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "request" expect: response: jsonrpc: "2.0" id: "get-request-doc" result: content: - type: "text" text: "match:contains:Class Request" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve response document successfully" request: jsonrpc: "2.0" id: "get-response-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "response" expect: response: jsonrpc: "2.0" id: "get-response-doc" result: content: - type: "text" text: "match:contains:Class Response" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve querystring document successfully" request: jsonrpc: "2.0" id: "get-querystring-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "querystring" expect: response: jsonrpc: "2.0" id: "get-querystring-doc" result: content: - type: "text" text: "match:contains:QueryString" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve render document successfully" request: jsonrpc: "2.0" id: "get-render-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "render" expect: response: jsonrpc: "2.0" id: "get-render-doc" result: content: - type: "text" text: "match:contains:render" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" # Product model tests - it: "should retrieve product-full document successfully" request: jsonrpc: "2.0" id: "get-product-full-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "product-full" expect: response: jsonrpc: "2.0" id: "get-product-full-doc" result: content: - type: "text" text: "match:contains:product" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve cart document successfully" request: jsonrpc: "2.0" id: "get-cart-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "cart" expect: response: jsonrpc: "2.0" id: "get-cart-doc" result: content: - type: "text" text: "match:contains:cart" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" # Customer model tests - it: "should retrieve account document successfully" request: jsonrpc: "2.0" id: "get-account-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "account" expect: response: jsonrpc: "2.0" id: "get-account-doc" result: content: - type: "text" text: "match:contains:account" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" # Response format validation tests - it: "should return properly structured JSON content" request: jsonrpc: "2.0" id: "validate-server-structure" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "validate-server-structure" result: content: - type: "text" text: "match:regex:\\{[\\s\\S]*title[\\s\\S]*sections[\\s\\S]*content[\\s\\S]*\\}" isError: false stderr: "toBeEmpty" - it: "should include document metadata" request: jsonrpc: "2.0" id: "validate-metadata" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "validate-metadata" result: content: - type: "text" text: "match:regex:[\\s\\S]*type[\\s\\S]*category[\\s\\S]*filename[\\s\\S]*lastModified[\\s\\S]*" isError: false stderr: "toBeEmpty" - it: "should include sections array" request: jsonrpc: "2.0" id: "validate-sections" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "validate-sections" result: content: - type: "text" text: "match:regex:[\\s\\S]*sections[\\s\\S]*\\[[\\s\\S]*\\][\\s\\S]*" isError: false stderr: "toBeEmpty" - it: "should include comprehensive content" request: jsonrpc: "2.0" id: "validate-content-detail" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "validate-content-detail" result: content: - type: "text" text: "match:regex:[\\s\\S]*Description[\\s\\S]*Method Summary[\\s\\S]*Method Detail[\\s\\S]*" isError: false stderr: "toBeEmpty" # Error handling tests - it: "should handle nonexistent document gracefully" request: jsonrpc: "2.0" id: "error-nonexistent" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "nonexistent-document" expect: response: jsonrpc: "2.0" id: "error-nonexistent" result: content: - type: "text" text: "match:contains:not found" isError: true stderr: "toBeEmpty" - it: "should handle empty document name" request: jsonrpc: "2.0" id: "error-empty-name" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "" expect: response: jsonrpc: "2.0" id: "error-empty-name" result: content: - type: "text" text: "match:regex:(Error|not found|invalid)" isError: true stderr: "toBeEmpty" - it: "should handle invalid document name characters" request: jsonrpc: "2.0" id: "error-invalid-chars" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "invalid/document/name" expect: response: jsonrpc: "2.0" id: "error-invalid-chars" result: content: - type: "text" text: "match:regex:(Error|not found|invalid)" isError: true stderr: "toBeEmpty" - it: "should handle missing documentName parameter" request: jsonrpc: "2.0" id: "error-missing-param" method: "tools/call" params: name: "get_sfra_document" arguments: {} expect: response: jsonrpc: "2.0" id: "error-missing-param" result: content: - type: "text" text: "match:regex:(Error|required|missing|documentName|non-empty string)" isError: true stderr: "toBeEmpty" # Case sensitivity tests - it appears the tool is case-insensitive - it: "should handle case variations for document names" request: jsonrpc: "2.0" id: "case-insensitive-upper" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "SERVER" expect: response: jsonrpc: "2.0" id: "case-insensitive-upper" result: content: - type: "text" text: "match:contains:Class Server" isError: false stderr: "toBeEmpty" - it: "should handle mixed case document names" request: jsonrpc: "2.0" id: "case-insensitive-mixed" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "Server" expect: response: jsonrpc: "2.0" id: "case-insensitive-mixed" result: content: - type: "text" text: "match:contains:Class Server" isError: false stderr: "toBeEmpty" # Content quality tests - it: "should provide meaningful content for server document" request: jsonrpc: "2.0" id: "content-quality-server" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "server" expect: response: jsonrpc: "2.0" id: "content-quality-server" result: content: - type: "text" text: "match:regex:[\\s\\S]*middleware[\\s\\S]*routing[\\s\\S]*HTTP[\\s\\S]*" isError: false stderr: "toBeEmpty" - it: "should provide meaningful content for request document" request: jsonrpc: "2.0" id: "content-quality-request" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "request" expect: response: jsonrpc: "2.0" id: "content-quality-request" result: content: - type: "text" text: "match:regex:[\\s\\S]*HTTP[\\s\\S]*session[\\s\\S]*customer[\\s\\S]*" isError: false stderr: "toBeEmpty" # Additional model document tests - it: "should retrieve billing document successfully" request: jsonrpc: "2.0" id: "get-billing-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "billing" expect: response: jsonrpc: "2.0" id: "get-billing-doc" result: content: - type: "text" text: "match:contains:billing" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" - it: "should retrieve shipping document successfully" request: jsonrpc: "2.0" id: "get-shipping-doc" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "shipping" expect: response: jsonrpc: "2.0" id: "get-shipping-doc" result: content: - type: "text" text: "match:contains:shipping" isError: false performance: maxResponseTime: "2000ms" stderr: "toBeEmpty" # Edge case tests - it: "should handle document names with hyphens" request: jsonrpc: "2.0" id: "hyphen-document" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "product-full" expect: response: jsonrpc: "2.0" id: "hyphen-document" result: content: - type: "text" text: "match:type:string" isError: false stderr: "toBeEmpty" - it: "should handle very long nonexistent document names" request: jsonrpc: "2.0" id: "long-nonexistent" method: "tools/call" params: name: "get_sfra_document" arguments: documentName: "this-is-a-very-long-document-name-that-definitely-does-not-exist-anywhere" expect: response: jsonrpc: "2.0" id: "long-nonexistent" result: content: - type: "text" text: "match:regex:(Error|not found)" isError: true stderr: "toBeEmpty" ``` -------------------------------------------------------------------------------- /tests/mcp/node/get-log-file-contents.full-mode.programmatic.test.js: -------------------------------------------------------------------------------- ```javascript import { test, describe, before, after, beforeEach } from 'node:test'; import { strict as assert } from 'node:assert'; import { connect } from 'mcp-aegis'; describe('get_log_file_contents - Optimized Programmatic Tests', () => { let client; let testFile; before(async () => { client = await connect('./aegis.config.with-dw.json'); // Discover one working test file for optimization testFile = await discoverTestFile(); }); after(async () => { if (client?.connected) { await client.disconnect(); } }); beforeEach(() => { // CRITICAL: Clear all buffers to prevent leaking into next tests client.clearAllBuffers(); }); // === Helper Functions === function assertValidMCPResponse(result) { assert.ok(result.content, 'Should have content'); assert.ok(Array.isArray(result.content), 'Content should be array'); assert.equal(typeof result.isError, 'boolean', 'isError should be boolean'); } function parseResponseText(text) { return text.startsWith('"') && text.endsWith('"') ? JSON.parse(text) : text; } function assertTextContent(result, expectedSubstring) { assertValidMCPResponse(result); assert.equal(result.content[0].type, 'text'); const actualText = parseResponseText(result.content[0].text); assert.ok(actualText.includes(expectedSubstring), `Expected "${expectedSubstring}" in response`); } function assertSuccessResponse(result) { assertValidMCPResponse(result); assert.equal(result.isError, false, 'Should not be an error response'); assert.equal(result.content[0].type, 'text'); } function assertErrorResponse(result, expectedErrorSubstring) { assertValidMCPResponse(result); assert.equal(result.isError, true, 'Should be an error response'); if (expectedErrorSubstring) { assertTextContent(result, expectedErrorSubstring); } } async function discoverTestFile() { // Try to discover one working file using the job log tool try { const result = await client.callTool('get_latest_job_log_files', {}); if (!result.isError) { const text = parseResponseText(result.content[0].text); const match = text.match(/File:\s+(.+\.log)/); if (match) { return `jobs/ImportCatalog/${match[1]}`; } } } catch { // Ignore discovery errors } // Fallback to expected file return 'jobs/ImportCatalog/Job-ImportCatalog-0987654321.log'; } // === Core Functionality Tests === describe('Core Functionality', () => { test('should read log file with complete metadata', async () => { const result = await client.callTool('get_log_file_contents', { filename: testFile }); assertSuccessResponse(result); assertTextContent(result, 'Log File Contents:'); assertTextContent(result, testFile); assertTextContent(result, 'Total lines:'); assertTextContent(result, 'Content size:'); // Validate SFCC timestamp pattern const content = parseResponseText(result.content[0].text); const timestampPattern = /\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} GMT\]/; assert.ok(timestampPattern.test(content), 'Should contain SFCC timestamps'); }); test('should handle maxBytes parameter with content validation', async () => { const result = await client.callTool('get_log_file_contents', { filename: testFile, maxBytes: 500 }); assertSuccessResponse(result); assertTextContent(result, 'Content size: 500 bytes'); // Should still include essential metadata despite size limit assertTextContent(result, 'Log File Contents:'); assertTextContent(result, 'Total lines:'); }); test('should handle tailOnly parameter correctly', async () => { const fullResult = await client.callTool('get_log_file_contents', { filename: testFile, maxBytes: 1000 }); const tailResult = await client.callTool('get_log_file_contents', { filename: testFile, maxBytes: 1000, tailOnly: true }); assertSuccessResponse(fullResult); assertSuccessResponse(tailResult); assertTextContent(tailResult, 'tail read'); assertTextContent(tailResult, 'Content size: 1000 bytes'); }); }); // === Dynamic Validation Tests === describe('Dynamic Validation', () => { test('should validate content structure consistency', async () => { const testCases = [ { maxBytes: 200 }, { maxBytes: 1000 }, { tailOnly: true, maxBytes: 500 }, { tailOnly: false } ]; for (const params of testCases) { const result = await client.callTool('get_log_file_contents', { filename: testFile, ...params }); assertSuccessResponse(result); // All responses should have consistent structure assert.equal(result.content.length, 1, 'Should have one content element'); const content = parseResponseText(result.content[0].text); assert.ok(content.includes('Log File Contents:'), 'Should have header'); assert.ok(content.includes('Total lines:'), 'Should have line count'); } }); test('should handle parameter edge cases with validation', async () => { const edgeCases = [ { name: 'minimal bytes', params: { maxBytes: 1 } }, { name: 'large bytes', params: { maxBytes: 50000 } }, { name: 'tail with small bytes', params: { tailOnly: true, maxBytes: 10 } } ]; for (const testCase of edgeCases) { const result = await client.callTool('get_log_file_contents', { filename: testFile, ...testCase.params }); assertSuccessResponse(result); const content = parseResponseText(result.content[0].text); // Even with edge cases, should maintain structure assert.ok(content.includes('Log File Contents:'), `${testCase.name} should maintain header structure`); } }); }); // === Error Handling Tests === describe('Error Handling', () => { test('should handle invalid parameters gracefully', async () => { const errorCases = [ { args: {}, expectedError: 'filename' }, { args: { filename: '' }, expectedError: 'filename' }, { args: { filename: testFile, maxBytes: 0 }, expectedError: 'Invalid maxBytes' }, { args: { filename: testFile, maxBytes: -1 }, expectedError: 'Invalid maxBytes' } ]; for (const errorCase of errorCases) { const result = await client.callTool('get_log_file_contents', errorCase.args); assertErrorResponse(result, errorCase.expectedError); } }); test('should handle security-related filename patterns', async () => { const securityTests = [ '../../../etc/passwd', '/etc/passwd', 'file\x00.log', 'file|rm -rf /.log' ]; for (const filename of securityTests) { const result = await client.callTool('get_log_file_contents', { filename }); assertValidMCPResponse(result); // Should not return sensitive system content if (!result.isError) { const content = parseResponseText(result.content[0].text); assert.ok(!content.includes('root:x:0:0'), 'Should not return system password file content'); } } }); }); // === Multi-Step Integration Tests === describe('Integration Workflows', () => { test('should integrate with file discovery tools', async () => { // Step 1: Discover available files const listResult = await client.callTool('get_latest_job_log_files', {}); if (!listResult.isError) { const listText = parseResponseText(listResult.content[0].text); // Step 2: Extract a file path from the list const fileMatch = listText.match(/File:\s+(.+\.log)/); if (fileMatch) { const discoveredFile = `jobs/ImportCatalog/${fileMatch[1]}`; // Step 3: Read the discovered file const contentResult = await client.callTool('get_log_file_contents', { filename: discoveredFile }); assertSuccessResponse(contentResult); assertTextContent(contentResult, discoveredFile); } } }); test('should support progressive content analysis workflow', async () => { // Step 1: Get a sample of log content const sampleResult = await client.callTool('get_log_file_contents', { filename: testFile, maxBytes: 1000 }); assertSuccessResponse(sampleResult); const sampleContent = parseResponseText(sampleResult.content[0].text); // Step 2: Based on sample, get full content if needed if (sampleContent.includes('INFO')) { const fullResult = await client.callTool('get_log_file_contents', { filename: testFile, maxBytes: 10000 }); assertSuccessResponse(fullResult); const fullContent = parseResponseText(fullResult.content[0].text); // Step 3: Validate that full content contains sample content structure assert.ok(fullContent.includes('Log File Contents:'), 'Full content should have header'); assert.ok(fullContent.length >= sampleContent.length, 'Full content should be larger'); } }); }); // === Business Logic Validation === describe('Business Logic Validation', () => { test('should validate log entry format and content', async () => { const result = await client.callTool('get_log_file_contents', { filename: testFile, maxBytes: 2000 }); assertSuccessResponse(result); const content = parseResponseText(result.content[0].text); // Validate SFCC-specific log structure const logEntryPattern = /\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} GMT)\]\s+(INFO|WARN|ERROR|DEBUG)\s+(\w+)/; const matches = content.match(logEntryPattern); if (matches) { // Validate timestamp is recent - Fix timestamp parsing for SFCC format // Convert "2025-09-22 12:00:00.000 GMT" to "2025-09-22T12:00:00.000Z" const isoTimestamp = matches[1].replace(' ', 'T').replace(' GMT', 'Z'); const logDate = new Date(isoTimestamp); const now = new Date(); const daysDiff = (now - logDate) / (1000 * 60 * 60 * 24); // Allow reasonable timeframe for test log data (within 1 day of current time) assert.ok(Math.abs(daysDiff) < 1, 'Log timestamp should be within reasonable timeframe (±1 day)'); // Validate log level assert.ok(['INFO', 'WARN', 'ERROR', 'DEBUG'].includes(matches[2]), 'Should have valid log level'); // Validate thread/component information assert.ok(matches[3].length > 0, 'Should have thread/component information'); } }); test('should validate content size reporting accuracy', async () => { const testSizes = [100, 500, 1000]; for (const size of testSizes) { const result = await client.callTool('get_log_file_contents', { filename: testFile, maxBytes: size }); assertSuccessResponse(result); assertTextContent(result, `Content size: ${size} bytes`); // Validate that actual content respects the size limit const content = parseResponseText(result.content[0].text); const actualContentMatch = content.match(/---\n\n([\s\S]*)$/); if (actualContentMatch) { const actualLogContent = actualContentMatch[1]; // Should be approximately the requested size (allowing for encoding differences) assert.ok(actualLogContent.length <= size + 50, `Content should respect size limit: ${actualLogContent.length} <= ${size + 50}`); } } }); }); // === Reliability and State Management === describe('Reliability Testing', () => { test('should maintain state consistency across requests', async () => { const params = { filename: testFile, maxBytes: 1000 }; const results = []; // Make multiple identical requests for (let i = 0; i < 3; i++) { const result = await client.callTool('get_log_file_contents', params); results.push(result); assertSuccessResponse(result); } // All results should be identical (no state leakage) const firstContent = parseResponseText(results[0].content[0].text); for (let i = 1; i < results.length; i++) { const content = parseResponseText(results[i].content[0].text); assert.equal(content, firstContent, `Request ${i} should match first request`); } }); test('should handle alternating parameter patterns', async () => { const patterns = [ { maxBytes: 500 }, { tailOnly: true, maxBytes: 300 }, { maxBytes: 1000 }, { tailOnly: false } ]; for (let i = 0; i < patterns.length; i++) { const result = await client.callTool('get_log_file_contents', { filename: testFile, ...patterns[i] }); assertSuccessResponse(result); // Each request should succeed independently const content = parseResponseText(result.content[0].text); assert.ok(content.includes('Log File Contents:'), `Pattern ${i} should maintain proper structure`); } }); }); }); ``` -------------------------------------------------------------------------------- /docs/dw_util/SecureFilter.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.util # Class SecureFilter ## Inheritance Hierarchy - Object - dw.util.SecureFilter ## Description SecureFilter contains many methods for manipulating untrusted data Strings into RFC-Compliant Strings for a given context by removing "bad" data from the untrusted data. ## Constructor Summary ## Method Summary ### forHtmlContent **Signature:** `static forHtmlContent(input : String) : String` Filters illegal characters from a given input for use in a general HTML context. ### forHtmlInDoubleQuoteAttribute **Signature:** `static forHtmlInDoubleQuoteAttribute(input : String) : String` Filters illegal characters from a given input for use in an HTML Attribute guarded by a double quote. ### forHtmlInSingleQuoteAttribute **Signature:** `static forHtmlInSingleQuoteAttribute(input : String) : String` Filters illegal characters from a given input for use in an HTML Attribute guarded by a single quote. ### forHtmlUnquotedAttribute **Signature:** `static forHtmlUnquotedAttribute(input : String) : String` Filters illegal characters from a given input for use in an HTML Attribute left unguarded. ### forJavaScriptInAttribute **Signature:** `static forJavaScriptInAttribute(input : String) : String` Filters illegal characters from a given input for use in JavaScript inside an HTML attribute. ### forJavaScriptInBlock **Signature:** `static forJavaScriptInBlock(input : String) : String` Filters illegal characters from a given input for use in JavaScript inside an HTML block. ### forJavaScriptInHTML **Signature:** `static forJavaScriptInHTML(input : String) : String` Filters illegal characters from a given input for use in JavaScript inside an HTML context. ### forJavaScriptInSource **Signature:** `static forJavaScriptInSource(input : String) : String` Filters illegal characters from a given input for use in JavaScript inside a JavaScript source file. ### forJSONValue **Signature:** `static forJSONValue(input : String) : String` Filters illegal characters from a given input for use in a JSON Object Value to prevent escaping into a trusted context. ### forUriComponent **Signature:** `static forUriComponent(input : String) : String` Filters illegal characters from a given input for use as a component of a URI. ### forUriComponentStrict **Signature:** `static forUriComponentStrict(input : String) : String` Filters illegal characters from a given input for use as a component of a URI. ### forXmlCommentContent **Signature:** `static forXmlCommentContent(input : String) : String` Filters illegal characters from a given input for use in an XML comments. ### forXmlContent **Signature:** `static forXmlContent(input : String) : String` Filters illegal characters from a given input for use in a general XML context. ### forXmlInDoubleQuoteAttribute **Signature:** `static forXmlInDoubleQuoteAttribute(input : String) : String` Filters illegal characters from a given input for use in an XML attribute guarded by a double quote. ### forXmlInSingleQuoteAttribute **Signature:** `static forXmlInSingleQuoteAttribute(input : String) : String` Filters illegal characters from a given input for use in an XML attribute guarded by a single quote. ## Method Detail ## Method Details ### forHtmlContent **Signature:** `static forHtmlContent(input : String) : String` **Description:** Filters illegal characters from a given input for use in a general HTML context. E.g. text content and text attributes. This method takes the UNION of allowed characters among all contexts, so may be more imprecise that the more specific contexts. Generally, this method is preferred unless you specifically understand the context in which untrusted data will be output. Example Usage: <div>${SecureFilter.forHtmlContent(unsafeData)}</div> <input value="${SecureFilter.forHtmlContent(unsafeData)}" /> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forHtmlInDoubleQuoteAttribute **Signature:** `static forHtmlInDoubleQuoteAttribute(input : String) : String` **Description:** Filters illegal characters from a given input for use in an HTML Attribute guarded by a double quote. This method is preferred if you understand exactly how the output of this will be used in the HTML document. Example Usage: <div id="${SecureFilter.forHtmlInDoubleQuoteAttribute(unsafeData)}"></div> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forHtmlInSingleQuoteAttribute **Signature:** `static forHtmlInSingleQuoteAttribute(input : String) : String` **Description:** Filters illegal characters from a given input for use in an HTML Attribute guarded by a single quote. This method is preferred if you understand exactly how the output of this will be used in the HTML document. Example Usage: <div id='${SecureFilter.forHtmlInSingleQuoteAttribute(unsafeData)}'></div> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filterd, if necessary **Returns:** a properly filtered string for the given input --- ### forHtmlUnquotedAttribute **Signature:** `static forHtmlUnquotedAttribute(input : String) : String` **Description:** Filters illegal characters from a given input for use in an HTML Attribute left unguarded. This method is preferred if you understand exactly how the output of this will be used in the HTML document. Example Usage: <div id=${SecureFilter.forHtmlUnquotedAttribute(unsafeData)}></div> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forJavaScriptInAttribute **Signature:** `static forJavaScriptInAttribute(input : String) : String` **Description:** Filters illegal characters from a given input for use in JavaScript inside an HTML attribute. This method is preferred if you understand exactly how the output of the will be used in the page Example Usage: <button onclick="alert('${SecureFilter.forJavaScriptInAttribute(unsafeData)}');"> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forJavaScriptInBlock **Signature:** `static forJavaScriptInBlock(input : String) : String` **Description:** Filters illegal characters from a given input for use in JavaScript inside an HTML block. This method is preferred if you understand exactly how the output of the will be used in the page Example Usage: <script type="text/javascript"> var data = "${SecureFilter.forJavaScriptInBlock(unsafeData)}"; </script> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forJavaScriptInHTML **Signature:** `static forJavaScriptInHTML(input : String) : String` **Description:** Filters illegal characters from a given input for use in JavaScript inside an HTML context. This method takes the UNION of allowed characters among the other contexts, so may be more imprecise that the more specific contexts. Generally, this method is preferred unless you specifically understand the context in which untrusted data will be output. Example Usage: <script type="text/javascript"> var data = "${SecureFilter.forJavaScriptInHTML(unsafeData)}"; </script> <button onclick="alert('${SecureFilter.forJavaScriptInHTML(unsafeData)}');"> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forJavaScriptInSource **Signature:** `static forJavaScriptInSource(input : String) : String` **Description:** Filters illegal characters from a given input for use in JavaScript inside a JavaScript source file. This method is preferred if you understand exactly how the output of the will be used in the page Example Usage: <...inside foobar.js...> var data = "${SecureFilter.forJavaScriptInSource(unsafeData)}"; Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forJSONValue **Signature:** `static forJSONValue(input : String) : String` **Description:** Filters illegal characters from a given input for use in a JSON Object Value to prevent escaping into a trusted context. Example Usage: var json = {"trusted_data" : SecureFilter.forJSONValue(unsafeData)}; return JSON.stringify(json); Flow: Allow AlphaNumerics Remove all other characters **Parameters:** - `input`: ed input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forUriComponent **Signature:** `static forUriComponent(input : String) : String` **Description:** Filters illegal characters from a given input for use as a component of a URI. This is equivalent to javascript's filterURIComponent and does a realistic job of encoding. Example Usage: <a href="http://host.com?value=${SecureFilter.forUriComponent(unsafeData)}"/> Allows: A-Z, a-z, 0-9, -, _, ., ~, !, *, ', (, ) Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forUriComponentStrict **Signature:** `static forUriComponentStrict(input : String) : String` **Description:** Filters illegal characters from a given input for use as a component of a URI. This is a strict filter and fully complies with RFC3986. Example Usage: <a href="http://host.com?value=${SecureFilter.forUriComponentStrict(unsafeData)}"/> Allows: A-Z, a-z, 0-9, -, _, ., ~ Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forXmlCommentContent **Signature:** `static forXmlCommentContent(input : String) : String` **Description:** Filters illegal characters from a given input for use in an XML comments. This method is preferred if you understand the context in which untrusted data will be output. Note: It is recommended that you use a real parser, as this method can be misused, but is left here if a parser is unavailable to you Example Usage: <!-- ${SecureFilter.forXmlCommentContent(unsafeData)} --> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forXmlContent **Signature:** `static forXmlContent(input : String) : String` **Description:** Filters illegal characters from a given input for use in a general XML context. E.g. text content and text attributes. This method takes the UNION of allowed characters between the other contexts, so may be more imprecise that the more specific contexts. Generally, this method is preferred unless you specifically understand the context in which untrusted data will be output. Note: It is recommended that you use a real parser, as this method can be misused, but is left here if a parser is unavailable to you Example Usage: <foo>${SecureFilter.forXmlContent(unsafeData)}</foo> <bar attr="${SecureFilter.forXmlContent(unsafeData)}"></bar> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forXmlInDoubleQuoteAttribute **Signature:** `static forXmlInDoubleQuoteAttribute(input : String) : String` **Description:** Filters illegal characters from a given input for use in an XML attribute guarded by a double quote. This method is preferred if you understand the context in which untrusted data will be output. Note: It is recommended that you use a real parser, as this method can be misused, but is left here if a parser is unavailable to you Example Usage: <bar attr="${SecureFilter.forXmlInDoubleQuoteAttribute(unsafeData)}"></bar> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ### forXmlInSingleQuoteAttribute **Signature:** `static forXmlInSingleQuoteAttribute(input : String) : String` **Description:** Filters illegal characters from a given input for use in an XML attribute guarded by a single quote. This method is preferred if you understand the context in which untrusted data will be output. Note: It is recommended that you use a real parser, as this method can be misused, but is left here if a parser is unavailable to you Example Usage: <bar attr='${SecureFilter.forXmlInSingleQuoteAttribute(unsafeData)}'></bar> Flow: Allow AlphaNumerics and some Special characters Remove all other characters **Parameters:** - `input`: untrusted input to be filtered, if necessary **Returns:** a properly filtered string for the given input --- ```