This is page 4 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 -------------------------------------------------------------------------------- /docs/TopLevel/RegExp.md: -------------------------------------------------------------------------------- ```markdown ## Package: TopLevel # Class RegExp ## Inheritance Hierarchy - Object - RegExp ## Description The RegExp object is a static object that generates instances of a regular expression for pattern matching and monitors all regular expressions in the current window or frame. Consult ECMA standards for the format of the pattern strings supported by these regular expressions. ## Properties ### global **Type:** boolean If the regular expression instance has the g modifier, then this property is set to true. ### ignoreCase **Type:** boolean If the regular expression instance has the i modifier, then this property is set to true. ### lastIndex **Type:** Number This is the zero-based index value of the character within the String where the next search for the pattern begins. In a new search, the value is zero. ### multiline **Type:** boolean If a search extends across multiple lines of test, the multiline property is set to true. ### source **Type:** String A String version of the characters used to create the regular expression. The value does not include the forward slash delimiters that surround the expression. ## Constructor Summary RegExp(pattern : String) Constructs the regular expression using the specified pattern. RegExp(pattern : String, attributes : String) Constructs the regular expression using the specified pattern and attributes. ## Method Summary ### exec **Signature:** `exec(string : String) : Array` Performs a search through the specified parameter for the current regular expression and returns an array of match information if successful. ### test **Signature:** `test(string : String) : boolean` Returns true if there is a match of the regular expression anywhere in the specified parameter. ## Constructor Detail ## Method Detail ## Method Details ### exec **Signature:** `exec(string : String) : Array` **Description:** Performs a search through the specified parameter for the current regular expression and returns an array of match information if successful. Returns null if the search produces no results. **Parameters:** - `string`: the String to apply the regular expression. **Returns:** an array of match information if successful, null otherwise. --- ### test **Signature:** `test(string : String) : boolean` **Description:** Returns true if there is a match of the regular expression anywhere in the specified parameter. No additional information is available about the results of the search. **Parameters:** - `string`: the String to apply the regular expression. **Returns:** true if there is a match of the regular expression anywhere in the specified parameter, false otherwise. --- ``` -------------------------------------------------------------------------------- /docs-site/App.tsx: -------------------------------------------------------------------------------- ```typescript import React from 'react'; import type { RouteRecord } from 'vite-react-ssg'; import { Navigate } from 'react-router-dom'; import Layout from './components/Layout'; import HomePage from './pages/HomePage'; import ConfigurationPage from './pages/ConfigurationPage'; import AIInterfacesPage from './pages/AIInterfacesPage'; import FeaturesPage from './pages/FeaturesPage'; import ToolsPage from './pages/ToolsPage'; import ExamplesPage from './pages/ExamplesPage'; import SecurityPage from './pages/SecurityPage'; import DevelopmentPage from './pages/DevelopmentPage'; import TroubleshootingPage from './pages/TroubleshootingPage'; export const routes: RouteRecord[] = [ { path: '/', element: <Layout />, children: [ { index: true, element: <HomePage />, }, // Routes with trailing slashes { path: 'configuration/', element: <ConfigurationPage />, }, { path: 'ai-interfaces/', element: <AIInterfacesPage />, }, { path: 'features/', element: <FeaturesPage />, }, { path: 'tools/', element: <ToolsPage />, }, { path: 'examples/', element: <ExamplesPage />, }, { path: 'security/', element: <SecurityPage />, }, { path: 'development/', element: <DevelopmentPage />, }, { path: 'troubleshooting/', element: <TroubleshootingPage />, }, // Redirects from non-trailing slash URLs to trailing slash URLs { path: 'configuration', element: <Navigate to="/configuration/" replace />, }, { path: 'ai-interfaces', element: <Navigate to="/ai-interfaces/" replace />, }, { path: 'features', element: <Navigate to="/features/" replace />, }, { path: 'tools', element: <Navigate to="/tools/" replace />, }, { path: 'examples', element: <Navigate to="/examples/" replace />, }, { path: 'security', element: <Navigate to="/security/" replace />, }, { path: 'development', element: <Navigate to="/development/" replace />, }, { path: 'troubleshooting', element: <Navigate to="/troubleshooting/" replace />, }, // Redirect old installation path to AI interfaces { path: 'installation', element: <Navigate to="/ai-interfaces/" replace />, }, { path: 'installation/', element: <Navigate to="/ai-interfaces/" replace />, }, ], }, ]; export default routes; ``` -------------------------------------------------------------------------------- /docs/dw_web/PageMetaTag.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.web # Class PageMetaTag ## Inheritance Hierarchy - Object - dw.web.PageMetaTag ## Description Page meta tags are used in HTML documents to provide structured data about a web page. They are usually part of the head section. Common tags are for example robots, description or social tags like open graph (e.g. 'og:title'). Page meta tags can be obtained within: home page context Site detail page context Product Content listing page context ProductSearchModel ContentSearchModel and can be set at PageMetaData container object, which is always available in the pipeline dictionary and is used as transfer object to fill the head area with meaningful page meta tag elements. ## Properties ### content **Type:** String (Read Only) The page meta tag content. ### ID **Type:** String (Read Only) The page meta tag ID. ### name **Type:** boolean (Read Only) Returns true if the page meta tag type is name, false otherwise. ### property **Type:** boolean (Read Only) Returns true if the page meta tag type is property, false otherwise. ### title **Type:** boolean (Read Only) Returns true if the page meta tag type is title, false otherwise. ## Constructor Summary ## Method Summary ### getContent **Signature:** `getContent() : String` Returns the page meta tag content. ### getID **Signature:** `getID() : String` Returns the page meta tag ID. ### isName **Signature:** `isName() : boolean` Returns true if the page meta tag type is name, false otherwise. ### isProperty **Signature:** `isProperty() : boolean` Returns true if the page meta tag type is property, false otherwise. ### isTitle **Signature:** `isTitle() : boolean` Returns true if the page meta tag type is title, false otherwise. ## Method Detail ## Method Details ### getContent **Signature:** `getContent() : String` **Description:** Returns the page meta tag content. **Returns:** page meta tag content --- ### getID **Signature:** `getID() : String` **Description:** Returns the page meta tag ID. **Returns:** page meta tag ID --- ### isName **Signature:** `isName() : boolean` **Description:** Returns true if the page meta tag type is name, false otherwise. **Returns:** true if the page meta tag type is name, false otherwise --- ### isProperty **Signature:** `isProperty() : boolean` **Description:** Returns true if the page meta tag type is property, false otherwise. **Returns:** true if the page meta tag type is property, false otherwise --- ### isTitle **Signature:** `isTitle() : boolean` **Description:** Returns true if the page meta tag type is title, false otherwise. **Returns:** true if the page meta tag type is title, false otherwise --- ``` -------------------------------------------------------------------------------- /docs/dw_catalog/ProductInventoryMgr.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.catalog # Class ProductInventoryMgr ## Inheritance Hierarchy - Object - dw.catalog.ProductInventoryMgr ## Description This manager provides access to inventory-related objects. ## Constants ### INTEGRATIONMODE_B2C **Type:** String = "B2C" Integration mode 'B2C' - using B2C inventory, no integration with Omnichannel Inventory ### INTEGRATIONMODE_OCI **Type:** String = "OCI" Integration mode 'OCI' - integration with Omnichannel Inventory enabled ### INTEGRATIONMODE_OCI_CACHE **Type:** String = "OCI_CACHE" Integration mode 'OCI_CACHE' - using B2C inventory, initializing cache as preparation for integration with Omnichannel Inventory ## Properties ### inventoryIntegrationMode **Type:** String (Read Only) The current inventory integration mode as one of INTEGRATIONMODE_B2C INTEGRATIONMODE_OCI_CACHE INTEGRATIONMODE_OCI ### inventoryList **Type:** ProductInventoryList (Read Only) The inventory list assigned to the current site or null if no inventory list is assigned to the current site. ## Constructor Summary ## Method Summary ### getInventoryIntegrationMode **Signature:** `static getInventoryIntegrationMode() : String` Returns the current inventory integration mode as one of INTEGRATIONMODE_B2C INTEGRATIONMODE_OCI_CACHE INTEGRATIONMODE_OCI ### getInventoryList **Signature:** `static getInventoryList() : ProductInventoryList` Returns the inventory list assigned to the current site or null if no inventory list is assigned to the current site. ### getInventoryList **Signature:** `static getInventoryList(listID : String) : ProductInventoryList` Returns the inventory list with the passed ID or null if no inventory list exists with that ID. ## Method Detail ## Method Details ### getInventoryIntegrationMode **Signature:** `static getInventoryIntegrationMode() : String` **Description:** Returns the current inventory integration mode as one of INTEGRATIONMODE_B2C INTEGRATIONMODE_OCI_CACHE INTEGRATIONMODE_OCI **Returns:** The current inventory integration mode as a constant String. --- ### getInventoryList **Signature:** `static getInventoryList() : ProductInventoryList` **Description:** Returns the inventory list assigned to the current site or null if no inventory list is assigned to the current site. **Returns:** The ProductInventoryList assigned to the current site, or null. --- ### getInventoryList **Signature:** `static getInventoryList(listID : String) : ProductInventoryList` **Description:** Returns the inventory list with the passed ID or null if no inventory list exists with that ID. **Parameters:** - `listID`: The ID of the inventory list to retrieve. **Returns:** The ProductInventoryList identified by listID, or null. --- ``` -------------------------------------------------------------------------------- /docs/dw_job/JobExecution.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.job # Class JobExecution ## Inheritance Hierarchy - Object - dw.job.JobExecution ## Description Represents an execution of a job. The job execution can be accessed from a JobStepExecution via JobStepExecution.getJobExecution(). If a pipeline is used to implement a step the step execution is available in the pipeline dictionary under the key 'JobStepExecution'. If a script module is used to implement a step the step execution is available as the second parameter of the module's function that is used to execute the step, e.g.: ```javascript ... exports.execute( parameters, stepExecution) { ... var jobExecution = stepExecution.getJobExecution(); ... } ... ``` ## Properties ### context **Type:** Map (Read Only) The job context which can be used to share data between steps. NOTE: Steps should be self-contained, the job context should only be used when necessary and with caution. If two steps which are running in parallel in the same job store data in the job context using the same key the result is undefined. Don't add any complex data to the job context since only simple data types are supported (for example, String and Integer). ### ID **Type:** String (Read Only) The ID of this job execution. ### jobID **Type:** String (Read Only) The ID of the job this job execution belongs to. ## Constructor Summary This class does not have a constructor, so you cannot create it directly. ## Method Summary ### getContext **Signature:** `getContext() : Map` Returns the job context which can be used to share data between steps. ### getID **Signature:** `getID() : String` Returns the ID of this job execution. ### getJobID **Signature:** `getJobID() : String` Returns the ID of the job this job execution belongs to. ## Method Detail ## Method Details ### getContext **Signature:** `getContext() : Map` **Description:** Returns the job context which can be used to share data between steps. NOTE: Steps should be self-contained, the job context should only be used when necessary and with caution. If two steps which are running in parallel in the same job store data in the job context using the same key the result is undefined. Don't add any complex data to the job context since only simple data types are supported (for example, String and Integer). **Returns:** the map that represents the job context. --- ### getID **Signature:** `getID() : String` **Description:** Returns the ID of this job execution. **Returns:** the ID of this job execution. --- ### getJobID **Signature:** `getJobID() : String` **Description:** Returns the ID of the job this job execution belongs to. **Returns:** the ID of the job this job execution belongs to. --- ``` -------------------------------------------------------------------------------- /src/services/file-system-service.ts: -------------------------------------------------------------------------------- ```typescript /** * File System Service Interface and Implementation * * Provides an abstraction layer over Node.js file system operations * to enable easier testing and better dependency injection. */ import * as fs from 'fs/promises'; /** * Interface for file system operations */ export interface IFileSystemService { /** * Check if a file or directory exists */ exists(path: string): Promise<boolean>; /** * Create a directory recursively */ mkdir(path: string, options?: { recursive?: boolean }): Promise<void>; /** * Write content to a file */ writeFile(path: string, content: string): Promise<void>; /** * Read content from a file */ readFile(path: string): Promise<string>; /** * Check access to a file or directory */ access(path: string): Promise<void>; } /** * Production implementation of file system service */ export class FileSystemService implements IFileSystemService { async exists(path: string): Promise<boolean> { try { await fs.access(path); return true; } catch { return false; } } async mkdir(path: string, options?: { recursive?: boolean }): Promise<void> { await fs.mkdir(path, options); } async writeFile(path: string, content: string): Promise<void> { await fs.writeFile(path, content); } async readFile(path: string): Promise<string> { return await fs.readFile(path, 'utf-8'); } async access(path: string): Promise<void> { await fs.access(path); } } /** * Mock implementation for testing */ export class MockFileSystemService implements IFileSystemService { private mockFiles: Map<string, string> = new Map(); private mockDirectories: Set<string> = new Set(); // Mock methods for testing setup setMockFile(path: string, content: string): void { this.mockFiles.set(path, content); } setMockDirectory(path: string): void { this.mockDirectories.add(path); } clearMocks(): void { this.mockFiles.clear(); this.mockDirectories.clear(); } // Service implementation async exists(path: string): Promise<boolean> { return this.mockFiles.has(path) || this.mockDirectories.has(path); } async mkdir(path: string, _options?: { recursive?: boolean }): Promise<void> { this.mockDirectories.add(path); } async writeFile(path: string, content: string): Promise<void> { this.mockFiles.set(path, content); } async readFile(path: string): Promise<string> { const content = this.mockFiles.get(path); if (content === undefined) { throw new Error(`File not found: ${path}`); } return content; } async access(path: string): Promise<void> { if (!(await this.exists(path))) { throw new Error(`Path not accessible: ${path}`); } } } ``` -------------------------------------------------------------------------------- /docs/dw_rpc/WebReference.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.rpc # Class WebReference ## Inheritance Hierarchy - Object - dw.rpc.WebReference ## Description Represents a web service defined in a WSDL file. The implementation is backed by a JAX-RPC framework. You should use the newer dw.ws package and WebReference2 class instead, which is based on JAX-WS. Use the Services module in Business Manager to set timeout values, not the methods for this class. The Services module provides better analytics and timeout management. To create an instance of a WebReference object, in a B2C Commerce Script file, reference a WSDL file in the webreferences directory and request the service Stub using one of the get service methods. For example, if your WSDL file is MyWSDL.wsdl, to create an instance of WebReference and access the Stub: var webref : WebReference = webreferences.MyWSDL; var stub : Stub = webref.getDefaultService(); Note: script classes representing your WSDL file are are generated by the platform and then placed in the WebReferences package. You do not need to include the importPackage statement in your B2C Commerce Script file to use classes in the WebReferences package. ## Properties ### defaultService **Type:** Stub (Read Only) The default service of the WebReference object. If you have more than one service defined in your WSDL, the default service is the first service alphabetically. If the service has multiple ports defined, the default service uses the SOAP port name that is first alphabetically. ## Constructor Summary WebReference() ## Method Summary ### getDefaultService **Signature:** `getDefaultService() : Stub` Returns the default service of the WebReference object. ### getService **Signature:** `getService(service : String, port : String) : Stub` Returns a specific service from this WebReference. ## Constructor Detail ## Method Detail ## Method Details ### getDefaultService **Signature:** `getDefaultService() : Stub` **Description:** Returns the default service of the WebReference object. If you have more than one service defined in your WSDL, the default service is the first service alphabetically. If the service has multiple ports defined, the default service uses the SOAP port name that is first alphabetically. **Deprecated:** use webreferences2 instead **Returns:** the default service of the WebReference object. --- ### getService **Signature:** `getService(service : String, port : String) : Stub` **Description:** Returns a specific service from this WebReference. **Deprecated:** use webreferences2 instead **Parameters:** - `service`: the service to locate. - `port`: the port name to use. var port = webref.getService("SampleServiceName","SamplePortName"); **Returns:** a specific service from this WebReference. --- ``` -------------------------------------------------------------------------------- /docs/dw_web/FormList.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.web # Class FormList ## Inheritance Hierarchy - Object - dw.web.FormElement - dw.web.FormGroup - dw.web.FormList ## Description Represents a list of forms. ## Properties ### selectManyItems **Type:** List (Read Only) The selected list items if the list is configured to support selection of items. ### selectManyObjects **Type:** List (Read Only) A list of all selected objects if the list is configured to support the selection of items. The objects are the objects that were bound to each row. ### selectOneItem **Type:** FormListItem (Read Only) The default list item if the list is configured to support the selection of a default item. ### selectOneObject **Type:** Object (Read Only) The selected object if the list is configured to support the selection of a default item. The object is the object bound to the item. ## Constructor Summary ## Method Summary ### getSelectManyItems **Signature:** `getSelectManyItems() : List` returns the selected list items if the list is configured to support selection of items. ### getSelectManyObjects **Signature:** `getSelectManyObjects() : List` Returns a list of all selected objects if the list is configured to support the selection of items. ### getSelectOneItem **Signature:** `getSelectOneItem() : FormListItem` Returns the default list item if the list is configured to support the selection of a default item. ### getSelectOneObject **Signature:** `getSelectOneObject() : Object` Returns the selected object if the list is configured to support the selection of a default item. ## Method Detail ## Method Details ### getSelectManyItems **Signature:** `getSelectManyItems() : List` **Description:** returns the selected list items if the list is configured to support selection of items. **Returns:** a List of FormListItem elements or null if no selection was configured for the form. --- ### getSelectManyObjects **Signature:** `getSelectManyObjects() : List` **Description:** Returns a list of all selected objects if the list is configured to support the selection of items. The objects are the objects that were bound to each row. **Returns:** a List of objects or null if no selection was configured for the form. --- ### getSelectOneItem **Signature:** `getSelectOneItem() : FormListItem` **Description:** Returns the default list item if the list is configured to support the selection of a default item. **Returns:** the default FormListItem elements or null if no selection was configured --- ### getSelectOneObject **Signature:** `getSelectOneObject() : Object` **Description:** Returns the selected object if the list is configured to support the selection of a default item. The object is the object bound to the item. **Returns:** the selected object. --- ``` -------------------------------------------------------------------------------- /docs/dw_extensions.paymentrequest/PaymentRequestHookResult.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.extensions.paymentrequest # Class PaymentRequestHookResult ## Inheritance Hierarchy - Object - dw.extensions.paymentrequest.PaymentRequestHookResult ## Description Result of a hook handling a Payment Request request ## Properties ### eventDetail **Type:** Object (Read Only) Detail to the JS custom event to dispatch in response to this result. ### eventName **Type:** String (Read Only) Name of the JS custom event to dispatch in response to this result. ### redirect **Type:** URL (Read Only) URL to navigate to in response to this result. ### status **Type:** Status (Read Only) Status describing the outcome of this result. ## Constructor Summary PaymentRequestHookResult(status : Status, redirect : URL) Constructs a result with the given outcome information. ## Method Summary ### getEventDetail **Signature:** `getEventDetail() : Object` Detail to the JS custom event to dispatch in response to this result. ### getEventName **Signature:** `getEventName() : String` Name of the JS custom event to dispatch in response to this result. ### getRedirect **Signature:** `getRedirect() : URL` URL to navigate to in response to this result. ### getStatus **Signature:** `getStatus() : Status` Status describing the outcome of this result. ### setEvent **Signature:** `setEvent(name : String) : void` Sets the name of the JS custom event to dispatch in response to this result. ### setEvent **Signature:** `setEvent(name : String, detail : Object) : void` Sets the name and detail of the JS custom event to dispatch in response to this result. ## Constructor Detail ## Method Detail ## Method Details ### getEventDetail **Signature:** `getEventDetail() : Object` **Description:** Detail to the JS custom event to dispatch in response to this result. **Returns:** event detail --- ### getEventName **Signature:** `getEventName() : String` **Description:** Name of the JS custom event to dispatch in response to this result. **Returns:** event name --- ### getRedirect **Signature:** `getRedirect() : URL` **Description:** URL to navigate to in response to this result. **Returns:** redirect URL --- ### getStatus **Signature:** `getStatus() : Status` **Description:** Status describing the outcome of this result. **Returns:** status of this result --- ### setEvent **Signature:** `setEvent(name : String) : void` **Description:** Sets the name of the JS custom event to dispatch in response to this result. **Parameters:** - `name`: JS custom event name --- ### setEvent **Signature:** `setEvent(name : String, detail : Object) : void` **Description:** Sets the name and detail of the JS custom event to dispatch in response to this result. **Parameters:** - `name`: JS custom event name - `detail`: JS custom event detail --- ``` -------------------------------------------------------------------------------- /docs/dw_net/WebDAVFileInfo.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.net # Class WebDAVFileInfo ## Inheritance Hierarchy - Object - dw.net.WebDAVFileInfo ## Description Simple class representing a file on a remote WebDAV location. The class possesses only read-only attributes of the file and does not permit any manipulation of the file itself. Instances of this class are returned by WebDAVClient.propfind(String) which is used to get a listing of files in a WebDAV directory. Note: when this class is used with sensitive data, be careful in persisting sensitive information to disk. ## Properties ### contentType **Type:** String (Read Only) The content type of the file. ### creationDate **Type:** Date (Read Only) The creationDate of the file. ### directory **Type:** boolean (Read Only) Identifies if the file is a directory. ### name **Type:** String (Read Only) The name of the file. ### path **Type:** String (Read Only) The path of the file. ### size **Type:** Number (Read Only) The size of the file. ## Constructor Summary ## Method Summary ### getContentType **Signature:** `getContentType() : String` Returns the content type of the file. ### getCreationDate **Signature:** `getCreationDate() : Date` Returns the creationDate of the file. ### getName **Signature:** `getName() : String` Returns the name of the file. ### getPath **Signature:** `getPath() : String` Returns the path of the file. ### getSize **Signature:** `getSize() : Number` Returns the size of the file. ### isDirectory **Signature:** `isDirectory() : boolean` Identifies if the file is a directory. ### lastModified **Signature:** `lastModified() : Date` Returns the lastModified date of the file. ## Method Detail ## Method Details ### getContentType **Signature:** `getContentType() : String` **Description:** Returns the content type of the file. **Returns:** the content type of the file. --- ### getCreationDate **Signature:** `getCreationDate() : Date` **Description:** Returns the creationDate of the file. **Returns:** the creationDate of the file. --- ### getName **Signature:** `getName() : String` **Description:** Returns the name of the file. **Returns:** the name of the file. --- ### getPath **Signature:** `getPath() : String` **Description:** Returns the path of the file. **Returns:** the path of the file. --- ### getSize **Signature:** `getSize() : Number` **Description:** Returns the size of the file. **Returns:** the size of the file. --- ### isDirectory **Signature:** `isDirectory() : boolean` **Description:** Identifies if the file is a directory. **Returns:** true if the file is a directory, false otherwise. --- ### lastModified **Signature:** `lastModified() : Date` **Description:** Returns the lastModified date of the file. **Returns:** the lastModified date of the file. --- ``` -------------------------------------------------------------------------------- /docs/dw_order/SumItem.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order # Class SumItem ## Inheritance Hierarchy - Object - dw.order.SumItem ## Description Container used to represent an subtotal or grandtotal item which contains various prices and a tax breakdown held in a collection of tax-items. Usage example: var invoice : Invoice = ...; var productNet = invoice.productSubTotal.netPrice; var serviceNet = invoice.serviceSubTotal.netPrice; var grandNet = invoice.grandTotal.netPrice; var grandTax = invoice.grandTotal.tax; var grandGross = invoice.grandTotal.grossPrice; # tax breakdown for each(taxItem : TaxItem in invoice.grandTotal.taxItems) { var tax : Money = taxItem.amount; var taxGroup : TaxGroup = taxItem.taxGroup; var rate : Double = taxGroup.rate; var caption :String = taxGroup.caption; var taxType :String = taxGroup.taxType; } ## Properties ### grossPrice **Type:** Money (Read Only) Gross price of SumItem. ### netPrice **Type:** Money (Read Only) Net price of SumItem. ### tax **Type:** Money (Read Only) Total tax for SumItem. ### taxBasis **Type:** Money (Read Only) Price of entire SumItem on which tax calculation is based. Same as getNetPrice() or getGrossPrice() depending on whether the order is based on net or gross prices. ### taxItems **Type:** Collection (Read Only) Tax items representing a tax breakdown for the SumItem. ## Constructor Summary ## Method Summary ### getGrossPrice **Signature:** `getGrossPrice() : Money` Gross price of SumItem. ### getNetPrice **Signature:** `getNetPrice() : Money` Net price of SumItem. ### getTax **Signature:** `getTax() : Money` Total tax for SumItem. ### getTaxBasis **Signature:** `getTaxBasis() : Money` Price of entire SumItem on which tax calculation is based. ### getTaxItems **Signature:** `getTaxItems() : Collection` Tax items representing a tax breakdown for the SumItem. ## Method Detail ## Method Details ### getGrossPrice **Signature:** `getGrossPrice() : Money` **Description:** Gross price of SumItem. **Returns:** Gross price of SumItem. --- ### getNetPrice **Signature:** `getNetPrice() : Money` **Description:** Net price of SumItem. **Returns:** Net price of SumItem. --- ### getTax **Signature:** `getTax() : Money` **Description:** Total tax for SumItem. **Returns:** Total tax for SumItem. --- ### getTaxBasis **Signature:** `getTaxBasis() : Money` **Description:** Price of entire SumItem on which tax calculation is based. Same as getNetPrice() or getGrossPrice() depending on whether the order is based on net or gross prices. **Returns:** Price of entire item on which tax calculation is based --- ### getTaxItems **Signature:** `getTaxItems() : Collection` **Description:** Tax items representing a tax breakdown for the SumItem. **Returns:** tax items representing a tax breakdown for the SumItem **See Also:** TaxItem --- ``` -------------------------------------------------------------------------------- /src/utils/log-tool-constants.ts: -------------------------------------------------------------------------------- ```typescript /** * Shared constants for log tool handlers * Centralizes defaults, types, and configuration */ // Log levels enum for type safety export enum LogLevel { ERROR = 'error', WARN = 'warn', INFO = 'info', DEBUG = 'debug', ALL = 'all' } // Default limits for different tool types export const DEFAULT_LIMITS = { latest: 10, search: 20, jobEntries: 50, jobSearch: 20, jobFiles: 10, } as const; // Tool name sets for O(1) lookup export const LOG_TOOL_NAMES_SET = new Set([ 'get_latest_error', 'get_latest_warn', 'get_latest_info', 'get_latest_debug', 'summarize_logs', 'search_logs', 'list_log_files', 'get_log_file_contents', ] as const); export const JOB_LOG_TOOL_NAMES_SET = new Set([ 'get_latest_job_log_files', 'search_job_logs_by_name', 'get_job_log_entries', 'search_job_logs', 'get_job_execution_summary', ] as const); // Type definitions export type LogToolName = 'get_latest_error' | 'get_latest_warn' | 'get_latest_info' | 'get_latest_debug' | 'summarize_logs' | 'search_logs' | 'list_log_files' | 'get_log_file_contents'; export type JobLogToolName = 'get_latest_job_log_files' | 'search_job_logs_by_name' | 'get_job_log_entries' | 'search_job_logs' | 'get_job_execution_summary'; // Typed argument interfaces for each tool export type LogToolArgs = | { tool: 'get_latest_error' | 'get_latest_warn' | 'get_latest_info' | 'get_latest_debug'; limit?: number; date?: string } | { tool: 'summarize_logs'; date?: string } | { tool: 'search_logs'; pattern: string; logLevel?: LogLevel; limit?: number; date?: string } | { tool: 'list_log_files' } | { tool: 'get_log_file_contents'; filename: string; maxBytes?: number; tailOnly?: boolean }; export type JobLogToolArgs = | { tool: 'get_latest_job_log_files'; limit?: number } | { tool: 'search_job_logs_by_name'; jobName: string; limit?: number } | { tool: 'get_job_log_entries'; level?: LogLevel; limit?: number; jobName?: string } | { tool: 'search_job_logs'; pattern: string; level?: LogLevel; limit?: number; jobName?: string } | { tool: 'get_job_execution_summary'; jobName: string }; // Helper functions export function getLimit(providedLimit: number | undefined, toolType: keyof typeof DEFAULT_LIMITS): number { return providedLimit ?? DEFAULT_LIMITS[toolType]; } export function isValidLogLevel(level: string): level is LogLevel { return Object.values(LogLevel).includes(level as LogLevel); } export function deriveLogLevel(toolName: string, argsLevel?: string): LogLevel { if (argsLevel && isValidLogLevel(argsLevel)) { return argsLevel as LogLevel; } // Extract level from tool name for get_latest_* tools const match = toolName.match(/get_latest_(\w+)/); if (match && isValidLogLevel(match[1])) { return match[1] as LogLevel; } return LogLevel.ALL; } ``` -------------------------------------------------------------------------------- /docs/TopLevel/BigInt.md: -------------------------------------------------------------------------------- ```markdown ## Package: TopLevel # Class BigInt ## Inheritance Hierarchy - Object - BigInt ## Description A BigInt object is a wrapper for a primitive bigint value. bigint values can be numbers too large to be stored as number values. A bigint literal in code is an integer number with an appended n. Example: var hugeNumber = 1245678901234567890n; var hugeNumberObject = BigInt( hugeNumber ); ## Constructor Summary BigInt() Constructs a BigInt with value 0. BigInt(value : BigInt) Constructs a new BigInt using the specified BigInt. BigInt(value : String) Constructs a BigInt using the specified value. ## Method Summary ### asIntN **Signature:** `static asIntN(bits : Number, value : BigInt) : BigInt` Clamps the given BigInt value to a signed integer with a given precision. ### asUintN **Signature:** `static asUintN(bits : Number, value : BigInt) : BigInt` Clamps the given BigInt value to an unsigned integer with a given precision. ### toLocaleString **Signature:** `toLocaleString() : String` Converts this BigInt to a String using local number formatting conventions. ### toString **Signature:** `toString() : String` A String representation of this BigInt. ### toString **Signature:** `toString(radix : Number) : String` Converts the BigInt into a string using the specified radix (base). ## Constructor Detail ## Method Detail ## Method Details ### asIntN **Signature:** `static asIntN(bits : Number, value : BigInt) : BigInt` **Description:** Clamps the given BigInt value to a signed integer with a given precision. **Parameters:** - `bits`: Number of bits required for resulting integer. - `value`: The value to be clamped to the given number of bits. **Returns:** The value modulo 2bits, as a signed integer. --- ### asUintN **Signature:** `static asUintN(bits : Number, value : BigInt) : BigInt` **Description:** Clamps the given BigInt value to an unsigned integer with a given precision. **Parameters:** - `bits`: Number of bits required for resulting integer. - `value`: The value to be clamped to the given number of bits. **Returns:** The value modulo 2bits, as an unsigned integer. --- ### toLocaleString **Signature:** `toLocaleString() : String` **Description:** Converts this BigInt to a String using local number formatting conventions. The current implementation actually only returns the same as toString(). **Returns:** a String using local number formatting conventions. --- ### toString **Signature:** `toString() : String` **Description:** A String representation of this BigInt. **Returns:** a String representation of this BigInt. --- ### toString **Signature:** `toString(radix : Number) : String` **Description:** Converts the BigInt into a string using the specified radix (base). **Parameters:** - `radix`: the radix to use. **Returns:** a String representation of this BigInt. --- ``` -------------------------------------------------------------------------------- /docs/TopLevel/Module.md: -------------------------------------------------------------------------------- ```markdown ## Package: TopLevel # Class Module ## Inheritance Hierarchy - Object - Module ## Description CommonJS modules are JavaScript files that are loaded using the require(String) function. This function returns a module object, which wraps the script code from the file. Within a module implementation, the module object can be accessed via the module variable. A module has a unique absolute id. The same module may be resolved by require(String) for different path arguments, like relative paths (starting with "./" or "../"), or absolute paths. See the documentation of require for more details about the lookup procedure. Every module object has an exports property which can be used by the module implementation to expose its public functions or properties. Only functions and properties that are explicitly exported are accessible from other modules, all others are private and not visible. For convenience, the global exports variable is by default also initialized with the module.exports property of the current module. In the most simple case, module elements can be exposed by adding them to the exports object, like: // Greeting.js exports.sayHello = function() { return 'Hello World!'; }; This is equivalent to: // Greeting.js module.exports.sayHello = function() { return 'Hello World!'; }; With the above implementation, a caller (for example another module in the same directory) could call the module function like this: var message = require('./Greeting').sayHello(); It is also possible to replace the whole module exports object with a completely different value, for example with a function: // Greeting.js module.exports = function sayHello() { return 'Hi!'; } Now the result of require would be a function, which can be invoked directly like: var message = require('./Greeting')(); This construction can be used for exporting constructor functions, so that a module becomes something like a class: // Greeting.js function Greeting() { this.message = 'Hi!'; } Greeting.prototype.getMessage = function() { return this.message; } module.exports = Greeting; which would be used like: var Greeting = require('./Greeting'); var m = new Greeting().getMessage(); ## Properties ### cartridge **Type:** String The name of the cartridge which contains the module. ### exports **Type:** Object The exports of the module. ### id **Type:** String The absolute, normalized id of the module, which uniquely identifies it. A call to the global.require(String) function with this id would resolve this module. ### superModule **Type:** Module The module (if exists) that is overridden by this module. The super module would have the same path as the current module but its code location would be checked later in the lookup sequence. This property is useful to reuse functionality implemented in overridden modules. ## Constructor Summary ## Method Summary ``` -------------------------------------------------------------------------------- /docs/sfra/billing.md: -------------------------------------------------------------------------------- ```markdown # SFRA Billing Model ## Overview The Billing model represents billing information for the current basket or order in SFRA applications. It provides a simple structure for managing billing address, payment information, and address associations. ## Constructor ```javascript function billing(addressModel, paymentModel, associatedAddressId) ``` Creates a Billing model instance with billing address, payment, and address association information. ### Parameters - `addressModel` (Object) - The billing address of the current basket - `paymentModel` (Object) - Payment information for the current basket - `associatedAddressId` (string) - The matching ID of the shipping or customer address ## Properties ### billingAddress **Type:** Object The billing address model containing complete address information including: - Address lines, city, state, postal code - Customer name and contact information - Country code and other address details ### payment **Type:** Object Payment model containing payment method information such as: - Credit card details (masked) - Payment processor information - Payment method type - Payment instrument details ### matchingAddressId **Type:** string The ID that matches this billing address to either: - A shipping address (if billing and shipping are the same) - A saved customer address - null if it's a new address ## Usage Example ```javascript var BillingModel = require('*/cartridge/models/billing'); var AddressModel = require('*/cartridge/models/address'); var PaymentModel = require('*/cartridge/models/payment'); // Create address and payment models var billingAddress = new AddressModel(basket.billingAddress); var paymentInfo = new PaymentModel(basket, customer); var matchingId = getMatchingAddressId(basket.billingAddress); // Create billing model var billing = new BillingModel(billingAddress, paymentInfo, matchingId); // Access billing properties console.log(billing.billingAddress.firstName); console.log(billing.payment.selectedPaymentInstruments); console.log(billing.matchingAddressId); ``` ## Address Matching The `matchingAddressId` property helps determine: - If the billing address matches a shipping address - If the billing address matches a saved customer address - Whether to show "same as shipping" options in the UI - Address management and selection logic ## Notes - Simple container model that aggregates billing-related information - Used extensively in checkout and order processing - Address matching enables UI optimizations like "same as shipping" - Works with both new and saved addresses - Integrates with payment processing workflows ## Related Models - **AddressModel** - Used for billing address formatting - **PaymentModel** - Used for payment information - **OrderModel** - Uses billing model for order information - **Cart Model** - May include billing information during checkout ``` -------------------------------------------------------------------------------- /src/clients/docs/referenced-types-extractor.ts: -------------------------------------------------------------------------------- ```typescript /** * Referenced Types Extractor * * Responsible for extracting referenced types from SFCC class documentation * content. Analyzes property types, method signatures, return types, and * parameter types to identify related classes. * * Single Responsibility: Type reference extraction from documentation content */ export class ReferencedTypesExtractor { /** * Parse markdown content and extract referenced types from a class */ static extractReferencedTypes(content: string): string[] { const referencedTypes = new Set<string>(); const lines = content.split('\n'); for (const line of lines) { // Extract types from property definitions const propTypeMatch = line.match(/\*\*Type:\*\*\s*([A-Za-z][A-Za-z0-9.]*)/); if (propTypeMatch) { const type = propTypeMatch[1]; // Only include SFCC types (those that start with uppercase or contain dots) if (this.isSFCCType(type)) { referencedTypes.add(type); } } // Extract return types from method signatures const methodReturnMatch = line.match(/:\s*([A-Za-z][A-Za-z0-9.]*)\s*$/); if (methodReturnMatch) { const type = methodReturnMatch[1]; if (this.isSFCCType(type)) { referencedTypes.add(type); } } // Extract parameter types from method signatures const paramMatches = line.match(/\(\s*([^)]+)\s*\)/); if (paramMatches) { const params = paramMatches[1]; const typeMatches = params.match(/:\s*([A-Za-z][A-Za-z0-9.]*)/g); if (typeMatches) { typeMatches.forEach(match => { const type = match.replace(/:\s*/, ''); if (this.isSFCCType(type)) { referencedTypes.add(type); } }); } } } return Array.from(referencedTypes); } /** * Check if a type name represents an SFCC type * SFCC types typically start with uppercase or contain dots */ private static isSFCCType(type: string): boolean { return /^[A-Z]/.test(type) || type.includes('.'); } /** * Filter out circular references and self-references */ static filterCircularReferences( referencedTypes: string[], currentClassName: string, ): string[] { return referencedTypes.filter(typeName => { // Skip if it's the same class to avoid circular references if (typeName === currentClassName || typeName.endsWith(`.${currentClassName}`)) { return false; } return true; }); } /** * Extract and filter referenced types with circular reference protection */ static extractFilteredReferencedTypes( content: string, currentClassName: string, ): string[] { const referencedTypes = this.extractReferencedTypes(content); return this.filterCircularReferences(referencedTypes, currentClassName); } } ``` -------------------------------------------------------------------------------- /docs/dw_svc/ServiceProfile.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.svc # Class ServiceProfile ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.svc.ServiceProfile ## Description Configuration object for Service Profiles. ## Properties ### cbCalls **Type:** Number (Read Only) The maximum number of errors in an interval allowed by the circuit breaker. ### cbMillis **Type:** Number (Read Only) The interval of the circuit breaker in milliseconds. ### ID **Type:** String (Read Only) The unique Service ID. ### rateLimitCalls **Type:** Number (Read Only) The maximum number of calls in an interval allowed by the rate limiter. ### rateLimitMillis **Type:** Number (Read Only) The interval of the rate limiter in milliseconds. ### timeoutMillis **Type:** Number (Read Only) The service call timeout in milliseconds. ## Constructor Summary ## Method Summary ### getCbCalls **Signature:** `getCbCalls() : Number` Returns the maximum number of errors in an interval allowed by the circuit breaker. ### getCbMillis **Signature:** `getCbMillis() : Number` Returns the interval of the circuit breaker in milliseconds. ### getID **Signature:** `getID() : String` Returns the unique Service ID. ### getRateLimitCalls **Signature:** `getRateLimitCalls() : Number` Returns the maximum number of calls in an interval allowed by the rate limiter. ### getRateLimitMillis **Signature:** `getRateLimitMillis() : Number` Returns the interval of the rate limiter in milliseconds. ### getTimeoutMillis **Signature:** `getTimeoutMillis() : Number` Returns the service call timeout in milliseconds. ## Method Detail ## Method Details ### getCbCalls **Signature:** `getCbCalls() : Number` **Description:** Returns the maximum number of errors in an interval allowed by the circuit breaker. **Returns:** Maximum number of errors in an interval allowed by the circuit breaker. --- ### getCbMillis **Signature:** `getCbMillis() : Number` **Description:** Returns the interval of the circuit breaker in milliseconds. **Returns:** Circuit breaker interval in milliseconds. --- ### getID **Signature:** `getID() : String` **Description:** Returns the unique Service ID. **Returns:** unique Service ID --- ### getRateLimitCalls **Signature:** `getRateLimitCalls() : Number` **Description:** Returns the maximum number of calls in an interval allowed by the rate limiter. **Returns:** Maximum number of calls in an interval allowed by the rate limiter. --- ### getRateLimitMillis **Signature:** `getRateLimitMillis() : Number` **Description:** Returns the interval of the rate limiter in milliseconds. **Returns:** Interval of the rate limiter in milliseconds. --- ### getTimeoutMillis **Signature:** `getTimeoutMillis() : Number` **Description:** Returns the service call timeout in milliseconds. **Returns:** Service call timeout in milliseconds. --- ``` -------------------------------------------------------------------------------- /docs/dw_system/Pipeline.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.system # Class Pipeline ## Inheritance Hierarchy - Object - dw.system.Pipeline ## Description A helper for executing pipelines from JavaScript. The main purpose for this API is to invoke process pipelines from JavaScript controllers, e.g. pipelines that return with an end node and that do not perform user interactions. Pipelines that span across multiple requests (e.g. that contain Interaction-Continue-Nodes) are not supported and may not work as expected. The pipeline will be executed within the current request and not by a remote call, so this API works roughly like a Call node in a pipeline. The called pipeline will get its own local pipeline dictionary. The dictionary can be populated with initial values from an argument object. Any results from the pipeline can be read from the pipeline dictionary that is returned by the execute(String) methods. If an exception occurs during the pipeline processing, the Error-branch of the pipeline will be called. If no error handling exists for the pipeline, the exception will be propagated and can be handled by the script code. If the pipeline finishes with an End node, the name of the end node can be obtained from the returned pipeline dictionary under the key 'EndNodeName'. Example: let Pipeline = require('dw/system/Pipeline'); let pdict = Pipeline.execute('MyPipeline-Start', { MyArgString: 'someStringValue', MyArgNumber: 12345, MyArgBoolean: true }); let result = pdict.MyReturnValue; This feature requires an API version >=15.5. ## Constructor Summary ## Method Summary ### execute **Signature:** `static execute(pipeline : String) : PipelineDictionary` Executes a pipeline. ### execute **Signature:** `static execute(pipeline : String, args : Object) : PipelineDictionary` Executes a pipeline. ## Method Detail ## Method Details ### execute **Signature:** `static execute(pipeline : String) : PipelineDictionary` **Description:** Executes a pipeline. **API Versioned:** From version 15.5. New convenience method for easier migration of pipeline-based systems to JavaScript controllers. **Parameters:** - `pipeline`: the pipeline identifier, must consist of the pipeline name and the start node name, like 'PipelineName-StartNodeName' **Returns:** the pipeline dictionary with the pipeline results --- ### execute **Signature:** `static execute(pipeline : String, args : Object) : PipelineDictionary` **Description:** Executes a pipeline. The pipeline dictionary will be initialized with the provided arguments. **API Versioned:** From version 15.5. New convenience method for easier migration of pipeline-based systems to JavaScript controllers. **Parameters:** - `pipeline`: the pipeline identifier, must consist of a pipeline name and a start node name, like 'PipelineName-StartNodeName' - `args`: an object whose properties represent the initial values of the pipeline dictionary **Returns:** the pipeline dictionary with the pipeline results --- ``` -------------------------------------------------------------------------------- /docs/dw_order/PaymentProcessor.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order # Class PaymentProcessor ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.order.PaymentProcessor ## Description A PaymentProcessor represents an entity that processes payments of one or more types. In the B2C Commerce system, a payment processor is just a container for configuration values, which describe, for example, the parameters (URL, merchant ID, password, etc) required for connecting to a payment gateway. The system has several built in PaymentProcessors. These are: BASIC_CREDIT BASIC_GIFT_CERTIFICATE CYBERSOURCE_CREDIT CYBERSOURCE_BML PAYPAL_CREDIT PAYPAL_EXPRESS VERISIGN_CREDIT The first two of these are merely placeholders with no associated preference values. The remaining system payment processors define preference values which are maintained in the Business Manager and are used in conjunction with built-in B2C Commerce payment integrations. Preferences of system PaymentProcessors are not intended to be read programmatically. Merchants may also define custom payment processors. This is done by defining a payment processor with an arbitrary ID in the Business Manager, and then configuring an attribute group with the same ID on the SitePreferences system object. Attributes added to the group will be considered preferences of the payment processor and will be readable through getPreferenceValue(String). Merchants can design their checkout process to read these preferences at run time for connecting to their payment gateways. Every PaymentMethod in the system is associated with at most one PaymentProcessor. This basically represents the physical payment gateway which processes the (logical) payment method. Each payment processor may be associated with an arbitrary number of payment methods. Also, each payment transaction has one PaymentProcessor which is set by custom code during the checkout process. ## Properties ### ID **Type:** String (Read Only) The 'ID' of this processor. ## Constructor Summary ## Method Summary ### getID **Signature:** `getID() : String` Returns the 'ID' of this processor. ### getPreferenceValue **Signature:** `getPreferenceValue(name : String) : Object` Returns the value of the specified preference for this payment processor. ## Method Detail ## Method Details ### getID **Signature:** `getID() : String` **Description:** Returns the 'ID' of this processor. **Returns:** the 'ID' of this processor, e.g. "BASIC_CREDIT". --- ### getPreferenceValue **Signature:** `getPreferenceValue(name : String) : Object` **Description:** Returns the value of the specified preference for this payment processor. If the preference name is invalid (or null) or no preference value is defined for this payment processor, null is returned. **Parameters:** - `name`: preference name. Typically an attribute defined on SitePreferences contained in an attribute group whose name is the same as this.ID. **Returns:** preference value, or null. --- ``` -------------------------------------------------------------------------------- /src/tool-configs/best-practices-tool-config.ts: -------------------------------------------------------------------------------- ```typescript import { GenericToolSpec, ToolExecutionContext } from '../core/handlers/base-handler.js'; import { ToolArguments } from '../core/handlers/base-handler.js'; import { ValidationHelpers, CommonValidations } from '../core/handlers/validation-helpers.js'; import { SFCCBestPracticesClient } from '../clients/best-practices-client.js'; export const BEST_PRACTICE_TOOL_NAMES = [ 'get_available_best_practice_guides', 'get_best_practice_guide', 'search_best_practices', 'get_hook_reference', ] as const; export type BestPracticeToolName = typeof BEST_PRACTICE_TOOL_NAMES[number]; export const BEST_PRACTICE_TOOL_NAMES_SET = new Set<BestPracticeToolName>(BEST_PRACTICE_TOOL_NAMES); /** * Configuration for SFCC best practices tools * Maps each tool to its validation, execution, and messaging logic */ export const BEST_PRACTICES_TOOL_CONFIG: Record<BestPracticeToolName, GenericToolSpec<ToolArguments, any>> = { get_available_best_practice_guides: { defaults: (args: ToolArguments) => args, validate: (_args: ToolArguments, _toolName: string) => { // No validation needed for list operation }, exec: async (_args: ToolArguments, context: ToolExecutionContext) => { const client = context.bestPracticesClient as SFCCBestPracticesClient; return client.getAvailableGuides(); }, logMessage: (_args: ToolArguments) => 'List guides', }, get_best_practice_guide: { defaults: (args: ToolArguments) => args, validate: (args: ToolArguments, toolName: string) => { ValidationHelpers.validateArguments(args, CommonValidations.requiredString('guideName'), toolName); }, exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.bestPracticesClient as SFCCBestPracticesClient; return client.getBestPracticeGuide(args.guideName as string); }, logMessage: (args: ToolArguments) => `Guide ${args.guideName}`, }, search_best_practices: { defaults: (args: ToolArguments) => args, validate: (args: ToolArguments, toolName: string) => { ValidationHelpers.validateArguments(args, CommonValidations.requiredString('query'), toolName); }, exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.bestPracticesClient as SFCCBestPracticesClient; return client.searchBestPractices(args.query as string); }, logMessage: (args: ToolArguments) => `Search best practices ${args.query}`, }, get_hook_reference: { defaults: (args: ToolArguments) => args, validate: (args: ToolArguments, toolName: string) => { ValidationHelpers.validateArguments(args, CommonValidations.requiredString('guideName'), toolName); }, exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.bestPracticesClient as SFCCBestPracticesClient; return client.getHookReference(args.guideName as string); }, logMessage: (args: ToolArguments) => `Hook reference ${args.guideName}`, }, }; ``` -------------------------------------------------------------------------------- /src/clients/ocapi/site-preferences-client.ts: -------------------------------------------------------------------------------- ```typescript /** * OCAPI Site Preferences Client * * This module handles all SFCC site preference related operations including * searching preferences across different instance types and preference groups. */ import { OCAPIConfig } from '../../types/types.js'; import { OCAPIAuthClient } from '../base/ocapi-auth-client.js'; import { QueryBuilder } from '../../utils/query-builder.js'; import { Validator } from '../../utils/validator.js'; import { buildOCAPIBaseUrl } from '../../utils/ocapi-url-builder.js'; /** * Interface for search request structure */ interface SearchRequest { query?: { text_query?: { fields: string[]; search_phrase: string; }; term_query?: { fields: string[]; operator: string; values: any[]; }; filtered_query?: { filter: any; query: any; }; bool_query?: { must?: any[]; must_not?: any[]; should?: any[]; }; match_all_query?: {}; }; sorts?: Array<{ field: string; sort_order?: 'asc' | 'desc'; }>; start?: number; count?: number; select?: string; } /** * Site preferences search options */ interface SitePreferencesOptions { maskPasswords?: boolean; expand?: string; } /** * OCAPI Site Preferences Client * Specialized client for site preference operations */ export class OCAPISitePreferencesClient extends OCAPIAuthClient { constructor(config: OCAPIConfig) { super(config); // Override the baseUrl for this specialized client this.baseUrl = buildOCAPIBaseUrl(config); } /** * Search site preferences across sites in the specified preference group and instance * * Allows searching for preferences by id, display_name, description, and value_type * Supports text queries, term queries, filtered queries, and boolean queries * * Searchable fields: * - id - String * - display_name - Localized String * - description - Localized String * - value_type - one of { * string, int, double, text, html, date, image, boolean, money, quantity, * datetime, email, password, set_of_string, set_of_int, set_of_double, enum_of_string, enum_of_int * } * * Note: value_type can only be joined with other attributes using a conjunction (AND) * Only searchable attributes can be used in sorting */ async searchSitePreferences( groupId: string, instanceType: string, searchRequest: SearchRequest, options?: SitePreferencesOptions, ): Promise<any> { Validator.validateRequired({ groupId, instanceType }, ['groupId', 'instanceType']); const validatedInstanceType = Validator.validateInstanceType(instanceType); Validator.validateSearchRequest(searchRequest); let endpoint = `/site_preferences/preference_groups/${encodeURIComponent(groupId)}/${validatedInstanceType}/preference_search`; if (options) { const queryString = QueryBuilder.fromObject(options); if (queryString) { endpoint += `?${queryString}`; } } return this.post(endpoint, searchRequest); } } ``` -------------------------------------------------------------------------------- /docs/dw_job/JobStepExecution.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.job # Class JobStepExecution ## Inheritance Hierarchy - Object - dw.job.JobStepExecution ## Description Represents an execution of a step that belongs to a job. The job execution this step execution belongs to can be accessed via getJobExecution(). If a pipeline is used to implement a step this step execution is available in the pipeline dictionary under the key 'JobStepExecution'. If a script module is used to implement a step this step execution is available as the second parameter of the module's function that is used to execute the step, e.g.: ```javascript ... exports.execute( parameters, stepExecution) { ... var jobExecution = stepExecution.getJobExecution(); ... } ... ``` ## Properties ### ID **Type:** String (Read Only) The ID of this step execution. ### jobExecution **Type:** JobExecution (Read Only) The job execution this step execution belongs to. ### stepID **Type:** String (Read Only) The ID of the step this step execution belongs to. ### stepTypeID **Type:** String (Read Only) The ID of the step type of the step this step execution belongs to. ## Constructor Summary This class does not have a constructor, so you cannot create it directly. ## Method Summary ### getID **Signature:** `getID() : String` Returns the ID of this step execution. ### getJobExecution **Signature:** `getJobExecution() : JobExecution` Returns the job execution this step execution belongs to. ### getParameterValue **Signature:** `getParameterValue(name : String) : Object` Returns the value of the parameter of the step this step execution belongs to. ### getStepID **Signature:** `getStepID() : String` Returns the ID of the step this step execution belongs to. ### getStepTypeID **Signature:** `getStepTypeID() : String` Returns the ID of the step type of the step this step execution belongs to. ## Method Details ### getID **Signature:** `getID() : String` **Description:** Returns the ID of this step execution. **Returns:** the ID of this step execution. --- ### getJobExecution **Signature:** `getJobExecution() : JobExecution` **Description:** Returns the job execution this step execution belongs to. **Returns:** the job execution this step execution belongs to. --- ### getParameterValue **Signature:** `getParameterValue(name : String) : Object` **Description:** Returns the value of the parameter of the step this step execution belongs to. **Parameters:** - `name`: The name of the parameter. **Returns:** the value of the parameter of the step this step execution belongs to. --- ### getStepID **Signature:** `getStepID() : String` **Description:** Returns the ID of the step this step execution belongs to. **Returns:** the ID of the step this step execution belongs to. --- ### getStepTypeID **Signature:** `getStepTypeID() : String` **Description:** Returns the ID of the step type of the step this step execution belongs to. **Returns:** the ID of the step type of the step this step execution belongs to. --- ``` -------------------------------------------------------------------------------- /docs/dw_util/MappingMgr.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.util # Class MappingMgr ## Inheritance Hierarchy - Object - dw.util.MappingMgr ## Description Used to manage and interface with mappings loaded into the system via the ImportKeyValueMapping job step. Class can be used to retrieve values for known keys, iterate over all keys known in a mapping or list all known mappings. Mappings are read into the system using the ImportKeyValueMapping job step. Generic mapping capability enables you to map keys to values, with the mapping stored in a high-performance data store that is independent of the database. This supports large datasets, with high performance for lookup. An example of using this feature is to map SKUs from a backend system to Commerce Cloud Digital SKUs on-the-fly in Digital script, so that interaction with the backend system is transparent and does not require adding Digital SKUs to the third party system. ## Properties ### mappingNames **Type:** Collection (Read Only) List all known mappings. ## Constructor Summary ## Method Summary ### get **Signature:** `static get(mappingName : String, key : MappingKey) : Map` Returns a map containing value(s) associated to the specified key for the specified mapping. ### getFirst **Signature:** `static getFirst(mappingName : String, key : MappingKey) : String` Gets the first string value of a mapping by name and key. ### getMappingNames **Signature:** `static getMappingNames() : Collection` List all known mappings. ### keyIterator **Signature:** `static keyIterator(mappingName : String) : SeekableIterator` Key iterator over known mapping keys by mapping name. ## Method Detail ## Method Details ### get **Signature:** `static get(mappingName : String, key : MappingKey) : Map` **Description:** Returns a map containing value(s) associated to the specified key for the specified mapping. **Parameters:** - `mappingName`: the mapping name - `key`: the key **Throws:** IllegalArgumentException - if mappingName is unknown --- ### getFirst **Signature:** `static getFirst(mappingName : String, key : MappingKey) : String` **Description:** Gets the first string value of a mapping by name and key. Ordering is determined by the input CSV file. Throws an exception if mappingName does not exist. **Parameters:** - `mappingName`: the mapping name - `key`: the key **Returns:** the value if a single value. The first value sequentially if a compound value. **Throws:** IllegalArgumentException - if mappingName is unknown --- ### getMappingNames **Signature:** `static getMappingNames() : Collection` **Description:** List all known mappings. **Returns:** the collection of mapping names --- ### keyIterator **Signature:** `static keyIterator(mappingName : String) : SeekableIterator` **Description:** Key iterator over known mapping keys by mapping name. Throws an exception if mappingName does not exist. **Parameters:** - `mappingName`: the mapping name **Returns:** the seekable iterator **Throws:** IllegalArgumentException - if mappingName is unknown --- ``` -------------------------------------------------------------------------------- /docs/dw_suggest/SuggestedTerms.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.suggest # Class SuggestedTerms ## Inheritance Hierarchy - Object - dw.suggest.SuggestedTerms ## Description This container represents a list of suggested terms, all belonging to a particular single original term of the users input search phrase. Each user input term of the search phrase is being processed separately by the suggestion engine. For each original term, a list of terms will be suggested, either completed terms, corrected terms or even the exact term if they are known to the engine as they are. A instance of this class refers to the original unmodified term, as well as to a list of SuggestedTerms objects representing a single suggested term. ## Properties ### empty **Type:** boolean (Read Only) Returns true if this set of suggested terms is empty. ### firstTerm **Type:** SuggestedTerm (Read Only) This method returns the suggested term which is considered best matching with the original term. See getTerms() for a note on ordering of suggested terms. ### originalTerm **Type:** String (Read Only) The original term of the user input, for which this instance provides a list of suggested terms. Suggested terms can either be corrected, or completed or exact matching. ### terms **Type:** Iterator (Read Only) The list of SuggestedTerms suggested for the original term. ## Constructor Summary ## Method Summary ### getFirstTerm **Signature:** `getFirstTerm() : SuggestedTerm` This method returns the suggested term which is considered best matching with the original term. ### getOriginalTerm **Signature:** `getOriginalTerm() : String` Returns the original term of the user input, for which this instance provides a list of suggested terms. ### getTerms **Signature:** `getTerms() : Iterator` Returns the list of SuggestedTerms suggested for the original term. ### isEmpty **Signature:** `isEmpty() : boolean` Returns true if this set of suggested terms is empty. ## Method Detail ## Method Details ### getFirstTerm **Signature:** `getFirstTerm() : SuggestedTerm` **Description:** This method returns the suggested term which is considered best matching with the original term. See getTerms() for a note on ordering of suggested terms. **Returns:** the best matching term **See Also:** getOriginalTerm() getTerms() --- ### getOriginalTerm **Signature:** `getOriginalTerm() : String` **Description:** Returns the original term of the user input, for which this instance provides a list of suggested terms. Suggested terms can either be corrected, or completed or exact matching. **Returns:** the original unmodified term of the user input search phrase --- ### getTerms **Signature:** `getTerms() : Iterator` **Description:** Returns the list of SuggestedTerms suggested for the original term. **Returns:** a iterator of suggested terms, might be empty **See Also:** getOriginalTerm() isEmpty() --- ### isEmpty **Signature:** `isEmpty() : boolean` **Description:** Returns true if this set of suggested terms is empty. **Returns:** true if no suggested term is contained in this set, false otherwise --- ``` -------------------------------------------------------------------------------- /src/clients/base/oauth-token.ts: -------------------------------------------------------------------------------- ```typescript /** * OAuth Token Manager for SFCC OCAPI * * This module provides a singleton Token class that manages OAuth 2.0 access tokens * for SFCC OCAPI requests. It handles automatic token refresh when tokens expire. */ import { OAuthToken, OAuthTokenResponse } from '../../types/types.js'; /** * Singleton class for managing OAuth tokens * Handles token storage, expiration checking, and automatic refresh */ export class TokenManager { private static instance: TokenManager; private tokens: Map<string, OAuthToken> = new Map(); private constructor() {} /** * Get the singleton instance of TokenManager */ static getInstance(): TokenManager { if (!TokenManager.instance) { TokenManager.instance = new TokenManager(); } return TokenManager.instance; } /** * Generate a unique key for the token based on hostname and client ID */ private getTokenKey(hostname: string, clientId: string): string { return `${hostname}:${clientId}`; } /** * Check if a token is valid (exists and not expired) * Includes a 60-second buffer to avoid using tokens that are about to expire */ isTokenValid(hostname: string, clientId: string): boolean { const key = this.getTokenKey(hostname, clientId); const token = this.tokens.get(key); if (!token) { return false; } // Add 60-second buffer to avoid using tokens that are about to expire const now = Date.now(); const expirationBuffer = 60 * 1000; // 60 seconds in milliseconds return token.expiresAt > (now + expirationBuffer); } /** * Get a valid token for the given hostname and client ID * Returns null if no valid token exists */ getValidToken(hostname: string, clientId: string): string | null { if (!this.isTokenValid(hostname, clientId)) { return null; } const key = this.getTokenKey(hostname, clientId); const token = this.tokens.get(key); return token?.accessToken ?? null; } /** * Store a new token from the OAuth response */ storeToken(hostname: string, clientId: string, tokenResponse: OAuthTokenResponse): void { const key = this.getTokenKey(hostname, clientId); const now = Date.now(); const token: OAuthToken = { accessToken: tokenResponse.access_token, tokenType: tokenResponse.token_type, expiresAt: now + (tokenResponse.expires_in * 1000), // Convert seconds to milliseconds }; this.tokens.set(key, token); } /** * Clear a token (useful for testing or when a token becomes invalid) */ clearToken(hostname: string, clientId: string): void { const key = this.getTokenKey(hostname, clientId); this.tokens.delete(key); } /** * Clear all tokens */ clearAllTokens(): void { this.tokens.clear(); } /** * Get token expiration time for debugging purposes */ getTokenExpiration(hostname: string, clientId: string): Date | null { const key = this.getTokenKey(hostname, clientId); const token = this.tokens.get(key); if (!token) { return null; } return new Date(token.expiresAt); } } ``` -------------------------------------------------------------------------------- /docs/TopLevel/Set.md: -------------------------------------------------------------------------------- ```markdown ## Package: TopLevel # Class Set ## Inheritance Hierarchy - Object - Set ## Description A Set can store any kind of element and ensures that no duplicates exist. Objects are stored and iterated in insertion order. ## Properties ### size **Type:** Number Number of elements stored in this set. ## Constructor Summary Set() Creates an empty Set. Set(values : Iterable) If the passed value is null or undefined then an empty set is constructed. ## Method Summary ### add **Signature:** `add(object : Object) : Set` Adds an element to the set. ### clear **Signature:** `clear() : void` Removes all elements from this set. ### delete **Signature:** `delete(object : Object) : boolean` Removes the element from the set. ### entries **Signature:** `entries() : ES6Iterator` Returns an iterator containing all elements of this set. ### forEach **Signature:** `forEach(callback : Function) : void` Runs the provided callback function once for each element present in this set. ### forEach **Signature:** `forEach(callback : Function, thisObject : Object) : void` Runs the provided callback function once for each element present in this set. ### has **Signature:** `has(object : Object) : boolean` Returns if this set contains the given object. ## Constructor Detail ## Method Detail ## Method Details ### add **Signature:** `add(object : Object) : Set` **Description:** Adds an element to the set. Does nothing if the set already contains the element. **Parameters:** - `object`: The object to add. **Returns:** This set object. --- ### clear **Signature:** `clear() : void` **Description:** Removes all elements from this set. --- ### delete **Signature:** `delete(object : Object) : boolean` **Description:** Removes the element from the set. **Parameters:** - `object`: The object to be removed. **Returns:** true if the set contained the object that was removed. Else false is returned. --- ### entries **Signature:** `entries() : ES6Iterator` **Description:** Returns an iterator containing all elements of this set. --- ### forEach **Signature:** `forEach(callback : Function) : void` **Description:** Runs the provided callback function once for each element present in this set. **Parameters:** - `callback`: The function to call, which is invoked with three arguments: the element (as value), the element (as index), and the Set object being iterated. --- ### forEach **Signature:** `forEach(callback : Function, thisObject : Object) : void` **Description:** Runs the provided callback function once for each element present in this set. **Parameters:** - `callback`: The function to call, which is invoked with three arguments: the element (as value), the element (as index), and the Set object being iterated. - `thisObject`: The Object to use as 'this' when executing callback. --- ### has **Signature:** `has(object : Object) : boolean` **Description:** Returns if this set contains the given object. **Parameters:** - `object`: The object to look for. **Returns:** true if the set contains the object else false is returned. --- ``` -------------------------------------------------------------------------------- /docs/dw_object/ObjectAttributeGroup.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.object # Class ObjectAttributeGroup ## Inheritance Hierarchy - Object - dw.object.ObjectAttributeGroup ## Description Represents a group of object attributes. ## Properties ### attributeDefinitions **Type:** Collection (Read Only) All attribute definitions for this group. The collection may contain both system attribute definition as well as custom attribute definitions. ### description **Type:** String (Read Only) The description of this group in the current locale. ### displayName **Type:** String (Read Only) The display name of this group. ### ID **Type:** String (Read Only) The ID of this group. ### objectTypeDefinition **Type:** ObjectTypeDefinition (Read Only) The object type definition to which this attribute group belongs. ### system **Type:** boolean (Read Only) Identifies if this is an sytem or a custom attribute group. A system attribute group is pre-defined and can not be deleted. ## Constructor Summary ## Method Summary ### getAttributeDefinitions **Signature:** `getAttributeDefinitions() : Collection` Returns all attribute definitions for this group. ### getDescription **Signature:** `getDescription() : String` Returns the description of this group in the current locale. ### getDisplayName **Signature:** `getDisplayName() : String` Returns the display name of this group. ### getID **Signature:** `getID() : String` Returns the ID of this group. ### getObjectTypeDefinition **Signature:** `getObjectTypeDefinition() : ObjectTypeDefinition` Returns the object type definition to which this attribute group belongs. ### isSystem **Signature:** `isSystem() : boolean` Identifies if this is an sytem or a custom attribute group. ## Method Detail ## Method Details ### getAttributeDefinitions **Signature:** `getAttributeDefinitions() : Collection` **Description:** Returns all attribute definitions for this group. The collection may contain both system attribute definition as well as custom attribute definitions. **Returns:** all attribute definitions for this group. --- ### getDescription **Signature:** `getDescription() : String` **Description:** Returns the description of this group in the current locale. **Returns:** the display name of this group. --- ### getDisplayName **Signature:** `getDisplayName() : String` **Description:** Returns the display name of this group. **Returns:** the display name of this group. --- ### getID **Signature:** `getID() : String` **Description:** Returns the ID of this group. **Returns:** the ID of this group. --- ### getObjectTypeDefinition **Signature:** `getObjectTypeDefinition() : ObjectTypeDefinition` **Description:** Returns the object type definition to which this attribute group belongs. **Returns:** the object type definition to which this attribute group belongs. --- ### isSystem **Signature:** `isSystem() : boolean` **Description:** Identifies if this is an sytem or a custom attribute group. A system attribute group is pre-defined and can not be deleted. **Returns:** true if this is a system attribute group, false otherwise. --- ``` -------------------------------------------------------------------------------- /src/utils/log-cache.ts: -------------------------------------------------------------------------------- ```typescript import { SFCCLogClient } from '../clients/log-client.js'; /** * Simple in-memory cache for log operations * Provides short-term caching to avoid repeated API calls for common operations */ export class LogCache { private cache = new Map<string, { data: any; timestamp: number; ttl: number }>(); private readonly DEFAULT_TTL = 5000; // 5 seconds default TTL private readonly MAX_CACHE_SIZE = 100; // Prevent memory bloat /** * Get cached data if available and not expired */ get<T>(key: string): T | null { const entry = this.cache.get(key); if (!entry) { return null; } // Check if expired if (Date.now() - entry.timestamp > entry.ttl) { this.cache.delete(key); return null; } return entry.data as T; } /** * Set cached data with TTL */ set(key: string, data: any, ttl: number = this.DEFAULT_TTL): void { // Implement basic LRU by removing oldest entries when cache is full if (this.cache.size >= this.MAX_CACHE_SIZE) { const oldestKey = this.cache.keys().next().value; if (oldestKey) { this.cache.delete(oldestKey); } } this.cache.set(key, { data, timestamp: Date.now(), ttl, }); } /** * Generate cache key for log operations */ static generateKey(operation: string, args: Record<string, any>): string { const sortedArgs = Object.keys(args) .sort() .map(key => `${key}=${args[key]}`) .join('&'); return `${operation}:${sortedArgs}`; } /** * Clear all cached entries */ clear(): void { this.cache.clear(); } /** * Remove expired entries (can be called periodically) */ cleanup(): void { const now = Date.now(); for (const [key, entry] of this.cache.entries()) { if (now - entry.timestamp > entry.ttl) { this.cache.delete(key); } } } } /** * Enhanced log client wrapper with caching capabilities * Provides transparent caching for frequently accessed log operations */ export class CachedLogClient { private cache = new LogCache(); private readonly CACHEABLE_OPERATIONS = new Set([ 'list_log_files', 'get_latest_job_log_files', 'summarize_logs', ]); constructor(private logClient: SFCCLogClient) {} /** * Execute operation with caching if applicable */ async executeWithCache<T>( operation: string, args: Record<string, any>, executor: () => Promise<T>, ttl?: number, ): Promise<T> { // Only cache certain operations to avoid stale data issues if (!this.CACHEABLE_OPERATIONS.has(operation)) { return executor(); } const cacheKey = LogCache.generateKey(operation, args); const cached = this.cache.get<T>(cacheKey); if (cached !== null) { return cached; } const result = await executor(); this.cache.set(cacheKey, result, ttl); return result; } /** * Clear cache - useful when log state might have changed */ clearCache(): void { this.cache.clear(); } /** * Cleanup expired cache entries */ cleanupCache(): void { this.cache.cleanup(); } } ``` -------------------------------------------------------------------------------- /docs/TopLevel/Generator.md: -------------------------------------------------------------------------------- ```markdown ## Package: TopLevel # Class Generator ## Inheritance Hierarchy - Object - Generator ## Description A generator is a special type of function that works as a factory for iterators and it allows you to define an iterative algorithm by writing a single function which can maintain its own state. A function becomes a generator if it contains one or more yield statements. When a generator function is called, the body of the function does not execute straight away; instead, it returns a generator-iterator object. Each call to the generator-iterator's next() method will execute the body of the function up to the next yield statement and return its result. When either the end of the function or a return statement is reached, a StopIteration exception is thrown. For example, the following fib() function is a Fibonacci number generator, that returns the generator when it encounters the yield statement: function fib() { var fibNum = 0, j = 1; while (true) { yield fibNum; var t = fibNum; fibNum = j; j += t; } } To use the generator, simply call the next() method to access the values returned by the function: var gen = fib(); for (var i = 0; i < 10; i++) { document.write(gen.next() " "); } ## Constructor Summary Generator() ## Method Summary ### close **Signature:** `close() : void` Closes the iteration of the generator. ### next **Signature:** `next() : Object` Resumes the iteration of the generator by continuing the function at the statement after the yield statement. ### send **Signature:** `send(value : Object) : Object` Allows you to control the resumption of the iterative algorithm. ## Constructor Detail ## Method Detail ## Method Details ### close **Signature:** `close() : void` **Description:** Closes the iteration of the generator. Any finally clauses active in the generator function are run. If a finally clause throws any exception other than StopIteration, the exception is propagated to the caller of the close() method. --- ### next **Signature:** `next() : Object` **Description:** Resumes the iteration of the generator by continuing the function at the statement after the yield statement. This function throws a StopIterator exception when there are no additional iterative steps. **Returns:** the result of resuming the iterative algorithm or a StopIterator exception if the sequence is exhausted. **See Also:** StopIteration --- ### send **Signature:** `send(value : Object) : Object` **Description:** Allows you to control the resumption of the iterative algorithm. Once a generator has been started by calling its next() method, you can use send() and pass a specific value that will be treated as the result of the last yield. The generator will then return the operand of the subsequent yield. You can't start a generator at an arbitrary point; you must start it with next() before you can send() it a specific value. Note that calling send(undefined) is equivalent to calling next(). However, starting a newborn generator with any value other than 'undefined' when calling send() will result in a TypeError exception. **Parameters:** - `value`: the value to use. --- ``` -------------------------------------------------------------------------------- /docs/dw_crypto/JWEHeader.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.crypto # Class JWEHeader ## Inheritance Hierarchy - Object - dw.crypto.JWEHeader ## Description This class represents an immutable header of a JWE (JSON Web Encryption) object. ## Properties ### algorithm **Type:** String (Read Only) Get the value of the algorithm parameter (alg). ### encryptionAlgorithm **Type:** String (Read Only) Get the value of the encryption algorithm parameter (enc). ## Constructor Summary ## Method Summary ### getAlgorithm **Signature:** `getAlgorithm() : String` Get the value of the algorithm parameter (alg). ### getEncryptionAlgorithm **Signature:** `getEncryptionAlgorithm() : String` Get the value of the encryption algorithm parameter (enc). ### parse **Signature:** `static parse(map : Object) : JWEHeader` Convert the given Map or JavaScript object into a JWE header. ### parseEncoded **Signature:** `static parseEncoded(base64encoded : String) : JWEHeader` Parse the given string as a Base64URL-encoded JWE header. ### parseJSON **Signature:** `static parseJSON(json : String) : JWEHeader` Parse the given string as a JWE header. ### toMap **Signature:** `toMap() : Map` Get a copy of these headers as a Map. ### toString **Signature:** `toString() : String` Get the content of the headers as a JSON String. ## Method Detail ## Method Details ### getAlgorithm **Signature:** `getAlgorithm() : String` **Description:** Get the value of the algorithm parameter (alg). **Returns:** Algorithm parameter from this header. --- ### getEncryptionAlgorithm **Signature:** `getEncryptionAlgorithm() : String` **Description:** Get the value of the encryption algorithm parameter (enc). **Returns:** Encryption algorithm parameter from this header. --- ### parse **Signature:** `static parse(map : Object) : JWEHeader` **Description:** Convert the given Map or JavaScript object into a JWE header. All keys correspond to JWE parameters. The algorithm (alg) and encryption method (enc) parameters are required. See JWE.decrypt(KeyRef) for supported values. **Parameters:** - `map`: Map or object data to convert. **Returns:** JWE Header. --- ### parseEncoded **Signature:** `static parseEncoded(base64encoded : String) : JWEHeader` **Description:** Parse the given string as a Base64URL-encoded JWE header. The algorithm (alg) and encryption method (enc) parameters are required. See JWE.decrypt(KeyRef) for supported values. **Parameters:** - `base64encoded`: Base64URL string to parse. **Returns:** JWE Header. --- ### parseJSON **Signature:** `static parseJSON(json : String) : JWEHeader` **Description:** Parse the given string as a JWE header. The algorithm (alg) and encryption method (enc) parameters are required. See JWE.decrypt(KeyRef) for supported values. **Parameters:** - `json`: JSON string to parse. **Returns:** JWE Header. --- ### toMap **Signature:** `toMap() : Map` **Description:** Get a copy of these headers as a Map. **Returns:** Copy of the JWE headers. --- ### toString **Signature:** `toString() : String` **Description:** Get the content of the headers as a JSON String. **Returns:** JSON String. --- ``` -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.yml: -------------------------------------------------------------------------------- ```yaml name: ❓ Question/Help description: Ask a question or get help with using the SFCC Development MCP Server title: "[Question]: " labels: ["question", "needs-triage"] assignees: [] body: - type: markdown attributes: value: | Need help or have a question? We're here to help! Please provide as much detail as possible so we can assist you effectively. - type: checkboxes id: terms attributes: label: Pre-submission Checklist description: Please confirm you have completed these steps before asking your question. options: - label: I have searched existing issues and discussions for similar questions required: true - label: I have read the README.md and relevant documentation required: true - label: I have checked the troubleshooting section (if applicable) required: true - type: dropdown id: question-category attributes: label: Question Category description: What category does your question fall into? options: - Installation and Setup - Configuration and Authentication - Using MCP Tools - SFCC Integration - Troubleshooting - Best Practices - Performance - Security - Development/Contributing - Other validations: required: true - type: textarea id: question attributes: label: Your Question description: What would you like to know? placeholder: Please ask your question clearly and provide context... validations: required: true - type: textarea id: context attributes: label: Context and Background description: Provide relevant context about what you're trying to accomplish placeholder: | - What are you trying to achieve? - What's your current setup? - What have you tried so far? - type: textarea id: current-setup attributes: label: Current Setup description: Describe your current configuration and environment value: | - OS: [e.g., macOS 14.1, Windows 11, Ubuntu 22.04] - Node.js version: [run `node --version`] - SFCC Dev MCP version: [check package.json version] - Operating mode: [Documentation-only or Full mode] - MCP Client: [e.g., Claude Desktop, Custom implementation] - type: textarea id: attempted-solutions attributes: label: What Have You Tried? description: What steps have you already taken to solve this? placeholder: | 1. I tried... 2. I looked at... 3. I configured... - type: textarea id: expected-outcome attributes: label: Expected Outcome description: What do you expect or hope to happen? - type: textarea id: relevant-logs attributes: label: Relevant Logs or Error Messages description: Include any relevant logs or error messages (remove sensitive information) render: shell - type: textarea id: additional-info attributes: label: Additional Information description: Any other information that might be helpful ``` -------------------------------------------------------------------------------- /docs/dw_customer/Wallet.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.customer # Class Wallet ## Inheritance Hierarchy - Object - dw.customer.Wallet ## Description Represents a set of payment instruments associated with a registered customer. Note: this class allows access to sensitive personal and private information. Pay attention to appropriate legal and regulatory requirements when developing. ## Properties ### paymentInstruments **Type:** Collection (Read Only) A collection of all payment instruments associated with the related customer. ## Constructor Summary ## Method Summary ### createPaymentInstrument **Signature:** `createPaymentInstrument(paymentMethodId : String) : CustomerPaymentInstrument` Creates a new, empty payment instrument object associated with the related customer for the given payment method. ### getPaymentInstruments **Signature:** `getPaymentInstruments() : Collection` Returns a collection of all payment instruments associated with the related customer. ### getPaymentInstruments **Signature:** `getPaymentInstruments(paymentMethodID : String) : Collection` Returns a collection of all payment instruments associated with the related customer filtered by the given payment method id. ### removePaymentInstrument **Signature:** `removePaymentInstrument(instrument : CustomerPaymentInstrument) : void` Removes a payment instrument associated with the customer. ## Method Detail ## Method Details ### createPaymentInstrument **Signature:** `createPaymentInstrument(paymentMethodId : String) : CustomerPaymentInstrument` **Description:** Creates a new, empty payment instrument object associated with the related customer for the given payment method. **Parameters:** - `paymentMethodId`: the id of a payment method **Returns:** the new payment instrument object. **Throws:** NullArgumentException - If passed 'paymentMethodId' is null. --- ### getPaymentInstruments **Signature:** `getPaymentInstruments() : Collection` **Description:** Returns a collection of all payment instruments associated with the related customer. **Returns:** Collection of all payment instruments. --- ### getPaymentInstruments **Signature:** `getPaymentInstruments(paymentMethodID : String) : Collection` **Description:** Returns a collection of all payment instruments associated with the related customer filtered by the given payment method id. If null is passed as payment method id all payment instruments of the customer will be retrieved. If for the given payment method id no payment instrument is associated with the customer an empty collection will be returned. **Parameters:** - `paymentMethodID`: the paymentMethodID the payment method id to filter for **Returns:** Collection of payment instruments for a payment method. --- ### removePaymentInstrument **Signature:** `removePaymentInstrument(instrument : CustomerPaymentInstrument) : void` **Description:** Removes a payment instrument associated with the customer. **Parameters:** - `instrument`: the instrument associated with this customer **Throws:** NullArgumentException - If passed 'instrument' is null. IllegalArgumentException - If passed 'instrument' belongs to an other customer --- ``` -------------------------------------------------------------------------------- /docs/dw_extensions.payments/SalesforcePayPalOrderAddress.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.extensions.payments # Class SalesforcePayPalOrderAddress ## Inheritance Hierarchy - Object - dw.extensions.payments.SalesforcePayPalOrderAddress ## Description Salesforce Payments representation of a PayPal order address object. See Salesforce Payments documentation for how to gain access and configure it for use on your sites. ## Properties ### addressLine1 **Type:** String (Read Only) The address line 1. ### addressLine2 **Type:** String (Read Only) The address line 2. ### adminArea1 **Type:** String (Read Only) The address highest level sub-division in a country, which is usually a province, state, or ISO-3166-2 subdivision. ### adminArea2 **Type:** String (Read Only) The address city, town, or village. ### countryCode **Type:** String (Read Only) The address two-character ISO 3166-1 code that identifies the country or region. ### fullName **Type:** String (Read Only) The address full name. ### postalCode **Type:** String (Read Only) The address postal code. ## Constructor Summary ## Method Summary ### getAddressLine1 **Signature:** `getAddressLine1() : String` Returns the address line 1. ### getAddressLine2 **Signature:** `getAddressLine2() : String` Returns the address line 2. ### getAdminArea1 **Signature:** `getAdminArea1() : String` Returns the address highest level sub-division in a country, which is usually a province, state, or ISO-3166-2 subdivision. ### getAdminArea2 **Signature:** `getAdminArea2() : String` Returns the address city, town, or village. ### getCountryCode **Signature:** `getCountryCode() : String` Returns the address two-character ISO 3166-1 code that identifies the country or region. ### getFullName **Signature:** `getFullName() : String` Returns the address full name. ### getPostalCode **Signature:** `getPostalCode() : String` Returns the address postal code. ## Method Detail ## Method Details ### getAddressLine1 **Signature:** `getAddressLine1() : String` **Description:** Returns the address line 1. **Returns:** address line 1 --- ### getAddressLine2 **Signature:** `getAddressLine2() : String` **Description:** Returns the address line 2. **Returns:** address line 2 --- ### getAdminArea1 **Signature:** `getAdminArea1() : String` **Description:** Returns the address highest level sub-division in a country, which is usually a province, state, or ISO-3166-2 subdivision. **Returns:** address highest level sub-division in a country, such as a state --- ### getAdminArea2 **Signature:** `getAdminArea2() : String` **Description:** Returns the address city, town, or village. **Returns:** address city, town, or village --- ### getCountryCode **Signature:** `getCountryCode() : String` **Description:** Returns the address two-character ISO 3166-1 code that identifies the country or region. **Returns:** address country code --- ### getFullName **Signature:** `getFullName() : String` **Description:** Returns the address full name. **Returns:** address full name --- ### getPostalCode **Signature:** `getPostalCode() : String` **Description:** Returns the address postal code. **Returns:** address postal code --- ``` -------------------------------------------------------------------------------- /src/types/types.ts: -------------------------------------------------------------------------------- ```typescript /** * Type definitions for SFCC MCP Server * * This module contains all TypeScript interfaces and types used throughout * the SFCC (Salesforce B2C Commerce Cloud) MCP server application. */ /** * Configuration interface for SFCC connection * Supports both basic authentication (username/password) and OAuth (clientId/clientSecret) */ export interface SFCCConfig { /** SFCC hostname (e.g., zziu-006.dx.commercecloud.salesforce.com) */ hostname?: string; /** Username for basic authentication (optional if using OAuth) */ username?: string; /** Password for basic authentication (optional if using OAuth) */ password?: string; /** Client ID for OAuth authentication (optional if using basic auth) */ clientId?: string; /** Client secret for OAuth authentication (optional if using basic auth) */ clientSecret?: string; /** Site ID for SFCC instance */ siteId?: string; } /** * Configuration structure from dw.json file * This matches the standard Salesforce Commerce Cloud dw.json configuration format */ export interface DwJsonConfig { /** SFCC hostname */ hostname: string; /** Username for WebDAV access */ username: string; /** Password for WebDAV access */ password: string; /** Optional code version */ 'code-version'?: string; /** Optional client ID for OAuth */ 'client-id'?: string; /** Optional client secret for OAuth */ 'client-secret'?: string; /** Optional site ID for SFCC instance */ 'site-id'?: string; } /** * Log levels supported by the SFCC logging system */ export type LogLevel = 'error' | 'warn' | 'info' | 'debug'; /** * Structure for log file metadata */ export interface LogFileInfo { /** File name */ name: string; /** File size in bytes */ size: number; /** Last modification timestamp */ lastModified: string; } /** * Summary statistics for log analysis */ export interface LogSummary { /** Date of the logs being summarized */ date: string; /** Number of error entries found */ errorCount: number; /** Number of warning entries found */ warningCount: number; /** Number of info entries found */ infoCount: number; /** Number of debug entries found */ debugCount: number; /** List of unique error patterns identified */ keyIssues: string[]; /** List of log files analyzed */ files: string[]; } /** * OAuth 2.0 token response from SFCC authorization server */ export interface OAuthTokenResponse { /** Token expiration time in seconds */ expires_in: number; /** Token type (always "Bearer" for SFCC) */ token_type: string; /** The actual access token */ access_token: string; } /** * OAuth token with expiration tracking */ export interface OAuthToken { /** The access token */ accessToken: string; /** Token type */ tokenType: string; /** When the token expires (timestamp) */ expiresAt: number; } /** * OCAPI client configuration */ export interface OCAPIConfig { /** SFCC hostname */ hostname: string; /** OAuth client ID */ clientId: string; /** OAuth client secret */ clientSecret: string; /** Site ID (optional, for shop API) */ siteId?: string; /** API version (default: v21_3) */ version?: string; } ``` -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- ```markdown ## 📋 Pull Request Summary ### Type of Change <!-- Please select the type of change this PR introduces --> - [ ] 🐛 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (non-breaking change which adds functionality) - [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] 📚 Documentation update (changes to documentation only) - [ ] 🔧 Configuration/tooling update (changes to build process, CI/CD, etc.) - [ ] ♻️ Code refactoring (no functional changes, no API changes) - [ ] 🎨 Style/formatting changes (code formatting, missing semicolons, etc.) - [ ] ⚡ Performance improvement - [ ] 🧪 Test improvements - [ ] 🔒 Security enhancement ### Description <!-- Provide a clear and concise description of what this PR does --> ### Related Issues <!-- Link to related issues using keywords like "Fixes #123" or "Closes #456" --> - Fixes # - Related to # ### Changes Made <!-- List the main changes made in this PR --> - - - ### Testing <!-- Describe how you tested your changes --> - [ ] Unit tests added/updated - [ ] Integration tests added/updated - [ ] Manual testing performed - [ ] Tested in documentation-only mode - [ ] Tested in full mode (with SFCC credentials) - [ ] All existing tests pass ### Test Coverage <!-- Describe what testing was done --> ### Breaking Changes <!-- If this is a breaking change, describe what breaks and how to migrate --> ### Documentation <!-- Check all that apply --> - [ ] README.md updated (if user-facing changes) - [ ] copilot-instructions.md updated (if architectural changes) - [ ] API documentation updated - [ ] Best practices guides updated - [ ] Code comments added/updated - [ ] No documentation changes needed ### Performance Impact <!-- Describe any performance implications --> - [ ] No performance impact - [ ] Performance improvement - [ ] Minor performance impact (acceptable) - [ ] Significant performance impact (needs discussion) ### Security Considerations <!-- Describe any security implications --> - [ ] No security impact - [ ] Security improvement - [ ] Reviewed for security implications - [ ] No new external dependencies - [ ] New dependencies reviewed for security ### Checklist <!-- Ensure all items are checked before requesting review --> - [ ] Code follows the project's style guidelines - [ ] Self-review of the code has been performed - [ ] Code is well-commented, particularly in hard-to-understand areas - [ ] Changes generate no new warnings or errors - [ ] Any dependent changes have been merged and published - [ ] Version numbers updated (if applicable) - [ ] Changelog updated (if applicable) ### Reviewer Notes <!-- Any specific areas you'd like reviewers to focus on --> ### Screenshots/Examples <!-- If applicable, add screenshots or code examples --> --- ### For Maintainers <!-- This section is for maintainers to fill out during review --> #### Review Checklist - [ ] Code quality and style - [ ] Test coverage adequate - [ ] Documentation updated appropriately - [ ] Security implications reviewed - [ ] Performance impact acceptable - [ ] Breaking changes properly documented - [ ] Version bump needed - [ ] Release notes needed ``` -------------------------------------------------------------------------------- /tests/path-service.test.ts: -------------------------------------------------------------------------------- ```typescript import { PathService, MockPathService } from '../src/services/path-service.js'; describe('PathService', () => { describe('Production PathService', () => { let service: PathService; beforeEach(() => { service = new PathService(); }); it('should be instantiable', () => { expect(service).toBeInstanceOf(PathService); }); it('should join paths correctly', () => { expect(service.join('a', 'b', 'c')).toMatch(/a.b.c/); }); it('should resolve paths correctly', () => { const resolved = service.resolve('test', 'path'); expect(service.isAbsolute(resolved)).toBe(true); }); it('should get dirname correctly', () => { const result = service.dirname('/path/to/file.txt'); expect(result).toMatch(/.*path.to/); }); it('should get basename correctly', () => { expect(service.basename('/path/to/file.txt')).toBe('file.txt'); expect(service.basename('/path/to/file.txt', '.txt')).toBe('file'); }); it('should get extension correctly', () => { expect(service.extname('/path/to/file.txt')).toBe('.txt'); expect(service.extname('/path/to/file')).toBe(''); }); it('should normalize paths correctly', () => { const normalized = service.normalize('/path//to///file.txt'); expect(normalized).not.toMatch(/\/\/+/); }); it('should detect absolute paths correctly', () => { expect(service.isAbsolute('/absolute/path')).toBe(true); expect(service.isAbsolute('relative/path')).toBe(false); }); }); describe('MockPathService', () => { let mockService: MockPathService; beforeEach(() => { mockService = new MockPathService(); }); it('should be instantiable', () => { expect(mockService).toBeInstanceOf(MockPathService); }); it('should join paths with forward slashes', () => { expect(mockService.join('a', 'b', 'c')).toBe('a/b/c'); }); it('should resolve paths with mock root', () => { expect(mockService.resolve('test', 'path')).toBe('/mock/root/test/path'); expect(mockService.resolve('/absolute', 'path')).toBe('/absolute/path'); }); it('should get dirname correctly', () => { expect(mockService.dirname('/path/to/file.txt')).toBe('/path/to'); expect(mockService.dirname('/file.txt')).toBe('/'); }); it('should get basename correctly', () => { expect(mockService.basename('/path/to/file.txt')).toBe('file.txt'); expect(mockService.basename('/path/to/file.txt', '.txt')).toBe('file'); expect(mockService.basename('/path/to/file.txt', '.js')).toBe('file.txt'); }); it('should get extension correctly', () => { expect(mockService.extname('/path/to/file.txt')).toBe('.txt'); expect(mockService.extname('/path/to/file.min.js')).toBe('.js'); expect(mockService.extname('/path/to/file')).toBe(''); }); it('should normalize paths correctly', () => { expect(mockService.normalize('/path//to///file.txt')).toBe('/path/to/file.txt'); }); it('should detect absolute paths correctly', () => { expect(mockService.isAbsolute('/absolute/path')).toBe(true); expect(mockService.isAbsolute('relative/path')).toBe(false); }); }); }); ``` -------------------------------------------------------------------------------- /docs-site/components/SEO.tsx: -------------------------------------------------------------------------------- ```typescript import React from 'react'; import { Head } from 'vite-react-ssg'; interface SEOProps { title?: string; description?: string; keywords?: string; canonical?: string; ogImage?: string; ogType?: 'website' | 'article'; twitterCard?: 'summary' | 'summary_large_image'; noindex?: boolean; } const SEO: React.FC<SEOProps> = ({ title = 'SFCC Development MCP Server', description = 'Model Context Protocol server for Salesforce B2C Commerce Cloud development. Access comprehensive documentation, analyze logs, explore system objects, and get best practices with AI assistance.', keywords = 'SFCC, Salesforce Commerce Cloud, Model Context Protocol, MCP server, AI development tools, SFCC documentation, Commerce Cloud development', canonical, ogImage = 'https://sfcc-mcp-dev.rhino-inquisitor.com/explain-product-pricing-methods.png', ogType = 'website', twitterCard = 'summary_large_image', structuredData, noindex = false }) => { const baseUrl = 'https://sfcc-mcp-dev.rhino-inquisitor.com'; const fullCanonical = canonical ? `${baseUrl}${canonical}` : baseUrl; const fullTitle = title === 'SFCC Development MCP Server' ? title : `${title} | SFCC Development MCP Server`; return ( <Head> <title>{fullTitle}</title> <meta name="description" content={description} /> <meta name="keywords" content={keywords} /> <link rel="canonical" href={fullCanonical} /> {/* Basic Meta Tags */} <meta name="author" content="Thomas Theunen" /> <meta name="publisher" content="Thomas Theunen" /> {noindex ? ( <meta name="robots" content="noindex, nofollow" /> ) : ( <meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" /> )} {/* Open Graph Tags */} <meta property="og:title" content={fullTitle} /> <meta property="og:description" content={description} /> <meta property="og:type" content={ogType} /> <meta property="og:url" content={fullCanonical} /> <meta property="og:site_name" content="SFCC Development MCP Server" /> <meta property="og:image" content={ogImage} /> <meta property="og:image:alt" content={title} /> <meta property="og:image:width" content="1200" /> <meta property="og:image:height" content="630" /> <meta property="og:locale" content="en_US" /> {/* Twitter Card Tags */} <meta name="twitter:card" content={twitterCard} /> <meta name="twitter:title" content={fullTitle} /> <meta name="twitter:description" content={description} /> <meta name="twitter:image" content={ogImage} /> <meta name="twitter:image:alt" content={title} /> <meta name="twitter:creator" content="@taurgis" /> <meta name="twitter:site" content="@taurgis" /> {/* Additional Meta Tags */} <meta name="application-name" content="SFCC Development MCP Server" /> <meta name="msapplication-tooltip" content={description} /> <meta name="apple-mobile-web-app-title" content="SFCC MCP Server" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="default" /> </Head> ); }; export default SEO; ``` -------------------------------------------------------------------------------- /docs/dw_svc/FTPService.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.svc # Class FTPService ## Inheritance Hierarchy - Object - dw.svc.Service - dw.svc.FTPService ## Description Represents an FTP or SFTP Service. There are two basic styles of configuration for this service. In the first style, createRequest is implemented to call the setOperation method on the Service. This will cause the single operation to be performed and returned as the data object in the parseResponse method. Any error status is set automatically based on the returned value of the operation. In the second style, execute is implemented to perform one or more operations using the serviceClient available on the Service object. This serviceClient will be either an FTPClient or an SFTPClient. The return value of execute will be passed as the data object in the parseResponse method. Note that the use of the FTP client is deprecated, and SFTP should be used instead. ## Properties ### autoDisconnect **Type:** boolean The status of whether the underlying FTP connection will be disconnected after the service call. ### client **Type:** Object (Read Only) The underlying client object. This is either an FTPClient or SFTPClient, depending on the protocol. ## Constructor Summary ## Method Summary ### getClient **Signature:** `getClient() : Object` Returns the underlying client object. ### isAutoDisconnect **Signature:** `isAutoDisconnect() : boolean` Returns the status of whether the underlying FTP connection will be disconnected after the service call. ### setAutoDisconnect **Signature:** `setAutoDisconnect(b : boolean) : FTPService` Sets the auto-disconnect flag. ### setOperation **Signature:** `setOperation(name : String, args : Object...) : FTPService` Sets a single operation to perform during the execute phase of the service. ## Method Detail ## Method Details ### getClient **Signature:** `getClient() : Object` **Description:** Returns the underlying client object. This is either an FTPClient or SFTPClient, depending on the protocol. **Returns:** (S)FTP Client object. --- ### isAutoDisconnect **Signature:** `isAutoDisconnect() : boolean` **Description:** Returns the status of whether the underlying FTP connection will be disconnected after the service call. **Returns:** The auto-disconnect flag. --- ### setAutoDisconnect **Signature:** `setAutoDisconnect(b : boolean) : FTPService` **Description:** Sets the auto-disconnect flag. If true, the underlying FTP connection will be disconnected after the service call. If false then it will remain open. The default value is true. **Parameters:** - `b`: true to enable auto-disconnect, false otherwise. **Returns:** this FTP or SFTP Service. --- ### setOperation **Signature:** `setOperation(name : String, args : Object...) : FTPService` **Description:** Sets a single operation to perform during the execute phase of the service. The given arguments make up a method name and arguments on the underlying getClient() object. This method will be invoked during execution, with the result passed into the callback's parseResponse method. This is required unless the callback defines an execute method. **Parameters:** - `name`: Method name. - `args`: Method arguments. **Returns:** this FTP or SFTP Service. --- ``` -------------------------------------------------------------------------------- /docs/dw_order.hooks/CalculateHooks.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order.hooks # Class CalculateHooks ## Inheritance Hierarchy - dw.order.hooks.CalculateHooks ## Description This interface represents all script hooks that can be registered to customize the order and basket calculation functionality. It contains the extension points (hook names), and the functions that are called by each extension point. A function must be defined inside a JavaScript source and must be exported. The script with the exported hook function must be located inside a site cartridge. Inside the site cartridge a 'package.json' file with a 'hooks' entry must exist. "hooks": "./hooks.json" The hooks entry links to a json file, relative to the 'package.json' file. This file lists all registered hooks inside the hooks property: "hooks": [ {"name": "dw.order.calculate", "script": "./calculate.js"} ] A hook entry has a 'name' and a 'script' property. The 'name' contains the extension point, the hook name. The 'script' contains the script relative to the hooks file, with the exported hook function. ## Constants ## Properties ## Constructor Summary ## Method Summary ### calculate **Signature:** `calculate(lineItemCtnr : LineItemCtnr) : Status` The function is called by extension point extensionPointCalculate. ### calculateShipping **Signature:** `calculateShipping(lineItemCtnr : LineItemCtnr) : Status` The function is called by extension point extensionPointCalculateShipping. ### calculateTax **Signature:** `calculateTax(lineItemCtnr : LineItemCtnr) : Status` The function is called by extension point extensionPointCalculateTax. ## Method Detail ## Method Details ### calculate **Signature:** `calculate(lineItemCtnr : LineItemCtnr) : Status` **Description:** The function is called by extension point extensionPointCalculate. It provides a single place for the line item container calculation. To provide a fallback for existing implementations, the default implementation calls the hook dw.ocapi.shop.basket.calculate. However, this hook is deprecated, and calling it will create entries in the deprecated API usage logs. You should override this function to use dw.order.calculate instead. If you provide your own implementation, you should provide and use the following hooks. Best practice is to use the hook manager to retrieve them in the calculate hook, and avoid calling them directly. extensionPointCalculateTax for tax calculation extensionPointCalculateShipping for shipping calculation **Parameters:** - `lineItemCtnr`: the line item container to be (re)calculated. --- ### calculateShipping **Signature:** `calculateShipping(lineItemCtnr : LineItemCtnr) : Status` **Description:** The function is called by extension point extensionPointCalculateShipping. It provides a single place for shipping calculation during the line item container calculation. **Parameters:** - `lineItemCtnr`: the line item container to be (re)calculated. --- ### calculateTax **Signature:** `calculateTax(lineItemCtnr : LineItemCtnr) : Status` **Description:** The function is called by extension point extensionPointCalculateTax. It provides a single place for tax calculation during the line item container calculation. **Parameters:** - `lineItemCtnr`: the line item container to be (re)calculated. --- ``` -------------------------------------------------------------------------------- /docs/dw_catalog/ProductPriceTable.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.catalog # Class ProductPriceTable ## Inheritance Hierarchy - Object - dw.catalog.ProductPriceTable ## Description A ProductPriceTable is a map of quantities to prices representing the potentially tiered prices of a product in Commerce Cloud Digital. The price of a product is the price associated with the largest quantity in the ProductPriceTable which does not exceed the purchase quantity. ## Properties ### quantities **Type:** Collection (Read Only) All quantities stored in the price table. ## Constructor Summary ## Method Summary ### getNextQuantity **Signature:** `getNextQuantity(quantity : Quantity) : Quantity` Returns the quantity following the passed quantity in the price table. ### getPercentage **Signature:** `getPercentage(quantity : Quantity) : Number` Returns the percentage off value of the price related to the passed quantity, calculated based on the price of the products minimum order quantity. ### getPrice **Signature:** `getPrice(quantity : Quantity) : Money` Returns the monetary price for the passed order quantity. ### getPriceBook **Signature:** `getPriceBook(quantity : Quantity) : PriceBook` Returns the price book which defined the monetary price for the passed order quantity. ### getQuantities **Signature:** `getQuantities() : Collection` Returns all quantities stored in the price table. ## Method Detail ## Method Details ### getNextQuantity **Signature:** `getNextQuantity(quantity : Quantity) : Quantity` **Description:** Returns the quantity following the passed quantity in the price table. If the passed quantity is the last entry in the price table, null is returned. **Parameters:** - `quantity`: the quantity to use to locate the next quantity in the price table. **Returns:** the next quantity or null. --- ### getPercentage **Signature:** `getPercentage(quantity : Quantity) : Number` **Description:** Returns the percentage off value of the price related to the passed quantity, calculated based on the price of the products minimum order quantity. **Parameters:** - `quantity`: the price quantity to compute the percentage off. **Returns:** the percentage off value of the price related to the passed quantity. --- ### getPrice **Signature:** `getPrice(quantity : Quantity) : Money` **Description:** Returns the monetary price for the passed order quantity. If no price is defined for the passed quantity, null is returned. This can happen if for example no price is defined for a single item. **Parameters:** - `quantity`: the quantity to use to determine price. **Returns:** price amount for the passed quantity --- ### getPriceBook **Signature:** `getPriceBook(quantity : Quantity) : PriceBook` **Description:** Returns the price book which defined the monetary price for the passed order quantity. If no price is defined for the passed quantity, null is returned. This can happen if for example no price is defined for a single item. **Parameters:** - `quantity`: the quantity to use to determine price. **Returns:** the price book defining this price, or null --- ### getQuantities **Signature:** `getQuantities() : Collection` **Description:** Returns all quantities stored in the price table. **Returns:** all price table quantities. --- ``` -------------------------------------------------------------------------------- /docs-site/components/ConfigModeTabs.tsx: -------------------------------------------------------------------------------- ```typescript import React from 'react'; import CodeBlock, { InlineCode } from './CodeBlock'; export const ConfigModeTabs: React.FC = () => { const [active, setActive] = React.useState<'docs' | 'full' | 'env'>('docs'); const tabBase = 'px-5 py-2 rounded-full text-xs md:text-sm font-medium transition border'; return ( <div> <div role="tablist" aria-label="Configuration modes" className="flex flex-wrap gap-3 mb-8"> <button aria-selected={active==='docs'} onClick={()=>setActive('docs')} className={`${tabBase} ${active==='docs' ? 'bg-green-600 text-white border-green-600 shadow' : 'bg-white text-gray-700 border-gray-200 hover:border-green-400 hover:text-green-600'}`}>Docs Only</button> <button aria-selected={active==='full'} onClick={()=>setActive('full')} className={`${tabBase} ${active==='full' ? 'bg-blue-600 text-white border-blue-600 shadow' : 'bg-white text-gray-700 border-gray-200 hover:border-blue-400 hover:text-blue-600'}`}>Full Mode</button> <button aria-selected={active==='env'} onClick={()=>setActive('env')} className={`${tabBase} ${active==='env' ? 'bg-purple-600 text-white border-purple-600 shadow' : 'bg-white text-gray-700 border-gray-200 hover:border-purple-400 hover:text-purple-600'}`}>Env Vars</button> </div> {active==='docs' && ( <div role="tabpanel" className="space-y-4 animate-fade-in"> <p className="text-sm text-gray-600">No credentials required. Add the server to your AI client:</p> <CodeBlock language="json" code={`{\n \"mcpServers\": {\n \"sfcc-dev\": {\n \"command\": \"npx\",\n \"args\": [\"sfcc-dev-mcp\"]\n }\n }\n}`} /> <ul className="text-xs text-gray-600 list-disc pl-5 space-y-1"> <li>Enables documentation, best practices & cartridge generation</li> <li>Upgrade anytime by adding <InlineCode>--dw-json</InlineCode></li> </ul> </div> )} {active==='full' && ( <div role="tabpanel" className="space-y-4 animate-fade-in"> <p className="text-sm text-gray-600">Provide a <InlineCode>dw.json</InlineCode> file to unlock logs, system objects & code versions.</p> <CodeBlock language="json" code={`{\n \"mcpServers\": {\n \"sfcc-dev\": {\n \"command\": \"npx\",\n \"args\": [\"sfcc-dev-mcp\", \"--dw-json\", \"/path/to/dw.json\"]\n }\n }\n}`} /> <p className="text-xs text-gray-500">Add <InlineCode>--debug true</InlineCode> temporarily when diagnosing configuration issues.</p> </div> )} {active==='env' && ( <div role="tabpanel" className="space-y-4 animate-fade-in"> <p className="text-sm text-gray-600">Use environment variables in CI or container setups. No file needed.</p> <CodeBlock language="bash" code={`export SFCC_HOSTNAME=\"your-instance.sandbox.us01.dx.commercecloud.salesforce.com\"\nexport SFCC_USERNAME=\"your-username\"\nexport SFCC_PASSWORD=\"your-password\"\nexport SFCC_CLIENT_ID=\"your-client-id\"\nexport SFCC_CLIENT_SECRET=\"your-client-secret\"\n\nnpx sfcc-dev-mcp`} /> <p className="text-xs text-gray-500">Command-line <InlineCode>--dw-json</InlineCode> always overrides env vars.</p> </div> )} </div> ); }; export default ConfigModeTabs; ``` -------------------------------------------------------------------------------- /docs/dw_customer/ProductListRegistrant.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.customer # Class ProductListRegistrant ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.customer.ProductListRegistrant ## Description A ProductListRegistrant is typically associated with an event related product list such as a gift registry. It holds information about a person associated with the event such as a bride or groom. ## Properties ### email **Type:** String The email address of the registrant or null. ### firstName **Type:** String The first name of the registrant or null. ### lastName **Type:** String The last name of the registrant or null. ### role **Type:** String The role of the registrant or null. The role of a registrant can be for example the bride of a bridal couple. ## Constructor Summary ## Method Summary ### getEmail **Signature:** `getEmail() : String` Returns the email address of the registrant or null. ### getFirstName **Signature:** `getFirstName() : String` Returns the first name of the registrant or null. ### getLastName **Signature:** `getLastName() : String` Returns the last name of the registrant or null. ### getRole **Signature:** `getRole() : String` Returns the role of the registrant or null. ### setEmail **Signature:** `setEmail(email : String) : void` Sets the email address of the registrant. ### setFirstName **Signature:** `setFirstName(firstName : String) : void` Sets the first name of the registrant. ### setLastName **Signature:** `setLastName(lastName : String) : void` Sets the last name of the registrant. ### setRole **Signature:** `setRole(role : String) : void` Sets the role of the registrant. ## Method Detail ## Method Details ### getEmail **Signature:** `getEmail() : String` **Description:** Returns the email address of the registrant or null. **Returns:** the email address of the registrant or null. --- ### getFirstName **Signature:** `getFirstName() : String` **Description:** Returns the first name of the registrant or null. **Returns:** the first name of the registrant or null. --- ### getLastName **Signature:** `getLastName() : String` **Description:** Returns the last name of the registrant or null. **Returns:** the last name of the registrant or null. --- ### getRole **Signature:** `getRole() : String` **Description:** Returns the role of the registrant or null. The role of a registrant can be for example the bride of a bridal couple. **Returns:** the role name of the registrant or null. --- ### setEmail **Signature:** `setEmail(email : String) : void` **Description:** Sets the email address of the registrant. **Parameters:** - `email`: the email address of the registrant. --- ### setFirstName **Signature:** `setFirstName(firstName : String) : void` **Description:** Sets the first name of the registrant. **Parameters:** - `firstName`: the first name of the registrant. --- ### setLastName **Signature:** `setLastName(lastName : String) : void` **Description:** Sets the last name of the registrant. **Parameters:** - `lastName`: the last name of the registrant. --- ### setRole **Signature:** `setRole(role : String) : void` **Description:** Sets the role of the registrant. **Parameters:** - `role`: the role of the registrant. --- ``` -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- ```yaml name: Publish to NPM on: release: types: [published] jobs: publish: runs-on: ubuntu-latest permissions: contents: write id-token: write steps: - name: Checkout code uses: actions/checkout@v5 with: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v5 with: node-version: '20' registry-url: 'https://registry.npmjs.org' cache: 'npm' - name: Configure Git run: | git config --global user.name "github-actions[bot]" git config --global user.email "github-actions[bot]@users.noreply.github.com" - name: Install dependencies run: npm ci - name: Build project run: npm run build - name: Setup SFCC mock server run: | cd tests/servers/sfcc-mock-server npm install npm run setup:logs node server.js --port 3000 & sleep 5 - name: Run tests run: npm test - name: Run linting run: npm run lint:check - name: Final build for publishing run: npm run build - name: Extract version and create release branch run: | # Extract version from the release tag (remove 'v' prefix if present) VERSION=${GITHUB_REF#refs/tags/} VERSION=${VERSION#v} echo "Setting package version to: $VERSION" # Create and switch to release branch BRANCH_NAME="release/v$VERSION" echo "Creating release branch: $BRANCH_NAME" git checkout -b $BRANCH_NAME # Update package version npm version $VERSION --no-git-tag-version # Commit the version update git add package.json package-lock.json git commit -m "chore: bump version to $VERSION for release" # Push the release branch git push origin $BRANCH_NAME - name: Stop SFCC mock server if: always() run: | # Kill SFCC mock server process pkill -f "node.*server.js" || true # Fallback: kill any remaining server processes on port 3000 lsof -ti :3000 | xargs kill -9 2>/dev/null || true - name: Publish to NPM run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Install MCP Publisher run: | curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.0.0/mcp-publisher_1.0.0_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher - name: Update server.json version run: | # Extract version from the release tag (remove 'v' prefix if present) VERSION=${GITHUB_REF#refs/tags/} VERSION=${VERSION#v} echo "Updating server.json version to: $VERSION" # Update server.json version to match the release jq --arg v "$VERSION" '.version = $v | .packages[0].version = $v' server.json > tmp && mv tmp server.json - name: Login to MCP Registry run: ./mcp-publisher login github-oidc - name: Publish to MCP Registry run: ./mcp-publisher publish ``` -------------------------------------------------------------------------------- /tests/servers/sfcc-mock-server/src/middleware/auth.js: -------------------------------------------------------------------------------- ```javascript /** * Authentication Middleware * * Handles OAuth token generation and validation for OCAPI endpoints. * Maintains simple in-memory token storage suitable for testing. */ class AuthenticationManager { constructor(config) { this.config = config; this.activeTokens = new Set(); this.validCredentials = config.validCredentials; } /** * Handle OAuth2 token requests */ handleOAuthToken(req, res) { const { grant_type } = req.body; // Validate grant type if (grant_type !== 'client_credentials' && grant_type !== 'urn:demandware:params:oauth:grant-type:client-id:dwsid:dwsecuretoken') { return res.status(400).json({ error: 'unsupported_grant_type', error_description: 'The authorization grant type is not supported' }); } // Extract credentials from Basic Auth header const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Basic ')) { return res.status(401).json({ error: 'invalid_client', error_description: 'Client authentication failed - missing Basic auth header' }); } const base64Credentials = authHeader.split(' ')[1]; const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii'); const [client_id, client_secret] = credentials.split(':'); // Validate credentials if (client_id !== this.validCredentials.clientId || client_secret !== this.validCredentials.clientSecret) { return res.status(401).json({ error: 'invalid_client', error_description: 'Client authentication failed' }); } // Generate mock access token const accessToken = `mock_token_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; this.activeTokens.add(accessToken); res.json({ access_token: accessToken, token_type: 'Bearer', expires_in: 3600, scope: 'SFCC_DATA_API' }); } /** * Middleware to require Bearer token authentication */ requireAuth() { return (req, res, next) => { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ error: 'unauthorized', message: 'Missing or invalid authorization header' }); } const token = authHeader.substring(7); if (!this.activeTokens.has(token)) { return res.status(401).json({ error: 'invalid_token', message: 'The access token is invalid or expired' }); } req.accessToken = token; next(); }; } /** * Clear expired tokens (for cleanup) */ clearExpiredTokens() { // For testing purposes, we'll keep tokens active // In a real implementation, you'd track token expiration } } module.exports = AuthenticationManager; ``` -------------------------------------------------------------------------------- /src/clients/docs/class-name-resolver.ts: -------------------------------------------------------------------------------- ```typescript /** * Class Name Resolver * * Responsible for normalizing and resolving SFCC class names between * different formats (dot notation vs underscore notation) and extracting * simple class names from fully qualified names. * * Single Responsibility: Class name format conversion and resolution */ export class ClassNameResolver { /** * Normalize class name to handle both dot and underscore formats * Examples: * - dw.content.ContentMgr -> dw_content.ContentMgr * - dw_content.ContentMgr -> dw_content.ContentMgr (unchanged) * - ContentMgr -> ContentMgr (unchanged) */ static normalizeClassName(className: string): string { // If it contains dots but not underscores in the package part, convert dots to underscores if (className.includes('.') && !className.includes('_')) { // Split by dots and convert package parts (all but last) to use underscores const parts = className.split('.'); if (parts.length > 1) { const packageParts = parts.slice(0, -1); const simpleClassName = parts[parts.length - 1]; return `${packageParts.join('_')}.${simpleClassName}`; } } return className; } /** * Extract simple class name from full class name * Examples: * - dw_content.ContentMgr -> ContentMgr * - ContentMgr -> ContentMgr */ static extractSimpleClassName(className: string): string { const parts = className.split('.'); return parts[parts.length - 1]; } /** * Convert class names from internal format to official format * Examples: * - dw_content.ContentMgr -> dw.content.ContentMgr * - TopLevel.String -> String */ static toOfficialFormat(className: string): string { return className.replace(/_/g, '.'); } /** * Find class matches by simple class name * Useful when multiple packages contain classes with the same name */ static findClassMatches( targetClassName: string, classCache: Map<string, any>, ): Array<{ key: string; info: any }> { const normalizedTarget = this.normalizeClassName(targetClassName); const simpleTarget = this.extractSimpleClassName(normalizedTarget); return Array.from(classCache.entries()) .filter(([, info]) => info.className === simpleTarget) .map(([key, info]) => ({ key, info })); } /** * Resolve class name with fallback logic * First tries exact match, then falls back to simple name matching */ static resolveClassName( className: string, classCache: Map<string, any>, ): { key: string; info: any } | null { // Normalize class name to support both formats const normalizedClassName = this.normalizeClassName(className); // Try exact match first with normalized name const exactMatch = classCache.get(normalizedClassName); if (exactMatch) { return { key: normalizedClassName, info: exactMatch }; } // If not found, try to find by class name only (without package) const matches = this.findClassMatches(normalizedClassName, classCache); if (matches.length === 1) { return matches[0]; } else if (matches.length > 1) { const matchKeys = matches.map(({ key }) => key).join(', '); throw new Error(`Multiple classes found with name "${this.extractSimpleClassName(normalizedClassName)}": ${matchKeys}`); } return null; } } ``` -------------------------------------------------------------------------------- /docs/sfra/product-tile.md: -------------------------------------------------------------------------------- ```markdown # SFRA Product Tile Model ## Overview The Product Tile model represents a product in tile/grid view format, typically used in product listing pages, search results, and category pages. It provides essential product information optimized for display in compact tile formats. ## Module Function ```javascript module.exports = function productTile(product, apiProduct, productType) ``` Decorates a product object with product tile information using various decorators. ### Parameters - `product` (Object) - Product Model to be decorated - `apiProduct` (dw.catalog.Product) - Product information returned by the script API - `productType` (string) - Product type information ('product', 'variant', 'master', 'set', etc.) ### Returns Object - Decorated product model with tile-specific information ## Applied Decorators The product tile model applies the following decorators: ### base Adds fundamental product information including uuid, id, productName, productType, and brand. ### searchPrice Adds pricing information optimized for search results and product tiles: `price` property with promotional pricing. ### images Adds product images with the following configuration: - **Types:** ['medium'] - Medium-sized images suitable for tiles - **Quantity:** 'single' - Single image per type ### ratings Adds product rating information: `rating` value calculated from product ID. ### setProductsCollection (conditional) Applied only when `productType === 'set'`. Adds `numberOfProductsInSet` property with count of products in the set. ### searchVariationAttributes Adds variation attribute information: `variationAttributes` array optimized for search results and product listings (specifically color swatches). ## Usage Example ```javascript var productTileDecorator = require('*/cartridge/models/product/productTile'); var productFactory = require('*/cartridge/scripts/factories/product'); // Create base product model var product = productFactory.get({ pid: 'product-id' }); // Apply product tile decorations var tileProduct = productTileDecorator(product, apiProduct, 'product'); // Access tile-specific properties console.log(tileProduct.images.medium); console.log(tileProduct.price); console.log(tileProduct.ratings); ``` ## Typical Properties After Decoration After applying the product tile decorators, the product object typically contains: - **uuid** - Product UUID - **id** - Product ID - **productName** - Product name - **productType** - Product type - **brand** - Product brand - **price** - Pricing information with promotions (DefaultPrice or RangePrice) - **images** - Medium-sized product images - **rating** - Product rating value - **variationAttributes** - Color variation swatches and options - **numberOfProductsInSet** - Number of products in set (for product sets only) ## Notes - Optimized for performance in product listing scenarios - Uses medium-sized images to balance quality and load time - Includes promotional pricing for accurate display - Handles different product types (simple, master, variant, set) - Variation attributes are optimized for search/listing context ## Related Models - **Full Product Model** - More detailed product information - **Product Bundle Model** - For bundled products - **Product Set Model** - For product sets - **Product Decorators** - Individual decoration functions ``` -------------------------------------------------------------------------------- /docs/dw_catalog/ProductInventoryList.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.catalog # Class ProductInventoryList ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.catalog.ProductInventoryList ## Description The ProductInventoryList provides access to ID, description and defaultInStockFlag of the list. Furthermore inventory records can be accessed by product or product ID. When using Omnichannel Inventory (OCI): B2C Commerce uses ProductInventoryLists to reference and expose OCI Locations and Location Groups. They're required for synchronizing availability data and creating reservations. Create a ProductInventoryList in B2C Commerce for each OCI Location and Location Group that B2C Commerce will access. The ProductInventoryList ID must match the External Reference field on the corresponding Location or Location Group. A ProductInventoryList ID/External Reference must have between 2 and 128 characters (inclusive). It can include only lowercase letters, uppercase letters, digits, hyphens, and underscores. ## Properties ### defaultInStockFlag **Type:** boolean (Read Only) The default in-stock flag of the inventory list. ### description **Type:** String (Read Only) The description of the inventory list. ### ID **Type:** String (Read Only) The ID of the inventory list. ## Constructor Summary ## Method Summary ### getDefaultInStockFlag **Signature:** `getDefaultInStockFlag() : boolean` Returns the default in-stock flag of the inventory list. ### getDescription **Signature:** `getDescription() : String` Returns the description of the inventory list. ### getID **Signature:** `getID() : String` Returns the ID of the inventory list. ### getRecord **Signature:** `getRecord(product : Product) : ProductInventoryRecord` Returns the inventory record for the specified product or null if there is no record for the product in this list. ### getRecord **Signature:** `getRecord(productID : String) : ProductInventoryRecord` Returns the inventory record for the specified product ID or null if there is no record for the product id in this list. ## Method Detail ## Method Details ### getDefaultInStockFlag **Signature:** `getDefaultInStockFlag() : boolean` **Description:** Returns the default in-stock flag of the inventory list. **Returns:** Default in-stock flag of inventory list. --- ### getDescription **Signature:** `getDescription() : String` **Description:** Returns the description of the inventory list. **Returns:** Description of inventory list. --- ### getID **Signature:** `getID() : String` **Description:** Returns the ID of the inventory list. **Returns:** ID of inventory list. --- ### getRecord **Signature:** `getRecord(product : Product) : ProductInventoryRecord` **Description:** Returns the inventory record for the specified product or null if there is no record for the product in this list. **Parameters:** - `product`: The product to lookup inventory record. **Returns:** Inventory record or null if not found. --- ### getRecord **Signature:** `getRecord(productID : String) : ProductInventoryRecord` **Description:** Returns the inventory record for the specified product ID or null if there is no record for the product id in this list. **Parameters:** - `productID`: The product ID to lookup inventory record. **Returns:** Inventory record or null if not found. --- ``` -------------------------------------------------------------------------------- /docs/dw_web/FormElementValidationResult.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.web # Class FormElementValidationResult ## Inheritance Hierarchy - Object - dw.web.FormElementValidationResult ## Description Represents a form element validation result. The validation script specified for form groups and fields can create such FormElementValidationResult with the desired validity, message and data and can then return it. The server side form element validation will evaluate these settings, i.e. calculate the corresponding element validity and message. The optional data provided with this instance will be kept and can be accessed again from the form element after server side validation. ## Properties ### data **Type:** Map (Read Only) Provides optional data acquired during validation. ### message **Type:** String Provides an optional message in case of validation failure. ### valid **Type:** boolean States if the validation succeeded or failed. ## Constructor Summary FormElementValidationResult(valid : boolean) Creates a FormElementValidationResult with given setting for the validity but without any message. FormElementValidationResult(valid : boolean, message : String) Creates a FormElementValidationResult with given setting for the validity and corresponding message. FormElementValidationResult(valid : boolean, message : String, data : Map) Creates a FormElementValidationResult with given setting for the validity and corresponding message. ## Method Summary ### addData **Signature:** `addData(key : Object, value : Object) : void` Adds optional data acquired during validation. ### getData **Signature:** `getData() : Map` Provides optional data acquired during validation. ### getMessage **Signature:** `getMessage() : String` Provides an optional message in case of validation failure. ### isValid **Signature:** `isValid() : boolean` States if the validation succeeded or failed. ### setMessage **Signature:** `setMessage(message : String) : void` Sets an optional message in case of validation failure. ### setValid **Signature:** `setValid(valid : boolean) : void` Sets if the validation succeeded or failed. ## Constructor Detail ## Method Detail ## Method Details ### addData **Signature:** `addData(key : Object, value : Object) : void` **Description:** Adds optional data acquired during validation. **Parameters:** - `key`: the key for which the data value will be stored - `value`: the data value that is stored for the given key --- ### getData **Signature:** `getData() : Map` **Description:** Provides optional data acquired during validation. **Returns:** the data acquired during validation --- ### getMessage **Signature:** `getMessage() : String` **Description:** Provides an optional message in case of validation failure. **Returns:** the message for validation failure --- ### isValid **Signature:** `isValid() : boolean` **Description:** States if the validation succeeded or failed. **Returns:** true if the validation succeeded --- ### setMessage **Signature:** `setMessage(message : String) : void` **Description:** Sets an optional message in case of validation failure. **Parameters:** - `message`: the message for validation failure --- ### setValid **Signature:** `setValid(valid : boolean) : void` **Description:** Sets if the validation succeeded or failed. **Parameters:** - `valid`: if the validation succeeded --- ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- ```json { "name": "sfcc-dev-mcp", "version": "1.0.14", "description": "MCP server for Salesforce B2C Commerce Cloud development assistance including logs, debugging, and development tools", "mcpName": "io.github.taurgis/sfcc-dev-mcp", "main": "dist/index.js", "bin": { "sfcc-dev-mcp": "./dist/main.js" }, "repository": { "type": "git", "url": "git+https://github.com/taurgis/sfcc-dev-mcp.git" }, "homepage": "https://github.com/taurgis/sfcc-dev-mcp#readme", "bugs": { "url": "https://github.com/taurgis/sfcc-dev-mcp/issues" }, "scripts": { "build": "tsc && rm -rf ./dist/docs && cp -r ./docs ./dist/docs", "start": "node dist/main.js", "dev": "tsx src/main.ts", "inspector": "npx @modelcontextprotocol/inspector node dist/main.js", "convert-docs": "node scripts/convert-docs.js", "convert-docs:test": "node scripts/convert-docs.js --test", "convert-docs:limit": "node scripts/convert-docs.js --limit 5", "github-pages": "cd docs-site && rm -f Gemfile.lock && bundle install --path vendor/bundle && bundle exec jekyll serve --livereload --host=0.0.0.0", "test": "npm run test:all", "test:watch": "jest --watch", "test:coverage": "jest --coverage", "test:mcp:yaml": "aegis 'tests/mcp/yaml/*.docs-only.test.mcp.yml' --config './aegis.config.docs-only.json'", "test:mcp:yaml:full": "aegis 'tests/mcp/yaml/*.full-mode.test.mcp.yml' --config './aegis.config.with-dw.json'", "test:mcp:node": "node --test tests/mcp/node/*.programmatic.test.js", "test:mcp:all": "npm run test:mcp:yaml && npm run test:mcp:yaml:full && npm run test:mcp:node", "test:mcp:ci": "npm run test:mcp:yaml -- --json && npm run test:mcp:yaml:full -- --json && npm run test:mcp:node", "test:all": "jest && npm run test:mock-server:setup && npm run test:mcp:all", "test:mock-server:setup": "cd tests/servers/sfcc-mock-server && npm install && npm run setup", "test:mock-server:start": "cd tests/servers/sfcc-mock-server && npm start", "test:mock-server": "jest --testPathPatterns=sfcc-mock-server", "validate:server-json": "node -e \"const {readFileSync} = require('fs'); const serverJson = JSON.parse(readFileSync('./server.json', 'utf8')); console.log('server.json is valid JSON'); console.log('Server name:', serverJson.name); console.log('Version:', serverJson.version); console.log('Package identifier:', serverJson.packages[0].identifier);\"", "lint": "eslint .", "lint:fix": "eslint . --fix", "lint:check": "eslint . --max-warnings 0", "prepublishOnly": "npm run build", "prepare": "husky" }, "keywords": [ "mcp", "salesforce", "commerce-cloud", "sfcc", "development", "logs", "debugging", "webdav" ], "author": "Thomas Theunen <[email protected]>", "license": "MIT", "engines": { "node": ">=18", "npm": ">=8" }, "type": "module", "dependencies": { "@modelcontextprotocol/sdk": "1.18.0", "webdav": "5.8.0" }, "devDependencies": { "@eslint/js": "9.36.0", "@types/eslint": "9.6.1", "@types/jest": "30.0.0", "@types/node": "24.4.0", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "eslint": "9.36.0", "husky": "9.1.7", "jest": "30.1.3", "mcp-aegis": "1.0.18", "ts-jest": "29.4.4", "tsx": "4.20.5", "typescript": "5.9.2", "typescript-eslint": "8.44.0" } } ``` -------------------------------------------------------------------------------- /docs/sfra/content.md: -------------------------------------------------------------------------------- ```markdown # SFRA Content Model ## Overview The Content model represents a content asset in SFRA applications. It provides structured access to content information including body text, metadata, and rendering template information for content management and display. ## Constructor ```javascript function content(contentValue, renderingTemplate) ``` Creates a Content model instance from a content asset. ### Parameters - `contentValue` (dw.content.Content) - Result of ContentMgr.getContent call - `renderingTemplate` (string) - Optional rendering template for the content ### Returns Object - Content model instance, or null if content is not online ## Properties ### body **Type:** string | null The main content body text from the content asset's custom.body attribute. ### UUID **Type:** string Unique identifier for the content asset. ### ID **Type:** string Content asset ID for referencing and linking. ### name **Type:** string Display name of the content asset. ### template **Type:** string Rendering template path for the content. Uses either: - Content asset's specified template - Provided renderingTemplate parameter - Default: 'components/content/contentAssetInc' ### pageTitle **Type:** string SEO page title for the content asset. ### pageDescription **Type:** string SEO meta description for the content asset. ### pageKeywords **Type:** string SEO meta keywords for the content asset. ### pageMetaTags **Type:** Array Additional SEO meta tags for the content asset. ## Content Availability The model only processes online content assets. If `contentValue.online` is false, the constructor returns null instead of a content object. ## Template Resolution Template selection follows this priority: 1. Content asset's own template property 2. Provided renderingTemplate parameter 3. Default template: 'components/content/contentAssetInc' ## Usage Example ```javascript var ContentModel = require('*/cartridge/models/content'); var ContentMgr = require('dw/content/ContentMgr'); // Get content asset var contentAsset = ContentMgr.getContent('privacy-policy'); var customTemplate = 'pages/content/contentPage'; var content = new ContentModel(contentAsset, customTemplate); if (content) { // Access content properties console.log(content.name); // "Privacy Policy" console.log(content.ID); // "privacy-policy" console.log(content.body); // Content body HTML console.log(content.template); // Template path // Access SEO properties console.log(content.pageTitle); // SEO title console.log(content.pageDescription); // SEO description } else { console.log('Content is offline or not found'); } ``` ## SEO Support The model provides comprehensive SEO metadata: - **pageTitle** - For HTML title tag - **pageDescription** - For meta description - **pageKeywords** - For meta keywords - **pageMetaTags** - For additional custom meta tags ## Notes - Only processes online content assets - Provides flexible template resolution - Includes comprehensive SEO metadata - Handles missing content gracefully (returns null) - Body content comes from custom.body attribute - Template fallback ensures content can always be rendered ## Related Models - **Page Models** - May include content assets - **Search Models** - May return content in search results - **Category Models** - May reference related content ``` -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.yml: -------------------------------------------------------------------------------- ```yaml name: 📚 Documentation Issue description: Report issues with documentation or suggest documentation improvements title: "[Docs]: " labels: ["documentation", "needs-triage"] assignees: [] body: - type: markdown attributes: value: | Thanks for helping improve our documentation! Please provide details about the documentation issue or improvement. - type: dropdown id: doc-type attributes: label: Documentation Type description: What type of documentation is this about? options: - README.md - API Documentation (docs/ folder) - Best Practices Guides - Code Comments/JSDoc - Setup/Installation Instructions - Configuration Guide - Troubleshooting Guide - Contributing Guidelines - GitHub Templates - Other validations: required: true - type: dropdown id: issue-type attributes: label: Issue Type description: What kind of documentation issue is this? options: - Missing documentation - Incorrect/outdated information - Unclear or confusing content - Broken links or references - Formatting issues - Grammar/spelling errors - Missing examples - Inconsistent information - Accessibility issues - Other validations: required: true - type: textarea id: location attributes: label: Location description: Where is the documentation issue located? placeholder: | - File path: docs/best-practices/cartridge_creation.md - Section: "Setting up Authentication" - Line number: 45 - URL: (if applicable) validations: required: true - type: textarea id: current-content attributes: label: Current Content (if applicable) description: Quote or describe the current problematic content render: markdown - type: textarea id: issue-description attributes: label: Issue Description description: Clearly describe what's wrong or what's missing placeholder: Explain what makes the current documentation problematic or what information is missing... validations: required: true - type: textarea id: suggested-improvement attributes: label: Suggested Improvement description: How should this be fixed or what should be added? placeholder: Provide your suggestion for improving the documentation... validations: required: true - type: textarea id: user-impact attributes: label: User Impact description: How does this documentation issue affect users? placeholder: | - Makes it difficult to get started - Causes confusion during setup - Leads to incorrect implementation - Wastes developer time... - type: dropdown id: audience attributes: label: Target Audience description: Who is primarily affected by this documentation issue? multiple: true options: - New users/first-time setup - SFCC developers - MCP server developers - Contributors - All users - Advanced users only - type: textarea id: additional-context attributes: label: Additional Context description: Any additional context, examples, or references that would help improve the documentation ``` -------------------------------------------------------------------------------- /docs/dw_util/Currency.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.util # Class Currency ## Inheritance Hierarchy - Object - dw.util.Currency ## Description Represents a currency supported by the system. ## Properties ### currencyCode **Type:** String (Read Only) Gets the ISO 4217 mnemonic currency code of this currency. ### defaultFractionDigits **Type:** Number (Read Only) Gets the default number of fraction digits used with this currency. For example, the default number of fraction digits for the Euro is 2, while for the Japanese Yen it's 0. ### name **Type:** String (Read Only) Gets a long name for this currency. e.g. "United States Dollar". The returned name is the one stored in the system for this currency. Currently only English names are available, but in the future this method may return a locale-specific name. ### symbol **Type:** String (Read Only) Gets the symbol of this currency. e.g. "$" for the US Dollar. ## Constructor Summary ## Method Summary ### getCurrency **Signature:** `static getCurrency(currencyCode : String) : Currency` Returns a Currency instance for the given currency code, or null if there is no such currency. ### getCurrencyCode **Signature:** `getCurrencyCode() : String` Gets the ISO 4217 mnemonic currency code of this currency. ### getDefaultFractionDigits **Signature:** `getDefaultFractionDigits() : Number` Gets the default number of fraction digits used with this currency. ### getName **Signature:** `getName() : String` Gets a long name for this currency. ### getSymbol **Signature:** `getSymbol() : String` Gets the symbol of this currency. ### toString **Signature:** `toString() : String` Returns the ISO 4217 mnemonic currency code of this currency. ## Method Detail ## Method Details ### getCurrency **Signature:** `static getCurrency(currencyCode : String) : Currency` **Description:** Returns a Currency instance for the given currency code, or null if there is no such currency. **Parameters:** - `currencyCode`: the ISO 4217 mnemonic code of the currency. **Returns:** the Currency instance for the given currency code. --- ### getCurrencyCode **Signature:** `getCurrencyCode() : String` **Description:** Gets the ISO 4217 mnemonic currency code of this currency. **Returns:** the ISO 4217 mnemonic currency code of this currency. --- ### getDefaultFractionDigits **Signature:** `getDefaultFractionDigits() : Number` **Description:** Gets the default number of fraction digits used with this currency. For example, the default number of fraction digits for the Euro is 2, while for the Japanese Yen it's 0. **Returns:** the default number of fraction digits used with this currency. --- ### getName **Signature:** `getName() : String` **Description:** Gets a long name for this currency. e.g. "United States Dollar". The returned name is the one stored in the system for this currency. Currently only English names are available, but in the future this method may return a locale-specific name. **Returns:** a long name for this currency. e.g. "United States Dollar". --- ### getSymbol **Signature:** `getSymbol() : String` **Description:** Gets the symbol of this currency. e.g. "$" for the US Dollar. **Returns:** the symbol of this currency. --- ### toString **Signature:** `toString() : String` **Description:** Returns the ISO 4217 mnemonic currency code of this currency. **Returns:** the ISO 4217 mnemonic currency code of this currency. --- ``` -------------------------------------------------------------------------------- /src/tool-configs/sfra-tool-config.ts: -------------------------------------------------------------------------------- ```typescript import { GenericToolSpec, ToolExecutionContext } from '../core/handlers/base-handler.js'; import { ToolArguments } from '../core/handlers/base-handler.js'; import { ValidationHelpers, CommonValidations } from '../core/handlers/validation-helpers.js'; import { SFRAClient } from '../clients/sfra-client.js'; export const SFRA_TOOL_NAMES = [ 'get_available_sfra_documents', 'get_sfra_document', 'search_sfra_documentation', 'get_sfra_documents_by_category', 'get_sfra_categories', ] as const; export type SFRAToolName = typeof SFRA_TOOL_NAMES[number]; export const SFRA_TOOL_NAMES_SET = new Set<SFRAToolName>(SFRA_TOOL_NAMES); /** * Configuration for SFRA documentation tools * Maps each tool to its validation, execution, and messaging logic */ export const SFRA_TOOL_CONFIG: Record<SFRAToolName, GenericToolSpec<ToolArguments, any>> = { get_available_sfra_documents: { defaults: (args: ToolArguments) => args, validate: (_args: ToolArguments, _toolName: string) => { // No validation needed for list operation }, exec: async (_args: ToolArguments, context: ToolExecutionContext) => { const client = context.sfraClient as SFRAClient; return client.getAvailableDocuments(); }, logMessage: (_args: ToolArguments) => 'List SFRA docs', }, get_sfra_document: { defaults: (args: ToolArguments) => args, validate: (args: ToolArguments, toolName: string) => { ValidationHelpers.validateArguments(args, CommonValidations.requiredString('documentName'), toolName); }, exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.sfraClient as SFRAClient; const result = await client.getSFRADocument(args.documentName as string); if (!result) { throw new Error(`SFRA document "${args.documentName}" not found`); } return result; }, logMessage: (args: ToolArguments) => `SFRA doc ${args.documentName}`, }, search_sfra_documentation: { defaults: (args: ToolArguments) => args, validate: (args: ToolArguments, toolName: string) => { ValidationHelpers.validateArguments(args, CommonValidations.requiredString('query'), toolName); }, exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.sfraClient as SFRAClient; return client.searchSFRADocumentation(args.query as string); }, logMessage: (args: ToolArguments) => `Search SFRA ${args.query}`, }, get_sfra_documents_by_category: { defaults: (args: ToolArguments) => args, validate: (args: ToolArguments, toolName: string) => { ValidationHelpers.validateArguments(args, CommonValidations.requiredString('category'), toolName); }, exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.sfraClient as SFRAClient; return client.getDocumentsByCategory(args.category as string); }, logMessage: (args: ToolArguments) => `SFRA docs by category ${args.category}`, }, get_sfra_categories: { defaults: (args: ToolArguments) => args, validate: (_args: ToolArguments, _toolName: string) => { // No validation needed for list operation }, exec: async (_args: ToolArguments, context: ToolExecutionContext) => { const client = context.sfraClient as SFRAClient; return client.getAvailableCategories(); }, logMessage: (_args: ToolArguments) => 'SFRA categories', }, }; ``` -------------------------------------------------------------------------------- /docs/dw_util/Template.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.util # Class Template ## Inheritance Hierarchy - Object - dw.util.Template ## Description Reads an ISML template from the file system and renders it into a MimeEncodedText object. Optional substitution values can be passed to the isml template via the render(Map) method. Substitution parameters can be accessed within the template through <isprint value="${param.parameter}"> or for backward compatibility through <isprint value="${pdict.parameter}"> The access through pdict only gives access to the parameter map provided at rendering time and doesn't offer access to the system PipelineDictionary. The pdict access to the property map is only considered to ease the transition from SendMail pipelet API based templates. If the PipelineDictionary or properties of the PipelineDictionary are needed, they need to be included in the Property map passed to the render method. ## Constructor Summary Template(templateName : String) Creates a new template. Template(templateName : String, localeID : String) Creates a new template with the locale being set to the given localeID. ## Method Summary ### render **Signature:** `render() : MimeEncodedText` Renders the template specified at instantiation time, without any substitution parameters. ### render **Signature:** `render(params : Map) : MimeEncodedText` Renders the template specified at instantiation time with the given substitution parameters. ### setLocale **Signature:** `setLocale(localeID : String) : Template` Sets an optional localeID which is used instead of the current requests localeID. ## Constructor Detail ## Method Detail ## Method Details ### render **Signature:** `render() : MimeEncodedText` **Description:** Renders the template specified at instantiation time, without any substitution parameters. Any isprint tags referring to param/pdict will be unresolved and will be replaced with empty strings. If there's an explicit localeID set through setLocale(String), it takes precedence over the localeID associated with the current request. **Returns:** MimeEncodedText with isprint tags referring to param/pdict replaced with an empty String --- ### render **Signature:** `render(params : Map) : MimeEncodedText` **Description:** Renders the template specified at instantiation time with the given substitution parameters. These parameters are available to ISML templates through variables named 'param' and 'pdict'. Note that in this context, pdict is not referring to the system PipelineDictionary, as the System Pipeline Dictionary is not accessible from this script API. If there's an explicit localeID set through setLocale(String), it takes precedence over the localeID associated with the current request. **Parameters:** - `params`: Map of substitution parameters which are specified within the ISML template. Access is available from within the ISML template through named variables param or pdict. **Returns:** MimeEncodedText containing the rendered template. Variables in the template referring to param/pdict are replaced with the value from the params map or empty if the value isn't found in the map --- ### setLocale **Signature:** `setLocale(localeID : String) : Template` **Description:** Sets an optional localeID which is used instead of the current requests localeID. **Parameters:** - `localeID`: to be used for processing this template. Throws an exception if localeID is blank **Returns:** this Template object --- ``` -------------------------------------------------------------------------------- /docs/dw_system/SearchStatus.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.system # Class SearchStatus ## Inheritance Hierarchy - Object - dw.system.SearchStatus ## Description A SearchStatus is used for communicating a Search API status back to a client. A status consists of status code and description. More information about search API call can be fetched by using SearchStatus class method getStatusCode and getDescription, which can be used by clients to perform different operations. ## Constants ### EMPTY_QUERY **Type:** Number = 6 EMPTY_QUERY search result status code 6, this indicates that search has been made with empty query. ### ERROR **Type:** Number = 9 ERROR search result status code 9, this indicates that internal server error has been occurred. ### LIMITED **Type:** Number = 2 LIMITED search result status code 2, this indicates that limitations on search result have been applied and full search result is not returned. ### NO_CATALOG **Type:** Number = 4 NO_CATALOG search result status code 4, this indicates that there is no catalog associated for search query. ### NO_CATEGORY **Type:** Number = 5 NO_CATEGORY search result status code 5, this indicates that there is no category associated for search query. ### NO_INDEX **Type:** Number = 8 NO_INDEX search result status code 8, this indicates that there is no active search index available. ### NOT_EXECUTED **Type:** Number = 0 NOT_EXECUTED search result status code 0, this indicates that search API call has not been made on SearchModel. ### OFFLINE_CATEGORY **Type:** Number = 7 OFFLINE_CATEGORY search result status code 7, this indicates that the category associated with search query is offline. ### ROOT_SEARCH **Type:** Number = 3 ROOT_SEARCH search result status code 3, this indicates that search result is returned for ROOT search. ### SUCCESSFUL **Type:** Number = 1 SUCCESSFUL search result status code 1, this indicates that search API call is executed without any issue. ## Properties ### description **Type:** String (Read Only) Returns status code description of search result, it provides more details about search API call status. ### statusCode **Type:** Number (Read Only) Returns status code of search result, by default it will return 0 which means that search has not been executed on SearchModel. ## Constructor Summary ## Method Summary ### getDescription **Signature:** `getDescription() : String` Returns status code description of search result, it provides more details about search API call status. ### getStatusCode **Signature:** `getStatusCode() : Number` Returns status code of search result, by default it will return 0 which means that search has not been executed on SearchModel. ### toString **Signature:** `toString() : String` Returns string values of status code and description. ## Method Detail ## Method Details ### getDescription **Signature:** `getDescription() : String` **Description:** Returns status code description of search result, it provides more details about search API call status. **Returns:** search status description --- ### getStatusCode **Signature:** `getStatusCode() : Number` **Description:** Returns status code of search result, by default it will return 0 which means that search has not been executed on SearchModel. **Returns:** search status code --- ### toString **Signature:** `toString() : String` **Description:** Returns string values of status code and description. **Returns:** search status string --- ``` -------------------------------------------------------------------------------- /docs/dw_object/CustomAttributes.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.object # Class CustomAttributes ## Inheritance Hierarchy - Object - dw.object.CustomAttributes ## Description This class is used together with other classes that contain custom attributes and is used to read and write these attributes. The actual attributes are accessible as ECMA properties. The syntax for setting and retrieving the value of a custom attribute depends upon the type of the attribute. If the wrong syntax is used to set an individual attribute than an exception will be thrown. The following script examples demonstrate how to work with custom attributes. Suppose we have an ExtensibleObject named "eo" possessing attributes of all the different types supported by the Commerce Cloud Digital metadata system. The following script snippet shows that setting single-valued attributes is simply a matter of using the assignment operator and standard ECMA primitives and built-in types: // attribute of value type 'Boolean' eo.custom.bvalue = true; var b : Boolean = eo.custom.bvalue; // attribute of value type 'Integer' eo.custom.ivalue = 10; var i : Number = eo.custom.ivalue; // attribute of value type 'Number' eo.custom.dvalue = 99.99; var d : Number = eo.custom.dvalue; // attribute of value type 'String' eo.custom.svalue = "String1"; var s : String = eo.custom.svalue; // attribute of value type 'Email' eo.custom.emailvalue = "[email protected]"; var e : String = eo.custom.emailvalue; // attribute of value type 'Text' eo.custom.tvalue = "laaaaaaaaaaaarge text"; var t : String = eo.custom.tvalue; // attribute of value type 'Date' eo.custom.dtvalue = new Date; var date : Date = eo.custom.dtvalue; Setting and retrieving the values for multi-value attributes is also straightforward and uses ECMA arrays to represent the multiple values. Set-of attributes and enum-of attributes are handled in a very similar manner. The chief difference is that enum-of attributes are limited to a prescribed set of value definitions whereas set-of attributes are open-ended. Furthermore, each value in an enum-of attribute has a value and a display name which affects the retrieval logic. Multi-value attributes are returned as an array. This array is read-only and can't be used to update the multi-value attribute. To update the multi-value attribute an array with new values must be assigned to the attribute. // attribute of value type 'Set of String' // set the attribute value only if it hasn't been already set if( !('setofstringvalue' in eo.custom) ) { eo.custom.setofstringvalue = new Array("abc","def","ghi"); } // returns an Array of String instances var setofstring : Array = eo.custom.setofstringvalue; var s1 : String = setofstring[0]; var s2 : String = setofstring[1]; var s3 : String = setofstring[2]; // attribute of value type 'Enum of Integer' with multi-value handling eo.custom.enumofintmultivalue = new Array(1, 2, 3); // returns an Array of EnumValue instances var enumofintmulti : Array = eo.custom.enumofintmultivalue; var value1 : Number = enumofintmulti[0].getValue(); var displayvalue1 : String = enumofintmulti[0].getDisplayValue(); var value2 : Number = enumofintmulti[1].getValue(); var displayvalue2 : String = enumofintmulti[1].getDisplayValue(); var value3 : Number = enumofintmulti[2].getValue(); var displayvalue3 : String = enumofintmulti[2].getDisplayValue(); For further details on the Commerce Cloud Digital attribute system, see the core Commerce Cloud Digital documentation. ## Constructor Summary ## Method Summary ``` -------------------------------------------------------------------------------- /docs/dw_util/SortedMap.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.util # Class SortedMap ## Inheritance Hierarchy - Object - dw.util.Map - dw.util.SortedMap ## Description A map that further guarantees that it will be in ascending key order, sorted according to the natural ordering of its keys, or by a comparator provided at sorted map creation time. This order is reflected when iterating over the sorted map's collection views (returned by the entrySet, keySet and values methods). Note that sorting by natural order is only supported for Number, String, Date, Money and Quantity as key. ## Constructor Summary SortedMap() Constructor to create a new SortedMap. SortedMap(comparator : Object) Constructor to create a new SortedMap. ## Method Summary ### clone **Signature:** `clone() : SortedMap` Returns a shallow copy of this map. ### firstKey **Signature:** `firstKey() : Object` Returns the first (lowest) key currently in this sorted map. ### headMap **Signature:** `headMap(key : Object) : SortedMap` Returns a view of the portion of this map whose keys are strictly less than toKey. ### lastKey **Signature:** `lastKey() : Object` Returns the last (highest) key currently in this sorted map. ### subMap **Signature:** `subMap(from : Object, to : Object) : SortedMap` Returns a view of the portion of this map whose keys range from fromKey, inclusive, to toKey, exclusive. ### tailMap **Signature:** `tailMap(key : Object) : SortedMap` Returns a view of the portion of this map whose keys are greater than or equal to fromKey. ## Constructor Detail ## Method Detail ## Method Details ### clone **Signature:** `clone() : SortedMap` **Description:** Returns a shallow copy of this map. **Returns:** a shallow copy of this map. --- ### firstKey **Signature:** `firstKey() : Object` **Description:** Returns the first (lowest) key currently in this sorted map. **Returns:** the first (lowest) key currently in this sorted map. --- ### headMap **Signature:** `headMap(key : Object) : SortedMap` **Description:** Returns a view of the portion of this map whose keys are strictly less than toKey. **Parameters:** - `key`: high endpoint (exclusive) of the headMap. **Returns:** a view of the portion of this map whose keys are strictly less than toKey. --- ### lastKey **Signature:** `lastKey() : Object` **Description:** Returns the last (highest) key currently in this sorted map. **Returns:** the last (highest) key currently in this sorted map. --- ### subMap **Signature:** `subMap(from : Object, to : Object) : SortedMap` **Description:** Returns a view of the portion of this map whose keys range from fromKey, inclusive, to toKey, exclusive. (If fromKey and toKey are equal, the returned sorted map is empty.) **Parameters:** - `from`: low endpoint (inclusive) of the subMap. - `to`: high endpoint (exclusive) of the subMap. **Returns:** a view of the portion of this map whose keys range from fromKey, inclusive, to toKey, exclusive. --- ### tailMap **Signature:** `tailMap(key : Object) : SortedMap` **Description:** Returns a view of the portion of this map whose keys are greater than or equal to fromKey. The returned sorted map is backed by this map, so changes in the returned sorted map are reflected in this map, and vice-versa. The returned sorted map supports all optional map operations. **Parameters:** - `key`: low endpoint (inclusive) of the tailMap. **Returns:** a view of the portion of this map whose keys are greater than or equal to fromKey. --- ```