#
tokens: 49269/50000 36/825 files (page 6/61)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 6 of 61. Use http://codebase.md/taurgis/sfcc-dev-mcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .DS_Store
├── .github
│   ├── dependabot.yml
│   ├── instructions
│   │   ├── mcp-node-tests.instructions.md
│   │   └── mcp-yml-tests.instructions.md
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   ├── documentation.yml
│   │   ├── feature_request.yml
│   │   └── question.yml
│   ├── PULL_REQUEST_TEMPLATE
│   │   ├── bug_fix.md
│   │   ├── documentation.md
│   │   └── new_tool.md
│   ├── pull_request_template.md
│   └── workflows
│       ├── ci.yml
│       ├── deploy-pages.yml
│       ├── publish.yml
│       └── update-docs.yml
├── .gitignore
├── .husky
│   └── pre-commit
├── aegis.config.docs-only.json
├── aegis.config.json
├── aegis.config.with-dw.json
├── AGENTS.md
├── ai-instructions
│   ├── claude-desktop
│   │   └── claude_custom_instructions.md
│   ├── cursor
│   │   └── .cursor
│   │       └── rules
│   │           ├── debugging-workflows.mdc
│   │           ├── hooks-development.mdc
│   │           ├── isml-templates.mdc
│   │           ├── job-framework.mdc
│   │           ├── performance-optimization.mdc
│   │           ├── scapi-endpoints.mdc
│   │           ├── security-patterns.mdc
│   │           ├── sfcc-development.mdc
│   │           ├── sfra-controllers.mdc
│   │           ├── sfra-models.mdc
│   │           ├── system-objects.mdc
│   │           └── testing-patterns.mdc
│   └── github-copilot
│       └── copilot-instructions.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── docs
│   ├── best-practices
│   │   ├── cartridge_creation.md
│   │   ├── isml_templates.md
│   │   ├── job_framework.md
│   │   ├── localserviceregistry.md
│   │   ├── ocapi_hooks.md
│   │   ├── performance.md
│   │   ├── scapi_custom_endpoint.md
│   │   ├── scapi_hooks.md
│   │   ├── security.md
│   │   ├── sfra_client_side_js.md
│   │   ├── sfra_controllers.md
│   │   ├── sfra_models.md
│   │   └── sfra_scss.md
│   ├── dw_campaign
│   │   ├── ABTest.md
│   │   ├── ABTestMgr.md
│   │   ├── ABTestSegment.md
│   │   ├── AmountDiscount.md
│   │   ├── ApproachingDiscount.md
│   │   ├── BonusChoiceDiscount.md
│   │   ├── BonusDiscount.md
│   │   ├── Campaign.md
│   │   ├── CampaignMgr.md
│   │   ├── CampaignStatusCodes.md
│   │   ├── Coupon.md
│   │   ├── CouponMgr.md
│   │   ├── CouponRedemption.md
│   │   ├── CouponStatusCodes.md
│   │   ├── Discount.md
│   │   ├── DiscountPlan.md
│   │   ├── FixedPriceDiscount.md
│   │   ├── FixedPriceShippingDiscount.md
│   │   ├── FreeDiscount.md
│   │   ├── FreeShippingDiscount.md
│   │   ├── PercentageDiscount.md
│   │   ├── PercentageOptionDiscount.md
│   │   ├── PriceBookPriceDiscount.md
│   │   ├── Promotion.md
│   │   ├── PromotionMgr.md
│   │   ├── PromotionPlan.md
│   │   ├── SlotContent.md
│   │   ├── SourceCodeGroup.md
│   │   ├── SourceCodeInfo.md
│   │   ├── SourceCodeStatusCodes.md
│   │   └── TotalFixedPriceDiscount.md
│   ├── dw_catalog
│   │   ├── Catalog.md
│   │   ├── CatalogMgr.md
│   │   ├── Category.md
│   │   ├── CategoryAssignment.md
│   │   ├── CategoryLink.md
│   │   ├── PriceBook.md
│   │   ├── PriceBookMgr.md
│   │   ├── Product.md
│   │   ├── ProductActiveData.md
│   │   ├── ProductAttributeModel.md
│   │   ├── ProductAvailabilityLevels.md
│   │   ├── ProductAvailabilityModel.md
│   │   ├── ProductInventoryList.md
│   │   ├── ProductInventoryMgr.md
│   │   ├── ProductInventoryRecord.md
│   │   ├── ProductLink.md
│   │   ├── ProductMgr.md
│   │   ├── ProductOption.md
│   │   ├── ProductOptionModel.md
│   │   ├── ProductOptionValue.md
│   │   ├── ProductPriceInfo.md
│   │   ├── ProductPriceModel.md
│   │   ├── ProductPriceTable.md
│   │   ├── ProductSearchHit.md
│   │   ├── ProductSearchModel.md
│   │   ├── ProductSearchRefinementDefinition.md
│   │   ├── ProductSearchRefinements.md
│   │   ├── ProductSearchRefinementValue.md
│   │   ├── ProductVariationAttribute.md
│   │   ├── ProductVariationAttributeValue.md
│   │   ├── ProductVariationModel.md
│   │   ├── Recommendation.md
│   │   ├── SearchModel.md
│   │   ├── SearchRefinementDefinition.md
│   │   ├── SearchRefinements.md
│   │   ├── SearchRefinementValue.md
│   │   ├── SortingOption.md
│   │   ├── SortingRule.md
│   │   ├── Store.md
│   │   ├── StoreGroup.md
│   │   ├── StoreInventoryFilter.md
│   │   ├── StoreInventoryFilterValue.md
│   │   ├── StoreMgr.md
│   │   ├── Variant.md
│   │   └── VariationGroup.md
│   ├── dw_content
│   │   ├── Content.md
│   │   ├── ContentMgr.md
│   │   ├── ContentSearchModel.md
│   │   ├── ContentSearchRefinementDefinition.md
│   │   ├── ContentSearchRefinements.md
│   │   ├── ContentSearchRefinementValue.md
│   │   ├── Folder.md
│   │   ├── Library.md
│   │   ├── MarkupText.md
│   │   └── MediaFile.md
│   ├── dw_crypto
│   │   ├── CertificateRef.md
│   │   ├── CertificateUtils.md
│   │   ├── Cipher.md
│   │   ├── Encoding.md
│   │   ├── JWE.md
│   │   ├── JWEHeader.md
│   │   ├── JWS.md
│   │   ├── JWSHeader.md
│   │   ├── KeyRef.md
│   │   ├── Mac.md
│   │   ├── MessageDigest.md
│   │   ├── SecureRandom.md
│   │   ├── Signature.md
│   │   ├── WeakCipher.md
│   │   ├── WeakMac.md
│   │   ├── WeakMessageDigest.md
│   │   ├── WeakSignature.md
│   │   └── X509Certificate.md
│   ├── dw_customer
│   │   ├── AddressBook.md
│   │   ├── AgentUserMgr.md
│   │   ├── AgentUserStatusCodes.md
│   │   ├── AuthenticationStatus.md
│   │   ├── Credentials.md
│   │   ├── Customer.md
│   │   ├── CustomerActiveData.md
│   │   ├── CustomerAddress.md
│   │   ├── CustomerCDPData.md
│   │   ├── CustomerContextMgr.md
│   │   ├── CustomerGroup.md
│   │   ├── CustomerList.md
│   │   ├── CustomerMgr.md
│   │   ├── CustomerPasswordConstraints.md
│   │   ├── CustomerPaymentInstrument.md
│   │   ├── CustomerStatusCodes.md
│   │   ├── EncryptedObject.md
│   │   ├── ExternalProfile.md
│   │   ├── OrderHistory.md
│   │   ├── ProductList.md
│   │   ├── ProductListItem.md
│   │   ├── ProductListItemPurchase.md
│   │   ├── ProductListMgr.md
│   │   ├── ProductListRegistrant.md
│   │   ├── Profile.md
│   │   └── Wallet.md
│   ├── dw_extensions.applepay
│   │   ├── ApplePayHookResult.md
│   │   └── ApplePayHooks.md
│   ├── dw_extensions.facebook
│   │   ├── FacebookFeedHooks.md
│   │   └── FacebookProduct.md
│   ├── dw_extensions.paymentrequest
│   │   ├── PaymentRequestHookResult.md
│   │   └── PaymentRequestHooks.md
│   ├── dw_extensions.payments
│   │   ├── SalesforceBancontactPaymentDetails.md
│   │   ├── SalesforceCardPaymentDetails.md
│   │   ├── SalesforceEpsPaymentDetails.md
│   │   ├── SalesforceIdealPaymentDetails.md
│   │   ├── SalesforceKlarnaPaymentDetails.md
│   │   ├── SalesforcePaymentDetails.md
│   │   ├── SalesforcePaymentIntent.md
│   │   ├── SalesforcePaymentMethod.md
│   │   ├── SalesforcePaymentRequest.md
│   │   ├── SalesforcePaymentsHooks.md
│   │   ├── SalesforcePaymentsMgr.md
│   │   ├── SalesforcePaymentsSiteConfiguration.md
│   │   ├── SalesforcePayPalOrder.md
│   │   ├── SalesforcePayPalOrderAddress.md
│   │   ├── SalesforcePayPalOrderPayer.md
│   │   ├── SalesforcePayPalPaymentDetails.md
│   │   ├── SalesforceSepaDebitPaymentDetails.md
│   │   └── SalesforceVenmoPaymentDetails.md
│   ├── dw_extensions.pinterest
│   │   ├── PinterestAvailability.md
│   │   ├── PinterestFeedHooks.md
│   │   ├── PinterestOrder.md
│   │   ├── PinterestOrderHooks.md
│   │   └── PinterestProduct.md
│   ├── dw_io
│   │   ├── CSVStreamReader.md
│   │   ├── CSVStreamWriter.md
│   │   ├── File.md
│   │   ├── FileReader.md
│   │   ├── FileWriter.md
│   │   ├── InputStream.md
│   │   ├── OutputStream.md
│   │   ├── PrintWriter.md
│   │   ├── RandomAccessFileReader.md
│   │   ├── Reader.md
│   │   ├── StringWriter.md
│   │   ├── Writer.md
│   │   ├── XMLIndentingStreamWriter.md
│   │   ├── XMLStreamConstants.md
│   │   ├── XMLStreamReader.md
│   │   └── XMLStreamWriter.md
│   ├── dw_job
│   │   ├── JobExecution.md
│   │   └── JobStepExecution.md
│   ├── dw_net
│   │   ├── FTPClient.md
│   │   ├── FTPFileInfo.md
│   │   ├── HTTPClient.md
│   │   ├── HTTPRequestPart.md
│   │   ├── Mail.md
│   │   ├── SFTPClient.md
│   │   ├── SFTPFileInfo.md
│   │   ├── WebDAVClient.md
│   │   └── WebDAVFileInfo.md
│   ├── dw_object
│   │   ├── ActiveData.md
│   │   ├── CustomAttributes.md
│   │   ├── CustomObject.md
│   │   ├── CustomObjectMgr.md
│   │   ├── Extensible.md
│   │   ├── ExtensibleObject.md
│   │   ├── Note.md
│   │   ├── ObjectAttributeDefinition.md
│   │   ├── ObjectAttributeGroup.md
│   │   ├── ObjectAttributeValueDefinition.md
│   │   ├── ObjectTypeDefinition.md
│   │   ├── PersistentObject.md
│   │   ├── SimpleExtensible.md
│   │   └── SystemObjectMgr.md
│   ├── dw_order
│   │   ├── AbstractItem.md
│   │   ├── AbstractItemCtnr.md
│   │   ├── Appeasement.md
│   │   ├── AppeasementItem.md
│   │   ├── Basket.md
│   │   ├── BasketMgr.md
│   │   ├── BonusDiscountLineItem.md
│   │   ├── CouponLineItem.md
│   │   ├── CreateAgentBasketLimitExceededException.md
│   │   ├── CreateBasketFromOrderException.md
│   │   ├── CreateCouponLineItemException.md
│   │   ├── CreateOrderException.md
│   │   ├── CreateTemporaryBasketLimitExceededException.md
│   │   ├── GiftCertificate.md
│   │   ├── GiftCertificateLineItem.md
│   │   ├── GiftCertificateMgr.md
│   │   ├── GiftCertificateStatusCodes.md
│   │   ├── Invoice.md
│   │   ├── InvoiceItem.md
│   │   ├── LineItem.md
│   │   ├── LineItemCtnr.md
│   │   ├── Order.md
│   │   ├── OrderAddress.md
│   │   ├── OrderItem.md
│   │   ├── OrderMgr.md
│   │   ├── OrderPaymentInstrument.md
│   │   ├── OrderProcessStatusCodes.md
│   │   ├── PaymentCard.md
│   │   ├── PaymentInstrument.md
│   │   ├── PaymentMethod.md
│   │   ├── PaymentMgr.md
│   │   ├── PaymentProcessor.md
│   │   ├── PaymentStatusCodes.md
│   │   ├── PaymentTransaction.md
│   │   ├── PriceAdjustment.md
│   │   ├── PriceAdjustmentLimitTypes.md
│   │   ├── ProductLineItem.md
│   │   ├── ProductShippingCost.md
│   │   ├── ProductShippingLineItem.md
│   │   ├── ProductShippingModel.md
│   │   ├── Return.md
│   │   ├── ReturnCase.md
│   │   ├── ReturnCaseItem.md
│   │   ├── ReturnItem.md
│   │   ├── Shipment.md
│   │   ├── ShipmentShippingCost.md
│   │   ├── ShipmentShippingModel.md
│   │   ├── ShippingLineItem.md
│   │   ├── ShippingLocation.md
│   │   ├── ShippingMethod.md
│   │   ├── ShippingMgr.md
│   │   ├── ShippingOrder.md
│   │   ├── ShippingOrderItem.md
│   │   ├── SumItem.md
│   │   ├── TaxGroup.md
│   │   ├── TaxItem.md
│   │   ├── TaxMgr.md
│   │   ├── TrackingInfo.md
│   │   └── TrackingRef.md
│   ├── dw_order.hooks
│   │   ├── CalculateHooks.md
│   │   ├── OrderHooks.md
│   │   ├── PaymentHooks.md
│   │   ├── ReturnHooks.md
│   │   └── ShippingOrderHooks.md
│   ├── dw_rpc
│   │   ├── SOAPUtil.md
│   │   ├── Stub.md
│   │   └── WebReference.md
│   ├── dw_suggest
│   │   ├── BrandSuggestions.md
│   │   ├── CategorySuggestions.md
│   │   ├── ContentSuggestions.md
│   │   ├── CustomSuggestions.md
│   │   ├── ProductSuggestions.md
│   │   ├── SearchPhraseSuggestions.md
│   │   ├── SuggestedCategory.md
│   │   ├── SuggestedContent.md
│   │   ├── SuggestedPhrase.md
│   │   ├── SuggestedProduct.md
│   │   ├── SuggestedTerm.md
│   │   ├── SuggestedTerms.md
│   │   ├── Suggestions.md
│   │   └── SuggestModel.md
│   ├── dw_svc
│   │   ├── FTPService.md
│   │   ├── FTPServiceDefinition.md
│   │   ├── HTTPFormService.md
│   │   ├── HTTPFormServiceDefinition.md
│   │   ├── HTTPService.md
│   │   ├── HTTPServiceDefinition.md
│   │   ├── LocalServiceRegistry.md
│   │   ├── Result.md
│   │   ├── Service.md
│   │   ├── ServiceCallback.md
│   │   ├── ServiceConfig.md
│   │   ├── ServiceCredential.md
│   │   ├── ServiceDefinition.md
│   │   ├── ServiceProfile.md
│   │   ├── ServiceRegistry.md
│   │   ├── SOAPService.md
│   │   └── SOAPServiceDefinition.md
│   ├── dw_system
│   │   ├── AgentUserStatusCodes.md
│   │   ├── Cache.md
│   │   ├── CacheMgr.md
│   │   ├── HookMgr.md
│   │   ├── InternalObject.md
│   │   ├── JobProcessMonitor.md
│   │   ├── Log.md
│   │   ├── Logger.md
│   │   ├── LogNDC.md
│   │   ├── OrganizationPreferences.md
│   │   ├── Pipeline.md
│   │   ├── PipelineDictionary.md
│   │   ├── RemoteInclude.md
│   │   ├── Request.md
│   │   ├── RequestHooks.md
│   │   ├── Response.md
│   │   ├── RESTErrorResponse.md
│   │   ├── RESTResponseMgr.md
│   │   ├── RESTSuccessResponse.md
│   │   ├── SearchStatus.md
│   │   ├── Session.md
│   │   ├── Site.md
│   │   ├── SitePreferences.md
│   │   ├── Status.md
│   │   ├── StatusItem.md
│   │   ├── System.md
│   │   └── Transaction.md
│   ├── dw_util
│   │   ├── ArrayList.md
│   │   ├── Assert.md
│   │   ├── BigInteger.md
│   │   ├── Bytes.md
│   │   ├── Calendar.md
│   │   ├── Collection.md
│   │   ├── Currency.md
│   │   ├── DateUtils.md
│   │   ├── Decimal.md
│   │   ├── FilteringCollection.md
│   │   ├── Geolocation.md
│   │   ├── HashMap.md
│   │   ├── HashSet.md
│   │   ├── Iterator.md
│   │   ├── LinkedHashMap.md
│   │   ├── LinkedHashSet.md
│   │   ├── List.md
│   │   ├── Locale.md
│   │   ├── Map.md
│   │   ├── MapEntry.md
│   │   ├── MappingKey.md
│   │   ├── MappingMgr.md
│   │   ├── PropertyComparator.md
│   │   ├── SecureEncoder.md
│   │   ├── SecureFilter.md
│   │   ├── SeekableIterator.md
│   │   ├── Set.md
│   │   ├── SortedMap.md
│   │   ├── SortedSet.md
│   │   ├── StringUtils.md
│   │   ├── Template.md
│   │   └── UUIDUtils.md
│   ├── dw_value
│   │   ├── EnumValue.md
│   │   ├── MimeEncodedText.md
│   │   ├── Money.md
│   │   └── Quantity.md
│   ├── dw_web
│   │   ├── ClickStream.md
│   │   ├── ClickStreamEntry.md
│   │   ├── Cookie.md
│   │   ├── Cookies.md
│   │   ├── CSRFProtection.md
│   │   ├── Form.md
│   │   ├── FormAction.md
│   │   ├── FormElement.md
│   │   ├── FormElementValidationResult.md
│   │   ├── FormField.md
│   │   ├── FormFieldOption.md
│   │   ├── FormFieldOptions.md
│   │   ├── FormGroup.md
│   │   ├── FormList.md
│   │   ├── FormListItem.md
│   │   ├── Forms.md
│   │   ├── HttpParameter.md
│   │   ├── HttpParameterMap.md
│   │   ├── LoopIterator.md
│   │   ├── PageMetaData.md
│   │   ├── PageMetaTag.md
│   │   ├── PagingModel.md
│   │   ├── Resource.md
│   │   ├── URL.md
│   │   ├── URLAction.md
│   │   ├── URLParameter.md
│   │   ├── URLRedirect.md
│   │   ├── URLRedirectMgr.md
│   │   └── URLUtils.md
│   ├── sfra
│   │   ├── account.md
│   │   ├── address.md
│   │   ├── billing.md
│   │   ├── cart.md
│   │   ├── categories.md
│   │   ├── content.md
│   │   ├── locale.md
│   │   ├── order.md
│   │   ├── payment.md
│   │   ├── price-default.md
│   │   ├── price-range.md
│   │   ├── price-tiered.md
│   │   ├── product-bundle.md
│   │   ├── product-full.md
│   │   ├── product-line-items.md
│   │   ├── product-search.md
│   │   ├── product-tile.md
│   │   ├── querystring.md
│   │   ├── render.md
│   │   ├── request.md
│   │   ├── response.md
│   │   ├── server.md
│   │   ├── shipping.md
│   │   ├── store.md
│   │   ├── stores.md
│   │   └── totals.md
│   └── TopLevel
│       ├── APIException.md
│       ├── arguments.md
│       ├── Array.md
│       ├── ArrayBuffer.md
│       ├── BigInt.md
│       ├── Boolean.md
│       ├── ConversionError.md
│       ├── DataView.md
│       ├── Date.md
│       ├── Error.md
│       ├── ES6Iterator.md
│       ├── EvalError.md
│       ├── Fault.md
│       ├── Float32Array.md
│       ├── Float64Array.md
│       ├── Function.md
│       ├── Generator.md
│       ├── global.md
│       ├── Int16Array.md
│       ├── Int32Array.md
│       ├── Int8Array.md
│       ├── InternalError.md
│       ├── IOError.md
│       ├── Iterable.md
│       ├── Iterator.md
│       ├── JSON.md
│       ├── Map.md
│       ├── Math.md
│       ├── Module.md
│       ├── Namespace.md
│       ├── Number.md
│       ├── Object.md
│       ├── QName.md
│       ├── RangeError.md
│       ├── ReferenceError.md
│       ├── RegExp.md
│       ├── Set.md
│       ├── StopIteration.md
│       ├── String.md
│       ├── Symbol.md
│       ├── SyntaxError.md
│       ├── SystemError.md
│       ├── TypeError.md
│       ├── Uint16Array.md
│       ├── Uint32Array.md
│       ├── Uint8Array.md
│       ├── Uint8ClampedArray.md
│       ├── URIError.md
│       ├── WeakMap.md
│       ├── WeakSet.md
│       ├── XML.md
│       ├── XMLList.md
│       └── XMLStreamError.md
├── docs-site
│   ├── .gitignore
│   ├── App.tsx
│   ├── components
│   │   ├── Badge.tsx
│   │   ├── BreadcrumbSchema.tsx
│   │   ├── CodeBlock.tsx
│   │   ├── Collapsible.tsx
│   │   ├── ConfigBuilder.tsx
│   │   ├── ConfigHero.tsx
│   │   ├── ConfigModeTabs.tsx
│   │   ├── icons.tsx
│   │   ├── Layout.tsx
│   │   ├── LightCodeContainer.tsx
│   │   ├── NewcomerCTA.tsx
│   │   ├── NextStepsStrip.tsx
│   │   ├── OnThisPage.tsx
│   │   ├── Search.tsx
│   │   ├── SEO.tsx
│   │   ├── Sidebar.tsx
│   │   ├── StructuredData.tsx
│   │   ├── ToolCard.tsx
│   │   ├── ToolFilters.tsx
│   │   ├── Typography.tsx
│   │   └── VersionBadge.tsx
│   ├── constants.tsx
│   ├── index.html
│   ├── main.tsx
│   ├── metadata.json
│   ├── package-lock.json
│   ├── package.json
│   ├── pages
│   │   ├── AIInterfacesPage.tsx
│   │   ├── ConfigurationPage.tsx
│   │   ├── DevelopmentPage.tsx
│   │   ├── ExamplesPage.tsx
│   │   ├── FeaturesPage.tsx
│   │   ├── HomePage.tsx
│   │   ├── SecurityPage.tsx
│   │   ├── ToolsPage.tsx
│   │   └── TroubleshootingPage.tsx
│   ├── postcss.config.js
│   ├── public
│   │   ├── .well-known
│   │   │   └── security.txt
│   │   ├── 404.html
│   │   ├── android-chrome-192x192.png
│   │   ├── android-chrome-512x512.png
│   │   ├── apple-touch-icon.png
│   │   ├── explain-product-pricing-methods-no-mcp.png
│   │   ├── explain-product-pricing-methods.png
│   │   ├── favicon-16x16.png
│   │   ├── favicon-32x32.png
│   │   ├── favicon.ico
│   │   ├── llms.txt
│   │   ├── robots.txt
│   │   ├── site.webmanifest
│   │   └── sitemap.xml
│   ├── README.md
│   ├── scripts
│   │   ├── generate-search-index.js
│   │   ├── generate-sitemap.js
│   │   └── search-dev.js
│   ├── src
│   │   └── styles
│   │       ├── input.css
│   │       └── prism-theme.css
│   ├── tailwind.config.js
│   ├── tsconfig.json
│   ├── types.ts
│   ├── utils
│   │   ├── search.ts
│   │   └── toolsData.ts
│   └── vite.config.ts
├── eslint.config.js
├── jest.config.js
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── scripts
│   └── convert-docs.js
├── SECURITY.md
├── server.json
├── src
│   ├── clients
│   │   ├── base
│   │   │   ├── http-client.ts
│   │   │   ├── oauth-token.ts
│   │   │   └── ocapi-auth-client.ts
│   │   ├── best-practices-client.ts
│   │   ├── cartridge-generation-client.ts
│   │   ├── docs
│   │   │   ├── class-content-parser.ts
│   │   │   ├── class-name-resolver.ts
│   │   │   ├── documentation-scanner.ts
│   │   │   ├── index.ts
│   │   │   └── referenced-types-extractor.ts
│   │   ├── docs-client.ts
│   │   ├── log-client.ts
│   │   ├── logs
│   │   │   ├── index.ts
│   │   │   ├── log-analyzer.ts
│   │   │   ├── log-client.ts
│   │   │   ├── log-constants.ts
│   │   │   ├── log-file-discovery.ts
│   │   │   ├── log-file-reader.ts
│   │   │   ├── log-formatter.ts
│   │   │   ├── log-processor.ts
│   │   │   ├── log-types.ts
│   │   │   └── webdav-client-manager.ts
│   │   ├── ocapi
│   │   │   ├── code-versions-client.ts
│   │   │   ├── site-preferences-client.ts
│   │   │   └── system-objects-client.ts
│   │   ├── ocapi-client.ts
│   │   └── sfra-client.ts
│   ├── config
│   │   ├── configuration-factory.ts
│   │   └── dw-json-loader.ts
│   ├── core
│   │   ├── handlers
│   │   │   ├── abstract-log-tool-handler.ts
│   │   │   ├── base-handler.ts
│   │   │   ├── best-practices-handler.ts
│   │   │   ├── cartridge-handler.ts
│   │   │   ├── client-factory.ts
│   │   │   ├── code-version-handler.ts
│   │   │   ├── docs-handler.ts
│   │   │   ├── job-log-handler.ts
│   │   │   ├── job-log-tool-config.ts
│   │   │   ├── log-handler.ts
│   │   │   ├── log-tool-config.ts
│   │   │   ├── sfra-handler.ts
│   │   │   ├── system-object-handler.ts
│   │   │   └── validation-helpers.ts
│   │   ├── server.ts
│   │   └── tool-definitions.ts
│   ├── index.ts
│   ├── main.ts
│   ├── services
│   │   ├── file-system-service.ts
│   │   ├── index.ts
│   │   └── path-service.ts
│   ├── tool-configs
│   │   ├── best-practices-tool-config.ts
│   │   ├── cartridge-tool-config.ts
│   │   ├── code-version-tool-config.ts
│   │   ├── docs-tool-config.ts
│   │   ├── job-log-tool-config.ts
│   │   ├── log-tool-config.ts
│   │   ├── sfra-tool-config.ts
│   │   └── system-object-tool-config.ts
│   ├── types
│   │   └── types.ts
│   └── utils
│       ├── cache.ts
│       ├── job-log-tool-config.ts
│       ├── job-log-utils.ts
│       ├── log-cache.ts
│       ├── log-tool-config.ts
│       ├── log-tool-constants.ts
│       ├── log-tool-utils.ts
│       ├── logger.ts
│       ├── ocapi-url-builder.ts
│       ├── path-resolver.ts
│       ├── query-builder.ts
│       ├── utils.ts
│       └── validator.ts
├── tests
│   ├── __mocks__
│   │   ├── docs-client.ts
│   │   ├── src
│   │   │   └── clients
│   │   │       └── base
│   │   │           └── http-client.js
│   │   └── webdav.js
│   ├── base-handler.test.ts
│   ├── base-http-client.test.ts
│   ├── best-practices-handler.test.ts
│   ├── cache.test.ts
│   ├── cartridge-handler.test.ts
│   ├── class-content-parser.test.ts
│   ├── class-name-resolver.test.ts
│   ├── client-factory.test.ts
│   ├── code-version-handler.test.ts
│   ├── code-versions-client.test.ts
│   ├── config.test.ts
│   ├── configuration-factory.test.ts
│   ├── docs-handler.test.ts
│   ├── documentation-scanner.test.ts
│   ├── file-system-service.test.ts
│   ├── job-log-handler.test.ts
│   ├── job-log-utils.test.ts
│   ├── log-client.test.ts
│   ├── log-handler.test.ts
│   ├── log-processor.test.ts
│   ├── logger.test.ts
│   ├── mcp
│   │   ├── AGENTS.md
│   │   ├── node
│   │   │   ├── activate-code-version-advanced.full-mode.programmatic.test.js
│   │   │   ├── code-versions.full-mode.programmatic.test.js
│   │   │   ├── generate-cartridge-structure.docs-only.programmatic.test.js
│   │   │   ├── get-available-best-practice-guides.docs-only.programmatic.test.js
│   │   │   ├── get-available-sfra-documents.programmatic.test.js
│   │   │   ├── get-best-practice-guide.docs-only.programmatic.test.js
│   │   │   ├── get-hook-reference.docs-only.programmatic.test.js
│   │   │   ├── get-job-execution-summary.full-mode.programmatic.test.js
│   │   │   ├── get-job-log-entries.full-mode.programmatic.test.js
│   │   │   ├── get-latest-debug.full-mode.programmatic.test.js
│   │   │   ├── get-latest-error.full-mode.programmatic.test.js
│   │   │   ├── get-latest-info.full-mode.programmatic.test.js
│   │   │   ├── get-latest-job-log-files.full-mode.programmatic.test.js
│   │   │   ├── get-latest-warn.full-mode.programmatic.test.js
│   │   │   ├── get-log-file-contents.full-mode.programmatic.test.js
│   │   │   ├── get-sfcc-class-documentation.docs-only.programmatic.test.js
│   │   │   ├── get-sfcc-class-info.docs-only.programmatic.test.js
│   │   │   ├── get-sfra-categories.docs-only.programmatic.test.js
│   │   │   ├── get-sfra-document.programmatic.test.js
│   │   │   ├── get-sfra-documents-by-category.docs-only.programmatic.test.js
│   │   │   ├── get-system-object-definition.full-mode.programmatic.test.js
│   │   │   ├── get-system-object-definitions.docs-only.programmatic.test.js
│   │   │   ├── get-system-object-definitions.full-mode.programmatic.test.js
│   │   │   ├── list-log-files.full-mode.programmatic.test.js
│   │   │   ├── list-sfcc-classes.docs-only.programmatic.test.js
│   │   │   ├── search-best-practices.docs-only.programmatic.test.js
│   │   │   ├── search-custom-object-attribute-definitions.full-mode.programmatic.test.js
│   │   │   ├── search-job-logs-by-name.full-mode.programmatic.test.js
│   │   │   ├── search-job-logs.full-mode.programmatic.test.js
│   │   │   ├── search-logs.full-mode.programmatic.test.js
│   │   │   ├── search-sfcc-classes.docs-only.programmatic.test.js
│   │   │   ├── search-sfcc-methods.docs-only.programmatic.test.js
│   │   │   ├── search-sfra-documentation.docs-only.programmatic.test.js
│   │   │   ├── search-site-preferences.full-mode.programmatic.test.js
│   │   │   ├── search-system-object-attribute-definitions.full-mode.programmatic.test.js
│   │   │   ├── search-system-object-attribute-groups.full-mode.programmatic.test.js
│   │   │   ├── summarize-logs.full-mode.programmatic.test.js
│   │   │   ├── tools.docs-only.programmatic.test.js
│   │   │   └── tools.full-mode.programmatic.test.js
│   │   ├── README.md
│   │   ├── test-fixtures
│   │   │   └── dw.json
│   │   └── yaml
│   │       ├── activate-code-version.docs-only.test.mcp.yml
│   │       ├── activate-code-version.full-mode.test.mcp.yml
│   │       ├── get_latest_error.test.mcp.yml
│   │       ├── get-available-best-practice-guides.docs-only.test.mcp.yml
│   │       ├── get-available-best-practice-guides.full-mode.test.mcp.yml
│   │       ├── get-available-sfra-documents.docs-only.test.mcp.yml
│   │       ├── get-available-sfra-documents.full-mode.test.mcp.yml
│   │       ├── get-best-practice-guide.docs-only.test.mcp.yml
│   │       ├── get-best-practice-guide.full-mode.test.mcp.yml
│   │       ├── get-code-versions.docs-only.test.mcp.yml
│   │       ├── get-code-versions.full-mode.test.mcp.yml
│   │       ├── get-hook-reference.docs-only.test.mcp.yml
│   │       ├── get-hook-reference.full-mode.test.mcp.yml
│   │       ├── get-job-execution-summary.full-mode.test.mcp.yml
│   │       ├── get-job-log-entries.full-mode.test.mcp.yml
│   │       ├── get-latest-debug.full-mode.test.mcp.yml
│   │       ├── get-latest-error.full-mode.test.mcp.yml
│   │       ├── get-latest-info.full-mode.test.mcp.yml
│   │       ├── get-latest-job-log-files.full-mode.test.mcp.yml
│   │       ├── get-latest-warn.full-mode.test.mcp.yml
│   │       ├── get-log-file-contents.full-mode.test.mcp.yml
│   │       ├── get-sfcc-class-documentation.docs-only.test.mcp.yml
│   │       ├── get-sfcc-class-documentation.full-mode.test.mcp.yml
│   │       ├── get-sfcc-class-info.docs-only.test.mcp.yml
│   │       ├── get-sfcc-class-info.full-mode.test.mcp.yml
│   │       ├── get-sfra-categories.docs-only.test.mcp.yml
│   │       ├── get-sfra-categories.full-mode.test.mcp.yml
│   │       ├── get-sfra-document.docs-only.test.mcp.yml
│   │       ├── get-sfra-document.full-mode.test.mcp.yml
│   │       ├── get-sfra-documents-by-category.docs-only.test.mcp.yml
│   │       ├── get-sfra-documents-by-category.full-mode.test.mcp.yml
│   │       ├── get-system-object-definition.docs-only.test.mcp.yml
│   │       ├── get-system-object-definition.full-mode.test.mcp.yml
│   │       ├── get-system-object-definitions.docs-only.test.mcp.yml
│   │       ├── get-system-object-definitions.full-mode.test.mcp.yml
│   │       ├── list-log-files.full-mode.test.mcp.yml
│   │       ├── list-sfcc-classes.docs-only.test.mcp.yml
│   │       ├── list-sfcc-classes.full-mode.test.mcp.yml
│   │       ├── search-best-practices.docs-only.test.mcp.yml
│   │       ├── search-best-practices.full-mode.test.mcp.yml
│   │       ├── search-custom-object-attribute-definitions.docs-only.test.mcp.yml
│   │       ├── search-custom-object-attribute-definitions.test.mcp.yml
│   │       ├── search-job-logs-by-name.full-mode.test.mcp.yml
│   │       ├── search-job-logs.full-mode.test.mcp.yml
│   │       ├── search-logs.full-mode.test.mcp.yml
│   │       ├── search-sfcc-classes.docs-only.test.mcp.yml
│   │       ├── search-sfcc-classes.full-mode.test.mcp.yml
│   │       ├── search-sfcc-methods.docs-only.test.mcp.yml
│   │       ├── search-sfcc-methods.full-mode.test.mcp.yml
│   │       ├── search-sfra-documentation.docs-only.test.mcp.yml
│   │       ├── search-sfra-documentation.full-mode.test.mcp.yml
│   │       ├── search-site-preferences.docs-only.test.mcp.yml
│   │       ├── search-site-preferences.full-mode.test.mcp.yml
│   │       ├── search-system-object-attribute-definitions.docs-only.test.mcp.yml
│   │       ├── search-system-object-attribute-definitions.full-mode.test.mcp.yml
│   │       ├── search-system-object-attribute-groups.docs-only.test.mcp.yml
│   │       ├── search-system-object-attribute-groups.full-mode.test.mcp.yml
│   │       ├── summarize-logs.full-mode.test.mcp.yml
│   │       ├── tools.docs-only.test.mcp.yml
│   │       └── tools.full-mode.test.mcp.yml
│   ├── oauth-token.test.ts
│   ├── ocapi-auth-client.test.ts
│   ├── ocapi-client.test.ts
│   ├── path-service.test.ts
│   ├── query-builder.test.ts
│   ├── referenced-types-extractor.test.ts
│   ├── servers
│   │   ├── sfcc-mock-server
│   │   │   ├── mock-data
│   │   │   │   └── ocapi
│   │   │   │       ├── code-versions.json
│   │   │   │       ├── custom-object-attributes-customapi.json
│   │   │   │       ├── custom-object-attributes-globalsettings.json
│   │   │   │       ├── custom-object-attributes-versionhistory.json
│   │   │   │       ├── site-preferences-ccv.json
│   │   │   │       ├── site-preferences-fastforward.json
│   │   │   │       ├── site-preferences-sfra.json
│   │   │   │       ├── site-preferences-storefront.json
│   │   │   │       ├── site-preferences-system.json
│   │   │   │       ├── system-object-attribute-groups-campaign.json
│   │   │   │       ├── system-object-attribute-groups-category.json
│   │   │   │       ├── system-object-attribute-groups-order.json
│   │   │   │       ├── system-object-attribute-groups-product.json
│   │   │   │       ├── system-object-attribute-groups-sitepreferences.json
│   │   │   │       ├── system-object-attributes-customeraddress.json
│   │   │   │       ├── system-object-attributes-product-expanded.json
│   │   │   │       ├── system-object-attributes-product.json
│   │   │   │       ├── system-object-definition-category.json
│   │   │   │       ├── system-object-definition-customer.json
│   │   │   │       ├── system-object-definition-customeraddress.json
│   │   │   │       ├── system-object-definition-order.json
│   │   │   │       ├── system-object-definition-product.json
│   │   │   │       ├── system-object-definitions-old.json
│   │   │   │       └── system-object-definitions.json
│   │   │   ├── package-lock.json
│   │   │   ├── package.json
│   │   │   ├── README.md
│   │   │   ├── scripts
│   │   │   │   └── setup-logs.js
│   │   │   ├── server.js
│   │   │   └── src
│   │   │       ├── app.js
│   │   │       ├── config
│   │   │       │   └── server-config.js
│   │   │       ├── middleware
│   │   │       │   ├── auth.js
│   │   │       │   ├── cors.js
│   │   │       │   └── logging.js
│   │   │       ├── routes
│   │   │       │   ├── ocapi
│   │   │       │   │   ├── code-versions-handler.js
│   │   │       │   │   ├── oauth-handler.js
│   │   │       │   │   ├── ocapi-error-utils.js
│   │   │       │   │   ├── ocapi-utils.js
│   │   │       │   │   ├── site-preferences-handler.js
│   │   │       │   │   └── system-objects-handler.js
│   │   │       │   ├── ocapi.js
│   │   │       │   └── webdav.js
│   │   │       └── utils
│   │   │           ├── mock-data-loader.js
│   │   │           └── webdav-xml.js
│   │   └── sfcc-mock-server-manager.ts
│   ├── sfcc-mock-server.test.ts
│   ├── site-preferences-client.test.ts
│   ├── system-objects-client.test.ts
│   ├── utils.test.ts
│   ├── validation-helpers.test.ts
│   └── validator.test.ts
├── tsconfig.json
└── tsconfig.test.json
```

# Files

--------------------------------------------------------------------------------
/src/clients/base/oauth-token.ts:
--------------------------------------------------------------------------------

```typescript
  1 | /**
  2 |  * OAuth Token Manager for SFCC OCAPI
  3 |  *
  4 |  * This module provides a singleton Token class that manages OAuth 2.0 access tokens
  5 |  * for SFCC OCAPI requests. It handles automatic token refresh when tokens expire.
  6 |  */
  7 | 
  8 | import { OAuthToken, OAuthTokenResponse } from '../../types/types.js';
  9 | 
 10 | /**
 11 |  * Singleton class for managing OAuth tokens
 12 |  * Handles token storage, expiration checking, and automatic refresh
 13 |  */
 14 | export class TokenManager {
 15 |   private static instance: TokenManager;
 16 |   private tokens: Map<string, OAuthToken> = new Map();
 17 | 
 18 |   private constructor() {}
 19 | 
 20 |   /**
 21 |    * Get the singleton instance of TokenManager
 22 |    */
 23 |   static getInstance(): TokenManager {
 24 |     if (!TokenManager.instance) {
 25 |       TokenManager.instance = new TokenManager();
 26 |     }
 27 |     return TokenManager.instance;
 28 |   }
 29 | 
 30 |   /**
 31 |    * Generate a unique key for the token based on hostname and client ID
 32 |    */
 33 |   private getTokenKey(hostname: string, clientId: string): string {
 34 |     return `${hostname}:${clientId}`;
 35 |   }
 36 | 
 37 |   /**
 38 |    * Check if a token is valid (exists and not expired)
 39 |    * Includes a 60-second buffer to avoid using tokens that are about to expire
 40 |    */
 41 |   isTokenValid(hostname: string, clientId: string): boolean {
 42 |     const key = this.getTokenKey(hostname, clientId);
 43 |     const token = this.tokens.get(key);
 44 | 
 45 |     if (!token) {
 46 |       return false;
 47 |     }
 48 | 
 49 |     // Add 60-second buffer to avoid using tokens that are about to expire
 50 |     const now = Date.now();
 51 |     const expirationBuffer = 60 * 1000; // 60 seconds in milliseconds
 52 | 
 53 |     return token.expiresAt > (now + expirationBuffer);
 54 |   }
 55 | 
 56 |   /**
 57 |    * Get a valid token for the given hostname and client ID
 58 |    * Returns null if no valid token exists
 59 |    */
 60 |   getValidToken(hostname: string, clientId: string): string | null {
 61 |     if (!this.isTokenValid(hostname, clientId)) {
 62 |       return null;
 63 |     }
 64 | 
 65 |     const key = this.getTokenKey(hostname, clientId);
 66 |     const token = this.tokens.get(key);
 67 |     return token?.accessToken ?? null;
 68 |   }
 69 | 
 70 |   /**
 71 |    * Store a new token from the OAuth response
 72 |    */
 73 |   storeToken(hostname: string, clientId: string, tokenResponse: OAuthTokenResponse): void {
 74 |     const key = this.getTokenKey(hostname, clientId);
 75 |     const now = Date.now();
 76 | 
 77 |     const token: OAuthToken = {
 78 |       accessToken: tokenResponse.access_token,
 79 |       tokenType: tokenResponse.token_type,
 80 |       expiresAt: now + (tokenResponse.expires_in * 1000), // Convert seconds to milliseconds
 81 |     };
 82 | 
 83 |     this.tokens.set(key, token);
 84 |   }
 85 | 
 86 |   /**
 87 |    * Clear a token (useful for testing or when a token becomes invalid)
 88 |    */
 89 |   clearToken(hostname: string, clientId: string): void {
 90 |     const key = this.getTokenKey(hostname, clientId);
 91 |     this.tokens.delete(key);
 92 |   }
 93 | 
 94 |   /**
 95 |    * Clear all tokens
 96 |    */
 97 |   clearAllTokens(): void {
 98 |     this.tokens.clear();
 99 |   }
100 | 
101 |   /**
102 |    * Get token expiration time for debugging purposes
103 |    */
104 |   getTokenExpiration(hostname: string, clientId: string): Date | null {
105 |     const key = this.getTokenKey(hostname, clientId);
106 |     const token = this.tokens.get(key);
107 | 
108 |     if (!token) {
109 |       return null;
110 |     }
111 | 
112 |     return new Date(token.expiresAt);
113 |   }
114 | }
115 | 
```

--------------------------------------------------------------------------------
/docs/TopLevel/Set.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: TopLevel
  2 | 
  3 | # Class Set
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - Set
  9 | 
 10 | ## Description
 11 | 
 12 | A Set can store any kind of element and ensures that no duplicates exist. Objects are stored and iterated in insertion order.
 13 | 
 14 | ## Properties
 15 | 
 16 | ### size
 17 | 
 18 | **Type:** Number
 19 | 
 20 | Number of elements stored in this set.
 21 | 
 22 | ## Constructor Summary
 23 | 
 24 | Set() Creates an empty Set.
 25 | 
 26 | Set(values : Iterable) If the passed value is null or undefined then an empty set is constructed.
 27 | 
 28 | ## Method Summary
 29 | 
 30 | ### add
 31 | 
 32 | **Signature:** `add(object : Object) : Set`
 33 | 
 34 | Adds an element to the set.
 35 | 
 36 | ### clear
 37 | 
 38 | **Signature:** `clear() : void`
 39 | 
 40 | Removes all elements from this set.
 41 | 
 42 | ### delete
 43 | 
 44 | **Signature:** `delete(object : Object) : boolean`
 45 | 
 46 | Removes the element from the set.
 47 | 
 48 | ### entries
 49 | 
 50 | **Signature:** `entries() : ES6Iterator`
 51 | 
 52 | Returns an iterator containing all elements of this set.
 53 | 
 54 | ### forEach
 55 | 
 56 | **Signature:** `forEach(callback : Function) : void`
 57 | 
 58 | Runs the provided callback function once for each element present in this set.
 59 | 
 60 | ### forEach
 61 | 
 62 | **Signature:** `forEach(callback : Function, thisObject : Object) : void`
 63 | 
 64 | Runs the provided callback function once for each element present in this set.
 65 | 
 66 | ### has
 67 | 
 68 | **Signature:** `has(object : Object) : boolean`
 69 | 
 70 | Returns if this set contains the given object.
 71 | 
 72 | ## Constructor Detail
 73 | 
 74 | ## Method Detail
 75 | 
 76 | ## Method Details
 77 | 
 78 | ### add
 79 | 
 80 | **Signature:** `add(object : Object) : Set`
 81 | 
 82 | **Description:** Adds an element to the set. Does nothing if the set already contains the element.
 83 | 
 84 | **Parameters:**
 85 | 
 86 | - `object`: The object to add.
 87 | 
 88 | **Returns:**
 89 | 
 90 | This set object.
 91 | 
 92 | ---
 93 | 
 94 | ### clear
 95 | 
 96 | **Signature:** `clear() : void`
 97 | 
 98 | **Description:** Removes all elements from this set.
 99 | 
100 | ---
101 | 
102 | ### delete
103 | 
104 | **Signature:** `delete(object : Object) : boolean`
105 | 
106 | **Description:** Removes the element from the set.
107 | 
108 | **Parameters:**
109 | 
110 | - `object`: The object to be removed.
111 | 
112 | **Returns:**
113 | 
114 | true if the set contained the object that was removed. Else false is returned.
115 | 
116 | ---
117 | 
118 | ### entries
119 | 
120 | **Signature:** `entries() : ES6Iterator`
121 | 
122 | **Description:** Returns an iterator containing all elements of this set.
123 | 
124 | ---
125 | 
126 | ### forEach
127 | 
128 | **Signature:** `forEach(callback : Function) : void`
129 | 
130 | **Description:** Runs the provided callback function once for each element present in this set.
131 | 
132 | **Parameters:**
133 | 
134 | - `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.
135 | 
136 | ---
137 | 
138 | ### forEach
139 | 
140 | **Signature:** `forEach(callback : Function, thisObject : Object) : void`
141 | 
142 | **Description:** Runs the provided callback function once for each element present in this set.
143 | 
144 | **Parameters:**
145 | 
146 | - `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.
147 | - `thisObject`: The Object to use as 'this' when executing callback.
148 | 
149 | ---
150 | 
151 | ### has
152 | 
153 | **Signature:** `has(object : Object) : boolean`
154 | 
155 | **Description:** Returns if this set contains the given object.
156 | 
157 | **Parameters:**
158 | 
159 | - `object`: The object to look for.
160 | 
161 | **Returns:**
162 | 
163 | true if the set contains the object else false is returned.
164 | 
165 | ---
```

--------------------------------------------------------------------------------
/docs/dw_object/ObjectAttributeGroup.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.object
  2 | 
  3 | # Class ObjectAttributeGroup
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.object.ObjectAttributeGroup
  9 | 
 10 | ## Description
 11 | 
 12 | Represents a group of object attributes.
 13 | 
 14 | ## Properties
 15 | 
 16 | ### attributeDefinitions
 17 | 
 18 | **Type:** Collection (Read Only)
 19 | 
 20 | All attribute definitions for this group. The collection
 21 |  may contain both system attribute definition as well as custom
 22 |  attribute definitions.
 23 | 
 24 | ### description
 25 | 
 26 | **Type:** String (Read Only)
 27 | 
 28 | The description of this group in the current locale.
 29 | 
 30 | ### displayName
 31 | 
 32 | **Type:** String (Read Only)
 33 | 
 34 | The display name of this group.
 35 | 
 36 | ### ID
 37 | 
 38 | **Type:** String (Read Only)
 39 | 
 40 | The ID of this group.
 41 | 
 42 | ### objectTypeDefinition
 43 | 
 44 | **Type:** ObjectTypeDefinition (Read Only)
 45 | 
 46 | The object type definition to which this attribute group
 47 |  belongs.
 48 | 
 49 | ### system
 50 | 
 51 | **Type:** boolean (Read Only)
 52 | 
 53 | Identifies if this is an sytem or a custom attribute group. A system
 54 |  attribute group is pre-defined and can not be deleted.
 55 | 
 56 | ## Constructor Summary
 57 | 
 58 | ## Method Summary
 59 | 
 60 | ### getAttributeDefinitions
 61 | 
 62 | **Signature:** `getAttributeDefinitions() : Collection`
 63 | 
 64 | Returns all attribute definitions for this group.
 65 | 
 66 | ### getDescription
 67 | 
 68 | **Signature:** `getDescription() : String`
 69 | 
 70 | Returns the description of this group in the current locale.
 71 | 
 72 | ### getDisplayName
 73 | 
 74 | **Signature:** `getDisplayName() : String`
 75 | 
 76 | Returns the display name of this group.
 77 | 
 78 | ### getID
 79 | 
 80 | **Signature:** `getID() : String`
 81 | 
 82 | Returns the ID of this group.
 83 | 
 84 | ### getObjectTypeDefinition
 85 | 
 86 | **Signature:** `getObjectTypeDefinition() : ObjectTypeDefinition`
 87 | 
 88 | Returns the object type definition to which this attribute group belongs.
 89 | 
 90 | ### isSystem
 91 | 
 92 | **Signature:** `isSystem() : boolean`
 93 | 
 94 | Identifies if this is an sytem or a custom attribute group.
 95 | 
 96 | ## Method Detail
 97 | 
 98 | ## Method Details
 99 | 
100 | ### getAttributeDefinitions
101 | 
102 | **Signature:** `getAttributeDefinitions() : Collection`
103 | 
104 | **Description:** Returns all attribute definitions for this group. The collection may contain both system attribute definition as well as custom attribute definitions.
105 | 
106 | **Returns:**
107 | 
108 | all attribute definitions for this group.
109 | 
110 | ---
111 | 
112 | ### getDescription
113 | 
114 | **Signature:** `getDescription() : String`
115 | 
116 | **Description:** Returns the description of this group in the current locale.
117 | 
118 | **Returns:**
119 | 
120 | the display name of this group.
121 | 
122 | ---
123 | 
124 | ### getDisplayName
125 | 
126 | **Signature:** `getDisplayName() : String`
127 | 
128 | **Description:** Returns the display name of this group.
129 | 
130 | **Returns:**
131 | 
132 | the display name of this group.
133 | 
134 | ---
135 | 
136 | ### getID
137 | 
138 | **Signature:** `getID() : String`
139 | 
140 | **Description:** Returns the ID of this group.
141 | 
142 | **Returns:**
143 | 
144 | the ID of this group.
145 | 
146 | ---
147 | 
148 | ### getObjectTypeDefinition
149 | 
150 | **Signature:** `getObjectTypeDefinition() : ObjectTypeDefinition`
151 | 
152 | **Description:** Returns the object type definition to which this attribute group belongs.
153 | 
154 | **Returns:**
155 | 
156 | the object type definition to which this attribute group belongs.
157 | 
158 | ---
159 | 
160 | ### isSystem
161 | 
162 | **Signature:** `isSystem() : boolean`
163 | 
164 | **Description:** Identifies if this is an sytem or a custom attribute group. A system attribute group is pre-defined and can not be deleted.
165 | 
166 | **Returns:**
167 | 
168 | true if this is a system attribute group, false otherwise.
169 | 
170 | ---
```

--------------------------------------------------------------------------------
/src/utils/log-cache.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { SFCCLogClient } from '../clients/log-client.js';
  2 | 
  3 | /**
  4 |  * Simple in-memory cache for log operations
  5 |  * Provides short-term caching to avoid repeated API calls for common operations
  6 |  */
  7 | export class LogCache {
  8 |   private cache = new Map<string, { data: any; timestamp: number; ttl: number }>();
  9 |   private readonly DEFAULT_TTL = 5000; // 5 seconds default TTL
 10 |   private readonly MAX_CACHE_SIZE = 100; // Prevent memory bloat
 11 | 
 12 |   /**
 13 |    * Get cached data if available and not expired
 14 |    */
 15 |   get<T>(key: string): T | null {
 16 |     const entry = this.cache.get(key);
 17 |     if (!entry) {
 18 |       return null;
 19 |     }
 20 | 
 21 |     // Check if expired
 22 |     if (Date.now() - entry.timestamp > entry.ttl) {
 23 |       this.cache.delete(key);
 24 |       return null;
 25 |     }
 26 | 
 27 |     return entry.data as T;
 28 |   }
 29 | 
 30 |   /**
 31 |    * Set cached data with TTL
 32 |    */
 33 |   set(key: string, data: any, ttl: number = this.DEFAULT_TTL): void {
 34 |     // Implement basic LRU by removing oldest entries when cache is full
 35 |     if (this.cache.size >= this.MAX_CACHE_SIZE) {
 36 |       const oldestKey = this.cache.keys().next().value;
 37 |       if (oldestKey) {
 38 |         this.cache.delete(oldestKey);
 39 |       }
 40 |     }
 41 | 
 42 |     this.cache.set(key, {
 43 |       data,
 44 |       timestamp: Date.now(),
 45 |       ttl,
 46 |     });
 47 |   }
 48 | 
 49 |   /**
 50 |    * Generate cache key for log operations
 51 |    */
 52 |   static generateKey(operation: string, args: Record<string, any>): string {
 53 |     const sortedArgs = Object.keys(args)
 54 |       .sort()
 55 |       .map(key => `${key}=${args[key]}`)
 56 |       .join('&');
 57 | 
 58 |     return `${operation}:${sortedArgs}`;
 59 |   }
 60 | 
 61 |   /**
 62 |    * Clear all cached entries
 63 |    */
 64 |   clear(): void {
 65 |     this.cache.clear();
 66 |   }
 67 | 
 68 |   /**
 69 |    * Remove expired entries (can be called periodically)
 70 |    */
 71 |   cleanup(): void {
 72 |     const now = Date.now();
 73 |     for (const [key, entry] of this.cache.entries()) {
 74 |       if (now - entry.timestamp > entry.ttl) {
 75 |         this.cache.delete(key);
 76 |       }
 77 |     }
 78 |   }
 79 | }
 80 | 
 81 | /**
 82 |  * Enhanced log client wrapper with caching capabilities
 83 |  * Provides transparent caching for frequently accessed log operations
 84 |  */
 85 | export class CachedLogClient {
 86 |   private cache = new LogCache();
 87 |   private readonly CACHEABLE_OPERATIONS = new Set([
 88 |     'list_log_files',
 89 |     'get_latest_job_log_files',
 90 |     'summarize_logs',
 91 |   ]);
 92 | 
 93 |   constructor(private logClient: SFCCLogClient) {}
 94 | 
 95 |   /**
 96 |    * Execute operation with caching if applicable
 97 |    */
 98 |   async executeWithCache<T>(
 99 |     operation: string,
100 |     args: Record<string, any>,
101 |     executor: () => Promise<T>,
102 |     ttl?: number,
103 |   ): Promise<T> {
104 |     // Only cache certain operations to avoid stale data issues
105 |     if (!this.CACHEABLE_OPERATIONS.has(operation)) {
106 |       return executor();
107 |     }
108 | 
109 |     const cacheKey = LogCache.generateKey(operation, args);
110 |     const cached = this.cache.get<T>(cacheKey);
111 | 
112 |     if (cached !== null) {
113 |       return cached;
114 |     }
115 | 
116 |     const result = await executor();
117 |     this.cache.set(cacheKey, result, ttl);
118 |     return result;
119 |   }
120 | 
121 |   /**
122 |    * Clear cache - useful when log state might have changed
123 |    */
124 |   clearCache(): void {
125 |     this.cache.clear();
126 |   }
127 | 
128 |   /**
129 |    * Cleanup expired cache entries
130 |    */
131 |   cleanupCache(): void {
132 |     this.cache.cleanup();
133 |   }
134 | }
135 | 
```

--------------------------------------------------------------------------------
/docs/TopLevel/Generator.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Package: TopLevel
 2 | 
 3 | # Class Generator
 4 | 
 5 | ## Inheritance Hierarchy
 6 | 
 7 | - Object
 8 |   - Generator
 9 | 
10 | ## Description
11 | 
12 | 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() " "); }
13 | 
14 | ## Constructor Summary
15 | 
16 | Generator()
17 | 
18 | ## Method Summary
19 | 
20 | ### close
21 | 
22 | **Signature:** `close() : void`
23 | 
24 | Closes the iteration of the generator.
25 | 
26 | ### next
27 | 
28 | **Signature:** `next() : Object`
29 | 
30 | Resumes the iteration of the generator by continuing the function at the statement after the yield statement.
31 | 
32 | ### send
33 | 
34 | **Signature:** `send(value : Object) : Object`
35 | 
36 | Allows you to control the resumption of the iterative algorithm.
37 | 
38 | ## Constructor Detail
39 | 
40 | ## Method Detail
41 | 
42 | ## Method Details
43 | 
44 | ### close
45 | 
46 | **Signature:** `close() : void`
47 | 
48 | **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.
49 | 
50 | ---
51 | 
52 | ### next
53 | 
54 | **Signature:** `next() : Object`
55 | 
56 | **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.
57 | 
58 | **Returns:**
59 | 
60 | the result of resuming the iterative algorithm or a StopIterator exception if the sequence is exhausted.
61 | 
62 | **See Also:**
63 | 
64 | StopIteration
65 | 
66 | ---
67 | 
68 | ### send
69 | 
70 | **Signature:** `send(value : Object) : Object`
71 | 
72 | **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.
73 | 
74 | **Parameters:**
75 | 
76 | - `value`: the value to use.
77 | 
78 | ---
```

--------------------------------------------------------------------------------
/docs/dw_crypto/JWEHeader.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.crypto
  2 | 
  3 | # Class JWEHeader
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.crypto.JWEHeader
  9 | 
 10 | ## Description
 11 | 
 12 | This class represents an immutable header of a JWE (JSON Web Encryption) object.
 13 | 
 14 | ## Properties
 15 | 
 16 | ### algorithm
 17 | 
 18 | **Type:** String (Read Only)
 19 | 
 20 | Get the value of the algorithm parameter (alg).
 21 | 
 22 | ### encryptionAlgorithm
 23 | 
 24 | **Type:** String (Read Only)
 25 | 
 26 | Get the value of the encryption algorithm parameter (enc).
 27 | 
 28 | ## Constructor Summary
 29 | 
 30 | ## Method Summary
 31 | 
 32 | ### getAlgorithm
 33 | 
 34 | **Signature:** `getAlgorithm() : String`
 35 | 
 36 | Get the value of the algorithm parameter (alg).
 37 | 
 38 | ### getEncryptionAlgorithm
 39 | 
 40 | **Signature:** `getEncryptionAlgorithm() : String`
 41 | 
 42 | Get the value of the encryption algorithm parameter (enc).
 43 | 
 44 | ### parse
 45 | 
 46 | **Signature:** `static parse(map : Object) : JWEHeader`
 47 | 
 48 | Convert the given Map or JavaScript object into a JWE header.
 49 | 
 50 | ### parseEncoded
 51 | 
 52 | **Signature:** `static parseEncoded(base64encoded : String) : JWEHeader`
 53 | 
 54 | Parse the given string as a Base64URL-encoded JWE header.
 55 | 
 56 | ### parseJSON
 57 | 
 58 | **Signature:** `static parseJSON(json : String) : JWEHeader`
 59 | 
 60 | Parse the given string as a JWE header.
 61 | 
 62 | ### toMap
 63 | 
 64 | **Signature:** `toMap() : Map`
 65 | 
 66 | Get a copy of these headers as a Map.
 67 | 
 68 | ### toString
 69 | 
 70 | **Signature:** `toString() : String`
 71 | 
 72 | Get the content of the headers as a JSON String.
 73 | 
 74 | ## Method Detail
 75 | 
 76 | ## Method Details
 77 | 
 78 | ### getAlgorithm
 79 | 
 80 | **Signature:** `getAlgorithm() : String`
 81 | 
 82 | **Description:** Get the value of the algorithm parameter (alg).
 83 | 
 84 | **Returns:**
 85 | 
 86 | Algorithm parameter from this header.
 87 | 
 88 | ---
 89 | 
 90 | ### getEncryptionAlgorithm
 91 | 
 92 | **Signature:** `getEncryptionAlgorithm() : String`
 93 | 
 94 | **Description:** Get the value of the encryption algorithm parameter (enc).
 95 | 
 96 | **Returns:**
 97 | 
 98 | Encryption algorithm parameter from this header.
 99 | 
100 | ---
101 | 
102 | ### parse
103 | 
104 | **Signature:** `static parse(map : Object) : JWEHeader`
105 | 
106 | **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.
107 | 
108 | **Parameters:**
109 | 
110 | - `map`: Map or object data to convert.
111 | 
112 | **Returns:**
113 | 
114 | JWE Header.
115 | 
116 | ---
117 | 
118 | ### parseEncoded
119 | 
120 | **Signature:** `static parseEncoded(base64encoded : String) : JWEHeader`
121 | 
122 | **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.
123 | 
124 | **Parameters:**
125 | 
126 | - `base64encoded`: Base64URL string to parse.
127 | 
128 | **Returns:**
129 | 
130 | JWE Header.
131 | 
132 | ---
133 | 
134 | ### parseJSON
135 | 
136 | **Signature:** `static parseJSON(json : String) : JWEHeader`
137 | 
138 | **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.
139 | 
140 | **Parameters:**
141 | 
142 | - `json`: JSON string to parse.
143 | 
144 | **Returns:**
145 | 
146 | JWE Header.
147 | 
148 | ---
149 | 
150 | ### toMap
151 | 
152 | **Signature:** `toMap() : Map`
153 | 
154 | **Description:** Get a copy of these headers as a Map.
155 | 
156 | **Returns:**
157 | 
158 | Copy of the JWE headers.
159 | 
160 | ---
161 | 
162 | ### toString
163 | 
164 | **Signature:** `toString() : String`
165 | 
166 | **Description:** Get the content of the headers as a JSON String.
167 | 
168 | **Returns:**
169 | 
170 | JSON String.
171 | 
172 | ---
```

--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.yml:
--------------------------------------------------------------------------------

```yaml
  1 | name: ❓ Question/Help
  2 | description: Ask a question or get help with using the SFCC Development MCP Server
  3 | title: "[Question]: "
  4 | labels: ["question", "needs-triage"]
  5 | assignees: []
  6 | body:
  7 |   - type: markdown
  8 |     attributes:
  9 |       value: |
 10 |         Need help or have a question? We're here to help! Please provide as much detail as possible so we can assist you effectively.
 11 | 
 12 |   - type: checkboxes
 13 |     id: terms
 14 |     attributes:
 15 |       label: Pre-submission Checklist
 16 |       description: Please confirm you have completed these steps before asking your question.
 17 |       options:
 18 |         - label: I have searched existing issues and discussions for similar questions
 19 |           required: true
 20 |         - label: I have read the README.md and relevant documentation
 21 |           required: true
 22 |         - label: I have checked the troubleshooting section (if applicable)
 23 |           required: true
 24 | 
 25 |   - type: dropdown
 26 |     id: question-category
 27 |     attributes:
 28 |       label: Question Category
 29 |       description: What category does your question fall into?
 30 |       options:
 31 |         - Installation and Setup
 32 |         - Configuration and Authentication
 33 |         - Using MCP Tools
 34 |         - SFCC Integration
 35 |         - Troubleshooting
 36 |         - Best Practices
 37 |         - Performance
 38 |         - Security
 39 |         - Development/Contributing
 40 |         - Other
 41 |     validations:
 42 |       required: true
 43 | 
 44 |   - type: textarea
 45 |     id: question
 46 |     attributes:
 47 |       label: Your Question
 48 |       description: What would you like to know?
 49 |       placeholder: Please ask your question clearly and provide context...
 50 |     validations:
 51 |       required: true
 52 | 
 53 |   - type: textarea
 54 |     id: context
 55 |     attributes:
 56 |       label: Context and Background
 57 |       description: Provide relevant context about what you're trying to accomplish
 58 |       placeholder: |
 59 |         - What are you trying to achieve?
 60 |         - What's your current setup?
 61 |         - What have you tried so far?
 62 | 
 63 |   - type: textarea
 64 |     id: current-setup
 65 |     attributes:
 66 |       label: Current Setup
 67 |       description: Describe your current configuration and environment
 68 |       value: |
 69 |         - OS: [e.g., macOS 14.1, Windows 11, Ubuntu 22.04]
 70 |         - Node.js version: [run `node --version`]
 71 |         - SFCC Dev MCP version: [check package.json version]
 72 |         - Operating mode: [Documentation-only or Full mode]
 73 |         - MCP Client: [e.g., Claude Desktop, Custom implementation]
 74 | 
 75 |   - type: textarea
 76 |     id: attempted-solutions
 77 |     attributes:
 78 |       label: What Have You Tried?
 79 |       description: What steps have you already taken to solve this?
 80 |       placeholder: |
 81 |         1. I tried...
 82 |         2. I looked at...
 83 |         3. I configured...
 84 | 
 85 |   - type: textarea
 86 |     id: expected-outcome
 87 |     attributes:
 88 |       label: Expected Outcome
 89 |       description: What do you expect or hope to happen?
 90 | 
 91 |   - type: textarea
 92 |     id: relevant-logs
 93 |     attributes:
 94 |       label: Relevant Logs or Error Messages
 95 |       description: Include any relevant logs or error messages (remove sensitive information)
 96 |       render: shell
 97 | 
 98 |   - type: textarea
 99 |     id: additional-info
100 |     attributes:
101 |       label: Additional Information
102 |       description: Any other information that might be helpful
103 | 
```

--------------------------------------------------------------------------------
/docs/dw_customer/Wallet.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.customer
  2 | 
  3 | # Class Wallet
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.customer.Wallet
  9 | 
 10 | ## Description
 11 | 
 12 | 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.
 13 | 
 14 | ## Properties
 15 | 
 16 | ### paymentInstruments
 17 | 
 18 | **Type:** Collection (Read Only)
 19 | 
 20 | A collection of all payment instruments associated with the
 21 |  related customer.
 22 | 
 23 | ## Constructor Summary
 24 | 
 25 | ## Method Summary
 26 | 
 27 | ### createPaymentInstrument
 28 | 
 29 | **Signature:** `createPaymentInstrument(paymentMethodId : String) : CustomerPaymentInstrument`
 30 | 
 31 | Creates a new, empty payment instrument object associated with the related customer for the given payment method.
 32 | 
 33 | ### getPaymentInstruments
 34 | 
 35 | **Signature:** `getPaymentInstruments() : Collection`
 36 | 
 37 | Returns a collection of all payment instruments associated with the related customer.
 38 | 
 39 | ### getPaymentInstruments
 40 | 
 41 | **Signature:** `getPaymentInstruments(paymentMethodID : String) : Collection`
 42 | 
 43 | Returns a collection of all payment instruments associated with the related customer filtered by the given payment method id.
 44 | 
 45 | ### removePaymentInstrument
 46 | 
 47 | **Signature:** `removePaymentInstrument(instrument : CustomerPaymentInstrument) : void`
 48 | 
 49 | Removes a payment instrument associated with the customer.
 50 | 
 51 | ## Method Detail
 52 | 
 53 | ## Method Details
 54 | 
 55 | ### createPaymentInstrument
 56 | 
 57 | **Signature:** `createPaymentInstrument(paymentMethodId : String) : CustomerPaymentInstrument`
 58 | 
 59 | **Description:** Creates a new, empty payment instrument object associated with the related customer for the given payment method.
 60 | 
 61 | **Parameters:**
 62 | 
 63 | - `paymentMethodId`: the id of a payment method
 64 | 
 65 | **Returns:**
 66 | 
 67 | the new payment instrument object.
 68 | 
 69 | **Throws:**
 70 | 
 71 | NullArgumentException - If passed 'paymentMethodId' is null.
 72 | 
 73 | ---
 74 | 
 75 | ### getPaymentInstruments
 76 | 
 77 | **Signature:** `getPaymentInstruments() : Collection`
 78 | 
 79 | **Description:** Returns a collection of all payment instruments associated with the related customer.
 80 | 
 81 | **Returns:**
 82 | 
 83 | Collection of all payment instruments.
 84 | 
 85 | ---
 86 | 
 87 | ### getPaymentInstruments
 88 | 
 89 | **Signature:** `getPaymentInstruments(paymentMethodID : String) : Collection`
 90 | 
 91 | **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.
 92 | 
 93 | **Parameters:**
 94 | 
 95 | - `paymentMethodID`: the paymentMethodID the payment method id to filter for
 96 | 
 97 | **Returns:**
 98 | 
 99 | Collection of payment instruments for a payment method.
100 | 
101 | ---
102 | 
103 | ### removePaymentInstrument
104 | 
105 | **Signature:** `removePaymentInstrument(instrument : CustomerPaymentInstrument) : void`
106 | 
107 | **Description:** Removes a payment instrument associated with the customer.
108 | 
109 | **Parameters:**
110 | 
111 | - `instrument`: the instrument associated with this customer
112 | 
113 | **Throws:**
114 | 
115 | NullArgumentException - If passed 'instrument' is null.
116 | IllegalArgumentException - If passed 'instrument' belongs to an other customer
117 | 
118 | ---
```

--------------------------------------------------------------------------------
/docs/dw_extensions.payments/SalesforcePayPalOrderAddress.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.extensions.payments
  2 | 
  3 | # Class SalesforcePayPalOrderAddress
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.extensions.payments.SalesforcePayPalOrderAddress
  9 | 
 10 | ## Description
 11 | 
 12 | 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.
 13 | 
 14 | ## Properties
 15 | 
 16 | ### addressLine1
 17 | 
 18 | **Type:** String (Read Only)
 19 | 
 20 | The address line 1.
 21 | 
 22 | ### addressLine2
 23 | 
 24 | **Type:** String (Read Only)
 25 | 
 26 | The address line 2.
 27 | 
 28 | ### adminArea1
 29 | 
 30 | **Type:** String (Read Only)
 31 | 
 32 | The address highest level sub-division in a country, which is usually a province, state, or ISO-3166-2
 33 |  subdivision.
 34 | 
 35 | ### adminArea2
 36 | 
 37 | **Type:** String (Read Only)
 38 | 
 39 | The address city, town, or village.
 40 | 
 41 | ### countryCode
 42 | 
 43 | **Type:** String (Read Only)
 44 | 
 45 | The address two-character ISO 3166-1 code that identifies the country or region.
 46 | 
 47 | ### fullName
 48 | 
 49 | **Type:** String (Read Only)
 50 | 
 51 | The address full name.
 52 | 
 53 | ### postalCode
 54 | 
 55 | **Type:** String (Read Only)
 56 | 
 57 | The address postal code.
 58 | 
 59 | ## Constructor Summary
 60 | 
 61 | ## Method Summary
 62 | 
 63 | ### getAddressLine1
 64 | 
 65 | **Signature:** `getAddressLine1() : String`
 66 | 
 67 | Returns the address line 1.
 68 | 
 69 | ### getAddressLine2
 70 | 
 71 | **Signature:** `getAddressLine2() : String`
 72 | 
 73 | Returns the address line 2.
 74 | 
 75 | ### getAdminArea1
 76 | 
 77 | **Signature:** `getAdminArea1() : String`
 78 | 
 79 | Returns the address highest level sub-division in a country, which is usually a province, state, or ISO-3166-2 subdivision.
 80 | 
 81 | ### getAdminArea2
 82 | 
 83 | **Signature:** `getAdminArea2() : String`
 84 | 
 85 | Returns the address city, town, or village.
 86 | 
 87 | ### getCountryCode
 88 | 
 89 | **Signature:** `getCountryCode() : String`
 90 | 
 91 | Returns the address two-character ISO 3166-1 code that identifies the country or region.
 92 | 
 93 | ### getFullName
 94 | 
 95 | **Signature:** `getFullName() : String`
 96 | 
 97 | Returns the address full name.
 98 | 
 99 | ### getPostalCode
100 | 
101 | **Signature:** `getPostalCode() : String`
102 | 
103 | Returns the address postal code.
104 | 
105 | ## Method Detail
106 | 
107 | ## Method Details
108 | 
109 | ### getAddressLine1
110 | 
111 | **Signature:** `getAddressLine1() : String`
112 | 
113 | **Description:** Returns the address line 1.
114 | 
115 | **Returns:**
116 | 
117 | address line 1
118 | 
119 | ---
120 | 
121 | ### getAddressLine2
122 | 
123 | **Signature:** `getAddressLine2() : String`
124 | 
125 | **Description:** Returns the address line 2.
126 | 
127 | **Returns:**
128 | 
129 | address line 2
130 | 
131 | ---
132 | 
133 | ### getAdminArea1
134 | 
135 | **Signature:** `getAdminArea1() : String`
136 | 
137 | **Description:** Returns the address highest level sub-division in a country, which is usually a province, state, or ISO-3166-2 subdivision.
138 | 
139 | **Returns:**
140 | 
141 | address highest level sub-division in a country, such as a state
142 | 
143 | ---
144 | 
145 | ### getAdminArea2
146 | 
147 | **Signature:** `getAdminArea2() : String`
148 | 
149 | **Description:** Returns the address city, town, or village.
150 | 
151 | **Returns:**
152 | 
153 | address city, town, or village
154 | 
155 | ---
156 | 
157 | ### getCountryCode
158 | 
159 | **Signature:** `getCountryCode() : String`
160 | 
161 | **Description:** Returns the address two-character ISO 3166-1 code that identifies the country or region.
162 | 
163 | **Returns:**
164 | 
165 | address country code
166 | 
167 | ---
168 | 
169 | ### getFullName
170 | 
171 | **Signature:** `getFullName() : String`
172 | 
173 | **Description:** Returns the address full name.
174 | 
175 | **Returns:**
176 | 
177 | address full name
178 | 
179 | ---
180 | 
181 | ### getPostalCode
182 | 
183 | **Signature:** `getPostalCode() : String`
184 | 
185 | **Description:** Returns the address postal code.
186 | 
187 | **Returns:**
188 | 
189 | address postal code
190 | 
191 | ---
```

--------------------------------------------------------------------------------
/src/types/types.ts:
--------------------------------------------------------------------------------

```typescript
  1 | /**
  2 |  * Type definitions for SFCC MCP Server
  3 |  *
  4 |  * This module contains all TypeScript interfaces and types used throughout
  5 |  * the SFCC (Salesforce B2C Commerce Cloud) MCP server application.
  6 |  */
  7 | 
  8 | /**
  9 |  * Configuration interface for SFCC connection
 10 |  * Supports both basic authentication (username/password) and OAuth (clientId/clientSecret)
 11 |  */
 12 | export interface SFCCConfig {
 13 |   /** SFCC hostname (e.g., zziu-006.dx.commercecloud.salesforce.com) */
 14 |   hostname?: string;
 15 |   /** Username for basic authentication (optional if using OAuth) */
 16 |   username?: string;
 17 |   /** Password for basic authentication (optional if using OAuth) */
 18 |   password?: string;
 19 |   /** Client ID for OAuth authentication (optional if using basic auth) */
 20 |   clientId?: string;
 21 |   /** Client secret for OAuth authentication (optional if using basic auth) */
 22 |   clientSecret?: string;
 23 |   /** Site ID for SFCC instance */
 24 |   siteId?: string;
 25 | }
 26 | 
 27 | /**
 28 |  * Configuration structure from dw.json file
 29 |  * This matches the standard Salesforce Commerce Cloud dw.json configuration format
 30 |  */
 31 | export interface DwJsonConfig {
 32 |   /** SFCC hostname */
 33 |   hostname: string;
 34 |   /** Username for WebDAV access */
 35 |   username: string;
 36 |   /** Password for WebDAV access */
 37 |   password: string;
 38 |   /** Optional code version */
 39 |   'code-version'?: string;
 40 |   /** Optional client ID for OAuth */
 41 |   'client-id'?: string;
 42 |   /** Optional client secret for OAuth */
 43 |   'client-secret'?: string;
 44 |   /** Optional site ID for SFCC instance */
 45 |   'site-id'?: string;
 46 | }
 47 | 
 48 | /**
 49 |  * Log levels supported by the SFCC logging system
 50 |  */
 51 | export type LogLevel = 'error' | 'warn' | 'info' | 'debug';
 52 | 
 53 | /**
 54 |  * Structure for log file metadata
 55 |  */
 56 | export interface LogFileInfo {
 57 |   /** File name */
 58 |   name: string;
 59 |   /** File size in bytes */
 60 |   size: number;
 61 |   /** Last modification timestamp */
 62 |   lastModified: string;
 63 | }
 64 | 
 65 | /**
 66 |  * Summary statistics for log analysis
 67 |  */
 68 | export interface LogSummary {
 69 |   /** Date of the logs being summarized */
 70 |   date: string;
 71 |   /** Number of error entries found */
 72 |   errorCount: number;
 73 |   /** Number of warning entries found */
 74 |   warningCount: number;
 75 |   /** Number of info entries found */
 76 |   infoCount: number;
 77 |   /** Number of debug entries found */
 78 |   debugCount: number;
 79 |   /** List of unique error patterns identified */
 80 |   keyIssues: string[];
 81 |   /** List of log files analyzed */
 82 |   files: string[];
 83 | }
 84 | 
 85 | /**
 86 |  * OAuth 2.0 token response from SFCC authorization server
 87 |  */
 88 | export interface OAuthTokenResponse {
 89 |   /** Token expiration time in seconds */
 90 |   expires_in: number;
 91 |   /** Token type (always "Bearer" for SFCC) */
 92 |   token_type: string;
 93 |   /** The actual access token */
 94 |   access_token: string;
 95 | }
 96 | 
 97 | /**
 98 |  * OAuth token with expiration tracking
 99 |  */
100 | export interface OAuthToken {
101 |   /** The access token */
102 |   accessToken: string;
103 |   /** Token type */
104 |   tokenType: string;
105 |   /** When the token expires (timestamp) */
106 |   expiresAt: number;
107 | }
108 | 
109 | /**
110 |  * OCAPI client configuration
111 |  */
112 | export interface OCAPIConfig {
113 |   /** SFCC hostname */
114 |   hostname: string;
115 |   /** OAuth client ID */
116 |   clientId: string;
117 |   /** OAuth client secret */
118 |   clientSecret: string;
119 |   /** Site ID (optional, for shop API) */
120 |   siteId?: string;
121 |   /** API version (default: v21_3) */
122 |   version?: string;
123 | }
124 | 
```

--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## 📋 Pull Request Summary
  2 | 
  3 | ### Type of Change
  4 | <!-- Please select the type of change this PR introduces -->
  5 | - [ ] 🐛 Bug fix (non-breaking change which fixes an issue)
  6 | - [ ] ✨ New feature (non-breaking change which adds functionality)
  7 | - [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  8 | - [ ] 📚 Documentation update (changes to documentation only)
  9 | - [ ] 🔧 Configuration/tooling update (changes to build process, CI/CD, etc.)
 10 | - [ ] ♻️ Code refactoring (no functional changes, no API changes)
 11 | - [ ] 🎨 Style/formatting changes (code formatting, missing semicolons, etc.)
 12 | - [ ] ⚡ Performance improvement
 13 | - [ ] 🧪 Test improvements
 14 | - [ ] 🔒 Security enhancement
 15 | 
 16 | ### Description
 17 | <!-- Provide a clear and concise description of what this PR does -->
 18 | 
 19 | 
 20 | ### Related Issues
 21 | <!-- Link to related issues using keywords like "Fixes #123" or "Closes #456" -->
 22 | - Fixes #
 23 | - Related to #
 24 | 
 25 | ### Changes Made
 26 | <!-- List the main changes made in this PR -->
 27 | - 
 28 | - 
 29 | - 
 30 | 
 31 | ### Testing
 32 | <!-- Describe how you tested your changes -->
 33 | - [ ] Unit tests added/updated
 34 | - [ ] Integration tests added/updated
 35 | - [ ] Manual testing performed
 36 | - [ ] Tested in documentation-only mode
 37 | - [ ] Tested in full mode (with SFCC credentials)
 38 | - [ ] All existing tests pass
 39 | 
 40 | ### Test Coverage
 41 | <!-- Describe what testing was done -->
 42 | 
 43 | 
 44 | ### Breaking Changes
 45 | <!-- If this is a breaking change, describe what breaks and how to migrate -->
 46 | 
 47 | 
 48 | ### Documentation
 49 | <!-- Check all that apply -->
 50 | - [ ] README.md updated (if user-facing changes)
 51 | - [ ] copilot-instructions.md updated (if architectural changes)
 52 | - [ ] API documentation updated
 53 | - [ ] Best practices guides updated
 54 | - [ ] Code comments added/updated
 55 | - [ ] No documentation changes needed
 56 | 
 57 | ### Performance Impact
 58 | <!-- Describe any performance implications -->
 59 | - [ ] No performance impact
 60 | - [ ] Performance improvement
 61 | - [ ] Minor performance impact (acceptable)
 62 | - [ ] Significant performance impact (needs discussion)
 63 | 
 64 | ### Security Considerations
 65 | <!-- Describe any security implications -->
 66 | - [ ] No security impact
 67 | - [ ] Security improvement
 68 | - [ ] Reviewed for security implications
 69 | - [ ] No new external dependencies
 70 | - [ ] New dependencies reviewed for security
 71 | 
 72 | ### Checklist
 73 | <!-- Ensure all items are checked before requesting review -->
 74 | - [ ] Code follows the project's style guidelines
 75 | - [ ] Self-review of the code has been performed
 76 | - [ ] Code is well-commented, particularly in hard-to-understand areas
 77 | - [ ] Changes generate no new warnings or errors
 78 | - [ ] Any dependent changes have been merged and published
 79 | - [ ] Version numbers updated (if applicable)
 80 | - [ ] Changelog updated (if applicable)
 81 | 
 82 | ### Reviewer Notes
 83 | <!-- Any specific areas you'd like reviewers to focus on -->
 84 | 
 85 | 
 86 | ### Screenshots/Examples
 87 | <!-- If applicable, add screenshots or code examples -->
 88 | 
 89 | 
 90 | ---
 91 | 
 92 | ### For Maintainers
 93 | <!-- This section is for maintainers to fill out during review -->
 94 | 
 95 | #### Review Checklist
 96 | - [ ] Code quality and style
 97 | - [ ] Test coverage adequate
 98 | - [ ] Documentation updated appropriately
 99 | - [ ] Security implications reviewed
100 | - [ ] Performance impact acceptable
101 | - [ ] Breaking changes properly documented
102 | - [ ] Version bump needed
103 | - [ ] Release notes needed
104 | 
```

--------------------------------------------------------------------------------
/tests/path-service.test.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { PathService, MockPathService } from '../src/services/path-service.js';
 2 | 
 3 | describe('PathService', () => {
 4 |   describe('Production PathService', () => {
 5 |     let service: PathService;
 6 | 
 7 |     beforeEach(() => {
 8 |       service = new PathService();
 9 |     });
10 | 
11 |     it('should be instantiable', () => {
12 |       expect(service).toBeInstanceOf(PathService);
13 |     });
14 | 
15 |     it('should join paths correctly', () => {
16 |       expect(service.join('a', 'b', 'c')).toMatch(/a.b.c/);
17 |     });
18 | 
19 |     it('should resolve paths correctly', () => {
20 |       const resolved = service.resolve('test', 'path');
21 |       expect(service.isAbsolute(resolved)).toBe(true);
22 |     });
23 | 
24 |     it('should get dirname correctly', () => {
25 |       const result = service.dirname('/path/to/file.txt');
26 |       expect(result).toMatch(/.*path.to/);
27 |     });
28 | 
29 |     it('should get basename correctly', () => {
30 |       expect(service.basename('/path/to/file.txt')).toBe('file.txt');
31 |       expect(service.basename('/path/to/file.txt', '.txt')).toBe('file');
32 |     });
33 | 
34 |     it('should get extension correctly', () => {
35 |       expect(service.extname('/path/to/file.txt')).toBe('.txt');
36 |       expect(service.extname('/path/to/file')).toBe('');
37 |     });
38 | 
39 |     it('should normalize paths correctly', () => {
40 |       const normalized = service.normalize('/path//to///file.txt');
41 |       expect(normalized).not.toMatch(/\/\/+/);
42 |     });
43 | 
44 |     it('should detect absolute paths correctly', () => {
45 |       expect(service.isAbsolute('/absolute/path')).toBe(true);
46 |       expect(service.isAbsolute('relative/path')).toBe(false);
47 |     });
48 |   });
49 | 
50 |   describe('MockPathService', () => {
51 |     let mockService: MockPathService;
52 | 
53 |     beforeEach(() => {
54 |       mockService = new MockPathService();
55 |     });
56 | 
57 |     it('should be instantiable', () => {
58 |       expect(mockService).toBeInstanceOf(MockPathService);
59 |     });
60 | 
61 |     it('should join paths with forward slashes', () => {
62 |       expect(mockService.join('a', 'b', 'c')).toBe('a/b/c');
63 |     });
64 | 
65 |     it('should resolve paths with mock root', () => {
66 |       expect(mockService.resolve('test', 'path')).toBe('/mock/root/test/path');
67 |       expect(mockService.resolve('/absolute', 'path')).toBe('/absolute/path');
68 |     });
69 | 
70 |     it('should get dirname correctly', () => {
71 |       expect(mockService.dirname('/path/to/file.txt')).toBe('/path/to');
72 |       expect(mockService.dirname('/file.txt')).toBe('/');
73 |     });
74 | 
75 |     it('should get basename correctly', () => {
76 |       expect(mockService.basename('/path/to/file.txt')).toBe('file.txt');
77 |       expect(mockService.basename('/path/to/file.txt', '.txt')).toBe('file');
78 |       expect(mockService.basename('/path/to/file.txt', '.js')).toBe('file.txt');
79 |     });
80 | 
81 |     it('should get extension correctly', () => {
82 |       expect(mockService.extname('/path/to/file.txt')).toBe('.txt');
83 |       expect(mockService.extname('/path/to/file.min.js')).toBe('.js');
84 |       expect(mockService.extname('/path/to/file')).toBe('');
85 |     });
86 | 
87 |     it('should normalize paths correctly', () => {
88 |       expect(mockService.normalize('/path//to///file.txt')).toBe('/path/to/file.txt');
89 |     });
90 | 
91 |     it('should detect absolute paths correctly', () => {
92 |       expect(mockService.isAbsolute('/absolute/path')).toBe(true);
93 |       expect(mockService.isAbsolute('relative/path')).toBe(false);
94 |     });
95 |   });
96 | });
97 | 
```

--------------------------------------------------------------------------------
/docs-site/components/SEO.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import React from 'react';
 2 | import { Head } from 'vite-react-ssg';
 3 | 
 4 | interface SEOProps {
 5 |   title?: string;
 6 |   description?: string;
 7 |   keywords?: string;
 8 |   canonical?: string;
 9 |   ogImage?: string;
10 |   ogType?: 'website' | 'article';
11 |   twitterCard?: 'summary' | 'summary_large_image';
12 |   noindex?: boolean;
13 | }
14 | 
15 | const SEO: React.FC<SEOProps> = ({
16 |   title = 'SFCC Development MCP Server',
17 |   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.',
18 |   keywords = 'SFCC, Salesforce Commerce Cloud, Model Context Protocol, MCP server, AI development tools, SFCC documentation, Commerce Cloud development',
19 |   canonical,
20 |   ogImage = 'https://sfcc-mcp-dev.rhino-inquisitor.com/explain-product-pricing-methods.png',
21 |   ogType = 'website',
22 |   twitterCard = 'summary_large_image',
23 |   structuredData,
24 |   noindex = false
25 | }) => {
26 |   const baseUrl = 'https://sfcc-mcp-dev.rhino-inquisitor.com';
27 |   const fullCanonical = canonical ? `${baseUrl}${canonical}` : baseUrl;
28 |   const fullTitle = title === 'SFCC Development MCP Server' ? title : `${title} | SFCC Development MCP Server`;
29 | 
30 |   return (
31 |     <Head>
32 |       <title>{fullTitle}</title>
33 |       <meta name="description" content={description} />
34 |       <meta name="keywords" content={keywords} />
35 |       <link rel="canonical" href={fullCanonical} />
36 |       
37 |       {/* Basic Meta Tags */}
38 |       <meta name="author" content="Thomas Theunen" />
39 |       <meta name="publisher" content="Thomas Theunen" />
40 |       {noindex ? (
41 |         <meta name="robots" content="noindex, nofollow" />
42 |       ) : (
43 |         <meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" />
44 |       )}
45 | 
46 |       {/* Open Graph Tags */}
47 |       <meta property="og:title" content={fullTitle} />
48 |       <meta property="og:description" content={description} />
49 |       <meta property="og:type" content={ogType} />
50 |       <meta property="og:url" content={fullCanonical} />
51 |       <meta property="og:site_name" content="SFCC Development MCP Server" />
52 |       <meta property="og:image" content={ogImage} />
53 |       <meta property="og:image:alt" content={title} />
54 |       <meta property="og:image:width" content="1200" />
55 |       <meta property="og:image:height" content="630" />
56 |       <meta property="og:locale" content="en_US" />
57 | 
58 |       {/* Twitter Card Tags */}
59 |       <meta name="twitter:card" content={twitterCard} />
60 |       <meta name="twitter:title" content={fullTitle} />
61 |       <meta name="twitter:description" content={description} />
62 |       <meta name="twitter:image" content={ogImage} />
63 |       <meta name="twitter:image:alt" content={title} />
64 |       <meta name="twitter:creator" content="@taurgis" />
65 |       <meta name="twitter:site" content="@taurgis" />
66 | 
67 |       {/* Additional Meta Tags */}
68 |       <meta name="application-name" content="SFCC Development MCP Server" />
69 |       <meta name="msapplication-tooltip" content={description} />
70 |       <meta name="apple-mobile-web-app-title" content="SFCC MCP Server" />
71 |       <meta name="apple-mobile-web-app-capable" content="yes" />
72 |       <meta name="apple-mobile-web-app-status-bar-style" content="default" />
73 | 
74 | 
75 |     </Head>
76 |   );
77 | };
78 | 
79 | export default SEO;
```

--------------------------------------------------------------------------------
/docs/dw_svc/FTPService.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.svc
  2 | 
  3 | # Class FTPService
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.svc.Service
  9 |   - dw.svc.FTPService
 10 | 
 11 | ## Description
 12 | 
 13 | 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.
 14 | 
 15 | ## Properties
 16 | 
 17 | ### autoDisconnect
 18 | 
 19 | **Type:** boolean
 20 | 
 21 | The status of whether the underlying FTP connection will be disconnected after the service call.
 22 | 
 23 | ### client
 24 | 
 25 | **Type:** Object (Read Only)
 26 | 
 27 | The underlying client object.
 28 |  
 29 |  This is either an FTPClient or SFTPClient, depending on the protocol.
 30 | 
 31 | ## Constructor Summary
 32 | 
 33 | ## Method Summary
 34 | 
 35 | ### getClient
 36 | 
 37 | **Signature:** `getClient() : Object`
 38 | 
 39 | Returns the underlying client object.
 40 | 
 41 | ### isAutoDisconnect
 42 | 
 43 | **Signature:** `isAutoDisconnect() : boolean`
 44 | 
 45 | Returns the status of whether the underlying FTP connection will be disconnected after the service call.
 46 | 
 47 | ### setAutoDisconnect
 48 | 
 49 | **Signature:** `setAutoDisconnect(b : boolean) : FTPService`
 50 | 
 51 | Sets the auto-disconnect flag.
 52 | 
 53 | ### setOperation
 54 | 
 55 | **Signature:** `setOperation(name : String, args : Object...) : FTPService`
 56 | 
 57 | Sets a single operation to perform during the execute phase of the service.
 58 | 
 59 | ## Method Detail
 60 | 
 61 | ## Method Details
 62 | 
 63 | ### getClient
 64 | 
 65 | **Signature:** `getClient() : Object`
 66 | 
 67 | **Description:** Returns the underlying client object. This is either an FTPClient or SFTPClient, depending on the protocol.
 68 | 
 69 | **Returns:**
 70 | 
 71 | (S)FTP Client object.
 72 | 
 73 | ---
 74 | 
 75 | ### isAutoDisconnect
 76 | 
 77 | **Signature:** `isAutoDisconnect() : boolean`
 78 | 
 79 | **Description:** Returns the status of whether the underlying FTP connection will be disconnected after the service call.
 80 | 
 81 | **Returns:**
 82 | 
 83 | The auto-disconnect flag.
 84 | 
 85 | ---
 86 | 
 87 | ### setAutoDisconnect
 88 | 
 89 | **Signature:** `setAutoDisconnect(b : boolean) : FTPService`
 90 | 
 91 | **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.
 92 | 
 93 | **Parameters:**
 94 | 
 95 | - `b`: true to enable auto-disconnect, false otherwise.
 96 | 
 97 | **Returns:**
 98 | 
 99 | this FTP or SFTP Service.
100 | 
101 | ---
102 | 
103 | ### setOperation
104 | 
105 | **Signature:** `setOperation(name : String, args : Object...) : FTPService`
106 | 
107 | **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.
108 | 
109 | **Parameters:**
110 | 
111 | - `name`: Method name.
112 | - `args`: Method arguments.
113 | 
114 | **Returns:**
115 | 
116 | this FTP or SFTP Service.
117 | 
118 | ---
```

--------------------------------------------------------------------------------
/docs/dw_order.hooks/CalculateHooks.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Package: dw.order.hooks
 2 | 
 3 | # Class CalculateHooks
 4 | 
 5 | ## Inheritance Hierarchy
 6 | 
 7 | - dw.order.hooks.CalculateHooks
 8 | 
 9 | ## Description
10 | 
11 | 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.
12 | 
13 | ## Constants
14 | 
15 | ## Properties
16 | 
17 | ## Constructor Summary
18 | 
19 | ## Method Summary
20 | 
21 | ### calculate
22 | 
23 | **Signature:** `calculate(lineItemCtnr : LineItemCtnr) : Status`
24 | 
25 | The function is called by extension point extensionPointCalculate.
26 | 
27 | ### calculateShipping
28 | 
29 | **Signature:** `calculateShipping(lineItemCtnr : LineItemCtnr) : Status`
30 | 
31 | The function is called by extension point extensionPointCalculateShipping.
32 | 
33 | ### calculateTax
34 | 
35 | **Signature:** `calculateTax(lineItemCtnr : LineItemCtnr) : Status`
36 | 
37 | The function is called by extension point extensionPointCalculateTax.
38 | 
39 | ## Method Detail
40 | 
41 | ## Method Details
42 | 
43 | ### calculate
44 | 
45 | **Signature:** `calculate(lineItemCtnr : LineItemCtnr) : Status`
46 | 
47 | **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
48 | 
49 | **Parameters:**
50 | 
51 | - `lineItemCtnr`: the line item container to be (re)calculated.
52 | 
53 | ---
54 | 
55 | ### calculateShipping
56 | 
57 | **Signature:** `calculateShipping(lineItemCtnr : LineItemCtnr) : Status`
58 | 
59 | **Description:** The function is called by extension point extensionPointCalculateShipping. It provides a single place for shipping calculation during the line item container calculation.
60 | 
61 | **Parameters:**
62 | 
63 | - `lineItemCtnr`: the line item container to be (re)calculated.
64 | 
65 | ---
66 | 
67 | ### calculateTax
68 | 
69 | **Signature:** `calculateTax(lineItemCtnr : LineItemCtnr) : Status`
70 | 
71 | **Description:** The function is called by extension point extensionPointCalculateTax. It provides a single place for tax calculation during the line item container calculation.
72 | 
73 | **Parameters:**
74 | 
75 | - `lineItemCtnr`: the line item container to be (re)calculated.
76 | 
77 | ---
```

--------------------------------------------------------------------------------
/docs/dw_catalog/ProductPriceTable.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.catalog
  2 | 
  3 | # Class ProductPriceTable
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.catalog.ProductPriceTable
  9 | 
 10 | ## Description
 11 | 
 12 | 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.
 13 | 
 14 | ## Properties
 15 | 
 16 | ### quantities
 17 | 
 18 | **Type:** Collection (Read Only)
 19 | 
 20 | All quantities stored in the price table.
 21 | 
 22 | ## Constructor Summary
 23 | 
 24 | ## Method Summary
 25 | 
 26 | ### getNextQuantity
 27 | 
 28 | **Signature:** `getNextQuantity(quantity : Quantity) : Quantity`
 29 | 
 30 | Returns the quantity following the passed quantity in the price table.
 31 | 
 32 | ### getPercentage
 33 | 
 34 | **Signature:** `getPercentage(quantity : Quantity) : Number`
 35 | 
 36 | Returns the percentage off value of the price related to the passed quantity, calculated based on the price of the products minimum order quantity.
 37 | 
 38 | ### getPrice
 39 | 
 40 | **Signature:** `getPrice(quantity : Quantity) : Money`
 41 | 
 42 | Returns the monetary price for the passed order quantity.
 43 | 
 44 | ### getPriceBook
 45 | 
 46 | **Signature:** `getPriceBook(quantity : Quantity) : PriceBook`
 47 | 
 48 | Returns the price book which defined the monetary price for the passed order quantity.
 49 | 
 50 | ### getQuantities
 51 | 
 52 | **Signature:** `getQuantities() : Collection`
 53 | 
 54 | Returns all quantities stored in the price table.
 55 | 
 56 | ## Method Detail
 57 | 
 58 | ## Method Details
 59 | 
 60 | ### getNextQuantity
 61 | 
 62 | **Signature:** `getNextQuantity(quantity : Quantity) : Quantity`
 63 | 
 64 | **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.
 65 | 
 66 | **Parameters:**
 67 | 
 68 | - `quantity`: the quantity to use to locate the next quantity in the price table.
 69 | 
 70 | **Returns:**
 71 | 
 72 | the next quantity or null.
 73 | 
 74 | ---
 75 | 
 76 | ### getPercentage
 77 | 
 78 | **Signature:** `getPercentage(quantity : Quantity) : Number`
 79 | 
 80 | **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.
 81 | 
 82 | **Parameters:**
 83 | 
 84 | - `quantity`: the price quantity to compute the percentage off.
 85 | 
 86 | **Returns:**
 87 | 
 88 | the percentage off value of the price related to the passed quantity.
 89 | 
 90 | ---
 91 | 
 92 | ### getPrice
 93 | 
 94 | **Signature:** `getPrice(quantity : Quantity) : Money`
 95 | 
 96 | **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.
 97 | 
 98 | **Parameters:**
 99 | 
100 | - `quantity`: the quantity to use to determine price.
101 | 
102 | **Returns:**
103 | 
104 | price amount for the passed quantity
105 | 
106 | ---
107 | 
108 | ### getPriceBook
109 | 
110 | **Signature:** `getPriceBook(quantity : Quantity) : PriceBook`
111 | 
112 | **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.
113 | 
114 | **Parameters:**
115 | 
116 | - `quantity`: the quantity to use to determine price.
117 | 
118 | **Returns:**
119 | 
120 | the price book defining this price, or null
121 | 
122 | ---
123 | 
124 | ### getQuantities
125 | 
126 | **Signature:** `getQuantities() : Collection`
127 | 
128 | **Description:** Returns all quantities stored in the price table.
129 | 
130 | **Returns:**
131 | 
132 | all price table quantities.
133 | 
134 | ---
```

--------------------------------------------------------------------------------
/docs-site/components/ConfigModeTabs.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import React from 'react';
 2 | import CodeBlock, { InlineCode } from './CodeBlock';
 3 | 
 4 | export const ConfigModeTabs: React.FC = () => {
 5 |   const [active, setActive] = React.useState<'docs' | 'full' | 'env'>('docs');
 6 |   const tabBase = 'px-5 py-2 rounded-full text-xs md:text-sm font-medium transition border';
 7 |   return (
 8 |     <div>
 9 |       <div role="tablist" aria-label="Configuration modes" className="flex flex-wrap gap-3 mb-8">
10 |         <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>
11 |         <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>
12 |         <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>
13 |       </div>
14 |       {active==='docs' && (
15 |         <div role="tabpanel" className="space-y-4 animate-fade-in">
16 |           <p className="text-sm text-gray-600">No credentials required. Add the server to your AI client:</p>
17 |           <CodeBlock language="json" code={`{\n  \"mcpServers\": {\n    \"sfcc-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\"sfcc-dev-mcp\"]\n    }\n  }\n}`} />
18 |           <ul className="text-xs text-gray-600 list-disc pl-5 space-y-1">
19 |             <li>Enables documentation, best practices & cartridge generation</li>
20 |             <li>Upgrade anytime by adding <InlineCode>--dw-json</InlineCode></li>
21 |           </ul>
22 |         </div>
23 |       )}
24 |       {active==='full' && (
25 |         <div role="tabpanel" className="space-y-4 animate-fade-in">
26 |           <p className="text-sm text-gray-600">Provide a <InlineCode>dw.json</InlineCode> file to unlock logs, system objects & code versions.</p>
27 |           <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}`} />
28 |           <p className="text-xs text-gray-500">Add <InlineCode>--debug true</InlineCode> temporarily when diagnosing configuration issues.</p>
29 |         </div>
30 |       )}
31 |       {active==='env' && (
32 |         <div role="tabpanel" className="space-y-4 animate-fade-in">
33 |           <p className="text-sm text-gray-600">Use environment variables in CI or container setups. No file needed.</p>
34 |           <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`} />
35 |           <p className="text-xs text-gray-500">Command-line <InlineCode>--dw-json</InlineCode> always overrides env vars.</p>
36 |         </div>
37 |       )}
38 |     </div>
39 |   );
40 | };
41 | 
42 | export default ConfigModeTabs;
43 | 
```

--------------------------------------------------------------------------------
/docs/dw_customer/ProductListRegistrant.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.customer
  2 | 
  3 | # Class ProductListRegistrant
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.object.PersistentObject
  9 |   - dw.object.ExtensibleObject
 10 |     - dw.customer.ProductListRegistrant
 11 | 
 12 | ## Description
 13 | 
 14 | 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.
 15 | 
 16 | ## Properties
 17 | 
 18 | ### email
 19 | 
 20 | **Type:** String
 21 | 
 22 | The email address of the registrant or null.
 23 | 
 24 | ### firstName
 25 | 
 26 | **Type:** String
 27 | 
 28 | The first name of the registrant or null.
 29 | 
 30 | ### lastName
 31 | 
 32 | **Type:** String
 33 | 
 34 | The last name of the registrant or null.
 35 | 
 36 | ### role
 37 | 
 38 | **Type:** String
 39 | 
 40 | The role of the registrant or null. The role of a registrant
 41 |  can be for example the bride of a bridal couple.
 42 | 
 43 | ## Constructor Summary
 44 | 
 45 | ## Method Summary
 46 | 
 47 | ### getEmail
 48 | 
 49 | **Signature:** `getEmail() : String`
 50 | 
 51 | Returns the email address of the registrant or null.
 52 | 
 53 | ### getFirstName
 54 | 
 55 | **Signature:** `getFirstName() : String`
 56 | 
 57 | Returns the first name of the registrant or null.
 58 | 
 59 | ### getLastName
 60 | 
 61 | **Signature:** `getLastName() : String`
 62 | 
 63 | Returns the last name of the registrant or null.
 64 | 
 65 | ### getRole
 66 | 
 67 | **Signature:** `getRole() : String`
 68 | 
 69 | Returns the role of the registrant or null.
 70 | 
 71 | ### setEmail
 72 | 
 73 | **Signature:** `setEmail(email : String) : void`
 74 | 
 75 | Sets the email address of the registrant.
 76 | 
 77 | ### setFirstName
 78 | 
 79 | **Signature:** `setFirstName(firstName : String) : void`
 80 | 
 81 | Sets the first name of the registrant.
 82 | 
 83 | ### setLastName
 84 | 
 85 | **Signature:** `setLastName(lastName : String) : void`
 86 | 
 87 | Sets the last name of the registrant.
 88 | 
 89 | ### setRole
 90 | 
 91 | **Signature:** `setRole(role : String) : void`
 92 | 
 93 | Sets the role of the registrant.
 94 | 
 95 | ## Method Detail
 96 | 
 97 | ## Method Details
 98 | 
 99 | ### getEmail
100 | 
101 | **Signature:** `getEmail() : String`
102 | 
103 | **Description:** Returns the email address of the registrant or null.
104 | 
105 | **Returns:**
106 | 
107 | the email address of the registrant or null.
108 | 
109 | ---
110 | 
111 | ### getFirstName
112 | 
113 | **Signature:** `getFirstName() : String`
114 | 
115 | **Description:** Returns the first name of the registrant or null.
116 | 
117 | **Returns:**
118 | 
119 | the first name of the registrant or null.
120 | 
121 | ---
122 | 
123 | ### getLastName
124 | 
125 | **Signature:** `getLastName() : String`
126 | 
127 | **Description:** Returns the last name of the registrant or null.
128 | 
129 | **Returns:**
130 | 
131 | the last name of the registrant or null.
132 | 
133 | ---
134 | 
135 | ### getRole
136 | 
137 | **Signature:** `getRole() : String`
138 | 
139 | **Description:** Returns the role of the registrant or null. The role of a registrant can be for example the bride of a bridal couple.
140 | 
141 | **Returns:**
142 | 
143 | the role name of the registrant or null.
144 | 
145 | ---
146 | 
147 | ### setEmail
148 | 
149 | **Signature:** `setEmail(email : String) : void`
150 | 
151 | **Description:** Sets the email address of the registrant.
152 | 
153 | **Parameters:**
154 | 
155 | - `email`: the email address of the registrant.
156 | 
157 | ---
158 | 
159 | ### setFirstName
160 | 
161 | **Signature:** `setFirstName(firstName : String) : void`
162 | 
163 | **Description:** Sets the first name of the registrant.
164 | 
165 | **Parameters:**
166 | 
167 | - `firstName`: the first name of the registrant.
168 | 
169 | ---
170 | 
171 | ### setLastName
172 | 
173 | **Signature:** `setLastName(lastName : String) : void`
174 | 
175 | **Description:** Sets the last name of the registrant.
176 | 
177 | **Parameters:**
178 | 
179 | - `lastName`: the last name of the registrant.
180 | 
181 | ---
182 | 
183 | ### setRole
184 | 
185 | **Signature:** `setRole(role : String) : void`
186 | 
187 | **Description:** Sets the role of the registrant.
188 | 
189 | **Parameters:**
190 | 
191 | - `role`: the role of the registrant.
192 | 
193 | ---
```

--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------

```yaml
  1 | name: Publish to NPM
  2 | 
  3 | on:
  4 |   release:
  5 |     types: [published]
  6 | 
  7 | jobs:
  8 |   publish:
  9 |     runs-on: ubuntu-latest
 10 |     permissions:
 11 |       contents: write
 12 |       id-token: write
 13 | 
 14 |     steps:
 15 |       - name: Checkout code
 16 |         uses: actions/checkout@v5
 17 |         with:
 18 |           token: ${{ secrets.GITHUB_TOKEN }}
 19 |           fetch-depth: 0
 20 | 
 21 |       - name: Setup Node.js
 22 |         uses: actions/setup-node@v5
 23 |         with:
 24 |           node-version: '20'
 25 |           registry-url: 'https://registry.npmjs.org'
 26 |           cache: 'npm'
 27 | 
 28 |       - name: Configure Git
 29 |         run: |
 30 |           git config --global user.name "github-actions[bot]"
 31 |           git config --global user.email "github-actions[bot]@users.noreply.github.com"
 32 | 
 33 |       - name: Install dependencies
 34 |         run: npm ci
 35 | 
 36 |       - name: Build project
 37 |         run: npm run build
 38 | 
 39 |       - name: Setup SFCC mock server
 40 |         run: |
 41 |           cd tests/servers/sfcc-mock-server
 42 |           npm install
 43 |           npm run setup:logs
 44 |           node server.js --port 3000 &
 45 |           sleep 5
 46 | 
 47 |       - name: Run tests
 48 |         run: npm test
 49 | 
 50 |       - name: Run linting
 51 |         run: npm run lint:check
 52 | 
 53 |       - name: Final build for publishing
 54 |         run: npm run build
 55 | 
 56 |       - name: Extract version and create release branch
 57 |         run: |
 58 |           # Extract version from the release tag (remove 'v' prefix if present)
 59 |           VERSION=${GITHUB_REF#refs/tags/}
 60 |           VERSION=${VERSION#v}
 61 |           echo "Setting package version to: $VERSION"
 62 |           
 63 |           # Create and switch to release branch
 64 |           BRANCH_NAME="release/v$VERSION"
 65 |           echo "Creating release branch: $BRANCH_NAME"
 66 |           git checkout -b $BRANCH_NAME
 67 | 
 68 |           # Update package version
 69 |           npm version $VERSION --no-git-tag-version
 70 | 
 71 |           # Commit the version update
 72 |           git add package.json package-lock.json
 73 |           git commit -m "chore: bump version to $VERSION for release"
 74 | 
 75 |           # Push the release branch
 76 |           git push origin $BRANCH_NAME
 77 | 
 78 |       - name: Stop SFCC mock server
 79 |         if: always()
 80 |         run: |
 81 |           # Kill SFCC mock server process
 82 |           pkill -f "node.*server.js" || true
 83 |           # Fallback: kill any remaining server processes on port 3000
 84 |           lsof -ti :3000 | xargs kill -9 2>/dev/null || true
 85 | 
 86 |       - name: Publish to NPM
 87 |         run: npm publish
 88 |         env:
 89 |           NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
 90 | 
 91 |       - name: Install MCP Publisher
 92 |         run: |
 93 |           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
 94 | 
 95 |       - name: Update server.json version
 96 |         run: |
 97 |           # Extract version from the release tag (remove 'v' prefix if present)
 98 |           VERSION=${GITHUB_REF#refs/tags/}
 99 |           VERSION=${VERSION#v}
100 |           echo "Updating server.json version to: $VERSION"
101 |           
102 |           # Update server.json version to match the release
103 |           jq --arg v "$VERSION" '.version = $v | .packages[0].version = $v' server.json > tmp && mv tmp server.json
104 | 
105 |       - name: Login to MCP Registry
106 |         run: ./mcp-publisher login github-oidc
107 | 
108 |       - name: Publish to MCP Registry
109 |         run: ./mcp-publisher publish
110 | 
```

--------------------------------------------------------------------------------
/tests/servers/sfcc-mock-server/src/middleware/auth.js:
--------------------------------------------------------------------------------

```javascript
  1 | /**
  2 |  * Authentication Middleware
  3 |  * 
  4 |  * Handles OAuth token generation and validation for OCAPI endpoints.
  5 |  * Maintains simple in-memory token storage suitable for testing.
  6 |  */
  7 | 
  8 | class AuthenticationManager {
  9 |     constructor(config) {
 10 |         this.config = config;
 11 |         this.activeTokens = new Set();
 12 |         this.validCredentials = config.validCredentials;
 13 |     }
 14 | 
 15 |     /**
 16 |      * Handle OAuth2 token requests
 17 |      */
 18 |     handleOAuthToken(req, res) {
 19 |         const { grant_type } = req.body;
 20 |         
 21 |         // Validate grant type
 22 |         if (grant_type !== 'client_credentials' && 
 23 |             grant_type !== 'urn:demandware:params:oauth:grant-type:client-id:dwsid:dwsecuretoken') {
 24 |             return res.status(400).json({
 25 |                 error: 'unsupported_grant_type',
 26 |                 error_description: 'The authorization grant type is not supported'
 27 |             });
 28 |         }
 29 |         
 30 |         // Extract credentials from Basic Auth header
 31 |         const authHeader = req.headers.authorization;
 32 |         if (!authHeader || !authHeader.startsWith('Basic ')) {
 33 |             return res.status(401).json({
 34 |                 error: 'invalid_client',
 35 |                 error_description: 'Client authentication failed - missing Basic auth header'
 36 |             });
 37 |         }
 38 |         
 39 |         const base64Credentials = authHeader.split(' ')[1];
 40 |         const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
 41 |         const [client_id, client_secret] = credentials.split(':');
 42 |         
 43 |         // Validate credentials
 44 |         if (client_id !== this.validCredentials.clientId || 
 45 |             client_secret !== this.validCredentials.clientSecret) {
 46 |             return res.status(401).json({
 47 |                 error: 'invalid_client',
 48 |                 error_description: 'Client authentication failed'
 49 |             });
 50 |         }
 51 |         
 52 |         // Generate mock access token
 53 |         const accessToken = `mock_token_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
 54 |         this.activeTokens.add(accessToken);
 55 |         
 56 |         res.json({
 57 |             access_token: accessToken,
 58 |             token_type: 'Bearer',
 59 |             expires_in: 3600,
 60 |             scope: 'SFCC_DATA_API'
 61 |         });
 62 |     }
 63 | 
 64 |     /**
 65 |      * Middleware to require Bearer token authentication
 66 |      */
 67 |     requireAuth() {
 68 |         return (req, res, next) => {
 69 |             const authHeader = req.headers.authorization;
 70 |             
 71 |             if (!authHeader || !authHeader.startsWith('Bearer ')) {
 72 |                 return res.status(401).json({
 73 |                     error: 'unauthorized',
 74 |                     message: 'Missing or invalid authorization header'
 75 |                 });
 76 |             }
 77 |             
 78 |             const token = authHeader.substring(7);
 79 |             
 80 |             if (!this.activeTokens.has(token)) {
 81 |                 return res.status(401).json({
 82 |                     error: 'invalid_token',
 83 |                     message: 'The access token is invalid or expired'
 84 |                 });
 85 |             }
 86 |             
 87 |             req.accessToken = token;
 88 |             next();
 89 |         };
 90 |     }
 91 | 
 92 |     /**
 93 |      * Clear expired tokens (for cleanup)
 94 |      */
 95 |     clearExpiredTokens() {
 96 |         // For testing purposes, we'll keep tokens active
 97 |         // In a real implementation, you'd track token expiration
 98 |     }
 99 | }
100 | 
101 | module.exports = AuthenticationManager;
```

--------------------------------------------------------------------------------
/src/clients/docs/class-name-resolver.ts:
--------------------------------------------------------------------------------

```typescript
  1 | /**
  2 |  * Class Name Resolver
  3 |  *
  4 |  * Responsible for normalizing and resolving SFCC class names between
  5 |  * different formats (dot notation vs underscore notation) and extracting
  6 |  * simple class names from fully qualified names.
  7 |  *
  8 |  * Single Responsibility: Class name format conversion and resolution
  9 |  */
 10 | 
 11 | export class ClassNameResolver {
 12 |   /**
 13 |    * Normalize class name to handle both dot and underscore formats
 14 |    * Examples:
 15 |    * - dw.content.ContentMgr -> dw_content.ContentMgr
 16 |    * - dw_content.ContentMgr -> dw_content.ContentMgr (unchanged)
 17 |    * - ContentMgr -> ContentMgr (unchanged)
 18 |    */
 19 |   static normalizeClassName(className: string): string {
 20 |     // If it contains dots but not underscores in the package part, convert dots to underscores
 21 |     if (className.includes('.') && !className.includes('_')) {
 22 |       // Split by dots and convert package parts (all but last) to use underscores
 23 |       const parts = className.split('.');
 24 |       if (parts.length > 1) {
 25 |         const packageParts = parts.slice(0, -1);
 26 |         const simpleClassName = parts[parts.length - 1];
 27 |         return `${packageParts.join('_')}.${simpleClassName}`;
 28 |       }
 29 |     }
 30 |     return className;
 31 |   }
 32 | 
 33 |   /**
 34 |    * Extract simple class name from full class name
 35 |    * Examples:
 36 |    * - dw_content.ContentMgr -> ContentMgr
 37 |    * - ContentMgr -> ContentMgr
 38 |    */
 39 |   static extractSimpleClassName(className: string): string {
 40 |     const parts = className.split('.');
 41 |     return parts[parts.length - 1];
 42 |   }
 43 | 
 44 |   /**
 45 |    * Convert class names from internal format to official format
 46 |    * Examples:
 47 |    * - dw_content.ContentMgr -> dw.content.ContentMgr
 48 |    * - TopLevel.String -> String
 49 |    */
 50 |   static toOfficialFormat(className: string): string {
 51 |     return className.replace(/_/g, '.');
 52 |   }
 53 | 
 54 |   /**
 55 |    * Find class matches by simple class name
 56 |    * Useful when multiple packages contain classes with the same name
 57 |    */
 58 |   static findClassMatches(
 59 |     targetClassName: string,
 60 |     classCache: Map<string, any>,
 61 |   ): Array<{ key: string; info: any }> {
 62 |     const normalizedTarget = this.normalizeClassName(targetClassName);
 63 |     const simpleTarget = this.extractSimpleClassName(normalizedTarget);
 64 | 
 65 |     return Array.from(classCache.entries())
 66 |       .filter(([, info]) => info.className === simpleTarget)
 67 |       .map(([key, info]) => ({ key, info }));
 68 |   }
 69 | 
 70 |   /**
 71 |    * Resolve class name with fallback logic
 72 |    * First tries exact match, then falls back to simple name matching
 73 |    */
 74 |   static resolveClassName(
 75 |     className: string,
 76 |     classCache: Map<string, any>,
 77 |   ): { key: string; info: any } | null {
 78 |     // Normalize class name to support both formats
 79 |     const normalizedClassName = this.normalizeClassName(className);
 80 | 
 81 |     // Try exact match first with normalized name
 82 |     const exactMatch = classCache.get(normalizedClassName);
 83 |     if (exactMatch) {
 84 |       return { key: normalizedClassName, info: exactMatch };
 85 |     }
 86 | 
 87 |     // If not found, try to find by class name only (without package)
 88 |     const matches = this.findClassMatches(normalizedClassName, classCache);
 89 | 
 90 |     if (matches.length === 1) {
 91 |       return matches[0];
 92 |     } else if (matches.length > 1) {
 93 |       const matchKeys = matches.map(({ key }) => key).join(', ');
 94 |       throw new Error(`Multiple classes found with name "${this.extractSimpleClassName(normalizedClassName)}": ${matchKeys}`);
 95 |     }
 96 | 
 97 |     return null;
 98 |   }
 99 | }
100 | 
```

--------------------------------------------------------------------------------
/docs/sfra/product-tile.md:
--------------------------------------------------------------------------------

```markdown
 1 | # SFRA Product Tile Model
 2 | 
 3 | ## Overview
 4 | 
 5 | 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.
 6 | 
 7 | ## Module Function
 8 | 
 9 | ```javascript
10 | module.exports = function productTile(product, apiProduct, productType)
11 | ```
12 | 
13 | Decorates a product object with product tile information using various decorators.
14 | 
15 | ### Parameters
16 | 
17 | - `product` (Object) - Product Model to be decorated
18 | - `apiProduct` (dw.catalog.Product) - Product information returned by the script API
19 | - `productType` (string) - Product type information ('product', 'variant', 'master', 'set', etc.)
20 | 
21 | ### Returns
22 | 
23 | Object - Decorated product model with tile-specific information
24 | 
25 | ## Applied Decorators
26 | 
27 | The product tile model applies the following decorators:
28 | 
29 | ### base
30 | Adds fundamental product information including uuid, id, productName, productType, and brand.
31 | 
32 | ### searchPrice
33 | Adds pricing information optimized for search results and product tiles: `price` property with promotional pricing.
34 | 
35 | ### images
36 | Adds product images with the following configuration:
37 | - **Types:** ['medium'] - Medium-sized images suitable for tiles
38 | - **Quantity:** 'single' - Single image per type
39 | 
40 | ### ratings
41 | Adds product rating information: `rating` value calculated from product ID.
42 | 
43 | ### setProductsCollection (conditional)
44 | Applied only when `productType === 'set'`. Adds `numberOfProductsInSet` property with count of products in the set.
45 | 
46 | ### searchVariationAttributes
47 | Adds variation attribute information: `variationAttributes` array optimized for search results and product listings (specifically color swatches).
48 | 
49 | ## Usage Example
50 | 
51 | ```javascript
52 | var productTileDecorator = require('*/cartridge/models/product/productTile');
53 | var productFactory = require('*/cartridge/scripts/factories/product');
54 | 
55 | // Create base product model
56 | var product = productFactory.get({ pid: 'product-id' });
57 | 
58 | // Apply product tile decorations
59 | var tileProduct = productTileDecorator(product, apiProduct, 'product');
60 | 
61 | // Access tile-specific properties
62 | console.log(tileProduct.images.medium);
63 | console.log(tileProduct.price);
64 | console.log(tileProduct.ratings);
65 | ```
66 | 
67 | ## Typical Properties After Decoration
68 | 
69 | After applying the product tile decorators, the product object typically contains:
70 | 
71 | - **uuid** - Product UUID
72 | - **id** - Product ID
73 | - **productName** - Product name  
74 | - **productType** - Product type
75 | - **brand** - Product brand
76 | - **price** - Pricing information with promotions (DefaultPrice or RangePrice)
77 | - **images** - Medium-sized product images
78 | - **rating** - Product rating value
79 | - **variationAttributes** - Color variation swatches and options
80 | - **numberOfProductsInSet** - Number of products in set (for product sets only)
81 | 
82 | ## Notes
83 | 
84 | - Optimized for performance in product listing scenarios
85 | - Uses medium-sized images to balance quality and load time
86 | - Includes promotional pricing for accurate display
87 | - Handles different product types (simple, master, variant, set)
88 | - Variation attributes are optimized for search/listing context
89 | 
90 | ## Related Models
91 | 
92 | - **Full Product Model** - More detailed product information
93 | - **Product Bundle Model** - For bundled products
94 | - **Product Set Model** - For product sets
95 | - **Product Decorators** - Individual decoration functions
96 | 
```

--------------------------------------------------------------------------------
/docs/dw_catalog/ProductInventoryList.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.catalog
  2 | 
  3 | # Class ProductInventoryList
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.object.PersistentObject
  9 |   - dw.object.ExtensibleObject
 10 |     - dw.catalog.ProductInventoryList
 11 | 
 12 | ## Description
 13 | 
 14 | 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.
 15 | 
 16 | ## Properties
 17 | 
 18 | ### defaultInStockFlag
 19 | 
 20 | **Type:** boolean (Read Only)
 21 | 
 22 | The default in-stock flag of the inventory list.
 23 | 
 24 | ### description
 25 | 
 26 | **Type:** String (Read Only)
 27 | 
 28 | The description of the inventory list.
 29 | 
 30 | ### ID
 31 | 
 32 | **Type:** String (Read Only)
 33 | 
 34 | The ID of the inventory list.
 35 | 
 36 | ## Constructor Summary
 37 | 
 38 | ## Method Summary
 39 | 
 40 | ### getDefaultInStockFlag
 41 | 
 42 | **Signature:** `getDefaultInStockFlag() : boolean`
 43 | 
 44 | Returns the default in-stock flag of the inventory list.
 45 | 
 46 | ### getDescription
 47 | 
 48 | **Signature:** `getDescription() : String`
 49 | 
 50 | Returns the description of the inventory list.
 51 | 
 52 | ### getID
 53 | 
 54 | **Signature:** `getID() : String`
 55 | 
 56 | Returns the ID of the inventory list.
 57 | 
 58 | ### getRecord
 59 | 
 60 | **Signature:** `getRecord(product : Product) : ProductInventoryRecord`
 61 | 
 62 | Returns the inventory record for the specified product or null if there is no record for the product in this list.
 63 | 
 64 | ### getRecord
 65 | 
 66 | **Signature:** `getRecord(productID : String) : ProductInventoryRecord`
 67 | 
 68 | Returns the inventory record for the specified product ID or null if there is no record for the product id in this list.
 69 | 
 70 | ## Method Detail
 71 | 
 72 | ## Method Details
 73 | 
 74 | ### getDefaultInStockFlag
 75 | 
 76 | **Signature:** `getDefaultInStockFlag() : boolean`
 77 | 
 78 | **Description:** Returns the default in-stock flag of the inventory list.
 79 | 
 80 | **Returns:**
 81 | 
 82 | Default in-stock flag of inventory list.
 83 | 
 84 | ---
 85 | 
 86 | ### getDescription
 87 | 
 88 | **Signature:** `getDescription() : String`
 89 | 
 90 | **Description:** Returns the description of the inventory list.
 91 | 
 92 | **Returns:**
 93 | 
 94 | Description of inventory list.
 95 | 
 96 | ---
 97 | 
 98 | ### getID
 99 | 
100 | **Signature:** `getID() : String`
101 | 
102 | **Description:** Returns the ID of the inventory list.
103 | 
104 | **Returns:**
105 | 
106 | ID of inventory list.
107 | 
108 | ---
109 | 
110 | ### getRecord
111 | 
112 | **Signature:** `getRecord(product : Product) : ProductInventoryRecord`
113 | 
114 | **Description:** Returns the inventory record for the specified product or null if there is no record for the product in this list.
115 | 
116 | **Parameters:**
117 | 
118 | - `product`: The product to lookup inventory record.
119 | 
120 | **Returns:**
121 | 
122 | Inventory record or null if not found.
123 | 
124 | ---
125 | 
126 | ### getRecord
127 | 
128 | **Signature:** `getRecord(productID : String) : ProductInventoryRecord`
129 | 
130 | **Description:** Returns the inventory record for the specified product ID or null if there is no record for the product id in this list.
131 | 
132 | **Parameters:**
133 | 
134 | - `productID`: The product ID to lookup inventory record.
135 | 
136 | **Returns:**
137 | 
138 | Inventory record or null if not found.
139 | 
140 | ---
```

--------------------------------------------------------------------------------
/docs/dw_web/FormElementValidationResult.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.web
  2 | 
  3 | # Class FormElementValidationResult
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.web.FormElementValidationResult
  9 | 
 10 | ## Description
 11 | 
 12 | 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.
 13 | 
 14 | ## Properties
 15 | 
 16 | ### data
 17 | 
 18 | **Type:** Map (Read Only)
 19 | 
 20 | Provides optional data acquired during validation.
 21 | 
 22 | ### message
 23 | 
 24 | **Type:** String
 25 | 
 26 | Provides an optional message in case of validation failure.
 27 | 
 28 | ### valid
 29 | 
 30 | **Type:** boolean
 31 | 
 32 | States if the validation succeeded or failed.
 33 | 
 34 | ## Constructor Summary
 35 | 
 36 | FormElementValidationResult(valid : boolean) Creates a FormElementValidationResult with given setting for the validity but without any message.
 37 | 
 38 | FormElementValidationResult(valid : boolean, message : String) Creates a FormElementValidationResult with given setting for the validity and corresponding message.
 39 | 
 40 | FormElementValidationResult(valid : boolean, message : String, data : Map) Creates a FormElementValidationResult with given setting for the validity and corresponding message.
 41 | 
 42 | ## Method Summary
 43 | 
 44 | ### addData
 45 | 
 46 | **Signature:** `addData(key : Object, value : Object) : void`
 47 | 
 48 | Adds optional data acquired during validation.
 49 | 
 50 | ### getData
 51 | 
 52 | **Signature:** `getData() : Map`
 53 | 
 54 | Provides optional data acquired during validation.
 55 | 
 56 | ### getMessage
 57 | 
 58 | **Signature:** `getMessage() : String`
 59 | 
 60 | Provides an optional message in case of validation failure.
 61 | 
 62 | ### isValid
 63 | 
 64 | **Signature:** `isValid() : boolean`
 65 | 
 66 | States if the validation succeeded or failed.
 67 | 
 68 | ### setMessage
 69 | 
 70 | **Signature:** `setMessage(message : String) : void`
 71 | 
 72 | Sets an optional message in case of validation failure.
 73 | 
 74 | ### setValid
 75 | 
 76 | **Signature:** `setValid(valid : boolean) : void`
 77 | 
 78 | Sets if the validation succeeded or failed.
 79 | 
 80 | ## Constructor Detail
 81 | 
 82 | ## Method Detail
 83 | 
 84 | ## Method Details
 85 | 
 86 | ### addData
 87 | 
 88 | **Signature:** `addData(key : Object, value : Object) : void`
 89 | 
 90 | **Description:** Adds optional data acquired during validation.
 91 | 
 92 | **Parameters:**
 93 | 
 94 | - `key`: the key for which the data value will be stored
 95 | - `value`: the data value that is stored for the given key
 96 | 
 97 | ---
 98 | 
 99 | ### getData
100 | 
101 | **Signature:** `getData() : Map`
102 | 
103 | **Description:** Provides optional data acquired during validation.
104 | 
105 | **Returns:**
106 | 
107 | the data acquired during validation
108 | 
109 | ---
110 | 
111 | ### getMessage
112 | 
113 | **Signature:** `getMessage() : String`
114 | 
115 | **Description:** Provides an optional message in case of validation failure.
116 | 
117 | **Returns:**
118 | 
119 | the message for validation failure
120 | 
121 | ---
122 | 
123 | ### isValid
124 | 
125 | **Signature:** `isValid() : boolean`
126 | 
127 | **Description:** States if the validation succeeded or failed.
128 | 
129 | **Returns:**
130 | 
131 | true if the validation succeeded
132 | 
133 | ---
134 | 
135 | ### setMessage
136 | 
137 | **Signature:** `setMessage(message : String) : void`
138 | 
139 | **Description:** Sets an optional message in case of validation failure.
140 | 
141 | **Parameters:**
142 | 
143 | - `message`: the message for validation failure
144 | 
145 | ---
146 | 
147 | ### setValid
148 | 
149 | **Signature:** `setValid(valid : boolean) : void`
150 | 
151 | **Description:** Sets if the validation succeeded or failed.
152 | 
153 | **Parameters:**
154 | 
155 | - `valid`: if the validation succeeded
156 | 
157 | ---
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "sfcc-dev-mcp",
 3 |   "version": "1.0.14",
 4 |   "description": "MCP server for Salesforce B2C Commerce Cloud development assistance including logs, debugging, and development tools",
 5 |   "mcpName": "io.github.taurgis/sfcc-dev-mcp",
 6 |   "main": "dist/index.js",
 7 |   "bin": {
 8 |     "sfcc-dev-mcp": "./dist/main.js"
 9 |   },
10 |   "repository": {
11 |     "type": "git",
12 |     "url": "git+https://github.com/taurgis/sfcc-dev-mcp.git"
13 |   },
14 |   "homepage": "https://github.com/taurgis/sfcc-dev-mcp#readme",
15 |   "bugs": {
16 |     "url": "https://github.com/taurgis/sfcc-dev-mcp/issues"
17 |   },
18 |   "scripts": {
19 |     "build": "tsc && rm -rf ./dist/docs && cp -r ./docs ./dist/docs",
20 |     "start": "node dist/main.js",
21 |     "dev": "tsx src/main.ts",
22 |     "inspector": "npx @modelcontextprotocol/inspector node dist/main.js",
23 |     "convert-docs": "node scripts/convert-docs.js",
24 |     "convert-docs:test": "node scripts/convert-docs.js --test",
25 |     "convert-docs:limit": "node scripts/convert-docs.js --limit 5",
26 |     "github-pages": "cd docs-site && rm -f Gemfile.lock && bundle install --path vendor/bundle && bundle exec jekyll serve --livereload --host=0.0.0.0",
27 |     "test": "npm run test:all",
28 |     "test:watch": "jest --watch",
29 |     "test:coverage": "jest --coverage",
30 |     "test:mcp:yaml": "aegis 'tests/mcp/yaml/*.docs-only.test.mcp.yml' --config './aegis.config.docs-only.json'",
31 |     "test:mcp:yaml:full": "aegis 'tests/mcp/yaml/*.full-mode.test.mcp.yml' --config './aegis.config.with-dw.json'",
32 |     "test:mcp:node": "node --test tests/mcp/node/*.programmatic.test.js",
33 |     "test:mcp:all": "npm run test:mcp:yaml && npm run test:mcp:yaml:full && npm run test:mcp:node",
34 |     "test:mcp:ci": "npm run test:mcp:yaml -- --json && npm run test:mcp:yaml:full -- --json && npm run test:mcp:node",
35 |     "test:all": "jest && npm run test:mock-server:setup && npm run test:mcp:all",
36 |     "test:mock-server:setup": "cd tests/servers/sfcc-mock-server && npm install && npm run setup",
37 |     "test:mock-server:start": "cd tests/servers/sfcc-mock-server && npm start",
38 |     "test:mock-server": "jest --testPathPatterns=sfcc-mock-server",
39 |     "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);\"",
40 |     "lint": "eslint .",
41 |     "lint:fix": "eslint . --fix",
42 |     "lint:check": "eslint . --max-warnings 0",
43 |     "prepublishOnly": "npm run build",
44 |     "prepare": "husky"
45 |   },
46 |   "keywords": [
47 |     "mcp",
48 |     "salesforce",
49 |     "commerce-cloud",
50 |     "sfcc",
51 |     "development",
52 |     "logs",
53 |     "debugging",
54 |     "webdav"
55 |   ],
56 |   "author": "Thomas Theunen <[email protected]>",
57 |   "license": "MIT",
58 |   "engines": {
59 |     "node": ">=18",
60 |     "npm": ">=8"
61 |   },
62 |   "type": "module",
63 |   "dependencies": {
64 |     "@modelcontextprotocol/sdk": "1.18.0",
65 |     "webdav": "5.8.0"
66 |   },
67 |   "devDependencies": {
68 |     "@eslint/js": "9.36.0",
69 |     "@types/eslint": "9.6.1",
70 |     "@types/jest": "30.0.0",
71 |     "@types/node": "24.4.0",
72 |     "ajv": "^8.17.1",
73 |     "ajv-formats": "^3.0.1",
74 |     "eslint": "9.36.0",
75 |     "husky": "9.1.7",
76 |     "jest": "30.1.3",
77 |     "mcp-aegis": "1.0.18",
78 |     "ts-jest": "29.4.4",
79 |     "tsx": "4.20.5",
80 |     "typescript": "5.9.2",
81 |     "typescript-eslint": "8.44.0"
82 |   }
83 | }
84 | 
```

--------------------------------------------------------------------------------
/docs/sfra/content.md:
--------------------------------------------------------------------------------

```markdown
  1 | # SFRA Content Model
  2 | 
  3 | ## Overview
  4 | 
  5 | 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.
  6 | 
  7 | ## Constructor
  8 | 
  9 | ```javascript
 10 | function content(contentValue, renderingTemplate)
 11 | ```
 12 | 
 13 | Creates a Content model instance from a content asset.
 14 | 
 15 | ### Parameters
 16 | 
 17 | - `contentValue` (dw.content.Content) - Result of ContentMgr.getContent call
 18 | - `renderingTemplate` (string) - Optional rendering template for the content
 19 | 
 20 | ### Returns
 21 | 
 22 | Object - Content model instance, or null if content is not online
 23 | 
 24 | ## Properties
 25 | 
 26 | ### body
 27 | **Type:** string | null
 28 | 
 29 | The main content body text from the content asset's custom.body attribute.
 30 | 
 31 | ### UUID
 32 | **Type:** string
 33 | 
 34 | Unique identifier for the content asset.
 35 | 
 36 | ### ID
 37 | **Type:** string
 38 | 
 39 | Content asset ID for referencing and linking.
 40 | 
 41 | ### name
 42 | **Type:** string
 43 | 
 44 | Display name of the content asset.
 45 | 
 46 | ### template
 47 | **Type:** string
 48 | 
 49 | Rendering template path for the content. Uses either:
 50 | - Content asset's specified template
 51 | - Provided renderingTemplate parameter
 52 | - Default: 'components/content/contentAssetInc'
 53 | 
 54 | ### pageTitle
 55 | **Type:** string
 56 | 
 57 | SEO page title for the content asset.
 58 | 
 59 | ### pageDescription
 60 | **Type:** string
 61 | 
 62 | SEO meta description for the content asset.
 63 | 
 64 | ### pageKeywords
 65 | **Type:** string
 66 | 
 67 | SEO meta keywords for the content asset.
 68 | 
 69 | ### pageMetaTags
 70 | **Type:** Array
 71 | 
 72 | Additional SEO meta tags for the content asset.
 73 | 
 74 | ## Content Availability
 75 | 
 76 | The model only processes online content assets. If `contentValue.online` is false, the constructor returns null instead of a content object.
 77 | 
 78 | ## Template Resolution
 79 | 
 80 | Template selection follows this priority:
 81 | 1. Content asset's own template property
 82 | 2. Provided renderingTemplate parameter
 83 | 3. Default template: 'components/content/contentAssetInc'
 84 | 
 85 | ## Usage Example
 86 | 
 87 | ```javascript
 88 | var ContentModel = require('*/cartridge/models/content');
 89 | var ContentMgr = require('dw/content/ContentMgr');
 90 | 
 91 | // Get content asset
 92 | var contentAsset = ContentMgr.getContent('privacy-policy');
 93 | var customTemplate = 'pages/content/contentPage';
 94 | 
 95 | var content = new ContentModel(contentAsset, customTemplate);
 96 | 
 97 | if (content) {
 98 |     // Access content properties
 99 |     console.log(content.name);           // "Privacy Policy"
100 |     console.log(content.ID);             // "privacy-policy"
101 |     console.log(content.body);           // Content body HTML
102 |     console.log(content.template);       // Template path
103 |     
104 |     // Access SEO properties
105 |     console.log(content.pageTitle);      // SEO title
106 |     console.log(content.pageDescription); // SEO description
107 | } else {
108 |     console.log('Content is offline or not found');
109 | }
110 | ```
111 | 
112 | ## SEO Support
113 | 
114 | The model provides comprehensive SEO metadata:
115 | - **pageTitle** - For HTML title tag
116 | - **pageDescription** - For meta description
117 | - **pageKeywords** - For meta keywords
118 | - **pageMetaTags** - For additional custom meta tags
119 | 
120 | ## Notes
121 | 
122 | - Only processes online content assets
123 | - Provides flexible template resolution
124 | - Includes comprehensive SEO metadata
125 | - Handles missing content gracefully (returns null)
126 | - Body content comes from custom.body attribute
127 | - Template fallback ensures content can always be rendered
128 | 
129 | ## Related Models
130 | 
131 | - **Page Models** - May include content assets
132 | - **Search Models** - May return content in search results
133 | - **Category Models** - May reference related content
134 | 
```

--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/documentation.yml:
--------------------------------------------------------------------------------

```yaml
  1 | name: 📚 Documentation Issue
  2 | description: Report issues with documentation or suggest documentation improvements
  3 | title: "[Docs]: "
  4 | labels: ["documentation", "needs-triage"]
  5 | assignees: []
  6 | body:
  7 |   - type: markdown
  8 |     attributes:
  9 |       value: |
 10 |         Thanks for helping improve our documentation! Please provide details about the documentation issue or improvement.
 11 | 
 12 |   - type: dropdown
 13 |     id: doc-type
 14 |     attributes:
 15 |       label: Documentation Type
 16 |       description: What type of documentation is this about?
 17 |       options:
 18 |         - README.md
 19 |         - API Documentation (docs/ folder)
 20 |         - Best Practices Guides
 21 |         - Code Comments/JSDoc
 22 |         - Setup/Installation Instructions
 23 |         - Configuration Guide
 24 |         - Troubleshooting Guide
 25 |         - Contributing Guidelines
 26 |         - GitHub Templates
 27 |         - Other
 28 |     validations:
 29 |       required: true
 30 | 
 31 |   - type: dropdown
 32 |     id: issue-type
 33 |     attributes:
 34 |       label: Issue Type
 35 |       description: What kind of documentation issue is this?
 36 |       options:
 37 |         - Missing documentation
 38 |         - Incorrect/outdated information
 39 |         - Unclear or confusing content
 40 |         - Broken links or references
 41 |         - Formatting issues
 42 |         - Grammar/spelling errors
 43 |         - Missing examples
 44 |         - Inconsistent information
 45 |         - Accessibility issues
 46 |         - Other
 47 |     validations:
 48 |       required: true
 49 | 
 50 |   - type: textarea
 51 |     id: location
 52 |     attributes:
 53 |       label: Location
 54 |       description: Where is the documentation issue located?
 55 |       placeholder: |
 56 |         - File path: docs/best-practices/cartridge_creation.md
 57 |         - Section: "Setting up Authentication"
 58 |         - Line number: 45
 59 |         - URL: (if applicable)
 60 |     validations:
 61 |       required: true
 62 | 
 63 |   - type: textarea
 64 |     id: current-content
 65 |     attributes:
 66 |       label: Current Content (if applicable)
 67 |       description: Quote or describe the current problematic content
 68 |       render: markdown
 69 | 
 70 |   - type: textarea
 71 |     id: issue-description
 72 |     attributes:
 73 |       label: Issue Description
 74 |       description: Clearly describe what's wrong or what's missing
 75 |       placeholder: Explain what makes the current documentation problematic or what information is missing...
 76 |     validations:
 77 |       required: true
 78 | 
 79 |   - type: textarea
 80 |     id: suggested-improvement
 81 |     attributes:
 82 |       label: Suggested Improvement
 83 |       description: How should this be fixed or what should be added?
 84 |       placeholder: Provide your suggestion for improving the documentation...
 85 |     validations:
 86 |       required: true
 87 | 
 88 |   - type: textarea
 89 |     id: user-impact
 90 |     attributes:
 91 |       label: User Impact
 92 |       description: How does this documentation issue affect users?
 93 |       placeholder: |
 94 |         - Makes it difficult to get started
 95 |         - Causes confusion during setup
 96 |         - Leads to incorrect implementation
 97 |         - Wastes developer time...
 98 | 
 99 |   - type: dropdown
100 |     id: audience
101 |     attributes:
102 |       label: Target Audience
103 |       description: Who is primarily affected by this documentation issue?
104 |       multiple: true
105 |       options:
106 |         - New users/first-time setup
107 |         - SFCC developers
108 |         - MCP server developers
109 |         - Contributors
110 |         - All users
111 |         - Advanced users only
112 | 
113 |   - type: textarea
114 |     id: additional-context
115 |     attributes:
116 |       label: Additional Context
117 |       description: Any additional context, examples, or references that would help improve the documentation
118 | 
```

--------------------------------------------------------------------------------
/docs/dw_util/Currency.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.util
  2 | 
  3 | # Class Currency
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.util.Currency
  9 | 
 10 | ## Description
 11 | 
 12 | Represents a currency supported by the system.
 13 | 
 14 | ## Properties
 15 | 
 16 | ### currencyCode
 17 | 
 18 | **Type:** String (Read Only)
 19 | 
 20 | Gets the ISO 4217 mnemonic currency code of this currency.
 21 | 
 22 | ### defaultFractionDigits
 23 | 
 24 | **Type:** Number (Read Only)
 25 | 
 26 | Gets the default number of fraction digits used with this currency.
 27 |  For example, the default number of fraction digits for the Euro is 2,
 28 |  while for the Japanese Yen it's 0.
 29 | 
 30 | ### name
 31 | 
 32 | **Type:** String (Read Only)
 33 | 
 34 | Gets a long name for this currency. e.g. "United States Dollar".
 35 |  The returned name is the one stored in the system for this currency.
 36 |  Currently only English names are available, but in the future
 37 |  this method may return a locale-specific name.
 38 | 
 39 | ### symbol
 40 | 
 41 | **Type:** String (Read Only)
 42 | 
 43 | Gets the symbol of this currency. e.g. "$" for the US Dollar.
 44 | 
 45 | ## Constructor Summary
 46 | 
 47 | ## Method Summary
 48 | 
 49 | ### getCurrency
 50 | 
 51 | **Signature:** `static getCurrency(currencyCode : String) : Currency`
 52 | 
 53 | Returns a Currency instance for the given currency code, or null if there is no such currency.
 54 | 
 55 | ### getCurrencyCode
 56 | 
 57 | **Signature:** `getCurrencyCode() : String`
 58 | 
 59 | Gets the ISO 4217 mnemonic currency code of this currency.
 60 | 
 61 | ### getDefaultFractionDigits
 62 | 
 63 | **Signature:** `getDefaultFractionDigits() : Number`
 64 | 
 65 | Gets the default number of fraction digits used with this currency.
 66 | 
 67 | ### getName
 68 | 
 69 | **Signature:** `getName() : String`
 70 | 
 71 | Gets a long name for this currency.
 72 | 
 73 | ### getSymbol
 74 | 
 75 | **Signature:** `getSymbol() : String`
 76 | 
 77 | Gets the symbol of this currency.
 78 | 
 79 | ### toString
 80 | 
 81 | **Signature:** `toString() : String`
 82 | 
 83 | Returns the ISO 4217 mnemonic currency code of this currency.
 84 | 
 85 | ## Method Detail
 86 | 
 87 | ## Method Details
 88 | 
 89 | ### getCurrency
 90 | 
 91 | **Signature:** `static getCurrency(currencyCode : String) : Currency`
 92 | 
 93 | **Description:** Returns a Currency instance for the given currency code, or null if there is no such currency.
 94 | 
 95 | **Parameters:**
 96 | 
 97 | - `currencyCode`: the ISO 4217 mnemonic code of the currency.
 98 | 
 99 | **Returns:**
100 | 
101 | the Currency instance for the given currency code.
102 | 
103 | ---
104 | 
105 | ### getCurrencyCode
106 | 
107 | **Signature:** `getCurrencyCode() : String`
108 | 
109 | **Description:** Gets the ISO 4217 mnemonic currency code of this currency.
110 | 
111 | **Returns:**
112 | 
113 | the ISO 4217 mnemonic currency code of this currency.
114 | 
115 | ---
116 | 
117 | ### getDefaultFractionDigits
118 | 
119 | **Signature:** `getDefaultFractionDigits() : Number`
120 | 
121 | **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.
122 | 
123 | **Returns:**
124 | 
125 | the default number of fraction digits used with this currency.
126 | 
127 | ---
128 | 
129 | ### getName
130 | 
131 | **Signature:** `getName() : String`
132 | 
133 | **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.
134 | 
135 | **Returns:**
136 | 
137 | a long name for this currency. e.g. "United States Dollar".
138 | 
139 | ---
140 | 
141 | ### getSymbol
142 | 
143 | **Signature:** `getSymbol() : String`
144 | 
145 | **Description:** Gets the symbol of this currency. e.g. "$" for the US Dollar.
146 | 
147 | **Returns:**
148 | 
149 | the symbol of this currency.
150 | 
151 | ---
152 | 
153 | ### toString
154 | 
155 | **Signature:** `toString() : String`
156 | 
157 | **Description:** Returns the ISO 4217 mnemonic currency code of this currency.
158 | 
159 | **Returns:**
160 | 
161 | the ISO 4217 mnemonic currency code of this currency.
162 | 
163 | ---
```

--------------------------------------------------------------------------------
/src/tool-configs/sfra-tool-config.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { GenericToolSpec, ToolExecutionContext } from '../core/handlers/base-handler.js';
 2 | import { ToolArguments } from '../core/handlers/base-handler.js';
 3 | import { ValidationHelpers, CommonValidations } from '../core/handlers/validation-helpers.js';
 4 | import { SFRAClient } from '../clients/sfra-client.js';
 5 | 
 6 | export const SFRA_TOOL_NAMES = [
 7 |   'get_available_sfra_documents',
 8 |   'get_sfra_document',
 9 |   'search_sfra_documentation',
10 |   'get_sfra_documents_by_category',
11 |   'get_sfra_categories',
12 | ] as const;
13 | 
14 | export type SFRAToolName = typeof SFRA_TOOL_NAMES[number];
15 | export const SFRA_TOOL_NAMES_SET = new Set<SFRAToolName>(SFRA_TOOL_NAMES);
16 | 
17 | /**
18 |  * Configuration for SFRA documentation tools
19 |  * Maps each tool to its validation, execution, and messaging logic
20 |  */
21 | export const SFRA_TOOL_CONFIG: Record<SFRAToolName, GenericToolSpec<ToolArguments, any>> = {
22 |   get_available_sfra_documents: {
23 |     defaults: (args: ToolArguments) => args,
24 |     validate: (_args: ToolArguments, _toolName: string) => {
25 |       // No validation needed for list operation
26 |     },
27 |     exec: async (_args: ToolArguments, context: ToolExecutionContext) => {
28 |       const client = context.sfraClient as SFRAClient;
29 |       return client.getAvailableDocuments();
30 |     },
31 |     logMessage: (_args: ToolArguments) => 'List SFRA docs',
32 |   },
33 | 
34 |   get_sfra_document: {
35 |     defaults: (args: ToolArguments) => args,
36 |     validate: (args: ToolArguments, toolName: string) => {
37 |       ValidationHelpers.validateArguments(args, CommonValidations.requiredString('documentName'), toolName);
38 |     },
39 |     exec: async (args: ToolArguments, context: ToolExecutionContext) => {
40 |       const client = context.sfraClient as SFRAClient;
41 |       const result = await client.getSFRADocument(args.documentName as string);
42 |       if (!result) {
43 |         throw new Error(`SFRA document "${args.documentName}" not found`);
44 |       }
45 |       return result;
46 |     },
47 |     logMessage: (args: ToolArguments) => `SFRA doc ${args.documentName}`,
48 |   },
49 | 
50 |   search_sfra_documentation: {
51 |     defaults: (args: ToolArguments) => args,
52 |     validate: (args: ToolArguments, toolName: string) => {
53 |       ValidationHelpers.validateArguments(args, CommonValidations.requiredString('query'), toolName);
54 |     },
55 |     exec: async (args: ToolArguments, context: ToolExecutionContext) => {
56 |       const client = context.sfraClient as SFRAClient;
57 |       return client.searchSFRADocumentation(args.query as string);
58 |     },
59 |     logMessage: (args: ToolArguments) => `Search SFRA ${args.query}`,
60 |   },
61 | 
62 |   get_sfra_documents_by_category: {
63 |     defaults: (args: ToolArguments) => args,
64 |     validate: (args: ToolArguments, toolName: string) => {
65 |       ValidationHelpers.validateArguments(args, CommonValidations.requiredString('category'), toolName);
66 |     },
67 |     exec: async (args: ToolArguments, context: ToolExecutionContext) => {
68 |       const client = context.sfraClient as SFRAClient;
69 |       return client.getDocumentsByCategory(args.category as string);
70 |     },
71 |     logMessage: (args: ToolArguments) => `SFRA docs by category ${args.category}`,
72 |   },
73 | 
74 |   get_sfra_categories: {
75 |     defaults: (args: ToolArguments) => args,
76 |     validate: (_args: ToolArguments, _toolName: string) => {
77 |       // No validation needed for list operation
78 |     },
79 |     exec: async (_args: ToolArguments, context: ToolExecutionContext) => {
80 |       const client = context.sfraClient as SFRAClient;
81 |       return client.getAvailableCategories();
82 |     },
83 |     logMessage: (_args: ToolArguments) => 'SFRA categories',
84 |   },
85 | };
86 | 
```

--------------------------------------------------------------------------------
/docs/dw_util/Template.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Package: dw.util
 2 | 
 3 | # Class Template
 4 | 
 5 | ## Inheritance Hierarchy
 6 | 
 7 | - Object
 8 |   - dw.util.Template
 9 | 
10 | ## Description
11 | 
12 | 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.
13 | 
14 | ## Constructor Summary
15 | 
16 | Template(templateName : String) Creates a new template.
17 | 
18 | Template(templateName : String, localeID : String) Creates a new template with the locale being set to the given localeID.
19 | 
20 | ## Method Summary
21 | 
22 | ### render
23 | 
24 | **Signature:** `render() : MimeEncodedText`
25 | 
26 | Renders the template specified at instantiation time, without any substitution parameters.
27 | 
28 | ### render
29 | 
30 | **Signature:** `render(params : Map) : MimeEncodedText`
31 | 
32 | Renders the template specified at instantiation time with the given substitution parameters.
33 | 
34 | ### setLocale
35 | 
36 | **Signature:** `setLocale(localeID : String) : Template`
37 | 
38 | Sets an optional localeID which is used instead of the current requests localeID.
39 | 
40 | ## Constructor Detail
41 | 
42 | ## Method Detail
43 | 
44 | ## Method Details
45 | 
46 | ### render
47 | 
48 | **Signature:** `render() : MimeEncodedText`
49 | 
50 | **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.
51 | 
52 | **Returns:**
53 | 
54 | MimeEncodedText with isprint tags referring to param/pdict replaced with an empty String
55 | 
56 | ---
57 | 
58 | ### render
59 | 
60 | **Signature:** `render(params : Map) : MimeEncodedText`
61 | 
62 | **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.
63 | 
64 | **Parameters:**
65 | 
66 | - `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.
67 | 
68 | **Returns:**
69 | 
70 | 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
71 | 
72 | ---
73 | 
74 | ### setLocale
75 | 
76 | **Signature:** `setLocale(localeID : String) : Template`
77 | 
78 | **Description:** Sets an optional localeID which is used instead of the current requests localeID.
79 | 
80 | **Parameters:**
81 | 
82 | - `localeID`: to be used for processing this template. Throws an exception if localeID is blank
83 | 
84 | **Returns:**
85 | 
86 | this Template object
87 | 
88 | ---
```

--------------------------------------------------------------------------------
/docs/dw_system/SearchStatus.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.system
  2 | 
  3 | # Class SearchStatus
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.system.SearchStatus
  9 | 
 10 | ## Description
 11 | 
 12 | 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.
 13 | 
 14 | ## Constants
 15 | 
 16 | ### EMPTY_QUERY
 17 | 
 18 | **Type:** Number = 6
 19 | 
 20 | EMPTY_QUERY search result status code 6, this indicates that search has been made with empty query.
 21 | 
 22 | ### ERROR
 23 | 
 24 | **Type:** Number = 9
 25 | 
 26 | ERROR search result status code 9, this indicates that internal server error has been occurred.
 27 | 
 28 | ### LIMITED
 29 | 
 30 | **Type:** Number = 2
 31 | 
 32 | LIMITED search result status code 2, this indicates that limitations on search result have been applied and full search result is not returned.
 33 | 
 34 | ### NO_CATALOG
 35 | 
 36 | **Type:** Number = 4
 37 | 
 38 | NO_CATALOG search result status code 4, this indicates that there is no catalog associated for search query.
 39 | 
 40 | ### NO_CATEGORY
 41 | 
 42 | **Type:** Number = 5
 43 | 
 44 | NO_CATEGORY search result status code 5, this indicates that there is no category associated for search query.
 45 | 
 46 | ### NO_INDEX
 47 | 
 48 | **Type:** Number = 8
 49 | 
 50 | NO_INDEX search result status code 8, this indicates that there is no active search index available.
 51 | 
 52 | ### NOT_EXECUTED
 53 | 
 54 | **Type:** Number = 0
 55 | 
 56 | NOT_EXECUTED search result status code 0, this indicates that search API call has not been made on SearchModel.
 57 | 
 58 | ### OFFLINE_CATEGORY
 59 | 
 60 | **Type:** Number = 7
 61 | 
 62 | OFFLINE_CATEGORY search result status code 7, this indicates that the category associated with search query is offline.
 63 | 
 64 | ### ROOT_SEARCH
 65 | 
 66 | **Type:** Number = 3
 67 | 
 68 | ROOT_SEARCH search result status code 3, this indicates that search result is returned for ROOT search.
 69 | 
 70 | ### SUCCESSFUL
 71 | 
 72 | **Type:** Number = 1
 73 | 
 74 | SUCCESSFUL search result status code 1, this indicates that search API call is executed without any issue.
 75 | 
 76 | ## Properties
 77 | 
 78 | ### description
 79 | 
 80 | **Type:** String (Read Only)
 81 | 
 82 | Returns status code description of search result, it provides more details about search API call status.
 83 | 
 84 | ### statusCode
 85 | 
 86 | **Type:** Number (Read Only)
 87 | 
 88 | Returns status code of search result, by default it will return 0 which means that search has not been executed
 89 |  on SearchModel.
 90 | 
 91 | ## Constructor Summary
 92 | 
 93 | ## Method Summary
 94 | 
 95 | ### getDescription
 96 | 
 97 | **Signature:** `getDescription() : String`
 98 | 
 99 | Returns status code description of search result, it provides more details about search API call status.
100 | 
101 | ### getStatusCode
102 | 
103 | **Signature:** `getStatusCode() : Number`
104 | 
105 | Returns status code of search result, by default it will return 0 which means that search has not been executed on SearchModel.
106 | 
107 | ### toString
108 | 
109 | **Signature:** `toString() : String`
110 | 
111 | Returns string values of status code and description.
112 | 
113 | ## Method Detail
114 | 
115 | ## Method Details
116 | 
117 | ### getDescription
118 | 
119 | **Signature:** `getDescription() : String`
120 | 
121 | **Description:** Returns status code description of search result, it provides more details about search API call status.
122 | 
123 | **Returns:**
124 | 
125 | search status description
126 | 
127 | ---
128 | 
129 | ### getStatusCode
130 | 
131 | **Signature:** `getStatusCode() : Number`
132 | 
133 | **Description:** Returns status code of search result, by default it will return 0 which means that search has not been executed on SearchModel.
134 | 
135 | **Returns:**
136 | 
137 | search status code
138 | 
139 | ---
140 | 
141 | ### toString
142 | 
143 | **Signature:** `toString() : String`
144 | 
145 | **Description:** Returns string values of status code and description.
146 | 
147 | **Returns:**
148 | 
149 | search status string
150 | 
151 | ---
```

--------------------------------------------------------------------------------
/docs/dw_object/CustomAttributes.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Package: dw.object
 2 | 
 3 | # Class CustomAttributes
 4 | 
 5 | ## Inheritance Hierarchy
 6 | 
 7 | - Object
 8 |   - dw.object.CustomAttributes
 9 | 
10 | ## Description
11 | 
12 | 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.
13 | 
14 | ## Constructor Summary
15 | 
16 | ## Method Summary
```

--------------------------------------------------------------------------------
/docs/dw_util/SortedMap.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.util
  2 | 
  3 | # Class SortedMap
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.util.Map
  9 |   - dw.util.SortedMap
 10 | 
 11 | ## Description
 12 | 
 13 | 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.
 14 | 
 15 | ## Constructor Summary
 16 | 
 17 | SortedMap() Constructor to create a new SortedMap.
 18 | 
 19 | SortedMap(comparator : Object) Constructor to create a new SortedMap.
 20 | 
 21 | ## Method Summary
 22 | 
 23 | ### clone
 24 | 
 25 | **Signature:** `clone() : SortedMap`
 26 | 
 27 | Returns a shallow copy of this map.
 28 | 
 29 | ### firstKey
 30 | 
 31 | **Signature:** `firstKey() : Object`
 32 | 
 33 | Returns the first (lowest) key currently in this sorted map.
 34 | 
 35 | ### headMap
 36 | 
 37 | **Signature:** `headMap(key : Object) : SortedMap`
 38 | 
 39 | Returns a view of the portion of this map whose keys are strictly less than toKey.
 40 | 
 41 | ### lastKey
 42 | 
 43 | **Signature:** `lastKey() : Object`
 44 | 
 45 | Returns the last (highest) key currently in this sorted map.
 46 | 
 47 | ### subMap
 48 | 
 49 | **Signature:** `subMap(from : Object, to : Object) : SortedMap`
 50 | 
 51 | Returns a view of the portion of this map whose keys range from fromKey, inclusive, to toKey, exclusive.
 52 | 
 53 | ### tailMap
 54 | 
 55 | **Signature:** `tailMap(key : Object) : SortedMap`
 56 | 
 57 | Returns a view of the portion of this map whose keys are greater than or equal to fromKey.
 58 | 
 59 | ## Constructor Detail
 60 | 
 61 | ## Method Detail
 62 | 
 63 | ## Method Details
 64 | 
 65 | ### clone
 66 | 
 67 | **Signature:** `clone() : SortedMap`
 68 | 
 69 | **Description:** Returns a shallow copy of this map.
 70 | 
 71 | **Returns:**
 72 | 
 73 | a shallow copy of this map.
 74 | 
 75 | ---
 76 | 
 77 | ### firstKey
 78 | 
 79 | **Signature:** `firstKey() : Object`
 80 | 
 81 | **Description:** Returns the first (lowest) key currently in this sorted map.
 82 | 
 83 | **Returns:**
 84 | 
 85 | the first (lowest) key currently in this sorted map.
 86 | 
 87 | ---
 88 | 
 89 | ### headMap
 90 | 
 91 | **Signature:** `headMap(key : Object) : SortedMap`
 92 | 
 93 | **Description:** Returns a view of the portion of this map whose keys are strictly less than toKey.
 94 | 
 95 | **Parameters:**
 96 | 
 97 | - `key`: high endpoint (exclusive) of the headMap.
 98 | 
 99 | **Returns:**
100 | 
101 | a view of the portion of this map whose keys are strictly less than toKey.
102 | 
103 | ---
104 | 
105 | ### lastKey
106 | 
107 | **Signature:** `lastKey() : Object`
108 | 
109 | **Description:** Returns the last (highest) key currently in this sorted map.
110 | 
111 | **Returns:**
112 | 
113 | the last (highest) key currently in this sorted map.
114 | 
115 | ---
116 | 
117 | ### subMap
118 | 
119 | **Signature:** `subMap(from : Object, to : Object) : SortedMap`
120 | 
121 | **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.)
122 | 
123 | **Parameters:**
124 | 
125 | - `from`: low endpoint (inclusive) of the subMap.
126 | - `to`: high endpoint (exclusive) of the subMap.
127 | 
128 | **Returns:**
129 | 
130 | a view of the portion of this map whose keys range from fromKey, inclusive, to toKey, exclusive.
131 | 
132 | ---
133 | 
134 | ### tailMap
135 | 
136 | **Signature:** `tailMap(key : Object) : SortedMap`
137 | 
138 | **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.
139 | 
140 | **Parameters:**
141 | 
142 | - `key`: low endpoint (inclusive) of the tailMap.
143 | 
144 | **Returns:**
145 | 
146 | a view of the portion of this map whose keys are greater than or equal to fromKey.
147 | 
148 | ---
```

--------------------------------------------------------------------------------
/docs/dw_system/Transaction.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Package: dw.system
 2 | 
 3 | # Class Transaction
 4 | 
 5 | ## Inheritance Hierarchy
 6 | 
 7 | - Object
 8 |   - dw.system.Transaction
 9 | 
10 | ## Description
11 | 
12 | Represents the current transaction. A transaction provides a context for performing atomic changes to persistent business objects. Before a business object can be created, changed, or deleted, a transaction must be started using the begin() method. All changes on the touched business objects will only be made durable when the transaction is committed with commit(). If a transaction is rolled back, all changes so far will be reverted and the business object will have their previous state again. It is possible to begin a transaction multiple times in a nested way (like begin-begin-commit-commit). In this case, in order to commit the changes the commit method must be called symmetrically as often as begin. It is also possible to run multiple transactions within a single request, one after another (like begin-commit-begin-commit). In case of any exception while working with business objects inside of a transaction, the transaction cannot be committed anymore, but only be rolled back. Business code may try to take appropriate actions if it expects business-related problems at commit (for example, constraint violations). When a transaction is still open at the end of a pipeline call, controller call, or job step, the remaining changes are committed unless an exception is thrown. The following best practices exist for using transactions: Avoid long running transactions in jobs. Use one transaction for changes that belong together and need a joint rollback. In most cases, one transaction for all changes in a request is better than multiple transactions for each individual object. Don’t begin and commit a huge number of small transactions in a loop. Avoid changing the same objects in parallel transactions. Example 1 - explicit control: var txn = require('dw/system/Transaction'); txn.begin(); // work with business objects here txn.commit(); Example 2 - implicit control: var txn = require('dw/system/Transaction'); txn.wrap(function(){ // work with business objects here });
13 | 
14 | ## Constructor Summary
15 | 
16 | ## Method Summary
17 | 
18 | ### begin
19 | 
20 | **Signature:** `static begin() : void`
21 | 
22 | Begins a transaction.
23 | 
24 | ### commit
25 | 
26 | **Signature:** `static commit() : void`
27 | 
28 | Commits the current transaction.
29 | 
30 | ### rollback
31 | 
32 | **Signature:** `static rollback() : void`
33 | 
34 | Rolls back the current transaction.
35 | 
36 | ### wrap
37 | 
38 | **Signature:** `static wrap(callback : Function) : Object`
39 | 
40 | Encloses the provided callback function in a begin-commit transactional context.
41 | 
42 | ## Method Detail
43 | 
44 | ## Method Details
45 | 
46 | ### begin
47 | 
48 | **Signature:** `static begin() : void`
49 | 
50 | **Description:** Begins a transaction.
51 | 
52 | ---
53 | 
54 | ### commit
55 | 
56 | **Signature:** `static commit() : void`
57 | 
58 | **Description:** Commits the current transaction. The transaction must have been started with begin() before.
59 | 
60 | ---
61 | 
62 | ### rollback
63 | 
64 | **Signature:** `static rollback() : void`
65 | 
66 | **Description:** Rolls back the current transaction. The transaction must have been started with begin() before.
67 | 
68 | ---
69 | 
70 | ### wrap
71 | 
72 | **Signature:** `static wrap(callback : Function) : Object`
73 | 
74 | **Description:** Encloses the provided callback function in a begin-commit transactional context. If the transaction cannot be committed successfully, it is rolled back instead and an exception is thrown.
75 | 
76 | **Parameters:**
77 | 
78 | - `callback`: a function that should be executed within a transactional context
79 | 
80 | **Returns:**
81 | 
82 | the result of the callback function, if it returns something
83 | 
84 | ---
```

--------------------------------------------------------------------------------
/docs/dw_customer/AgentUserMgr.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Package: dw.customer
 2 | 
 3 | # Class AgentUserMgr
 4 | 
 5 | ## Inheritance Hierarchy
 6 | 
 7 | - Object
 8 |   - dw.customer.AgentUserMgr
 9 | 
10 | ## Description
11 | 
12 | Provides helper methods for handling agent user functionality (login and logout) Pay attention to appropriate legal and regulatory requirements related to this functionality.
13 | 
14 | ## Constructor Summary
15 | 
16 | ## Method Summary
17 | 
18 | ### loginAgentUser
19 | 
20 | **Signature:** `static loginAgentUser(login : String, password : String) : Status`
21 | 
22 | Logs in an agent user (which for example is authorized to login on-behalf of a customer for instance to place an order).
23 | 
24 | ### loginOnBehalfOfCustomer
25 | 
26 | **Signature:** `static loginOnBehalfOfCustomer(customer : Customer) : Status`
27 | 
28 | This method logs the specified customer into the current session if the current agent user has the functional permission 'Login_On_Behalf' in the current site.
29 | 
30 | ### logoutAgentUser
31 | 
32 | **Signature:** `static logoutAgentUser() : Status`
33 | 
34 | Performs a logout of the agent user and the current customer which are attached to the current session.
35 | 
36 | ## Method Detail
37 | 
38 | ## Method Details
39 | 
40 | ### loginAgentUser
41 | 
42 | **Signature:** `static loginAgentUser(login : String, password : String) : Status`
43 | 
44 | **Description:** Logs in an agent user (which for example is authorized to login on-behalf of a customer for instance to place an order). The login is only allowed during a secure protocol request (https) and only in the storefront context. The user must have the permission 'Login_Agent'. When the login is successful, a new session will be created. Any objects that need to be preserved in the session need to bet set on the session afterwards. A Status object is returned which signals whether the login was successful or not. In case of a login failure the status object contains the reason for this. See AgentUserStatusCodes for more information.
45 | 
46 | **Parameters:**
47 | 
48 | - `login`: the login name for the agent user.
49 | - `password`: the password for the agent user.
50 | 
51 | **Returns:**
52 | 
53 | the login status (OK if successful, error code otherwise).
54 | 
55 | ---
56 | 
57 | ### loginOnBehalfOfCustomer
58 | 
59 | **Signature:** `static loginOnBehalfOfCustomer(customer : Customer) : Status`
60 | 
61 | **Description:** This method logs the specified customer into the current session if the current agent user has the functional permission 'Login_On_Behalf' in the current site. The dwcustomer cookie will not be set. The login is only allowed during a secure protocol request (https). A Status object is returned indicating whether the login was successful or not (and indicating the failure reason). See AgentUserStatusCodes for more information. Error conditions include: if the method is not called in the storefront context if the given customer is not a registered customer (anonymous) if the given customer is not registered for the current site if the given customer is disabled if there is no agent user at the current session if the agent user is not logged in if the agent user has not the functional permission 'Login_On_Behalf'
62 | 
63 | **Parameters:**
64 | 
65 | - `customer`: The customer, which should be logged instead of the agent user
66 | 
67 | **Returns:**
68 | 
69 | the login status (OK if successful, error code otherwise).
70 | 
71 | ---
72 | 
73 | ### logoutAgentUser
74 | 
75 | **Signature:** `static logoutAgentUser() : Status`
76 | 
77 | **Description:** Performs a logout of the agent user and the current customer which are attached to the current session. The logout is only allowed during a secure protocol request (https) and only in the storefront context.
78 | 
79 | **Returns:**
80 | 
81 | the logout status (OK if successful, error code otherwise).
82 | 
83 | ---
```

--------------------------------------------------------------------------------
/docs/sfra/price-default.md:
--------------------------------------------------------------------------------

```markdown
  1 | # SFRA Default Price Model
  2 | 
  3 | ## Overview
  4 | 
  5 | The Default Price model represents standard product pricing in SFRA applications. It provides formatted price information including sales prices, list prices, and currency details for product display and calculations.
  6 | 
  7 | ## Constructor
  8 | 
  9 | ```javascript
 10 | function DefaultPrice(salesPrice, listPrice)
 11 | ```
 12 | 
 13 | Creates a Default Price model instance with sales and list pricing information.
 14 | 
 15 | ### Parameters
 16 | 
 17 | - `salesPrice` (dw.value.Money) - Sales price from the API
 18 | - `listPrice` (dw.value.Money) - List price from the API (optional)
 19 | 
 20 | ## Properties
 21 | 
 22 | ### sales
 23 | **Type:** Object
 24 | 
 25 | Sales price information containing:
 26 | - `value` (number | null) - Decimal price value
 27 | - `currency` (string | null) - Currency code
 28 | - `formatted` (string | null) - Formatted price string for display
 29 | - `decimalPrice` (string | null) - Decimal price as string
 30 | 
 31 | ### list
 32 | **Type:** Object | null
 33 | 
 34 | List price information (same structure as sales) or null if no list price provided.
 35 | 
 36 | ## Helper Functions
 37 | 
 38 | ### toPriceModel(price)
 39 | Converts an API Money object to a structured price model.
 40 | 
 41 | **Parameters:**
 42 | - `price` (dw.value.Money) - Price object from the API
 43 | 
 44 | **Returns:** Object - Formatted price object with value, currency, formatted string, and decimal price
 45 | 
 46 | ## Price Object Structure
 47 | 
 48 | Each price object (sales/list) contains:
 49 | 
 50 | ### value
 51 | Raw numeric price value for calculations and comparisons.
 52 | 
 53 | ### currency
 54 | Three-letter currency code (e.g., "USD", "EUR").
 55 | 
 56 | ### formatted
 57 | User-friendly formatted price string with currency symbol (e.g., "$29.99").
 58 | 
 59 | ### decimalPrice
 60 | String representation of the decimal price for precise display.
 61 | 
 62 | ## Usage Example
 63 | 
 64 | ```javascript
 65 | var DefaultPrice = require('*/cartridge/models/price/default');
 66 | 
 67 | // Get prices from product
 68 | var product = ProductMgr.getProduct('product-id');
 69 | var salesPrice = product.getPriceModel().getPrice();
 70 | var listPrice = product.getPriceModel().getPriceBookPrice('list-price-book');
 71 | 
 72 | var price = new DefaultPrice(salesPrice, listPrice);
 73 | 
 74 | // Access sales price
 75 | console.log(price.sales.formatted);    // "$29.99"
 76 | console.log(price.sales.value);        // 29.99
 77 | console.log(price.sales.currency);     // "USD"
 78 | 
 79 | // Check for list price (original/MSRP)
 80 | if (price.list) {
 81 |     console.log('Was: ' + price.list.formatted);
 82 |     console.log('Now: ' + price.sales.formatted);
 83 |     
 84 |     // Calculate discount percentage
 85 |     var discount = ((price.list.value - price.sales.value) / price.list.value) * 100;
 86 |     console.log('Save ' + discount.toFixed(0) + '%');
 87 | }
 88 | ```
 89 | 
 90 | ## Price Availability
 91 | 
 92 | The model handles unavailable prices gracefully:
 93 | - When price is not available, all properties return null
 94 | - Prevents errors when price calculation fails
 95 | - Provides consistent structure regardless of price availability
 96 | 
 97 | ## Currency Support
 98 | 
 99 | The model supports international pricing:
100 | - Currency codes from the Money object
101 | - Formatted strings respect locale settings
102 | - Decimal representation for precise calculations
103 | 
104 | ## Notes
105 | 
106 | - Handles both sales and list prices
107 | - Gracefully manages unavailable prices with null values
108 | - Provides multiple price formats for different use cases
109 | - Supports international currencies and formatting
110 | - List price is optional (may be null)
111 | - Decimal price provides precise string representation
112 | 
113 | ## Related Models
114 | 
115 | - **Tiered Price Model** - For quantity-based pricing
116 | - **Range Price Model** - For price range displays
117 | - **Product Models** - Use price models for product pricing
118 | - **Cart Models** - Use price models for line item pricing
119 | 
```
Page 6/61FirstPrevNextLast