This is page 10 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 -------------------------------------------------------------------------------- /src/core/server.ts: -------------------------------------------------------------------------------- ```typescript /** * MCP Server for SFCC Development * * This module implements the Model Context Protocol (MCP) server for accessing * Salesforce B2C Commerce Cloud development features. It provides a standardized interface * for AI assistants to interact with SFCC development tools and data. */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { SFCCConfig } from '../types/types.js'; import { Logger } from '../utils/logger.js'; import { ConfigurationFactory } from '../config/configuration-factory.js'; import { SFCC_DOCUMENTATION_TOOLS, BEST_PRACTICES_TOOLS, SFRA_DOCUMENTATION_TOOLS, LOG_TOOLS, JOB_LOG_TOOLS, SYSTEM_OBJECT_TOOLS, CARTRIDGE_GENERATION_TOOLS, CODE_VERSION_TOOLS, } from './tool-definitions.js'; // Modular tool handlers import { BaseToolHandler, HandlerContext } from './handlers/base-handler.js'; import { LogToolHandler } from './handlers/log-handler.js'; import { JobLogToolHandler } from './handlers/job-log-handler.js'; import { DocsToolHandler } from './handlers/docs-handler.js'; import { BestPracticesToolHandler } from './handlers/best-practices-handler.js'; import { SFRAToolHandler } from './handlers/sfra-handler.js'; import { SystemObjectToolHandler } from './handlers/system-object-handler.js'; import { CodeVersionToolHandler } from './handlers/code-version-handler.js'; import { CartridgeToolHandler } from './handlers/cartridge-handler.js'; /** * MCP Server implementation for SFCC development assistance * * This class sets up the MCP server, defines available tools, and handles * requests from MCP clients (like AI assistants) to interact with SFCC development features. */ export class SFCCDevServer { private server!: Server; private logger: Logger; private config: SFCCConfig; private capabilities: ReturnType<typeof ConfigurationFactory.getCapabilities>; private handlers: BaseToolHandler[] = []; /** * Initialize the SFCC Development MCP Server * * @param config - SFCC configuration for connecting to the logging system */ constructor(config: SFCCConfig) { this.logger = Logger.getChildLogger('Server'); this.config = config; this.logMethodEntry('constructor', { hostname: config.hostname }); this.capabilities = ConfigurationFactory.getCapabilities(config); this.initializeServer(); this.registerHandlers(); this.setupToolHandlers(); this.logMethodExit('constructor'); } private initializeServer(): void { this.server = new Server( { name: 'SFCC Development MCP Server', version: '1.0.14', // synced with package.json }, { capabilities: { tools: {}, }, }, ); } private logMethodEntry(methodName: string, params?: any): void { this.logger.methodEntry(methodName, params); } private logMethodExit(methodName: string, result?: any): void { this.logger.methodExit(methodName, result); } // Register modular handlers (each encapsulates its own responsibility) private registerHandlers(): void { const context: HandlerContext = { logger: this.logger, config: this.config, capabilities: this.capabilities, }; this.handlers = [ new LogToolHandler(context, 'Log'), new JobLogToolHandler(context, 'JobLog'), new DocsToolHandler(context, 'Docs'), new BestPracticesToolHandler(context, 'BestPractices'), new SFRAToolHandler(context, 'SFRA'), new SystemObjectToolHandler(context, 'SystemObjects'), new CodeVersionToolHandler(context, 'CodeVersions'), new CartridgeToolHandler(context, 'Cartridge'), ]; } /** * Set up MCP tool handlers for SFCC operations */ private setupToolHandlers(): void { this.server.setRequestHandler(ListToolsRequestSchema, async () => { const tools = []; // Always available tools tools.push(...SFCC_DOCUMENTATION_TOOLS); tools.push(...BEST_PRACTICES_TOOLS); tools.push(...SFRA_DOCUMENTATION_TOOLS); tools.push(...CARTRIDGE_GENERATION_TOOLS); // Conditional tools based on available capabilities if (this.capabilities.canAccessLogs) { tools.push(...LOG_TOOLS); tools.push(...JOB_LOG_TOOLS); } if (this.capabilities.canAccessOCAPI) { tools.push(...SYSTEM_OBJECT_TOOLS); tools.push(...CODE_VERSION_TOOLS); } return { tools }; }); this.server.setRequestHandler(CallToolRequestSchema, async (request): Promise<any> => { const { name, arguments: args } = request.params; const startTime = Date.now(); this.logger.methodEntry(`handleToolRequest:${name}`, args); try { const handler = this.handlers.find((h) => h.canHandle(name)); if (!handler) { this.logger.error(`Unknown tool requested: ${name}`); throw new Error(`Unknown tool: ${name}`); } const result = await handler.handle(name, args ?? {}, startTime); // Log the full response in debug mode this.logger.debug(`Full response for ${name}:`, { contentType: result.content?.[0]?.type, contentLength: result.content?.[0]?.text?.length ?? 0, responsePreview: result.content?.[0]?.text?.substring(0, 200) + (result.content?.[0]?.text?.length > 200 ? '...' : ''), fullResponse: result.content?.[0]?.text, }); return result as any; } catch (error) { this.logger.error(`Error handling tool "${name}":`, error); this.logger.timing(`${name}_error`, startTime); const errorResult = { content: [ { type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; // Log error response in debug mode this.logger.debug(`Error response for ${name}:`, errorResult); return errorResult as any; } finally { this.logger.methodExit(`handleToolRequest:${name}`); } }); } /** * Start the MCP server */ async run(): Promise<void> { const transport = new StdioServerTransport(); // Set up graceful shutdown process.on('SIGINT', () => this.shutdown()); process.on('SIGTERM', () => this.shutdown()); await this.server.connect(transport); this.logger.log('SFCC Development MCP server running on stdio'); } /** * Gracefully shutdown the server and dispose of resources */ private async shutdown(): Promise<void> { this.logger.log('Shutting down SFCC Development MCP server...'); // Dispose of all handlers await Promise.all(this.handlers.map(handler => handler.dispose())); this.logger.log('SFCC Development MCP server shutdown complete'); process.exit(0); } } ``` -------------------------------------------------------------------------------- /tests/servers/sfcc-mock-server/src/routes/ocapi/ocapi-error-utils.js: -------------------------------------------------------------------------------- ```javascript /** * OCAPI Error Utilities * * Utilities for generating SFCC-compliant error responses that match * the real OCAPI Data API error format and behavior. */ class OCAPIErrorUtils { /** * Create a standard SFCC fault response */ static createFaultResponse(type, message, args = {}, statusCode = 400, version = "23.2") { return { response: { "_v": version, "fault": { "arguments": args, "type": type, "message": message } }, statusCode: statusCode }; } /** * Create ObjectTypeNotFoundException (404) */ static createObjectTypeNotFound(objectType) { return this.createFaultResponse( "ObjectTypeNotFoundException", `No object type with ID '${objectType}' could be found.`, { objectType }, 404 ); } /** * Create PropertyConstraintViolationException (400) */ static createPropertyConstraintViolation(path, document = "search_request") { return this.createFaultResponse( "PropertyConstraintViolationException", `An error occurred while decoding the request. There's a value constraint violation of property '${path}' in document '${document}'.`, { path, document }, 400 ); } /** * Create EnumConstraintViolationException (400) */ static createEnumConstraintViolation(enumValue, document = "search_request") { return this.createFaultResponse( "EnumConstraintViolationException", `An error occurred while decoding the request. There's an unknown enum value '${enumValue}' in document '${document}'.`, { document, enumValue }, 400 ); } /** * Create InvalidRequestException (400) */ static createInvalidRequest(message, field = null) { const args = field ? { field } : {}; return this.createFaultResponse( "InvalidRequestException", message, args, 400 ); } /** * Create AuthenticationFailedException (401) */ static createAuthenticationFailed() { return this.createFaultResponse( "AuthenticationFailedException", "Authentication failed. Please check your credentials.", {}, 401 ); } /** * Create InsufficientPermissionsException (403) */ static createInsufficientPermissions(permission = "access") { return this.createFaultResponse( "InsufficientPermissionsException", `You are not allowed to ${permission} the requested resource.`, { permission }, 403 ); } /** * Create InternalServerException (500) */ static createInternalServerError(details = "An unexpected error occurred.") { return this.createFaultResponse( "InternalServerException", details, {}, 500 ); } /** * Validate object type against known system objects */ static validateObjectType(objectType) { const validObjectTypes = [ 'Product', 'Customer', 'Order', 'Category', 'Site', 'SitePreferences', 'CustomerGroup', 'CustomerAddress', 'Profile', 'Basket', 'OrderPaymentInstrument', 'ProductOption', 'ProductVariationAttribute', 'PriceBook', 'Campaign', 'Promotion', 'Content', 'ContentSlot', 'Folder', 'Library' ]; if (!validObjectTypes.includes(objectType)) { return this.createObjectTypeNotFound(objectType); } return null; } /** * Validate search request structure */ static validateSearchRequest(searchRequest) { // Check if searchRequest exists if (!searchRequest || typeof searchRequest !== 'object') { return this.createPropertyConstraintViolation("$", "search_request"); } // Check if query exists if (!searchRequest.query) { return this.createPropertyConstraintViolation("$.query", "search_request"); } // Validate query type const validQueryTypes = ['text_query', 'term_query', 'filtered_query', 'bool_query', 'match_all_query']; const hasValidQuery = validQueryTypes.some(type => searchRequest.query[type]); if (!hasValidQuery) { return this.createInvalidRequest( "Search query must contain at least one of: text_query, term_query, filtered_query, bool_query, match_all_query" ); } return null; } /** * Validate pagination parameters */ static validatePagination(start, count) { // Validate start parameter if (start !== undefined && start !== null) { if (typeof start !== 'number' || start < 0) { return this.createInvalidRequest("start must be a positive number"); } } // Validate count parameter if (count !== undefined && count !== null) { if (typeof count !== 'number' || count < 0) { return this.createPropertyConstraintViolation("$.count", "search_request"); } if (count > 200) { return this.createPropertyConstraintViolation("$.count", "search_request"); } } return null; } /** * Validate text_query structure */ static validateTextQuery(textQuery) { if (!textQuery.fields || !Array.isArray(textQuery.fields) || textQuery.fields.length === 0) { return this.createPropertyConstraintViolation("$.query.text_query.fields", "search_request"); } if (!textQuery.search_phrase || typeof textQuery.search_phrase !== 'string') { return this.createPropertyConstraintViolation("$.query.text_query.search_phrase", "search_request"); } return null; } /** * Validate term_query structure */ static validateTermQuery(termQuery) { if (!termQuery.fields || !Array.isArray(termQuery.fields) || termQuery.fields.length === 0) { return this.createPropertyConstraintViolation("$.query.term_query.fields", "search_request"); } if (!termQuery.operator || typeof termQuery.operator !== 'string') { return this.createPropertyConstraintViolation("$.query.term_query.operator", "search_request"); } if (!termQuery.values || !Array.isArray(termQuery.values)) { return this.createPropertyConstraintViolation("$.query.term_query.values", "search_request"); } return null; } /** * Send error response */ static sendErrorResponse(res, errorInfo) { res.status(errorInfo.statusCode).json(errorInfo.response); } } module.exports = OCAPIErrorUtils; ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/get-log-file-contents.full-mode.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml --- description: "Test get_log_file_contents tool in full mode - optimized for YAML/aegis testing" tests: # === Basic Functionality === - it: "should get log file contents with proper structure" request: jsonrpc: "2.0" id: "get-contents-basic" method: "tools/call" params: name: "get_log_file_contents" arguments: filename: "jobs/ImportCatalog/Job-ImportCatalog-0987654321.log" expect: response: jsonrpc: "2.0" id: "get-contents-basic" result: content: "match:arrayLength:1" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "1500ms" - it: "should include essential metadata in response" request: jsonrpc: "2.0" id: "get-contents-metadata" method: "tools/call" params: name: "get_log_file_contents" arguments: filename: "jobs/ImportCatalog/Job-ImportCatalog-0987654321.log" expect: response: jsonrpc: "2.0" id: "get-contents-metadata" result: content: match:arrayElements: type: "text" text: "match:contains:Log File Contents:" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "1500ms" - it: "should include timestamps in SFCC format" request: jsonrpc: "2.0" id: "get-contents-timestamps" method: "tools/call" params: name: "get_log_file_contents" arguments: filename: "jobs/ImportCatalog/Job-ImportCatalog-0987654321.log" expect: response: jsonrpc: "2.0" id: "get-contents-timestamps" result: content: match:arrayElements: match:partial: text: "match:regex:\\[\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3} GMT\\]" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "1500ms" # === Parameter Validation === - it: "should work with maxBytes parameter" request: jsonrpc: "2.0" id: "get-contents-maxbytes" method: "tools/call" params: name: "get_log_file_contents" arguments: filename: "jobs/ImportCatalog/Job-ImportCatalog-0987654321.log" maxBytes: 500 expect: response: jsonrpc: "2.0" id: "get-contents-maxbytes" result: content: match:arrayElements: type: "text" text: "match:contains:Content size:" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "1000ms" - it: "should work with tailOnly parameter" request: jsonrpc: "2.0" id: "get-contents-tailonly" method: "tools/call" params: name: "get_log_file_contents" arguments: filename: "jobs/ImportCatalog/Job-ImportCatalog-0987654321.log" tailOnly: true maxBytes: 200 expect: response: jsonrpc: "2.0" id: "get-contents-tailonly" result: content: match:arrayElements: match:partial: text: "match:contains:tail read" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "1000ms" # === Error Handling === - it: "should handle non-existent file gracefully" request: jsonrpc: "2.0" id: "get-contents-notfound" method: "tools/call" params: name: "get_log_file_contents" arguments: filename: "nonexistent-file.log" expect: response: jsonrpc: "2.0" id: "get-contents-notfound" result: content: match:arrayElements: match:partial: text: "match:contains:Failed to get_log_file_contents" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "1500ms" - it: "should handle missing filename parameter" request: jsonrpc: "2.0" id: "get-contents-missing-filename" method: "tools/call" params: name: "get_log_file_contents" arguments: {} expect: response: jsonrpc: "2.0" id: "get-contents-missing-filename" result: content: match:arrayElements: match:partial: text: "match:contains:filename must be a non-empty string" isError: true stderr: "toBeEmpty" performance: maxResponseTime: "800ms" - it: "should handle empty filename parameter" request: jsonrpc: "2.0" id: "get-contents-empty-filename" method: "tools/call" params: name: "get_log_file_contents" arguments: filename: "" expect: response: jsonrpc: "2.0" id: "get-contents-empty-filename" result: content: match:arrayElements: match:partial: text: "match:contains:filename must be a non-empty string" isError: true stderr: "toBeEmpty" performance: maxResponseTime: "800ms" - it: "should handle invalid maxBytes parameter" request: jsonrpc: "2.0" id: "get-contents-invalid-maxbytes" method: "tools/call" params: name: "get_log_file_contents" arguments: filename: "jobs/ImportCatalog/Job-ImportCatalog-0987654321.log" maxBytes: 0 expect: response: jsonrpc: "2.0" id: "get-contents-invalid-maxbytes" result: content: match:arrayElements: match:partial: text: "match:contains:Invalid maxBytes" isError: true stderr: "toBeEmpty" performance: maxResponseTime: "800ms" # === Content Structure Validation === - it: "should return exactly one content element" request: jsonrpc: "2.0" id: "get-contents-single-element" method: "tools/call" params: name: "get_log_file_contents" arguments: filename: "jobs/ImportCatalog/Job-ImportCatalog-0987654321.log" expect: response: jsonrpc: "2.0" id: "get-contents-single-element" result: content: "match:arrayLength:1" isError: "match:type:boolean" stderr: "toBeEmpty" performance: maxResponseTime: "1500ms" - it: "should return proper content types" request: jsonrpc: "2.0" id: "get-contents-types" method: "tools/call" params: name: "get_log_file_contents" arguments: filename: "jobs/ImportCatalog/Job-ImportCatalog-0987654321.log" expect: response: jsonrpc: "2.0" id: "get-contents-types" result: content: match:arrayElements: type: "text" text: "match:type:string" isError: "match:type:boolean" stderr: "toBeEmpty" performance: maxResponseTime: "1500ms" ``` -------------------------------------------------------------------------------- /src/clients/docs/documentation-scanner.ts: -------------------------------------------------------------------------------- ```typescript /** * Documentation Scanner * * Responsible for scanning the documentation directory structure and * discovering SFCC class documentation files with security validation. * * Single Responsibility: File system operations and documentation discovery */ import fs from 'fs/promises'; import path from 'path'; import { Logger } from '../../utils/logger.js'; export interface SFCCClassInfo { className: string; packageName: string; filePath: string; content: string; } export class DocumentationScanner { private logger: Logger; constructor() { this.logger = Logger.getChildLogger('DocumentationScanner'); } /** * Check if a directory name represents an SFCC-specific directory * SFCC directories include dw_ prefixed namespaces and TopLevel * Excludes best-practices and sfra directories */ private isSFCCDirectory(directoryName: string): boolean { // Include dw_ prefixed directories (SFCC namespaces) if (directoryName.startsWith('dw_')) { return true; } // Include TopLevel directory (contains core JavaScript classes) if (directoryName === 'TopLevel') { return true; } // Exclude best-practices directory (handled by best practices tools) if (directoryName === 'best-practices') { return false; } // Exclude sfra directory (handled by SFRA tools) if (directoryName === 'sfra') { return false; } // Exclude any other non-SFCC directories return false; } /** * Validate file name for security concerns */ private validateFileName(fileName: string): boolean { // Enhanced security validation - validate file name before path operations if (!fileName || typeof fileName !== 'string') { this.logger.warn(`Warning: Invalid file name type: ${fileName}`); return false; } // Prevent null bytes and dangerous characters in the file name itself if (fileName.includes('\0') || fileName.includes('\x00')) { this.logger.warn(`Warning: File name contains null bytes: ${fileName}`); return false; } // Prevent path traversal sequences in the file name if (fileName.includes('..') || fileName.includes('/') || fileName.includes('\\')) { this.logger.warn(`Warning: File name contains path traversal sequences: ${fileName}`); return false; } // Only allow alphanumeric characters, underscores, hyphens, and dots for file names if (!/^[a-zA-Z0-9_.-]+$/.test(fileName)) { this.logger.warn(`Warning: File name contains invalid characters: ${fileName}`); return false; } return true; } /** * Validate file path for security concerns */ private validateFilePath(filePath: string, packagePath: string, docsPath: string): boolean { // Additional security validation - ensure the resolved path is within the package directory const resolvedPath = path.resolve(filePath); const resolvedPackagePath = path.resolve(packagePath); const resolvedDocsPath = path.resolve(docsPath); // Ensure the file is within the package directory and docs directory if (!resolvedPath.startsWith(resolvedPackagePath) || !resolvedPath.startsWith(resolvedDocsPath)) { this.logger.warn(`Warning: File path outside allowed directory: ${filePath}`); return false; } // Ensure the file still ends with .md after path resolution if (!resolvedPath.toLowerCase().endsWith('.md')) { this.logger.warn(`Warning: File does not reference a markdown file: ${filePath}`); return false; } return true; } /** * Validate file content for security concerns */ private validateFileContent(content: string, fileName: string): boolean { // Basic content validation if (!content.trim()) { this.logger.warn(`Warning: Empty documentation file: ${fileName}`); return false; } // Check for binary content if (content.includes('\0')) { this.logger.warn(`Warning: Binary content detected in: ${fileName}`); return false; } return true; } /** * Read and validate a single documentation file */ private async readDocumentationFile( fileName: string, packagePath: string, packageName: string, docsPath: string, ): Promise<SFCCClassInfo | null> { if (!this.validateFileName(fileName)) { return null; } const className = fileName.replace('.md', ''); const filePath = path.join(packagePath, fileName); if (!this.validateFilePath(filePath, packagePath, docsPath)) { return null; } try { const resolvedPath = path.resolve(filePath); const content = await fs.readFile(resolvedPath, 'utf-8'); if (!this.validateFileContent(content, fileName)) { return null; } return { className, packageName, filePath, content, }; } catch (fileError) { this.logger.warn(`Warning: Could not read file ${fileName}: ${fileError}`); return null; } } /** * Scan a single package directory for documentation files */ private async scanPackageDirectory( packageName: string, packagePath: string, docsPath: string, ): Promise<SFCCClassInfo[]> { const classInfos: SFCCClassInfo[] = []; try { const files = await fs.readdir(packagePath); for (const file of files) { // Validate file name type and basic content before processing if (!file || typeof file !== 'string') { this.logger.warn(`Warning: Invalid file name type: ${file}`); continue; } if (file.endsWith('.md')) { const classInfo = await this.readDocumentationFile(file, packagePath, packageName, docsPath); if (classInfo) { classInfos.push(classInfo); } } } } catch (error) { this.logger.warn(`Warning: Could not read package ${packageName}: ${error}`); } return classInfos; } /** * Scan the docs directory and index all SFCC classes * Only scans SFCC-specific directories, excluding best-practices and sfra */ async scanDocumentation(docsPath: string): Promise<Map<string, SFCCClassInfo>> { const classCache = new Map<string, SFCCClassInfo>(); const packages = await fs.readdir(docsPath, { withFileTypes: true }); for (const packageDir of packages) { if (!packageDir.isDirectory()) { continue; } const packageName = packageDir.name; // Only scan SFCC-specific directories (dw_ prefixed and TopLevel) // Exclude best-practices and sfra directories which are handled by other tools if (!this.isSFCCDirectory(packageName)) { continue; } const packagePath = path.join(docsPath, packageName); const classInfos = await this.scanPackageDirectory(packageName, packagePath, docsPath); // Add to cache with normalized keys for (const classInfo of classInfos) { const cacheKey = `${packageName}.${classInfo.className}`; classCache.set(cacheKey, classInfo); } } return classCache; } } ``` -------------------------------------------------------------------------------- /docs/dw_catalog/SearchRefinements.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.catalog # Class SearchRefinements ## Inheritance Hierarchy - Object - dw.catalog.SearchRefinements ## Description Common search refinements base class. ## Constants ### ASCENDING **Type:** Number = 0 Flag for an ascending sort. ### DESCENDING **Type:** Number = 1 Flag for a descending sort. ### SORT_VALUE_COUNT **Type:** Number = 1 Flag for sorting on value count. ### SORT_VALUE_NAME **Type:** Number = 0 Flag for sorting on value name. ## Properties ### allRefinementDefinitions **Type:** Collection (Read Only) A sorted list of refinement definitions that are appropriate for the deepest common category (or deepest common folder) of the search result. The method concatenates the sorted refinement definitions per category starting at the root category until reaching the deepest common category. The method does not filter out refinement definitions that do not provide values for the current search result and can therefore also be used on empty search results. ### refinementDefinitions **Type:** Collection (Read Only) A sorted list of refinement definitions that are appropriate for the deepest common category (or deepest common folder) of the search result. The method concatenates the sorted refinement definitions per category starting at the root category until reaching the deepest common category. The method also filters out refinement definitions that do not provide any values for the current search result. ## Constructor Summary ## Method Summary ### getAllRefinementDefinitions **Signature:** `getAllRefinementDefinitions() : Collection` Returns a sorted list of refinement definitions that are appropriate for the deepest common category (or deepest common folder) of the search result. ### getAllRefinementValues **Signature:** `getAllRefinementValues(attributeName : String) : Collection` Returns a sorted collection of refinement values for the given refinement attribute. ### getAllRefinementValues **Signature:** `getAllRefinementValues(attributeName : String, sortMode : Number, sortDirection : Number) : Collection` Returns a sorted collection of refinement values for the given refinement attribute. ### getRefinementDefinitions **Signature:** `getRefinementDefinitions() : Collection` Returns a sorted list of refinement definitions that are appropriate for the deepest common category (or deepest common folder) of the search result. ### getRefinementValues **Signature:** `getRefinementValues(attributeName : String, sortMode : Number, sortDirection : Number) : Collection` Returns a collection of refinement values for the given refinement attribute, sorting mode and sorting direction. ## Method Detail ## Method Details ### getAllRefinementDefinitions **Signature:** `getAllRefinementDefinitions() : Collection` **Description:** Returns a sorted list of refinement definitions that are appropriate for the deepest common category (or deepest common folder) of the search result. The method concatenates the sorted refinement definitions per category starting at the root category until reaching the deepest common category. The method does not filter out refinement definitions that do not provide values for the current search result and can therefore also be used on empty search results. **Returns:** A sorted list of refinement definitions appropriate for the search result (based on its deepest common category) --- ### getAllRefinementValues **Signature:** `getAllRefinementValues(attributeName : String) : Collection` **Description:** Returns a sorted collection of refinement values for the given refinement attribute. The returned collection includes all refinement values for which the hit count is greater than 0 within the search result when the passed attribute is excluded from filtering the search hits but all other refinement filters are still applied. This method is useful for rendering broadening options for attributes that the search is currently refined by. This method does NOT return refinement values independent of the search result. For product search refinements, this method may return slightly different results based on the "value set" property of the refinement definition. See ProductSearchRefinements.getAllRefinementValues(ProductSearchRefinementDefinition) for details. **Parameters:** - `attributeName`: The name of the attribute to return refinement values for. **Returns:** The collection of SearchRefinementValue instances, sorted according to the settings of the refinement definition, or null if there is no refinement definition for the passed attribute name. --- ### getAllRefinementValues **Signature:** `getAllRefinementValues(attributeName : String, sortMode : Number, sortDirection : Number) : Collection` **Description:** Returns a sorted collection of refinement values for the given refinement attribute. In general, the returned collection includes all refinement values for which hit count is greater than 0 within the search result assuming that: The passed refinement attribute is NOT used to filter the search hits. All other refinements are still applied. This is useful for rendering broadening options for the refinement definitions that the search is already refined by. It is important to note that this method does NOT return refinement values independent of the search result. For product search refinements, this method may return slightly different results based on the "value set" of the refinement definition. See ProductSearchRefinements.getAllRefinementValues(ProductSearchRefinementDefinition) for details. **Parameters:** - `attributeName`: The name of the attribute to return refinement values for. - `sortMode`: The sort mode to use to control how the collection is sorted. - `sortDirection`: The sort direction to use. **Returns:** The collection of SearchRefinementValue instances, sorted according to the passed parameters. --- ### getRefinementDefinitions **Signature:** `getRefinementDefinitions() : Collection` **Description:** Returns a sorted list of refinement definitions that are appropriate for the deepest common category (or deepest common folder) of the search result. The method concatenates the sorted refinement definitions per category starting at the root category until reaching the deepest common category. The method also filters out refinement definitions that do not provide any values for the current search result. **Returns:** A sorted list of refinement definitions appropriate for the search result (based on its deepest common category) --- ### getRefinementValues **Signature:** `getRefinementValues(attributeName : String, sortMode : Number, sortDirection : Number) : Collection` **Description:** Returns a collection of refinement values for the given refinement attribute, sorting mode and sorting direction. **Parameters:** - `attributeName`: The attribute name to use when collection refinement values. - `sortMode`: The sort mode to use to control how the collection is sorted. - `sortDirection`: The sort direction to use. **Returns:** The collection of refinement values. --- ``` -------------------------------------------------------------------------------- /docs/dw_campaign/Campaign.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.campaign # Class Campaign ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.campaign.Campaign ## Description A Campaign is a set of experiences (or site configurations) which may be deployed as a single unit for a given time frame. The system currently supports 3 types of experience that may be assigned to a campaign: Promotions Slot Configurations Sorting Rules This list may be extended in the future. A campaign can have a start and end date or be open-ended. It may also have "qualifiers" which determine which customers the campaign applies to. The currently supported qualifiers are: Customer groups (where "Everyone" is a possible customer group) Source codes Coupons A campaign can have list of stores or store groups where it can be applicable to. ## Properties ### active **Type:** boolean (Read Only) Returns 'true' if the campaign is currently active, otherwise 'false'. A campaign is active if it is enabled and scheduled for now. ### applicableInStore **Type:** boolean (Read Only) Returns true if campaign is applicable to store, otherwise false. ### applicableOnline **Type:** boolean (Read Only) Returns true if campaign is applicable to online site, otherwise false. ### coupons **Type:** Collection (Read Only) The coupons assigned to the campaign. ### customerGroups **Type:** Collection (Read Only) The customer groups assigned to the campaign. ### description **Type:** String (Read Only) The internal description of the campaign. ### enabled **Type:** boolean (Read Only) Returns true if campaign is enabled, otherwise false. ### endDate **Type:** Date (Read Only) The end date of the campaign. If no end date is defined for the campaign, null is returned. A campaign w/o end date will run forever. ### ID **Type:** String (Read Only) The unique campaign ID. ### promotions **Type:** Collection (Read Only) Returns promotions defined in this campaign in no particular order. ### sourceCodeGroups **Type:** Collection (Read Only) The source codes assigned to the campaign. ### startDate **Type:** Date (Read Only) The start date of the campaign. If no start date is defined for the campaign, null is returned. A campaign w/o start date is immediately effective. ### storeGroups **Type:** Collection (Read Only) Returns store groups assigned to the campaign. ### stores **Type:** Collection (Read Only) Returns stores assigned to the campaign. ## Constructor Summary ## Method Summary ### getCoupons **Signature:** `getCoupons() : Collection` Returns the coupons assigned to the campaign. ### getCustomerGroups **Signature:** `getCustomerGroups() : Collection` Returns the customer groups assigned to the campaign. ### getDescription **Signature:** `getDescription() : String` Returns the internal description of the campaign. ### getEndDate **Signature:** `getEndDate() : Date` Returns the end date of the campaign. ### getID **Signature:** `getID() : String` Returns the unique campaign ID. ### getPromotions **Signature:** `getPromotions() : Collection` Returns promotions defined in this campaign in no particular order. ### getSourceCodeGroups **Signature:** `getSourceCodeGroups() : Collection` Returns the source codes assigned to the campaign. ### getStartDate **Signature:** `getStartDate() : Date` Returns the start date of the campaign. ### getStoreGroups **Signature:** `getStoreGroups() : Collection` Returns store groups assigned to the campaign. ### getStores **Signature:** `getStores() : Collection` Returns stores assigned to the campaign. ### isActive **Signature:** `isActive() : boolean` Returns 'true' if the campaign is currently active, otherwise 'false'. ### isApplicableInStore **Signature:** `isApplicableInStore() : boolean` Returns true if campaign is applicable to store, otherwise false. ### isApplicableOnline **Signature:** `isApplicableOnline() : boolean` Returns true if campaign is applicable to online site, otherwise false. ### isEnabled **Signature:** `isEnabled() : boolean` Returns true if campaign is enabled, otherwise false. ## Method Detail ## Method Details ### getCoupons **Signature:** `getCoupons() : Collection` **Description:** Returns the coupons assigned to the campaign. **Returns:** All coupons assigned to the campaign. --- ### getCustomerGroups **Signature:** `getCustomerGroups() : Collection` **Description:** Returns the customer groups assigned to the campaign. **Returns:** Customer groups assigned to campaign. --- ### getDescription **Signature:** `getDescription() : String` **Description:** Returns the internal description of the campaign. **Returns:** Internal description of campaign. --- ### getEndDate **Signature:** `getEndDate() : Date` **Description:** Returns the end date of the campaign. If no end date is defined for the campaign, null is returned. A campaign w/o end date will run forever. **Returns:** End date of campaign. --- ### getID **Signature:** `getID() : String` **Description:** Returns the unique campaign ID. **Returns:** ID of the campaign. --- ### getPromotions **Signature:** `getPromotions() : Collection` **Description:** Returns promotions defined in this campaign in no particular order. **Returns:** All promotions defined in campaign. --- ### getSourceCodeGroups **Signature:** `getSourceCodeGroups() : Collection` **Description:** Returns the source codes assigned to the campaign. **Returns:** All source code groups assigned to campaign. --- ### getStartDate **Signature:** `getStartDate() : Date` **Description:** Returns the start date of the campaign. If no start date is defined for the campaign, null is returned. A campaign w/o start date is immediately effective. **Returns:** Start date of campaign. --- ### getStoreGroups **Signature:** `getStoreGroups() : Collection` **Description:** Returns store groups assigned to the campaign. **Returns:** All store groups assigned to the campaign. --- ### getStores **Signature:** `getStores() : Collection` **Description:** Returns stores assigned to the campaign. **Returns:** All stores assigned to the campaign. --- ### isActive **Signature:** `isActive() : boolean` **Description:** Returns 'true' if the campaign is currently active, otherwise 'false'. A campaign is active if it is enabled and scheduled for now. **Returns:** true of campaign is active, otherwise false. --- ### isApplicableInStore **Signature:** `isApplicableInStore() : boolean` **Description:** Returns true if campaign is applicable to store, otherwise false. **Returns:** true if campaign is applicable to store, otherwise false. --- ### isApplicableOnline **Signature:** `isApplicableOnline() : boolean` **Description:** Returns true if campaign is applicable to online site, otherwise false. **Returns:** true if campaign is applicable to online site, otherwise false. --- ### isEnabled **Signature:** `isEnabled() : boolean` **Description:** Returns true if campaign is enabled, otherwise false. **Returns:** true if campaign is enabled, otherwise false. --- ``` -------------------------------------------------------------------------------- /docs/dw_order/ProductShippingLineItem.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order # Class ProductShippingLineItem ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.order.LineItem - dw.order.ProductShippingLineItem ## Description Represents a specific line item in a shipment. A ProductShippingLineItem defines lineitem-specific shipping costs. ## Constants ### PRODUCT_SHIPPING_ID **Type:** String = "PRODUCT_SHIPPING" Reserved constant. ## Properties ### adjustedGrossPrice **Type:** Money (Read Only) The gross price of the product shipping line item after applying all product-shipping-level adjustments. ### adjustedNetPrice **Type:** Money (Read Only) The net price of the product shipping line item after applying all product-shipping-level adjustments. ### adjustedPrice **Type:** Money (Read Only) The price of the product shipping line item after applying all pproduct-shipping-level adjustments. For net pricing the adjusted net price is returned (see getAdjustedNetPrice()). For gross pricing, the adjusted gross price is returned (see getAdjustedGrossPrice()). ### adjustedTax **Type:** Money (Read Only) The tax of the unit after applying adjustments, in the purchase currency. ### priceAdjustments **Type:** Collection (Read Only) An iterator of price adjustments that have been applied to this product shipping line item. ### productLineItem **Type:** ProductLineItem (Read Only) The parent product line item this shipping line item belongs to. ### quantity **Type:** Quantity The quantity of the shipping cost. ### shipment **Type:** Shipment (Read Only) The shipment this shipping line item belongs to. ### surcharge **Type:** boolean The 'surcharge' flag. ## Constructor Summary ## Method Summary ### getAdjustedGrossPrice **Signature:** `getAdjustedGrossPrice() : Money` Returns the gross price of the product shipping line item after applying all product-shipping-level adjustments. ### getAdjustedNetPrice **Signature:** `getAdjustedNetPrice() : Money` Returns the net price of the product shipping line item after applying all product-shipping-level adjustments. ### getAdjustedPrice **Signature:** `getAdjustedPrice() : Money` Returns the price of the product shipping line item after applying all pproduct-shipping-level adjustments. ### getAdjustedTax **Signature:** `getAdjustedTax() : Money` Returns the tax of the unit after applying adjustments, in the purchase currency. ### getPriceAdjustments **Signature:** `getPriceAdjustments() : Collection` Returns an iterator of price adjustments that have been applied to this product shipping line item. ### getProductLineItem **Signature:** `getProductLineItem() : ProductLineItem` Returns the parent product line item this shipping line item belongs to. ### getQuantity **Signature:** `getQuantity() : Quantity` Returns the quantity of the shipping cost. ### getShipment **Signature:** `getShipment() : Shipment` Returns the shipment this shipping line item belongs to. ### isSurcharge **Signature:** `isSurcharge() : boolean` Returns the 'surcharge' flag. ### setPriceValue **Signature:** `setPriceValue(value : Number) : void` Sets price attributes of the line item based on the purchase currency, taxation policy and line item quantity. The method sets the 'basePrice' attribute of the line item. ### setQuantity **Signature:** `setQuantity(quantity : Quantity) : void` Sets the quantity of the shipping cost. ### setSurcharge **Signature:** `setSurcharge(flag : boolean) : void` Sets the 'surcharge' flag. ## Method Detail ## Method Details ### getAdjustedGrossPrice **Signature:** `getAdjustedGrossPrice() : Money` **Description:** Returns the gross price of the product shipping line item after applying all product-shipping-level adjustments. **Returns:** gross price after applying product-shipping-level adjustments **See Also:** getAdjustedNetPrice() getAdjustedPrice() --- ### getAdjustedNetPrice **Signature:** `getAdjustedNetPrice() : Money` **Description:** Returns the net price of the product shipping line item after applying all product-shipping-level adjustments. **Returns:** net price after applying product-shipping-level adjustments **See Also:** getAdjustedGrossPrice() getAdjustedPrice() --- ### getAdjustedPrice **Signature:** `getAdjustedPrice() : Money` **Description:** Returns the price of the product shipping line item after applying all pproduct-shipping-level adjustments. For net pricing the adjusted net price is returned (see getAdjustedNetPrice()). For gross pricing, the adjusted gross price is returned (see getAdjustedGrossPrice()). **Returns:** Adjusted net or gross price **See Also:** getAdjustedGrossPrice() getAdjustedNetPrice() --- ### getAdjustedTax **Signature:** `getAdjustedTax() : Money` **Description:** Returns the tax of the unit after applying adjustments, in the purchase currency. **Returns:** the tax of the unit after applying adjustments, in the purchase currency. --- ### getPriceAdjustments **Signature:** `getPriceAdjustments() : Collection` **Description:** Returns an iterator of price adjustments that have been applied to this product shipping line item. **Returns:** a collection of price adjustments that have been applied to this product shipping line item. --- ### getProductLineItem **Signature:** `getProductLineItem() : ProductLineItem` **Description:** Returns the parent product line item this shipping line item belongs to. **Returns:** the product line item --- ### getQuantity **Signature:** `getQuantity() : Quantity` **Description:** Returns the quantity of the shipping cost. **Returns:** the shipping quantity --- ### getShipment **Signature:** `getShipment() : Shipment` **Description:** Returns the shipment this shipping line item belongs to. **Returns:** the shipment --- ### isSurcharge **Signature:** `isSurcharge() : boolean` **Description:** Returns the 'surcharge' flag. **Returns:** true if this is a surcharge shipping cost, false if fixed shipping cost --- ### setPriceValue **Signature:** `setPriceValue(value : Number) : void` **Description:** Sets price attributes of the line item based on the purchase currency, taxation policy and line item quantity. The method sets the 'basePrice' attribute of the line item. Additionally, it sets the 'netPrice' attribute of the line item if the current taxation policy is 'net', and the 'grossPrice' attribute, if the current taxation policy is 'gross'. The 'netPrice'/'grossPrice' attributes are set by multiplying the specified price value with the line item quantity. If null is specified as value, the price attributes are reset to Money.NA. **Parameters:** - `value`: Price value or null --- ### setQuantity **Signature:** `setQuantity(quantity : Quantity) : void` **Description:** Sets the quantity of the shipping cost. **Parameters:** - `quantity`: the shipping quantity --- ### setSurcharge **Signature:** `setSurcharge(flag : boolean) : void` **Description:** Sets the 'surcharge' flag. **Parameters:** - `flag`: true if this is a surcharge shipping cost, false if this is a fixed shipping cost. --- ``` -------------------------------------------------------------------------------- /docs/sfra/product-search.md: -------------------------------------------------------------------------------- ```markdown # SFRA Product Search Model ## Overview The Product Search model represents search functionality in SFRA applications, providing comprehensive search results, refinements, sorting options, and pagination for product discovery and catalog browsing. ## Constructor ```javascript function ProductSearch(productSearch, httpParams, sortingRule, sortingOptions, rootCategory) ``` Creates a Product Search model instance with search results and related functionality. ### Parameters - `productSearch` (dw.catalog.ProductSearchModel) - Product search object from the API - `httpParams` (Object) - HTTP query parameters including search terms and refinements - `sortingRule` (string) - Current sorting rule being applied - `sortingOptions` (dw.util.ArrayList<dw.catalog.SortingOption>) - Options to sort search results - `rootCategory` (dw.catalog.Category) - Search result's root category if applicable ## Properties ### searchKeywords **Type:** string The search keywords entered by the user. ### category **Type:** Object | null Current category information if this is a category-based search. ### productIds **Type:** Array<Object> Array of product information objects with `productID` and `productSearchHit` properties for search results. ### products **Type:** Array<Object> Array of product tile models for the search results. **Note:** This property is not directly set by the constructor but would be populated by calling code using the `productIds` array. ### pageNumber **Type:** number Current page number for pagination (1-based). ### pageSize **Type:** number Number of products displayed per page (from httpParams.sz or default). ### count **Type:** number Total number of products found matching the search criteria. ### isCategorySearch **Type:** boolean Indicates whether this is a category-based search. ### isRefinedCategorySearch **Type:** boolean Indicates whether this is a refined category search. ### resetLink **Type:** string URL to reset all search refinements (AJAX endpoint). ### resetLinkSeo **Type:** string SEO-friendly URL to reset all search refinements. ### refinements **Type:** Array<Object> (computed property) Array of available search refinements including: - `displayName` - Human-readable refinement name - `isCategoryRefinement` - Boolean flag for category refinements - `isAttributeRefinement` - Boolean flag for attribute refinements - `isPriceRefinement` - Boolean flag for price refinements - `isPromotionRefinement` - Boolean flag for promotion refinements - `values` - Array of refinement value objects ### selectedFilters **Type:** Array<Object> (computed property) Array of currently applied refinements extracted from the refinements. ### productSort **Type:** ProductSortOptions Available sorting options for the search results (ProductSortOptions model instance). ### bannerImageUrl **Type:** string | null URL for category banner image (null if not available). ### showMoreUrl **Type:** string URL to load more search results (for infinite scroll or "show more" functionality). ### permalink **Type:** string Permalink URL for the current search with filters and pagination preserved. ### isSearchSuggestionsAvailable **Type:** boolean Indicates whether search suggestions are available for the current search. ### suggestionPhrases **Type:** Array<Object> Array of suggested search phrases with `value` and `url` properties (only available when `isSearchSuggestionsAvailable` is true). ### category **Type:** Object | null Current category information if this is a category-based search, including: - `name` - Category display name - `id` - Category ID - `pageTitle` - Category page title - `pageDescription` - Category page description - `pageKeywords` - Category page keywords ### pageMetaTags **Type:** Object Page meta tags for SEO purposes. ## Helper Functions ### getResetLink(search, httpParams, actionEndpoint) Generates URL to remove all refinements and reset search criteria. **Parameters:** - `search` (dw.catalog.ProductSearchModel) - Product search object - `httpParams` (Object) - Query parameters - `actionEndpoint` (string) - Action endpoint to use **Returns:** string - URL to reset search refinements ### getRefinements(productSearch, refinements, refinementDefinitions) Retrieves and formats search refinements for display. **Parameters:** - `productSearch` (dw.catalog.ProductSearchModel) - Product search object - `refinements` (dw.catalog.ProductSearchRefinements) - Search refinements - `refinementDefinitions` (ArrayList) - Refinement definitions **Returns:** Array<Object> - Formatted refinement objects ## Usage Example ```javascript var ProductSearch = require('*/cartridge/models/search/productSearch'); // From search controller var productSearch = new ProductSearch( apiProductSearch, req.querystring, sortingRule, sortingOptions, rootCategory ); // Access search results console.log('Found ' + productSearch.count + ' products'); console.log('Search term: ' + productSearch.searchKeywords); // Display product IDs (products would be populated separately) productSearch.productIds.forEach(function(item) { console.log('Product ID: ' + item.productID); }); // Handle refinements productSearch.refinements.forEach(function(refinement) { console.log(refinement.displayName + ':'); refinement.values.forEach(function(value) { console.log(' ' + value.displayValue + ' (' + value.hitCount + ')'); }); }); // Pagination console.log('Page ' + productSearch.pageNumber + ', showing ' + productSearch.pageSize + ' items'); // Check for search suggestions if (productSearch.isSearchSuggestionsAvailable) { productSearch.suggestionPhrases.forEach(function(phrase) { console.log('Suggested: ' + phrase.value); }); } ``` ## Search Types ### Keyword Search - Based on search terms entered by users - Full-text search across product attributes - Includes search suggestions and spell correction ### Category Search - Browse products within specific categories - Maintains category hierarchy navigation - Category-specific refinements and sorting ### Refined Search - Apply filters to narrow results - Multiple refinement types (price, attributes, categories) - Combinable refinements with removal options ## Refinement Types The model supports various refinement types: - **Category Refinements** - Filter by product categories - **Attribute Refinements** - Filter by product attributes (color, size, brand) - **Price Refinements** - Filter by price ranges - **Promotion Refinements** - Filter by promotional offers ## Notes - Provides comprehensive search functionality for SFRA storefronts - Handles both keyword and category-based searches - Includes pagination support with configurable page sizes - Supports multiple refinement types with hit counts - Integrates with product tile models for consistent display - Includes sorting options and search result optimization - Provides URLs for search refinement and reset functionality ## Related Models - **ProductSortOptions** - Used for search result sorting - **Product Tile Model** - Used for individual product display - **Categories Model** - Used for category-based searches - **Refinement Models** - Used for search filtering ``` -------------------------------------------------------------------------------- /docs/dw_util/Locale.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.util # Class Locale ## Inheritance Hierarchy - Object - dw.util.Locale ## Description Represents a Locale supported by the system. ## Properties ### country **Type:** String (Read Only) The uppercase ISO 3166 2-letter country/region code for this Locale. If no country has been specified for this Locale, this value is an empty string. ### displayCountry **Type:** String (Read Only) The display name of this Locale's country, in this Locale's language, not in the session locale's language. If no country has been specified for this Locale, this value is an empty string. ### displayLanguage **Type:** String (Read Only) The display name of this Locale's language, in this Locale's language, not in the session locale's language. If no country has been specified for this Locale, this value is an empty string. ### displayName **Type:** String (Read Only) The display name of this Locale, in this Locale's language, not in the session locale's language. If no display name has been specified for this Locale, this value is an empty string. ### ID **Type:** String (Read Only) The String representation of the localeID. Combines the language and the country key, concatenated with "_". For example: "en_US". This attribute is the primary key of the class. ### ISO3Country **Type:** String (Read Only) The uppercase ISO 3166 3-letter country/region code for this Locale. If no country has been specified for this Locale, this value is an empty string. ### ISO3Language **Type:** String (Read Only) The 3-letter ISO 639 language code for this Locale. If no language has been specified for this Locale, this value is an empty string. ### language **Type:** String (Read Only) The lowercase ISO 639 language code for this Locale. If no language has been specified for this Locale, this value is an empty string. ## Constructor Summary ## Method Summary ### getCountry **Signature:** `getCountry() : String` Returns the uppercase ISO 3166 2-letter country/region code for this Locale. ### getDisplayCountry **Signature:** `getDisplayCountry() : String` Returns the display name of this Locale's country, in this Locale's language, not in the session locale's language. ### getDisplayLanguage **Signature:** `getDisplayLanguage() : String` Returns the display name of this Locale's language, in this Locale's language, not in the session locale's language. ### getDisplayName **Signature:** `getDisplayName() : String` Returns the display name of this Locale, in this Locale's language, not in the session locale's language. ### getID **Signature:** `getID() : String` Returns the String representation of the localeID. ### getISO3Country **Signature:** `getISO3Country() : String` Returns the uppercase ISO 3166 3-letter country/region code for this Locale. ### getISO3Language **Signature:** `getISO3Language() : String` Returns the 3-letter ISO 639 language code for this Locale. ### getLanguage **Signature:** `getLanguage() : String` Returns the lowercase ISO 639 language code for this Locale. ### getLocale **Signature:** `static getLocale(localeId : String) : Locale` Returns a Locale instance for the given localeId, or null if no such Locale could be found. ### toString **Signature:** `toString() : String` Returns the String representation of the localeID. ## Method Detail ## Method Details ### getCountry **Signature:** `getCountry() : String` **Description:** Returns the uppercase ISO 3166 2-letter country/region code for this Locale. If no country has been specified for this Locale, this value is an empty string. **Returns:** the uppercase ISO 3166 2-letter country/region code for this Locale. If no country has been specified for this Locale, this value is an empty string. --- ### getDisplayCountry **Signature:** `getDisplayCountry() : String` **Description:** Returns the display name of this Locale's country, in this Locale's language, not in the session locale's language. If no country has been specified for this Locale, this value is an empty string. **Returns:** the display name of this Locale's country, in this Locale's language. If no country has been specified for this Locale, this value is an empty string. --- ### getDisplayLanguage **Signature:** `getDisplayLanguage() : String` **Description:** Returns the display name of this Locale's language, in this Locale's language, not in the session locale's language. If no country has been specified for this Locale, this value is an empty string. **Returns:** the display name of this Locale's language, in this Locale's language. If no language has been specified for this Locale, this value is an empty string. --- ### getDisplayName **Signature:** `getDisplayName() : String` **Description:** Returns the display name of this Locale, in this Locale's language, not in the session locale's language. If no display name has been specified for this Locale, this value is an empty string. **Returns:** the display name of this Locale, in this Locale's language. If no display name has been specified for this Locale, this value is an empty string. --- ### getID **Signature:** `getID() : String` **Description:** Returns the String representation of the localeID. Combines the language and the country key, concatenated with "_". For example: "en_US". This attribute is the primary key of the class. **Returns:** the String representation of the localeID. --- ### getISO3Country **Signature:** `getISO3Country() : String` **Description:** Returns the uppercase ISO 3166 3-letter country/region code for this Locale. If no country has been specified for this Locale, this value is an empty string. **Returns:** the uppercase ISO 3166 3-letter country/region code for this Locale. If no country has been specified for this Locale, this value is an empty string. --- ### getISO3Language **Signature:** `getISO3Language() : String` **Description:** Returns the 3-letter ISO 639 language code for this Locale. If no language has been specified for this Locale, this value is an empty string. **Returns:** the 3-letter ISO 639 language code for this Locale. If no language has been specified for this Locale, this value is an empty string. --- ### getLanguage **Signature:** `getLanguage() : String` **Description:** Returns the lowercase ISO 639 language code for this Locale. If no language has been specified for this Locale, this value is an empty string. **Returns:** the lowercase ISO 639 language code for this Locale. If no language has been specified for this Locale, this value is an empty string. --- ### getLocale **Signature:** `static getLocale(localeId : String) : Locale` **Description:** Returns a Locale instance for the given localeId, or null if no such Locale could be found. **Parameters:** - `localeId`: the localeID of the desired Locale **Returns:** the Locale instance for the given localeId, or null if no such Locale could be found. --- ### toString **Signature:** `toString() : String` **Description:** Returns the String representation of the localeID. Combines the language and the country key, concatenated with "_". For example: "en_US". This attribute is the primary key of the class. **Returns:** the String representation of the localeID. --- ``` -------------------------------------------------------------------------------- /docs/dw_system/Status.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.system # Class Status ## Inheritance Hierarchy - Object - dw.system.Status ## Description A Status is used for communicating an API status code back to a client. A status consists of multiple StatusItem. Most often a Status contains only one StatusItem. For convenience, a message with parameters is formatted using standard formatting patterns. If you want to display locale-specific messages in your application, you should use the Status.getCode() as key for a resource bundle. ## Properties ### code **Type:** String (Read Only) The status code either of the first ERROR StatusItem or when there is no ERROR StatusITEM, the first StatusItem in the overall list. The status code is the unique identifier for the message and can be used by client programs to check for a specific status and to generate a localized message. ### details **Type:** Map (Read Only) The details either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. ### error **Type:** boolean (Read Only) Checks if the status is an ERROR. The Status is an ERROR if one of the contained StatusItems is an ERROR. ### items **Type:** List (Read Only) All status items. ### message **Type:** String (Read Only) The message either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. Note: Custom code and client programs must not use this message to identify a specific status. The getCode() must be used for that purpose. The actual message can change from release to release. ### parameters **Type:** List (Read Only) The parameters either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. ### status **Type:** Number (Read Only) The overall status. If all StatusItems are OK, the method returns OK. If one StatusItem is an ERROR it returns ERROR. ## Constructor Summary Status() Creates a Status object with no StatusItems. Status(status : Number) Creates a Status with a single StatusItem. Status(status : Number, code : String) Creates a Status with a single StatusItem. Status(status : Number, code : String, message : String, parameters : Object...) Creates a Status with a single StatusItem. ## Method Summary ### addDetail **Signature:** `addDetail(key : String, value : Object) : void` Add detail information for the given key of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. ### addItem **Signature:** `addItem(item : StatusItem) : void` Adds an additional status item to this status instance. ### getCode **Signature:** `getCode() : String` Returns the status code either of the first ERROR StatusItem or when there is no ERROR StatusITEM, the first StatusItem in the overall list. ### getDetail **Signature:** `getDetail(key : String) : Object` Returns the detail value for the given key of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. ### getDetails **Signature:** `getDetails() : Map` Returns the details either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. ### getItems **Signature:** `getItems() : List` Returns all status items. ### getMessage **Signature:** `getMessage() : String` Returns the message either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. ### getParameters **Signature:** `getParameters() : List` Returns the parameters either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. ### getStatus **Signature:** `getStatus() : Number` Returns the overall status. ### isError **Signature:** `isError() : boolean` Checks if the status is an ERROR. ## Constructor Detail ## Method Detail ## Method Details ### addDetail **Signature:** `addDetail(key : String, value : Object) : void` **Description:** Add detail information for the given key of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. **Parameters:** - `key`: the key of the first ERROR StatusItem or the first StatusItem in the list. - `value`: the detail value. --- ### addItem **Signature:** `addItem(item : StatusItem) : void` **Description:** Adds an additional status item to this status instance. **Parameters:** - `item`: the status item to add. --- ### getCode **Signature:** `getCode() : String` **Description:** Returns the status code either of the first ERROR StatusItem or when there is no ERROR StatusITEM, the first StatusItem in the overall list. The status code is the unique identifier for the message and can be used by client programs to check for a specific status and to generate a localized message. **Returns:** the status code --- ### getDetail **Signature:** `getDetail(key : String) : Object` **Description:** Returns the detail value for the given key of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. **Parameters:** - `key`: the key for the detail to return. **Returns:** the detail value for the given key of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. --- ### getDetails **Signature:** `getDetails() : Map` **Description:** Returns the details either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. **Returns:** the details either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. --- ### getItems **Signature:** `getItems() : List` **Description:** Returns all status items. **Returns:** all status items. --- ### getMessage **Signature:** `getMessage() : String` **Description:** Returns the message either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. Note: Custom code and client programs must not use this message to identify a specific status. The getCode() must be used for that purpose. The actual message can change from release to release. **Returns:** the message either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. --- ### getParameters **Signature:** `getParameters() : List` **Description:** Returns the parameters either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. **Returns:** the parameters either of the first ERROR StatusItem or when there is no ERROR StatusItem, the first StatusItem in the overall list. --- ### getStatus **Signature:** `getStatus() : Number` **Description:** Returns the overall status. If all StatusItems are OK, the method returns OK. If one StatusItem is an ERROR it returns ERROR. **Returns:** either OK or ERROR --- ### isError **Signature:** `isError() : boolean` **Description:** Checks if the status is an ERROR. The Status is an ERROR if one of the contained StatusItems is an ERROR. **Returns:** true if status is an ERROR, false otherwise. --- ``` -------------------------------------------------------------------------------- /docs/dw_crypto/Signature.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.crypto # Class Signature ## Inheritance Hierarchy - Object - dw.crypto.Signature ## Description This class allows access to signature services offered through the Java Cryptography Architecture (JCA). At this time the signature/verification implementation of the methods is based on the default RSA JCE provider of the JDK - sun.security.rsa.SunRsaSign dw.crypto.Signature is an adapter to the security provider implementation and covers several digest algorithms: SHA1withRSA (deprecated) SHA256withRSA SHA384withRSA SHA512withRSA SHA256withRSA/PSS SHA384withRSA/PSS SHA512withRSA/PSS SHA256withECDSA SHA384withECDSA SHA512withECDSA Key size generally ranges between 512 and 65536 bits (the latter of which is unnecessarily large). Default key size for RSA is 1024. SHA384withRSA and SHA512withRSA require a key with length of at least 1024 bits. For ECDSA, the following key sizes are supported: SHA256withECDSA: 256-bit key (NIST P-256) SHA384withECDSA: 384-bit key (NIST P-384) SHA512withECDSA: 521-bit key (NIST P-521) When choosing a key size - beware of the tradeoff between security and processing time: The longer the key, the harder to break it but also it takes more time for the two sides to sign and verify the signature. An exception will be thrown for keys shorter than 2048 bits in this version of the API. Note: this class handles sensitive security-related data. Pay special attention to PCI DSS v3. requirements 2, 4, 12, and other relevant requirements. ## Constants ### SUPPORTED_DIGEST_ALGORITHMS_AS_ARRAY **Type:** String Supported digest algorithms exposed as a string array ## Properties ## Constructor Summary Signature() ## Method Summary ### isDigestAlgorithmSupported **Signature:** `isDigestAlgorithmSupported(digestAlgorithm : String) : boolean` Checks to see if a digest algorithm is supported ### sign **Signature:** `sign(contentToSign : String, privateKey : String, digestAlgorithm : String) : String` Signs a string and returns a string ### sign **Signature:** `sign(contentToSign : String, privateKey : KeyRef, digestAlgorithm : String) : String` Signs a string and returns a string ### signBytes **Signature:** `signBytes(contentToSign : Bytes, privateKey : String, digestAlgorithm : String) : Bytes` Signs bytes and returns bytes ### signBytes **Signature:** `signBytes(contentToSign : Bytes, privateKey : KeyRef, digestAlgorithm : String) : Bytes` Signs bytes and returns bytes ### verifyBytesSignature **Signature:** `verifyBytesSignature(signature : Bytes, contentToVerify : Bytes, publicKey : String, digestAlgorithm : String) : boolean` Verifies a signature supplied as bytes ### verifyBytesSignature **Signature:** `verifyBytesSignature(signature : Bytes, contentToVerify : Bytes, certificate : CertificateRef, digestAlgorithm : String) : boolean` Verifies a signature supplied as bytes ### verifySignature **Signature:** `verifySignature(signature : String, contentToVerify : String, publicKey : String, digestAlgorithm : String) : boolean` Verifies a signature supplied as string ### verifySignature **Signature:** `verifySignature(signature : String, contentToVerify : String, certificate : CertificateRef, digestAlgorithm : String) : boolean` Verifies a signature supplied as string ## Constructor Detail ## Method Detail ## Method Details ### isDigestAlgorithmSupported **Signature:** `isDigestAlgorithmSupported(digestAlgorithm : String) : boolean` **Description:** Checks to see if a digest algorithm is supported **Parameters:** - `digestAlgorithm`: the digest algorithm name **Returns:** a boolean indicating success (true) or failure (false) --- ### sign **Signature:** `sign(contentToSign : String, privateKey : String, digestAlgorithm : String) : String` **Description:** Signs a string and returns a string **Parameters:** - `contentToSign`: base64 encoded content to sign - `privateKey`: base64 encoded private key - `digestAlgorithm`: must be one of the currently supported ones **Returns:** the base64 encoded signature --- ### sign **Signature:** `sign(contentToSign : String, privateKey : KeyRef, digestAlgorithm : String) : String` **Description:** Signs a string and returns a string **Parameters:** - `contentToSign`: base64 encoded content to sign - `privateKey`: a reference to a private key entry in the keystore - `digestAlgorithm`: must be one of the currently supported ones **Returns:** the base64 encoded signature --- ### signBytes **Signature:** `signBytes(contentToSign : Bytes, privateKey : String, digestAlgorithm : String) : Bytes` **Description:** Signs bytes and returns bytes **Parameters:** - `contentToSign`: transformed with UTF-8 encoding into a byte stream - `privateKey`: base64 encoded private key - `digestAlgorithm`: must be one of the currently supported ones **Returns:** signature --- ### signBytes **Signature:** `signBytes(contentToSign : Bytes, privateKey : KeyRef, digestAlgorithm : String) : Bytes` **Description:** Signs bytes and returns bytes **Parameters:** - `contentToSign`: transformed with UTF-8 encoding into a byte stream - `privateKey`: a reference to a private key entry in the keystore - `digestAlgorithm`: must be one of the currently supported ones **Returns:** signature --- ### verifyBytesSignature **Signature:** `verifyBytesSignature(signature : Bytes, contentToVerify : Bytes, publicKey : String, digestAlgorithm : String) : boolean` **Description:** Verifies a signature supplied as bytes **Parameters:** - `signature`: signature to check as bytes - `contentToVerify`: as bytes - `publicKey`: base64 encoded public key - `digestAlgorithm`: must be one of the currently supported ones **Returns:** a boolean indicating success (true) or failure (false) --- ### verifyBytesSignature **Signature:** `verifyBytesSignature(signature : Bytes, contentToVerify : Bytes, certificate : CertificateRef, digestAlgorithm : String) : boolean` **Description:** Verifies a signature supplied as bytes **Parameters:** - `signature`: signature to check as bytes - `contentToVerify`: as bytes - `certificate`: a reference to a trusted certificate - `digestAlgorithm`: must be one of the currently supported ones **Returns:** a boolean indicating success (true) or failure (false) --- ### verifySignature **Signature:** `verifySignature(signature : String, contentToVerify : String, publicKey : String, digestAlgorithm : String) : boolean` **Description:** Verifies a signature supplied as string **Parameters:** - `signature`: base64 encoded signature - `contentToVerify`: base64 encoded content to verify - `publicKey`: base64 encoded public key - `digestAlgorithm`: must be one of the currently supported ones **Returns:** a boolean indicating success (true) or failure (false) --- ### verifySignature **Signature:** `verifySignature(signature : String, contentToVerify : String, certificate : CertificateRef, digestAlgorithm : String) : boolean` **Description:** Verifies a signature supplied as string **Parameters:** - `signature`: base64 encoded signature - `contentToVerify`: base64 encoded content to verify - `certificate`: a reference to a trusted certificate - `digestAlgorithm`: must be one of the currently supported ones **Returns:** a boolean indicating success (true) or failure (false) --- ``` -------------------------------------------------------------------------------- /docs/dw_order/GiftCertificateLineItem.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order # Class GiftCertificateLineItem ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.order.LineItem - dw.order.GiftCertificateLineItem ## Description Represents a Gift Certificate line item in the cart. When an order is processed, a Gift Certificate is created based on the information in the Gift Certificate line item. ## Properties ### giftCertificateID **Type:** String The ID of the gift certificate that this line item was used to create. If this line item has not been used to create a Gift Certificate, this method returns null. ### message **Type:** String The message to include in the email of the person receiving the gift certificate line item. ### productListItem **Type:** ProductListItem The associated ProductListItem. ### recipientEmail **Type:** String The email address of the person receiving the gift certificate line item. ### recipientName **Type:** String The name of the person receiving the gift certificate line item. ### senderName **Type:** String The name of the person or organization that sent the gift certificate line item or null if undefined. ### shipment **Type:** Shipment The associated Shipment. ## Constructor Summary ## Method Summary ### getGiftCertificateID **Signature:** `getGiftCertificateID() : String` Returns the ID of the gift certificate that this line item was used to create. ### getMessage **Signature:** `getMessage() : String` Returns the message to include in the email of the person receiving the gift certificate line item. ### getProductListItem **Signature:** `getProductListItem() : ProductListItem` Returns the associated ProductListItem. ### getRecipientEmail **Signature:** `getRecipientEmail() : String` Returns the email address of the person receiving the gift certificate line item. ### getRecipientName **Signature:** `getRecipientName() : String` Returns the name of the person receiving the gift certificate line item. ### getSenderName **Signature:** `getSenderName() : String` Returns the name of the person or organization that sent the gift certificate line item or null if undefined. ### getShipment **Signature:** `getShipment() : Shipment` Returns the associated Shipment. ### setGiftCertificateID **Signature:** `setGiftCertificateID(id : String) : void` Sets the ID of the gift certificate associated with this line item. ### setMessage **Signature:** `setMessage(message : String) : void` Sets the message to include in the email of the person receiving the gift certificate line item. ### setProductListItem **Signature:** `setProductListItem(productListItem : ProductListItem) : void` Sets the associated ProductListItem. ### setRecipientEmail **Signature:** `setRecipientEmail(recipientEmail : String) : void` Sets the email address of the person receiving the gift certificate line item. ### setRecipientName **Signature:** `setRecipientName(recipient : String) : void` Sets the name of the person receiving the gift certificate line item. ### setSenderName **Signature:** `setSenderName(sender : String) : void` Sets the name of the person or organization that sent the gift certificate line item. ### setShipment **Signature:** `setShipment(shipment : Shipment) : void` Associates the gift certificate line item with the specified shipment. ## Method Detail ## Method Details ### getGiftCertificateID **Signature:** `getGiftCertificateID() : String` **Description:** Returns the ID of the gift certificate that this line item was used to create. If this line item has not been used to create a Gift Certificate, this method returns null. **Returns:** the ID of the gift certificate or null if undefined. --- ### getMessage **Signature:** `getMessage() : String` **Description:** Returns the message to include in the email of the person receiving the gift certificate line item. **Returns:** the message to include in the email of the person receiving the gift certificate line item. --- ### getProductListItem **Signature:** `getProductListItem() : ProductListItem` **Description:** Returns the associated ProductListItem. **Returns:** item or null. --- ### getRecipientEmail **Signature:** `getRecipientEmail() : String` **Description:** Returns the email address of the person receiving the gift certificate line item. **Returns:** the email address of the person receiving the gift certificate line item. --- ### getRecipientName **Signature:** `getRecipientName() : String` **Description:** Returns the name of the person receiving the gift certificate line item. **Returns:** the name of the person receiving the gift certificate line item. --- ### getSenderName **Signature:** `getSenderName() : String` **Description:** Returns the name of the person or organization that sent the gift certificate line item or null if undefined. **Returns:** the name of the person or organization that sent the gift certificate line item or null if undefined. --- ### getShipment **Signature:** `getShipment() : Shipment` **Description:** Returns the associated Shipment. **Returns:** The shipment of the gift certificate line item --- ### setGiftCertificateID **Signature:** `setGiftCertificateID(id : String) : void` **Description:** Sets the ID of the gift certificate associated with this line item. **Parameters:** - `id`: the ID of the gift certificate associated with this line item. --- ### setMessage **Signature:** `setMessage(message : String) : void` **Description:** Sets the message to include in the email of the person receiving the gift certificate line item. **Parameters:** - `message`: the message to include in the email of the person receiving the gift certificate line item. --- ### setProductListItem **Signature:** `setProductListItem(productListItem : ProductListItem) : void` **Description:** Sets the associated ProductListItem. The product list item to be set must be of type gift certificate otherwise an exception is thrown. **Parameters:** - `productListItem`: the product list item to be associated --- ### setRecipientEmail **Signature:** `setRecipientEmail(recipientEmail : String) : void` **Description:** Sets the email address of the person receiving the gift certificate line item. **Parameters:** - `recipientEmail`: the email address of the person receiving the gift certificate line item. --- ### setRecipientName **Signature:** `setRecipientName(recipient : String) : void` **Description:** Sets the name of the person receiving the gift certificate line item. **Parameters:** - `recipient`: the name of the person receiving the gift certificate line item. --- ### setSenderName **Signature:** `setSenderName(sender : String) : void` **Description:** Sets the name of the person or organization that sent the gift certificate line item. **Parameters:** - `sender`: the name of the person or organization that sent the gift certificate line item. --- ### setShipment **Signature:** `setShipment(shipment : Shipment) : void` **Description:** Associates the gift certificate line item with the specified shipment. Gift certificate line item and shipment must belong to the same line item ctnr. **Parameters:** - `shipment`: The new shipment of the gift certificate line item --- ``` -------------------------------------------------------------------------------- /src/utils/cache.ts: -------------------------------------------------------------------------------- ```typescript /** * In-Memory Caching Module * * Provides efficient caching with TTL (Time-To-Live) and LRU (Least Recently Used) eviction * to reduce IO operations and improve response times for SFCC documentation queries. */ export interface CacheEntry<T> { value: T; timestamp: number; accessCount: number; lastAccessed: number; } export interface CacheOptions { maxSize?: number; ttlMs?: number; cleanupIntervalMs?: number; } export class InMemoryCache<T> { private cache = new Map<string, CacheEntry<T>>(); private readonly maxSize: number; private readonly ttlMs: number; private cleanupTimer?: NodeJS.Timeout; constructor(options: CacheOptions = {}) { this.maxSize = options.maxSize ?? 1000; this.ttlMs = options.ttlMs ?? 60 * 60 * 1000; // 1 hour default for static data // Setup automatic cleanup - less frequent for static data const cleanupInterval = options.cleanupIntervalMs ?? 10 * 60 * 1000; // 10 minutes this.cleanupTimer = setInterval(() => this.cleanup(), cleanupInterval); } /** * Store a value in the cache */ set(key: string, value: T): void { const now = Date.now(); // Handle zero max size - don't store anything if (this.maxSize === 0) { return; } // If at max capacity and adding a new key, remove LRU item first if (this.cache.size >= this.maxSize && !this.cache.has(key)) { this.evictLRU(); } this.cache.set(key, { value, timestamp: now, accessCount: 0, lastAccessed: now, }); } /** * Retrieve a value from the cache */ get(key: string): T | undefined { const entry = this.cache.get(key); if (!entry) { return undefined; } const now = Date.now(); // Check if entry has expired if (now - entry.timestamp > this.ttlMs) { this.cache.delete(key); return undefined; } // Update access statistics entry.accessCount++; entry.lastAccessed = now; return entry.value; } /** * Check if a key exists in the cache (without updating access stats) */ has(key: string): boolean { const entry = this.cache.get(key); if (!entry) { return false; } // Check if entry has expired if (Date.now() - entry.timestamp > this.ttlMs) { this.cache.delete(key); return false; } return true; } /** * Remove a specific key from the cache */ delete(key: string): boolean { return this.cache.delete(key); } /** * Clear all entries from the cache */ clear(): void { this.cache.clear(); } /** * Get cache statistics */ getStats(): { size: number; maxSize: number; hitRate: number; entries: Array<{ key: string; accessCount: number; age: number }>; } { const now = Date.now(); const entries = Array.from(this.cache.entries()).map(([key, entry]) => ({ key, accessCount: entry.accessCount, age: now - entry.timestamp, })); const totalAccesses = entries.reduce((sum, entry) => sum + entry.accessCount, 0); const totalHits = entries.filter(entry => entry.accessCount > 0).length; return { size: this.cache.size, maxSize: this.maxSize, hitRate: totalAccesses > 0 ? totalHits / totalAccesses : 0, entries, }; } /** * Remove expired entries from the cache */ private cleanup(): void { const now = Date.now(); const expiredKeys: string[] = []; for (const [key, entry] of this.cache.entries()) { if (now - entry.timestamp > this.ttlMs) { expiredKeys.push(key); } } expiredKeys.forEach(key => this.cache.delete(key)); } /** * Evict the least recently used item */ private evictLRU(): void { let oldestKey: string | undefined; let oldestTime = Date.now(); for (const [key, entry] of this.cache.entries()) { if (entry.lastAccessed < oldestTime) { oldestTime = entry.lastAccessed; oldestKey = key; } } if (oldestKey) { this.cache.delete(oldestKey); } } /** * Cleanup resources */ destroy(): void { if (this.cleanupTimer) { clearInterval(this.cleanupTimer); this.cleanupTimer = undefined; } this.clear(); } } /** * Multi-layer cache manager for different types of data */ export class CacheManager { private fileContentCache: InMemoryCache<string>; private classDetailsCache: InMemoryCache<any>; private searchResultsCache: InMemoryCache<any>; private methodSearchCache: InMemoryCache<any>; constructor() { // Much longer TTL for static documentation data that doesn't change during server runtime this.fileContentCache = new InMemoryCache<string>({ maxSize: 500, ttlMs: 4 * 60 * 60 * 1000, // 4 hours - raw file content is completely static cleanupIntervalMs: 30 * 60 * 1000, // 30 minutes cleanup interval }); this.classDetailsCache = new InMemoryCache({ maxSize: 300, ttlMs: 2 * 60 * 60 * 1000, // 2 hours - parsed data is static cleanupIntervalMs: 20 * 60 * 1000, // 20 minutes cleanup interval }); this.searchResultsCache = new InMemoryCache({ maxSize: 200, ttlMs: 60 * 60 * 1000, // 1 hour - search results are static cleanupIntervalMs: 15 * 60 * 1000, // 15 minutes cleanup interval }); this.methodSearchCache = new InMemoryCache({ maxSize: 100, ttlMs: 60 * 60 * 1000, // 1 hour - method search results are static cleanupIntervalMs: 15 * 60 * 1000, // 15 minutes cleanup interval }); } getFileContent(key: string): string | undefined { return this.fileContentCache.get(key); } setFileContent(key: string, content: string): void { this.fileContentCache.set(key, content); } getClassDetails(key: string): any { return this.classDetailsCache.get(key); } setClassDetails(key: string, details: any): void { this.classDetailsCache.set(key, details); } getSearchResults(key: string): any { return this.searchResultsCache.get(key); } setSearchResults(key: string, results: any): void { this.searchResultsCache.set(key, results); } getMethodSearch(key: string): any { return this.methodSearchCache.get(key); } setMethodSearch(key: string, results: any): void { this.methodSearchCache.set(key, results); } /** * Get comprehensive cache statistics */ getAllStats(): { fileContent: ReturnType<InMemoryCache<any>['getStats']>; classDetails: ReturnType<InMemoryCache<any>['getStats']>; searchResults: ReturnType<InMemoryCache<any>['getStats']>; methodSearch: ReturnType<InMemoryCache<any>['getStats']>; } { return { fileContent: this.fileContentCache.getStats(), classDetails: this.classDetailsCache.getStats(), searchResults: this.searchResultsCache.getStats(), methodSearch: this.methodSearchCache.getStats(), }; } /** * Clear all caches */ clearAll(): void { this.fileContentCache.clear(); this.classDetailsCache.clear(); this.searchResultsCache.clear(); this.methodSearchCache.clear(); } /** * Cleanup all resources */ destroy(): void { this.fileContentCache.destroy(); this.classDetailsCache.destroy(); this.searchResultsCache.destroy(); this.methodSearchCache.destroy(); } } ``` -------------------------------------------------------------------------------- /src/clients/logs/log-formatter.ts: -------------------------------------------------------------------------------- ```typescript /** * Output formatting and presentation logic for logs */ import { formatBytes } from '../../utils/utils.js'; import { LOG_CONSTANTS, LOG_MESSAGES } from './log-constants.js'; import type { LogSummary, LogFileInfo, LogLevel, JobLogInfo } from './log-types.js'; export class LogFormatter { /** * Format latest log entries response */ static formatLatestLogs( entries: string[], level: LogLevel, limit: number, files: string[], ): string { const fileList = files.join(', '); return `Latest ${limit} ${level} messages from files: ${fileList}\n\n${entries.join('\n\n---\n\n')}`; } /** * Format search results */ static formatSearchResults( matches: string[], pattern: string, date: string, ): string { if (matches.length === 0) { return LOG_MESSAGES.NO_SEARCH_MATCHES(pattern, date); } return `${LOG_MESSAGES.SEARCH_RESULTS(matches.length, pattern)}\n\n${matches.join('\n\n')}`; } /** * Format "no files found" message */ static formatNoFilesFound( level: LogLevel, date: string, availableFiles: string[], ): string { const available = availableFiles.join(', '); return LOG_MESSAGES.NO_FILES_FOUND(level, date, available); } /** * Format log summary into a readable string */ static formatLogSummary(summary: LogSummary): string { const keyIssuesSection = summary.keyIssues.length > 0 ? summary.keyIssues.map((issue: string) => `- ${issue}`).join('\n') : 'No major issues detected'; return [ `Log Summary for ${summary.date}:`, '', '📊 Counts:', `- Errors: ${summary.errorCount}`, `- Warnings: ${summary.warningCount}`, `- Info: ${summary.infoCount}`, `- Debug: ${summary.debugCount}`, '', `📁 Log Files (${summary.files.length}):`, summary.files.map((f: string) => `- ${f}`).join('\n'), '', '🔥 Key Issues:', keyIssuesSection, ].join('\n'); } /** * Format log files list with metadata */ static formatLogFilesList(logFiles: LogFileInfo[]): string { const totalFiles = (logFiles as any).totalCount ?? logFiles.length; const showingText = totalFiles > LOG_CONSTANTS.MAX_LOG_FILES_DISPLAY ? ` (showing latest ${LOG_CONSTANTS.MAX_LOG_FILES_DISPLAY} of ${totalFiles} total)` : ''; return `Available log files${showingText}:\n\n${logFiles.map((file: LogFileInfo) => `📄 ${file.name}\n Size: ${formatBytes(file.size)}\n Modified: ${file.lastModified}`, ).join('\n\n')}`; } /** * Format file processing summary */ static formatProcessingSummary( entriesReturned: number, filesProcessed: number, totalEntries: number, ): string { return `Parsed ${totalEntries} total entries from ${filesProcessed} files, returning latest ${entriesReturned}`; } /** * Format log level statistics */ static formatLogLevelStats(stats: Record<LogLevel, number>): string { const entries = Object.entries(stats) as Array<[LogLevel, number]>; return entries .map(([level, count]) => `${level}: ${count}`) .join(', '); } /** * Format error message with context */ static formatError(operation: string, error: unknown): string { const message = error instanceof Error ? error.message : String(error); return `Failed to ${operation}: ${message}`; } /** * Format file list for debugging */ static formatFileList(files: string[], prefix = ''): string { return files.map(f => `${prefix}${f}`).join(', '); } /** * Format timestamp for display */ static formatTimestamp(date: Date): string { return date.toISOString().replace('T', ' ').substring(0, 19); } /** * Format log entry with timestamp and level highlighting */ static formatLogEntry(entry: string, highlightLevel = false): string { if (!highlightLevel) { return entry; } return entry .replace(/ ERROR /g, ' 🔴 ERROR ') .replace(/ WARN /g, ' 🟡 WARN ') .replace(/ INFO /g, ' 🔵 INFO ') .replace(/ DEBUG /g, ' 🟢 DEBUG '); } /** * Format progress indicator */ static formatProgress(current: number, total: number, operation: string): string { const percentage = Math.round((current / total) * 100); return `${operation}: ${current}/${total} (${percentage}%)`; } /** * Format file size summary */ static formatFileSizes(files: Array<{ name: string; size: number }>): string { const totalSize = files.reduce((sum, file) => sum + file.size, 0); const avgSize = totalSize / files.length; return `Total: ${formatBytes(totalSize)}, Average: ${formatBytes(avgSize)}, Files: ${files.length}`; } /** * Truncate long text with ellipsis */ static truncateText(text: string, maxLength: number): string { if (text.length <= maxLength) { return text; } return `${text.substring(0, maxLength - 3)}...`; } /** * Format job log list */ static formatJobLogList(jobLogs: JobLogInfo[]): string { if (jobLogs.length === 0) { return 'No job logs found.'; } return `Found ${jobLogs.length} job logs:\n\n${jobLogs.map((jobLog: JobLogInfo) => { const baseInfo = `🔧 Job: ${jobLog.jobName}\n ID: ${jobLog.jobId}\n File: ${jobLog.logFile.split('/').pop()}\n Modified: ${jobLog.lastModified}`; const sizeInfo = jobLog.size ? `\n Size: ${formatBytes(jobLog.size)}` : ''; return baseInfo + sizeInfo; }).join('\n\n')}`; } /** * Format job log entries with job context */ static formatJobLogEntries( entries: string[], level: LogLevel | 'all', limit: number, jobContext?: string, ): string { const levelDisplay = level === 'all' ? 'all levels' : level; const contextText = jobContext ? ` from ${jobContext}` : ''; return `Latest ${limit} ${levelDisplay} messages${contextText}:\n\n${entries.join('\n\n---\n\n')}`; } /** * Format job execution summary */ static formatJobExecutionSummary(summary: { startTime?: string; endTime?: string; status?: string; duration?: string; errorCount: number; warningCount: number; steps: string[]; }, jobName: string): string { const sections = [ `Job Execution Summary: ${jobName}`, '', '⏱️ Timing:', `- Start: ${summary.startTime ?? 'Unknown'}`, `- End: ${summary.endTime ?? 'Unknown'}`, `- Duration: ${summary.duration ?? 'Unknown'}`, '', '📊 Status:', `- Status: ${summary.status ?? 'Unknown'}`, `- Errors: ${summary.errorCount}`, `- Warnings: ${summary.warningCount}`, ]; if (summary.steps.length > 0) { sections.push( '', '🔄 Steps:', ...summary.steps.map(step => `- ${step}`), ); } return sections.join('\n'); } /** * Format job search results */ static formatJobSearchResults( matches: string[], pattern: string, jobContext?: string, ): string { if (matches.length === 0) { const contextText = jobContext ? ` in ${jobContext} logs` : ' in job logs'; return `No matches found for "${pattern}"${contextText}`; } const contextText = jobContext ? ` in ${jobContext} logs` : ' in job logs'; return `Found ${matches.length} matches for "${pattern}"${contextText}:\n\n${matches.join('\n\n')}`; } } ``` -------------------------------------------------------------------------------- /docs/dw_extensions.payments/SalesforcePaymentMethod.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.extensions.payments # Class SalesforcePaymentMethod ## Inheritance Hierarchy - Object - dw.extensions.payments.SalesforcePaymentMethod ## Description Salesforce Payments representation of a payment method object. See Salesforce Payments documentation for how to gain access and configure it for use on your sites. A payment method contains information about a credential used by a shopper to attempt payment, such as a payment card or bank account. The available information differs for each type of payment method. It includes only limited information that can be safely presented to a shopper to remind them what credential they used, and specifically not complete card, account, or other numbers that could be used to make future payments. ## Constants ### TYPE_AFTERPAY_CLEARPAY **Type:** String = "afterpay_clearpay" Represents the Afterpay Clearpay payment method. ### TYPE_BANCONTACT **Type:** String = "bancontact" Represents the Bancontact payment method. ### TYPE_CARD **Type:** String = "card" Represents a credit card type of payment method. ### TYPE_EPS **Type:** String = "eps" Represents the EPS (Electronic Payment Standard) payment method. ### TYPE_IDEAL **Type:** String = "ideal" Represents the iDEAL payment method. ### TYPE_KLARNA **Type:** String = "klarna" Represents the Klarna payment method. ### TYPE_SEPA_DEBIT **Type:** String = "sepa_debit" Represents the SEPA Debit payment method. ## Properties ### bank **Type:** String (Read Only) The bank of this payment method, or null if none is available. Available on TYPE_IDEAL and TYPE_EPS type methods. ### bankCode **Type:** String (Read Only) The bank code of this payment method, or null if none is available. Available on TYPE_SEPA_DEBIT and TYPE_BANCONTACT type methods. ### bankName **Type:** String (Read Only) The bank name of this payment method, or null if none is available. Available on TYPE_BANCONTACT type methods. ### branchCode **Type:** String (Read Only) The bank branch code of this payment method, or null if none is available. Available on TYPE_SEPA_DEBIT type methods. ### brand **Type:** String (Read Only) The brand of this payment method, or null if none is available. Available on TYPE_CARD type methods. ### country **Type:** String (Read Only) The country of this payment method, or null if none is available. Available on TYPE_SEPA_DEBIT type methods. ### ID **Type:** String (Read Only) The identifier of this payment method. ### last4 **Type:** String (Read Only) The last 4 digits of the credential for this payment method, or null if none is available. Available on TYPE_CARD, TYPE_SEPA_DEBIT, and TYPE_BANCONTACT type methods. ### paymentMethodCategory **Type:** String (Read Only) The payment method category of this payment method, or null if none is available. Available on TYPE_KLARNA type methods. ### type **Type:** String (Read Only) The type of this payment method. ## Constructor Summary ## Method Summary ### getBank **Signature:** `getBank() : String` Returns the bank of this payment method, or null if none is available. ### getBankCode **Signature:** `getBankCode() : String` Returns the bank code of this payment method, or null if none is available. ### getBankName **Signature:** `getBankName() : String` Returns the bank name of this payment method, or null if none is available. ### getBranchCode **Signature:** `getBranchCode() : String` Returns the bank branch code of this payment method, or null if none is available. ### getBrand **Signature:** `getBrand() : String` Returns the brand of this payment method, or null if none is available. ### getCountry **Signature:** `getCountry() : String` Returns the country of this payment method, or null if none is available. ### getID **Signature:** `getID() : String` Returns the identifier of this payment method. ### getLast4 **Signature:** `getLast4() : String` Returns the last 4 digits of the credential for this payment method, or null if none is available. ### getPaymentDetails **Signature:** `getPaymentDetails(paymentInstrument : OrderPaymentInstrument) : SalesforcePaymentDetails` Returns the details to the Salesforce Payments payment for this payment method, using the given payment instrument. ### getPaymentMethodCategory **Signature:** `getPaymentMethodCategory() : String` Returns the payment method category of this payment method, or null if none is available. ### getType **Signature:** `getType() : String` Returns the type of this payment method. ## Method Detail ## Method Details ### getBank **Signature:** `getBank() : String` **Description:** Returns the bank of this payment method, or null if none is available. Available on TYPE_IDEAL and TYPE_EPS type methods. **Returns:** payment method bank --- ### getBankCode **Signature:** `getBankCode() : String` **Description:** Returns the bank code of this payment method, or null if none is available. Available on TYPE_SEPA_DEBIT and TYPE_BANCONTACT type methods. **Returns:** payment method bank code --- ### getBankName **Signature:** `getBankName() : String` **Description:** Returns the bank name of this payment method, or null if none is available. Available on TYPE_BANCONTACT type methods. **Returns:** payment method bank name --- ### getBranchCode **Signature:** `getBranchCode() : String` **Description:** Returns the bank branch code of this payment method, or null if none is available. Available on TYPE_SEPA_DEBIT type methods. **Returns:** payment method bank branch code --- ### getBrand **Signature:** `getBrand() : String` **Description:** Returns the brand of this payment method, or null if none is available. Available on TYPE_CARD type methods. **Returns:** payment method brand --- ### getCountry **Signature:** `getCountry() : String` **Description:** Returns the country of this payment method, or null if none is available. Available on TYPE_SEPA_DEBIT type methods. **Returns:** payment method country --- ### getID **Signature:** `getID() : String` **Description:** Returns the identifier of this payment method. **Returns:** payment method identifier --- ### getLast4 **Signature:** `getLast4() : String` **Description:** Returns the last 4 digits of the credential for this payment method, or null if none is available. Available on TYPE_CARD, TYPE_SEPA_DEBIT, and TYPE_BANCONTACT type methods. **Returns:** payment method credential last 4 digits --- ### getPaymentDetails **Signature:** `getPaymentDetails(paymentInstrument : OrderPaymentInstrument) : SalesforcePaymentDetails` **Description:** Returns the details to the Salesforce Payments payment for this payment method, using the given payment instrument. **Parameters:** - `paymentInstrument`: payment instrument **Returns:** The payment details --- ### getPaymentMethodCategory **Signature:** `getPaymentMethodCategory() : String` **Description:** Returns the payment method category of this payment method, or null if none is available. Available on TYPE_KLARNA type methods. **Returns:** payment method category --- ### getType **Signature:** `getType() : String` **Description:** Returns the type of this payment method. **Returns:** payment method type **See Also:** TYPE_BANCONTACT TYPE_CARD TYPE_EPS TYPE_AFTERPAY_CLEARPAY TYPE_IDEAL TYPE_SEPA_DEBIT --- ``` -------------------------------------------------------------------------------- /docs/dw_web/Cookie.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.web # Class Cookie ## Inheritance Hierarchy - Object - dw.web.Cookie ## Description Represents an HTTP cookie used for storing information on a client browser. Cookies are passed along in the HTTP request and can be retrieved by calling dw.system.Request.getHttpCookies(). Cookies must comply with RFC6265. We recommend you use only printable ASCII characters without separators, such as a comma or equal sign. If JSON is used as a cookie value, it must be encoded. Note: this class allows access to sensitive security-related data. Pay special attention to PCI DSS v3. requirements 2, 4, and 12. See Request.getHttpCookies(). ## Constants ### EMPTYNAME **Type:** String = "dw_emptyname__" Default name for cookies with empty strings. ## Properties ### comment **Type:** String The comment associated with the cookie. ### domain **Type:** String The domain associated with the cookie. ### httpOnly **Type:** boolean Identifies if the cookie is http-only. ### maxAge **Type:** Number The maximum age of the cookie, specified in seconds. By default, -1 indicating the cookie will persist until client shutdown. ### name **Type:** String (Read Only) The cookie's name. ### path **Type:** String The path for the cookie. ### secure **Type:** boolean Identifies if the cookie is secure. ### value **Type:** String The cookie's value. ### version **Type:** Number The version for the cookie. 0 means original Netscape cookie and 1 means RFC 2109 compliant cookie. ## Constructor Summary Cookie(name : String, value : String) Constructs a new cookie using the specified name and value. ## Method Summary ### getComment **Signature:** `getComment() : String` Returns the comment associated with the cookie. ### getDomain **Signature:** `getDomain() : String` Returns the domain associated with the cookie. ### getMaxAge **Signature:** `getMaxAge() : Number` Returns the maximum age of the cookie, specified in seconds. ### getName **Signature:** `getName() : String` Returns the cookie's name. ### getPath **Signature:** `getPath() : String` Returns the path for the cookie. ### getSecure **Signature:** `getSecure() : boolean` Identifies if the cookie is secure. ### getValue **Signature:** `getValue() : String` Returns the cookie's value. ### getVersion **Signature:** `getVersion() : Number` Returns the version for the cookie. ### isHttpOnly **Signature:** `isHttpOnly() : boolean` Identifies if the cookie is http-only. ### setComment **Signature:** `setComment(comment : String) : void` Sets the comment associated with the cookie. ### setDomain **Signature:** `setDomain(domain : String) : void` Sets the domain associated with the cookie. ### setHttpOnly **Signature:** `setHttpOnly(httpOnly : boolean) : void` Sets the http-only state for the cookie. ### setMaxAge **Signature:** `setMaxAge(age : Number) : void` Sets the maximum age of the cookie in seconds. ### setPath **Signature:** `setPath(path : String) : void` Sets the path for the cookie. ### setSecure **Signature:** `setSecure(secure : boolean) : void` Sets the secure state for the cookie. ### setValue **Signature:** `setValue(value : String) : void` Sets the cookie's value. ### setVersion **Signature:** `setVersion(version : Number) : void` Sets the version for the cookie. ## Constructor Detail ## Method Detail ## Method Details ### getComment **Signature:** `getComment() : String` **Description:** Returns the comment associated with the cookie. **Returns:** the comment associated with the cookie. --- ### getDomain **Signature:** `getDomain() : String` **Description:** Returns the domain associated with the cookie. **Returns:** the domain associated with the cookie. --- ### getMaxAge **Signature:** `getMaxAge() : Number` **Description:** Returns the maximum age of the cookie, specified in seconds. By default, -1 indicating the cookie will persist until client shutdown. **Returns:** an integer specifying the maximum age of the cookie in seconds; if negative, means the cookie persists until client shutdown --- ### getName **Signature:** `getName() : String` **Description:** Returns the cookie's name. **Returns:** the cookie's name. --- ### getPath **Signature:** `getPath() : String` **Description:** Returns the path for the cookie. **Returns:** the path for the cookie. --- ### getSecure **Signature:** `getSecure() : boolean` **Description:** Identifies if the cookie is secure. **Returns:** true if the cookie is secure, false otherwise. --- ### getValue **Signature:** `getValue() : String` **Description:** Returns the cookie's value. **Returns:** the cookie's value. --- ### getVersion **Signature:** `getVersion() : Number` **Description:** Returns the version for the cookie. 0 means original Netscape cookie and 1 means RFC 2109 compliant cookie. **Returns:** the version for the cookie. --- ### isHttpOnly **Signature:** `isHttpOnly() : boolean` **Description:** Identifies if the cookie is http-only. **Returns:** true if the cookie is http-only, false otherwise. --- ### setComment **Signature:** `setComment(comment : String) : void` **Description:** Sets the comment associated with the cookie. Setting a comment automatically changes the cookie to be a RFC 2109 (set-cookie2) compliant cookie, because comments are only supported with RFC cookies and not with Netscapes original cookie. **Parameters:** - `comment`: the comment associated with the cookie. --- ### setDomain **Signature:** `setDomain(domain : String) : void` **Description:** Sets the domain associated with the cookie. **Parameters:** - `domain`: the comment associated with the cookie. --- ### setHttpOnly **Signature:** `setHttpOnly(httpOnly : boolean) : void` **Description:** Sets the http-only state for the cookie. **Parameters:** - `httpOnly`: sets http-only state for the cookie. --- ### setMaxAge **Signature:** `setMaxAge(age : Number) : void` **Description:** Sets the maximum age of the cookie in seconds. A positive value indicates that the cookie will expire after that many seconds have passed. Note that the value is the maximum age when the cookie will expire, not the cookie's current age. A negative value means that the cookie is not stored persistently and will be deleted when the client exits. A zero value causes the cookie to be deleted. **Parameters:** - `age`: an integer specifying the maximum age of the cookie in seconds; if negative, means the cookie is not stored; if zero, deletes the cookie --- ### setPath **Signature:** `setPath(path : String) : void` **Description:** Sets the path for the cookie. **Parameters:** - `path`: the path for the cookie. --- ### setSecure **Signature:** `setSecure(secure : boolean) : void` **Description:** Sets the secure state for the cookie. **Parameters:** - `secure`: sets secure state for the cookie. --- ### setValue **Signature:** `setValue(value : String) : void` **Description:** Sets the cookie's value. **Parameters:** - `value`: the value to set in the cookie. --- ### setVersion **Signature:** `setVersion(version : Number) : void` **Description:** Sets the version for the cookie. 0 means original Netscape cookie and 1 means RFC 2109 compliant cookie. The default is 0. **Parameters:** - `version`: the version for the cookie. --- ``` -------------------------------------------------------------------------------- /docs/dw_campaign/Coupon.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.campaign # Class Coupon ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.campaign.Coupon ## Description Represents a coupon in Commerce Cloud Digital. ## Constants ### TYPE_MULTIPLE_CODES **Type:** String = "MULTIPLE_CODES" Constant representing coupon type multiple-codes. ### TYPE_SINGLE_CODE **Type:** String = "SINGLE_CODE" Constant representing coupon type single-code. ### TYPE_SYSTEM_CODES **Type:** String = "SYSTEM_CODES" Constant representing coupon type system-codes. ## Properties ### codePrefix **Type:** String (Read Only) The prefix defined for coupons of type TYPE_SYSTEM_CODES If no prefix is defined, or coupon is of type TYPE_SINGLE_CODE or TYPE_MULTIPLE_CODES, null is returned. ### enabled **Type:** boolean (Read Only) Returns true if coupon is enabled, else false. ### ID **Type:** String (Read Only) The ID of the coupon. ### nextCouponCode **Type:** String (Read Only) The next unissued code of this coupon. For single-code coupons, the single fixed coupon code is returned. For all multi-code coupons, the next available, unissued coupon code is returned. If all codes of the coupon have been issued, then there is no next code, and null is returned. A transaction is required when calling this method. This needs to be ensured by the calling script. ### promotions **Type:** Collection (Read Only) The coupon-based promotions directly or indirectly (through campaigns) assigned to this coupon. ### redemptionLimitPerCode **Type:** Number (Read Only) The defined limit on redemption per coupon code. Null is returned if no limit is defined, which means that each code can be redeemed an unlimited number of times. ### redemptionLimitPerCustomer **Type:** Number (Read Only) The defined limit on redemption of this coupon per customer. Null is returned if no limit is defined, which means that customers can redeem this coupon an unlimited number of times. ### redemptionLimitPerTimeFrame **Type:** Number (Read Only) The defined limit on redemption per customer per time-frame (see getRedemptionLimitTimeFrame(). Null is returned if no limit is defined, which means that there is no time-specific redemption limit for customers. ### redemptionLimitTimeFrame **Type:** Number (Read Only) The time-frame (in days) of the defined limit on redemption per customer per time-frame. Null is returned if no limit is defined, which means that there is no time-specific redemption limit for customers. ### type **Type:** String (Read Only) The coupon type. Possible values are TYPE_SINGLE_CODE, TYPE_MULTIPLE_CODES and TYPE_SYSTEM_CODES. ## Constructor Summary ## Method Summary ### getCodePrefix **Signature:** `getCodePrefix() : String` Returns the prefix defined for coupons of type TYPE_SYSTEM_CODES If no prefix is defined, or coupon is of type TYPE_SINGLE_CODE or TYPE_MULTIPLE_CODES, null is returned. ### getID **Signature:** `getID() : String` Returns the ID of the coupon. ### getNextCouponCode **Signature:** `getNextCouponCode() : String` Returns the next unissued code of this coupon. ### getPromotions **Signature:** `getPromotions() : Collection` Returns the coupon-based promotions directly or indirectly (through campaigns) assigned to this coupon. ### getRedemptionLimitPerCode **Signature:** `getRedemptionLimitPerCode() : Number` Returns the defined limit on redemption per coupon code. ### getRedemptionLimitPerCustomer **Signature:** `getRedemptionLimitPerCustomer() : Number` Returns the defined limit on redemption of this coupon per customer. ### getRedemptionLimitPerTimeFrame **Signature:** `getRedemptionLimitPerTimeFrame() : Number` Returns the defined limit on redemption per customer per time-frame (see getRedemptionLimitTimeFrame(). ### getRedemptionLimitTimeFrame **Signature:** `getRedemptionLimitTimeFrame() : Number` Returns the time-frame (in days) of the defined limit on redemption per customer per time-frame. ### getType **Signature:** `getType() : String` Returns the coupon type. ### isEnabled **Signature:** `isEnabled() : boolean` Returns true if coupon is enabled, else false. ## Method Detail ## Method Details ### getCodePrefix **Signature:** `getCodePrefix() : String` **Description:** Returns the prefix defined for coupons of type TYPE_SYSTEM_CODES If no prefix is defined, or coupon is of type TYPE_SINGLE_CODE or TYPE_MULTIPLE_CODES, null is returned. **Returns:** Coupon code prefix or null --- ### getID **Signature:** `getID() : String` **Description:** Returns the ID of the coupon. **Returns:** Coupon ID --- ### getNextCouponCode **Signature:** `getNextCouponCode() : String` **Description:** Returns the next unissued code of this coupon. For single-code coupons, the single fixed coupon code is returned. For all multi-code coupons, the next available, unissued coupon code is returned. If all codes of the coupon have been issued, then there is no next code, and null is returned. A transaction is required when calling this method. This needs to be ensured by the calling script. **Returns:** Next available code of this coupon, or null if there are no available codes. --- ### getPromotions **Signature:** `getPromotions() : Collection` **Description:** Returns the coupon-based promotions directly or indirectly (through campaigns) assigned to this coupon. **Returns:** Promotions assigned to the coupon in no particular order. --- ### getRedemptionLimitPerCode **Signature:** `getRedemptionLimitPerCode() : Number` **Description:** Returns the defined limit on redemption per coupon code. Null is returned if no limit is defined, which means that each code can be redeemed an unlimited number of times. **Returns:** The maximum number of redemption per coupon code --- ### getRedemptionLimitPerCustomer **Signature:** `getRedemptionLimitPerCustomer() : Number` **Description:** Returns the defined limit on redemption of this coupon per customer. Null is returned if no limit is defined, which means that customers can redeem this coupon an unlimited number of times. **Returns:** The maximum number of redemption per customer --- ### getRedemptionLimitPerTimeFrame **Signature:** `getRedemptionLimitPerTimeFrame() : Number` **Description:** Returns the defined limit on redemption per customer per time-frame (see getRedemptionLimitTimeFrame(). Null is returned if no limit is defined, which means that there is no time-specific redemption limit for customers. **Returns:** The maximum number of redemption per customer within time-frame **See Also:** getRedemptionLimitTimeFrame() --- ### getRedemptionLimitTimeFrame **Signature:** `getRedemptionLimitTimeFrame() : Number` **Description:** Returns the time-frame (in days) of the defined limit on redemption per customer per time-frame. Null is returned if no limit is defined, which means that there is no time-specific redemption limit for customers. **Returns:** Timeframe (days) of redemption per time **See Also:** getRedemptionLimitPerTimeFrame() --- ### getType **Signature:** `getType() : String` **Description:** Returns the coupon type. Possible values are TYPE_SINGLE_CODE, TYPE_MULTIPLE_CODES and TYPE_SYSTEM_CODES. **Returns:** Coupon type --- ### isEnabled **Signature:** `isEnabled() : boolean` **Description:** Returns true if coupon is enabled, else false. **Returns:** true if coupon is enabled. --- ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/get-job-log-entries.full-mode.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml --- description: "Test get_job_log_entries tool in full mode - Aegis framework validation and core MCP functionality" tests: # Core functionality tests - essential MCP protocol validation - it: "should retrieve job log entries with default parameters" request: jsonrpc: "2.0" id: "job-entries-default" method: "tools/call" params: name: "get_job_log_entries" arguments: {} expect: response: jsonrpc: "2.0" id: "job-entries-default" result: content: match:arrayElements: match:partial: type: "text" text: "match:contains:Latest" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" - it: "should respect limit parameter" request: jsonrpc: "2.0" id: "job-entries-limit" method: "tools/call" params: name: "get_job_log_entries" arguments: limit: 5 expect: response: jsonrpc: "2.0" id: "job-entries-limit" result: content: match:arrayElements: match:partial: type: "text" text: "match:contains:Latest 5" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" # Parameter validation tests - level filtering (sample representative cases) - it: "should filter by error level" request: jsonrpc: "2.0" id: "job-entries-error" method: "tools/call" params: name: "get_job_log_entries" arguments: level: "error" limit: 3 expect: response: jsonrpc: "2.0" id: "job-entries-error" result: content: match:arrayElements: match:partial: type: "text" text: "match:contains:error messages" isError: false stderr: "toBeEmpty" - it: "should filter by info level" request: jsonrpc: "2.0" id: "job-entries-info" method: "tools/call" params: name: "get_job_log_entries" arguments: level: "info" limit: 3 expect: response: jsonrpc: "2.0" id: "job-entries-info" result: content: match:arrayElements: match:partial: type: "text" text: "match:contains:info messages" isError: false stderr: "toBeEmpty" # Job name filtering tests - it: "should filter by job name" request: jsonrpc: "2.0" id: "job-entries-by-name" method: "tools/call" params: name: "get_job_log_entries" arguments: jobName: "ProcessOrders" limit: 3 expect: response: jsonrpc: "2.0" id: "job-entries-by-name" result: content: match:arrayElements: match:partial: type: "text" text: "match:contains:from job: ProcessOrders" isError: false stderr: "toBeEmpty" - it: "should combine job name and level parameters" request: jsonrpc: "2.0" id: "job-entries-name-level" method: "tools/call" params: name: "get_job_log_entries" arguments: jobName: "ImportCatalog" level: "info" limit: 3 expect: response: jsonrpc: "2.0" id: "job-entries-name-level" result: content: match:arrayElements: match:partial: type: "text" text: "match:regex:.*info messages from job: ImportCatalog" isError: false stderr: "toBeEmpty" # Content structure validation - Aegis pattern matching capabilities - it: "should contain SystemJobThread pattern in job logs" request: jsonrpc: "2.0" id: "job-entries-content" method: "tools/call" params: name: "get_job_log_entries" arguments: limit: 5 expect: response: jsonrpc: "2.0" id: "job-entries-content" result: content: match:arrayElements: match:partial: type: "text" text: "match:contains:SystemJobThread" isError: false stderr: "toBeEmpty" - it: "should include proper GMT timestamps" request: jsonrpc: "2.0" id: "job-entries-timestamps" method: "tools/call" params: name: "get_job_log_entries" arguments: limit: 3 expect: response: jsonrpc: "2.0" id: "job-entries-timestamps" result: content: match:arrayElements: match:partial: type: "text" text: "match:regex:\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3} GMT" isError: false stderr: "toBeEmpty" # Error handling tests - essential MCP error response validation - it: "should handle zero limit with proper error response" request: jsonrpc: "2.0" id: "job-entries-zero-limit" method: "tools/call" params: name: "get_job_log_entries" arguments: limit: 0 expect: response: jsonrpc: "2.0" id: "job-entries-zero-limit" result: content: match:arrayElements: match:partial: type: "text" text: "match:contains:Invalid limit" isError: true stderr: "toBeEmpty" - it: "should handle invalid log level gracefully" request: jsonrpc: "2.0" id: "job-entries-invalid-level" method: "tools/call" params: name: "get_job_log_entries" arguments: level: "invalid" limit: 5 expect: response: jsonrpc: "2.0" id: "job-entries-invalid-level" result: content: match:arrayElements: match:partial: type: "text" text: "match:contains:Error" isError: true stderr: "toBeEmpty" - it: "should handle nonexistent job name gracefully" request: jsonrpc: "2.0" id: "job-entries-nonexistent-job" method: "tools/call" params: name: "get_job_log_entries" arguments: jobName: "NonExistentJob123" limit: 3 expect: response: jsonrpc: "2.0" id: "job-entries-nonexistent-job" result: content: match:arrayElements: match:partial: type: "text" text: "match:contains:No job logs found" isError: false stderr: "toBeEmpty" # Performance test - single representative case for aegis framework validation - it: "should respond within reasonable time for standard request" request: jsonrpc: "2.0" id: "job-entries-performance" method: "tools/call" params: name: "get_job_log_entries" arguments: limit: 10 expect: response: jsonrpc: "2.0" id: "job-entries-performance" result: content: match:arrayElements: match:partial: type: "text" text: "match:type:string" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2500ms" ``` -------------------------------------------------------------------------------- /docs/dw_order/PaymentMethod.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order # Class PaymentMethod ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.order.PaymentMethod ## Description The PaymentMethod class represents a logical type of payment a customer can make in the storefront. This class provides methods to access the payment method attributes, status, and (for card-based payment methods) the related payment cards. A typical storefront presents the customer a list of payment methods that a customer can choose from after he has entered his billing address during the checkout. PaymentMgr.getApplicablePaymentMethods(Customer, String, Number) is used to determine the PaymentMethods that are relevant for the customer based on the amount of his order, his customer groups, and his shipping address. ## Properties ### active **Type:** boolean (Read Only) Returns 'true' if payment method is active (enabled), otherwise 'false' is returned. ### activePaymentCards **Type:** List (Read Only) Returns enabled payment cards that are assigned to this payment method, regardless of current customer, country or payment amount restrictions. The payment cards are sorted as defined in the Business Manager. ### description **Type:** MarkupText (Read Only) The description of the payment method. ### ID **Type:** String (Read Only) The unique ID of the payment method. ### image **Type:** MediaFile (Read Only) The reference to the payment method image. ### name **Type:** String (Read Only) The name of the payment method. ### paymentProcessor **Type:** PaymentProcessor (Read Only) The payment processor associated to this payment method. ## Constructor Summary ## Method Summary ### getActivePaymentCards **Signature:** `getActivePaymentCards() : List` Returns enabled payment cards that are assigned to this payment method, regardless of current customer, country or payment amount restrictions. ### getApplicablePaymentCards **Signature:** `getApplicablePaymentCards(customer : Customer, countryCode : String, paymentAmount : Number) : List` Returns the sorted list of all enabled payment cards of this payment method applicable for the specified customer, country, payment amount and the session currency The payment cards are sorted as defined in the Business Manager. ### getDescription **Signature:** `getDescription() : MarkupText` Returns the description of the payment method. ### getID **Signature:** `getID() : String` Returns the unique ID of the payment method. ### getImage **Signature:** `getImage() : MediaFile` Returns the reference to the payment method image. ### getName **Signature:** `getName() : String` Returns the name of the payment method. ### getPaymentProcessor **Signature:** `getPaymentProcessor() : PaymentProcessor` Returns the payment processor associated to this payment method. ### isActive **Signature:** `isActive() : boolean` Returns 'true' if payment method is active (enabled), otherwise 'false' is returned. ### isApplicable **Signature:** `isApplicable(customer : Customer, countryCode : String, paymentAmount : Number) : boolean` Returns 'true' if this payment method is applicable for the specified customer, country and payment amount and the session currency. ## Method Detail ## Method Details ### getActivePaymentCards **Signature:** `getActivePaymentCards() : List` **Description:** Returns enabled payment cards that are assigned to this payment method, regardless of current customer, country or payment amount restrictions. The payment cards are sorted as defined in the Business Manager. **Returns:** List of enabled payment cards of current site --- ### getApplicablePaymentCards **Signature:** `getApplicablePaymentCards(customer : Customer, countryCode : String, paymentAmount : Number) : List` **Description:** Returns the sorted list of all enabled payment cards of this payment method applicable for the specified customer, country, payment amount and the session currency The payment cards are sorted as defined in the Business Manager. A payment card is applicable if the card is restricted by customer group, and at least one of the groups of the specified customer is assigned to the card the card is restricted by billing country, and the specified country code is assigned to the card the card is restricted by payment amount for the session currency, and the specified payment amount is within the limits of the min/max payment amount defined for the method and the session currency the card is restricted by currency code, and the specified currency code matches session currency. All parameters are optional, and if not specified, the respective restriction won't be validated. For example, if a card is restricted by billing country, but no country code is specified, this card will be returned, unless it is filtered out by customer group or payment amount. **Parameters:** - `customer`: Customer or null - `countryCode`: Billing country code or null - `paymentAmount`: Payment amount or null **Returns:** List of applicable payment cards of this payment method --- ### getDescription **Signature:** `getDescription() : MarkupText` **Description:** Returns the description of the payment method. **Returns:** Description of the payment method. --- ### getID **Signature:** `getID() : String` **Description:** Returns the unique ID of the payment method. **Returns:** ID of the payment method. --- ### getImage **Signature:** `getImage() : MediaFile` **Description:** Returns the reference to the payment method image. **Returns:** Image of the payment method. --- ### getName **Signature:** `getName() : String` **Description:** Returns the name of the payment method. **Returns:** Name of the payment method. --- ### getPaymentProcessor **Signature:** `getPaymentProcessor() : PaymentProcessor` **Description:** Returns the payment processor associated to this payment method. **Returns:** the payment processor associated to this payment method. --- ### isActive **Signature:** `isActive() : boolean` **Description:** Returns 'true' if payment method is active (enabled), otherwise 'false' is returned. **Returns:** true if payment method is active, otherwise false. --- ### isApplicable **Signature:** `isApplicable(customer : Customer, countryCode : String, paymentAmount : Number) : boolean` **Description:** Returns 'true' if this payment method is applicable for the specified customer, country and payment amount and the session currency. The payment method is applicable if the method is restricted by customer group, and at least one of the groups of the specified customer is assigned to the method the method is restricted by billing country, and the specified country code is assigned to the method the method is restricted by payment amount for the session currency, and the specified payment amount is within the limits of the min/max payment amount defined for the method and the session currency the method is restricted by currency code, and the specified currency code matches session currency. All parameters are optional, and if not specified, the respective restriction won't be validated. For example, if a method is restricted by billing country, but no country code is specified, this method will be returned, unless it is filtered out by customer group or payment amount. **Parameters:** - `customer`: Customer or null - `countryCode`: Billing country code or null - `paymentAmount`: Payment amount or null **Returns:** true if payment method is applicable, false otherwise --- ``` -------------------------------------------------------------------------------- /src/core/handlers/base-handler.ts: -------------------------------------------------------------------------------- ```typescript import { Logger } from '../../utils/logger.js'; import { SFCCConfig } from '../../types/types.js'; export interface HandlerContext { logger: Logger; config: SFCCConfig; capabilities: { canAccessLogs: boolean; canAccessOCAPI: boolean; }; } export interface ToolExecutionResult { content: Array<{ type: 'text'; text: string }>; isError?: boolean; } export interface ToolArguments { [key: string]: any; } /** * Generic tool specification interface * Defines the contract for declarative tool configuration */ export interface GenericToolSpec<TArgs = ToolArguments, TResult = any> { /** Optional validation function for tool arguments */ validate?: (args: TArgs, toolName: string) => void; /** Optional function to apply default values to arguments */ defaults?: (args: TArgs) => Partial<TArgs>; /** Main execution function for the tool */ exec: (args: TArgs, context: ToolExecutionContext) => Promise<TResult>; /** Function to generate log message for the tool execution */ logMessage: (args: TArgs) => string; } /** * Context provided to tool execution functions * Allows tools to access clients and other resources */ export interface ToolExecutionContext { /** Handler context with configuration and capabilities */ handlerContext: HandlerContext; /** Logger instance for the handler */ logger: any; /** Additional context data that can be provided by concrete handlers */ [key: string]: any; } export class HandlerError extends Error { constructor( message: string, public readonly toolName: string, public readonly code: string = 'HANDLER_ERROR', public readonly details?: any, ) { super(message); this.name = 'HandlerError'; } } export abstract class BaseToolHandler<TToolName extends string = string> { protected context: HandlerContext; protected logger: Logger; private _isInitialized = false; constructor(context: HandlerContext, subLoggerName: string) { this.context = context; this.logger = Logger.getChildLogger(`Handler:${subLoggerName}`); } /** * Abstract method to get tool configuration * Each concrete handler implements this with their specific config */ protected abstract getToolConfig(): Record<TToolName, GenericToolSpec>; /** * Abstract method to get tool name set for O(1) lookup * Each concrete handler implements this with their specific tool set */ protected abstract getToolNameSet(): Set<string>; /** * Abstract method to create execution context * Each concrete handler can provide specialized context */ protected abstract createExecutionContext(): Promise<ToolExecutionContext>; /** * Check if this handler can handle the given tool */ canHandle(toolName: string): boolean { return this.getToolNameSet().has(toolName); } /** * Config-driven tool execution * Handles validation, defaults, execution, and logging uniformly */ async handle(toolName: string, args: ToolArguments, startTime: number): Promise<ToolExecutionResult> { if (!this.canHandle(toolName)) { throw new Error(`Unsupported tool: ${toolName}`); } const toolConfig = this.getToolConfig(); const spec = toolConfig[toolName as TToolName]; if (!spec) { throw new Error(`No configuration found for tool: ${toolName}`); } return this.executeWithLogging( toolName, startTime, () => this.dispatchTool(spec, args), spec.logMessage(this.applyDefaults(spec, args)), ); } /** * Generic tool dispatch using configuration * Handles validation, defaults, and execution */ private async dispatchTool(spec: GenericToolSpec, args: ToolArguments): Promise<any> { const context = await this.createExecutionContext(); const processedArgs = this.createValidatedArgs(spec, args, 'tool'); return spec.exec(processedArgs, context); } /** * Apply default values to arguments */ private applyDefaults(spec: GenericToolSpec, args: ToolArguments): ToolArguments { if (!spec.defaults) { return args; } const defaults = spec.defaults(args); return { ...args, ...defaults }; } /** * Create validated arguments with defaults applied */ private createValidatedArgs(spec: GenericToolSpec, args: ToolArguments, toolName: string): ToolArguments { // Apply defaults first const processedArgs = this.applyDefaults(spec, args); // Validate if validator exists if (spec.validate) { spec.validate(processedArgs, toolName); } return processedArgs; } /** * Initialize the handler (lazy initialization) */ protected async initialize(): Promise<void> { if (this._isInitialized) { return; } await this.onInitialize(); this._isInitialized = true; } /** * Override this method for custom initialization logic */ protected async onInitialize(): Promise<void> { // Default: no-op } /** * Clean up resources when handler is destroyed */ async dispose(): Promise<void> { await this.onDispose(); this._isInitialized = false; } /** * Override this method for custom cleanup logic */ protected async onDispose(): Promise<void> { // Default: no-op } /** * Validate required arguments */ protected validateArgs(args: ToolArguments, required: string[], toolName: string): void { for (const field of required) { if (!args?.[field]) { throw new HandlerError( `${field} is required`, toolName, 'MISSING_ARGUMENT', { required, provided: Object.keys(args || {}) }, ); } } } /** * Create a standardized response */ protected createResponse(data: any, stringify: boolean = true): ToolExecutionResult { return { content: [ { type: 'text', text: stringify ? JSON.stringify(data, null, 2) : data }, ], isError: false, }; } /** * Create an error response */ protected createErrorResponse(error: Error, toolName: string): ToolExecutionResult { this.logger.error(`Error in ${toolName}:`, error); return { content: [ { type: 'text', text: error instanceof HandlerError ? `Error: ${error.message}` : `Error: ${error.message}`, }, ], isError: true, }; } /** * Execute a tool operation with standardized logging and error handling */ protected async executeWithLogging( toolName: string, startTime: number, operation: () => Promise<any>, logMessage?: string, ): Promise<ToolExecutionResult> { try { await this.initialize(); if (logMessage) { this.logger.debug(logMessage); } const result = await operation(); this.logger.timing(toolName, startTime); // Log result metadata for debugging this.logger.debug(`${toolName} completed successfully`, { resultType: typeof result, resultLength: Array.isArray(result) ? result.length : undefined, hasData: result != null, }); return this.createResponse(result); } catch (error) { this.logger.timing(`${toolName}_error`, startTime); return this.createErrorResponse(error as Error, toolName); } } /** * @deprecated Use executeWithLogging instead */ protected async wrap( toolName: string, startTime: number, fn: () => Promise<any>, logMessage?: string, ): Promise<ToolExecutionResult> { return this.executeWithLogging(toolName, startTime, fn, logMessage); } } ``` -------------------------------------------------------------------------------- /docs/dw_order/OrderPaymentInstrument.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order # Class OrderPaymentInstrument ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.customer.EncryptedObject - dw.order.PaymentInstrument - dw.order.OrderPaymentInstrument ## Description Represents any payment instrument used to pay orders, such as credit card or bank transfer. The object defines standard methods for credit card payment, and can be extended by attributes appropriate for other payment methods. ## Properties ### bankAccountDriversLicense **Type:** String (Read Only) The driver's license associated with a bank account if the calling context meets the following criteria: If the method call happens in the context of a storefront request and the current customer is identical to the customer related to the basket or order, and the current protocol is HTTPS. If the method call happens in the context of the business manager and the current user has permission to the Orders module. Otherwise, the method throws an exception. ### bankAccountNumber **Type:** String (Read Only) The account number if the calling context meets the following criteria: If the method call happens in the context of a storefront request and the current customer is identical to the customer related to the basket or order, and the current protocol is HTTPS. If the method call happens in the context of the business manager and the current user has permissions to the Orders module. Otherwise, the method throws an exception. ### capturedAmount **Type:** Money (Read Only) The sum of the captured amounts. The captured amounts are calculated on the fly. Associate a payment capture for an Payment Instrument with an Invoice using Invoice method addCaptureTransaction. ### creditCardNumber **Type:** String (Read Only) The de-crypted creditcard number if the calling context meets the following criteria: If the method call happens in the context of a storefront request and the current authenticated customer is referenced by the basket or order, and the current protocol is HTTPS. If the customer is anonymous, and the order references this customer, and the protocol is secure and the order status is CREATED. If the method call happens in the context of the business manager and the current user has the permission to manage orders. If the payment information has not been masked as a result of the data retention security policy for the site. Otherwise, the method returns the masked credit card number. ### paymentTransaction **Type:** PaymentTransaction (Read Only) The Payment Transaction for this Payment Instrument or null. ### refundedAmount **Type:** Money (Read Only) The sum of the refunded amounts. The refunded amounts are calculated on the fly. Associate a payment refund for an Payment Instrument with an Invoice using Invoice method addRefundTransaction. ## Constructor Summary ## Method Summary ### getBankAccountDriversLicense **Signature:** `getBankAccountDriversLicense() : String` Returns the driver's license associated with a bank account if the calling context meets the following criteria: If the method call happens in the context of a storefront request and the current customer is identical to the customer related to the basket or order, and the current protocol is HTTPS. ### getBankAccountNumber **Signature:** `getBankAccountNumber() : String` Returns the account number if the calling context meets the following criteria: If the method call happens in the context of a storefront request and the current customer is identical to the customer related to the basket or order, and the current protocol is HTTPS. ### getCapturedAmount **Signature:** `getCapturedAmount() : Money` Returns the sum of the captured amounts. ### getCreditCardNumber **Signature:** `getCreditCardNumber() : String` Returns the de-crypted creditcard number if the calling context meets the following criteria: If the method call happens in the context of a storefront request and the current authenticated customer is referenced by the basket or order, and the current protocol is HTTPS. ### getPaymentTransaction **Signature:** `getPaymentTransaction() : PaymentTransaction` Returns the Payment Transaction for this Payment Instrument or null. ### getRefundedAmount **Signature:** `getRefundedAmount() : Money` Returns the sum of the refunded amounts. ## Method Detail ## Method Details ### getBankAccountDriversLicense **Signature:** `getBankAccountDriversLicense() : String` **Description:** Returns the driver's license associated with a bank account if the calling context meets the following criteria: If the method call happens in the context of a storefront request and the current customer is identical to the customer related to the basket or order, and the current protocol is HTTPS. If the method call happens in the context of the business manager and the current user has permission to the Orders module. Otherwise, the method throws an exception. **Returns:** the driver's license number if the calling context meets the necessary criteria. --- ### getBankAccountNumber **Signature:** `getBankAccountNumber() : String` **Description:** Returns the account number if the calling context meets the following criteria: If the method call happens in the context of a storefront request and the current customer is identical to the customer related to the basket or order, and the current protocol is HTTPS. If the method call happens in the context of the business manager and the current user has permissions to the Orders module. Otherwise, the method throws an exception. **Returns:** the account number if the calling context meets the necessary criteria. --- ### getCapturedAmount **Signature:** `getCapturedAmount() : Money` **Description:** Returns the sum of the captured amounts. The captured amounts are calculated on the fly. Associate a payment capture for an Payment Instrument with an Invoice using Invoice method addCaptureTransaction. **Returns:** sum of captured amounts --- ### getCreditCardNumber **Signature:** `getCreditCardNumber() : String` **Description:** Returns the de-crypted creditcard number if the calling context meets the following criteria: If the method call happens in the context of a storefront request and the current authenticated customer is referenced by the basket or order, and the current protocol is HTTPS. If the customer is anonymous, and the order references this customer, and the protocol is secure and the order status is CREATED. If the method call happens in the context of the business manager and the current user has the permission to manage orders. If the payment information has not been masked as a result of the data retention security policy for the site. Otherwise, the method returns the masked credit card number. **Returns:** the de-crypted creditcard number if the calling context meets the necessary criteria. --- ### getPaymentTransaction **Signature:** `getPaymentTransaction() : PaymentTransaction` **Description:** Returns the Payment Transaction for this Payment Instrument or null. **Returns:** the Payment Transaction for this Payment Instrument or null. --- ### getRefundedAmount **Signature:** `getRefundedAmount() : Money` **Description:** Returns the sum of the refunded amounts. The refunded amounts are calculated on the fly. Associate a payment refund for an Payment Instrument with an Invoice using Invoice method addRefundTransaction. **Returns:** sum of refunded amounts --- ``` -------------------------------------------------------------------------------- /tests/servers/sfcc-mock-server/mock-data/ocapi/system-object-attributes-product-expanded.json: -------------------------------------------------------------------------------- ```json { "_v": "23.2", "_type": "object_attribute_definition_search_result", "count": 20, "hits": [ { "_type": "object_attribute_definition", "_resource_state": "47de03c012d48eee975077f45131088fe24f34660ecf4dc69de5737257836fda", "id": "EAN", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/EAN" }, { "_type": "object_attribute_definition", "_resource_state": "d9215260b911efb2f40c78cb1b9a7134feca85bf429a9462371db6a16d22e456", "id": "ID", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/ID" }, { "_type": "object_attribute_definition", "_resource_state": "5d41eb23dc9228d397af90560aaa1b8b0ff825e6d8699a56977366d3534c5cc6", "id": "UPC", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/UPC" }, { "_type": "object_attribute_definition", "_resource_state": "461201495377a8c0e50340bbce3ce929cecfbb74022d1ba87ff3bfeb2501b295", "id": "UUID", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/UUID" }, { "_type": "object_attribute_definition", "_resource_state": "94d3911611a738b687448c2742b6b61216925f45e60627906e871da0d752f35b", "id": "Wool", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/Wool" }, { "_type": "object_attribute_definition", "_resource_state": "f3714641f6cd57c36db45c8976a743e21dafdb52d753ea67013ef9a9209488f3", "id": "available", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/available" }, { "_type": "object_attribute_definition", "_resource_state": "5945247ee819586780982084e8099326c6cc04499492ff82f8603ecb224172d0", "id": "availableForInStorePickup", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/availableForInStorePickup" }, { "_type": "object_attribute_definition", "_resource_state": "835703bec9a082f3525872afaa1d371c985c70359812e1e4a751fb2d9b200df6", "id": "baseImageGroup", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/baseImageGroup" }, { "_type": "object_attribute_definition", "_resource_state": "67a18a0bbc59a1e4dd7e22d3fb6e1b624b9aacb68c4bb1cd18fe5dbe99d3e21b", "id": "bottomType", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/bottomType" }, { "_type": "object_attribute_definition", "_resource_state": "aa8ad7704c3818641e179362b17cdca0b56a411e0b0c2bbcd99689bc54193554", "id": "brand", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/brand" }, { "_type": "object_attribute_definition", "_resource_state": "503a227e5ed4449c29e36df3d093f000f5da55a8c3f15d50136e3a6371a0aa0a", "id": "bundledProducts", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/bundledProducts" }, { "_type": "object_attribute_definition", "_resource_state": "89b49b5c86e3e1b9b7bd6b84e8ea93f5a56e4e2e8f5b0d1b1a3b2c3d4e5f6789", "id": "catalog", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/catalog" }, { "_type": "object_attribute_definition", "_resource_state": "12345678901234567890123456789012345678901234567890123456789012345", "id": "categories", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/categories" }, { "_type": "object_attribute_definition", "_resource_state": "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef", "id": "classificationCategory", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/classificationCategory" }, { "_type": "object_attribute_definition", "_resource_state": "fedcbafedcbafedcbafedcbafedcbafedcbafedcbafedcbafedcbafedcbafedcba", "id": "color", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/color" }, { "_type": "object_attribute_definition", "_resource_state": "1111111111111111111111111111111111111111111111111111111111111111", "id": "creationDate", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/creationDate" }, { "_type": "object_attribute_definition", "_resource_state": "2222222222222222222222222222222222222222222222222222222222222222", "id": "custom", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/custom" }, { "_type": "object_attribute_definition", "_resource_state": "3333333333333333333333333333333333333333333333333333333333333333", "id": "description", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/description" }, { "_type": "object_attribute_definition", "_resource_state": "4444444444444444444444444444444444444444444444444444444444444444", "id": "imageGroups", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/imageGroups" }, { "_type": "object_attribute_definition", "_resource_state": "5555555555555555555555555555555555555555555555555555555555555555", "id": "lastModified", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/lastModified" } ], "next": { "_type": "result_page", "count": 5, "start": 5 }, "query": { "match_all_query": { "_type": "match_all_query" } }, "start": 0, "total": 113, "expandedData": { "brand": { "_type": "object_attribute_definition", "_resource_state": "aa8ad7704c3818641e179362b17cdca0b56a411e0b0c2bbcd99689bc54193554", "creation_date": "2024-02-19T10:18:31.000Z", "display_name": { "de": "Marke", "de-DE": "Marke", "it": "Marca", "fr": "Marque", "zh-CN": "品牌", "es": "Marca", "fr-CA": "Marque", "it-IT": "Marca", "default": "Brand", "ja": "ブランド", "fr-FR": "Marque", "ja-JP": "ブランド", "nl": "Merk" }, "effective_id": "brand", "externally_defined": false, "externally_managed": false, "field_length": 0, "id": "brand", "key": false, "last_modified": "2024-02-19T10:22:33.000Z", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/brand", "localizable": false, "mandatory": false, "min_length": 0, "multi_value_type": false, "order_required": false, "queryable": true, "read_only": false, "requires_encoding": false, "searchable": false, "set_value_type": false, "site_specific": false, "system": true, "value_type": "string", "visible": true } } } ``` -------------------------------------------------------------------------------- /docs/dw_content/ContentSearchRefinements.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.content # Class ContentSearchRefinements ## Inheritance Hierarchy - Object - dw.catalog.SearchRefinements - dw.content.ContentSearchRefinements ## Description This class provides an interface to refinement options for the content asset search. In a typical usage, the client application UI displays the search refinements along with the search results and allows customers to "refine" the results (i.e. limit the results that are shown) by specifying additional criteria, or "relax" (i.e. broaden) the results after previously refining. The two types of content search refinements are: Refine By Folder: Limit the content assets to those assigned to specific child/ancestor folder of the search folder. Refine By Attribute: Limit the content assets to those with specific values for a given attribute. Values may be grouped into "buckets" so that a given set of values are represented as a single refinement option. Rendering a content search refinement UI typically begins with iterating the refinement definitions for the search result. Call SearchRefinements.getRefinementDefinitions() or SearchRefinements.getAllRefinementDefinitions() to retrieve the appropriate collection of refinement definitions. For each definition, display the available refinement values by calling getAllRefinementValues(ContentSearchRefinementDefinition). Depending on the type of the refinement definition, the application must use slightly different logic to display the refinement widgets. For all 2 types, methods in ContentSearchModel are used to generate URLs to render hyperlinks in the UI. When clicked, these links trigger a call to the Search pipelet which in turn applies the appropriate filters to the native search result. ## Properties ### folderRefinementDefinition **Type:** ContentSearchRefinementDefinition (Read Only) The appropriate folder refinement definition based on the search result. The folder refinement definition returned will be the first that can be found traversing the folder tree upward starting at the deepest common folder of the search result. ### matchingFolders **Type:** Collection (Read Only) A collection of matching folders. ## Constructor Summary ## Method Summary ### getAllRefinementValues **Signature:** `getAllRefinementValues(definition : ContentSearchRefinementDefinition) : Collection` Returns a sorted collection of refinement values for the given refinement definition. ### getFolderHits **Signature:** `getFolderHits(folder : Folder) : Number` Returns the number of search hits for the passed folder object. ### getFolderRefinementDefinition **Signature:** `getFolderRefinementDefinition() : ContentSearchRefinementDefinition` Returns the appropriate folder refinement definition based on the search result. ### getMatchingFolders **Signature:** `getMatchingFolders() : Collection` Returns a collection of matching folders. ### getNextLevelFolderRefinementValues **Signature:** `getNextLevelFolderRefinementValues(folder : Folder) : Collection` Returns folder refinement values based on the current search result filtered such that only folder refinements representing children of the given folder are present. ### getRefinementValue **Signature:** `getRefinementValue(definition : ContentSearchRefinementDefinition, value : String) : ContentSearchRefinementValue` Returns the refinement value (incl. ### getRefinementValue **Signature:** `getRefinementValue(name : String, value : String) : ContentSearchRefinementValue` Returns the refinement value (incl. ### getRefinementValues **Signature:** `getRefinementValues(definition : ContentSearchRefinementDefinition) : Collection` Returns a collection of refinement values for the given refinement definition. ## Method Detail ## Method Details ### getAllRefinementValues **Signature:** `getAllRefinementValues(definition : ContentSearchRefinementDefinition) : Collection` **Description:** Returns a sorted collection of refinement values for the given refinement definition. The returned collection includes all refinement values for which the hit count is greater than 0 within the search result when the passed refinement definitions is excluded from filtering the search hits but all other refinement filters are still applied. This is useful for rendering broadening options for the refinement definitions that the search is already refined by. It is important to note that this method does NOT return refinement values independent of the search result. **Parameters:** - `definition`: The refinement definition to return refinement values for. **Returns:** The collection of ContentSearchRefinementValue instances sorted according to the settings of the definition. --- ### getFolderHits **Signature:** `getFolderHits(folder : Folder) : Number` **Description:** Returns the number of search hits for the passed folder object. **Parameters:** - `folder`: Folder object. **Returns:** Number of search hits. --- ### getFolderRefinementDefinition **Signature:** `getFolderRefinementDefinition() : ContentSearchRefinementDefinition` **Description:** Returns the appropriate folder refinement definition based on the search result. The folder refinement definition returned will be the first that can be found traversing the folder tree upward starting at the deepest common folder of the search result. **Returns:** The folder refinement definition or null if none can be found. --- ### getMatchingFolders **Signature:** `getMatchingFolders() : Collection` **Description:** Returns a collection of matching folders. **Returns:** Collection of matching folders. --- ### getNextLevelFolderRefinementValues **Signature:** `getNextLevelFolderRefinementValues(folder : Folder) : Collection` **Description:** Returns folder refinement values based on the current search result filtered such that only folder refinements representing children of the given folder are present. If no folder is given, the method uses the library's root folder. The refinement value content counts represent all hits contained in the library tree starting at the corresponding child folder. **Parameters:** - `folder`: The folder to return child folder refinement values for. **Returns:** The refinement values for all child folders of the given folder. --- ### getRefinementValue **Signature:** `getRefinementValue(definition : ContentSearchRefinementDefinition, value : String) : ContentSearchRefinementValue` **Description:** Returns the refinement value (incl. content hit count) for the given refinement definition and the given (selected) value. **Parameters:** - `definition`: The definition to return the refinement for. - `value`: The value to return the refinement value for. **Returns:** The refinement value. --- ### getRefinementValue **Signature:** `getRefinementValue(name : String, value : String) : ContentSearchRefinementValue` **Description:** Returns the refinement value (incl. content hit count) for the given attribute refinement and the given (selected) value. **Parameters:** - `name`: The name of the refinement attribute. - `value`: The value to return the refinement value for. **Returns:** The refinement value. --- ### getRefinementValues **Signature:** `getRefinementValues(definition : ContentSearchRefinementDefinition) : Collection` **Description:** Returns a collection of refinement values for the given refinement definition. The returned refinement values only include those that are part of the actual search result (i.e. hit count will always be > 0). **Parameters:** - `definition`: The refinement definition to return refinement values for. **Returns:** The collection of refinement values sorted according to the settings of the definition. --- ```