This is page 7 of 43. Use http://codebase.md/taurgis/sfcc-dev-mcp?lines=false&page={x} to view the full context. # Directory Structure ``` ├── .DS_Store ├── .github │ ├── dependabot.yml │ ├── instructions │ │ ├── mcp-node-tests.instructions.md │ │ └── mcp-yml-tests.instructions.md │ ├── ISSUE_TEMPLATE │ │ ├── bug_report.yml │ │ ├── config.yml │ │ ├── documentation.yml │ │ ├── feature_request.yml │ │ └── question.yml │ ├── PULL_REQUEST_TEMPLATE │ │ ├── bug_fix.md │ │ ├── documentation.md │ │ └── new_tool.md │ ├── pull_request_template.md │ └── workflows │ ├── ci.yml │ ├── deploy-pages.yml │ ├── publish.yml │ └── update-docs.yml ├── .gitignore ├── .husky │ └── pre-commit ├── aegis.config.docs-only.json ├── aegis.config.json ├── aegis.config.with-dw.json ├── AGENTS.md ├── ai-instructions │ ├── claude-desktop │ │ └── claude_custom_instructions.md │ ├── cursor │ │ └── .cursor │ │ └── rules │ │ ├── debugging-workflows.mdc │ │ ├── hooks-development.mdc │ │ ├── isml-templates.mdc │ │ ├── job-framework.mdc │ │ ├── performance-optimization.mdc │ │ ├── scapi-endpoints.mdc │ │ ├── security-patterns.mdc │ │ ├── sfcc-development.mdc │ │ ├── sfra-controllers.mdc │ │ ├── sfra-models.mdc │ │ ├── system-objects.mdc │ │ └── testing-patterns.mdc │ └── github-copilot │ └── copilot-instructions.md ├── CHANGELOG.md ├── CONTRIBUTING.md ├── docs │ ├── best-practices │ │ ├── cartridge_creation.md │ │ ├── isml_templates.md │ │ ├── job_framework.md │ │ ├── localserviceregistry.md │ │ ├── ocapi_hooks.md │ │ ├── performance.md │ │ ├── scapi_custom_endpoint.md │ │ ├── scapi_hooks.md │ │ ├── security.md │ │ ├── sfra_client_side_js.md │ │ ├── sfra_controllers.md │ │ ├── sfra_models.md │ │ └── sfra_scss.md │ ├── dw_campaign │ │ ├── ABTest.md │ │ ├── ABTestMgr.md │ │ ├── ABTestSegment.md │ │ ├── AmountDiscount.md │ │ ├── ApproachingDiscount.md │ │ ├── BonusChoiceDiscount.md │ │ ├── BonusDiscount.md │ │ ├── Campaign.md │ │ ├── CampaignMgr.md │ │ ├── CampaignStatusCodes.md │ │ ├── Coupon.md │ │ ├── CouponMgr.md │ │ ├── CouponRedemption.md │ │ ├── CouponStatusCodes.md │ │ ├── Discount.md │ │ ├── DiscountPlan.md │ │ ├── FixedPriceDiscount.md │ │ ├── FixedPriceShippingDiscount.md │ │ ├── FreeDiscount.md │ │ ├── FreeShippingDiscount.md │ │ ├── PercentageDiscount.md │ │ ├── PercentageOptionDiscount.md │ │ ├── PriceBookPriceDiscount.md │ │ ├── Promotion.md │ │ ├── PromotionMgr.md │ │ ├── PromotionPlan.md │ │ ├── SlotContent.md │ │ ├── SourceCodeGroup.md │ │ ├── SourceCodeInfo.md │ │ ├── SourceCodeStatusCodes.md │ │ └── TotalFixedPriceDiscount.md │ ├── dw_catalog │ │ ├── Catalog.md │ │ ├── CatalogMgr.md │ │ ├── Category.md │ │ ├── CategoryAssignment.md │ │ ├── CategoryLink.md │ │ ├── PriceBook.md │ │ ├── PriceBookMgr.md │ │ ├── Product.md │ │ ├── ProductActiveData.md │ │ ├── ProductAttributeModel.md │ │ ├── ProductAvailabilityLevels.md │ │ ├── ProductAvailabilityModel.md │ │ ├── ProductInventoryList.md │ │ ├── ProductInventoryMgr.md │ │ ├── ProductInventoryRecord.md │ │ ├── ProductLink.md │ │ ├── ProductMgr.md │ │ ├── ProductOption.md │ │ ├── ProductOptionModel.md │ │ ├── ProductOptionValue.md │ │ ├── ProductPriceInfo.md │ │ ├── ProductPriceModel.md │ │ ├── ProductPriceTable.md │ │ ├── ProductSearchHit.md │ │ ├── ProductSearchModel.md │ │ ├── ProductSearchRefinementDefinition.md │ │ ├── ProductSearchRefinements.md │ │ ├── ProductSearchRefinementValue.md │ │ ├── ProductVariationAttribute.md │ │ ├── ProductVariationAttributeValue.md │ │ ├── ProductVariationModel.md │ │ ├── Recommendation.md │ │ ├── SearchModel.md │ │ ├── SearchRefinementDefinition.md │ │ ├── SearchRefinements.md │ │ ├── SearchRefinementValue.md │ │ ├── SortingOption.md │ │ ├── SortingRule.md │ │ ├── Store.md │ │ ├── StoreGroup.md │ │ ├── StoreInventoryFilter.md │ │ ├── StoreInventoryFilterValue.md │ │ ├── StoreMgr.md │ │ ├── Variant.md │ │ └── VariationGroup.md │ ├── dw_content │ │ ├── Content.md │ │ ├── ContentMgr.md │ │ ├── ContentSearchModel.md │ │ ├── ContentSearchRefinementDefinition.md │ │ ├── ContentSearchRefinements.md │ │ ├── ContentSearchRefinementValue.md │ │ ├── Folder.md │ │ ├── Library.md │ │ ├── MarkupText.md │ │ └── MediaFile.md │ ├── dw_crypto │ │ ├── CertificateRef.md │ │ ├── CertificateUtils.md │ │ ├── Cipher.md │ │ ├── Encoding.md │ │ ├── JWE.md │ │ ├── JWEHeader.md │ │ ├── JWS.md │ │ ├── JWSHeader.md │ │ ├── KeyRef.md │ │ ├── Mac.md │ │ ├── MessageDigest.md │ │ ├── SecureRandom.md │ │ ├── Signature.md │ │ ├── WeakCipher.md │ │ ├── WeakMac.md │ │ ├── WeakMessageDigest.md │ │ ├── WeakSignature.md │ │ └── X509Certificate.md │ ├── dw_customer │ │ ├── AddressBook.md │ │ ├── AgentUserMgr.md │ │ ├── AgentUserStatusCodes.md │ │ ├── AuthenticationStatus.md │ │ ├── Credentials.md │ │ ├── Customer.md │ │ ├── CustomerActiveData.md │ │ ├── CustomerAddress.md │ │ ├── CustomerCDPData.md │ │ ├── CustomerContextMgr.md │ │ ├── CustomerGroup.md │ │ ├── CustomerList.md │ │ ├── CustomerMgr.md │ │ ├── CustomerPasswordConstraints.md │ │ ├── CustomerPaymentInstrument.md │ │ ├── CustomerStatusCodes.md │ │ ├── EncryptedObject.md │ │ ├── ExternalProfile.md │ │ ├── OrderHistory.md │ │ ├── ProductList.md │ │ ├── ProductListItem.md │ │ ├── ProductListItemPurchase.md │ │ ├── ProductListMgr.md │ │ ├── ProductListRegistrant.md │ │ ├── Profile.md │ │ └── Wallet.md │ ├── dw_extensions.applepay │ │ ├── ApplePayHookResult.md │ │ └── ApplePayHooks.md │ ├── dw_extensions.facebook │ │ ├── FacebookFeedHooks.md │ │ └── FacebookProduct.md │ ├── dw_extensions.paymentrequest │ │ ├── PaymentRequestHookResult.md │ │ └── PaymentRequestHooks.md │ ├── dw_extensions.payments │ │ ├── SalesforceBancontactPaymentDetails.md │ │ ├── SalesforceCardPaymentDetails.md │ │ ├── SalesforceEpsPaymentDetails.md │ │ ├── SalesforceIdealPaymentDetails.md │ │ ├── SalesforceKlarnaPaymentDetails.md │ │ ├── SalesforcePaymentDetails.md │ │ ├── SalesforcePaymentIntent.md │ │ ├── SalesforcePaymentMethod.md │ │ ├── SalesforcePaymentRequest.md │ │ ├── SalesforcePaymentsHooks.md │ │ ├── SalesforcePaymentsMgr.md │ │ ├── SalesforcePaymentsSiteConfiguration.md │ │ ├── SalesforcePayPalOrder.md │ │ ├── SalesforcePayPalOrderAddress.md │ │ ├── SalesforcePayPalOrderPayer.md │ │ ├── SalesforcePayPalPaymentDetails.md │ │ ├── SalesforceSepaDebitPaymentDetails.md │ │ └── SalesforceVenmoPaymentDetails.md │ ├── dw_extensions.pinterest │ │ ├── PinterestAvailability.md │ │ ├── PinterestFeedHooks.md │ │ ├── PinterestOrder.md │ │ ├── PinterestOrderHooks.md │ │ └── PinterestProduct.md │ ├── dw_io │ │ ├── CSVStreamReader.md │ │ ├── CSVStreamWriter.md │ │ ├── File.md │ │ ├── FileReader.md │ │ ├── FileWriter.md │ │ ├── InputStream.md │ │ ├── OutputStream.md │ │ ├── PrintWriter.md │ │ ├── RandomAccessFileReader.md │ │ ├── Reader.md │ │ ├── StringWriter.md │ │ ├── Writer.md │ │ ├── XMLIndentingStreamWriter.md │ │ ├── XMLStreamConstants.md │ │ ├── XMLStreamReader.md │ │ └── XMLStreamWriter.md │ ├── dw_job │ │ ├── JobExecution.md │ │ └── JobStepExecution.md │ ├── dw_net │ │ ├── FTPClient.md │ │ ├── FTPFileInfo.md │ │ ├── HTTPClient.md │ │ ├── HTTPRequestPart.md │ │ ├── Mail.md │ │ ├── SFTPClient.md │ │ ├── SFTPFileInfo.md │ │ ├── WebDAVClient.md │ │ └── WebDAVFileInfo.md │ ├── dw_object │ │ ├── ActiveData.md │ │ ├── CustomAttributes.md │ │ ├── CustomObject.md │ │ ├── CustomObjectMgr.md │ │ ├── Extensible.md │ │ ├── ExtensibleObject.md │ │ ├── Note.md │ │ ├── ObjectAttributeDefinition.md │ │ ├── ObjectAttributeGroup.md │ │ ├── ObjectAttributeValueDefinition.md │ │ ├── ObjectTypeDefinition.md │ │ ├── PersistentObject.md │ │ ├── SimpleExtensible.md │ │ └── SystemObjectMgr.md │ ├── dw_order │ │ ├── AbstractItem.md │ │ ├── AbstractItemCtnr.md │ │ ├── Appeasement.md │ │ ├── AppeasementItem.md │ │ ├── Basket.md │ │ ├── BasketMgr.md │ │ ├── BonusDiscountLineItem.md │ │ ├── CouponLineItem.md │ │ ├── CreateAgentBasketLimitExceededException.md │ │ ├── CreateBasketFromOrderException.md │ │ ├── CreateCouponLineItemException.md │ │ ├── CreateOrderException.md │ │ ├── CreateTemporaryBasketLimitExceededException.md │ │ ├── GiftCertificate.md │ │ ├── GiftCertificateLineItem.md │ │ ├── GiftCertificateMgr.md │ │ ├── GiftCertificateStatusCodes.md │ │ ├── Invoice.md │ │ ├── InvoiceItem.md │ │ ├── LineItem.md │ │ ├── LineItemCtnr.md │ │ ├── Order.md │ │ ├── OrderAddress.md │ │ ├── OrderItem.md │ │ ├── OrderMgr.md │ │ ├── OrderPaymentInstrument.md │ │ ├── OrderProcessStatusCodes.md │ │ ├── PaymentCard.md │ │ ├── PaymentInstrument.md │ │ ├── PaymentMethod.md │ │ ├── PaymentMgr.md │ │ ├── PaymentProcessor.md │ │ ├── PaymentStatusCodes.md │ │ ├── PaymentTransaction.md │ │ ├── PriceAdjustment.md │ │ ├── PriceAdjustmentLimitTypes.md │ │ ├── ProductLineItem.md │ │ ├── ProductShippingCost.md │ │ ├── ProductShippingLineItem.md │ │ ├── ProductShippingModel.md │ │ ├── Return.md │ │ ├── ReturnCase.md │ │ ├── ReturnCaseItem.md │ │ ├── ReturnItem.md │ │ ├── Shipment.md │ │ ├── ShipmentShippingCost.md │ │ ├── ShipmentShippingModel.md │ │ ├── ShippingLineItem.md │ │ ├── ShippingLocation.md │ │ ├── ShippingMethod.md │ │ ├── ShippingMgr.md │ │ ├── ShippingOrder.md │ │ ├── ShippingOrderItem.md │ │ ├── SumItem.md │ │ ├── TaxGroup.md │ │ ├── TaxItem.md │ │ ├── TaxMgr.md │ │ ├── TrackingInfo.md │ │ └── TrackingRef.md │ ├── dw_order.hooks │ │ ├── CalculateHooks.md │ │ ├── OrderHooks.md │ │ ├── PaymentHooks.md │ │ ├── ReturnHooks.md │ │ └── ShippingOrderHooks.md │ ├── dw_rpc │ │ ├── SOAPUtil.md │ │ ├── Stub.md │ │ └── WebReference.md │ ├── dw_suggest │ │ ├── BrandSuggestions.md │ │ ├── CategorySuggestions.md │ │ ├── ContentSuggestions.md │ │ ├── CustomSuggestions.md │ │ ├── ProductSuggestions.md │ │ ├── SearchPhraseSuggestions.md │ │ ├── SuggestedCategory.md │ │ ├── SuggestedContent.md │ │ ├── SuggestedPhrase.md │ │ ├── SuggestedProduct.md │ │ ├── SuggestedTerm.md │ │ ├── SuggestedTerms.md │ │ ├── Suggestions.md │ │ └── SuggestModel.md │ ├── dw_svc │ │ ├── FTPService.md │ │ ├── FTPServiceDefinition.md │ │ ├── HTTPFormService.md │ │ ├── HTTPFormServiceDefinition.md │ │ ├── HTTPService.md │ │ ├── HTTPServiceDefinition.md │ │ ├── LocalServiceRegistry.md │ │ ├── Result.md │ │ ├── Service.md │ │ ├── ServiceCallback.md │ │ ├── ServiceConfig.md │ │ ├── ServiceCredential.md │ │ ├── ServiceDefinition.md │ │ ├── ServiceProfile.md │ │ ├── ServiceRegistry.md │ │ ├── SOAPService.md │ │ └── SOAPServiceDefinition.md │ ├── dw_system │ │ ├── AgentUserStatusCodes.md │ │ ├── Cache.md │ │ ├── CacheMgr.md │ │ ├── HookMgr.md │ │ ├── InternalObject.md │ │ ├── JobProcessMonitor.md │ │ ├── Log.md │ │ ├── Logger.md │ │ ├── LogNDC.md │ │ ├── OrganizationPreferences.md │ │ ├── Pipeline.md │ │ ├── PipelineDictionary.md │ │ ├── RemoteInclude.md │ │ ├── Request.md │ │ ├── RequestHooks.md │ │ ├── Response.md │ │ ├── RESTErrorResponse.md │ │ ├── RESTResponseMgr.md │ │ ├── RESTSuccessResponse.md │ │ ├── SearchStatus.md │ │ ├── Session.md │ │ ├── Site.md │ │ ├── SitePreferences.md │ │ ├── Status.md │ │ ├── StatusItem.md │ │ ├── System.md │ │ └── Transaction.md │ ├── dw_util │ │ ├── ArrayList.md │ │ ├── Assert.md │ │ ├── BigInteger.md │ │ ├── Bytes.md │ │ ├── Calendar.md │ │ ├── Collection.md │ │ ├── Currency.md │ │ ├── DateUtils.md │ │ ├── Decimal.md │ │ ├── FilteringCollection.md │ │ ├── Geolocation.md │ │ ├── HashMap.md │ │ ├── HashSet.md │ │ ├── Iterator.md │ │ ├── LinkedHashMap.md │ │ ├── LinkedHashSet.md │ │ ├── List.md │ │ ├── Locale.md │ │ ├── Map.md │ │ ├── MapEntry.md │ │ ├── MappingKey.md │ │ ├── MappingMgr.md │ │ ├── PropertyComparator.md │ │ ├── SecureEncoder.md │ │ ├── SecureFilter.md │ │ ├── SeekableIterator.md │ │ ├── Set.md │ │ ├── SortedMap.md │ │ ├── SortedSet.md │ │ ├── StringUtils.md │ │ ├── Template.md │ │ └── UUIDUtils.md │ ├── dw_value │ │ ├── EnumValue.md │ │ ├── MimeEncodedText.md │ │ ├── Money.md │ │ └── Quantity.md │ ├── dw_web │ │ ├── ClickStream.md │ │ ├── ClickStreamEntry.md │ │ ├── Cookie.md │ │ ├── Cookies.md │ │ ├── CSRFProtection.md │ │ ├── Form.md │ │ ├── FormAction.md │ │ ├── FormElement.md │ │ ├── FormElementValidationResult.md │ │ ├── FormField.md │ │ ├── FormFieldOption.md │ │ ├── FormFieldOptions.md │ │ ├── FormGroup.md │ │ ├── FormList.md │ │ ├── FormListItem.md │ │ ├── Forms.md │ │ ├── HttpParameter.md │ │ ├── HttpParameterMap.md │ │ ├── LoopIterator.md │ │ ├── PageMetaData.md │ │ ├── PageMetaTag.md │ │ ├── PagingModel.md │ │ ├── Resource.md │ │ ├── URL.md │ │ ├── URLAction.md │ │ ├── URLParameter.md │ │ ├── URLRedirect.md │ │ ├── URLRedirectMgr.md │ │ └── URLUtils.md │ ├── sfra │ │ ├── account.md │ │ ├── address.md │ │ ├── billing.md │ │ ├── cart.md │ │ ├── categories.md │ │ ├── content.md │ │ ├── locale.md │ │ ├── order.md │ │ ├── payment.md │ │ ├── price-default.md │ │ ├── price-range.md │ │ ├── price-tiered.md │ │ ├── product-bundle.md │ │ ├── product-full.md │ │ ├── product-line-items.md │ │ ├── product-search.md │ │ ├── product-tile.md │ │ ├── querystring.md │ │ ├── render.md │ │ ├── request.md │ │ ├── response.md │ │ ├── server.md │ │ ├── shipping.md │ │ ├── store.md │ │ ├── stores.md │ │ └── totals.md │ └── TopLevel │ ├── APIException.md │ ├── arguments.md │ ├── Array.md │ ├── ArrayBuffer.md │ ├── BigInt.md │ ├── Boolean.md │ ├── ConversionError.md │ ├── DataView.md │ ├── Date.md │ ├── Error.md │ ├── ES6Iterator.md │ ├── EvalError.md │ ├── Fault.md │ ├── Float32Array.md │ ├── Float64Array.md │ ├── Function.md │ ├── Generator.md │ ├── global.md │ ├── Int16Array.md │ ├── Int32Array.md │ ├── Int8Array.md │ ├── InternalError.md │ ├── IOError.md │ ├── Iterable.md │ ├── Iterator.md │ ├── JSON.md │ ├── Map.md │ ├── Math.md │ ├── Module.md │ ├── Namespace.md │ ├── Number.md │ ├── Object.md │ ├── QName.md │ ├── RangeError.md │ ├── ReferenceError.md │ ├── RegExp.md │ ├── Set.md │ ├── StopIteration.md │ ├── String.md │ ├── Symbol.md │ ├── SyntaxError.md │ ├── SystemError.md │ ├── TypeError.md │ ├── Uint16Array.md │ ├── Uint32Array.md │ ├── Uint8Array.md │ ├── Uint8ClampedArray.md │ ├── URIError.md │ ├── WeakMap.md │ ├── WeakSet.md │ ├── XML.md │ ├── XMLList.md │ └── XMLStreamError.md ├── docs-site │ ├── .gitignore │ ├── App.tsx │ ├── components │ │ ├── Badge.tsx │ │ ├── BreadcrumbSchema.tsx │ │ ├── CodeBlock.tsx │ │ ├── Collapsible.tsx │ │ ├── ConfigBuilder.tsx │ │ ├── ConfigHero.tsx │ │ ├── ConfigModeTabs.tsx │ │ ├── icons.tsx │ │ ├── Layout.tsx │ │ ├── LightCodeContainer.tsx │ │ ├── NewcomerCTA.tsx │ │ ├── NextStepsStrip.tsx │ │ ├── OnThisPage.tsx │ │ ├── Search.tsx │ │ ├── SEO.tsx │ │ ├── Sidebar.tsx │ │ ├── StructuredData.tsx │ │ ├── ToolCard.tsx │ │ ├── ToolFilters.tsx │ │ ├── Typography.tsx │ │ └── VersionBadge.tsx │ ├── constants.tsx │ ├── index.html │ ├── main.tsx │ ├── metadata.json │ ├── package-lock.json │ ├── package.json │ ├── pages │ │ ├── AIInterfacesPage.tsx │ │ ├── ConfigurationPage.tsx │ │ ├── DevelopmentPage.tsx │ │ ├── ExamplesPage.tsx │ │ ├── FeaturesPage.tsx │ │ ├── HomePage.tsx │ │ ├── SecurityPage.tsx │ │ ├── ToolsPage.tsx │ │ └── TroubleshootingPage.tsx │ ├── postcss.config.js │ ├── public │ │ ├── .well-known │ │ │ └── security.txt │ │ ├── 404.html │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── explain-product-pricing-methods-no-mcp.png │ │ ├── explain-product-pricing-methods.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── llms.txt │ │ ├── robots.txt │ │ ├── site.webmanifest │ │ └── sitemap.xml │ ├── README.md │ ├── scripts │ │ ├── generate-search-index.js │ │ ├── generate-sitemap.js │ │ └── search-dev.js │ ├── src │ │ └── styles │ │ ├── input.css │ │ └── prism-theme.css │ ├── tailwind.config.js │ ├── tsconfig.json │ ├── types.ts │ ├── utils │ │ ├── search.ts │ │ └── toolsData.ts │ └── vite.config.ts ├── eslint.config.js ├── jest.config.js ├── LICENSE ├── package-lock.json ├── package.json ├── README.md ├── scripts │ └── convert-docs.js ├── SECURITY.md ├── server.json ├── src │ ├── clients │ │ ├── base │ │ │ ├── http-client.ts │ │ │ ├── oauth-token.ts │ │ │ └── ocapi-auth-client.ts │ │ ├── best-practices-client.ts │ │ ├── cartridge-generation-client.ts │ │ ├── docs │ │ │ ├── class-content-parser.ts │ │ │ ├── class-name-resolver.ts │ │ │ ├── documentation-scanner.ts │ │ │ ├── index.ts │ │ │ └── referenced-types-extractor.ts │ │ ├── docs-client.ts │ │ ├── log-client.ts │ │ ├── logs │ │ │ ├── index.ts │ │ │ ├── log-analyzer.ts │ │ │ ├── log-client.ts │ │ │ ├── log-constants.ts │ │ │ ├── log-file-discovery.ts │ │ │ ├── log-file-reader.ts │ │ │ ├── log-formatter.ts │ │ │ ├── log-processor.ts │ │ │ ├── log-types.ts │ │ │ └── webdav-client-manager.ts │ │ ├── ocapi │ │ │ ├── code-versions-client.ts │ │ │ ├── site-preferences-client.ts │ │ │ └── system-objects-client.ts │ │ ├── ocapi-client.ts │ │ └── sfra-client.ts │ ├── config │ │ ├── configuration-factory.ts │ │ └── dw-json-loader.ts │ ├── core │ │ ├── handlers │ │ │ ├── abstract-log-tool-handler.ts │ │ │ ├── base-handler.ts │ │ │ ├── best-practices-handler.ts │ │ │ ├── cartridge-handler.ts │ │ │ ├── client-factory.ts │ │ │ ├── code-version-handler.ts │ │ │ ├── docs-handler.ts │ │ │ ├── job-log-handler.ts │ │ │ ├── job-log-tool-config.ts │ │ │ ├── log-handler.ts │ │ │ ├── log-tool-config.ts │ │ │ ├── sfra-handler.ts │ │ │ ├── system-object-handler.ts │ │ │ └── validation-helpers.ts │ │ ├── server.ts │ │ └── tool-definitions.ts │ ├── index.ts │ ├── main.ts │ ├── services │ │ ├── file-system-service.ts │ │ ├── index.ts │ │ └── path-service.ts │ ├── tool-configs │ │ ├── best-practices-tool-config.ts │ │ ├── cartridge-tool-config.ts │ │ ├── code-version-tool-config.ts │ │ ├── docs-tool-config.ts │ │ ├── job-log-tool-config.ts │ │ ├── log-tool-config.ts │ │ ├── sfra-tool-config.ts │ │ └── system-object-tool-config.ts │ ├── types │ │ └── types.ts │ └── utils │ ├── cache.ts │ ├── job-log-tool-config.ts │ ├── job-log-utils.ts │ ├── log-cache.ts │ ├── log-tool-config.ts │ ├── log-tool-constants.ts │ ├── log-tool-utils.ts │ ├── logger.ts │ ├── ocapi-url-builder.ts │ ├── path-resolver.ts │ ├── query-builder.ts │ ├── utils.ts │ └── validator.ts ├── tests │ ├── __mocks__ │ │ ├── docs-client.ts │ │ ├── src │ │ │ └── clients │ │ │ └── base │ │ │ └── http-client.js │ │ └── webdav.js │ ├── base-handler.test.ts │ ├── base-http-client.test.ts │ ├── best-practices-handler.test.ts │ ├── cache.test.ts │ ├── cartridge-handler.test.ts │ ├── class-content-parser.test.ts │ ├── class-name-resolver.test.ts │ ├── client-factory.test.ts │ ├── code-version-handler.test.ts │ ├── code-versions-client.test.ts │ ├── config.test.ts │ ├── configuration-factory.test.ts │ ├── docs-handler.test.ts │ ├── documentation-scanner.test.ts │ ├── file-system-service.test.ts │ ├── job-log-handler.test.ts │ ├── job-log-utils.test.ts │ ├── log-client.test.ts │ ├── log-handler.test.ts │ ├── log-processor.test.ts │ ├── logger.test.ts │ ├── mcp │ │ ├── AGENTS.md │ │ ├── node │ │ │ ├── activate-code-version-advanced.full-mode.programmatic.test.js │ │ │ ├── code-versions.full-mode.programmatic.test.js │ │ │ ├── generate-cartridge-structure.docs-only.programmatic.test.js │ │ │ ├── get-available-best-practice-guides.docs-only.programmatic.test.js │ │ │ ├── get-available-sfra-documents.programmatic.test.js │ │ │ ├── get-best-practice-guide.docs-only.programmatic.test.js │ │ │ ├── get-hook-reference.docs-only.programmatic.test.js │ │ │ ├── get-job-execution-summary.full-mode.programmatic.test.js │ │ │ ├── get-job-log-entries.full-mode.programmatic.test.js │ │ │ ├── get-latest-debug.full-mode.programmatic.test.js │ │ │ ├── get-latest-error.full-mode.programmatic.test.js │ │ │ ├── get-latest-info.full-mode.programmatic.test.js │ │ │ ├── get-latest-job-log-files.full-mode.programmatic.test.js │ │ │ ├── get-latest-warn.full-mode.programmatic.test.js │ │ │ ├── get-log-file-contents.full-mode.programmatic.test.js │ │ │ ├── get-sfcc-class-documentation.docs-only.programmatic.test.js │ │ │ ├── get-sfcc-class-info.docs-only.programmatic.test.js │ │ │ ├── get-sfra-categories.docs-only.programmatic.test.js │ │ │ ├── get-sfra-document.programmatic.test.js │ │ │ ├── get-sfra-documents-by-category.docs-only.programmatic.test.js │ │ │ ├── get-system-object-definition.full-mode.programmatic.test.js │ │ │ ├── get-system-object-definitions.docs-only.programmatic.test.js │ │ │ ├── get-system-object-definitions.full-mode.programmatic.test.js │ │ │ ├── list-log-files.full-mode.programmatic.test.js │ │ │ ├── list-sfcc-classes.docs-only.programmatic.test.js │ │ │ ├── search-best-practices.docs-only.programmatic.test.js │ │ │ ├── search-custom-object-attribute-definitions.full-mode.programmatic.test.js │ │ │ ├── search-job-logs-by-name.full-mode.programmatic.test.js │ │ │ ├── search-job-logs.full-mode.programmatic.test.js │ │ │ ├── search-logs.full-mode.programmatic.test.js │ │ │ ├── search-sfcc-classes.docs-only.programmatic.test.js │ │ │ ├── search-sfcc-methods.docs-only.programmatic.test.js │ │ │ ├── search-sfra-documentation.docs-only.programmatic.test.js │ │ │ ├── search-site-preferences.full-mode.programmatic.test.js │ │ │ ├── search-system-object-attribute-definitions.full-mode.programmatic.test.js │ │ │ ├── search-system-object-attribute-groups.full-mode.programmatic.test.js │ │ │ ├── summarize-logs.full-mode.programmatic.test.js │ │ │ ├── tools.docs-only.programmatic.test.js │ │ │ └── tools.full-mode.programmatic.test.js │ │ ├── README.md │ │ ├── test-fixtures │ │ │ └── dw.json │ │ └── yaml │ │ ├── activate-code-version.docs-only.test.mcp.yml │ │ ├── activate-code-version.full-mode.test.mcp.yml │ │ ├── get_latest_error.test.mcp.yml │ │ ├── get-available-best-practice-guides.docs-only.test.mcp.yml │ │ ├── get-available-best-practice-guides.full-mode.test.mcp.yml │ │ ├── get-available-sfra-documents.docs-only.test.mcp.yml │ │ ├── get-available-sfra-documents.full-mode.test.mcp.yml │ │ ├── get-best-practice-guide.docs-only.test.mcp.yml │ │ ├── get-best-practice-guide.full-mode.test.mcp.yml │ │ ├── get-code-versions.docs-only.test.mcp.yml │ │ ├── get-code-versions.full-mode.test.mcp.yml │ │ ├── get-hook-reference.docs-only.test.mcp.yml │ │ ├── get-hook-reference.full-mode.test.mcp.yml │ │ ├── get-job-execution-summary.full-mode.test.mcp.yml │ │ ├── get-job-log-entries.full-mode.test.mcp.yml │ │ ├── get-latest-debug.full-mode.test.mcp.yml │ │ ├── get-latest-error.full-mode.test.mcp.yml │ │ ├── get-latest-info.full-mode.test.mcp.yml │ │ ├── get-latest-job-log-files.full-mode.test.mcp.yml │ │ ├── get-latest-warn.full-mode.test.mcp.yml │ │ ├── get-log-file-contents.full-mode.test.mcp.yml │ │ ├── get-sfcc-class-documentation.docs-only.test.mcp.yml │ │ ├── get-sfcc-class-documentation.full-mode.test.mcp.yml │ │ ├── get-sfcc-class-info.docs-only.test.mcp.yml │ │ ├── get-sfcc-class-info.full-mode.test.mcp.yml │ │ ├── get-sfra-categories.docs-only.test.mcp.yml │ │ ├── get-sfra-categories.full-mode.test.mcp.yml │ │ ├── get-sfra-document.docs-only.test.mcp.yml │ │ ├── get-sfra-document.full-mode.test.mcp.yml │ │ ├── get-sfra-documents-by-category.docs-only.test.mcp.yml │ │ ├── get-sfra-documents-by-category.full-mode.test.mcp.yml │ │ ├── get-system-object-definition.docs-only.test.mcp.yml │ │ ├── get-system-object-definition.full-mode.test.mcp.yml │ │ ├── get-system-object-definitions.docs-only.test.mcp.yml │ │ ├── get-system-object-definitions.full-mode.test.mcp.yml │ │ ├── list-log-files.full-mode.test.mcp.yml │ │ ├── list-sfcc-classes.docs-only.test.mcp.yml │ │ ├── list-sfcc-classes.full-mode.test.mcp.yml │ │ ├── search-best-practices.docs-only.test.mcp.yml │ │ ├── search-best-practices.full-mode.test.mcp.yml │ │ ├── search-custom-object-attribute-definitions.docs-only.test.mcp.yml │ │ ├── search-custom-object-attribute-definitions.test.mcp.yml │ │ ├── search-job-logs-by-name.full-mode.test.mcp.yml │ │ ├── search-job-logs.full-mode.test.mcp.yml │ │ ├── search-logs.full-mode.test.mcp.yml │ │ ├── search-sfcc-classes.docs-only.test.mcp.yml │ │ ├── search-sfcc-classes.full-mode.test.mcp.yml │ │ ├── search-sfcc-methods.docs-only.test.mcp.yml │ │ ├── search-sfcc-methods.full-mode.test.mcp.yml │ │ ├── search-sfra-documentation.docs-only.test.mcp.yml │ │ ├── search-sfra-documentation.full-mode.test.mcp.yml │ │ ├── search-site-preferences.docs-only.test.mcp.yml │ │ ├── search-site-preferences.full-mode.test.mcp.yml │ │ ├── search-system-object-attribute-definitions.docs-only.test.mcp.yml │ │ ├── search-system-object-attribute-definitions.full-mode.test.mcp.yml │ │ ├── search-system-object-attribute-groups.docs-only.test.mcp.yml │ │ ├── search-system-object-attribute-groups.full-mode.test.mcp.yml │ │ ├── summarize-logs.full-mode.test.mcp.yml │ │ ├── tools.docs-only.test.mcp.yml │ │ └── tools.full-mode.test.mcp.yml │ ├── oauth-token.test.ts │ ├── ocapi-auth-client.test.ts │ ├── ocapi-client.test.ts │ ├── path-service.test.ts │ ├── query-builder.test.ts │ ├── referenced-types-extractor.test.ts │ ├── servers │ │ ├── sfcc-mock-server │ │ │ ├── mock-data │ │ │ │ └── ocapi │ │ │ │ ├── code-versions.json │ │ │ │ ├── custom-object-attributes-customapi.json │ │ │ │ ├── custom-object-attributes-globalsettings.json │ │ │ │ ├── custom-object-attributes-versionhistory.json │ │ │ │ ├── site-preferences-ccv.json │ │ │ │ ├── site-preferences-fastforward.json │ │ │ │ ├── site-preferences-sfra.json │ │ │ │ ├── site-preferences-storefront.json │ │ │ │ ├── site-preferences-system.json │ │ │ │ ├── system-object-attribute-groups-campaign.json │ │ │ │ ├── system-object-attribute-groups-category.json │ │ │ │ ├── system-object-attribute-groups-order.json │ │ │ │ ├── system-object-attribute-groups-product.json │ │ │ │ ├── system-object-attribute-groups-sitepreferences.json │ │ │ │ ├── system-object-attributes-customeraddress.json │ │ │ │ ├── system-object-attributes-product-expanded.json │ │ │ │ ├── system-object-attributes-product.json │ │ │ │ ├── system-object-definition-category.json │ │ │ │ ├── system-object-definition-customer.json │ │ │ │ ├── system-object-definition-customeraddress.json │ │ │ │ ├── system-object-definition-order.json │ │ │ │ ├── system-object-definition-product.json │ │ │ │ ├── system-object-definitions-old.json │ │ │ │ └── system-object-definitions.json │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── README.md │ │ │ ├── scripts │ │ │ │ └── setup-logs.js │ │ │ ├── server.js │ │ │ └── src │ │ │ ├── app.js │ │ │ ├── config │ │ │ │ └── server-config.js │ │ │ ├── middleware │ │ │ │ ├── auth.js │ │ │ │ ├── cors.js │ │ │ │ └── logging.js │ │ │ ├── routes │ │ │ │ ├── ocapi │ │ │ │ │ ├── code-versions-handler.js │ │ │ │ │ ├── oauth-handler.js │ │ │ │ │ ├── ocapi-error-utils.js │ │ │ │ │ ├── ocapi-utils.js │ │ │ │ │ ├── site-preferences-handler.js │ │ │ │ │ └── system-objects-handler.js │ │ │ │ ├── ocapi.js │ │ │ │ └── webdav.js │ │ │ └── utils │ │ │ ├── mock-data-loader.js │ │ │ └── webdav-xml.js │ │ └── sfcc-mock-server-manager.ts │ ├── sfcc-mock-server.test.ts │ ├── site-preferences-client.test.ts │ ├── system-objects-client.test.ts │ ├── utils.test.ts │ ├── validation-helpers.test.ts │ └── validator.test.ts ├── tsconfig.json └── tsconfig.test.json ``` # Files -------------------------------------------------------------------------------- /docs-site/components/ToolCard.tsx: -------------------------------------------------------------------------------- ```typescript import React from 'react'; import { ToolMeta } from '../utils/toolsData'; import { InlineCode } from './CodeBlock'; interface ToolCardProps { tool: ToolMeta; } const ModeBadge: React.FC<{ mode: ToolMeta['mode'] }> = ({ mode }) => { if (mode === 'both') return <span className="text-[10px] font-semibold bg-gradient-to-r from-blue-600 to-purple-600 text-white px-2 py-0.5 rounded-full tracking-wide">Docs + Full</span>; if (mode === 'docs') return <span className="text-[10px] font-semibold bg-green-100 text-green-700 px-2 py-0.5 rounded-full tracking-wide">Docs</span>; return <span className="text-[10px] font-semibold bg-blue-100 text-blue-700 px-2 py-0.5 rounded-full tracking-wide">Full</span>; }; const ToolCard: React.FC<ToolCardProps> = ({ tool }) => { const [open, setOpen] = React.useState(false); return ( <div id={tool.id} className="group rounded-xl border border-gray-200 bg-white/90 backdrop-blur-sm p-4 shadow-sm hover:shadow transition relative"> <div className="flex items-start justify-between gap-4"> <div className="flex-1 min-w-0"> <div className="flex items-center gap-2 mb-2 flex-wrap"> <ModeBadge mode={tool.mode} /> {tool.popular && <span className="text-[10px] bg-yellow-100 text-yellow-700 px-1.5 py-0.5 rounded">Popular</span>} {tool.tags?.slice(0,3).map(tag => ( <span key={tag} className="text-[10px] bg-gray-100 text-gray-600 px-1.5 py-0.5 rounded">{tag}</span> ))} </div> <h4 className="font-mono text-sm font-semibold text-gray-900 break-all mb-1">{tool.name}</h4> <p className="text-xs text-gray-600 leading-relaxed line-clamp-2 group-hover:line-clamp-none transition-all">{tool.description}</p> </div> <button aria-label="Toggle details" onClick={() => setOpen(o=>!o)} className="shrink-0 rounded-lg border border-gray-200 p-2 hover:bg-gray-50 text-gray-500 hover:text-gray-700 transition" aria-expanded={open}> <svg className={`w-4 h-4 transform transition ${open ? 'rotate-180' : ''}`} fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" d="M19 9l-7 7-7-7" /></svg> </button> </div> {open && ( <div className="mt-4 space-y-3 animate-fade-in"> {tool.params && tool.params.length > 0 && ( <div> <p className="text-[11px] font-semibold text-gray-700 mb-1">Parameters</p> <div className="border border-gray-200 rounded-lg overflow-hidden bg-white/60"> <div className="divide-y divide-gray-200"> {tool.params.map(p => ( <div key={p.name} className="p-2 hover:bg-gray-50 transition flex gap-4 items-start"> {/* Name column */} <div className="flex-shrink-0 min-w-[100px]"> <InlineCode> <span className="text-[10px] font-medium">{p.name}</span> </InlineCode> </div> {/* Optional badge column (fixed width) */} <div className="w-[50px] flex justify-start"> {p.required === false ? ( <span className="text-[10px] leading-none px-1 py-0.5 rounded bg-gray-100 text-gray-500 border border-gray-200 whitespace-nowrap">optional</span> ) : ( <span className="text-[10px] text-transparent select-none">req</span> )} </div> {/* Description column */} <div className="text-[11px] text-gray-600 leading-relaxed flex-1 min-w-0">{p.description}</div> </div> ))} </div> </div> </div> )} {tool.examples && tool.examples.length > 0 && ( <div> <p className="text-[11px] font-semibold text-gray-700 mb-1">Example Prompts</p> <ul className="list-disc pl-5 space-y-0.5 text-[11px] text-gray-600"> {tool.examples.map(ex => ( <li key={ex} className="flex items-start gap-2"><span className="flex-1">{ex}</span> <button onClick={() => navigator.clipboard.writeText(ex)} className="ml-2 text-[10px] bg-gray-100 hover:bg-gray-200 text-gray-700 px-2 py-0.5 rounded transition">Copy</button> </li> ))} </ul> </div> )} </div> )} </div> ); }; export default ToolCard; ``` -------------------------------------------------------------------------------- /docs/dw_crypto/WeakMessageDigest.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.crypto # Class WeakMessageDigest ## Inheritance Hierarchy - Object - dw.crypto.WeakMessageDigest ## Description This API provides access to Deprecated algorithms. See MessageDigest for full documentation. WeakMessageDigest is simply a drop-in replacement that only supports deprecated algorithms. This is helpful when you need to deal with weak algorithms for backward compatibility purposes, but MessageDigest should always be used for new development and for anything intended to be secure. Note: this class handles sensitive security-related data. Pay special attention to PCI DSS v3. requirements 2, 4, and 12. ## Constants ### DIGEST_MD2 **Type:** String = "MD2" Constant representing the MD2 algorithm. This algorithm is obsolete. Do not use it for any sensitive data ### DIGEST_MD5 **Type:** String = "MD5" Constant representing the MD5 algorithm. This algorithm is obsolete. Do not use it for any sensitive data ### DIGEST_SHA **Type:** String = "SHA" Constant representing the SHA algorithm. This algorithm is obsolete. Do not use it for any sensitive data ### DIGEST_SHA_1 **Type:** String = "SHA-1" Constant representing the SHA 1 algorithm. This algorithm is obsolete. Do not use it for any sensitive data ## Properties ## Constructor Summary WeakMessageDigest(algorithm : String) Construct a MessageDigest with the specified algorithm name. ## Method Summary ### digest **Signature:** `digest(input : String) : String` Digests the passed string and returns a computed hash value as a string. ### digest **Signature:** `digest(algorithm : String, input : Bytes) : Bytes` Computes the hash value for the passed array of bytes. ### digest **Signature:** `digest() : Bytes` Completes the hash computation by performing final operations such as padding. ### digestBytes **Signature:** `digestBytes(input : Bytes) : Bytes` Computes the hash value for the passed Bytes. ### updateBytes **Signature:** `updateBytes(input : Bytes) : void` Updates the digest using the passed Bytes. ## Constructor Detail ## Method Detail ## Method Details ### digest **Signature:** `digest(input : String) : String` **Description:** Digests the passed string and returns a computed hash value as a string. The passed String is first encoded into a sequence of bytes using the platform's default encoding. The digest then performs any prerequisite padding, before computing the hash value. The hash is then converted into a string by converting all digits to hexadecimal. **Deprecated:** Deprecated because the conversion of the input to bytes using the default platform encoding and the hex-encoded return value are not generally appropriate. **Parameters:** - `input`: The value to hash as String, must not be null. **Returns:** The resulting hash value as hex-encoded string. --- ### digest **Signature:** `digest(algorithm : String, input : Bytes) : Bytes` **Description:** Computes the hash value for the passed array of bytes. The algorithm argument is optional. If null, then the algorithm established at construction time is used. The binary representation of the message is typically derived from a string and the resulting hash is typically converted with base64 back into a string. Example: Encoding.toBase64( digest( "MD5", new Bytes( "my password", "UTF-8" ) ) ); **Deprecated:** Deprecated because the digest algorithm should be the one set in the constructor. **Parameters:** - `algorithm`: The standard name of the digest algorithm, or null if the algorithm passed at construction time is to be used. The algorithm must be a supported algorithm. - `input`: The value to hash, must not be null. **Returns:** The resulting hash value. --- ### digest **Signature:** `digest() : Bytes` **Description:** Completes the hash computation by performing final operations such as padding. The binary representation of the message is typically derived from a string and the resulting hash is typically converted with base64 back into a string. Example: Encoding.toBase64( digest() ); **Returns:** The resulting hash value. --- ### digestBytes **Signature:** `digestBytes(input : Bytes) : Bytes` **Description:** Computes the hash value for the passed Bytes. The binary representation of the message is typically derived from a string and the resulting hash is typically converted with base64 back into a string. Example: Encoding.toBase64( digest( new Bytes( "my password", "UTF-8" ) ) ); **Parameters:** - `input`: The value to hash, must not be null. **Returns:** The resulting hash value. --- ### updateBytes **Signature:** `updateBytes(input : Bytes) : void` **Description:** Updates the digest using the passed Bytes. **Parameters:** - `input`: The value to hash, must not be null. --- ``` -------------------------------------------------------------------------------- /docs/sfra/product-line-items.md: -------------------------------------------------------------------------------- ```markdown # SFRA Product Line Items Model ## Overview The Product Line Items model represents a collection of product line items in a basket or order. It provides comprehensive information about each product in the cart including quantities, options, bonus products, and pricing details. ## Constructor ```javascript function ProductLineItems(productLineItems, view) ``` Creates a Product Line Items model with formatted line item information. ### Parameters - `productLineItems` (dw.util.Collection<dw.order.ProductLineItem>) - Collection of product line items from basket or order - `view` (string) - View context ('basket' or 'order') ## Properties ### items **Type:** Array<Object> Array of formatted product line items. Each item contains: #### Standard Product Items - `id` (string) - Product ID - `productName` (string) - Product display name - `quantity` (number) - Item quantity - `UUID` (string) - Line item UUID - `product` (Object) - Full product model with pricing, images, attributes - `options` (Array) - Product options if applicable - `bonusProducts` (Array) - Associated bonus products if applicable #### Items Without Product (Unassigned Categories) - `id` (string) - Product ID - `productName` (string) - Product name - `quantity` (number) - Item quantity - `UUID` (string) - Line item UUID - `noProduct` (boolean) - Flag indicating missing product (true) - `images` (Object) - Default "no image" placeholder ### totalQuantity **Type:** number Total quantity of all items in the collection. ## Helper Functions ### createProductLineItemsObject(allLineItems, view) Creates an array of formatted product line items with comprehensive product information. **Parameters:** - `allLineItems` (dw.util.Collection<dw.order.ProductLineItem>) - All product line items - `view` (string) - View context ('basket' or 'order') **Returns:** Array<Object> - Formatted line items array ## Product Line Item Structure Each product line item in the items array contains: ### Product Information - Complete product model created via ProductFactory - Includes pricing, images, availability, and attributes - Product options mapped with option IDs and selected values ### Bonus Products - Automatically detected and included for qualifying items - Each bonus product includes full product information - Linked via custom attributes (bonusProductLineItemUUID, preOrderUUID) ### Quantity and Identification - Line item quantity and UUID for cart operations - Product ID for catalog operations - Product name for display purposes ## Usage Example ```javascript var ProductLineItems = require('*/cartridge/models/productLineItems'); var BasketMgr = require('dw/order/BasketMgr'); var currentBasket = BasketMgr.getCurrentBasket(); var lineItemsModel = new ProductLineItems( currentBasket.productLineItems, 'basket' ); // Access line items console.log('Total items: ' + lineItemsModel.totalQuantity); lineItemsModel.items.forEach(function(item) { if (item.noProduct) { console.log('Missing product: ' + item.productName); } else { console.log(item.product.productName + ' x ' + item.quantity); // Check for options if (item.options && item.options.length > 0) { console.log('Options: ', item.options); } // Check for bonus products if (item.bonusProducts && item.bonusProducts.length > 0) { console.log('Bonus products: ' + item.bonusProducts.length); } } }); ``` ## Special Handling ### Missing Products When a product is no longer available or unassigned: - `noProduct` flag is set to true - Limited product information is available - Default "no image" placeholder is used - Product name and basic details are preserved ### Bonus Products - Automatically detected based on custom attributes - Each bonus product gets full ProductFactory treatment - Maintains relationship to parent product line item - Includes all product options and configurations ### Product Options - Maps option product line items to option configurations - Includes option ID and selected value ID for each option - Used for product configuration and pricing ## Notes - Handles both basket and order contexts - Gracefully handles missing or invalid products - Includes comprehensive product information via ProductFactory - Supports complex product relationships (bundles, sets, bonuses) - Maintains line item UUIDs for cart operations - Provides fallback handling for catalog issues ## Related Models - **Cart Model** - Uses product line items for cart display - **Order Model** - Uses product line items for order information - **Product Models** - Created via ProductFactory for each line item - **Totals Model** - Calculates totals based on line items ``` -------------------------------------------------------------------------------- /tests/servers/sfcc-mock-server/mock-data/ocapi/system-object-attributes-customeraddress.json: -------------------------------------------------------------------------------- ```json { "_v": "23.2", "_type": "object_attribute_definition_search_result", "count": 15, "hits": [ { "_type": "object_attribute_definition", "_resource_state": "3270518feb2ba23c77355a1690a5a9916acb509aa181e533b529de4abe2969f8", "id": "ID", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/ID" }, { "_type": "object_attribute_definition", "_resource_state": "3459bc3f84b37b9391714b05bbd8dedad7cac8edd3c243de0f0092549144240d", "id": "UUID", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/UUID" }, { "_type": "object_attribute_definition", "_resource_state": "45f36d21db7d180fb27087e13eec59e80562f51472378c4293284da7550787ee", "id": "address1", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/address1" }, { "_type": "object_attribute_definition", "_resource_state": "29d08491c3d2e65146b65fcfe44a64bf8ae7b538543d11d5bf6924c28965d9a0", "id": "address2", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/address2" }, { "_type": "object_attribute_definition", "_resource_state": "2cce8462628d664cf70c247d7d1cddd1f7dce24cd0e294db28162cdb62d8c291", "id": "city", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/city" }, { "_type": "object_attribute_definition", "_resource_state": "b15c7929905e11c4e1bf96a1de9c24f97645d5653c0a78efe916a3e1876be2ad", "id": "companyName", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/companyName" }, { "_type": "object_attribute_definition", "_resource_state": "c0eb64a92268d13fa32777eaec7f824dc5db27088a2d133442bd081e11480b0b", "id": "countryCode", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/countryCode" }, { "_type": "object_attribute_definition", "_resource_state": "f85a590a52c5d04bc7b61a4fc841d059e01e6dd2325761cf6d368a35b4b9b36b", "id": "creationDate", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/creationDate" }, { "_type": "object_attribute_definition", "_resource_state": "5aa6c1f0af128dde7fa233ffa45187322f56d095a81a3348edcc8b0a21a0109a", "id": "firstName", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/firstName" }, { "_type": "object_attribute_definition", "_resource_state": "fe691db5c3021705fcf0b30de48afa4eeb8172bd80846f830bb77eae9a0469bd", "id": "jobTitle", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/jobTitle" }, { "_type": "object_attribute_definition", "_resource_state": "c404f51befa8a2a01b9775107d28b8067cebb1218bcaa135b616e8257a041e9e", "id": "lastModified", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/lastModified" }, { "_type": "object_attribute_definition", "_resource_state": "84205a32eaaed93d867d8425d65347144f7ae376af1a45802602640e7c99e9c6", "id": "lastName", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/lastName" }, { "_type": "object_attribute_definition", "_resource_state": "be89fc4879cca7a9fa426cac2e82a2d8829a11e0b4a59028482cb98cdf2d4567", "id": "phone", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/phone" }, { "_type": "object_attribute_definition", "_resource_state": "4c78d7cb9d9e36a4cb69794ec547c3df032f12ff757ec716683913c6fe69feea", "id": "phone_country", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/phone_country" }, { "_type": "object_attribute_definition", "_resource_state": "e61daf9d3e2beae465b19f3d6d46bd184bbc6d56b94bf5866b17311b06e6d51b", "id": "postBox", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/CustomerAddress/attribute_definitions/postBox" } ], "next": { "_type": "result_page", "count": 15, "start": 15 }, "query": { "match_all_query": { "_type": "match_all_query" } }, "start": 0, "total": 23 } ``` -------------------------------------------------------------------------------- /docs/dw_svc/ServiceDefinition.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.svc # Class ServiceDefinition ## Inheritance Hierarchy - Object - dw.svc.ServiceDefinition ## Description Base class of Service Definitions. A service definition represents configuration that is shared across all Service instances. ## Properties ### configuration **Type:** ServiceConfig (Read Only) The Service Configuration stored in the database. ### mock **Type:** boolean The status of whether mock mode is enabled for all instances of this definition. ### serviceName **Type:** String (Read Only) The name of this service. ### throwOnError **Type:** boolean The status of whether the shared throwOnError flag is set. ## Constructor Summary ## Method Summary ### configure **Signature:** `configure(config : Object) : ServiceDefinition` Register a callback to handle custom portions of the service. ### getConfiguration **Signature:** `getConfiguration() : ServiceConfig` Returns the Service Configuration stored in the database. ### getServiceName **Signature:** `getServiceName() : String` Returns the name of this service. ### isMock **Signature:** `isMock() : boolean` Returns the status of whether mock mode is enabled for all instances of this definition. ### isThrowOnError **Signature:** `isThrowOnError() : boolean` Returns the status of whether the shared throwOnError flag is set. ### setMock **Signature:** `setMock() : ServiceDefinition` Sets the mock mode for all Service instances that use this definition. ### setThrowOnError **Signature:** `setThrowOnError() : ServiceDefinition` Sets the throwOnError flag to true for all Service instances that use this definition. ## Method Detail ## Method Details ### configure **Signature:** `configure(config : Object) : ServiceDefinition` **Description:** Register a callback to handle custom portions of the service. This callback may declare multiple methods: { initServiceClient: function() { // Create and return the internal service client object. // This is usually optional, except in the case of SOAP services. }, // svc is the call-specific Service instance. For example, it may be an HTTPService or FTPService. // params are the arguments passed to the call method (if any). createRequest: function(svc:Service, params) { // Perform any required call-time configuration. // Optionally return a Service-specific object }, // svc is the call-specific Service instance. // arg is the output of createRequest. execute: function(svc:Service, arg:Object) { // Execute the service call and return a result // This method is not used by default for HTTP-related services unless executeOverride is set. }, // Use the execute function if it is present. This is only required to use the functionality with HTTP services. executeOverride: true, // svc is the call-specific Service instance. // response is the output of execute. parseResponse: function(svc:Service, response: Object) { // Process the response object as needed. // The return value of this method will be the return value of the outer call method. }, // svc is the call-specific Service instance. // arg is the output of createRequest. mockCall: function(svc:Service, arg:Object) { // This method takes the place of the 'execute' phase when mocking is enabled. // Note initServiceClient, createRequest, and parseResponse still invoked. }, // svc is the call-specific Service instance. // params are the arguments passed to the call method (if any). mockFull: function(svc:Service, params) { // This method takes the place of the entire service call when mocking is enabled. // No other callbacks are invoked. The output of this method becomes the output of call. } } **Parameters:** - `config`: Callback object. **Returns:** this --- ### getConfiguration **Signature:** `getConfiguration() : ServiceConfig` **Description:** Returns the Service Configuration stored in the database. **Returns:** Service Configuration. --- ### getServiceName **Signature:** `getServiceName() : String` **Description:** Returns the name of this service. **Returns:** Service name. --- ### isMock **Signature:** `isMock() : boolean` **Description:** Returns the status of whether mock mode is enabled for all instances of this definition. **Returns:** true for mock mode, false otherwise. --- ### isThrowOnError **Signature:** `isThrowOnError() : boolean` **Description:** Returns the status of whether the shared throwOnError flag is set. **Returns:** throwOnError flag. --- ### setMock **Signature:** `setMock() : ServiceDefinition` **Description:** Sets the mock mode for all Service instances that use this definition. **Returns:** this Service Definition. --- ### setThrowOnError **Signature:** `setThrowOnError() : ServiceDefinition` **Description:** Sets the throwOnError flag to true for all Service instances that use this definition. **Returns:** this Service Definition. --- ``` -------------------------------------------------------------------------------- /docs-site/components/ConfigBuilder.tsx: -------------------------------------------------------------------------------- ```typescript import React from 'react'; import CodeBlock from './CodeBlock'; interface FieldState { hostname: string; username: string; password: string; clientId: string; clientSecret: string; codeVersion: string; siteId: string; minimal: boolean; } const initial: FieldState = { hostname: 'dev01-sandbox.us01.dx.commercecloud.salesforce.com', username: 'your-username', password: 'your-password', clientId: '', clientSecret: '', codeVersion: 'version1', siteId: 'RefArch', minimal: true }; const labelCls = 'block text-xs font-semibold uppercase tracking-wide text-gray-600 mb-1'; const inputCls = 'w-full rounded-lg border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 px-3 py-2 text-sm bg-white'; const pillBase = 'px-3 py-1.5 rounded-full text-xs font-medium transition border flex items-center gap-1'; export const ConfigBuilder: React.FC = () => { const [state, setState] = React.useState<FieldState>(initial); const toggleMinimal = () => setState(s => ({ ...s, minimal: !s.minimal })); const json = React.useMemo(() => { const base: Record<string, string> = { hostname: state.hostname, username: state.username, password: state.password }; if (!state.minimal) { if (state.clientId) base['client-id'] = state.clientId; if (state.clientSecret) base['client-secret'] = state.clientSecret; if (state.codeVersion) base['code-version'] = state.codeVersion; if (state.siteId) base['site-id'] = state.siteId; } return JSON.stringify(base, null, 2); }, [state]); const update = (k: keyof FieldState) => (e: React.ChangeEvent<HTMLInputElement>) => setState(s => ({ ...s, [k]: e.target.value })); return ( <div className="space-y-6"> <div className="flex flex-wrap gap-3 items-center"> <button onClick={toggleMinimal} className={`${pillBase} ${state.minimal ? 'bg-blue-600 text-white border-blue-600 shadow' : 'bg-white text-gray-700 border-gray-200 hover:border-blue-400'}`} aria-pressed={state.minimal}> {state.minimal ? 'Minimal Config' : 'Show Minimal'} </button> <button onClick={toggleMinimal} className={`${pillBase} ${!state.minimal ? 'bg-purple-600 text-white border-purple-600 shadow' : 'bg-white text-gray-700 border-gray-200 hover:border-purple-400'}`} aria-pressed={!state.minimal}> {!state.minimal ? 'Advanced Config' : 'Show Advanced'} </button> <span className="text-xs text-gray-500">Toggle to include OAuth + code/site fields</span> </div> <div className="grid md:grid-cols-2 gap-6"> <div className="space-y-4"> <div> <label className={labelCls}>Hostname *</label> <input value={state.hostname} onChange={update('hostname')} className={inputCls} /> </div> <div className="grid grid-cols-2 gap-4"> <div> <label className={labelCls}>Username *</label> <input value={state.username} onChange={update('username')} className={inputCls} /> </div> <div> <label className={labelCls}>Password *</label> <input type="password" value={state.password} onChange={update('password')} className={inputCls} /> </div> </div> {!state.minimal && ( <> <div className="grid grid-cols-2 gap-4"> <div> <label className={labelCls}>Client ID</label> <input value={state.clientId} onChange={update('clientId')} className={inputCls} /> </div> <div> <label className={labelCls}>Client Secret</label> <input type="password" value={state.clientSecret} onChange={update('clientSecret')} className={inputCls} /> </div> </div> <div className="grid grid-cols-2 gap-4"> <div> <label className={labelCls}>Code Version</label> <input value={state.codeVersion} onChange={update('codeVersion')} className={inputCls} /> </div> <div> <label className={labelCls}>Site ID</label> <input value={state.siteId} onChange={update('siteId')} className={inputCls} /> </div> </div> </> )} <p className="text-[11px] text-gray-500">* Required for WebDAV + log tools. Client credentials unlock Data API features.</p> </div> <div> <CodeBlock language="json" code={json} /> <p className="text-xs text-gray-500 -mt-4">Copy & save as <code className="font-mono">dw.json</code> then run with <code className="font-mono">--dw-json ./dw.json</code></p> </div> </div> </div> ); }; export default ConfigBuilder; ``` -------------------------------------------------------------------------------- /docs/dw_catalog/SearchRefinementValue.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.catalog # Class SearchRefinementValue ## Inheritance Hierarchy - Object - dw.catalog.SearchRefinementValue ## Description Represents the value of a product or content search refinement. ## Properties ### description **Type:** String (Read Only) The optional refinement value description in the current locale. ### displayValue **Type:** String (Read Only) The refinement display value. For attribute refinements, this is the appropriate display value based on optional value display names within the object attribute definition. If no display name is defined, the value itself is returned. For category refinements, this is the display name of the category in the current locale. For price refinements, this is a string representation of the range appropriate for display. ### hitCount **Type:** Number (Read Only) The hit count value. ### ID **Type:** String (Read Only) The refinement value's ID. For attribute refinements, this will be the ID of the corresponding ObjectAttributeDefinition. This ID is included in the querystring parameter names returned by the URL-generating methods of SearchModel. For price and category refinements, this value will be empty. ### presentationID **Type:** String (Read Only) The optional presentation ID associated with this refinement value. The presentation ID can be used, for example, to associate an ID with an HTML widget. ### value **Type:** String (Read Only) The refinement value. For attribute refinements, this is the attribute value if the refinement values are unbucketed, or the bucket display name if the values are bucketed. This value is included in the querystring parameter values returned by the URL-generating methods of SearchModel. For price refinements, the value will be a string representation of the price range lower bound. For category refinements, the value will be a category ID. ## Constructor Summary ## Method Summary ### getDescription **Signature:** `getDescription() : String` Returns the optional refinement value description in the current locale. ### getDisplayValue **Signature:** `getDisplayValue() : String` Returns the refinement display value. ### getHitCount **Signature:** `getHitCount() : Number` Returns the hit count value. ### getID **Signature:** `getID() : String` Returns the refinement value's ID. ### getPresentationID **Signature:** `getPresentationID() : String` Returns the optional presentation ID associated with this refinement value. ### getValue **Signature:** `getValue() : String` Returns the refinement value. ## Method Detail ## Method Details ### getDescription **Signature:** `getDescription() : String` **Description:** Returns the optional refinement value description in the current locale. **Returns:** the optional refinement value description in the current locale, or null if none is defined. --- ### getDisplayValue **Signature:** `getDisplayValue() : String` **Description:** Returns the refinement display value. For attribute refinements, this is the appropriate display value based on optional value display names within the object attribute definition. If no display name is defined, the value itself is returned. For category refinements, this is the display name of the category in the current locale. For price refinements, this is a string representation of the range appropriate for display. **Returns:** the refinement display value in the current locale. --- ### getHitCount **Signature:** `getHitCount() : Number` **Description:** Returns the hit count value. **Returns:** the hit count value. --- ### getID **Signature:** `getID() : String` **Description:** Returns the refinement value's ID. For attribute refinements, this will be the ID of the corresponding ObjectAttributeDefinition. This ID is included in the querystring parameter names returned by the URL-generating methods of SearchModel. For price and category refinements, this value will be empty. **Returns:** the refinement value's ID. --- ### getPresentationID **Signature:** `getPresentationID() : String` **Description:** Returns the optional presentation ID associated with this refinement value. The presentation ID can be used, for example, to associate an ID with an HTML widget. **Returns:** the presentation ID, or null if none is defined. --- ### getValue **Signature:** `getValue() : String` **Description:** Returns the refinement value. For attribute refinements, this is the attribute value if the refinement values are unbucketed, or the bucket display name if the values are bucketed. This value is included in the querystring parameter values returned by the URL-generating methods of SearchModel. For price refinements, the value will be a string representation of the price range lower bound. For category refinements, the value will be a category ID. **Returns:** the refinement value. --- ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/summarize-logs.full-mode.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml --- description: "Test summarize_logs tool in full mode" tests: # Core functionality - comprehensive structure validation - it: "should retrieve comprehensive log summary with complete structure" request: jsonrpc: "2.0" id: "summarize-comprehensive" method: "tools/call" params: name: "summarize_logs" arguments: {} expect: response: jsonrpc: "2.0" id: "summarize-comprehensive" result: content: match:arrayElements: type: "text" text: "match:regex:Log Summary for \\d{8}:[\\s\\S]*📊 Counts:[\\s\\S]*- Errors: \\d+[\\s\\S]*- Warnings: \\d+[\\s\\S]*- Info: \\d+[\\s\\S]*- Debug: \\d+[\\s\\S]*📁 Log Files \\(\\d+\\):[\\s\\S]*🔥 Key Issues:" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "3000ms" # Basic successful response validation - it: "should return standard MCP response format" request: jsonrpc: "2.0" id: "summarize-format" method: "tools/call" params: name: "summarize_logs" arguments: {} expect: response: jsonrpc: "2.0" id: "summarize-format" result: content: "match:arrayLength:1" isError: false stderr: "toBeEmpty" # Date parameter tests - focused on key scenarios - it: "should handle specific valid date parameter" request: jsonrpc: "2.0" id: "summarize-specific-date" method: "tools/call" params: name: "summarize_logs" arguments: date: "20250921" expect: response: jsonrpc: "2.0" id: "summarize-specific-date" result: content: match:arrayElements: type: "text" text: "match:regex:Log Summary for 20250921:|No log files found for date 20250921" isError: false stderr: "toBeEmpty" - it: "should handle no available logs gracefully" request: jsonrpc: "2.0" id: "summarize-no-logs" method: "tools/call" params: name: "summarize_logs" arguments: date: "20220101" expect: response: jsonrpc: "2.0" id: "summarize-no-logs" result: content: match:arrayElements: type: "text" text: "match:contains:No log files found for date 20220101" isError: false stderr: "toBeEmpty" # Edge cases - simplified and consolidated - it: "should handle invalid date formats gracefully" request: jsonrpc: "2.0" id: "summarize-invalid-date" method: "tools/call" params: name: "summarize_logs" arguments: date: "invalid-date" expect: response: jsonrpc: "2.0" id: "summarize-invalid-date" result: content: match:arrayElements: type: "text" text: "match:contains:No log files found for date invalid-date" isError: false stderr: "toBeEmpty" # YAML-specific pattern tests - what YAML does better than Node.js - it: "should validate emoji patterns and structure markers" request: jsonrpc: "2.0" id: "summarize-patterns" method: "tools/call" params: name: "summarize_logs" arguments: {} expect: response: jsonrpc: "2.0" id: "summarize-patterns" result: content: match:arrayElements: type: "text" text: "match:regex:📊.*📁.*🔥" isError: false stderr: "toBeEmpty" # Performance test - single focused scenario - it: "should complete log summary analysis within reasonable time for health monitoring" request: jsonrpc: "2.0" id: "summarize-performance" method: "tools/call" params: name: "summarize_logs" arguments: {} expect: response: jsonrpc: "2.0" id: "summarize-performance" result: content: match:arrayElements: type: "text" text: "match:type:string" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2500ms" # Stricter for critical health monitoring # Date format validation - specific YAML strength - it: "should use consistent YYYYMMDD date format in responses" request: jsonrpc: "2.0" id: "summarize-date-format" method: "tools/call" params: name: "summarize_logs" arguments: {} expect: response: jsonrpc: "2.0" id: "summarize-date-format" result: content: match:arrayElements: type: "text" text: "match:regex:Log Summary for \\d{8}:|No log files found for date \\d{8}" isError: false stderr: "toBeEmpty" ``` -------------------------------------------------------------------------------- /docs/dw_suggest/Suggestions.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.suggest # Class Suggestions ## Inheritance Hierarchy - Object - dw.suggest.Suggestions ## Description This is the base class for suggestions containers. For each type of items, a sub class provides methods to access the actual items. See the sub classes for more specific information. ## Properties ### searchPhraseSuggestions **Type:** SearchPhraseSuggestions (Read Only) The suggested search phrases that are associated to this suggestions. In contrast to the suggested items, the suggested phrases contains the corrected and completed versions of the original search phrase. ### suggestedPhrases **Type:** Iterator (Read Only) A list of SuggestedPhrase objects that relates to the user input search phrase. ### suggestedTerms **Type:** Iterator (Read Only) A list of SuggestedTerms objects. Each of the returned instances represents a set of terms suggested for a particular single term of the user input search phrase. ## Constructor Summary ## Method Summary ### getSearchPhraseSuggestions **Signature:** `getSearchPhraseSuggestions() : SearchPhraseSuggestions` Returns the suggested search phrases that are associated to this suggestions. ### getSuggestedPhrases **Signature:** `getSuggestedPhrases() : Iterator` Returns a list of SuggestedPhrase objects that relates to the user input search phrase. ### getSuggestedTerms **Signature:** `getSuggestedTerms() : Iterator` Returns a list of SuggestedTerms objects. ### hasSuggestedPhrases **Signature:** `hasSuggestedPhrases() : boolean` Returns whether this suggestions container has any suggested phrases. ### hasSuggestedTerms **Signature:** `hasSuggestedTerms() : boolean` Returns whether this suggestions container has any suggested terms. ### hasSuggestions **Signature:** `hasSuggestions() : boolean` Returns whether this suggestions container has any suggested items, i.e. ## Method Detail ## Method Details ### getSearchPhraseSuggestions **Signature:** `getSearchPhraseSuggestions() : SearchPhraseSuggestions` **Description:** Returns the suggested search phrases that are associated to this suggestions. In contrast to the suggested items, the suggested phrases contains the corrected and completed versions of the original search phrase. **Returns:** the suggested search phrases for this suggestions --- ### getSuggestedPhrases **Signature:** `getSuggestedPhrases() : Iterator` **Description:** Returns a list of SuggestedPhrase objects that relates to the user input search phrase. **Deprecated:** Please use method getSearchPhraseSuggestions() to obtain the suggested search phrases. **Returns:** a list of SuggestedPhrases **See Also:** hasSuggestedPhrases() --- ### getSuggestedTerms **Signature:** `getSuggestedTerms() : Iterator` **Description:** Returns a list of SuggestedTerms objects. Each of the returned instances represents a set of terms suggested for a particular single term of the user input search phrase. **Deprecated:** Please use method getSearchPhraseSuggestions() to obtain the suggested search phrases. **Returns:** a list of SuggestedTerms for each term of the user input search phrase --- ### hasSuggestedPhrases **Signature:** `hasSuggestedPhrases() : boolean` **Description:** Returns whether this suggestions container has any suggested phrases. Note that this method only looks for suggested phrases. It does not account for suggested terms or suggested objects. In other words, even if there are suggested terms or objects, this method will return false if this suggestions container has no phrases. **Deprecated:** Please use method getSearchPhraseSuggestions() to obtain the suggested search phrases. **Returns:** true only if there are phrases available --- ### hasSuggestedTerms **Signature:** `hasSuggestedTerms() : boolean` **Description:** Returns whether this suggestions container has any suggested terms. Note that this method checks suggested terms only, but not suggested phrases or suggested objects. **Deprecated:** Please use method getSearchPhraseSuggestions() to obtain the suggested search phrases. **Returns:** true only if there are terms available --- ### hasSuggestions **Signature:** `hasSuggestions() : boolean` **Description:** Returns whether this suggestions container has any suggested items, i.e. products. Note that this method only looks for concrete suggested items. It does not account for suggested terms. In other words, even if there are suggested terms, this method will return false if no matching items, like products or categories, were found for the suggested terms. To find out whether there are suggested terms and how they match with respect to the original search phrase, one can use getSuggestedTerms() to obtain a list of SuggestedTerms. **Returns:** true only if there are items found using the suggested terms **See Also:** getSuggestedTerms() SuggestedTerms.isEmpty() --- ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/get-latest-error.full-mode.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml --- description: "Test get_latest_error tool in full mode (focused YAML tests - complex scenarios covered in Node.js)" tests: # Basic functionality tests - it: "should retrieve error messages with default parameters" request: jsonrpc: "2.0" id: "error-default" method: "tools/call" params: name: "get_latest_error" arguments: {} expect: response: jsonrpc: "2.0" id: "error-default" result: content: match:arrayElements: type: "text" text: "match:contains:Latest 10 error messages" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" - it: "should respect limit parameter" request: jsonrpc: "2.0" id: "error-limit" method: "tools/call" params: name: "get_latest_error" arguments: limit: 3 expect: response: jsonrpc: "2.0" id: "error-limit" result: content: match:arrayElements: type: "text" text: "match:contains:Latest 3 error messages" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" # Basic content validation (detailed validation in Node.js tests) - it: "should include basic SFCC log structure elements" request: jsonrpc: "2.0" id: "error-structure" method: "tools/call" params: name: "get_latest_error" arguments: limit: 2 expect: response: jsonrpc: "2.0" id: "error-structure" result: content: match:arrayElements: match:partial: text: "match:regex:error-blade-[\\d]{8}-[\\d]{6}\\.log[\\s\\S]*ERROR[\\s\\S]*GMT" isError: false stderr: "toBeEmpty" # Parameter validation tests (core error cases) - it: "should reject string limit parameter" request: jsonrpc: "2.0" id: "error-string-limit" method: "tools/call" params: name: "get_latest_error" arguments: limit: "5" expect: response: jsonrpc: "2.0" id: "error-string-limit" result: content: match:arrayElements: type: "text" text: "match:contains:Invalid limit '5'" isError: true stderr: "toBeEmpty" - it: "should reject zero limit parameter" request: jsonrpc: "2.0" id: "error-zero-limit" method: "tools/call" params: name: "get_latest_error" arguments: limit: 0 expect: response: jsonrpc: "2.0" id: "error-zero-limit" result: content: match:arrayElements: match:partial: text: "match:contains:Invalid limit '0'" isError: true stderr: "toBeEmpty" - it: "should reject negative limit parameter" request: jsonrpc: "2.0" id: "error-negative-limit" method: "tools/call" params: name: "get_latest_error" arguments: limit: -5 expect: response: jsonrpc: "2.0" id: "error-negative-limit" result: content: match:arrayElements: match:partial: text: "match:contains:Invalid limit" isError: true stderr: "toBeEmpty" # Date parameter basic validation - it: "should handle valid date parameter" request: jsonrpc: "2.0" id: "error-valid-date" method: "tools/call" params: name: "get_latest_error" arguments: date: "20240101" limit: 1 expect: response: jsonrpc: "2.0" id: "error-valid-date" result: content: "match:type:array" isError: false stderr: "toBeEmpty" # Performance validation (basic) - it: "should respond quickly for small limits" request: jsonrpc: "2.0" id: "error-perf-small" method: "tools/call" params: name: "get_latest_error" arguments: limit: 1 expect: response: jsonrpc: "2.0" id: "error-perf-small" result: content: "match:type:array" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "1500ms" # Response structure consistency - it: "should return consistent MCP response structure" request: jsonrpc: "2.0" id: "error-mcp-structure" method: "tools/call" params: name: "get_latest_error" arguments: limit: 1 expect: response: jsonrpc: "2.0" id: "error-mcp-structure" result: match:partial: content: "match:type:array" isError: "match:type:boolean" stderr: "toBeEmpty" ``` -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- ```yaml name: ✨ Feature Request description: Suggest a new feature or enhancement for the SFCC Development MCP Server title: "[Feature]: " labels: ["enhancement", "needs-triage"] assignees: [] body: - type: markdown attributes: value: | Thanks for suggesting a new feature! Please provide detailed information to help us understand and evaluate your request. - type: checkboxes id: terms attributes: label: Pre-submission Checklist description: Please confirm you have completed these steps before submitting the feature request. options: - label: I have searched existing issues and discussions to ensure this feature hasn't been requested already required: true - label: I have reviewed the roadmap and documentation to confirm this feature doesn't already exist required: true - label: This feature aligns with the project's goals of improving SFCC development workflows required: true - type: dropdown id: feature-category attributes: label: Feature Category description: Which category does this feature request fall into? options: - New MCP Tool - SFCC API Integration Enhancement - Documentation/Best Practices - Authentication/Security - Performance/Caching - Configuration/Setup - Developer Experience - Testing/Quality Assurance - Other validations: required: true - type: textarea id: problem-statement attributes: label: Problem Statement description: What problem does this feature solve? What pain point are you experiencing? placeholder: Describe the current limitation or challenge you're facing in SFCC development... validations: required: true - type: textarea id: proposed-solution attributes: label: Proposed Solution description: Describe your ideal solution to this problem. placeholder: Explain how you envision this feature working... validations: required: true - type: textarea id: use-cases attributes: label: Use Cases description: Provide specific examples of how this feature would be used. placeholder: | 1. As a developer, I want to... so that... 2. When working on cartridge development, I need to... 3. During debugging sessions, it would help if... validations: required: true - type: dropdown id: target-mode attributes: label: Target Operating Mode description: Which operating mode should this feature support? multiple: true options: - Documentation-only mode - Full mode (with SFCC credentials) - Both modes - New mode (please specify in additional context) validations: required: true - type: dropdown id: priority attributes: label: Priority Level description: How would you rate the priority of this feature? options: - Critical - Blocking my work - High - Would significantly improve my workflow - Medium - Nice to have improvement - Low - Minor enhancement validations: required: true - type: textarea id: alternatives attributes: label: Alternative Solutions description: Have you considered any alternative approaches or workarounds? placeholder: Describe any workarounds you're currently using or other solutions you've considered... - type: textarea id: implementation-ideas attributes: label: Implementation Ideas (Optional) description: If you have ideas about how this could be implemented, please share them. placeholder: | - Could be implemented as a new tool in the clients/ directory - Might require changes to the authentication flow - Would need new SFCC API endpoints... - type: dropdown id: sfcc-apis attributes: label: SFCC APIs Involved description: Which SFCC APIs would this feature likely interact with? multiple: true options: - OCAPI (Open Commerce API) - SCAPI (Shopper API) - WebDAV - SFCC Logs - System Object Definitions - Site Preferences - Custom Objects - Not sure - Not applicable - type: textarea id: additional-context attributes: label: Additional Context description: Any other context, mockups, examples, or references that would help understand this feature request. - type: checkboxes id: contribution attributes: label: Contribution Intent description: Are you interested in contributing to this feature? options: - label: I'm willing to help implement this feature required: false - label: I can help with testing and validation required: false - label: I can provide domain expertise or consultation required: false ``` -------------------------------------------------------------------------------- /docs/dw_util/SeekableIterator.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.util # Class SeekableIterator ## Inheritance Hierarchy - Object - dw.util.Iterator - dw.util.SeekableIterator ## Description A special Iterator, which is returned by the system to iterate through large sets of data. The iterator supports seeking forward to a random position. This is a typical action when paging forward in a result set. The Iterator is primarily returned from search operations. Starting with API version 10.6, these iterators can only be iterated once to avoid possible memory problems for really large result sets. Putting them into the pipeline dictionary and trying to loop them multiple times is no longer possible because this would require buffering the iterated elements internally. Prior to 10.6, and for all customers still running API version 10.4 (compatibility mode), SeekableIterator instances stored in the pipeline dictionary could be iterated multiple times (for example, by several loop nodes). ## Properties ### count **Type:** Number (Read Only) The total element count for this iterator. The method returns -1, if the total count is not known. ## Constructor Summary ## Method Summary ### asList **Signature:** `asList(start : Number, size : Number) : List` Returns a list representing a subsequence within the iterator. ### close **Signature:** `close() : void` Closes all system resources associated with this iterator. ### first **Signature:** `first() : Object` Returns the first element of this iterator and closes it. ### forward **Signature:** `forward(n : Number) : void` Seeks forward by the given number of elements. ### forward **Signature:** `forward(n : Number, size : Number) : void` Seeks forward by the given number of elements and limits the iteration to the given number of elements. ### getCount **Signature:** `getCount() : Number` Returns the total element count for this iterator. ### hasNext **Signature:** `hasNext() : boolean` Indicates if there are more elements. ### next **Signature:** `next() : Object` Returns the next element from the Iterator. ## Method Detail ## Method Details ### asList **Signature:** `asList(start : Number, size : Number) : List` **Description:** Returns a list representing a subsequence within the iterator. The underlying system resources of the iterator will be closed at the end. The start position must be 0 or a positive number. **Parameters:** - `start`: the position from which to start the subsequence. - `size`: the number of items to collect. **Returns:** the list containing the subsequence. --- ### close **Signature:** `close() : void` **Description:** Closes all system resources associated with this iterator. Calling this method is strongly recommended if not all elements of this iterator are retrieved. This will allow the system to release system resources immediately. The SeekableIterator is closed automatically if all elements are retrieved. Then calling method close() is optional. --- ### first **Signature:** `first() : Object` **Description:** Returns the first element of this iterator and closes it. If the iterator does not contain another element null is returned. If any of the methods next(), forward(int) or forward(int,int) have been called before null is returned. This method is useful if only the first element of an iterator is needed. A possible example for the use of first() is: OrderMgr.queryOrders("queryString", "sortString", args).first() **Returns:** the first element of an iterator and closes the iterator or returns null if the iterator doesn't have another element or the methods next(), forward(int) or forward(int,int) have already been called. --- ### forward **Signature:** `forward(n : Number) : void` **Description:** Seeks forward by the given number of elements. The number of seek steps must be 0 or a positive number. **Parameters:** - `n`: the number of elements to seek forward. --- ### forward **Signature:** `forward(n : Number, size : Number) : void` **Description:** Seeks forward by the given number of elements and limits the iteration to the given number of elements. The method is typically used to position and trim an iterator for paging. The getCount() method will still return the total count of the underlying data collection. **Parameters:** - `n`: the number of elements to seek forward. - `size`: the maximum number of elements return from the iterator --- ### getCount **Signature:** `getCount() : Number` **Description:** Returns the total element count for this iterator. The method returns -1, if the total count is not known. **Returns:** the total element count for this iterator or -1. --- ### hasNext **Signature:** `hasNext() : boolean` **Description:** Indicates if there are more elements. **Returns:** true if there are more elements, false otherwise. --- ### next **Signature:** `next() : Object` **Description:** Returns the next element from the Iterator. **Returns:** the next element from the Iterator. --- ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/get-latest-warn.full-mode.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml --- description: "Test get_latest_warn tool in full mode - focused on MCP response validation" tests: # Core functionality validation - it: "should retrieve latest warn messages with default parameters" request: jsonrpc: "2.0" id: "warn-default" method: "tools/call" params: name: "get_latest_warn" arguments: {} expect: response: jsonrpc: "2.0" id: "warn-default" result: content: match:arrayElements: type: "text" text: "match:contains:Latest 10 warn messages" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" - it: "should respect limit parameter" request: jsonrpc: "2.0" id: "warn-limit" method: "tools/call" params: name: "get_latest_warn" arguments: limit: 3 expect: response: jsonrpc: "2.0" id: "warn-limit" result: content: match:arrayElements: match:partial: text: "match:regex:Latest 3 warn messages[\\s\\S]*warn-blade-[\\d]{8}-[\\d]{6}\\.log[\\s\\S]*WARN[\\s\\S]*GMT" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" # Core log structure validation in one comprehensive test - it: "should contain proper SFCC log structure elements" request: jsonrpc: "2.0" id: "warn-structure" method: "tools/call" params: name: "get_latest_warn" arguments: limit: 2 expect: response: jsonrpc: "2.0" id: "warn-structure" result: content: match:arrayElements: match:partial: # Validates: log filename, timestamp, WARN level, Sites info, separators in one test text: "match:regex:warn-blade-[\\d]{8}-[\\d]{6}\\.log[\\s\\S]*[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}\\.[\\d]{3} GMT[\\s\\S]*WARN PipelineCallServlet[\\s\\S]*Sites-[\\s\\S]*---" isError: false stderr: "toBeEmpty" # Error handling validation (key validation patterns) - it: "should handle string limit parameter with proper error message" request: jsonrpc: "2.0" id: "warn-string-limit" method: "tools/call" params: name: "get_latest_warn" arguments: limit: "5" expect: response: jsonrpc: "2.0" id: "warn-string-limit" result: content: match:arrayElements: type: "text" text: "match:regex:Error: Invalid limit '5'[\\s\\S]*Must be a valid number" isError: true stderr: "toBeEmpty" - it: "should handle zero limit with proper error message" request: jsonrpc: "2.0" id: "warn-zero-limit" method: "tools/call" params: name: "get_latest_warn" arguments: limit: 0 expect: response: jsonrpc: "2.0" id: "warn-zero-limit" result: content: match:arrayElements: type: "text" text: "match:regex:Error: Invalid limit '0'[\\s\\S]*Must be between 1 and 1000" isError: true stderr: "toBeEmpty" - it: "should handle negative limit with proper error message" request: jsonrpc: "2.0" id: "warn-negative-limit" method: "tools/call" params: name: "get_latest_warn" arguments: limit: -5 expect: response: jsonrpc: "2.0" id: "warn-negative-limit" result: content: match:arrayElements: type: "text" text: "match:contains:Error: Invalid limit '-5'" isError: true stderr: "toBeEmpty" # Edge case - large limit handling - it: "should handle large limit values appropriately" request: jsonrpc: "2.0" id: "warn-large-limit" method: "tools/call" params: name: "get_latest_warn" arguments: limit: 50 expect: response: jsonrpc: "2.0" id: "warn-large-limit" result: content: match:arrayElements: type: "text" text: "match:contains:Latest 50 warn messages" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "3000ms" # Date parameter edge case - it: "should handle invalid date format gracefully" request: jsonrpc: "2.0" id: "warn-invalid-date" method: "tools/call" params: name: "get_latest_warn" arguments: date: "invalid-date" limit: 1 expect: response: jsonrpc: "2.0" id: "warn-invalid-date" result: content: match:arrayElements: type: "text" text: "match:type:string" isError: false stderr: "toBeEmpty" ``` -------------------------------------------------------------------------------- /src/tool-configs/job-log-tool-config.ts: -------------------------------------------------------------------------------- ```typescript import { GenericToolSpec, ToolExecutionContext } from '../core/handlers/base-handler.js'; import { ToolArguments } from '../core/handlers/base-handler.js'; import { LogToolValidators } from '../utils/log-tool-utils.js'; import { ValidationHelpers, CommonValidations } from '../core/handlers/validation-helpers.js'; import { JobLogToolName, getLimit } from '../utils/log-tool-constants.js'; import { JobLogValidators, JobLogFormatters } from '../utils/job-log-utils.js'; import { SFCCLogClient } from '../clients/log-client.js'; /** * Configuration for job log tools * Maps each tool to its validation, execution, and messaging logic */ export const JOB_LOG_TOOL_CONFIG: Record<JobLogToolName, GenericToolSpec<ToolArguments, any>> = { get_latest_job_log_files: { defaults: (args: ToolArguments) => ({ limit: getLimit(args.limit as number, 'jobFiles'), }), validate: (args: ToolArguments, toolName: string) => LogToolValidators.validateLimit(args.limit as number, toolName), exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.logClient as SFCCLogClient; return client.getLatestJobLogFiles(args.limit as number); }, logMessage: (args: ToolArguments) => JobLogFormatters.formatJobLogMessage('Fetching latest job log files', { limit: args.limit as number, }), }, search_job_logs_by_name: { defaults: (args: ToolArguments) => ({ limit: getLimit(args.limit as number, 'jobFiles'), }), validate: (args: ToolArguments, toolName: string) => { ValidationHelpers.validateArguments(args, CommonValidations.requiredString('jobName'), toolName); LogToolValidators.validateLimit(args.limit as number, toolName); }, exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.logClient as SFCCLogClient; return client.searchJobLogsByName(args.jobName as string, args.limit as number); }, logMessage: (args: ToolArguments) => JobLogFormatters.formatJobLogMessage('Searching job logs by name', { jobName: args.jobName as string, limit: args.limit as number, }), }, get_job_log_entries: { defaults: (args: ToolArguments) => ({ level: args.level ?? 'all', limit: getLimit(args.limit as number, 'jobEntries'), }), validate: (args: ToolArguments, toolName: string) => { JobLogValidators.validateJobLogLevel(args.level as string, toolName); LogToolValidators.validateLimit(args.limit as number, toolName); }, exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.logClient as SFCCLogClient; return client.getJobLogEntries( args.level as any, args.limit as number, args.jobName as string, ); }, logMessage: (args: ToolArguments) => JobLogFormatters.formatJobLogMessage('Fetching job log entries', { level: args.level as string, limit: args.limit as number, jobName: args.jobName as string, }), }, search_job_logs: { defaults: (args: ToolArguments) => ({ level: args.level ?? 'all', limit: getLimit(args.limit as number, 'jobSearch'), }), validate: (args: ToolArguments, toolName: string) => { ValidationHelpers.validateArguments(args, CommonValidations.requiredString('pattern'), toolName); JobLogValidators.validateJobLogLevel(args.level as string, toolName); LogToolValidators.validateLimit(args.limit as number, toolName); // Validate optional jobName parameter - must be string if provided if (args.jobName !== undefined) { ValidationHelpers.validateArguments(args, CommonValidations.optionalField( 'jobName', 'string', (value: string) => typeof value === 'string' && value.trim().length > 0, 'jobName must be a non-empty string', ), toolName); } }, exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.logClient as SFCCLogClient; return client.searchJobLogs( args.pattern as string, args.level as any, args.limit as number, args.jobName as string, ); }, logMessage: (args: ToolArguments) => JobLogFormatters.formatJobLogMessage('Searching job logs', { pattern: args.pattern as string, level: args.level as string, limit: args.limit as number, jobName: args.jobName as string, }), }, get_job_execution_summary: { defaults: (args: ToolArguments) => args, validate: (args: ToolArguments, toolName: string) => { ValidationHelpers.validateArguments(args, CommonValidations.requiredString('jobName'), toolName); }, exec: async (args: ToolArguments, context: ToolExecutionContext) => { const client = context.logClient as SFCCLogClient; return client.getJobExecutionSummary(args.jobName as string); }, logMessage: (args: ToolArguments) => `Getting job execution summary for: ${args.jobName as string}`, }, }; ``` -------------------------------------------------------------------------------- /docs/dw_extensions.payments/SalesforcePayPalOrder.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.extensions.payments # Class SalesforcePayPalOrder ## Inheritance Hierarchy - Object - dw.extensions.payments.SalesforcePayPalOrder ## Description Salesforce Payments representation of a PayPal order object. See Salesforce Payments documentation for how to gain access and configure it for use on your sites. A PayPal order is automatically created when a shopper is ready to pay for items in their basket. It becomes completed when the shopper provides information to the payment provider that is acceptable to authorize payment for a given amount. ## Constants ### TYPE_PAYPAL **Type:** String = "paypal" Represents the PayPal funding source. ### TYPE_VENMO **Type:** String = "venmo" Represents the Venmo funding source. ## Properties ### amount **Type:** Money (Read Only) The amount of this PayPal order. ### captureID **Type:** String (Read Only) The ID of the capture against this order, or null if not available. ### completed **Type:** boolean (Read Only) Returns true if this PayPal order has been completed, or false if not. ### ID **Type:** String (Read Only) The identifier of this PayPal order. ### payer **Type:** SalesforcePayPalOrderPayer (Read Only) The payer information for this PayPal order, or null if not known. ### shipping **Type:** SalesforcePayPalOrderAddress (Read Only) The shipping address for this PayPal order, or null if not known. ## Constructor Summary ## Method Summary ### getAmount **Signature:** `getAmount() : Money` Returns the amount of this PayPal order. ### getCaptureID **Signature:** `getCaptureID() : String` Returns the ID of the capture against this order, or null if not available. ### getID **Signature:** `getID() : String` Returns the identifier of this PayPal order. ### getPayer **Signature:** `getPayer() : SalesforcePayPalOrderPayer` Returns the payer information for this PayPal order, or null if not known. ### getPaymentDetails **Signature:** `getPaymentDetails(paymentInstrument : OrderPaymentInstrument) : SalesforcePaymentDetails` Returns the details to the Salesforce Payments payment for this PayPal order, using the given payment instrument. ### getPaymentInstrument **Signature:** `getPaymentInstrument(basket : Basket) : OrderPaymentInstrument` Returns the payment instrument for this PayPal order in the given basket, or null if the given basket has none. ### getPaymentInstrument **Signature:** `getPaymentInstrument(order : Order) : OrderPaymentInstrument` Returns the payment instrument for this PayPal order in the given order, or null if the given order has none. ### getShipping **Signature:** `getShipping() : SalesforcePayPalOrderAddress` Returns the shipping address for this PayPal order, or null if not known. ### isCompleted **Signature:** `isCompleted() : boolean` Returns true if this PayPal order has been completed, or false if not. ## Method Detail ## Method Details ### getAmount **Signature:** `getAmount() : Money` **Description:** Returns the amount of this PayPal order. **Returns:** PayPal order amount --- ### getCaptureID **Signature:** `getCaptureID() : String` **Description:** Returns the ID of the capture against this order, or null if not available. **Returns:** PayPal order capture identifier --- ### getID **Signature:** `getID() : String` **Description:** Returns the identifier of this PayPal order. **Returns:** PayPal order identifier --- ### getPayer **Signature:** `getPayer() : SalesforcePayPalOrderPayer` **Description:** Returns the payer information for this PayPal order, or null if not known. **Returns:** order payer information --- ### getPaymentDetails **Signature:** `getPaymentDetails(paymentInstrument : OrderPaymentInstrument) : SalesforcePaymentDetails` **Description:** Returns the details to the Salesforce Payments payment for this PayPal order, using the given payment instrument. **Parameters:** - `paymentInstrument`: payment instrument **Returns:** The payment details --- ### getPaymentInstrument **Signature:** `getPaymentInstrument(basket : Basket) : OrderPaymentInstrument` **Description:** Returns the payment instrument for this PayPal order in the given basket, or null if the given basket has none. **Parameters:** - `basket`: basket **Returns:** basket payment instrument --- ### getPaymentInstrument **Signature:** `getPaymentInstrument(order : Order) : OrderPaymentInstrument` **Description:** Returns the payment instrument for this PayPal order in the given order, or null if the given order has none. **Parameters:** - `order`: order **Returns:** order payment instrument --- ### getShipping **Signature:** `getShipping() : SalesforcePayPalOrderAddress` **Description:** Returns the shipping address for this PayPal order, or null if not known. **Returns:** order shipping address --- ### isCompleted **Signature:** `isCompleted() : boolean` **Description:** Returns true if this PayPal order has been completed, or false if not. **Returns:** true if this PayPal order has been completed --- ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/get-latest-debug.full-mode.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml --- # Optimized YAML tests for get_latest_debug tool - focuses on MCP protocol compliance and basic functionality # Complex content validation, performance testing, and detailed parameter validation are handled in the programmatic tests # These tests primarily validate aegis testing framework integration and basic MCP responses description: "Test get_latest_debug tool in full mode - Basic MCP protocol and parameter validation" tests: # ======================================== # MCP PROTOCOL COMPLIANCE # ======================================== - it: "should return valid MCP response structure with default parameters" request: jsonrpc: "2.0" id: "debug-default" method: "tools/call" params: name: "get_latest_debug" arguments: {} expect: response: jsonrpc: "2.0" id: "debug-default" result: content: match:arrayElements: match:partial: type: "text" text: "match:type:string" isError: "match:type:boolean" stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" - it: "should contain expected content structure for default limit" request: jsonrpc: "2.0" id: "debug-content" method: "tools/call" params: name: "get_latest_debug" arguments: {} expect: response: jsonrpc: "2.0" id: "debug-content" result: content: match:arrayElements: type: "text" text: "match:contains:Latest 10 debug messages" isError: false stderr: "toBeEmpty" # ======================================== # PARAMETER VALIDATION # ======================================== - it: "should respect limit parameter" request: jsonrpc: "2.0" id: "debug-limit" method: "tools/call" params: name: "get_latest_debug" arguments: limit: 3 expect: response: jsonrpc: "2.0" id: "debug-limit" result: content: match:arrayElements: type: "text" text: "match:contains:Latest 3 debug messages" isError: false stderr: "toBeEmpty" - it: "should handle date parameter" request: jsonrpc: "2.0" id: "debug-date" method: "tools/call" params: name: "get_latest_debug" arguments: date: "20240101" limit: 2 expect: response: jsonrpc: "2.0" id: "debug-date" result: content: match:arrayElements: type: "text" text: "match:type:string" isError: false stderr: "toBeEmpty" # ======================================== # ERROR HANDLING # ======================================== - it: "should reject invalid string limit parameter" request: jsonrpc: "2.0" id: "debug-string-limit" method: "tools/call" params: name: "get_latest_debug" arguments: limit: "5" expect: response: jsonrpc: "2.0" id: "debug-string-limit" result: content: match:arrayElements: type: "text" text: "match:contains:Invalid limit '5' for get_latest_debug. Must be a valid number" isError: true stderr: "toBeEmpty" - it: "should reject zero limit parameter" request: jsonrpc: "2.0" id: "debug-zero-limit" method: "tools/call" params: name: "get_latest_debug" arguments: limit: 0 expect: response: jsonrpc: "2.0" id: "debug-zero-limit" result: content: match:arrayElements: type: "text" text: "match:contains:Invalid limit '0'" isError: true stderr: "toBeEmpty" # ======================================== # BASIC CONTENT VALIDATION # ======================================== - it: "should include basic SFCC log elements" request: jsonrpc: "2.0" id: "debug-basic-content" method: "tools/call" params: name: "get_latest_debug" arguments: limit: 2 expect: response: jsonrpc: "2.0" id: "debug-basic-content" result: content: match:arrayElements: match:partial: text: "match:contains:DEBUG" isError: false stderr: "toBeEmpty" - it: "should include log file names in response" request: jsonrpc: "2.0" id: "debug-filenames" method: "tools/call" params: name: "get_latest_debug" arguments: limit: 1 expect: response: jsonrpc: "2.0" id: "debug-filenames" result: content: match:arrayElements: match:partial: text: "match:contains:debug-blade-" isError: false stderr: "toBeEmpty" ``` -------------------------------------------------------------------------------- /docs/dw_web/FormElement.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.web # Class FormElement ## Inheritance Hierarchy - Object - dw.web.FormElement ## Description Represents a form element. ## Properties ### dynamicHtmlName **Type:** String (Read Only) A dynamic html name for the field. It can be used to suppress any autocompletion support from a browser, e.g. for credit card related fields. It can be also used for a unique form name, if one form is used multiple times in a page. ### formId **Type:** String (Read Only) The ID of the form element. The is is unique within the parent element of the form. ### htmlName **Type:** String (Read Only) The global unique name of the field, which can be used as name in the html form. For radio buttons this name is not unique. ### parent **Type:** FormElement (Read Only) The parent within the form. ### valid **Type:** boolean (Read Only) Identifies if this element and all its children elements are valid. A form element, which was not submitted in the last request is always valid. ### validationResult **Type:** FormElementValidationResult (Read Only) Provides a combined view on the validation status as per isValid() and getError(). In addition it also provides the data as returned by the validation in case a validation script was used. ## Constructor Summary ## Method Summary ### clearFormElement **Signature:** `clearFormElement() : void` This method clears the whole form. ### getDynamicHtmlName **Signature:** `getDynamicHtmlName() : String` Returns a dynamic html name for the field. ### getFormId **Signature:** `getFormId() : String` The ID of the form element. ### getHtmlName **Signature:** `getHtmlName() : String` Returns the global unique name of the field, which can be used as name in the html form. ### getParent **Signature:** `getParent() : FormElement` The parent within the form. ### getValidationResult **Signature:** `getValidationResult() : FormElementValidationResult` Provides a combined view on the validation status as per isValid() and getError(). ### invalidateFormElement **Signature:** `invalidateFormElement() : void` The method can be called to explicitly invalidate a form element. ### invalidateFormElement **Signature:** `invalidateFormElement(error : String) : void` The method can be called to explicitly invalidate a field. ### isValid **Signature:** `isValid() : boolean` Identifies if this element and all its children elements are valid. ## Method Detail ## Method Details ### clearFormElement **Signature:** `clearFormElement() : void` **Description:** This method clears the whole form. After clearing a form it contains no value or the default value, is not bound to any business object and has the status of being valid. --- ### getDynamicHtmlName **Signature:** `getDynamicHtmlName() : String` **Description:** Returns a dynamic html name for the field. It can be used to suppress any autocompletion support from a browser, e.g. for credit card related fields. It can be also used for a unique form name, if one form is used multiple times in a page. **Returns:** a dynamic html name. --- ### getFormId **Signature:** `getFormId() : String` **Description:** The ID of the form element. The is is unique within the parent element of the form. **Returns:** the ID of the form. --- ### getHtmlName **Signature:** `getHtmlName() : String` **Description:** Returns the global unique name of the field, which can be used as name in the html form. For radio buttons this name is not unique. **Returns:** the global unique name of the field. --- ### getParent **Signature:** `getParent() : FormElement` **Description:** The parent within the form. **Returns:** the parent within the form. --- ### getValidationResult **Signature:** `getValidationResult() : FormElementValidationResult` **Description:** Provides a combined view on the validation status as per isValid() and getError(). In addition it also provides the data as returned by the validation in case a validation script was used. **Returns:** the validation status (valid, error, data) --- ### invalidateFormElement **Signature:** `invalidateFormElement() : void` **Description:** The method can be called to explicitly invalidate a form element. The error text will be set to the one of two possible preconfigured custom error messages associated with the form definition. The "value-error" message will be used for FormField instances and "form-error" will be used for FormGroup instances. --- ### invalidateFormElement **Signature:** `invalidateFormElement(error : String) : void` **Description:** The method can be called to explicitly invalidate a field. The error text is set to the given error message. **Parameters:** - `error`: the error text to use. --- ### isValid **Signature:** `isValid() : boolean` **Description:** Identifies if this element and all its children elements are valid. A form element, which was not submitted in the last request is always valid. **Returns:** true if this element and all its children elements are valid, false otherwise. --- ``` -------------------------------------------------------------------------------- /docs/dw_crypto/WeakMac.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.crypto # Class WeakMac ## Inheritance Hierarchy - Object - dw.crypto.WeakMac ## Description This API provides access to Deprecated algorithms. See Mac for full documentation. WeakMac is simply a drop-in replacement that only supports deprecated algorithms. This is helpful when you need to deal with weak algorithms for backward compatibility purposes, but Mac should always be used for new development and for anything intended to be secure. This class provides the functionality of a "Message Authentication Code" (MAC) algorithm. A MAC provides a way to check the integrity of information transmitted over or stored in an unreliable medium, based on a secret key. Typically, message authentication codes are used between two parties that share a secret key in order to validate information transmitted between these parties. A MAC mechanism that is based on cryptographic hash functions is referred to as HMAC. HMAC can be used with any cryptographic hash function, e.g., SHA256, in combination with a secret shared key. HMAC is specified in RFC 2104. Note: this class handles sensitive security-related data. Pay special attention to PCI DSS v3. requirements 2, 4, and 12. ## Constants ### HMAC_MD5 **Type:** String = "HmacMD5" Constant representing the HMAC-MD5 keyed-hashing algorithm as defined in RFC 2104 "HMAC: Keyed-Hashing for Message Authentication" (February 1997). This algorithm uses as MD5 cryptographic hash function. This algorithm is obsolete. Do not use it for any sensitive data ### HMAC_SHA_1 **Type:** String = "HmacSHA1" Constant representing the HmacSHA1 algorithms as defined in RFC 2104 "HMAC: Keyed-Hashing for Message Authentication" (February 1997) with SHA-1 as the message digest algorithm. This algorithm is obsolete. Do not use it for any sensitive data ## Properties ## Constructor Summary WeakMac(algorithm : String) Construct a Mac encryption instance with the specified algorithm name. ## Method Summary ### digest **Signature:** `digest(input : String, key : String) : Bytes` Computes the hash value for the passed string input using the passed secret key. ### digest **Signature:** `digest(input : String, key : Bytes) : Bytes` Computes the hash value for the passed string input using the passed secret key. ### digest **Signature:** `digest(input : Bytes, key : Bytes) : Bytes` Computes the hash value for the passed bytes input using the passed secret key. ## Constructor Detail ## Method Detail ## Method Details ### digest **Signature:** `digest(input : String, key : String) : Bytes` **Description:** Computes the hash value for the passed string input using the passed secret key. Given input and the given key will be first converted with UTF-8 encoding into a byte array. The resulting hash is typically converted with base64 back into a string. **Parameters:** - `input`: A string to calculate a RFC 2104 compliant HMAC hash value for. - `key`: The secret key ready for use with the algorithm. The key's format depends on the chosen algorithm and the keys are assumed to be correctly formulated for the algorithm used, for example that the lengths are correct. Keys are not checked for validity. Only such keys that have no key parameters associated with them. **Returns:** The resulting hash value as bytes. **Throws:** IllegalArgumentException - if algorithm is not null and the specified algorithm name is not supported. --- ### digest **Signature:** `digest(input : String, key : Bytes) : Bytes` **Description:** Computes the hash value for the passed string input using the passed secret key. Given input will be first converted with UTF-8 encoding into a byte array. The resulting hash is typically converted with base64 back into a string. **Parameters:** - `input`: A string to calculate a RFC 2104 compliant HMAC hash value for. - `key`: The secret key as bytes ready for use with the algorithm. The key's format depends on the chosen algorithm and the keys are assumed to be correctly formulated for the algorithm used, for example that the lengths are correct. Keys are not checked for validity. Only such keys that have no key parameters associated with them. **Returns:** The resulting hash value as bytes. **Throws:** IllegalArgumentException - if algorithm is not null and the specified algorithm name is not supported. --- ### digest **Signature:** `digest(input : Bytes, key : Bytes) : Bytes` **Description:** Computes the hash value for the passed bytes input using the passed secret key. **Parameters:** - `input`: The bytes to calculate a RFC 2104 compliant HMAC hash value. - `key`: The secret key as byte array ready for use with the algorithm. The key's format depends on the chosen algorithm and the keys are assumed to be correctly formulated for the algorithm used, for example that the lengths are correct. Keys are not checked for validity. Only such keys that have no key parameters associated with them. **Returns:** The resulting hash value as bytes. **Throws:** IllegalArgumentException - if algorithm is not null and the specified algorithm name is not supported. --- ``` -------------------------------------------------------------------------------- /docs/dw_web/Resource.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.web # Class Resource ## Inheritance Hierarchy - Object - dw.web.Resource ## Description Library class which provides methods for retrieving messages from properties resource bundles which contain locale-specific strings. When your program needs a locale-specific String, it loads it from the resource bundle that is appropriate for the user's current locale. In this way, the program code is largely independent of the user's locale. In Commerce Cloud Digital, resources are associated with the templates of a cartridge. These bundles consist of properties files with a common name defined in the template/resources directory of a site cartridge. For example: templates/resources/message.properties templates/resources/message_en.properties templates/resources/message_en_US.properties templates/resources/message_de_DE.properties Resource bundle lookup generally follows the same rules as the Java ResourceBundle class, where the locale used for lookup is based on the current request. See method javadoc for additional details. Properties resource files are assumed to use the UTF-8 character encoding. Unicode escape sequences are also supported. ## Constructor Summary ## Method Summary ### msg **Signature:** `static msg(key : String) : String` Returns the message from the default properties resource bundle (base name "message") corresponding to the specified key and the request locale. ### msg **Signature:** `static msg(key : String, defaultMessage : String) : String` Returns the message from the default properties resource bundle (base name "message") corresponding to the specified key and the request locale. ### msg **Signature:** `static msg(key : String, bundleName : String, defaultMessage : String) : String` Returns the message from the specified properties resource bundle. ### msgf **Signature:** `static msgf(key : String, bundleName : String, defaultMessage : String, args : Object...) : String` Returns the message from the specified properties resource bundle, with the provided arguments substituted for the message argument placeholders (specified using the Java MessageFormat approach). ## Method Detail ## Method Details ### msg **Signature:** `static msg(key : String) : String` **Description:** Returns the message from the default properties resource bundle (base name "message") corresponding to the specified key and the request locale. This method is equivalent to msg(String, null). **Parameters:** - `key`: resource bundle message key **Returns:** the resource bundle message or the key itself if no message is defined. **See Also:** msg(String, String) --- ### msg **Signature:** `static msg(key : String, defaultMessage : String) : String` **Description:** Returns the message from the default properties resource bundle (base name "message") corresponding to the specified key and the request locale. If no message for the key is found, returns the default message if it is not null, otherwise returns the key itself. This method is equivalent to msg(key, null, defaultMessage). **Parameters:** - `key`: resource bundle message key - `defaultMessage`: default message to return if no message corresponding to the key is found **Returns:** the resource bundle message or default message **See Also:** msg(String, String, String) --- ### msg **Signature:** `static msg(key : String, bundleName : String, defaultMessage : String) : String` **Description:** Returns the message from the specified properties resource bundle. The resource bundle is located by iterating the site cartridges and looking for a bundle with the specified name in the cartridge template/resources directory. If it finds a bundle, it tries to return a message from the bundle using standard Java ResourceBundle logic. If a message is found in that cartridge's bundle, it is returned, otherwise, the next cartridge is examined. The method throws an exception if the key is null. **Parameters:** - `key`: resource bundle message key - `bundleName`: base bundle name, if null, default bundle name, "message", is used - `defaultMessage`: default message to return if no message corresponding to the key is found and defaultMessage is not null **Returns:** the resource bundle message or default message --- ### msgf **Signature:** `static msgf(key : String, bundleName : String, defaultMessage : String, args : Object...) : String` **Description:** Returns the message from the specified properties resource bundle, with the provided arguments substituted for the message argument placeholders (specified using the Java MessageFormat approach). If null is passed for the varargs argument, this method is equivalent to msg(key, bundleName, defaultMessage). **Parameters:** - `key`: resource bundle message key - `bundleName`: base bundle name, if null, default bundle name, "message", is used - `defaultMessage`: default message to return if no message corresponding to the key is found and defaultMessage is not null - `args`: optional list of arguments or a collection, which are included into the result string **Returns:** the resource bundle message or default message **See Also:** msg(String, String, String) --- ``` -------------------------------------------------------------------------------- /docs/dw_crypto/JWS.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.crypto # Class JWS ## Inheritance Hierarchy - Object - dw.crypto.JWS ## Description This class represents a JSON Web Signature (JWS) object. Note: this class handles sensitive security-related data. Pay special attention to PCI DSS v3 requirements 2, 4, and 12. ## Properties ### algorithm **Type:** String (Read Only) Get the algorithm (alg) from the header. ### header **Type:** JWSHeader (Read Only) Get a copy of the JWS header. ### headerMap **Type:** Map (Read Only) Get a copy of the JWS header as a Map. ### payload **Type:** String (Read Only) Get the payload from this object. This is available even if the signature has not been verified. ## Constructor Summary JWS(header : JWSHeader, payload : String) Construct a new JWS for signing. JWS(header : JWSHeader, payload : Bytes) Construct a new JWS for signing. ## Method Summary ### getAlgorithm **Signature:** `getAlgorithm() : String` Get the algorithm (alg) from the header. ### getHeader **Signature:** `getHeader() : JWSHeader` Get a copy of the JWS header. ### getHeaderMap **Signature:** `getHeaderMap() : Map` Get a copy of the JWS header as a Map. ### getPayload **Signature:** `getPayload() : String` Get the payload from this object. ### parse **Signature:** `static parse(jws : String) : JWS` Parse a JSON Web Signature (JWS) object from its compact serialization format. ### parse **Signature:** `static parse(jws : String, payload : String) : JWS` Parse a JSON Web Signature (JWS) object from its compact serialization format. ### parse **Signature:** `static parse(jws : String, payload : Bytes) : JWS` Parse a JSON Web Signature (JWS) object from its compact serialization format. ### serialize **Signature:** `serialize(detachPayload : boolean) : String` Get this JWS in compact serialization form. ### sign **Signature:** `sign(keyRef : KeyRef) : void` Sign the payload using the given private key. ### verify **Signature:** `verify(certificateRef : CertificateRef) : boolean` Verifies the signature of the payload. ## Constructor Detail ## Method Detail ## Method Details ### getAlgorithm **Signature:** `getAlgorithm() : String` **Description:** Get the algorithm (alg) from the header. **Returns:** Value of the algorithm or null if missing. --- ### getHeader **Signature:** `getHeader() : JWSHeader` **Description:** Get a copy of the JWS header. **Returns:** Copy of the JWS header. --- ### getHeaderMap **Signature:** `getHeaderMap() : Map` **Description:** Get a copy of the JWS header as a Map. **Returns:** Copy of the JWS header. --- ### getPayload **Signature:** `getPayload() : String` **Description:** Get the payload from this object. This is available even if the signature has not been verified. **Returns:** UTF-8 encoded payload. --- ### parse **Signature:** `static parse(jws : String) : JWS` **Description:** Parse a JSON Web Signature (JWS) object from its compact serialization format. **Parameters:** - `jws`: JWS in compact serialization format. **Returns:** JWS object. --- ### parse **Signature:** `static parse(jws : String, payload : String) : JWS` **Description:** Parse a JSON Web Signature (JWS) object from its compact serialization format. **Parameters:** - `jws`: JWS without a payload in compact serialization format. - `payload`: Detached payload **Returns:** JWS object. --- ### parse **Signature:** `static parse(jws : String, payload : Bytes) : JWS` **Description:** Parse a JSON Web Signature (JWS) object from its compact serialization format. **Parameters:** - `jws`: JWS without a payload in compact serialization format. - `payload`: Detached payload **Returns:** JWS object. --- ### serialize **Signature:** `serialize(detachPayload : boolean) : String` **Description:** Get this JWS in compact serialization form. **Parameters:** - `detachPayload`: true for a detached payload compliant with RFC-7797, or false to serialize the payload too. **Returns:** Compact serialized object. --- ### sign **Signature:** `sign(keyRef : KeyRef) : void` **Description:** Sign the payload using the given private key. The key type and size must match the algorithm given in the JWS header. **Parameters:** - `keyRef`: Reference to the private key. **Throws:** Exception - if there is an error while signing the payload. --- ### verify **Signature:** `verify(certificateRef : CertificateRef) : boolean` **Description:** Verifies the signature of the payload. If the x5c header parameter is present, then that certificate chain will be used to verify the signature and the given certificateRef must be its root certificate. If this parameter is not present then the given certificateRef will be used to directly verify the signature. The following algorithms are supported: ES256 ES256K ES384 ES512 RS256 RS384 RS512 PS256 PS384 PS512 **Parameters:** - `certificateRef`: Reference to the certificate to use for verification. **Returns:** a boolean indicating success (true) or failure (false). **Throws:** Exception - if there is an error while processing the certificate (for example if the x5c is not signed by the given certificate) or the algorithm is unsupported. --- ``` -------------------------------------------------------------------------------- /docs/sfra/request.md: -------------------------------------------------------------------------------- ```markdown # Class Request ## Inheritance Hierarchy - Object - sfra.models.Request ## Description The SFRA Request object is a local wrapper around the global request object that provides enhanced functionality for SFRA (Storefront Reference Architecture) applications. This class translates the global request, customer, and session objects into a more convenient local interface with additional properties and methods. The Request object automatically handles currency setting based on locale, provides easy access to form data and query parameters, and includes customer information in a normalized format. It serves as the primary interface for accessing request-related data in SFRA controllers and provides a consistent API across different types of requests (GET, POST, PUT, etc.). ## Properties ### httpMethod **Type:** String (Read Only) The HTTP method of the request (GET, POST, PUT, DELETE, etc.). ### host **Type:** String (Read Only) The HTTP host header value from the request. ### path **Type:** String (Read Only) The HTTP path portion of the request URL. ### httpHeaders **Type:** Object (Read Only) Collection of HTTP headers from the request. ### https **Type:** Boolean (Read Only) Indicates whether the request was made over HTTPS. ### includeRequest **Type:** Boolean (Read Only) Indicates whether this is an include request (remote include). ### session **Type:** Object (Read Only) Local session object containing privacy cache, currency information, and click stream data. ### httpParameterMap **Type:** dw.web.HttpParameterMap (Read Only) The raw HTTP parameter map from the global request object. ### querystring **Type:** QueryString (Read Only) Parsed query string parameters as a QueryString object. ### form **Type:** Object (Read Only) Normalized form data from the HTTP parameter map, excluding query string parameters. ### body **Type:** String (Read Only) The request body as a string for POST and PUT requests. ### geolocation **Type:** Object (Read Only) Geolocation information including country code, latitude, and longitude. ### currentCustomer **Type:** Object (Read Only) Local customer object containing profile, address book, and wallet information. ### locale **Type:** Object (Read Only) Current locale information including currency details. ### remoteAddress **Type:** String (Read Only) The remote IP address of the client making the request. ### referer **Type:** String (Read Only) The HTTP referer header value. ### pageMetaData **Type:** Object (Read Only) Page metadata object for managing SEO-related information. ## Constructor Summary ### Request **Signature:** `Request(request, customer, session)` Creates a new SFRA Request object from global request, customer, and session objects. **Parameters:** - `request` (Object) - Global request object - `customer` (dw.customer.Customer) - Global customer object - `session` (dw.system.Session) - Global session object ## Method Summary ### setLocale **Signature:** `setLocale(localeID) : Boolean` Sets the locale for the current request. **Parameters:** - `localeID` (String) - The locale ID to set **Returns:** - Boolean indicating success of locale setting ## Method Detail ### setLocale **Signature:** `setLocale(localeID) : Boolean` **Description:** Sets the locale for the current request and returns whether the operation was successful. **Parameters:** - `localeID` (String) - The locale identifier (e.g., "en_US", "fr_FR") **Returns:** Boolean value indicating whether the locale was successfully set. ## Property Details ### session **Type:** Object (Read Only) **Description:** Provides access to session-related information including: - `privacyCache` - Simple cache for session privacy data - `raw` - Reference to the original session object - `currency` - Current currency information with code, digits, name, and symbol - `setCurrency(value)` - Method to update session currency - `clickStream` - Click stream data with clicks array, first/last clicks, and partial flag ### currentCustomer **Type:** Object (Read Only) **Description:** Normalized customer object containing: **For Authenticated Customers:** - `profile` - Customer profile with name, email, phone, and customer number - `addressBook` - Address book with preferred address and addresses array - `wallet` - Payment instruments collection - `raw` - Reference to original customer object **For Unauthenticated Customers:** - `credentials` - Username information - `raw` - Reference to original customer object ### geolocation **Type:** Object (Read Only) **Description:** Geographic location information: - `countryCode` - Two-letter country code - `latitude` - Geographic latitude coordinate - `longitude` - Geographic longitude coordinate ### pageMetaData **Type:** Object (Read Only) **Description:** SEO and page metadata management: - `title` - Page title - `description` - Page description - `keywords` - Page keywords - `pageMetaTags` - Collection of meta tags - `addPageMetaTags(pageMetaTags)` - Method to add meta tags - `setTitle(title)` - Method to set page title - `setDescription(description)` - Method to set page description - `setKeywords(keywords)` - Method to set page keywords --- ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/get-latest-job-log-files.full-mode.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml --- description: "Test get_latest_job_log_files tool in full mode - Optimized for YAML/Aegis testing" tests: # Core functionality test with comprehensive content validation - it: "should retrieve job log files with complete format validation" request: jsonrpc: "2.0" id: "job-files-complete" method: "tools/call" params: name: "get_latest_job_log_files" arguments: limit: 1 expect: response: jsonrpc: "2.0" id: "job-files-complete" result: content: match:arrayElements: type: "text" # Response is JSON-encoded, so match the quoted content with escaped newlines text: "match:regex:\"Found 1 job logs:[\\s\\S]*🔧 Job: [A-Za-z]+[\\s\\S]*ID: [0-9]+[\\s\\S]*File: Job-[A-Za-z]+-[0-9]+\\.log[\\s\\S]*Modified: [A-Za-z]{3}, [0-9]{2} [A-Za-z]{3} [0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} GMT[\\s\\S]*Size: [0-9]+\\.[0-9]+ [A-Z]B\"" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" # Test default behavior (no limit parameter) - it: "should retrieve job log files with default parameters" request: jsonrpc: "2.0" id: "job-files-default" method: "tools/call" params: name: "get_latest_job_log_files" arguments: {} expect: response: jsonrpc: "2.0" id: "job-files-default" result: content: match:arrayElements: type: "text" text: "match:contains:Found" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" # Test limit parameter functionality - it: "should respect limit parameter" request: jsonrpc: "2.0" id: "job-files-limit" method: "tools/call" params: name: "get_latest_job_log_files" arguments: limit: 5 expect: response: jsonrpc: "2.0" id: "job-files-limit" result: content: match:arrayElements: type: "text" text: "match:contains:job logs:" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" # Response structure validation - it: "should return proper MCP response structure" request: jsonrpc: "2.0" id: "job-files-structure" method: "tools/call" params: name: "get_latest_job_log_files" arguments: limit: 1 expect: response: jsonrpc: "2.0" id: "job-files-structure" result: content: "match:type:array" isError: "match:type:boolean" stderr: "toBeEmpty" # Error handling: zero limit - it: "should reject zero limit parameter" request: jsonrpc: "2.0" id: "job-files-zero-limit" method: "tools/call" params: name: "get_latest_job_log_files" arguments: limit: 0 expect: response: jsonrpc: "2.0" id: "job-files-zero-limit" result: content: match:arrayElements: type: "text" text: "match:contains:Invalid limit '0' for tool" isError: true stderr: "toBeEmpty" performance: maxResponseTime: "1000ms" # Error handling: negative limit - it: "should reject negative limit parameter" request: jsonrpc: "2.0" id: "job-files-negative-limit" method: "tools/call" params: name: "get_latest_job_log_files" arguments: limit: -1 expect: response: jsonrpc: "2.0" id: "job-files-negative-limit" result: content: match:arrayElements: type: "text" text: "match:contains:Invalid limit '-1' for tool" isError: true stderr: "toBeEmpty" performance: maxResponseTime: "1000ms" # Error handling: invalid limit type - it: "should reject invalid limit parameter type" request: jsonrpc: "2.0" id: "job-files-invalid-limit" method: "tools/call" params: name: "get_latest_job_log_files" arguments: limit: "invalid" expect: response: jsonrpc: "2.0" id: "job-files-invalid-limit" result: content: match:arrayElements: type: "text" text: "match:contains:Invalid limit 'invalid' for tool. Must be a valid number" isError: true stderr: "toBeEmpty" performance: maxResponseTime: "1000ms" # Performance validation for successful operations - it: "should meet performance requirements for successful operations" request: jsonrpc: "2.0" id: "job-files-performance" method: "tools/call" params: name: "get_latest_job_log_files" arguments: limit: 10 expect: response: jsonrpc: "2.0" id: "job-files-performance" result: content: match:arrayElements: type: "text" text: "match:type:string" isError: false stderr: "toBeEmpty" performance: maxResponseTime: "2000ms" ``` -------------------------------------------------------------------------------- /docs/dw_system/StatusItem.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.system # Class StatusItem ## Inheritance Hierarchy - Object - dw.system.StatusItem ## Description A StatusItem holds all the status information. Multi StatusItems are bundled together into a Status. ## Properties ### code **Type:** String The status code is the unique identifier for the message and can be used by client programs to check for a specific status and to generate a localized message. ### details **Type:** Map (Read Only) The optional details for this StatusItem. ### error **Type:** boolean (Read Only) Returns whether this Status Item represents and error. ### message **Type:** String The default human readable message for this Status. Note: Custom code and client programs must not use this message to identify a specific status. The getCode() must be used for that purpose. The actual message can change from release to release. ### parameters **Type:** List The parameters to construct a custom message. ### status **Type:** Number The status. ## Constructor Summary StatusItem() Constructs a new OK StatusItem. StatusItem(status : Number) Constructs a new StatusItem with the given status. StatusItem(status : Number, code : String) Constructs a new StatusItem with the given status and code. StatusItem(status : Number, code : String, message : String, parameters : Object...) Constructs a new StatusItem with the given values. ## Method Summary ### addDetail **Signature:** `addDetail(key : String, value : Object) : void` Add an additional detail to this StatusItem. ### getCode **Signature:** `getCode() : String` The status code is the unique identifier for the message and can be used by client programs to check for a specific status and to generate a localized message. ### getDetails **Signature:** `getDetails() : Map` Returns the optional details for this StatusItem. ### getMessage **Signature:** `getMessage() : String` Returns the default human readable message for this Status. ### getParameters **Signature:** `getParameters() : List` Returns the parameters to construct a custom message. ### getStatus **Signature:** `getStatus() : Number` Returns the status. ### isError **Signature:** `isError() : boolean` Returns whether this Status Item represents and error. ### setCode **Signature:** `setCode(code : String) : void` Method to set the status code. ### setMessage **Signature:** `setMessage(message : String) : void` Sets the default human readable message for this Status. ### setParameters **Signature:** `setParameters(parameters : Object...) : void` Sets the parameters for a custom message. ### setStatus **Signature:** `setStatus(status : Number) : void` Set the status. ## Constructor Detail ## Method Detail ## Method Details ### addDetail **Signature:** `addDetail(key : String, value : Object) : void` **Description:** Add an additional detail to this StatusItem. **Parameters:** - `key`: the key for the detail. - `value`: the detail value. --- ### getCode **Signature:** `getCode() : String` **Description:** The status code is the unique identifier for the message and can be used by client programs to check for a specific status and to generate a localized message. **Returns:** the status code. --- ### getDetails **Signature:** `getDetails() : Map` **Description:** Returns the optional details for this StatusItem. **Returns:** the optional details for this StatusItem. --- ### getMessage **Signature:** `getMessage() : String` **Description:** Returns the default human readable message for this Status. Note: Custom code and client programs must not use this message to identify a specific status. The getCode() must be used for that purpose. The actual message can change from release to release. **Returns:** the default human readable message for this Status. --- ### getParameters **Signature:** `getParameters() : List` **Description:** Returns the parameters to construct a custom message. **Returns:** the parameters to construct a custom message. --- ### getStatus **Signature:** `getStatus() : Number` **Description:** Returns the status. **Returns:** either Status.OK or Status.ERROR. --- ### isError **Signature:** `isError() : boolean` **Description:** Returns whether this Status Item represents and error. **Returns:** true is this item represents an error, false otherwise. --- ### setCode **Signature:** `setCode(code : String) : void` **Description:** Method to set the status code. The status code is the unique identifier for the message and can be used by client programs to check for a specific status and to generate a localized message. **Parameters:** - `code`: the status code. --- ### setMessage **Signature:** `setMessage(message : String) : void` **Description:** Sets the default human readable message for this Status. **Parameters:** - `message`: the default human readable message for this Status. --- ### setParameters **Signature:** `setParameters(parameters : Object...) : void` **Description:** Sets the parameters for a custom message. **Parameters:** - `parameters`: the parameters for a custom message. --- ### setStatus **Signature:** `setStatus(status : Number) : void` **Description:** Set the status. **Parameters:** - `status`: either Status.OK or Status.ERROR. --- ``` -------------------------------------------------------------------------------- /docs/dw_catalog/PriceBookMgr.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.catalog # Class PriceBookMgr ## Inheritance Hierarchy - Object - dw.catalog.PriceBookMgr ## Description Price book manager provides methods to access price books. ## Properties ### allPriceBooks **Type:** Collection (Read Only) All price books defined for the organization. ### applicablePriceBooks **Type:** Collection A collection of price books that are set in the user session. ### sitePriceBooks **Type:** Collection (Read Only) All price books assigned to the current site. Please note that this doesn't include parent price books not assigned to the site, but considered by the price lookup. ## Constructor Summary ## Method Summary ### assignPriceBookToSite **Signature:** `static assignPriceBookToSite(priceBook : PriceBook, siteId : String) : boolean` Assign a price book to a site. ### getAllPriceBooks **Signature:** `static getAllPriceBooks() : Collection` Returns all price books defined for the organization. ### getApplicablePriceBooks **Signature:** `static getApplicablePriceBooks() : Collection` Returns a collection of price books that are set in the user session. ### getPriceBook **Signature:** `static getPriceBook(priceBookID : String) : PriceBook` Returns the price book of the current organization matching the specified ID. ### getSitePriceBooks **Signature:** `static getSitePriceBooks() : Collection` Returns all price books assigned to the current site. ### setApplicablePriceBooks **Signature:** `static setApplicablePriceBooks(priceBooks : PriceBook...) : void` Sets one or more price books to be considered by the product price lookup. ### unassignPriceBookFromAllSites **Signature:** `static unassignPriceBookFromAllSites(priceBook : PriceBook) : boolean` Unassign a price book from all sites. ### unassignPriceBookFromSite **Signature:** `static unassignPriceBookFromSite(priceBook : PriceBook, siteId : String) : boolean` Unassign a price book from a site. ## Method Detail ## Method Details ### assignPriceBookToSite **Signature:** `static assignPriceBookToSite(priceBook : PriceBook, siteId : String) : boolean` **Description:** Assign a price book to a site. This requires a transaction, see Transaction.wrap(Function) **Parameters:** - `priceBook`: price book to be assigned - `siteId`: id of the site to be assigned to, such as 'SiteGenesis'. The site has to be a storefront site. **Returns:** true if price book is assigned to site. Throws an exception if price book doesn't exist or site doesn't exist or site is not a storefront site. --- ### getAllPriceBooks **Signature:** `static getAllPriceBooks() : Collection` **Description:** Returns all price books defined for the organization. **Returns:** All price books of the organization. --- ### getApplicablePriceBooks **Signature:** `static getApplicablePriceBooks() : Collection` **Description:** Returns a collection of price books that are set in the user session. **Returns:** Collection of applicable price books set in the session. --- ### getPriceBook **Signature:** `static getPriceBook(priceBookID : String) : PriceBook` **Description:** Returns the price book of the current organization matching the specified ID. **Parameters:** - `priceBookID`: The price book id. **Returns:** Price book or null of not found --- ### getSitePriceBooks **Signature:** `static getSitePriceBooks() : Collection` **Description:** Returns all price books assigned to the current site. Please note that this doesn't include parent price books not assigned to the site, but considered by the price lookup. **Returns:** All price books assigned to the current site. --- ### setApplicablePriceBooks **Signature:** `static setApplicablePriceBooks(priceBooks : PriceBook...) : void` **Description:** Sets one or more price books to be considered by the product price lookup. The information is stored in the user session. If no price book is set in the user session, all active and valid price books assigned to the site are used for the price lookup. If price books are set, only those price books are considered by the price lookup. Note that the system does not assure that a price book set by this API is assigned to the current site. **Parameters:** - `priceBooks`: The price books that are set in the session as applicable price books. --- ### unassignPriceBookFromAllSites **Signature:** `static unassignPriceBookFromAllSites(priceBook : PriceBook) : boolean` **Description:** Unassign a price book from all sites. This requires a transaction, see Transaction.wrap(Function) **Parameters:** - `priceBook`: price book to be unassigned **Returns:** true if price book is unassigned from all sites. Throws an exception if price book doesn't exist --- ### unassignPriceBookFromSite **Signature:** `static unassignPriceBookFromSite(priceBook : PriceBook, siteId : String) : boolean` **Description:** Unassign a price book from a site. This requires a transaction, see Transaction.wrap(Function) **Parameters:** - `priceBook`: price book to be unassigned - `siteId`: id of the site to be unassigned from, such as 'SiteGenesis'. The site has to be a storefront site. **Returns:** true if price book is unassigned from site. Throws an exception if price book doesn't exist or site doesn't exist or site is not a storefront site. --- ``` -------------------------------------------------------------------------------- /docs/dw_crypto/Mac.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.crypto # Class Mac ## Inheritance Hierarchy - Object - dw.crypto.Mac ## Description This class provides the functionality of a "Message Authentication Code" (MAC) algorithm. A MAC provides a way to check the integrity of information transmitted over or stored in an unreliable medium, based on a secret key. Typically, message authentication codes are used between two parties that share a secret key in order to validate information transmitted between these parties. A MAC mechanism that is based on cryptographic hash functions is referred to as HMAC. HMAC can be used with any cryptographic hash function, e.g., SHA256, in combination with a secret shared key. HMAC is specified in RFC 2104. Note: this class handles sensitive security-related data. Pay special attention to PCI DSS v3. requirements 2, 4, and 12. ## Constants ### HMAC_MD5 **Type:** String = "HmacMD5" Constant representing the HMAC-MD5 keyed-hashing algorithm as defined in RFC 2104 "HMAC: Keyed-Hashing for Message Authentication" (February 1997). This algorithm uses as MD5 cryptographic hash function. ### HMAC_SHA_1 **Type:** String = "HmacSHA1" Constant representing the HmacSHA1 algorithms as defined in RFC 2104 "HMAC: Keyed-Hashing for Message Authentication" (February 1997) with SHA-1 as the message digest algorithm. ### HMAC_SHA_256 **Type:** String = "HmacSHA256" Constant representing the HmacSHA256 algorithms as defined in RFC 2104 "HMAC: Keyed-Hashing for Message Authentication" (February 1997) with SHA-256 as the message digest algorithm. ### HMAC_SHA_384 **Type:** String = "HmacSHA384" Constant representing the HmacSHA384 algorithms as defined in RFC 2104 "HMAC: Keyed-Hashing for Message Authentication" (February 1997) with SHA-384 as the message digest algorithm. ### HMAC_SHA_512 **Type:** String = "HmacSHA512" Constant representing the HmacSHA512 algorithms as defined in RFC 2104 "HMAC: Keyed-Hashing for Message Authentication" (February 1997) with SHA-512 as the message digest algorithm. ## Properties ## Constructor Summary Mac(algorithm : String) Construct a Mac encryption instance with the specified algorithm name. ## Method Summary ### digest **Signature:** `digest(input : String, key : String) : Bytes` Computes the hash value for the passed string input using the passed secret key. ### digest **Signature:** `digest(input : String, key : Bytes) : Bytes` Computes the hash value for the passed string input using the passed secret key. ### digest **Signature:** `digest(input : Bytes, key : Bytes) : Bytes` Computes the hash value for the passed bytes input using the passed secret key. ## Constructor Detail ## Method Detail ## Method Details ### digest **Signature:** `digest(input : String, key : String) : Bytes` **Description:** Computes the hash value for the passed string input using the passed secret key. Given input and the given key will be first converted with UTF-8 encoding into a byte array. The resulting hash is typically converted with base64 back into a string. **Parameters:** - `input`: A string to calculate a RFC 2104 compliant HMAC hash value for. - `key`: The secret key ready for use with the algorithm. The key's format depends on the chosen algorithm and the keys are assumed to be correctly formulated for the algorithm used, for example that the lengths are correct. Keys are not checked for validity. Only such keys that have no key parameters associated with them. **Returns:** The resulting hash value as bytes. **Throws:** IllegalArgumentException - if algorithm is not null and the specified algorithm name is not supported. --- ### digest **Signature:** `digest(input : String, key : Bytes) : Bytes` **Description:** Computes the hash value for the passed string input using the passed secret key. Given input will be first converted with UTF-8 encoding into a byte array. The resulting hash is typically converted with base64 back into a string. **Parameters:** - `input`: A string to calculate a RFC 2104 compliant HMAC hash value for. - `key`: The secret key as bytes ready for use with the algorithm. The key's format depends on the chosen algorithm and the keys are assumed to be correctly formulated for the algorithm used, for example that the lengths are correct. Keys are not checked for validity. Only such keys that have no key parameters associated with them. **Returns:** The resulting hash value as bytes. **Throws:** IllegalArgumentException - if algorithm is not null and the specified algorithm name is not supported. --- ### digest **Signature:** `digest(input : Bytes, key : Bytes) : Bytes` **Description:** Computes the hash value for the passed bytes input using the passed secret key. **Parameters:** - `input`: The bytes to calculate a RFC 2104 compliant HMAC hash value. - `key`: The secret key as byte array ready for use with the algorithm. The key's format depends on the chosen algorithm and the keys are assumed to be correctly formulated for the algorithm used, for example that the lengths are correct. Keys are not checked for validity. Only such keys that have no key parameters associated with them. **Returns:** The resulting hash value as bytes. **Throws:** IllegalArgumentException - if algorithm is not null and the specified algorithm name is not supported. --- ``` -------------------------------------------------------------------------------- /tests/servers/sfcc-mock-server/mock-data/ocapi/site-preferences-system.json: -------------------------------------------------------------------------------- ```json { "_v": "23.2", "_type": "preference_value_search_result", "count": 3, "hits": [ { "_type": "preference_value", "attribute_definition": { "_type": "object_attribute_definition", "_resource_state": "system1-resource-state", "creation_date": "2024-01-15T10:30:00.000Z", "description": { "default": "Global system configuration for payment processing" }, "display_name": { "default": "System Payment Gateway URL" }, "effective_id": "c_systemPaymentGatewayUrl", "externally_defined": false, "externally_managed": false, "id": "systemPaymentGatewayUrl", "key": false, "last_modified": "2024-01-15T10:30:00.000Z", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/SitePreferences/attribute_definitions/systemPaymentGatewayUrl", "localizable": false, "mandatory": true, "multi_value_type": false, "order_required": false, "queryable": false, "read_only": false, "requires_encoding": false, "searchable": false, "set_value_type": false, "site_specific": true, "system": false, "value_type": "string", "visible": true }, "description": { "default": "Global system configuration for payment processing" }, "display_name": { "default": "System Payment Gateway URL" }, "id": "systemPaymentGatewayUrl", "site_values": { "RefArch": "https://payments.example.com/api", "RefArchGlobal": "https://payments-global.example.com/api", "pxl_1": null, "pxl_2": null, "pxl_3": null, "pxl_4": null, "pxl_5": null, "pxl_6": null }, "value_type": "string" }, { "_type": "preference_value", "attribute_definition": { "_type": "object_attribute_definition", "_resource_state": "system2-resource-state", "creation_date": "2024-01-15T10:30:00.000Z", "description": { "default": "Enable debug logging for system operations" }, "display_name": { "default": "System Debug Enabled" }, "effective_id": "c_systemDebugEnabled", "externally_defined": false, "externally_managed": false, "id": "systemDebugEnabled", "key": false, "last_modified": "2024-01-15T10:30:00.000Z", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/SitePreferences/attribute_definitions/systemDebugEnabled", "localizable": false, "mandatory": false, "multi_value_type": false, "order_required": false, "queryable": false, "read_only": false, "requires_encoding": false, "searchable": false, "set_value_type": false, "site_specific": true, "system": false, "value_type": "boolean", "visible": true }, "description": { "default": "Enable debug logging for system operations" }, "display_name": { "default": "System Debug Enabled" }, "id": "systemDebugEnabled", "site_values": { "RefArch": false, "RefArchGlobal": true, "pxl_1": null, "pxl_2": null, "pxl_3": null, "pxl_4": null, "pxl_5": null, "pxl_6": null }, "value_type": "boolean" }, { "_type": "preference_value", "attribute_definition": { "_type": "object_attribute_definition", "_resource_state": "system3-resource-state", "creation_date": "2024-01-15T10:30:00.000Z", "description": { "default": "Maximum number of concurrent system operations" }, "display_name": { "default": "System Max Concurrent Operations" }, "effective_id": "c_systemMaxConcurrentOps", "externally_defined": false, "externally_managed": false, "id": "systemMaxConcurrentOps", "key": false, "last_modified": "2024-01-15T10:30:00.000Z", "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/SitePreferences/attribute_definitions/systemMaxConcurrentOps", "localizable": false, "mandatory": false, "multi_value_type": false, "order_required": false, "queryable": false, "read_only": false, "requires_encoding": false, "searchable": false, "set_value_type": false, "site_specific": false, "system": false, "value_type": "int", "visible": true }, "description": { "default": "Maximum number of concurrent system operations" }, "display_name": { "default": "System Max Concurrent Operations" }, "id": "systemMaxConcurrentOps", "site_values": { "RefArch": 10, "RefArchGlobal": 50, "pxl_1": null, "pxl_2": null, "pxl_3": null, "pxl_4": null, "pxl_5": null, "pxl_6": null }, "value_type": "int" } ], "query": { "match_all_query": { "_type": "match_all_query" } }, "select": "(**)", "start": 0, "total": 3 } ``` -------------------------------------------------------------------------------- /docs/dw_order/GiftCertificateMgr.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order # Class GiftCertificateMgr ## Inheritance Hierarchy - Object - dw.order.GiftCertificateMgr ## Description The GiftCertificateMgr class contains a set of static methods for interacting with GiftCertificates. ## Constants ### GC_ERROR_DISABLED **Type:** String = "GIFTCERTIFICATE-100" Indicates that an error occurred because the Gift Certificate is currently disabled. ### GC_ERROR_INSUFFICIENT_BALANCE **Type:** String = "GIFTCERTIFICATE-110" Indicates that an error occurred because the Gift Certificate does not have a sufficient balance to perform the requested operation. ### GC_ERROR_INVALID_AMOUNT **Type:** String = "GIFTCERTIFICATE-140" Indicates that an error occurred because the Gift Certificate Amount was not valid. ### GC_ERROR_INVALID_CODE **Type:** String = "GIFTCERTIFICATE-150" Indicates that an error occurred because the Gift Certificate ID was not valid. ### GC_ERROR_PENDING **Type:** String = "GIFTCERTIFICATE-130" Indicates that an error occurred because the Gift Certificate has been fully redeemed. ### GC_ERROR_REDEEMED **Type:** String = "GIFTCERTIFICATE-120" Indicates that an error occurred because the Gift Certificate has been fully redeemed. ## Properties ## Constructor Summary ## Method Summary ### createGiftCertificate **Signature:** `static createGiftCertificate(amount : Number, code : String) : GiftCertificate` Creates a Gift Certificate. ### createGiftCertificate **Signature:** `static createGiftCertificate(amount : Number) : GiftCertificate` Creates a Gift Certificate. ### getGiftCertificate **Signature:** `static getGiftCertificate(giftCertificateCode : String) : GiftCertificate` Returns the Gift Certificate identified by the specified gift certificate code. ### getGiftCertificateByCode **Signature:** `static getGiftCertificateByCode(giftCertificateCode : String) : GiftCertificate` Returns the Gift Certificate identified by the specified gift certificate code. ### getGiftCertificateByMerchantID **Signature:** `static getGiftCertificateByMerchantID(merchantID : String) : GiftCertificate` Returns the Gift Certificate identified by the specified merchant ID. ### redeemGiftCertificate **Signature:** `static redeemGiftCertificate(paymentInstrument : OrderPaymentInstrument) : Status` Redeems an amount from a Gift Certificate. ## Method Detail ## Method Details ### createGiftCertificate **Signature:** `static createGiftCertificate(amount : Number, code : String) : GiftCertificate` **Description:** Creates a Gift Certificate. If a non-empty Gift Certificate code is specified, the code will be used to create the Gift Certificate. Be aware that this code must be unique for the current site. If it is not unique, the Gift Certificate will not be created. **Parameters:** - `amount`: the amount of the gift certificate. Must not be negative or zero. - `code`: the code for the new gift certificate. If parameter is null or empty , the system will assign a code to the new gift certificate. **Returns:** the newly created Gift Certificate. --- ### createGiftCertificate **Signature:** `static createGiftCertificate(amount : Number) : GiftCertificate` **Description:** Creates a Gift Certificate. The system will assign a code to the new Gift Certificate. **Parameters:** - `amount`: the amount of the gift certificate. Must not be negative or zero. **Returns:** the newly created Gift Certificate. --- ### getGiftCertificate **Signature:** `static getGiftCertificate(giftCertificateCode : String) : GiftCertificate` **Description:** Returns the Gift Certificate identified by the specified gift certificate code. **Deprecated:** Use getGiftCertificateByCode(String) **Parameters:** - `giftCertificateCode`: to identify the Gift Certificate. **Returns:** the Gift Certificate identified by the specified code or null. --- ### getGiftCertificateByCode **Signature:** `static getGiftCertificateByCode(giftCertificateCode : String) : GiftCertificate` **Description:** Returns the Gift Certificate identified by the specified gift certificate code. **Parameters:** - `giftCertificateCode`: to identify the Gift Certificate. **Returns:** the Gift Certificate identified by the specified code or null. --- ### getGiftCertificateByMerchantID **Signature:** `static getGiftCertificateByMerchantID(merchantID : String) : GiftCertificate` **Description:** Returns the Gift Certificate identified by the specified merchant ID. **Parameters:** - `merchantID`: to identify the Gift Certificate. **Returns:** the Gift Certificate identified by the specified merchant ID or null. --- ### redeemGiftCertificate **Signature:** `static redeemGiftCertificate(paymentInstrument : OrderPaymentInstrument) : Status` **Description:** Redeems an amount from a Gift Certificate. The Gift Certificate ID is specified in the OrderPaymentInstrument and the amount specified in the PaymentTransaction associated with the OrderPaymentInstrument. If the PaymentTransaction.getTransactionID() is not null, the value returned by this method is used as the 'Order Number' for the redemption transaction. The 'Order Number' is visible via the Business Manager. **Parameters:** - `paymentInstrument`: the OrderPaymentInstrument containing the ID of the Gift Certificate to redeem, and the amount of the redemption. **Returns:** the status of the redemption operation. --- ``` -------------------------------------------------------------------------------- /docs/dw_svc/Result.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.svc # Class Result ## Inheritance Hierarchy - Object - dw.svc.Result ## Description Represents the result of a service call. ## Constants ### ERROR **Type:** String = "ERROR" Status indicating a general service error. ### OK **Type:** String = "OK" Status indicating a successful service call. ### SERVICE_UNAVAILABLE **Type:** String = "SERVICE_UNAVAILABLE" Status indicating the service is unavailable. This includes timeouts, rate limits, and remote server issues. ### UNAVAILABLE_CIRCUIT_BROKEN **Type:** String = "CIRCUIT_BROKEN" Unavailable reason: No call was made because the circuit breaker prevented it. ### UNAVAILABLE_CONFIG_PROBLEM **Type:** String = "CONFIG_PROBLEM" Unavailable reason: No call was made because the service was not configured correctly. ### UNAVAILABLE_DISABLED **Type:** String = "DISABLED" Unavailable reason: No call was made because the service is disabled. ### UNAVAILABLE_RATE_LIMITED **Type:** String = "RATE_LIMITED" Unavailable reason: No call was made because the rate limit was hit. ### UNAVAILABLE_TIMEOUT **Type:** String = "TIMEOUT" Unavailable reason: A real call was made but a timeout occurred. ## Properties ### error **Type:** Number (Read Only) An error-specific code if applicable. For example, this is the HTTP response code for an HTTPService. ### errorMessage **Type:** String (Read Only) An error message on a non-OK status. ### mockResult **Type:** boolean (Read Only) The status of whether the response is the result of a "mock" service call. ### msg **Type:** String (Read Only) An extra error message on failure (if any). ### object **Type:** Object (Read Only) The actual object returned by the service when the status is OK. ### ok **Type:** boolean (Read Only) The status of whether the service call was successful. ### status **Type:** String (Read Only) The status. This is "OK" on success. Failure codes include "ERROR" and "SERVICE_UNAVAILABLE". If the status is "SERVICE_UNAVAILABLE", then the unavailableReason is guaranteed to be non-null. ### unavailableReason **Type:** String (Read Only) The reason the status is SERVICE_UNAVAILABLE. ## Constructor Summary Result() Constructs a new result instance. ## Method Summary ### getError **Signature:** `getError() : Number` Returns an error-specific code if applicable. ### getErrorMessage **Signature:** `getErrorMessage() : String` Returns an error message on a non-OK status. ### getMsg **Signature:** `getMsg() : String` Returns an extra error message on failure (if any). ### getObject **Signature:** `getObject() : Object` Returns the actual object returned by the service when the status is OK. ### getStatus **Signature:** `getStatus() : String` Returns the status. ### getUnavailableReason **Signature:** `getUnavailableReason() : String` Returns the reason the status is SERVICE_UNAVAILABLE. ### isMockResult **Signature:** `isMockResult() : boolean` Returns the status of whether the response is the result of a "mock" service call. ### isOk **Signature:** `isOk() : boolean` Returns the status of whether the service call was successful. ### toString **Signature:** `toString() : String` Returns a string representation of the result. ## Constructor Detail ## Method Detail ## Method Details ### getError **Signature:** `getError() : Number` **Description:** Returns an error-specific code if applicable. For example, this is the HTTP response code for an HTTPService. **Returns:** Error-specific code (if applicable). --- ### getErrorMessage **Signature:** `getErrorMessage() : String` **Description:** Returns an error message on a non-OK status. **Returns:** Error message. --- ### getMsg **Signature:** `getMsg() : String` **Description:** Returns an extra error message on failure (if any). **Returns:** Error message, or null. --- ### getObject **Signature:** `getObject() : Object` **Description:** Returns the actual object returned by the service when the status is OK. **Returns:** Object returned by the service. --- ### getStatus **Signature:** `getStatus() : String` **Description:** Returns the status. This is "OK" on success. Failure codes include "ERROR" and "SERVICE_UNAVAILABLE". If the status is "SERVICE_UNAVAILABLE", then the unavailableReason is guaranteed to be non-null. **Returns:** Status code. **See Also:** OK ERROR SERVICE_UNAVAILABLE --- ### getUnavailableReason **Signature:** `getUnavailableReason() : String` **Description:** Returns the reason the status is SERVICE_UNAVAILABLE. **Returns:** Unavailable reason code, or null if the status is not SERVICE_UNAVAILABLE. **See Also:** UNAVAILABLE_TIMEOUT UNAVAILABLE_CIRCUIT_BROKEN UNAVAILABLE_RATE_LIMITED UNAVAILABLE_DISABLED UNAVAILABLE_CONFIG_PROBLEM --- ### isMockResult **Signature:** `isMockResult() : boolean` **Description:** Returns the status of whether the response is the result of a "mock" service call. **Returns:** true if this was a mock service call, false otherwise. --- ### isOk **Signature:** `isOk() : boolean` **Description:** Returns the status of whether the service call was successful. **Returns:** true on success, false otherwise. --- ### toString **Signature:** `toString() : String` **Description:** Returns a string representation of the result. **Returns:** a string representation of the result. --- ``` -------------------------------------------------------------------------------- /docs/dw_system/Log.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.system # Class Log ## Inheritance Hierarchy - Object - dw.system.Log ## Description A log4j like logger instance. To obtain such an instance, use the Logger.getRootLogger() or Logger.getLogger(String) or Logger.getLogger(String, String) methods. ## Properties ### debugEnabled **Type:** boolean (Read Only) This method returns true if debug logging is enabled for this logging instance. ### errorEnabled **Type:** boolean (Read Only) This method returns true if error logging is enabled for this logging instance. ### infoEnabled **Type:** boolean (Read Only) This method returns true if information logging is enabled for this logging instance. ### NDC **Type:** LogNDC (Read Only) The Nested Diagnostic Context for this script call. ### warnEnabled **Type:** boolean (Read Only) This method returns true if warning logging is enabled for this logging instance. ## Constructor Summary ## Method Summary ### debug **Signature:** `debug(msg : String, args : Object...) : void` The method reports an debug level message. ### error **Signature:** `error(msg : String, args : Object...) : void` The method reports an error level message. ### fatal **Signature:** `fatal(msg : String, args : Object...) : void` The method reports an warning level message. ### getNDC **Signature:** `static getNDC() : LogNDC` Returns the Nested Diagnostic Context for this script call. ### info **Signature:** `info(msg : String, args : Object...) : void` The method reports an information level message. ### isDebugEnabled **Signature:** `isDebugEnabled() : boolean` This method returns true if debug logging is enabled for this logging instance. ### isErrorEnabled **Signature:** `isErrorEnabled() : boolean` This method returns true if error logging is enabled for this logging instance. ### isInfoEnabled **Signature:** `isInfoEnabled() : boolean` This method returns true if information logging is enabled for this logging instance. ### isWarnEnabled **Signature:** `isWarnEnabled() : boolean` This method returns true if warning logging is enabled for this logging instance. ### warn **Signature:** `warn(msg : String, args : Object...) : void` The method reports an warning level message. ## Method Detail ## Method Details ### debug **Signature:** `debug(msg : String, args : Object...) : void` **Description:** The method reports an debug level message. Arguments can be embedded into the message, e.g. like "Failure {0} in {1}". The method implements the Java MessageFormat.format() syntax. **Parameters:** - `msg`: the message to log. - `args`: the arguments to insert into the message. --- ### error **Signature:** `error(msg : String, args : Object...) : void` **Description:** The method reports an error level message. Arguments can be embedded into the message, e.g. like "Failure {0} in {1}". The method implements the Java MessageFormat.format() syntax. **Parameters:** - `msg`: the message to log. - `args`: the arguments to insert into the message. --- ### fatal **Signature:** `fatal(msg : String, args : Object...) : void` **Description:** The method reports an warning level message. Arguments can be embedded into the message, e.g. like "Failure {0} in {1}". The method implements the Java MessageFormat.format() syntax. Note: Fatal log messages are always enabled and optionally send via E-Mail. **Parameters:** - `msg`: the message to log. - `args`: the arguments to insert into the message. --- ### getNDC **Signature:** `static getNDC() : LogNDC` **Description:** Returns the Nested Diagnostic Context for this script call. **Returns:** the nested diagnostic context --- ### info **Signature:** `info(msg : String, args : Object...) : void` **Description:** The method reports an information level message. Arguments can be embedded into the message, e.g. like "Failure {0} in {1}". The method implements the Java MessageFormat.format() syntax. **Parameters:** - `msg`: the message to log. - `args`: the arguments to insert into the message. --- ### isDebugEnabled **Signature:** `isDebugEnabled() : boolean` **Description:** This method returns true if debug logging is enabled for this logging instance. **Returns:** true if logging of debug messages is enabled, false otherwise. --- ### isErrorEnabled **Signature:** `isErrorEnabled() : boolean` **Description:** This method returns true if error logging is enabled for this logging instance. **Returns:** true if logging of error messages is enabled, false otherwise. --- ### isInfoEnabled **Signature:** `isInfoEnabled() : boolean` **Description:** This method returns true if information logging is enabled for this logging instance. **Returns:** true if logging of information messages is enabled, false otherwise. --- ### isWarnEnabled **Signature:** `isWarnEnabled() : boolean` **Description:** This method returns true if warning logging is enabled for this logging instance. **Returns:** true if logging of warning messages is enabled, false otherwise. --- ### warn **Signature:** `warn(msg : String, args : Object...) : void` **Description:** The method reports an warning level message. Arguments can be embedded into the message, e.g. like "Failure {0} in {1}". The method implements the Java MessageFormat.format() syntax. **Parameters:** - `msg`: the message to log. - `args`: the arguments to insert into the message. --- ``` -------------------------------------------------------------------------------- /docs/dw_order/ShippingMethod.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order # Class ShippingMethod ## Inheritance Hierarchy - Object - dw.object.PersistentObject - dw.object.ExtensibleObject - dw.order.ShippingMethod ## Description ShippingMethod represents how the shipment will be shipped. ## Properties ### baseMethod **Type:** ShippingMethod (Read Only) The base shipping method or null if undefined. ### currencyCode **Type:** String (Read Only) The currency code associated with the shipping method ### customerGroups **Type:** Collection (Read Only) The customer groups assigned to the shipping method. Assigned ids that do not belong to an existing customer group are ignored. ### defaultMethod **Type:** boolean (Read Only) Returns 'true' if the shipping method is marked as 'default' for the current session's currency. Otherwise 'false' is returned. ### dependentMethods **Type:** Collection (Read Only) The dependent shipping methods of this shipping method, regardless of the online status of the methods. Dependent shipping methods have this method as their base method. ### description **Type:** String (Read Only) The description of the shipping method as specified in the current locale or null if it could not be found. ### displayName **Type:** String (Read Only) The display name of the shipping method in the current locale or null if it could not be found. ### ID **Type:** String (Read Only) The ID of the shipping method. ### online **Type:** boolean (Read Only) Returns true if shipping method is online, false otherwise ### taxClassID **Type:** String (Read Only) The tax class id of the shipping method. ## Constructor Summary ## Method Summary ### getBaseMethod **Signature:** `getBaseMethod() : ShippingMethod` Returns the base shipping method or null if undefined. ### getCurrencyCode **Signature:** `getCurrencyCode() : String` Returns the currency code associated with the shipping method ### getCustomerGroups **Signature:** `getCustomerGroups() : Collection` Returns the customer groups assigned to the shipping method. ### getDependentMethods **Signature:** `getDependentMethods() : Collection` Returns the dependent shipping methods of this shipping method, regardless of the online status of the methods. ### getDescription **Signature:** `getDescription() : String` Returns the description of the shipping method as specified in the current locale or null if it could not be found. ### getDisplayName **Signature:** `getDisplayName() : String` Returns the display name of the shipping method in the current locale or null if it could not be found. ### getID **Signature:** `getID() : String` Returns the ID of the shipping method. ### getTaxClassID **Signature:** `getTaxClassID() : String` Returns the tax class id of the shipping method. ### isDefaultMethod **Signature:** `isDefaultMethod() : boolean` Returns 'true' if the shipping method is marked as 'default' for the current session's currency. ### isOnline **Signature:** `isOnline() : boolean` Returns true if shipping method is online, false otherwise ## Method Detail ## Method Details ### getBaseMethod **Signature:** `getBaseMethod() : ShippingMethod` **Description:** Returns the base shipping method or null if undefined. **Returns:** Base shipping method --- ### getCurrencyCode **Signature:** `getCurrencyCode() : String` **Description:** Returns the currency code associated with the shipping method **Returns:** currency code --- ### getCustomerGroups **Signature:** `getCustomerGroups() : Collection` **Description:** Returns the customer groups assigned to the shipping method. Assigned ids that do not belong to an existing customer group are ignored. **Returns:** customer groups --- ### getDependentMethods **Signature:** `getDependentMethods() : Collection` **Description:** Returns the dependent shipping methods of this shipping method, regardless of the online status of the methods. Dependent shipping methods have this method as their base method. **Returns:** Dependent shipping methods --- ### getDescription **Signature:** `getDescription() : String` **Description:** Returns the description of the shipping method as specified in the current locale or null if it could not be found. **Returns:** he description of the shipping method as specified in the current locale or null if it could not be found. --- ### getDisplayName **Signature:** `getDisplayName() : String` **Description:** Returns the display name of the shipping method in the current locale or null if it could not be found. **Returns:** the display name of the shipping method or null if it could not be found. --- ### getID **Signature:** `getID() : String` **Description:** Returns the ID of the shipping method. **Returns:** the ID of the shipping method. --- ### getTaxClassID **Signature:** `getTaxClassID() : String` **Description:** Returns the tax class id of the shipping method. **Returns:** the tax class id of the shipping method. --- ### isDefaultMethod **Signature:** `isDefaultMethod() : boolean` **Description:** Returns 'true' if the shipping method is marked as 'default' for the current session's currency. Otherwise 'false' is returned. **Returns:** 'true' if it is the default shipping method of the site --- ### isOnline **Signature:** `isOnline() : boolean` **Description:** Returns true if shipping method is online, false otherwise --- ``` -------------------------------------------------------------------------------- /docs/dw_order/TrackingInfo.md: -------------------------------------------------------------------------------- ```markdown ## Package: dw.order # Class TrackingInfo ## Inheritance Hierarchy - Object - dw.object.Extensible - dw.order.TrackingInfo ## Description Provides basic information about a tracking info. An instance is identified by an ID and can be referenced from n ShippingOrderItems using TrackingRefs. This also allows one ShippingOrderItem to be associated with n TrackingInfo. ## Properties ### carrier **Type:** String Get the Carrier. ### carrierService **Type:** String Get the service(ship method) of the used carrier. ### ID **Type:** String (Read Only) Get the mandatory identifier for this tracking information. The id allows the tracking information to be referenced from TrackingRefs. To support short shipping a shipping-order-item can manage a list of TrackingRefs, each with an optional quantity value allowing individual items to ship in multiple parcels with known item quantity in each. ### shipDate **Type:** Date Get the ship date. ### shippingOrder **Type:** ShippingOrder (Read Only) Gets the shipping order. ### trackingNumber **Type:** String Get the tracking number. ### trackingRefs **Type:** Collection (Read Only) Gets the tracking refs (shipping order items) which are assigned to this tracking info. ### warehouseID **Type:** String Get the id of the shipping warehouse. ## Constructor Summary ## Method Summary ### getCarrier **Signature:** `getCarrier() : String` Get the Carrier. ### getCarrierService **Signature:** `getCarrierService() : String` Get the service(ship method) of the used carrier. ### getID **Signature:** `getID() : String` Get the mandatory identifier for this tracking information. ### getShipDate **Signature:** `getShipDate() : Date` Get the ship date. ### getShippingOrder **Signature:** `getShippingOrder() : ShippingOrder` Gets the shipping order. ### getTrackingNumber **Signature:** `getTrackingNumber() : String` Get the tracking number. ### getTrackingRefs **Signature:** `getTrackingRefs() : Collection` Gets the tracking refs (shipping order items) which are assigned to this tracking info. ### getWarehouseID **Signature:** `getWarehouseID() : String` Get the id of the shipping warehouse. ### setCarrier **Signature:** `setCarrier(carrier : String) : void` Set the Carrier. ### setCarrierService **Signature:** `setCarrierService(carrierService : String) : void` Set the service(ship method) of the used carrier. ### setShipDate **Signature:** `setShipDate(shipDate : Date) : void` Set the ship date. ### setTrackingNumber **Signature:** `setTrackingNumber(trackingNumber : String) : void` Set the TrackingNumber. ### setWarehouseID **Signature:** `setWarehouseID(warehouseID : String) : void` Set the id of the shipping warehouse. ## Method Detail ## Method Details ### getCarrier **Signature:** `getCarrier() : String` **Description:** Get the Carrier. **Returns:** the Carrier --- ### getCarrierService **Signature:** `getCarrierService() : String` **Description:** Get the service(ship method) of the used carrier. **Returns:** the carrier service (ship method) --- ### getID **Signature:** `getID() : String` **Description:** Get the mandatory identifier for this tracking information. The id allows the tracking information to be referenced from TrackingRefs. To support short shipping a shipping-order-item can manage a list of TrackingRefs, each with an optional quantity value allowing individual items to ship in multiple parcels with known item quantity in each. **Returns:** the id **See Also:** ShippingOrder.addTrackingInfo(String) --- ### getShipDate **Signature:** `getShipDate() : Date` **Description:** Get the ship date. **Returns:** the ship date --- ### getShippingOrder **Signature:** `getShippingOrder() : ShippingOrder` **Description:** Gets the shipping order. **Returns:** the shipping order --- ### getTrackingNumber **Signature:** `getTrackingNumber() : String` **Description:** Get the tracking number. **Returns:** the TrackingNumber --- ### getTrackingRefs **Signature:** `getTrackingRefs() : Collection` **Description:** Gets the tracking refs (shipping order items) which are assigned to this tracking info. **Returns:** the tracking refs (shipping order items) which are assigned to this tracking info. --- ### getWarehouseID **Signature:** `getWarehouseID() : String` **Description:** Get the id of the shipping warehouse. **Returns:** the id of the shipping warehouse --- ### setCarrier **Signature:** `setCarrier(carrier : String) : void` **Description:** Set the Carrier. **Parameters:** - `carrier`: the Carrier --- ### setCarrierService **Signature:** `setCarrierService(carrierService : String) : void` **Description:** Set the service(ship method) of the used carrier. **Parameters:** - `carrierService`: the carrier service, eg. the ship method --- ### setShipDate **Signature:** `setShipDate(shipDate : Date) : void` **Description:** Set the ship date. **Parameters:** - `shipDate`: the ship date --- ### setTrackingNumber **Signature:** `setTrackingNumber(trackingNumber : String) : void` **Description:** Set the TrackingNumber. **Parameters:** - `trackingNumber`: the TrackingNumber --- ### setWarehouseID **Signature:** `setWarehouseID(warehouseID : String) : void` **Description:** Set the id of the shipping warehouse. **Parameters:** - `warehouseID`: the id of the shipping warehouse --- ``` -------------------------------------------------------------------------------- /docs/sfra/totals.md: -------------------------------------------------------------------------------- ```markdown # SFRA Totals Model ## Overview The Totals model represents comprehensive pricing and discount information for a basket or order in SFRA applications. It provides formatted monetary values, discount calculations, and tax information for checkout and order display. ## Constructor ```javascript function totals(lineItemContainer) ``` Creates a Totals model instance with comprehensive pricing information from a line item container. ### Parameters - `lineItemContainer` (dw.order.LineItemCtnr) - Current user's basket or order ## Properties ### subTotal **Type:** string Formatted subtotal of merchandise before taxes and shipping. ### totalShippingCost **Type:** string Formatted total shipping cost. ### grandTotal **Type:** string Formatted grand total including all items, taxes, shipping, and discounts. ### totalTax **Type:** string Formatted total tax amount. ### discounts **Type:** Array<Object> Array of discount objects including promotions and coupons. Each discount contains: **For Promotions:** - `UUID` (string) - Unique identifier - `lineItemText` (string) - Display text for the discount - `price` (string) - Formatted discount amount - `type` (string) - Always 'promotion' - `callOutMsg` (string) - Promotion callout message **For Coupons:** - `UUID` (string) - Unique identifier - `type` (string) - Always 'coupon' - `couponCode` (string) - The coupon code - `applied` (boolean) - Whether the coupon is applied - `valid` (boolean) - Whether the coupon is valid - `relationship` (Array) - Array of related price adjustments with callout messages ### discountsHtml **Type:** string HTML-formatted string of all discounts for display purposes. ### orderLevelDiscountTotal **Type:** Object Order-level discount information containing: - `value` (number) - Raw discount value - `formatted` (string) - Formatted discount amount ### shippingLevelDiscountTotal **Type:** Object Shipping-level discount information containing: - `value` (number) - Raw discount value - `formatted` (string) - Formatted discount amount ## Helper Functions ### getTotals(total) Formats a money total for display, handling unavailable totals. **Parameters:** - `total` (dw.value.Money) - Total price value **Returns:** string - Formatted money value or '-' if unavailable ### getOrderLevelDiscountTotal(lineItemContainer) Calculates order-level discount by comparing totals with and without order discounts. **Parameters:** - `lineItemContainer` (dw.order.LineItemCtnr) - Basket or order container **Returns:** Object - Order discount value and formatted amount ### getShippingLevelDiscountTotal(lineItemContainer) Calculates shipping-level discount by comparing shipping totals. **Parameters:** - `lineItemContainer` (dw.order.LineItemCtnr) - Basket or order container **Returns:** Object - Shipping discount value and formatted amount ### createDiscountObject(collection, discounts) Adds promotion discounts to a discounts object. **Parameters:** - `collection` (dw.util.Collection) - Collection of price adjustments - `discounts` (Object) - Existing discounts object **Returns:** Object - Updated discounts object ### getDiscounts(lineItemContainer) Creates a comprehensive array of all discounts including promotions and coupons. **Parameters:** - `lineItemContainer` (dw.order.LineItemCtnr) - Basket or order container **Returns:** Array<Object> - Array of discount objects ## Usage Example ```javascript var totals = require('*/cartridge/models/totals'); var BasketMgr = require('dw/order/BasketMgr'); var currentBasket = BasketMgr.getCurrentBasket(); var totalsModel = new totals(currentBasket); // Access formatted totals console.log(totalsModel.subTotal); // "$149.99" console.log(totalsModel.totalShippingCost); // "$9.95" console.log(totalsModel.grandTotal); // "$159.94" console.log(totalsModel.totalTax); // "$12.00" // Access discount information totalsModel.discounts.forEach(function(discount) { if (discount.type === 'promotion') { console.log('Promotion: ' + discount.lineItemText + ' - ' + discount.price); } else if (discount.type === 'coupon') { console.log('Coupon: ' + discount.couponCode + ' (applied: ' + discount.applied + ')'); } }); // Check for order-level discounts if (totalsModel.orderLevelDiscountTotal.value > 0) { console.log('Order discount: ' + totalsModel.orderLevelDiscountTotal.formatted); } ``` ## Discount Types The model handles different types of discounts: ### Promotions - Automatic promotional discounts - Include callout messages for display - Based on business rules and conditions ### Coupons - Customer-entered coupon codes - Include the coupon code for reference - May have usage restrictions ## HTML Formatting The `discountsHtml` property provides ready-to-use HTML formatting for discount display, using templates to ensure consistent presentation across the application. ## Notes - All monetary values are properly formatted for display - Handles unavailable totals gracefully with fallback formatting - Separates order-level and shipping-level discounts - Provides both individual discount details and aggregate totals - Compatible with both baskets and completed orders - Includes comprehensive tax calculation information ## Related Models - **Cart Model** - Uses totals for cart display - **Order Model** - Uses totals for order information - **Checkout Models** - Use totals throughout checkout process ``` -------------------------------------------------------------------------------- /tests/servers/sfcc-mock-server/src/app.js: -------------------------------------------------------------------------------- ```javascript /** * Express Application Setup * * Main Express application configuration with middleware setup and route registration. * Follows modular architecture with clean separation of concerns. */ const express = require('express'); const { createCorsMiddleware } = require('./middleware/cors'); const { createRequestLogger, createResponseLogger, createErrorLogger } = require('./middleware/logging'); const AuthenticationManager = require('./middleware/auth'); const WebDAVRouteHandler = require('./routes/webdav'); const OCAPIRouteHandler = require('./routes/ocapi'); class SFCCMockApp { constructor(config) { this.config = config; this.app = express(); this.authManager = new AuthenticationManager(config); this.setupMiddleware(); this.setupRoutes(); this.setupErrorHandling(); } setupMiddleware() { // CORS middleware (if enabled) if (this.config.features.cors) { this.app.use(createCorsMiddleware()); } // Body parsing middleware this.app.use(express.json({ limit: '10mb' })); this.app.use(express.urlencoded({ extended: true, limit: '10mb' })); // Logging middleware (if enabled) if (this.config.features.logging) { this.app.use(createRequestLogger(this.config.isDevMode)); this.app.use(createResponseLogger(this.config.isDevMode)); } // Custom method support for WebDAV this.app.use((req, res, next) => { // Add support for PROPFIND method if (req.headers['content-length'] === '0' && req.method === 'POST') { // Check if this might be a PROPFIND disguised as POST const contentType = req.headers['content-type']; if (!contentType || contentType.includes('application/xml')) { req.method = 'PROPFIND'; } } next(); }); } setupRoutes() { // Health check endpoint this.app.get('/health', (req, res) => { const summary = this.config.getSummary(); res.json({ status: 'ok', message: 'SFCC Mock Server is running', timestamp: new Date().toISOString(), config: summary }); }); // Server info endpoint this.app.get('/info', (req, res) => { const summary = this.config.getSummary(); res.json({ name: 'SFCC Mock Server', version: '1.0.0', description: 'Unified WebDAV and OCAPI mock server for SFCC development', config: summary }); }); // WebDAV routes (if enabled) if (this.config.features.webdav) { const webdavHandler = new WebDAVRouteHandler(this.config); this.app.use(webdavHandler.getRouter()); if (this.config.isDevMode) { console.log('✅ WebDAV routes enabled'); } } // OCAPI routes (if enabled) if (this.config.features.ocapi) { const ocapiHandler = new OCAPIRouteHandler(this.config, this.authManager); this.app.use(ocapiHandler.getRouter()); if (this.config.isDevMode) { console.log('✅ OCAPI routes enabled'); } } // Catch-all for undefined routes this.app.use('*', (req, res) => { res.status(404).json({ error: 'Not Found', message: `Route ${req.method} ${req.originalUrl} not found`, timestamp: new Date().toISOString(), availableEndpoints: this.getAvailableEndpoints() }); }); } setupErrorHandling() { // Error logging middleware this.app.use(createErrorLogger()); // Final error handler this.app.use((err, req, res, next) => { // Prevent header already sent errors if (res.headersSent) { return next(err); } const statusCode = err.statusCode || err.status || 500; const message = err.message || 'Internal Server Error'; res.status(statusCode).json({ error: 'Server Error', message: message, timestamp: new Date().toISOString(), ...(this.config.isDevMode && { stack: err.stack }) }); }); } getAvailableEndpoints() { const baseUrl = this.config.getServerUrl(); const endpoints = { health: `${baseUrl}/health`, info: `${baseUrl}/info` }; if (this.config.features.webdav) { endpoints.webdav = { logs: this.config.getWebdavLogsUrl(), directLogs: `${baseUrl}/Logs/` }; } if (this.config.features.ocapi) { const ocapiBase = this.config.getOcapiBaseUrl(); endpoints.ocapi = { oauth: `${baseUrl}/dw/oauth2/access_token`, systemObjects: `${ocapiBase}/system_object_definitions`, codeVersions: `${ocapiBase}/code_versions` }; } return endpoints; } getExpressApp() { return this.app; } getAuthManager() { return this.authManager; } } module.exports = SFCCMockApp; ``` -------------------------------------------------------------------------------- /src/utils/validator.ts: -------------------------------------------------------------------------------- ```typescript /** * Validation Utilities * * This module provides validation functions for SFCC API parameters and inputs. * It includes common validation patterns used across different API clients. */ /** * Custom validation error class */ export class ValidationError extends Error { constructor(message: string) { super(message); this.name = 'ValidationError'; } } /** * Valid instance types for SFCC site preferences */ const VALID_INSTANCE_TYPES = ['staging', 'development', 'sandbox', 'production'] as const; export type InstanceType = typeof VALID_INSTANCE_TYPES[number]; /** * Validation utility class */ export class Validator { /** * Validate that required fields are present and not empty */ static validateRequired(params: Record<string, any>, requiredFields: string[]): void { const missingFields: string[] = []; for (const field of requiredFields) { const value = params[field]; if (value === undefined || value === null || (typeof value === 'string' && value.trim().length === 0)) { missingFields.push(field); } } if (missingFields.length > 0) { throw new ValidationError(`Required fields are missing or empty: ${missingFields.join(', ')}`); } } /** * Validate instance type for site preferences */ static validateInstanceType(instanceType: string): InstanceType { if (!VALID_INSTANCE_TYPES.includes(instanceType as InstanceType)) { throw new ValidationError( `Invalid instance type '${instanceType}'. Must be one of: ${VALID_INSTANCE_TYPES.join(', ')}`, ); } return instanceType as InstanceType; } /** * Validate that a string is not empty */ static validateNotEmpty(value: string, fieldName: string): void { if (!value || value.trim().length === 0) { throw new ValidationError(`${fieldName} cannot be empty`); } } /** * Validate that a value is a positive number */ static validatePositiveNumber(value: number, fieldName: string): void { if (value < 0) { throw new ValidationError(`${fieldName} must be a positive number`); } } /** * Validate object type for system objects */ static validateObjectType(objectType: string): void { Validator.validateNotEmpty(objectType, 'objectType'); // Basic validation - could be extended with specific object type patterns if (!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(objectType)) { throw new ValidationError( `Invalid object type '${objectType}'. Must start with a letter and contain only letters, numbers, and underscores.`, ); } } /** * Validate search request structure */ static validateSearchRequest(searchRequest: any): void { if (!searchRequest || typeof searchRequest !== 'object') { throw new ValidationError('Search request must be a valid object'); } // Validate query structure if present if (searchRequest.query) { const query = searchRequest.query; // Check that at least one query type is specified const queryTypes = ['text_query', 'term_query', 'filtered_query', 'bool_query', 'match_all_query']; const hasValidQuery = queryTypes.some(type => query[type]); if (!hasValidQuery) { throw new ValidationError( `Search query must contain at least one of: ${queryTypes.join(', ')}`, ); } // Validate text_query structure if (query.text_query) { const textQuery = query.text_query; if (!textQuery.fields || !Array.isArray(textQuery.fields) || textQuery.fields.length === 0) { throw new ValidationError('text_query.fields must be a non-empty array'); } if (!textQuery.search_phrase || typeof textQuery.search_phrase !== 'string') { throw new ValidationError('text_query.search_phrase must be a non-empty string'); } } // Validate term_query structure if (query.term_query) { const termQuery = query.term_query; if (!termQuery.fields || !Array.isArray(termQuery.fields) || termQuery.fields.length === 0) { throw new ValidationError('term_query.fields must be a non-empty array'); } if (!termQuery.operator || typeof termQuery.operator !== 'string') { throw new ValidationError('term_query.operator must be a non-empty string'); } if (!termQuery.values || !Array.isArray(termQuery.values) || termQuery.values.length === 0) { throw new ValidationError('term_query.values must be a non-empty array'); } } } // Validate sorts structure if present if (searchRequest.sorts) { if (!Array.isArray(searchRequest.sorts)) { throw new ValidationError('sorts must be an array'); } searchRequest.sorts.forEach((sort: any, index: number) => { if (!sort.field || typeof sort.field !== 'string') { throw new ValidationError(`sorts[${index}].field must be a non-empty string`); } if (sort.sort_order && !['asc', 'desc'].includes(sort.sort_order)) { throw new ValidationError(`sorts[${index}].sort_order must be either 'asc' or 'desc'`); } }); } // Validate pagination parameters if (searchRequest.start !== undefined) { Validator.validatePositiveNumber(searchRequest.start, 'start'); } if (searchRequest.count !== undefined) { Validator.validatePositiveNumber(searchRequest.count, 'count'); } } } ```