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 |
```