This is page 12 of 61. Use http://codebase.md/taurgis/sfcc-dev-mcp?lines=true&page={x} to view the full context. # Directory Structure ``` ├── .DS_Store ├── .github │ ├── dependabot.yml │ ├── instructions │ │ ├── mcp-node-tests.instructions.md │ │ └── mcp-yml-tests.instructions.md │ ├── ISSUE_TEMPLATE │ │ ├── bug_report.yml │ │ ├── config.yml │ │ ├── documentation.yml │ │ ├── feature_request.yml │ │ └── question.yml │ ├── PULL_REQUEST_TEMPLATE │ │ ├── bug_fix.md │ │ ├── documentation.md │ │ └── new_tool.md │ ├── pull_request_template.md │ └── workflows │ ├── ci.yml │ ├── deploy-pages.yml │ ├── publish.yml │ └── update-docs.yml ├── .gitignore ├── .husky │ └── pre-commit ├── aegis.config.docs-only.json ├── aegis.config.json ├── aegis.config.with-dw.json ├── AGENTS.md ├── ai-instructions │ ├── claude-desktop │ │ └── claude_custom_instructions.md │ ├── cursor │ │ └── .cursor │ │ └── rules │ │ ├── debugging-workflows.mdc │ │ ├── hooks-development.mdc │ │ ├── isml-templates.mdc │ │ ├── job-framework.mdc │ │ ├── performance-optimization.mdc │ │ ├── scapi-endpoints.mdc │ │ ├── security-patterns.mdc │ │ ├── sfcc-development.mdc │ │ ├── sfra-controllers.mdc │ │ ├── sfra-models.mdc │ │ ├── system-objects.mdc │ │ └── testing-patterns.mdc │ └── github-copilot │ └── copilot-instructions.md ├── CHANGELOG.md ├── CONTRIBUTING.md ├── docs │ ├── best-practices │ │ ├── cartridge_creation.md │ │ ├── isml_templates.md │ │ ├── job_framework.md │ │ ├── localserviceregistry.md │ │ ├── ocapi_hooks.md │ │ ├── performance.md │ │ ├── scapi_custom_endpoint.md │ │ ├── scapi_hooks.md │ │ ├── security.md │ │ ├── sfra_client_side_js.md │ │ ├── sfra_controllers.md │ │ ├── sfra_models.md │ │ └── sfra_scss.md │ ├── dw_campaign │ │ ├── ABTest.md │ │ ├── ABTestMgr.md │ │ ├── ABTestSegment.md │ │ ├── AmountDiscount.md │ │ ├── ApproachingDiscount.md │ │ ├── BonusChoiceDiscount.md │ │ ├── BonusDiscount.md │ │ ├── Campaign.md │ │ ├── CampaignMgr.md │ │ ├── CampaignStatusCodes.md │ │ ├── Coupon.md │ │ ├── CouponMgr.md │ │ ├── CouponRedemption.md │ │ ├── CouponStatusCodes.md │ │ ├── Discount.md │ │ ├── DiscountPlan.md │ │ ├── FixedPriceDiscount.md │ │ ├── FixedPriceShippingDiscount.md │ │ ├── FreeDiscount.md │ │ ├── FreeShippingDiscount.md │ │ ├── PercentageDiscount.md │ │ ├── PercentageOptionDiscount.md │ │ ├── PriceBookPriceDiscount.md │ │ ├── Promotion.md │ │ ├── PromotionMgr.md │ │ ├── PromotionPlan.md │ │ ├── SlotContent.md │ │ ├── SourceCodeGroup.md │ │ ├── SourceCodeInfo.md │ │ ├── SourceCodeStatusCodes.md │ │ └── TotalFixedPriceDiscount.md │ ├── dw_catalog │ │ ├── Catalog.md │ │ ├── CatalogMgr.md │ │ ├── Category.md │ │ ├── CategoryAssignment.md │ │ ├── CategoryLink.md │ │ ├── PriceBook.md │ │ ├── PriceBookMgr.md │ │ ├── Product.md │ │ ├── ProductActiveData.md │ │ ├── ProductAttributeModel.md │ │ ├── ProductAvailabilityLevels.md │ │ ├── ProductAvailabilityModel.md │ │ ├── ProductInventoryList.md │ │ ├── ProductInventoryMgr.md │ │ ├── ProductInventoryRecord.md │ │ ├── ProductLink.md │ │ ├── ProductMgr.md │ │ ├── ProductOption.md │ │ ├── ProductOptionModel.md │ │ ├── ProductOptionValue.md │ │ ├── ProductPriceInfo.md │ │ ├── ProductPriceModel.md │ │ ├── ProductPriceTable.md │ │ ├── ProductSearchHit.md │ │ ├── ProductSearchModel.md │ │ ├── ProductSearchRefinementDefinition.md │ │ ├── ProductSearchRefinements.md │ │ ├── ProductSearchRefinementValue.md │ │ ├── ProductVariationAttribute.md │ │ ├── ProductVariationAttributeValue.md │ │ ├── ProductVariationModel.md │ │ ├── Recommendation.md │ │ ├── SearchModel.md │ │ ├── SearchRefinementDefinition.md │ │ ├── SearchRefinements.md │ │ ├── SearchRefinementValue.md │ │ ├── SortingOption.md │ │ ├── SortingRule.md │ │ ├── Store.md │ │ ├── StoreGroup.md │ │ ├── StoreInventoryFilter.md │ │ ├── StoreInventoryFilterValue.md │ │ ├── StoreMgr.md │ │ ├── Variant.md │ │ └── VariationGroup.md │ ├── dw_content │ │ ├── Content.md │ │ ├── ContentMgr.md │ │ ├── ContentSearchModel.md │ │ ├── ContentSearchRefinementDefinition.md │ │ ├── ContentSearchRefinements.md │ │ ├── ContentSearchRefinementValue.md │ │ ├── Folder.md │ │ ├── Library.md │ │ ├── MarkupText.md │ │ └── MediaFile.md │ ├── dw_crypto │ │ ├── CertificateRef.md │ │ ├── CertificateUtils.md │ │ ├── Cipher.md │ │ ├── Encoding.md │ │ ├── JWE.md │ │ ├── JWEHeader.md │ │ ├── JWS.md │ │ ├── JWSHeader.md │ │ ├── KeyRef.md │ │ ├── Mac.md │ │ ├── MessageDigest.md │ │ ├── SecureRandom.md │ │ ├── Signature.md │ │ ├── WeakCipher.md │ │ ├── WeakMac.md │ │ ├── WeakMessageDigest.md │ │ ├── WeakSignature.md │ │ └── X509Certificate.md │ ├── dw_customer │ │ ├── AddressBook.md │ │ ├── AgentUserMgr.md │ │ ├── AgentUserStatusCodes.md │ │ ├── AuthenticationStatus.md │ │ ├── Credentials.md │ │ ├── Customer.md │ │ ├── CustomerActiveData.md │ │ ├── CustomerAddress.md │ │ ├── CustomerCDPData.md │ │ ├── CustomerContextMgr.md │ │ ├── CustomerGroup.md │ │ ├── CustomerList.md │ │ ├── CustomerMgr.md │ │ ├── CustomerPasswordConstraints.md │ │ ├── CustomerPaymentInstrument.md │ │ ├── CustomerStatusCodes.md │ │ ├── EncryptedObject.md │ │ ├── ExternalProfile.md │ │ ├── OrderHistory.md │ │ ├── ProductList.md │ │ ├── ProductListItem.md │ │ ├── ProductListItemPurchase.md │ │ ├── ProductListMgr.md │ │ ├── ProductListRegistrant.md │ │ ├── Profile.md │ │ └── Wallet.md │ ├── dw_extensions.applepay │ │ ├── ApplePayHookResult.md │ │ └── ApplePayHooks.md │ ├── dw_extensions.facebook │ │ ├── FacebookFeedHooks.md │ │ └── FacebookProduct.md │ ├── dw_extensions.paymentrequest │ │ ├── PaymentRequestHookResult.md │ │ └── PaymentRequestHooks.md │ ├── dw_extensions.payments │ │ ├── SalesforceBancontactPaymentDetails.md │ │ ├── SalesforceCardPaymentDetails.md │ │ ├── SalesforceEpsPaymentDetails.md │ │ ├── SalesforceIdealPaymentDetails.md │ │ ├── SalesforceKlarnaPaymentDetails.md │ │ ├── SalesforcePaymentDetails.md │ │ ├── SalesforcePaymentIntent.md │ │ ├── SalesforcePaymentMethod.md │ │ ├── SalesforcePaymentRequest.md │ │ ├── SalesforcePaymentsHooks.md │ │ ├── SalesforcePaymentsMgr.md │ │ ├── SalesforcePaymentsSiteConfiguration.md │ │ ├── SalesforcePayPalOrder.md │ │ ├── SalesforcePayPalOrderAddress.md │ │ ├── SalesforcePayPalOrderPayer.md │ │ ├── SalesforcePayPalPaymentDetails.md │ │ ├── SalesforceSepaDebitPaymentDetails.md │ │ └── SalesforceVenmoPaymentDetails.md │ ├── dw_extensions.pinterest │ │ ├── PinterestAvailability.md │ │ ├── PinterestFeedHooks.md │ │ ├── PinterestOrder.md │ │ ├── PinterestOrderHooks.md │ │ └── PinterestProduct.md │ ├── dw_io │ │ ├── CSVStreamReader.md │ │ ├── CSVStreamWriter.md │ │ ├── File.md │ │ ├── FileReader.md │ │ ├── FileWriter.md │ │ ├── InputStream.md │ │ ├── OutputStream.md │ │ ├── PrintWriter.md │ │ ├── RandomAccessFileReader.md │ │ ├── Reader.md │ │ ├── StringWriter.md │ │ ├── Writer.md │ │ ├── XMLIndentingStreamWriter.md │ │ ├── XMLStreamConstants.md │ │ ├── XMLStreamReader.md │ │ └── XMLStreamWriter.md │ ├── dw_job │ │ ├── JobExecution.md │ │ └── JobStepExecution.md │ ├── dw_net │ │ ├── FTPClient.md │ │ ├── FTPFileInfo.md │ │ ├── HTTPClient.md │ │ ├── HTTPRequestPart.md │ │ ├── Mail.md │ │ ├── SFTPClient.md │ │ ├── SFTPFileInfo.md │ │ ├── WebDAVClient.md │ │ └── WebDAVFileInfo.md │ ├── dw_object │ │ ├── ActiveData.md │ │ ├── CustomAttributes.md │ │ ├── CustomObject.md │ │ ├── CustomObjectMgr.md │ │ ├── Extensible.md │ │ ├── ExtensibleObject.md │ │ ├── Note.md │ │ ├── ObjectAttributeDefinition.md │ │ ├── ObjectAttributeGroup.md │ │ ├── ObjectAttributeValueDefinition.md │ │ ├── ObjectTypeDefinition.md │ │ ├── PersistentObject.md │ │ ├── SimpleExtensible.md │ │ └── SystemObjectMgr.md │ ├── dw_order │ │ ├── AbstractItem.md │ │ ├── AbstractItemCtnr.md │ │ ├── Appeasement.md │ │ ├── AppeasementItem.md │ │ ├── Basket.md │ │ ├── BasketMgr.md │ │ ├── BonusDiscountLineItem.md │ │ ├── CouponLineItem.md │ │ ├── CreateAgentBasketLimitExceededException.md │ │ ├── CreateBasketFromOrderException.md │ │ ├── CreateCouponLineItemException.md │ │ ├── CreateOrderException.md │ │ ├── CreateTemporaryBasketLimitExceededException.md │ │ ├── GiftCertificate.md │ │ ├── GiftCertificateLineItem.md │ │ ├── GiftCertificateMgr.md │ │ ├── GiftCertificateStatusCodes.md │ │ ├── Invoice.md │ │ ├── InvoiceItem.md │ │ ├── LineItem.md │ │ ├── LineItemCtnr.md │ │ ├── Order.md │ │ ├── OrderAddress.md │ │ ├── OrderItem.md │ │ ├── OrderMgr.md │ │ ├── OrderPaymentInstrument.md │ │ ├── OrderProcessStatusCodes.md │ │ ├── PaymentCard.md │ │ ├── PaymentInstrument.md │ │ ├── PaymentMethod.md │ │ ├── PaymentMgr.md │ │ ├── PaymentProcessor.md │ │ ├── PaymentStatusCodes.md │ │ ├── PaymentTransaction.md │ │ ├── PriceAdjustment.md │ │ ├── PriceAdjustmentLimitTypes.md │ │ ├── ProductLineItem.md │ │ ├── ProductShippingCost.md │ │ ├── ProductShippingLineItem.md │ │ ├── ProductShippingModel.md │ │ ├── Return.md │ │ ├── ReturnCase.md │ │ ├── ReturnCaseItem.md │ │ ├── ReturnItem.md │ │ ├── Shipment.md │ │ ├── ShipmentShippingCost.md │ │ ├── ShipmentShippingModel.md │ │ ├── ShippingLineItem.md │ │ ├── ShippingLocation.md │ │ ├── ShippingMethod.md │ │ ├── ShippingMgr.md │ │ ├── ShippingOrder.md │ │ ├── ShippingOrderItem.md │ │ ├── SumItem.md │ │ ├── TaxGroup.md │ │ ├── TaxItem.md │ │ ├── TaxMgr.md │ │ ├── TrackingInfo.md │ │ └── TrackingRef.md │ ├── dw_order.hooks │ │ ├── CalculateHooks.md │ │ ├── OrderHooks.md │ │ ├── PaymentHooks.md │ │ ├── ReturnHooks.md │ │ └── ShippingOrderHooks.md │ ├── dw_rpc │ │ ├── SOAPUtil.md │ │ ├── Stub.md │ │ └── WebReference.md │ ├── dw_suggest │ │ ├── BrandSuggestions.md │ │ ├── CategorySuggestions.md │ │ ├── ContentSuggestions.md │ │ ├── CustomSuggestions.md │ │ ├── ProductSuggestions.md │ │ ├── SearchPhraseSuggestions.md │ │ ├── SuggestedCategory.md │ │ ├── SuggestedContent.md │ │ ├── SuggestedPhrase.md │ │ ├── SuggestedProduct.md │ │ ├── SuggestedTerm.md │ │ ├── SuggestedTerms.md │ │ ├── Suggestions.md │ │ └── SuggestModel.md │ ├── dw_svc │ │ ├── FTPService.md │ │ ├── FTPServiceDefinition.md │ │ ├── HTTPFormService.md │ │ ├── HTTPFormServiceDefinition.md │ │ ├── HTTPService.md │ │ ├── HTTPServiceDefinition.md │ │ ├── LocalServiceRegistry.md │ │ ├── Result.md │ │ ├── Service.md │ │ ├── ServiceCallback.md │ │ ├── ServiceConfig.md │ │ ├── ServiceCredential.md │ │ ├── ServiceDefinition.md │ │ ├── ServiceProfile.md │ │ ├── ServiceRegistry.md │ │ ├── SOAPService.md │ │ └── SOAPServiceDefinition.md │ ├── dw_system │ │ ├── AgentUserStatusCodes.md │ │ ├── Cache.md │ │ ├── CacheMgr.md │ │ ├── HookMgr.md │ │ ├── InternalObject.md │ │ ├── JobProcessMonitor.md │ │ ├── Log.md │ │ ├── Logger.md │ │ ├── LogNDC.md │ │ ├── OrganizationPreferences.md │ │ ├── Pipeline.md │ │ ├── PipelineDictionary.md │ │ ├── RemoteInclude.md │ │ ├── Request.md │ │ ├── RequestHooks.md │ │ ├── Response.md │ │ ├── RESTErrorResponse.md │ │ ├── RESTResponseMgr.md │ │ ├── RESTSuccessResponse.md │ │ ├── SearchStatus.md │ │ ├── Session.md │ │ ├── Site.md │ │ ├── SitePreferences.md │ │ ├── Status.md │ │ ├── StatusItem.md │ │ ├── System.md │ │ └── Transaction.md │ ├── dw_util │ │ ├── ArrayList.md │ │ ├── Assert.md │ │ ├── BigInteger.md │ │ ├── Bytes.md │ │ ├── Calendar.md │ │ ├── Collection.md │ │ ├── Currency.md │ │ ├── DateUtils.md │ │ ├── Decimal.md │ │ ├── FilteringCollection.md │ │ ├── Geolocation.md │ │ ├── HashMap.md │ │ ├── HashSet.md │ │ ├── Iterator.md │ │ ├── LinkedHashMap.md │ │ ├── LinkedHashSet.md │ │ ├── List.md │ │ ├── Locale.md │ │ ├── Map.md │ │ ├── MapEntry.md │ │ ├── MappingKey.md │ │ ├── MappingMgr.md │ │ ├── PropertyComparator.md │ │ ├── SecureEncoder.md │ │ ├── SecureFilter.md │ │ ├── SeekableIterator.md │ │ ├── Set.md │ │ ├── SortedMap.md │ │ ├── SortedSet.md │ │ ├── StringUtils.md │ │ ├── Template.md │ │ └── UUIDUtils.md │ ├── dw_value │ │ ├── EnumValue.md │ │ ├── MimeEncodedText.md │ │ ├── Money.md │ │ └── Quantity.md │ ├── dw_web │ │ ├── ClickStream.md │ │ ├── ClickStreamEntry.md │ │ ├── Cookie.md │ │ ├── Cookies.md │ │ ├── CSRFProtection.md │ │ ├── Form.md │ │ ├── FormAction.md │ │ ├── FormElement.md │ │ ├── FormElementValidationResult.md │ │ ├── FormField.md │ │ ├── FormFieldOption.md │ │ ├── FormFieldOptions.md │ │ ├── FormGroup.md │ │ ├── FormList.md │ │ ├── FormListItem.md │ │ ├── Forms.md │ │ ├── HttpParameter.md │ │ ├── HttpParameterMap.md │ │ ├── LoopIterator.md │ │ ├── PageMetaData.md │ │ ├── PageMetaTag.md │ │ ├── PagingModel.md │ │ ├── Resource.md │ │ ├── URL.md │ │ ├── URLAction.md │ │ ├── URLParameter.md │ │ ├── URLRedirect.md │ │ ├── URLRedirectMgr.md │ │ └── URLUtils.md │ ├── sfra │ │ ├── account.md │ │ ├── address.md │ │ ├── billing.md │ │ ├── cart.md │ │ ├── categories.md │ │ ├── content.md │ │ ├── locale.md │ │ ├── order.md │ │ ├── payment.md │ │ ├── price-default.md │ │ ├── price-range.md │ │ ├── price-tiered.md │ │ ├── product-bundle.md │ │ ├── product-full.md │ │ ├── product-line-items.md │ │ ├── product-search.md │ │ ├── product-tile.md │ │ ├── querystring.md │ │ ├── render.md │ │ ├── request.md │ │ ├── response.md │ │ ├── server.md │ │ ├── shipping.md │ │ ├── store.md │ │ ├── stores.md │ │ └── totals.md │ └── TopLevel │ ├── APIException.md │ ├── arguments.md │ ├── Array.md │ ├── ArrayBuffer.md │ ├── BigInt.md │ ├── Boolean.md │ ├── ConversionError.md │ ├── DataView.md │ ├── Date.md │ ├── Error.md │ ├── ES6Iterator.md │ ├── EvalError.md │ ├── Fault.md │ ├── Float32Array.md │ ├── Float64Array.md │ ├── Function.md │ ├── Generator.md │ ├── global.md │ ├── Int16Array.md │ ├── Int32Array.md │ ├── Int8Array.md │ ├── InternalError.md │ ├── IOError.md │ ├── Iterable.md │ ├── Iterator.md │ ├── JSON.md │ ├── Map.md │ ├── Math.md │ ├── Module.md │ ├── Namespace.md │ ├── Number.md │ ├── Object.md │ ├── QName.md │ ├── RangeError.md │ ├── ReferenceError.md │ ├── RegExp.md │ ├── Set.md │ ├── StopIteration.md │ ├── String.md │ ├── Symbol.md │ ├── SyntaxError.md │ ├── SystemError.md │ ├── TypeError.md │ ├── Uint16Array.md │ ├── Uint32Array.md │ ├── Uint8Array.md │ ├── Uint8ClampedArray.md │ ├── URIError.md │ ├── WeakMap.md │ ├── WeakSet.md │ ├── XML.md │ ├── XMLList.md │ └── XMLStreamError.md ├── docs-site │ ├── .gitignore │ ├── App.tsx │ ├── components │ │ ├── Badge.tsx │ │ ├── BreadcrumbSchema.tsx │ │ ├── CodeBlock.tsx │ │ ├── Collapsible.tsx │ │ ├── ConfigBuilder.tsx │ │ ├── ConfigHero.tsx │ │ ├── ConfigModeTabs.tsx │ │ ├── icons.tsx │ │ ├── Layout.tsx │ │ ├── LightCodeContainer.tsx │ │ ├── NewcomerCTA.tsx │ │ ├── NextStepsStrip.tsx │ │ ├── OnThisPage.tsx │ │ ├── Search.tsx │ │ ├── SEO.tsx │ │ ├── Sidebar.tsx │ │ ├── StructuredData.tsx │ │ ├── ToolCard.tsx │ │ ├── ToolFilters.tsx │ │ ├── Typography.tsx │ │ └── VersionBadge.tsx │ ├── constants.tsx │ ├── index.html │ ├── main.tsx │ ├── metadata.json │ ├── package-lock.json │ ├── package.json │ ├── pages │ │ ├── AIInterfacesPage.tsx │ │ ├── ConfigurationPage.tsx │ │ ├── DevelopmentPage.tsx │ │ ├── ExamplesPage.tsx │ │ ├── FeaturesPage.tsx │ │ ├── HomePage.tsx │ │ ├── SecurityPage.tsx │ │ ├── ToolsPage.tsx │ │ └── TroubleshootingPage.tsx │ ├── postcss.config.js │ ├── public │ │ ├── .well-known │ │ │ └── security.txt │ │ ├── 404.html │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── explain-product-pricing-methods-no-mcp.png │ │ ├── explain-product-pricing-methods.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── llms.txt │ │ ├── robots.txt │ │ ├── site.webmanifest │ │ └── sitemap.xml │ ├── README.md │ ├── scripts │ │ ├── generate-search-index.js │ │ ├── generate-sitemap.js │ │ └── search-dev.js │ ├── src │ │ └── styles │ │ ├── input.css │ │ └── prism-theme.css │ ├── tailwind.config.js │ ├── tsconfig.json │ ├── types.ts │ ├── utils │ │ ├── search.ts │ │ └── toolsData.ts │ └── vite.config.ts ├── eslint.config.js ├── jest.config.js ├── LICENSE ├── package-lock.json ├── package.json ├── README.md ├── scripts │ └── convert-docs.js ├── SECURITY.md ├── server.json ├── src │ ├── clients │ │ ├── base │ │ │ ├── http-client.ts │ │ │ ├── oauth-token.ts │ │ │ └── ocapi-auth-client.ts │ │ ├── best-practices-client.ts │ │ ├── cartridge-generation-client.ts │ │ ├── docs │ │ │ ├── class-content-parser.ts │ │ │ ├── class-name-resolver.ts │ │ │ ├── documentation-scanner.ts │ │ │ ├── index.ts │ │ │ └── referenced-types-extractor.ts │ │ ├── docs-client.ts │ │ ├── log-client.ts │ │ ├── logs │ │ │ ├── index.ts │ │ │ ├── log-analyzer.ts │ │ │ ├── log-client.ts │ │ │ ├── log-constants.ts │ │ │ ├── log-file-discovery.ts │ │ │ ├── log-file-reader.ts │ │ │ ├── log-formatter.ts │ │ │ ├── log-processor.ts │ │ │ ├── log-types.ts │ │ │ └── webdav-client-manager.ts │ │ ├── ocapi │ │ │ ├── code-versions-client.ts │ │ │ ├── site-preferences-client.ts │ │ │ └── system-objects-client.ts │ │ ├── ocapi-client.ts │ │ └── sfra-client.ts │ ├── config │ │ ├── configuration-factory.ts │ │ └── dw-json-loader.ts │ ├── core │ │ ├── handlers │ │ │ ├── abstract-log-tool-handler.ts │ │ │ ├── base-handler.ts │ │ │ ├── best-practices-handler.ts │ │ │ ├── cartridge-handler.ts │ │ │ ├── client-factory.ts │ │ │ ├── code-version-handler.ts │ │ │ ├── docs-handler.ts │ │ │ ├── job-log-handler.ts │ │ │ ├── job-log-tool-config.ts │ │ │ ├── log-handler.ts │ │ │ ├── log-tool-config.ts │ │ │ ├── sfra-handler.ts │ │ │ ├── system-object-handler.ts │ │ │ └── validation-helpers.ts │ │ ├── server.ts │ │ └── tool-definitions.ts │ ├── index.ts │ ├── main.ts │ ├── services │ │ ├── file-system-service.ts │ │ ├── index.ts │ │ └── path-service.ts │ ├── tool-configs │ │ ├── best-practices-tool-config.ts │ │ ├── cartridge-tool-config.ts │ │ ├── code-version-tool-config.ts │ │ ├── docs-tool-config.ts │ │ ├── job-log-tool-config.ts │ │ ├── log-tool-config.ts │ │ ├── sfra-tool-config.ts │ │ └── system-object-tool-config.ts │ ├── types │ │ └── types.ts │ └── utils │ ├── cache.ts │ ├── job-log-tool-config.ts │ ├── job-log-utils.ts │ ├── log-cache.ts │ ├── log-tool-config.ts │ ├── log-tool-constants.ts │ ├── log-tool-utils.ts │ ├── logger.ts │ ├── ocapi-url-builder.ts │ ├── path-resolver.ts │ ├── query-builder.ts │ ├── utils.ts │ └── validator.ts ├── tests │ ├── __mocks__ │ │ ├── docs-client.ts │ │ ├── src │ │ │ └── clients │ │ │ └── base │ │ │ └── http-client.js │ │ └── webdav.js │ ├── base-handler.test.ts │ ├── base-http-client.test.ts │ ├── best-practices-handler.test.ts │ ├── cache.test.ts │ ├── cartridge-handler.test.ts │ ├── class-content-parser.test.ts │ ├── class-name-resolver.test.ts │ ├── client-factory.test.ts │ ├── code-version-handler.test.ts │ ├── code-versions-client.test.ts │ ├── config.test.ts │ ├── configuration-factory.test.ts │ ├── docs-handler.test.ts │ ├── documentation-scanner.test.ts │ ├── file-system-service.test.ts │ ├── job-log-handler.test.ts │ ├── job-log-utils.test.ts │ ├── log-client.test.ts │ ├── log-handler.test.ts │ ├── log-processor.test.ts │ ├── logger.test.ts │ ├── mcp │ │ ├── AGENTS.md │ │ ├── node │ │ │ ├── activate-code-version-advanced.full-mode.programmatic.test.js │ │ │ ├── code-versions.full-mode.programmatic.test.js │ │ │ ├── generate-cartridge-structure.docs-only.programmatic.test.js │ │ │ ├── get-available-best-practice-guides.docs-only.programmatic.test.js │ │ │ ├── get-available-sfra-documents.programmatic.test.js │ │ │ ├── get-best-practice-guide.docs-only.programmatic.test.js │ │ │ ├── get-hook-reference.docs-only.programmatic.test.js │ │ │ ├── get-job-execution-summary.full-mode.programmatic.test.js │ │ │ ├── get-job-log-entries.full-mode.programmatic.test.js │ │ │ ├── get-latest-debug.full-mode.programmatic.test.js │ │ │ ├── get-latest-error.full-mode.programmatic.test.js │ │ │ ├── get-latest-info.full-mode.programmatic.test.js │ │ │ ├── get-latest-job-log-files.full-mode.programmatic.test.js │ │ │ ├── get-latest-warn.full-mode.programmatic.test.js │ │ │ ├── get-log-file-contents.full-mode.programmatic.test.js │ │ │ ├── get-sfcc-class-documentation.docs-only.programmatic.test.js │ │ │ ├── get-sfcc-class-info.docs-only.programmatic.test.js │ │ │ ├── get-sfra-categories.docs-only.programmatic.test.js │ │ │ ├── get-sfra-document.programmatic.test.js │ │ │ ├── get-sfra-documents-by-category.docs-only.programmatic.test.js │ │ │ ├── get-system-object-definition.full-mode.programmatic.test.js │ │ │ ├── get-system-object-definitions.docs-only.programmatic.test.js │ │ │ ├── get-system-object-definitions.full-mode.programmatic.test.js │ │ │ ├── list-log-files.full-mode.programmatic.test.js │ │ │ ├── list-sfcc-classes.docs-only.programmatic.test.js │ │ │ ├── search-best-practices.docs-only.programmatic.test.js │ │ │ ├── search-custom-object-attribute-definitions.full-mode.programmatic.test.js │ │ │ ├── search-job-logs-by-name.full-mode.programmatic.test.js │ │ │ ├── search-job-logs.full-mode.programmatic.test.js │ │ │ ├── search-logs.full-mode.programmatic.test.js │ │ │ ├── search-sfcc-classes.docs-only.programmatic.test.js │ │ │ ├── search-sfcc-methods.docs-only.programmatic.test.js │ │ │ ├── search-sfra-documentation.docs-only.programmatic.test.js │ │ │ ├── search-site-preferences.full-mode.programmatic.test.js │ │ │ ├── search-system-object-attribute-definitions.full-mode.programmatic.test.js │ │ │ ├── search-system-object-attribute-groups.full-mode.programmatic.test.js │ │ │ ├── summarize-logs.full-mode.programmatic.test.js │ │ │ ├── tools.docs-only.programmatic.test.js │ │ │ └── tools.full-mode.programmatic.test.js │ │ ├── README.md │ │ ├── test-fixtures │ │ │ └── dw.json │ │ └── yaml │ │ ├── activate-code-version.docs-only.test.mcp.yml │ │ ├── activate-code-version.full-mode.test.mcp.yml │ │ ├── get_latest_error.test.mcp.yml │ │ ├── get-available-best-practice-guides.docs-only.test.mcp.yml │ │ ├── get-available-best-practice-guides.full-mode.test.mcp.yml │ │ ├── get-available-sfra-documents.docs-only.test.mcp.yml │ │ ├── get-available-sfra-documents.full-mode.test.mcp.yml │ │ ├── get-best-practice-guide.docs-only.test.mcp.yml │ │ ├── get-best-practice-guide.full-mode.test.mcp.yml │ │ ├── get-code-versions.docs-only.test.mcp.yml │ │ ├── get-code-versions.full-mode.test.mcp.yml │ │ ├── get-hook-reference.docs-only.test.mcp.yml │ │ ├── get-hook-reference.full-mode.test.mcp.yml │ │ ├── get-job-execution-summary.full-mode.test.mcp.yml │ │ ├── get-job-log-entries.full-mode.test.mcp.yml │ │ ├── get-latest-debug.full-mode.test.mcp.yml │ │ ├── get-latest-error.full-mode.test.mcp.yml │ │ ├── get-latest-info.full-mode.test.mcp.yml │ │ ├── get-latest-job-log-files.full-mode.test.mcp.yml │ │ ├── get-latest-warn.full-mode.test.mcp.yml │ │ ├── get-log-file-contents.full-mode.test.mcp.yml │ │ ├── get-sfcc-class-documentation.docs-only.test.mcp.yml │ │ ├── get-sfcc-class-documentation.full-mode.test.mcp.yml │ │ ├── get-sfcc-class-info.docs-only.test.mcp.yml │ │ ├── get-sfcc-class-info.full-mode.test.mcp.yml │ │ ├── get-sfra-categories.docs-only.test.mcp.yml │ │ ├── get-sfra-categories.full-mode.test.mcp.yml │ │ ├── get-sfra-document.docs-only.test.mcp.yml │ │ ├── get-sfra-document.full-mode.test.mcp.yml │ │ ├── get-sfra-documents-by-category.docs-only.test.mcp.yml │ │ ├── get-sfra-documents-by-category.full-mode.test.mcp.yml │ │ ├── get-system-object-definition.docs-only.test.mcp.yml │ │ ├── get-system-object-definition.full-mode.test.mcp.yml │ │ ├── get-system-object-definitions.docs-only.test.mcp.yml │ │ ├── get-system-object-definitions.full-mode.test.mcp.yml │ │ ├── list-log-files.full-mode.test.mcp.yml │ │ ├── list-sfcc-classes.docs-only.test.mcp.yml │ │ ├── list-sfcc-classes.full-mode.test.mcp.yml │ │ ├── search-best-practices.docs-only.test.mcp.yml │ │ ├── search-best-practices.full-mode.test.mcp.yml │ │ ├── search-custom-object-attribute-definitions.docs-only.test.mcp.yml │ │ ├── search-custom-object-attribute-definitions.test.mcp.yml │ │ ├── search-job-logs-by-name.full-mode.test.mcp.yml │ │ ├── search-job-logs.full-mode.test.mcp.yml │ │ ├── search-logs.full-mode.test.mcp.yml │ │ ├── search-sfcc-classes.docs-only.test.mcp.yml │ │ ├── search-sfcc-classes.full-mode.test.mcp.yml │ │ ├── search-sfcc-methods.docs-only.test.mcp.yml │ │ ├── search-sfcc-methods.full-mode.test.mcp.yml │ │ ├── search-sfra-documentation.docs-only.test.mcp.yml │ │ ├── search-sfra-documentation.full-mode.test.mcp.yml │ │ ├── search-site-preferences.docs-only.test.mcp.yml │ │ ├── search-site-preferences.full-mode.test.mcp.yml │ │ ├── search-system-object-attribute-definitions.docs-only.test.mcp.yml │ │ ├── search-system-object-attribute-definitions.full-mode.test.mcp.yml │ │ ├── search-system-object-attribute-groups.docs-only.test.mcp.yml │ │ ├── search-system-object-attribute-groups.full-mode.test.mcp.yml │ │ ├── summarize-logs.full-mode.test.mcp.yml │ │ ├── tools.docs-only.test.mcp.yml │ │ └── tools.full-mode.test.mcp.yml │ ├── oauth-token.test.ts │ ├── ocapi-auth-client.test.ts │ ├── ocapi-client.test.ts │ ├── path-service.test.ts │ ├── query-builder.test.ts │ ├── referenced-types-extractor.test.ts │ ├── servers │ │ ├── sfcc-mock-server │ │ │ ├── mock-data │ │ │ │ └── ocapi │ │ │ │ ├── code-versions.json │ │ │ │ ├── custom-object-attributes-customapi.json │ │ │ │ ├── custom-object-attributes-globalsettings.json │ │ │ │ ├── custom-object-attributes-versionhistory.json │ │ │ │ ├── site-preferences-ccv.json │ │ │ │ ├── site-preferences-fastforward.json │ │ │ │ ├── site-preferences-sfra.json │ │ │ │ ├── site-preferences-storefront.json │ │ │ │ ├── site-preferences-system.json │ │ │ │ ├── system-object-attribute-groups-campaign.json │ │ │ │ ├── system-object-attribute-groups-category.json │ │ │ │ ├── system-object-attribute-groups-order.json │ │ │ │ ├── system-object-attribute-groups-product.json │ │ │ │ ├── system-object-attribute-groups-sitepreferences.json │ │ │ │ ├── system-object-attributes-customeraddress.json │ │ │ │ ├── system-object-attributes-product-expanded.json │ │ │ │ ├── system-object-attributes-product.json │ │ │ │ ├── system-object-definition-category.json │ │ │ │ ├── system-object-definition-customer.json │ │ │ │ ├── system-object-definition-customeraddress.json │ │ │ │ ├── system-object-definition-order.json │ │ │ │ ├── system-object-definition-product.json │ │ │ │ ├── system-object-definitions-old.json │ │ │ │ └── system-object-definitions.json │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ ├── README.md │ │ │ ├── scripts │ │ │ │ └── setup-logs.js │ │ │ ├── server.js │ │ │ └── src │ │ │ ├── app.js │ │ │ ├── config │ │ │ │ └── server-config.js │ │ │ ├── middleware │ │ │ │ ├── auth.js │ │ │ │ ├── cors.js │ │ │ │ └── logging.js │ │ │ ├── routes │ │ │ │ ├── ocapi │ │ │ │ │ ├── code-versions-handler.js │ │ │ │ │ ├── oauth-handler.js │ │ │ │ │ ├── ocapi-error-utils.js │ │ │ │ │ ├── ocapi-utils.js │ │ │ │ │ ├── site-preferences-handler.js │ │ │ │ │ └── system-objects-handler.js │ │ │ │ ├── ocapi.js │ │ │ │ └── webdav.js │ │ │ └── utils │ │ │ ├── mock-data-loader.js │ │ │ └── webdav-xml.js │ │ └── sfcc-mock-server-manager.ts │ ├── sfcc-mock-server.test.ts │ ├── site-preferences-client.test.ts │ ├── system-objects-client.test.ts │ ├── utils.test.ts │ ├── validation-helpers.test.ts │ └── validator.test.ts ├── tsconfig.json └── tsconfig.test.json ``` # Files -------------------------------------------------------------------------------- /docs/sfra/shipping.md: -------------------------------------------------------------------------------- ```markdown 1 | # SFRA Shipping Model 2 | 3 | ## Overview 4 | 5 | The Shipping model represents shipping information for a shipment in SFRA applications. It provides comprehensive shipping data including addresses, methods, product line items, and gift options for checkout and order processing. 6 | 7 | ## Constructor 8 | 9 | ```javascript 10 | function ShippingModel(shipment, address, customer, containerView) 11 | ``` 12 | 13 | Creates a Shipping model instance with complete shipping information. 14 | 15 | ### Parameters 16 | 17 | - `shipment` (dw.order.Shipment) - The default shipment of the current basket 18 | - `address` (Object) - The address to use to filter the shipping method list 19 | - `customer` (Object) - The current customer model 20 | - `containerView` (string) - The view of the product line items ('order' or 'basket') 21 | 22 | ## Properties 23 | 24 | ### UUID 25 | **Type:** string | null 26 | 27 | Unique identifier for the shipment. 28 | 29 | ### productLineItems 30 | **Type:** ProductLineItemsModel | null 31 | 32 | Product line items model containing all products in this shipment with detailed information. Created using `ProductLineItemsModel` (note the "Model" suffix). 33 | 34 | ### applicableShippingMethods 35 | **Type:** Array<Object> 36 | 37 | Array of shipping methods available for this shipment. Retrieved using `shippingHelpers.getApplicableShippingMethods(shipment, address)`. 38 | 39 | ### selectedShippingMethod 40 | **Type:** ShippingMethodModel | null 41 | 42 | Currently selected shipping method for this shipment, or null if none selected. 43 | 44 | ### shippingAddress 45 | **Type:** Object 46 | 47 | Shipping address for this shipment. Logic: 48 | - If shipment has address data (checked via `emptyAddress()` helper), uses `new AddressModel(shipment.shippingAddress).address` 49 | - Otherwise, uses the provided `address` parameter 50 | 51 | ### matchingAddressId 52 | **Type:** string | boolean 53 | 54 | ID of matching customer address, or false if no match found in customer's address book. 55 | 56 | ### isGift 57 | **Type:** boolean | null 58 | 59 | Indicates whether this shipment is marked as a gift. 60 | 61 | ### giftMessage 62 | **Type:** string | null 63 | 64 | Gift message for the shipment if it's marked as a gift. 65 | 66 | ## Helper Functions 67 | 68 | ### getProductLineItemsModel(shipment, containerView) 69 | Creates a product line items model for the shipment's products. 70 | 71 | **Parameters:** 72 | - `shipment` (dw.order.Shipment) - Target shipment 73 | - `containerView` (string) - View context 74 | 75 | **Returns:** ProductLineItemsModel | null 76 | 77 | ### getSelectedShippingMethod(shipment) 78 | Gets the selected shipping method for a shipment. 79 | 80 | **Parameters:** 81 | - `shipment` (dw.order.Shipment) - Target shipment 82 | 83 | **Returns:** ShippingMethodModel | null 84 | 85 | ### getShipmentUUID(shipment) 86 | Extracts the UUID from a shipment. 87 | 88 | **Parameters:** 89 | - `shipment` (dw.order.Shipment) - Target shipment 90 | 91 | **Returns:** string | null 92 | 93 | ### getAssociatedAddress(shipment, customer) 94 | Finds matching customer address for the shipping address. 95 | 96 | **Parameters:** 97 | - `shipment` (dw.order.Shipment) - Target shipment 98 | - `customer` (Object) - Customer model 99 | 100 | **Returns:** string | boolean - Matching address ID or false 101 | 102 | ### emptyAddress(shipment) 103 | Checks if the shipment has any address information populated. 104 | 105 | **Parameters:** 106 | - `shipment` (dw.order.Shipment) - Target shipment 107 | 108 | **Returns:** boolean - True if ANY of the address fields ['firstName', 'lastName', 'address1', 'address2', 'phone', 'city', 'postalCode', 'stateCode'] have values 109 | 110 | ## Address Handling 111 | 112 | The model provides flexible address handling: 113 | - **Address Population Check**: Uses `emptyAddress()` to check if shipment has address data 114 | - **Existing Address**: Uses `new AddressModel(shipment.shippingAddress).address` if address is populated 115 | - **Fallback Address**: Uses provided address parameter if shipment address is empty 116 | - **Address Matching**: Finds matching addresses in customer's address book using `isEquivalentAddress()` 117 | 118 | ## Usage Example 119 | 120 | ```javascript 121 | var ShippingModel = require('*/cartridge/models/shipping'); 122 | var BasketMgr = require('dw/order/BasketMgr'); 123 | 124 | var currentBasket = BasketMgr.getCurrentBasket(); 125 | var shipment = currentBasket.defaultShipment; 126 | var shippingAddress = getShippingAddress(); // Your address object 127 | var customer = req.currentCustomer; 128 | 129 | var shipping = new ShippingModel(shipment, shippingAddress, customer, 'basket'); 130 | 131 | // Access shipping information 132 | console.log('Shipment UUID: ' + shipping.UUID); 133 | console.log('Available methods: ' + shipping.applicableShippingMethods.length); 134 | 135 | if (shipping.selectedShippingMethod) { 136 | console.log('Selected: ' + shipping.selectedShippingMethod.displayName); 137 | } 138 | 139 | // Check address matching 140 | if (shipping.matchingAddressId) { 141 | console.log('Matches customer address: ' + shipping.matchingAddressId); 142 | } 143 | 144 | // Check for gift options 145 | if (shipping.isGift) { 146 | console.log('Gift message: ' + shipping.giftMessage); 147 | } 148 | 149 | // Access products in shipment (if productLineItems is not null) 150 | if (shipping.productLineItems) { 151 | shipping.productLineItems.items.forEach(function(item) { 152 | console.log(item.productName + ' x ' + item.quantity); 153 | }); 154 | } 155 | ``` 156 | 157 | ## Gift Functionality 158 | 159 | The model supports gift shipments: 160 | - **isGift** - Boolean flag for gift marking 161 | - **giftMessage** - Custom message for gift recipients 162 | - Integrates with gift wrapping and messaging features 163 | 164 | ## Notes 165 | 166 | - Handles both populated and empty shipping addresses with conditional logic 167 | - Integrates with `shippingHelpers.getApplicableShippingMethods()` for method calculation 168 | - Uses `AddressModel` for address formatting when shipment address exists 169 | - Provides address matching using `isEquivalentAddress()` for saved customer addresses 170 | - Supports gift functionality with boolean flags and message text 171 | - Works with both basket and order contexts via `containerView` parameter 172 | - Uses `ProductLineItemsModel` (with "Model" suffix) for line item information 173 | - All properties handle null shipments gracefully 174 | 175 | ## Related Models 176 | 177 | - **AddressModel** - Used for shipping address formatting 178 | - **ProductLineItemsModel** - Used for shipment products 179 | - **ShippingMethodModel** - Used for shipping method details 180 | - **Cart Model** - Uses shipping models for checkout 181 | - **Order Model** - Uses shipping models for order information 182 | ``` -------------------------------------------------------------------------------- /docs/dw_svc/Service.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.svc 2 | 3 | # Class Service 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.svc.Service 9 | 10 | ## Description 11 | 12 | Base class of Services. A service represents a call-specific configuration. Any configuration set here is local to the currently executing call. 13 | 14 | ## Properties 15 | 16 | ### configuration 17 | 18 | **Type:** ServiceConfig (Read Only) 19 | 20 | The Service Configuration. 21 | 22 | ### credentialID 23 | 24 | **Type:** String 25 | 26 | The ID of the currently associated Credential. 27 | 28 | ### mock 29 | 30 | **Type:** boolean 31 | 32 | The status of whether this service is executing in mock mode. 33 | 34 | ### requestData 35 | 36 | **Type:** Object (Read Only) 37 | 38 | The property that stores the object returned by createRequest. 39 | 40 | ### response 41 | 42 | **Type:** Object (Read Only) 43 | 44 | The property that stores the object returned by the service. 45 | 46 | This property is only useful after the service call(Object...) completes, and is the same as the object 47 | inside the Result. 48 | 49 | ### throwOnError 50 | 51 | **Type:** boolean 52 | 53 | The status of whether this service will throw an error when encountering a problem. 54 | 55 | ### URL 56 | 57 | **Type:** String 58 | 59 | The current URL, excluding any custom query parameters. 60 | 61 | ## Constructor Summary 62 | 63 | ## Method Summary 64 | 65 | ### call 66 | 67 | **Signature:** `call(args : Object...) : Result` 68 | 69 | Invokes the service. 70 | 71 | ### getConfiguration 72 | 73 | **Signature:** `getConfiguration() : ServiceConfig` 74 | 75 | Returns the Service Configuration. 76 | 77 | ### getCredentialID 78 | 79 | **Signature:** `getCredentialID() : String` 80 | 81 | Returns the ID of the currently associated Credential. 82 | 83 | ### getRequestData 84 | 85 | **Signature:** `getRequestData() : Object` 86 | 87 | Returns the property that stores the object returned by createRequest. 88 | 89 | ### getResponse 90 | 91 | **Signature:** `getResponse() : Object` 92 | 93 | Returns the property that stores the object returned by the service. 94 | 95 | ### getURL 96 | 97 | **Signature:** `getURL() : String` 98 | 99 | Returns the current URL, excluding any custom query parameters. 100 | 101 | ### isMock 102 | 103 | **Signature:** `isMock() : boolean` 104 | 105 | Returns the status of whether this service is executing in mock mode. 106 | 107 | ### isThrowOnError 108 | 109 | **Signature:** `isThrowOnError() : boolean` 110 | 111 | Returns the status of whether this service will throw an error when encountering a problem. 112 | 113 | ### setCredentialID 114 | 115 | **Signature:** `setCredentialID(id : String) : Service` 116 | 117 | Override the Credential by the credential object with the given ID. 118 | 119 | ### setMock 120 | 121 | **Signature:** `setMock() : Service` 122 | 123 | Forces the mock mode to be enabled. 124 | 125 | ### setThrowOnError 126 | 127 | **Signature:** `setThrowOnError() : Service` 128 | 129 | Forces a Service to throw an error when there is a problem instead of returning a Result with non-OK status. 130 | 131 | ### setURL 132 | 133 | **Signature:** `setURL(url : String) : Service` 134 | 135 | Override the URL to the given value. 136 | 137 | ## Method Detail 138 | 139 | ## Method Details 140 | 141 | ### call 142 | 143 | **Signature:** `call(args : Object...) : Result` 144 | 145 | **Description:** Invokes the service. 146 | 147 | **Parameters:** 148 | 149 | - `args`: Arguments to pass. If there is a single argument and that argument is an array, then each item in the array will become a separate argument. For example, the following results in three separate arguments to the service: svc.call( [1,2,3] ) and is functionally equivalent to svc.call( 1, 2, 3 ) This can be avoided by explicitly forming a List, enclosing the array in another array, or by sending a second argument. The following will all send the array as a List in the first argument. svc.call( ArrayList([1,2,3]) ) svc.call( [[1,2,3]] ) svc.call( [1,2,3], "" ) Another option is to change the definition of the associated ServiceCallback.createRequest(Service, Object...) to accept an object instead, and pass the array as a field of that object: svc.call( { 'data': [1,2,3] } ) 150 | 151 | **Returns:** 152 | 153 | Result of the service. 154 | 155 | --- 156 | 157 | ### getConfiguration 158 | 159 | **Signature:** `getConfiguration() : ServiceConfig` 160 | 161 | **Description:** Returns the Service Configuration. 162 | 163 | **Returns:** 164 | 165 | Service Configuration. 166 | 167 | --- 168 | 169 | ### getCredentialID 170 | 171 | **Signature:** `getCredentialID() : String` 172 | 173 | **Description:** Returns the ID of the currently associated Credential. 174 | 175 | **Returns:** 176 | 177 | Credential Name. 178 | 179 | --- 180 | 181 | ### getRequestData 182 | 183 | **Signature:** `getRequestData() : Object` 184 | 185 | **Description:** Returns the property that stores the object returned by createRequest. 186 | 187 | **Returns:** 188 | 189 | Object returned by createRequest. 190 | 191 | --- 192 | 193 | ### getResponse 194 | 195 | **Signature:** `getResponse() : Object` 196 | 197 | **Description:** Returns the property that stores the object returned by the service. This property is only useful after the service call(Object...) completes, and is the same as the object inside the Result. 198 | 199 | **Returns:** 200 | 201 | Object returned by the service. 202 | 203 | --- 204 | 205 | ### getURL 206 | 207 | **Signature:** `getURL() : String` 208 | 209 | **Description:** Returns the current URL, excluding any custom query parameters. 210 | 211 | **Returns:** 212 | 213 | URL. 214 | 215 | --- 216 | 217 | ### isMock 218 | 219 | **Signature:** `isMock() : boolean` 220 | 221 | **Description:** Returns the status of whether this service is executing in mock mode. 222 | 223 | **Returns:** 224 | 225 | true for mock mode, false otherwise. 226 | 227 | --- 228 | 229 | ### isThrowOnError 230 | 231 | **Signature:** `isThrowOnError() : boolean` 232 | 233 | **Description:** Returns the status of whether this service will throw an error when encountering a problem. 234 | 235 | **Returns:** 236 | 237 | true to throw an error, false otherwise. 238 | 239 | --- 240 | 241 | ### setCredentialID 242 | 243 | **Signature:** `setCredentialID(id : String) : Service` 244 | 245 | **Description:** Override the Credential by the credential object with the given ID. If the URL is also overridden, that URL will continue to override the URL in this credential. 246 | 247 | **Parameters:** 248 | 249 | - `id`: Credential ID. It must exist. 250 | 251 | **Returns:** 252 | 253 | this Service. 254 | 255 | --- 256 | 257 | ### setMock 258 | 259 | **Signature:** `setMock() : Service` 260 | 261 | **Description:** Forces the mock mode to be enabled. 262 | 263 | **Returns:** 264 | 265 | this Service. 266 | 267 | --- 268 | 269 | ### setThrowOnError 270 | 271 | **Signature:** `setThrowOnError() : Service` 272 | 273 | **Description:** Forces a Service to throw an error when there is a problem instead of returning a Result with non-OK status. 274 | 275 | **Returns:** 276 | 277 | this Service. 278 | 279 | --- 280 | 281 | ### setURL 282 | 283 | **Signature:** `setURL(url : String) : Service` 284 | 285 | **Description:** Override the URL to the given value. Any query parameters (if applicable) will be appended to this URL. 286 | 287 | **Parameters:** 288 | 289 | - `url`: Force the URL to the given value. 290 | 291 | **Returns:** 292 | 293 | this Service. 294 | 295 | --- ``` -------------------------------------------------------------------------------- /docs/dw_util/Bytes.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.util 2 | 3 | # Class Bytes 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.util.Bytes 9 | 10 | ## Description 11 | 12 | A simple immutable class representing an array of bytes, used for working with binary data in a scripting context. It acts as a view to ArrayBuffer. The buffer can be accessed through asUint8Array(). Limitation: The size of the resulting byte representation is limited by the quota api.jsArrayBufferSize that is defining the max size for a ArrayBuffer. 13 | 14 | ## Constants 15 | 16 | ### MAX_BYTES 17 | 18 | **Type:** Number = 10240L 19 | 20 | The maximum number of bytes that a Bytes object can represent == 10KB 21 | 22 | ## Properties 23 | 24 | ### length 25 | 26 | **Type:** Number (Read Only) 27 | 28 | The number of bytes represented by this object. 29 | 30 | ## Constructor Summary 31 | 32 | Bytes(arrayBufferOrView : Object) Construct a Bytes object from the given ArrayBuffer or view. 33 | 34 | Bytes(string : String) Construct a Bytes object from the given string using the default encoding. 35 | 36 | Bytes(string : String, encoding : String) Construct a Bytes object from the given string using the given encoding. 37 | 38 | ## Method Summary 39 | 40 | ### asUint8Array 41 | 42 | **Signature:** `asUint8Array() : Object` 43 | 44 | Returns a Uint8Array based on the ArrayBuffer used for this Bytes object. 45 | 46 | ### byteAt 47 | 48 | **Signature:** `byteAt(index : Number) : Number` 49 | 50 | Returns the value of the byte at position index as an integer. 51 | 52 | ### bytesAt 53 | 54 | **Signature:** `bytesAt(index : Number, length : Number) : Bytes` 55 | 56 | Return a new Bytes object containing the subsequence of this object's bytes specified by the index and length parameters. 57 | 58 | ### getLength 59 | 60 | **Signature:** `getLength() : Number` 61 | 62 | Returns the number of bytes represented by this object. 63 | 64 | ### intAt 65 | 66 | **Signature:** `intAt(index : Number) : Number` 67 | 68 | Absolute get method for reading a signed integer value (32 bit) in network byte order(= big endian). 69 | 70 | ### reverse 71 | 72 | **Signature:** `reverse() : Bytes` 73 | 74 | Return a new Bytes object which has the same bytes as this one in reverse order. 75 | 76 | ### shortAt 77 | 78 | **Signature:** `shortAt(index : Number) : Number` 79 | 80 | Absolute get method for reading a signed short value (16 bit) in network byte order(= big endian). 81 | 82 | ### toString 83 | 84 | **Signature:** `toString() : String` 85 | 86 | Constructs a new String by decoding this array of bytes using the default encoding. 87 | 88 | ### toString 89 | 90 | **Signature:** `toString(encoding : String) : String` 91 | 92 | Constructs a new String by decoding this array of bytes using the specified encoding. 93 | 94 | ## Constructor Detail 95 | 96 | ## Method Detail 97 | 98 | ## Method Details 99 | 100 | ### asUint8Array 101 | 102 | **Signature:** `asUint8Array() : Object` 103 | 104 | **Description:** Returns a Uint8Array based on the ArrayBuffer used for this Bytes object. Changes to the returned ArrayBuffer will be visible in the Bytes object. 105 | 106 | **API Versioned:** 107 | 108 | From version 21.2. 109 | 110 | **Returns:** 111 | 112 | A newly created Uint8Array based on the existing ArrayBuffer. 113 | 114 | --- 115 | 116 | ### byteAt 117 | 118 | **Signature:** `byteAt(index : Number) : Number` 119 | 120 | **Description:** Returns the value of the byte at position index as an integer. If index is out of range an exception is thrown. The byte is interpreted as signed and so the value returned will always be between -128 and +127. 121 | 122 | **Parameters:** 123 | 124 | - `index`: The index of the byte. 125 | 126 | **Returns:** 127 | 128 | The byte value at the specified index. 129 | 130 | **Throws:** 131 | 132 | IndexOutOfBoundsException - If the index argument is negative or not less than the length of this byte array. 133 | 134 | --- 135 | 136 | ### bytesAt 137 | 138 | **Signature:** `bytesAt(index : Number, length : Number) : Bytes` 139 | 140 | **Description:** Return a new Bytes object containing the subsequence of this object's bytes specified by the index and length parameters. The returned object is a new view onto the same data, no data is copied. 141 | 142 | **Parameters:** 143 | 144 | - `index`: The initial index for the new view, inclusive. 145 | - `length`: The number of bytes visible in the new view. 146 | 147 | **Returns:** 148 | 149 | a new Bytes object representing a subsequence of this Bytes object. 150 | 151 | **Throws:** 152 | 153 | ArrayIndexOutOfBoundsException - If index < 0 or index > getLength() or index + length > getLength() 154 | IllegalArgumentException - If length < 0 155 | 156 | --- 157 | 158 | ### getLength 159 | 160 | **Signature:** `getLength() : Number` 161 | 162 | **Description:** Returns the number of bytes represented by this object. 163 | 164 | **Returns:** 165 | 166 | The number of bytes. 167 | 168 | --- 169 | 170 | ### intAt 171 | 172 | **Signature:** `intAt(index : Number) : Number` 173 | 174 | **Description:** Absolute get method for reading a signed integer value (32 bit) in network byte order(= big endian). 175 | 176 | **Parameters:** 177 | 178 | - `index`: The byte index at which to read the number. 179 | 180 | **Returns:** 181 | 182 | The read number. 183 | 184 | **Throws:** 185 | 186 | IndexOutOfBoundsException - If index is negative or not smaller than the number of bytes minus three. 187 | 188 | --- 189 | 190 | ### reverse 191 | 192 | **Signature:** `reverse() : Bytes` 193 | 194 | **Description:** Return a new Bytes object which has the same bytes as this one in reverse order. 195 | 196 | **Returns:** 197 | 198 | a new Bytes object representing the reverse of this Bytes object. 199 | 200 | --- 201 | 202 | ### shortAt 203 | 204 | **Signature:** `shortAt(index : Number) : Number` 205 | 206 | **Description:** Absolute get method for reading a signed short value (16 bit) in network byte order(= big endian). 207 | 208 | **Parameters:** 209 | 210 | - `index`: The byte index at which to read the number. 211 | 212 | **Returns:** 213 | 214 | The read number. 215 | 216 | **Throws:** 217 | 218 | IndexOutOfBoundsException - If index is negative or not smaller than the number of bytes minus one. 219 | 220 | --- 221 | 222 | ### toString 223 | 224 | **Signature:** `toString() : String` 225 | 226 | **Description:** Constructs a new String by decoding this array of bytes using the default encoding. Convenience for toString( "UTF-8" ). Limitation: The method is protected by the quota api.jsStringLength that prevents creation of too long strings. 227 | 228 | **Returns:** 229 | 230 | A String representing the decoded array of bytes. 231 | 232 | --- 233 | 234 | ### toString 235 | 236 | **Signature:** `toString(encoding : String) : String` 237 | 238 | **Description:** Constructs a new String by decoding this array of bytes using the specified encoding. Limitation: The method is protected by the quota api.jsStringLength that prevents creation of too long strings. 239 | 240 | **Parameters:** 241 | 242 | - `encoding`: The name of a supported encoding. 243 | 244 | **Returns:** 245 | 246 | A String representing the decoded array of bytes. 247 | 248 | **Throws:** 249 | 250 | IllegalArgumentException - If the named encoding is not supported. 251 | 252 | --- ``` -------------------------------------------------------------------------------- /docs/dw_order/ShippingLocation.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.order 2 | 3 | # Class ShippingLocation 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.order.ShippingLocation 9 | 10 | ## Description 11 | 12 | Represents a specific location for a shipment. Note: this class allows access to sensitive personal and private information. Pay attention to appropriate legal and regulatory requirements related to this data. 13 | 14 | ## Properties 15 | 16 | ### address1 17 | 18 | **Type:** String 19 | 20 | The shipping location's first address. 21 | 22 | ### address2 23 | 24 | **Type:** String 25 | 26 | The shipping location's second address. 27 | 28 | ### city 29 | 30 | **Type:** String 31 | 32 | The shipping location's city. 33 | 34 | ### countryCode 35 | 36 | **Type:** String 37 | 38 | The shipping location's country code. 39 | 40 | ### postalCode 41 | 42 | **Type:** String 43 | 44 | The shipping location's postal code. 45 | 46 | ### postBox 47 | 48 | **Type:** String 49 | 50 | The shipping location's post box. 51 | 52 | ### stateCode 53 | 54 | **Type:** String 55 | 56 | The shipping location's state code. 57 | 58 | ### suite 59 | 60 | **Type:** String 61 | 62 | The shipping location's suite. 63 | 64 | ## Constructor Summary 65 | 66 | ShippingLocation() Constructs a new shipping location. 67 | 68 | ShippingLocation(address : CustomerAddress) Constructs a new shipping location and initializes it with the values of the specified address object. 69 | 70 | ShippingLocation(address : OrderAddress) Constructs a new shipping location and initializes it with the values of the specified address object. 71 | 72 | ## Method Summary 73 | 74 | ### getAddress1 75 | 76 | **Signature:** `getAddress1() : String` 77 | 78 | Returns the shipping location's first address. 79 | 80 | ### getAddress2 81 | 82 | **Signature:** `getAddress2() : String` 83 | 84 | Returns the shipping location's second address. 85 | 86 | ### getCity 87 | 88 | **Signature:** `getCity() : String` 89 | 90 | Returns the shipping location's city. 91 | 92 | ### getCountryCode 93 | 94 | **Signature:** `getCountryCode() : String` 95 | 96 | Returns the shipping location's country code. 97 | 98 | ### getPostalCode 99 | 100 | **Signature:** `getPostalCode() : String` 101 | 102 | Returns the shipping location's postal code. 103 | 104 | ### getPostBox 105 | 106 | **Signature:** `getPostBox() : String` 107 | 108 | Returns the shipping location's post box. 109 | 110 | ### getStateCode 111 | 112 | **Signature:** `getStateCode() : String` 113 | 114 | Returns the shipping location's state code. 115 | 116 | ### getSuite 117 | 118 | **Signature:** `getSuite() : String` 119 | 120 | Returns the shipping location's suite. 121 | 122 | ### setAddress1 123 | 124 | **Signature:** `setAddress1(aValue : String) : void` 125 | 126 | Sets the shipping location's first address. 127 | 128 | ### setAddress2 129 | 130 | **Signature:** `setAddress2(aValue : String) : void` 131 | 132 | Sets the shipping location's second address. 133 | 134 | ### setCity 135 | 136 | **Signature:** `setCity(aValue : String) : void` 137 | 138 | Sets the shipping location's city. 139 | 140 | ### setCountryCode 141 | 142 | **Signature:** `setCountryCode(aValue : String) : void` 143 | 144 | Sets the shipping location's country code. 145 | 146 | ### setPostalCode 147 | 148 | **Signature:** `setPostalCode(aValue : String) : void` 149 | 150 | Sets the shipping location's postal code. 151 | 152 | ### setPostBox 153 | 154 | **Signature:** `setPostBox(aValue : String) : void` 155 | 156 | Sets the shipping location's post box. 157 | 158 | ### setStateCode 159 | 160 | **Signature:** `setStateCode(aValue : String) : void` 161 | 162 | Sets the shipping location's state code. 163 | 164 | ### setSuite 165 | 166 | **Signature:** `setSuite(aValue : String) : void` 167 | 168 | Sets the shipping location's suite. 169 | 170 | ## Constructor Detail 171 | 172 | ## Method Detail 173 | 174 | ## Method Details 175 | 176 | ### getAddress1 177 | 178 | **Signature:** `getAddress1() : String` 179 | 180 | **Description:** Returns the shipping location's first address. 181 | 182 | **Returns:** 183 | 184 | the shipping location's first address. 185 | 186 | --- 187 | 188 | ### getAddress2 189 | 190 | **Signature:** `getAddress2() : String` 191 | 192 | **Description:** Returns the shipping location's second address. 193 | 194 | **Returns:** 195 | 196 | the shipping location's second address. 197 | 198 | --- 199 | 200 | ### getCity 201 | 202 | **Signature:** `getCity() : String` 203 | 204 | **Description:** Returns the shipping location's city. 205 | 206 | **Returns:** 207 | 208 | the shipping location's city. 209 | 210 | --- 211 | 212 | ### getCountryCode 213 | 214 | **Signature:** `getCountryCode() : String` 215 | 216 | **Description:** Returns the shipping location's country code. 217 | 218 | **Returns:** 219 | 220 | the shipping location's country code. 221 | 222 | --- 223 | 224 | ### getPostalCode 225 | 226 | **Signature:** `getPostalCode() : String` 227 | 228 | **Description:** Returns the shipping location's postal code. 229 | 230 | **Returns:** 231 | 232 | the shipping location's postal code. 233 | 234 | --- 235 | 236 | ### getPostBox 237 | 238 | **Signature:** `getPostBox() : String` 239 | 240 | **Description:** Returns the shipping location's post box. 241 | 242 | **Returns:** 243 | 244 | the shipping location's post box. 245 | 246 | --- 247 | 248 | ### getStateCode 249 | 250 | **Signature:** `getStateCode() : String` 251 | 252 | **Description:** Returns the shipping location's state code. 253 | 254 | **Returns:** 255 | 256 | the shipping location's state code. 257 | 258 | --- 259 | 260 | ### getSuite 261 | 262 | **Signature:** `getSuite() : String` 263 | 264 | **Description:** Returns the shipping location's suite. 265 | 266 | **Returns:** 267 | 268 | the shipping location's suite. 269 | 270 | --- 271 | 272 | ### setAddress1 273 | 274 | **Signature:** `setAddress1(aValue : String) : void` 275 | 276 | **Description:** Sets the shipping location's first address. 277 | 278 | **Parameters:** 279 | 280 | - `aValue`: the shipping location's first address. 281 | 282 | --- 283 | 284 | ### setAddress2 285 | 286 | **Signature:** `setAddress2(aValue : String) : void` 287 | 288 | **Description:** Sets the shipping location's second address. 289 | 290 | **Parameters:** 291 | 292 | - `aValue`: the shipping location's second address. 293 | 294 | --- 295 | 296 | ### setCity 297 | 298 | **Signature:** `setCity(aValue : String) : void` 299 | 300 | **Description:** Sets the shipping location's city. 301 | 302 | **Parameters:** 303 | 304 | - `aValue`: the shipping location's city. 305 | 306 | --- 307 | 308 | ### setCountryCode 309 | 310 | **Signature:** `setCountryCode(aValue : String) : void` 311 | 312 | **Description:** Sets the shipping location's country code. 313 | 314 | **Parameters:** 315 | 316 | - `aValue`: the shipping location's country code. 317 | 318 | --- 319 | 320 | ### setPostalCode 321 | 322 | **Signature:** `setPostalCode(aValue : String) : void` 323 | 324 | **Description:** Sets the shipping location's postal code. 325 | 326 | **Parameters:** 327 | 328 | - `aValue`: the shipping location's postal code. 329 | 330 | --- 331 | 332 | ### setPostBox 333 | 334 | **Signature:** `setPostBox(aValue : String) : void` 335 | 336 | **Description:** Sets the shipping location's post box. 337 | 338 | **Parameters:** 339 | 340 | - `aValue`: the shipping location's post box. 341 | 342 | --- 343 | 344 | ### setStateCode 345 | 346 | **Signature:** `setStateCode(aValue : String) : void` 347 | 348 | **Description:** Sets the shipping location's state code. 349 | 350 | **Parameters:** 351 | 352 | - `aValue`: the shipping location's state code. 353 | 354 | --- 355 | 356 | ### setSuite 357 | 358 | **Signature:** `setSuite(aValue : String) : void` 359 | 360 | **Description:** Sets the shipping location's suite. 361 | 362 | **Parameters:** 363 | 364 | - `aValue`: the shipping location's suite. 365 | 366 | --- ``` -------------------------------------------------------------------------------- /docs/dw_catalog/Recommendation.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.catalog 2 | 3 | # Class Recommendation 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.object.PersistentObject 9 | - dw.object.ExtensibleObject 10 | - dw.catalog.Recommendation 11 | 12 | ## Description 13 | 14 | Represents a recommendation in Commerce Cloud Digital. 15 | 16 | ## Constants 17 | 18 | ### RECOMMENDATION_TYPE_CROSS_SELL 19 | 20 | **Type:** Number = 1 21 | 22 | Represents a cross-sell recommendation. 23 | 24 | ### RECOMMENDATION_TYPE_OTHER 25 | 26 | **Type:** Number = 3 27 | 28 | Represents a recommendation that is neither a cross-sell or an up-sell. 29 | 30 | ### RECOMMENDATION_TYPE_UP_SELL 31 | 32 | **Type:** Number = 2 33 | 34 | Represents an up-sell recommendation. 35 | 36 | ## Properties 37 | 38 | ### calloutMsg 39 | 40 | **Type:** MarkupText (Read Only) 41 | 42 | The recommendation's callout message in the current locale. 43 | 44 | ### catalog 45 | 46 | **Type:** Catalog (Read Only) 47 | 48 | Return the catalog containing the recommendation. 49 | 50 | ### image 51 | 52 | **Type:** MediaFile (Read Only) 53 | 54 | The recommendation's image. 55 | 56 | ### longDescription 57 | 58 | **Type:** MarkupText (Read Only) 59 | 60 | The recommendation's long description in the current locale. 61 | 62 | ### name 63 | 64 | **Type:** String (Read Only) 65 | 66 | The name of the recommended item in the current locale. 67 | 68 | ### recommendationType 69 | 70 | **Type:** Number (Read Only) 71 | 72 | The type of the recommendation. 73 | 74 | ### recommendedItem 75 | 76 | **Type:** Object (Read Only) 77 | 78 | Return a reference to the recommended item. This will always be an 79 | object of type dw.catalog.Product since this is the only 80 | currently supported recommendation target type. 81 | 82 | ### recommendedItemID 83 | 84 | **Type:** String (Read Only) 85 | 86 | Return the ID of the recommended item. This will always be a product 87 | ID since this is the only currently supported recommendation target 88 | type. 89 | 90 | ### shortDescription 91 | 92 | **Type:** MarkupText (Read Only) 93 | 94 | The recommendation's short description in the current locale. 95 | 96 | ### sourceItem 97 | 98 | **Type:** Object (Read Only) 99 | 100 | Return a reference to the source item. This will be an object of type 101 | dw.catalog.Product or dw.catalog.Category. 102 | 103 | ### sourceItemID 104 | 105 | **Type:** String (Read Only) 106 | 107 | Return the ID of the recommendation source item. This will either be a 108 | product ID or category name. 109 | 110 | ## Constructor Summary 111 | 112 | ## Method Summary 113 | 114 | ### getCalloutMsg 115 | 116 | **Signature:** `getCalloutMsg() : MarkupText` 117 | 118 | Returns the recommendation's callout message in the current locale. 119 | 120 | ### getCatalog 121 | 122 | **Signature:** `getCatalog() : Catalog` 123 | 124 | Return the catalog containing the recommendation. 125 | 126 | ### getImage 127 | 128 | **Signature:** `getImage() : MediaFile` 129 | 130 | Returns the recommendation's image. 131 | 132 | ### getLongDescription 133 | 134 | **Signature:** `getLongDescription() : MarkupText` 135 | 136 | Returns the recommendation's long description in the current locale. 137 | 138 | ### getName 139 | 140 | **Signature:** `getName() : String` 141 | 142 | Returns the name of the recommended item in the current locale. 143 | 144 | ### getRecommendationType 145 | 146 | **Signature:** `getRecommendationType() : Number` 147 | 148 | Returns the type of the recommendation. 149 | 150 | ### getRecommendedItem 151 | 152 | **Signature:** `getRecommendedItem() : Object` 153 | 154 | Return a reference to the recommended item. 155 | 156 | ### getRecommendedItemID 157 | 158 | **Signature:** `getRecommendedItemID() : String` 159 | 160 | Return the ID of the recommended item. 161 | 162 | ### getShortDescription 163 | 164 | **Signature:** `getShortDescription() : MarkupText` 165 | 166 | Returns the recommendation's short description in the current locale. 167 | 168 | ### getSourceItem 169 | 170 | **Signature:** `getSourceItem() : Object` 171 | 172 | Return a reference to the source item. 173 | 174 | ### getSourceItemID 175 | 176 | **Signature:** `getSourceItemID() : String` 177 | 178 | Return the ID of the recommendation source item. 179 | 180 | ## Method Detail 181 | 182 | ## Method Details 183 | 184 | ### getCalloutMsg 185 | 186 | **Signature:** `getCalloutMsg() : MarkupText` 187 | 188 | **Description:** Returns the recommendation's callout message in the current locale. 189 | 190 | **Returns:** 191 | 192 | the recommendation's callout message in the current locale, or null if it wasn't found. 193 | 194 | --- 195 | 196 | ### getCatalog 197 | 198 | **Signature:** `getCatalog() : Catalog` 199 | 200 | **Description:** Return the catalog containing the recommendation. 201 | 202 | **Returns:** 203 | 204 | the catalog containing the recommendation. 205 | 206 | --- 207 | 208 | ### getImage 209 | 210 | **Signature:** `getImage() : MediaFile` 211 | 212 | **Description:** Returns the recommendation's image. 213 | 214 | **Returns:** 215 | 216 | the recommendation's image. 217 | 218 | --- 219 | 220 | ### getLongDescription 221 | 222 | **Signature:** `getLongDescription() : MarkupText` 223 | 224 | **Description:** Returns the recommendation's long description in the current locale. 225 | 226 | **Returns:** 227 | 228 | The recommendation's long description in the current locale, or null if it wasn't found. 229 | 230 | --- 231 | 232 | ### getName 233 | 234 | **Signature:** `getName() : String` 235 | 236 | **Description:** Returns the name of the recommended item in the current locale. 237 | 238 | **Returns:** 239 | 240 | The name of the recommended item for the current locale, or null if it wasn't found. 241 | 242 | --- 243 | 244 | ### getRecommendationType 245 | 246 | **Signature:** `getRecommendationType() : Number` 247 | 248 | **Description:** Returns the type of the recommendation. 249 | 250 | **Returns:** 251 | 252 | the type of the recommendation expressed as an integer. 253 | 254 | --- 255 | 256 | ### getRecommendedItem 257 | 258 | **Signature:** `getRecommendedItem() : Object` 259 | 260 | **Description:** Return a reference to the recommended item. This will always be an object of type dw.catalog.Product since this is the only currently supported recommendation target type. 261 | 262 | **Returns:** 263 | 264 | the recommended item, possibly null if the item does not exist. 265 | 266 | --- 267 | 268 | ### getRecommendedItemID 269 | 270 | **Signature:** `getRecommendedItemID() : String` 271 | 272 | **Description:** Return the ID of the recommended item. This will always be a product ID since this is the only currently supported recommendation target type. 273 | 274 | **Returns:** 275 | 276 | the recommended item ID. 277 | 278 | --- 279 | 280 | ### getShortDescription 281 | 282 | **Signature:** `getShortDescription() : MarkupText` 283 | 284 | **Description:** Returns the recommendation's short description in the current locale. 285 | 286 | **Returns:** 287 | 288 | the recommendations's short description in the current locale, or null if it wasn't found. 289 | 290 | --- 291 | 292 | ### getSourceItem 293 | 294 | **Signature:** `getSourceItem() : Object` 295 | 296 | **Description:** Return a reference to the source item. This will be an object of type dw.catalog.Product or dw.catalog.Category. 297 | 298 | **Returns:** 299 | 300 | the source item. 301 | 302 | --- 303 | 304 | ### getSourceItemID 305 | 306 | **Signature:** `getSourceItemID() : String` 307 | 308 | **Description:** Return the ID of the recommendation source item. This will either be a product ID or category name. 309 | 310 | **Returns:** 311 | 312 | the source item ID. 313 | 314 | --- ``` -------------------------------------------------------------------------------- /docs/dw_campaign/BonusChoiceDiscount.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.campaign 2 | 3 | # Class BonusChoiceDiscount 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.campaign.Discount 9 | - dw.campaign.BonusChoiceDiscount 10 | 11 | ## Description 12 | 13 | Represents a choice of bonus products discount in the discount plan, for example "Choose 3 DVDs from a list of 20 options with your purchase of any DVD player." 14 | 15 | ## Properties 16 | 17 | ### bonusProducts 18 | 19 | **Type:** List (Read Only) 20 | 21 | Get the list of bonus products which the customer is allowed to choose 22 | from for this discount. This list is configured by a merchant entering a 23 | list of SKUs for the discount. Products which do not exist in the system, 24 | or are offline, or are not assigned to a category in the site catalog are 25 | filtered out. Unavailable (i.e. out-of-stock) products are NOT filtered 26 | out. This allows merchants to display out-of-stock bonus products with 27 | appropriate messaging. 28 | 29 | If a returned product is a master product, the customer is entitled to 30 | choose from any variant. If the product is an option product, the 31 | customer is entitled to choose any value for each option. Since the 32 | promotions engine does not touch the value of the product option line 33 | items, it is the responsibility of custom code to set option prices. 34 | 35 | If the promotion is rule based, then this method will return an empty list. 36 | A ProductSearchModel should be used to return the bonus products the 37 | customer may choose from instead. See 38 | ProductSearchModel.PROMOTION_PRODUCT_TYPE_BONUS and 39 | ProductSearchModel.setPromotionID(String) 40 | 41 | ### maxBonusItems 42 | 43 | **Type:** Number (Read Only) 44 | 45 | The maximum number of bonus items that a customer is entitled to 46 | select for this discount. 47 | 48 | ### ruleBased 49 | 50 | **Type:** ProductSearchModel (Static) (Read Only) 51 | 52 | Returns true if this is a "rule based" bonus choice discount. 53 | For such discounts, there is no static list of bonus products 54 | associated with the discount but rather a discounted product 55 | rule associated with the promotion which defines the bonus 56 | products. To retrieve the list of selectable bonus products for 57 | display in the storefront, it is necessary to search for the 58 | bonus products using the ProductSearchModel 59 | API since the method getBonusProducts() in this class 60 | will always return an empty list. Furthermore, for rule based 61 | bonus-choice discounts, getBonusProductPrice(Product) 62 | will always return a price of 0.00 for bonus products. 63 | 64 | ## Constructor Summary 65 | 66 | ## Method Summary 67 | 68 | ### getBonusProductPrice 69 | 70 | **Signature:** `getBonusProductPrice(product : Product) : Number` 71 | 72 | Get the effective price for the passed bonus product. 73 | 74 | ### getBonusProducts 75 | 76 | **Signature:** `getBonusProducts() : List` 77 | 78 | Get the list of bonus products which the customer is allowed to choose from for this discount. 79 | 80 | ### getMaxBonusItems 81 | 82 | **Signature:** `getMaxBonusItems() : Number` 83 | 84 | Returns the maximum number of bonus items that a customer is entitled to select for this discount. 85 | 86 | ### isRuleBased 87 | 88 | **Signature:** `isRuleBased() : boolean` 89 | 90 | Returns true if this is a "rule based" bonus choice discount. 91 | 92 | ## Method Detail 93 | 94 | ## Method Details 95 | 96 | ### getBonusProductPrice 97 | 98 | **Signature:** `getBonusProductPrice(product : Product) : Number` 99 | 100 | **Description:** Get the effective price for the passed bonus product. This is expected to be one of the products returned by getBonusProducts() with one exception: If a master product is configured as a bonus product, this implies that a customer may choose from any of its variants. In this case, it is allowed to pass in a variant to this method and a price will be returned. If the passed product is not a valid bonus product, this method throws an exception. 101 | 102 | **Parameters:** 103 | 104 | - `product`: The bonus product to retrieve a price for, must not be null. 105 | 106 | **Returns:** 107 | 108 | The price of the passed bonus product as a Number. 109 | 110 | --- 111 | 112 | ### getBonusProducts 113 | 114 | **Signature:** `getBonusProducts() : List` 115 | 116 | **Description:** Get the list of bonus products which the customer is allowed to choose from for this discount. This list is configured by a merchant entering a list of SKUs for the discount. Products which do not exist in the system, or are offline, or are not assigned to a category in the site catalog are filtered out. Unavailable (i.e. out-of-stock) products are NOT filtered out. This allows merchants to display out-of-stock bonus products with appropriate messaging. If a returned product is a master product, the customer is entitled to choose from any variant. If the product is an option product, the customer is entitled to choose any value for each option. Since the promotions engine does not touch the value of the product option line items, it is the responsibility of custom code to set option prices. If the promotion is rule based, then this method will return an empty list. A ProductSearchModel should be used to return the bonus products the customer may choose from instead. See ProductSearchModel.PROMOTION_PRODUCT_TYPE_BONUS and ProductSearchModel.setPromotionID(String) 117 | 118 | **Returns:** 119 | 120 | An ordered list of bonus products that the customer may choose from for this discount. 121 | 122 | --- 123 | 124 | ### getMaxBonusItems 125 | 126 | **Signature:** `getMaxBonusItems() : Number` 127 | 128 | **Description:** Returns the maximum number of bonus items that a customer is entitled to select for this discount. 129 | 130 | **Returns:** 131 | 132 | The maximum number of bonus items that this discount permits a customer to select. 133 | 134 | --- 135 | 136 | ### isRuleBased 137 | 138 | **Signature:** `isRuleBased() : boolean` 139 | 140 | **Description:** Returns true if this is a "rule based" bonus choice discount. For such discounts, there is no static list of bonus products associated with the discount but rather a discounted product rule associated with the promotion which defines the bonus products. To retrieve the list of selectable bonus products for display in the storefront, it is necessary to search for the bonus products using the ProductSearchModel API since the method getBonusProducts() in this class will always return an empty list. Furthermore, for rule based bonus-choice discounts, getBonusProductPrice(Product) will always return a price of 0.00 for bonus products. 141 | 142 | **Returns:** 143 | 144 | True if this is a rule-based bonus-choice discount, or false if this discount defines a simple static list of bonus products. 145 | 146 | --- ``` -------------------------------------------------------------------------------- /docs/dw_svc/HTTPServiceDefinition.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.svc 2 | 3 | # Class HTTPServiceDefinition 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.svc.ServiceDefinition 9 | - dw.svc.HTTPServiceDefinition 10 | 11 | ## Description 12 | 13 | Represents an HTTP Service Definition. The HTTP Service will use the return value of the createRequest callback as the request body (if supported by the HTTP method). If this is an array of non-null HTTPRequestPart objects, then a multi-part request will be formed. Otherwise the object is converted to a String and used. See also XML.toXMLString() and JSON.stringify(Object), which must be explicitly called if needed. 14 | 15 | ## Properties 16 | 17 | ### authentication 18 | 19 | **Type:** String 20 | 21 | The authentication type. 22 | 23 | ### cachingTTL 24 | 25 | **Type:** Number 26 | 27 | The caching time to live value. 28 | 29 | ### encoding 30 | 31 | **Type:** String 32 | 33 | The request body encoding to declare. 34 | 35 | ### outFile 36 | 37 | **Type:** File 38 | 39 | The output file, or null if there is none. 40 | 41 | ### requestMethod 42 | 43 | **Type:** String 44 | 45 | The request method. 46 | 47 | ## Constructor Summary 48 | 49 | ## Method Summary 50 | 51 | ### addHeader 52 | 53 | **Signature:** `addHeader(name : String, val : String) : HTTPServiceDefinition` 54 | 55 | Adds an HTTP Header. 56 | 57 | ### addParam 58 | 59 | **Signature:** `addParam(name : String, val : String) : HTTPServiceDefinition` 60 | 61 | Adds a query parameter that will be appended to the URL. 62 | 63 | ### getAuthentication 64 | 65 | **Signature:** `getAuthentication() : String` 66 | 67 | Returns the authentication type. 68 | 69 | ### getCachingTTL 70 | 71 | **Signature:** `getCachingTTL() : Number` 72 | 73 | Returns the caching time to live value. 74 | 75 | ### getEncoding 76 | 77 | **Signature:** `getEncoding() : String` 78 | 79 | Returns the request body encoding to declare. 80 | 81 | ### getOutFile 82 | 83 | **Signature:** `getOutFile() : File` 84 | 85 | Returns the output file, or null if there is none. 86 | 87 | ### getRequestMethod 88 | 89 | **Signature:** `getRequestMethod() : String` 90 | 91 | Returns the request method. 92 | 93 | ### setAuthentication 94 | 95 | **Signature:** `setAuthentication(authentication : String) : HTTPServiceDefinition` 96 | 97 | Sets the type of authentication. 98 | 99 | ### setCachingTTL 100 | 101 | **Signature:** `setCachingTTL(ttl : Number) : HTTPServiceDefinition` 102 | 103 | Enables caching for GET requests. 104 | 105 | ### setEncoding 106 | 107 | **Signature:** `setEncoding(encoding : String) : HTTPServiceDefinition` 108 | 109 | Sets the encoding of the request body (if any). 110 | 111 | ### setOutFile 112 | 113 | **Signature:** `setOutFile(outFile : File) : HTTPServiceDefinition` 114 | 115 | Sets the output file in which to write the HTTP response body. 116 | 117 | ### setRequestMethod 118 | 119 | **Signature:** `setRequestMethod(requestMethod : String) : HTTPServiceDefinition` 120 | 121 | Sets the HTTP request method. 122 | 123 | ## Method Detail 124 | 125 | ## Method Details 126 | 127 | ### addHeader 128 | 129 | **Signature:** `addHeader(name : String, val : String) : HTTPServiceDefinition` 130 | 131 | **Description:** Adds an HTTP Header. 132 | 133 | **Parameters:** 134 | 135 | - `name`: Header name. 136 | - `val`: Header value. 137 | 138 | **Returns:** 139 | 140 | this HTTP Service Definition. 141 | 142 | --- 143 | 144 | ### addParam 145 | 146 | **Signature:** `addParam(name : String, val : String) : HTTPServiceDefinition` 147 | 148 | **Description:** Adds a query parameter that will be appended to the URL. 149 | 150 | **Parameters:** 151 | 152 | - `name`: Parameter name. 153 | - `val`: Parameter value. 154 | 155 | **Returns:** 156 | 157 | this HTTP Service Definition. 158 | 159 | --- 160 | 161 | ### getAuthentication 162 | 163 | **Signature:** `getAuthentication() : String` 164 | 165 | **Description:** Returns the authentication type. 166 | 167 | **Returns:** 168 | 169 | Authentication type. 170 | 171 | --- 172 | 173 | ### getCachingTTL 174 | 175 | **Signature:** `getCachingTTL() : Number` 176 | 177 | **Description:** Returns the caching time to live value. 178 | 179 | **Returns:** 180 | 181 | The caching time to live value in seconds. 182 | 183 | **See Also:** 184 | 185 | setCachingTTL(Number) 186 | 187 | --- 188 | 189 | ### getEncoding 190 | 191 | **Signature:** `getEncoding() : String` 192 | 193 | **Description:** Returns the request body encoding to declare. 194 | 195 | **Returns:** 196 | 197 | Request encoding. 198 | 199 | --- 200 | 201 | ### getOutFile 202 | 203 | **Signature:** `getOutFile() : File` 204 | 205 | **Description:** Returns the output file, or null if there is none. 206 | 207 | **Returns:** 208 | 209 | Output file or null. 210 | 211 | --- 212 | 213 | ### getRequestMethod 214 | 215 | **Signature:** `getRequestMethod() : String` 216 | 217 | **Description:** Returns the request method. 218 | 219 | **Returns:** 220 | 221 | HTTP Request method. 222 | 223 | --- 224 | 225 | ### setAuthentication 226 | 227 | **Signature:** `setAuthentication(authentication : String) : HTTPServiceDefinition` 228 | 229 | **Description:** Sets the type of authentication. Valid values include "BASIC" and "NONE". The default value is BASIC. 230 | 231 | **Parameters:** 232 | 233 | - `authentication`: Type of authentication. 234 | 235 | **Returns:** 236 | 237 | this HTTP Service Definition. 238 | 239 | --- 240 | 241 | ### setCachingTTL 242 | 243 | **Signature:** `setCachingTTL(ttl : Number) : HTTPServiceDefinition` 244 | 245 | **Description:** Enables caching for GET requests. This only caches status codes 2xx with a content length and size of less than 50k that are not immediately written to file. The URL and the user name are used as cache keys. The total size of cacheable content and the number of cached items is limited and automatically managed by the system. Cache control information sent by the remote server is ignored. Caching HTTP responses should be done very carefully. It is important to ensure that the response really depends only on the URL and doesn't contain any remote state information or time information which is independent of the URL. It is also important to verify that the application sends exactly the same URL multiple times. 246 | 247 | **Parameters:** 248 | 249 | - `ttl`: The time to live for the cached content in seconds. A value of 0 or less disables caching. 250 | 251 | **See Also:** 252 | 253 | HTTPClient.enableCaching(Number) 254 | 255 | --- 256 | 257 | ### setEncoding 258 | 259 | **Signature:** `setEncoding(encoding : String) : HTTPServiceDefinition` 260 | 261 | **Description:** Sets the encoding of the request body (if any). The default value is UTF-8. 262 | 263 | **Parameters:** 264 | 265 | - `encoding`: Encoding of the request body. 266 | 267 | **Returns:** 268 | 269 | this HTTP Service Definition. 270 | 271 | --- 272 | 273 | ### setOutFile 274 | 275 | **Signature:** `setOutFile(outFile : File) : HTTPServiceDefinition` 276 | 277 | **Description:** Sets the output file in which to write the HTTP response body. The default behavior is to not write a file. 278 | 279 | **Parameters:** 280 | 281 | - `outFile`: Output file, or null to disable. 282 | 283 | **Returns:** 284 | 285 | this HTTP Service Definition. 286 | 287 | --- 288 | 289 | ### setRequestMethod 290 | 291 | **Signature:** `setRequestMethod(requestMethod : String) : HTTPServiceDefinition` 292 | 293 | **Description:** Sets the HTTP request method. Valid values include GET, PUT, POST, and DELETE. The default value is POST. 294 | 295 | **Parameters:** 296 | 297 | - `requestMethod`: HTTP request method. 298 | 299 | **Returns:** 300 | 301 | this HTTP Service Definition. 302 | 303 | --- ``` -------------------------------------------------------------------------------- /docs/sfra/order.md: -------------------------------------------------------------------------------- ```markdown 1 | # SFRA Order Model 2 | 3 | ## Overview 4 | 5 | The Order model represents an order or basket in SFRA applications, providing comprehensive or## Helper Functions 6 | 7 | ### getCheckoutStepInformation(lineItemContainer) 8 | Returns checkout step completion status. 9 | 10 | **Parameters:** 11 | - `lineItemContainer` (dw.order.LineItemCtnr) - Order or basket 12 | 13 | **Returns:** Object - Checkout step status with shipping and billing completion flags 14 | 15 | ### getFirstProductLineItem(productLineItemsModel) 16 | Returns image information for the first product line item. 17 | 18 | **Parameters:** 19 | - `productLineItemsModel` (Object) - Product line items model 20 | 21 | **Returns:** Object | null - Object with imageURL, alt, and title properties, or null 22 | 23 | ### getAssociatedAddress(lineItemContainer, customer) 24 | Returns the matching address ID for a billing address. 25 | 26 | **Parameters:** 27 | - `lineItemContainer` (dw.order.LineItemCtnr) - Order or basket 28 | - `customer` (Object) - Customer model 29 | 30 | **Returns:** string | boolean - Matching shipment UUID or customer address ID, or false if no matchuding line items, totals, billing, shipping, and checkout step status. It's used for order confirmation pages, order history, and checkout processes. 31 | 32 | ## Constructor 33 | 34 | ```javascript 35 | function OrderModel(lineItemContainer, options) 36 | ``` 37 | 38 | Creates an Order model instance from a line item container (order or basket). 39 | 40 | ### Parameters 41 | 42 | - `lineItemContainer` (dw.order.LineItemCtnr) - Order or basket object 43 | - `options` (Object) - Configuration options including: 44 | - `config` (Object) - Configuration object with `numberOfLineItems` setting 45 | - `countryCode` (string) - Current request country code 46 | - `customer` (Object) - Customer object 47 | - `containerView` (string) - View context ('order' or 'basket') 48 | - `usingMultiShipping` (boolean) - Whether using multiple shipping addresses 49 | - `shippable` (boolean) - Whether order contains shippable items 50 | 51 | ## Properties 52 | 53 | ### resources 54 | **Type:** Object 55 | 56 | Resource strings for order-related messaging and labels. 57 | 58 | ### orderNumber 59 | **Type:** string | null 60 | 61 | The order number for completed orders, or null for baskets. 62 | 63 | ### creationDate 64 | **Type:** Date | null 65 | 66 | Date when the order was created, or null for baskets. 67 | 68 | ### orderEmail 69 | **Type:** string 70 | 71 | Customer email address associated with the order. 72 | 73 | ### orderStatus 74 | **Type:** Object | null 75 | 76 | Order status information, or null for baskets. 77 | 78 | ### usingMultiShipping 79 | **Type:** boolean 80 | 81 | Indicates whether the order uses multiple shipping addresses. 82 | 83 | ### shippable 84 | **Type:** boolean 85 | 86 | Indicates whether the order contains shippable items. 87 | 88 | ### priceTotal 89 | **Type:** string | null 90 | 91 | Formatted grand total amount from the totals model. 92 | 93 | ### productQuantityTotal 94 | **Type:** number | null 95 | 96 | Total quantity of all products in the order. 97 | 98 | ## Conditional Properties (when numberOfLineItems = '*') 99 | 100 | ### totals 101 | **Type:** TotalsModel 102 | 103 | Order totals including subtotals, taxes, shipping costs, and grand total. 104 | 105 | ### lineItemTotal 106 | **Type:** number | null 107 | 108 | Total number of line items in the order. 109 | 110 | ### steps 111 | **Type:** Object | null 112 | 113 | Checkout step information with completion status. 114 | 115 | ### items 116 | **Type:** ProductLineItemsModel 117 | 118 | Product line items model containing all order items with detailed product information. 119 | 120 | ### billing 121 | **Type:** BillingModel 122 | 123 | Billing information including billing address and payment methods. 124 | 125 | ### shipping 126 | **Type:** Array<Object> 127 | 128 | Array of shipping models containing shipping address and method information for each shipment. 129 | 130 | ## Conditional Properties (when numberOfLineItems = 'single') 131 | 132 | ### firstLineItem 133 | **Type:** Object | null 134 | 135 | Information about the first product line item including image details. 136 | 137 | ### shippedToFirstName 138 | **Type:** string 139 | 140 | First name from the first shipment's shipping address. 141 | 142 | ### shippedToLastName 143 | **Type:** string 144 | 145 | Last name from the first shipment's shipping address. 146 | 147 | ## Helper Functions 148 | 149 | ### getCheckoutStepInformation(lineItemContainer) 150 | Creates checkout step completion information. 151 | 152 | **Parameters:** 153 | - `lineItemContainer` (dw.order.LineItemCtnr) - Order or basket container 154 | 155 | **Returns:** Object - Checkout step status information 156 | 157 | ### getFirstProductLineItem(productLineItemsModel) 158 | Returns image information for the first product line item. 159 | 160 | **Parameters:** 161 | - `productLineItemsModel` (Object) - Product line items model 162 | 163 | **Returns:** Object | null - First item image information or null 164 | 165 | ### getAssociatedAddress(basket, customer) 166 | Returns the matching address ID for a billing address. 167 | 168 | **Parameters:** 169 | - `basket` (dw.order.Basket) - Customer's basket 170 | - `customer` (Object) - Customer model 171 | 172 | **Returns:** string | boolean - Matching address ID or false 173 | 174 | ## Usage Example 175 | 176 | ```javascript 177 | var OrderModel = require('*/cartridge/models/order'); 178 | var OrderMgr = require('dw/order/OrderMgr'); 179 | 180 | // For completed order 181 | var order = OrderMgr.getOrder('order-number'); 182 | var orderModel = new OrderModel(order, { numberOfLineItems: '*' }); 183 | 184 | // Access order properties 185 | console.log(orderModel.orderNumber); 186 | console.log(orderModel.totals.grandTotal); 187 | console.log(orderModel.billing.billingAddress); 188 | console.log(orderModel.items.length); 189 | 190 | // For checkout basket 191 | var currentBasket = BasketMgr.getCurrentBasket(); 192 | var checkoutModel = new OrderModel(currentBasket); 193 | console.log(checkoutModel.checkoutStep.shipping.iscompleted); 194 | ``` 195 | 196 | ## Configuration Options 197 | 198 | The model supports configuration through the options parameter: 199 | - **numberOfLineItems**: Controls how many line items to include 200 | - `'*'` - Include all line items (default) 201 | - Number - Include specific number of line items 202 | 203 | ## Notes 204 | 205 | - Works with both orders and baskets (line item containers) 206 | - Automatically determines checkout step completion status 207 | - Includes comprehensive totals with all discount calculations 208 | - Provides first line item image for order thumbnails 209 | - Handles multiple shipments with individual shipping information 210 | - All monetary values are properly formatted for display 211 | - Includes extensive localized resources for UI display 212 | 213 | ## Related Models 214 | 215 | - **TotalsModel** - Used for order total calculations 216 | - **ProductLineItemsModel** - Used for line item information 217 | - **BillingModel** - Used for billing information 218 | - **AddressModel** - Used for address formatting 219 | - **PaymentModel** - Used for payment information 220 | ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/get-code-versions.docs-only.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml 1 | # ================================================================================== 2 | # SFCC MCP Server - get_code_versions Tool YAML Tests (Docs-Only Mode) 3 | # Validates that code version tools are NOT available in docs-only mode 4 | # This tool requires SFCC credentials and should not be available without them 5 | # 6 | # Quick Test Commands: 7 | # aegis "tests/mcp/yaml/get-code-versions.docs-only.test.mcp.yml" --config "aegis.config.docs-only.json" --verbose 8 | # aegis query get_code_versions '{}' --config "aegis.config.docs-only.json" 9 | # ================================================================================== 10 | 11 | description: "get_code_versions tool docs-only mode tests - Tool unavailability validation" 12 | 13 | tests: 14 | # ================================================================================== 15 | # TOOL UNAVAILABILITY IN DOCS-ONLY MODE 16 | # ================================================================================== 17 | - it: "should NOT list get_code_versions tool in docs-only mode" 18 | request: 19 | jsonrpc: "2.0" 20 | id: "tool-not-available-docs" 21 | method: "tools/list" 22 | params: {} 23 | expect: 24 | response: 25 | jsonrpc: "2.0" 26 | id: "tool-not-available-docs" 27 | result: 28 | tools: 29 | match:arrayElements: 30 | match:partial: 31 | name: "match:type:string" 32 | description: "match:type:string" 33 | match:extractField: "tools.*.name" 34 | value: "match:not:arrayContains:get_code_versions" 35 | stderr: "toBeEmpty" 36 | 37 | # ================================================================================== 38 | # AUTHENTICATION ERROR TESTS (Tool Can Be Called But Returns Error) 39 | # ================================================================================== 40 | - it: "should return authentication error when calling get_code_versions in docs-only mode" 41 | request: 42 | jsonrpc: "2.0" 43 | id: "auth-error-default" 44 | method: "tools/call" 45 | params: 46 | name: "get_code_versions" 47 | arguments: {} 48 | expect: 49 | response: 50 | jsonrpc: "2.0" 51 | id: "auth-error-default" 52 | result: 53 | content: 54 | match:arrayElements: 55 | type: "text" 56 | text: "match:contains:OCAPI client not configured" 57 | isError: true 58 | stderr: "toBeEmpty" 59 | performance: 60 | maxResponseTime: "1000ms" 61 | 62 | - it: "should return consistent error message for authentication failure" 63 | request: 64 | jsonrpc: "2.0" 65 | id: "auth-error-consistent" 66 | method: "tools/call" 67 | params: 68 | name: "get_code_versions" 69 | arguments: {} 70 | expect: 71 | response: 72 | jsonrpc: "2.0" 73 | id: "auth-error-consistent" 74 | result: 75 | content: 76 | match:arrayElements: 77 | type: "text" 78 | text: "match:regex:Error[\\s\\S]*OCAPI[\\s\\S]*not configured[\\s\\S]*" 79 | isError: true 80 | stderr: "toBeEmpty" 81 | performance: 82 | maxResponseTime: "1000ms" 83 | 84 | # ================================================================================== 85 | # ERROR RESPONSE VALIDATION 86 | # ================================================================================== 87 | - it: "should return proper error structure in docs-only mode" 88 | request: 89 | jsonrpc: "2.0" 90 | id: "error-structure" 91 | method: "tools/call" 92 | params: 93 | name: "get_code_versions" 94 | arguments: {} 95 | expect: 96 | response: 97 | jsonrpc: "2.0" 98 | id: "error-structure" 99 | result: 100 | content: 101 | match:arrayElements: 102 | match:partial: 103 | type: "text" 104 | text: "match:type:string" 105 | isError: true 106 | stderr: "toBeEmpty" 107 | 108 | - it: "should handle parameters gracefully even when returning error" 109 | request: 110 | jsonrpc: "2.0" 111 | id: "error-with-params" 112 | method: "tools/call" 113 | params: 114 | name: "get_code_versions" 115 | arguments: 116 | extraParam: "ignored" 117 | expect: 118 | response: 119 | jsonrpc: "2.0" 120 | id: "error-with-params" 121 | result: 122 | content: 123 | match:arrayElements: 124 | type: "text" 125 | text: "match:contains:OCAPI client not configured" 126 | isError: true 127 | stderr: "toBeEmpty" 128 | performance: 129 | maxResponseTime: "1000ms" 130 | 131 | # ================================================================================== 132 | # PERFORMANCE TESTS FOR ERROR RESPONSES 133 | # ================================================================================== 134 | - it: "should fail fast when credentials not available" 135 | request: 136 | jsonrpc: "2.0" 137 | id: "fail-fast" 138 | method: "tools/call" 139 | params: 140 | name: "get_code_versions" 141 | arguments: {} 142 | expect: 143 | response: 144 | jsonrpc: "2.0" 145 | id: "fail-fast" 146 | result: 147 | content: 148 | match:arrayElements: 149 | match:partial: 150 | type: "text" 151 | isError: true 152 | stderr: "toBeEmpty" 153 | performance: 154 | maxResponseTime: "500ms" 155 | 156 | - it: "should maintain consistent error performance" 157 | request: 158 | jsonrpc: "2.0" 159 | id: "error-performance-consistency" 160 | method: "tools/call" 161 | params: 162 | name: "get_code_versions" 163 | arguments: {} 164 | expect: 165 | response: 166 | jsonrpc: "2.0" 167 | id: "error-performance-consistency" 168 | result: 169 | content: 170 | match:arrayElements: 171 | match:partial: 172 | type: "text" 173 | isError: true 174 | stderr: "toBeEmpty" 175 | performance: 176 | maxResponseTime: "800ms" 177 | 178 | # ================================================================================== 179 | # NEGATIVE TESTING - Invalid Tool Calls 180 | # ================================================================================== 181 | - it: "should handle invalid method calls gracefully" 182 | request: 183 | jsonrpc: "2.0" 184 | id: "invalid-method" 185 | method: "tools/call_invalid" 186 | params: 187 | name: "get_code_versions" 188 | arguments: {} 189 | expect: 190 | response: 191 | jsonrpc: "2.0" 192 | id: "invalid-method" 193 | error: 194 | code: "match:type:number" 195 | message: "match:type:string" 196 | stderr: "toBeEmpty" ``` -------------------------------------------------------------------------------- /docs-site/components/Layout.tsx: -------------------------------------------------------------------------------- ```typescript 1 | 2 | import React, { useState, useEffect } from 'react'; 3 | import { useLocation, Outlet } from 'react-router-dom'; 4 | import Sidebar from './Sidebar'; 5 | import OnThisPage from './OnThisPage'; 6 | import { TocItem } from '../types'; 7 | 8 | const Layout: React.FC = () => { 9 | const [toc, setToc] = useState<TocItem[]>([]); 10 | const [sidebarOpen, setSidebarOpen] = useState(false); 11 | const location = useLocation(); 12 | 13 | // Close sidebar on route change (mobile) 14 | useEffect(() => { 15 | setSidebarOpen(false); 16 | }, [location.pathname]); 17 | 18 | // Scroll restoration - scroll to top on route change or to specific element if hash is present 19 | useEffect(() => { 20 | // Only run on client side 21 | if (typeof window === 'undefined') return; 22 | 23 | const scrollToTarget = () => { 24 | let targetId = ''; 25 | 26 | // Check for hash fragment in location.hash 27 | if (location.hash) { 28 | targetId = location.hash.substring(1); // Remove the # symbol 29 | } 30 | // Check for URL-encoded hash (%23) in the pathname 31 | else if (location.pathname.includes('%23')) { 32 | const parts = location.pathname.split('%23'); 33 | if (parts.length > 1) { 34 | targetId = decodeURIComponent(parts[1]); 35 | } 36 | } 37 | 38 | if (targetId) { 39 | // If there's a target ID, try to scroll to that element 40 | const targetElement = document.getElementById(targetId); 41 | 42 | if (targetElement) { 43 | // Use multiple attempts with increasing delays to ensure DOM is ready 44 | const attemptScroll = (attempt = 0) => { 45 | const element = document.getElementById(targetId); 46 | if (element) { 47 | element.scrollIntoView({ 48 | behavior: 'smooth', 49 | block: 'start', 50 | inline: 'nearest' 51 | }); 52 | } else if (attempt < 5) { 53 | // Retry up to 5 times with increasing delay 54 | setTimeout(() => attemptScroll(attempt + 1), (attempt + 1) * 100); 55 | } 56 | }; 57 | 58 | // Initial attempt with small delay 59 | setTimeout(() => attemptScroll(), 100); 60 | } else { 61 | // Element not found immediately, try again after content loads 62 | setTimeout(() => { 63 | const retryElement = document.getElementById(targetId); 64 | if (retryElement) { 65 | retryElement.scrollIntoView({ 66 | behavior: 'smooth', 67 | block: 'start', 68 | inline: 'nearest' 69 | }); 70 | } 71 | }, 500); 72 | } 73 | } else { 74 | // No hash, scroll to top 75 | window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }); 76 | } 77 | }; 78 | 79 | scrollToTarget(); 80 | }, [location.pathname, location.hash]); 81 | 82 | useEffect(() => { 83 | // Only run on client side 84 | if (typeof window === 'undefined') return; 85 | 86 | // Use a small timeout to ensure the DOM has been updated with new content 87 | const timeoutId = setTimeout(() => { 88 | const mainContent = document.getElementById('main-content'); 89 | if (mainContent) { 90 | const headings = mainContent.querySelectorAll('h2'); 91 | const newToc: TocItem[] = Array.from(headings).map(heading => ({ 92 | id: heading.id, 93 | label: heading.textContent || '', 94 | level: 2, 95 | })); 96 | setToc(newToc); 97 | } 98 | }, 50); 99 | 100 | return () => clearTimeout(timeoutId); 101 | }, [location.pathname]); // Changed dependency to location.pathname 102 | 103 | return ( 104 | <div className="min-h-screen bg-white overflow-x-hidden"> 105 | {/* Mobile Header */} 106 | <header className="lg:hidden bg-white border-b border-slate-200 sticky top-0 z-50"> 107 | <div className="flex items-center justify-between px-4 py-3"> 108 | <div className="flex items-center gap-2 min-w-0"> 109 | <h1 className="text-xl font-bold text-slate-800">SFCC Dev</h1> 110 | <span className="text-xl font-light text-orange-500">MCP</span> 111 | <span className="text-xs text-slate-500 self-start mt-1">v1</span> 112 | </div> 113 | <button 114 | onClick={() => setSidebarOpen(!sidebarOpen)} 115 | className="p-2 text-slate-600 hover:text-slate-900 hover:bg-slate-100 rounded-md flex-shrink-0" 116 | aria-label="Toggle navigation" 117 | > 118 | <svg 119 | className="w-6 h-6" 120 | fill="none" 121 | stroke="currentColor" 122 | viewBox="0 0 24 24" 123 | > 124 | {sidebarOpen ? ( 125 | <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" /> 126 | ) : ( 127 | <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" /> 128 | )} 129 | </svg> 130 | </button> 131 | </div> 132 | </header> 133 | 134 | {/* Mobile Sidebar Overlay */} 135 | {sidebarOpen && ( 136 | <div 137 | className="lg:hidden fixed inset-0 z-40 bg-black bg-opacity-50" 138 | onClick={() => setSidebarOpen(false)} 139 | /> 140 | )} 141 | 142 | <div className="relative flex min-h-screen overflow-x-hidden"> 143 | {/* Desktop Sidebar */} 144 | <div className="fixed top-0 left-0 h-full w-64 hidden lg:block bg-slate-50 border-r border-slate-200"> 145 | <Sidebar /> 146 | </div> 147 | 148 | {/* Mobile Sidebar */} 149 | <div className={`lg:hidden fixed top-0 left-0 h-full w-64 bg-slate-50 border-r border-slate-200 transform transition-transform duration-200 ease-in-out z-50 ${ 150 | sidebarOpen ? 'translate-x-0' : '-translate-x-full' 151 | }`}> 152 | <Sidebar /> 153 | </div> 154 | 155 | <div className="lg:pl-64 flex-1 min-w-0 max-w-full"> 156 | <div className="flex min-w-0 max-w-full"> 157 | <main id="main-content" className="flex-1 max-w-4xl mx-auto sm:p-4 lg:p-12 min-w-0 overflow-hidden"> 158 | <div className="prose prose-slate max-w-none min-w-0 break-words"> 159 | <Outlet /> 160 | </div> 161 | </main> 162 | <aside className="hidden xl:block w-64 flex-shrink-0"> 163 | <div className="fixed top-0 right-0 h-full w-64 p-8"> 164 | <OnThisPage items={toc} /> 165 | </div> 166 | </aside> 167 | </div> 168 | </div> 169 | </div> 170 | </div> 171 | ); 172 | }; 173 | 174 | export default Layout; 175 | ``` -------------------------------------------------------------------------------- /tests/mcp/yaml/get-latest-info.full-mode.test.mcp.yml: -------------------------------------------------------------------------------- ```yaml 1 | description: "get_latest_info tool tests - Access recent info-level log entries" 2 | tests: 3 | # ======================================== 4 | # CORE FUNCTIONALITY 5 | # ======================================== 6 | 7 | - it: "should get latest info entries with default parameters" 8 | request: 9 | jsonrpc: "2.0" 10 | id: "get-latest-info-default" 11 | method: "tools/call" 12 | params: 13 | name: "get_latest_info" 14 | arguments: {} 15 | expect: 16 | response: 17 | jsonrpc: "2.0" 18 | id: "get-latest-info-default" 19 | result: 20 | content: 21 | match:arrayElements: 22 | match:partial: 23 | type: "text" 24 | text: "match:contains:Latest" 25 | isError: false 26 | stderr: "toBeEmpty" 27 | 28 | - it: "should respect custom limit parameter" 29 | request: 30 | jsonrpc: "2.0" 31 | id: "get-latest-info-limit" 32 | method: "tools/call" 33 | params: 34 | name: "get_latest_info" 35 | arguments: 36 | limit: 3 37 | expect: 38 | response: 39 | jsonrpc: "2.0" 40 | id: "get-latest-info-limit" 41 | result: 42 | content: 43 | match:arrayElements: 44 | match:partial: 45 | text: "match:contains:Latest 3 info messages" 46 | isError: false 47 | 48 | - it: "should contain INFO log level and log files" 49 | request: 50 | jsonrpc: "2.0" 51 | id: "get-latest-info-content" 52 | method: "tools/call" 53 | params: 54 | name: "get_latest_info" 55 | arguments: 56 | limit: 2 57 | expect: 58 | response: 59 | jsonrpc: "2.0" 60 | id: "get-latest-info-content" 61 | result: 62 | content: 63 | match:arrayElements: 64 | match:partial: 65 | text: "match:contains:INFO" 66 | isError: false 67 | 68 | - it: "should format multiple entries with separators" 69 | request: 70 | jsonrpc: "2.0" 71 | id: "get-latest-info-separators" 72 | method: "tools/call" 73 | params: 74 | name: "get_latest_info" 75 | arguments: 76 | limit: 3 77 | expect: 78 | response: 79 | jsonrpc: "2.0" 80 | id: "get-latest-info-separators" 81 | result: 82 | content: 83 | match:arrayElements: 84 | match:partial: 85 | text: "match:contains:---" 86 | isError: false 87 | 88 | # ======================================== 89 | # PARAMETER VALIDATION 90 | # ======================================== 91 | 92 | - it: "should return error for zero limit" 93 | request: 94 | jsonrpc: "2.0" 95 | id: "get-latest-info-zero-limit" 96 | method: "tools/call" 97 | params: 98 | name: "get_latest_info" 99 | arguments: 100 | limit: 0 101 | expect: 102 | response: 103 | jsonrpc: "2.0" 104 | id: "get-latest-info-zero-limit" 105 | result: 106 | content: 107 | match:arrayElements: 108 | match:partial: 109 | text: "match:contains:Invalid limit '0'" 110 | isError: true 111 | 112 | - it: "should return error for negative limit" 113 | request: 114 | jsonrpc: "2.0" 115 | id: "get-latest-info-negative-limit" 116 | method: "tools/call" 117 | params: 118 | name: "get_latest_info" 119 | arguments: 120 | limit: -5 121 | expect: 122 | response: 123 | jsonrpc: "2.0" 124 | id: "get-latest-info-negative-limit" 125 | result: 126 | content: 127 | match:arrayElements: 128 | match:partial: 129 | text: "match:contains:Invalid limit '-5'" 130 | isError: true 131 | 132 | - it: "should handle invalid limit type gracefully" 133 | request: 134 | jsonrpc: "2.0" 135 | id: "get-latest-info-invalid-limit" 136 | method: "tools/call" 137 | params: 138 | name: "get_latest_info" 139 | arguments: 140 | limit: "invalid" 141 | expect: 142 | response: 143 | jsonrpc: "2.0" 144 | id: "get-latest-info-invalid-limit" 145 | result: 146 | content: 147 | match:arrayElements: 148 | match:partial: 149 | text: "match:contains:Invalid limit 'invalid'" 150 | isError: true 151 | 152 | - it: "should handle invalid date gracefully" 153 | request: 154 | jsonrpc: "2.0" 155 | id: "get-latest-info-invalid-date" 156 | method: "tools/call" 157 | params: 158 | name: "get_latest_info" 159 | arguments: 160 | date: "invalid-date" 161 | limit: 3 162 | expect: 163 | response: 164 | jsonrpc: "2.0" 165 | id: "get-latest-info-invalid-date" 166 | result: 167 | content: 168 | match:arrayElements: 169 | match:partial: 170 | text: "match:contains:No info log files found" 171 | isError: false 172 | 173 | # ======================================== 174 | # EDGE CASES 175 | # ======================================== 176 | 177 | - it: "should handle limit of 1" 178 | request: 179 | jsonrpc: "2.0" 180 | id: "get-latest-info-limit-one" 181 | method: "tools/call" 182 | params: 183 | name: "get_latest_info" 184 | arguments: 185 | limit: 1 186 | expect: 187 | response: 188 | jsonrpc: "2.0" 189 | id: "get-latest-info-limit-one" 190 | result: 191 | content: 192 | match:arrayElements: 193 | match:partial: 194 | text: "match:contains:Latest 1 info messages" 195 | isError: false 196 | 197 | - it: "should handle large limit values" 198 | request: 199 | jsonrpc: "2.0" 200 | id: "get-latest-info-large-limit" 201 | method: "tools/call" 202 | params: 203 | name: "get_latest_info" 204 | arguments: 205 | limit: 100 206 | expect: 207 | response: 208 | jsonrpc: "2.0" 209 | id: "get-latest-info-large-limit" 210 | result: 211 | content: 212 | match:arrayElements: 213 | match:partial: 214 | text: "match:contains:Latest 100 info messages" 215 | isError: false 216 | 217 | # ======================================== 218 | # PERFORMANCE VALIDATION 219 | # ======================================== 220 | 221 | - it: "should respond within reasonable time" 222 | request: 223 | jsonrpc: "2.0" 224 | id: "get-latest-info-perf" 225 | method: "tools/call" 226 | params: 227 | name: "get_latest_info" 228 | arguments: 229 | limit: 10 230 | expect: 231 | response: 232 | jsonrpc: "2.0" 233 | id: "get-latest-info-perf" 234 | result: 235 | content: 236 | match:arrayElements: 237 | match:partial: 238 | type: "text" 239 | text: "match:type:string" 240 | isError: false 241 | performance: 242 | maxResponseTime: "800ms" 243 | ``` -------------------------------------------------------------------------------- /docs/dw_object/ObjectTypeDefinition.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.object 2 | 3 | # Class ObjectTypeDefinition 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.object.ObjectTypeDefinition 9 | 10 | ## Description 11 | 12 | The class provides access to the meta data of a system object or custom object. A short example should suffice to demonstrate how this metadata can be used in a script: var co : CustomObject = CustomObjectMgr.getCustomObject("sample", "MyCustomObject"); // get the object type definition var typeDef : ObjectTypeDefinition = co.describe(); // get the custom object attribute definition for name "enumIntValue" var attrDef : ObjectAttributeDefinition = typeDef.getCustomAttributeDefinition( "enumIntValue" ); // get the collection of object attribute value definitions var valueDefs : Collection = attrDef.getValues(); // return function if there are no object attribute value definitions if(valueDefs.isEmpty()) { return; } var displayValue : String; // loop over object attribute value definitions collection for each ( var valueDef : ObjectAttributeValueDefinition in valueDefs ) { if( valueDef.getValue() == co.custom.intValue ) { displayValue = valueDef.getDisplayValue(); break; } } 13 | 14 | ## Properties 15 | 16 | ### attributeDefinitions 17 | 18 | **Type:** Collection (Read Only) 19 | 20 | A collection of all declared attributes for the object. 21 | The collection contains both system and custom attributes. There might 22 | be system and custom attribute with identical names. So the name of the 23 | attribute is not a uniqueness criteria. Additional the isCustom() flag 24 | must be checked. 25 | 26 | ### attributeGroups 27 | 28 | **Type:** Collection (Read Only) 29 | 30 | A collection of all declared attribute groups. A attribute group 31 | is a collection of attribute, which are typically displayed together as 32 | a visual group. 33 | 34 | ### displayName 35 | 36 | **Type:** String (Read Only) 37 | 38 | The display name of the definition, which can be used in the 39 | user interface. 40 | 41 | ### ID 42 | 43 | **Type:** String (Read Only) 44 | 45 | The type id of the business objects. 46 | 47 | ### system 48 | 49 | **Type:** boolean (Read Only) 50 | 51 | Identifies if this object definition is for a system type or a custom 52 | type. 53 | 54 | ## Constructor Summary 55 | 56 | ## Method Summary 57 | 58 | ### getAttributeDefinitions 59 | 60 | **Signature:** `getAttributeDefinitions() : Collection` 61 | 62 | Returns a collection of all declared attributes for the object. 63 | 64 | ### getAttributeGroup 65 | 66 | **Signature:** `getAttributeGroup(name : String) : ObjectAttributeGroup` 67 | 68 | Returns the attribute group with the given name within this object type definition. 69 | 70 | ### getAttributeGroups 71 | 72 | **Signature:** `getAttributeGroups() : Collection` 73 | 74 | Returns a collection of all declared attribute groups. 75 | 76 | ### getCustomAttributeDefinition 77 | 78 | **Signature:** `getCustomAttributeDefinition(name : String) : ObjectAttributeDefinition` 79 | 80 | Returns the custom attribute definition with the given name. 81 | 82 | ### getDisplayName 83 | 84 | **Signature:** `getDisplayName() : String` 85 | 86 | Returns the display name of the definition, which can be used in the user interface. 87 | 88 | ### getID 89 | 90 | **Signature:** `getID() : String` 91 | 92 | Returns the type id of the business objects. 93 | 94 | ### getSystemAttributeDefinition 95 | 96 | **Signature:** `getSystemAttributeDefinition(name : String) : ObjectAttributeDefinition` 97 | 98 | Returns the system attribute definition with the given name. 99 | 100 | ### isSystem 101 | 102 | **Signature:** `isSystem() : boolean` 103 | 104 | Identifies if this object definition is for a system type or a custom type. 105 | 106 | ## Method Detail 107 | 108 | ## Method Details 109 | 110 | ### getAttributeDefinitions 111 | 112 | **Signature:** `getAttributeDefinitions() : Collection` 113 | 114 | **Description:** Returns a collection of all declared attributes for the object. The collection contains both system and custom attributes. There might be system and custom attribute with identical names. So the name of the attribute is not a uniqueness criteria. Additional the isCustom() flag must be checked. 115 | 116 | **Returns:** 117 | 118 | a collection of all declared attributes for the object. 119 | 120 | --- 121 | 122 | ### getAttributeGroup 123 | 124 | **Signature:** `getAttributeGroup(name : String) : ObjectAttributeGroup` 125 | 126 | **Description:** Returns the attribute group with the given name within this object type definition. 127 | 128 | **Parameters:** 129 | 130 | - `name`: The name of the attribute scope to return. 131 | 132 | **Returns:** 133 | 134 | The matching attribute scope or null if no such scope exists. 135 | 136 | --- 137 | 138 | ### getAttributeGroups 139 | 140 | **Signature:** `getAttributeGroups() : Collection` 141 | 142 | **Description:** Returns a collection of all declared attribute groups. A attribute group is a collection of attribute, which are typically displayed together as a visual group. 143 | 144 | **Returns:** 145 | 146 | a collection of all declared attribute groups. 147 | 148 | --- 149 | 150 | ### getCustomAttributeDefinition 151 | 152 | **Signature:** `getCustomAttributeDefinition(name : String) : ObjectAttributeDefinition` 153 | 154 | **Description:** Returns the custom attribute definition with the given name. The method returns null if no custom attribute is defined with that name. 155 | 156 | **Parameters:** 157 | 158 | - `name`: The unique name of the custom attribute definition within the object type. 159 | 160 | **Returns:** 161 | 162 | The matching attribute definition or null in case no such definition exists. 163 | 164 | --- 165 | 166 | ### getDisplayName 167 | 168 | **Signature:** `getDisplayName() : String` 169 | 170 | **Description:** Returns the display name of the definition, which can be used in the user interface. 171 | 172 | **Returns:** 173 | 174 | the display name of the definition, which can be used in the user interface. 175 | 176 | --- 177 | 178 | ### getID 179 | 180 | **Signature:** `getID() : String` 181 | 182 | **Description:** Returns the type id of the business objects. 183 | 184 | **Returns:** 185 | 186 | the type id of the business objects. 187 | 188 | --- 189 | 190 | ### getSystemAttributeDefinition 191 | 192 | **Signature:** `getSystemAttributeDefinition(name : String) : ObjectAttributeDefinition` 193 | 194 | **Description:** Returns the system attribute definition with the given name. The method returns null if no system attribute is defined with that name. Only system objects have system attributes. A CustomObject has no system attributes and so the method will always return null for a CustomObject. 195 | 196 | **Parameters:** 197 | 198 | - `name`: The unique name of the custom attribute definition within the object type. 199 | 200 | **Returns:** 201 | 202 | The matching attribute definition or null in case no such definition exists. 203 | 204 | --- 205 | 206 | ### isSystem 207 | 208 | **Signature:** `isSystem() : boolean` 209 | 210 | **Description:** Identifies if this object definition is for a system type or a custom type. 211 | 212 | **Returns:** 213 | 214 | true if this object definition is for a system type, false otherwise. 215 | 216 | --- ``` -------------------------------------------------------------------------------- /docs/dw_util/Geolocation.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.util 2 | 3 | # Class Geolocation 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.util.Geolocation 9 | 10 | ## Description 11 | 12 | Read-only class representing a position on the earth (latitude and longitude) and information associated with that location (e.g. country, city, etc). The Commerce Cloud Digital system can provide geolocation information for a Request and this information can be used in customer group segmentation rules. Note: This class is not related to the store locator API (i.e. the GetNearestStores pipelet) which uses a static set of store locations loaded into the system by the merchant. This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com. 13 | 14 | ## Properties 15 | 16 | ### available 17 | 18 | **Type:** boolean (Read Only) 19 | 20 | Returns 'true' if a valid GeoLocation was found for the IP address 21 | (meaning at least Latitude and Longitude were found), false otherwise. 22 | 23 | ### city 24 | 25 | **Type:** String (Read Only) 26 | 27 | Get the city name in English associated with this location. 28 | 29 | ### countryCode 30 | 31 | **Type:** String (Read Only) 32 | 33 | Get the ISO country code associated with this location. 34 | 35 | ### countryName 36 | 37 | **Type:** String (Read Only) 38 | 39 | Get the country name in English that the system associates with this location on the 40 | earth. 41 | 42 | ### latitude 43 | 44 | **Type:** Number (Read Only) 45 | 46 | Get the latitude coordinate associated with this location which is a 47 | number between -90.0 and +90.0. 48 | 49 | ### longitude 50 | 51 | **Type:** Number (Read Only) 52 | 53 | Get the longitude coordinate associated with this location which is a 54 | number between -180.0 and +180.0. 55 | 56 | ### metroCode 57 | 58 | **Type:** String (Read Only) 59 | 60 | Get the metro code associated with this location. 61 | 62 | ### postalCode 63 | 64 | **Type:** String (Read Only) 65 | 66 | Get the postal code associated with this location. 67 | 68 | ### regionCode 69 | 70 | **Type:** String (Read Only) 71 | 72 | Get the region (e.g. province or state) code for this location. 73 | 74 | ### regionName 75 | 76 | **Type:** String (Read Only) 77 | 78 | Get the region (e.g. province in state) name in English that the system 79 | associates with this location. 80 | 81 | ## Constructor Summary 82 | 83 | Geolocation(countryCode : String, countryName : String, regionCode : String, regionName : String, metroCode : String, city : String, postalCode : String, latitude : Number, longitude : Number) Constructor for a Geolocation object 84 | 85 | ## Method Summary 86 | 87 | ### getCity 88 | 89 | **Signature:** `getCity() : String` 90 | 91 | Get the city name in English associated with this location. 92 | 93 | ### getCountryCode 94 | 95 | **Signature:** `getCountryCode() : String` 96 | 97 | Get the ISO country code associated with this location. 98 | 99 | ### getCountryName 100 | 101 | **Signature:** `getCountryName() : String` 102 | 103 | Get the country name in English that the system associates with this location on the earth. 104 | 105 | ### getLatitude 106 | 107 | **Signature:** `getLatitude() : Number` 108 | 109 | Get the latitude coordinate associated with this location which is a number between -90.0 and +90.0. 110 | 111 | ### getLongitude 112 | 113 | **Signature:** `getLongitude() : Number` 114 | 115 | Get the longitude coordinate associated with this location which is a number between -180.0 and +180.0. 116 | 117 | ### getMetroCode 118 | 119 | **Signature:** `getMetroCode() : String` 120 | 121 | Get the metro code associated with this location. 122 | 123 | ### getPostalCode 124 | 125 | **Signature:** `getPostalCode() : String` 126 | 127 | Get the postal code associated with this location. 128 | 129 | ### getRegionCode 130 | 131 | **Signature:** `getRegionCode() : String` 132 | 133 | Get the region (e.g. 134 | 135 | ### getRegionName 136 | 137 | **Signature:** `getRegionName() : String` 138 | 139 | Get the region (e.g. 140 | 141 | ### isAvailable 142 | 143 | **Signature:** `isAvailable() : boolean` 144 | 145 | Returns 'true' if a valid GeoLocation was found for the IP address (meaning at least Latitude and Longitude were found), false otherwise. 146 | 147 | ## Constructor Detail 148 | 149 | ## Method Detail 150 | 151 | ## Method Details 152 | 153 | ### getCity 154 | 155 | **Signature:** `getCity() : String` 156 | 157 | **Description:** Get the city name in English associated with this location. 158 | 159 | **Returns:** 160 | 161 | the city that the system associates with this location on the earth. 162 | 163 | --- 164 | 165 | ### getCountryCode 166 | 167 | **Signature:** `getCountryCode() : String` 168 | 169 | **Description:** Get the ISO country code associated with this location. 170 | 171 | **Returns:** 172 | 173 | The two-character ISO 3166-1 alpha code for the country. 174 | 175 | --- 176 | 177 | ### getCountryName 178 | 179 | **Signature:** `getCountryName() : String` 180 | 181 | **Description:** Get the country name in English that the system associates with this location on the earth. 182 | 183 | **Returns:** 184 | 185 | the country name that the system associates with this location on the earth. 186 | 187 | --- 188 | 189 | ### getLatitude 190 | 191 | **Signature:** `getLatitude() : Number` 192 | 193 | **Description:** Get the latitude coordinate associated with this location which is a number between -90.0 and +90.0. 194 | 195 | **Returns:** 196 | 197 | The latitude of the location as a floating point number. 198 | 199 | --- 200 | 201 | ### getLongitude 202 | 203 | **Signature:** `getLongitude() : Number` 204 | 205 | **Description:** Get the longitude coordinate associated with this location which is a number between -180.0 and +180.0. 206 | 207 | **Returns:** 208 | 209 | The longitude of the location as a floating point number. 210 | 211 | --- 212 | 213 | ### getMetroCode 214 | 215 | **Signature:** `getMetroCode() : String` 216 | 217 | **Description:** Get the metro code associated with this location. 218 | 219 | **Returns:** 220 | 221 | The metro code of the location if the location is in the US. See the Google AdWords API for returned values. 222 | 223 | --- 224 | 225 | ### getPostalCode 226 | 227 | **Signature:** `getPostalCode() : String` 228 | 229 | **Description:** Get the postal code associated with this location. 230 | 231 | **Returns:** 232 | 233 | The postal code of the location. Postal codes are not available for all countries. In some countries, this will only contain part of the postal code. 234 | 235 | --- 236 | 237 | ### getRegionCode 238 | 239 | **Signature:** `getRegionCode() : String` 240 | 241 | **Description:** Get the region (e.g. province or state) code for this location. 242 | 243 | **Returns:** 244 | 245 | This is a string up to three characters long containing the subdivision portion of the code. 246 | 247 | --- 248 | 249 | ### getRegionName 250 | 251 | **Signature:** `getRegionName() : String` 252 | 253 | **Description:** Get the region (e.g. province in state) name in English that the system associates with this location. 254 | 255 | **Returns:** 256 | 257 | the region name that the system associates with this location on the earth. 258 | 259 | --- 260 | 261 | ### isAvailable 262 | 263 | **Signature:** `isAvailable() : boolean` 264 | 265 | **Description:** Returns 'true' if a valid GeoLocation was found for the IP address (meaning at least Latitude and Longitude were found), false otherwise. 266 | 267 | **Returns:** 268 | 269 | 'true' if a valid GeoLocation was found for the IP address (meaning at least Latitude and Longitude were found), false otherwise. 270 | 271 | --- ``` -------------------------------------------------------------------------------- /docs/dw_crypto/Encoding.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.crypto 2 | 3 | # Class Encoding 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.crypto.Encoding 9 | 10 | ## Description 11 | 12 | Utility class which handles several common character encodings. 13 | 14 | ## Constructor Summary 15 | 16 | ## Method Summary 17 | 18 | ### fromBase64 19 | 20 | **Signature:** `static fromBase64(string : String) : Bytes` 21 | 22 | Decode the given string which represents a sequence of characters encoded in base-64 to a byte array. 23 | 24 | ### fromHex 25 | 26 | **Signature:** `static fromHex(string : String) : Bytes` 27 | 28 | Converts a String representing hexadecimal values into an array of bytes of those same values. 29 | 30 | ### fromURI 31 | 32 | **Signature:** `static fromURI(string : String) : String` 33 | 34 | Decodes a URL safe string into its original form. 35 | 36 | ### fromURI 37 | 38 | **Signature:** `static fromURI(string : String, encoding : String) : String` 39 | 40 | Decodes a URL safe string into its original form using the specified encoding. 41 | 42 | ### toBase64 43 | 44 | **Signature:** `static toBase64(bytes : Bytes) : String` 45 | 46 | Convert the given byte array to a string encoded in base-64. 47 | 48 | ### toBase64URL 49 | 50 | **Signature:** `static toBase64URL(bytes : Bytes) : String` 51 | 52 | Convert the given byte array to a string encoded in base-64 for URLs. 53 | 54 | ### toHex 55 | 56 | **Signature:** `static toHex(bytes : Bytes) : String` 57 | 58 | Converts an array of bytes into a string representing the hexadecimal values of each byte in order. 59 | 60 | ### toURI 61 | 62 | **Signature:** `static toURI(string : String) : String` 63 | 64 | Encodes a string into its URL safe form according to the "application/x-www-form-urlencoded" encoding scheme using the default encoding. 65 | 66 | ### toURI 67 | 68 | **Signature:** `static toURI(string : String, encoding : String) : String` 69 | 70 | Encodes a string into its URL safe form according to the "application/x-www-form-urlencoded" encoding scheme using the specified encoding. 71 | 72 | ## Method Detail 73 | 74 | ## Method Details 75 | 76 | ### fromBase64 77 | 78 | **Signature:** `static fromBase64(string : String) : Bytes` 79 | 80 | **Description:** Decode the given string which represents a sequence of characters encoded in base-64 to a byte array. This operation supports both the base-64 and base-64 for URL formats. Characters not in the base-64 alphabet are ignored. An exception is thrown if a null value is passed. Note: This decoding operation is limited to the maximum number of bytes that a Bytes object can hold. See Bytes. 81 | 82 | **Parameters:** 83 | 84 | - `string`: A string consisting of characters in base-64 alphabet to decode. 85 | 86 | **Returns:** 87 | 88 | The decoded array of bytes. 89 | 90 | --- 91 | 92 | ### fromHex 93 | 94 | **Signature:** `static fromHex(string : String) : Bytes` 95 | 96 | **Description:** Converts a String representing hexadecimal values into an array of bytes of those same values. The returned byte array will be half the length of the passed, as it takes two characters to represent any given byte. An exception is thrown if the passed string has an odd number of character or if any characters in the string are not valid hexadecimal characters. An exception is thrown if a null value is passed. Note: This decoding operation is limited to the maximum number of bytes that a Bytes object can hold. See Bytes. 97 | 98 | **Parameters:** 99 | 100 | - `string`: A string containing only hex characters to decode. 101 | 102 | **Returns:** 103 | 104 | The decoded array of bytes. 105 | 106 | --- 107 | 108 | ### fromURI 109 | 110 | **Signature:** `static fromURI(string : String) : String` 111 | 112 | **Description:** Decodes a URL safe string into its original form. Escaped characters are converted back to their original representation. An exception is thrown if URL decoding is unsuccessful or if null is passed. 113 | 114 | **Parameters:** 115 | 116 | - `string`: The string to decode. 117 | 118 | **Returns:** 119 | 120 | The decoded string. 121 | 122 | --- 123 | 124 | ### fromURI 125 | 126 | **Signature:** `static fromURI(string : String, encoding : String) : String` 127 | 128 | **Description:** Decodes a URL safe string into its original form using the specified encoding. Escaped characters are converted back to their original representation. An exception is thrown if URL decoding is unsuccessful or if the specified encoding is unsupported or if null is passed for either argument. 129 | 130 | **Parameters:** 131 | 132 | - `string`: The string to decode. 133 | - `encoding`: The name of a supported encoding. 134 | 135 | **Returns:** 136 | 137 | The decoded string. 138 | 139 | --- 140 | 141 | ### toBase64 142 | 143 | **Signature:** `static toBase64(bytes : Bytes) : String` 144 | 145 | **Description:** Convert the given byte array to a string encoded in base-64. This method does not chunk the data by adding line breaks. An exception is thrown if a null value is passed. 146 | 147 | **Parameters:** 148 | 149 | - `bytes`: The array of bytes to encode. 150 | 151 | **Returns:** 152 | 153 | The encoded string containing only Base64 characters. 154 | 155 | --- 156 | 157 | ### toBase64URL 158 | 159 | **Signature:** `static toBase64URL(bytes : Bytes) : String` 160 | 161 | **Description:** Convert the given byte array to a string encoded in base-64 for URLs. This method does not chunk the data by adding line breaks and it does not add any padding. An exception is thrown if a null value is passed. 162 | 163 | **Parameters:** 164 | 165 | - `bytes`: The array of bytes to encode. 166 | 167 | **Returns:** 168 | 169 | The encoded string containing only Base64URL characters. 170 | 171 | --- 172 | 173 | ### toHex 174 | 175 | **Signature:** `static toHex(bytes : Bytes) : String` 176 | 177 | **Description:** Converts an array of bytes into a string representing the hexadecimal values of each byte in order. The returned string will be double the length of the passed array, as it takes two characters to represent any given byte. An exception is thrown if a null value is passed. 178 | 179 | **Parameters:** 180 | 181 | - `bytes`: The array of bytes to encode. 182 | 183 | **Returns:** 184 | 185 | The encoded string containing only hex characters. 186 | 187 | --- 188 | 189 | ### toURI 190 | 191 | **Signature:** `static toURI(string : String) : String` 192 | 193 | **Description:** Encodes a string into its URL safe form according to the "application/x-www-form-urlencoded" encoding scheme using the default encoding. Unsafe characters are escaped. An exception is thrown if a null value is passed. 194 | 195 | **Parameters:** 196 | 197 | - `string`: The string to encode. 198 | 199 | **Returns:** 200 | 201 | The encoded string. 202 | 203 | --- 204 | 205 | ### toURI 206 | 207 | **Signature:** `static toURI(string : String, encoding : String) : String` 208 | 209 | **Description:** Encodes a string into its URL safe form according to the "application/x-www-form-urlencoded" encoding scheme using the specified encoding. Unsafe characters are escaped. An exception is thrown if the specified encoding is unsupported. An exception is thrown if either argument is null. 210 | 211 | **Parameters:** 212 | 213 | - `string`: The string to encode. 214 | - `encoding`: The name of a supported encoding. 215 | 216 | **Returns:** 217 | 218 | The encoded string. 219 | 220 | --- ``` -------------------------------------------------------------------------------- /docs/dw_order/CouponLineItem.md: -------------------------------------------------------------------------------- ```markdown 1 | ## Package: dw.order 2 | 3 | # Class CouponLineItem 4 | 5 | ## Inheritance Hierarchy 6 | 7 | - Object 8 | - dw.object.PersistentObject 9 | - dw.object.ExtensibleObject 10 | - dw.order.CouponLineItem 11 | 12 | ## Description 13 | 14 | The CouponLineItem class is used to store redeemed coupons in the Basket. 15 | 16 | ## Properties 17 | 18 | ### applied 19 | 20 | **Type:** boolean (Read Only) 21 | 22 | Identifies if the coupon is currently applied in the basket. A coupon 23 | line is applied if there exists at least one price adjustment related 24 | to the coupon line item. 25 | 26 | ### basedOnCampaign 27 | 28 | **Type:** boolean (Read Only) 29 | 30 | Returns true if the line item represents a coupon of a campaign. If the coupon line item represents a custom 31 | coupon code, the method returns false. 32 | 33 | ### bonusDiscountLineItems 34 | 35 | **Type:** Collection (Read Only) 36 | 37 | The bonus discount line items of the line item container triggered 38 | by this coupon. 39 | 40 | ### couponCode 41 | 42 | **Type:** String (Read Only) 43 | 44 | The coupon code. 45 | 46 | ### priceAdjustments 47 | 48 | **Type:** Collection (Read Only) 49 | 50 | The price adjustments of the line item container triggered 51 | by this coupon. 52 | 53 | ### promotion 54 | 55 | **Type:** Promotion (Read Only) 56 | 57 | The promotion related to the coupon line item. 58 | 59 | ### promotionID 60 | 61 | **Type:** String (Read Only) 62 | 63 | The id of the related promotion. 64 | 65 | ### statusCode 66 | 67 | **Type:** String (Read Only) 68 | 69 | This method provides a detailed error status in case the coupon code of 70 | this coupon line item instance became invalid. 71 | 72 | ### valid 73 | 74 | **Type:** CouponStatusCodes.APPLIED (Read Only) 75 | 76 | Allows to check whether the coupon code of this coupon line item instance 77 | is valid. Coupon line item is valid, if status code is one of the following: 78 | 79 | CouponStatusCodes.APPLIED 80 | CouponStatusCodes.NO_APPLICABLE_PROMOTION 81 | 82 | ## Constructor Summary 83 | 84 | ## Method Summary 85 | 86 | ### associatePriceAdjustment 87 | 88 | **Signature:** `associatePriceAdjustment(priceAdjustment : PriceAdjustment) : void` 89 | 90 | Associates the specified price adjustment with the coupon line item. 91 | 92 | ### getBonusDiscountLineItems 93 | 94 | **Signature:** `getBonusDiscountLineItems() : Collection` 95 | 96 | Returns the bonus discount line items of the line item container triggered by this coupon. 97 | 98 | ### getCouponCode 99 | 100 | **Signature:** `getCouponCode() : String` 101 | 102 | Returns the coupon code. 103 | 104 | ### getPriceAdjustments 105 | 106 | **Signature:** `getPriceAdjustments() : Collection` 107 | 108 | Returns the price adjustments of the line item container triggered by this coupon. 109 | 110 | ### getPromotion 111 | 112 | **Signature:** `getPromotion() : Promotion` 113 | 114 | Returns the promotion related to the coupon line item. 115 | 116 | ### getPromotionID 117 | 118 | **Signature:** `getPromotionID() : String` 119 | 120 | Returns the id of the related promotion. 121 | 122 | ### getStatusCode 123 | 124 | **Signature:** `getStatusCode() : String` 125 | 126 | This method provides a detailed error status in case the coupon code of this coupon line item instance became invalid. 127 | 128 | ### isApplied 129 | 130 | **Signature:** `isApplied() : boolean` 131 | 132 | Identifies if the coupon is currently applied in the basket. 133 | 134 | ### isBasedOnCampaign 135 | 136 | **Signature:** `isBasedOnCampaign() : boolean` 137 | 138 | Returns true if the line item represents a coupon of a campaign. 139 | 140 | ### isValid 141 | 142 | **Signature:** `isValid() : boolean` 143 | 144 | Allows to check whether the coupon code of this coupon line item instance is valid. 145 | 146 | ## Method Detail 147 | 148 | ## Method Details 149 | 150 | ### associatePriceAdjustment 151 | 152 | **Signature:** `associatePriceAdjustment(priceAdjustment : PriceAdjustment) : void` 153 | 154 | **Description:** Associates the specified price adjustment with the coupon line item. This method is only applicable if used for price adjustments and coupon line items NOT based on B2C Commerce campaigns. 155 | 156 | **Parameters:** 157 | 158 | - `priceAdjustment`: Price adjustment to be associated with coupon line item. 159 | 160 | --- 161 | 162 | ### getBonusDiscountLineItems 163 | 164 | **Signature:** `getBonusDiscountLineItems() : Collection` 165 | 166 | **Description:** Returns the bonus discount line items of the line item container triggered by this coupon. 167 | 168 | **Returns:** 169 | 170 | Price adjustments triggered by the coupon 171 | 172 | --- 173 | 174 | ### getCouponCode 175 | 176 | **Signature:** `getCouponCode() : String` 177 | 178 | **Description:** Returns the coupon code. 179 | 180 | **Returns:** 181 | 182 | Coupon code 183 | 184 | --- 185 | 186 | ### getPriceAdjustments 187 | 188 | **Signature:** `getPriceAdjustments() : Collection` 189 | 190 | **Description:** Returns the price adjustments of the line item container triggered by this coupon. 191 | 192 | **Returns:** 193 | 194 | Price adjustments triggered by the coupon 195 | 196 | --- 197 | 198 | ### getPromotion 199 | 200 | **Signature:** `getPromotion() : Promotion` 201 | 202 | **Description:** Returns the promotion related to the coupon line item. 203 | 204 | **Deprecated:** 205 | 206 | A coupon code and its coupon can be associated with multiple promotions. Therefore, this method is not appropriate anymore. For backward-compatibility, the method returns one of the promotions associated with the coupon code. 207 | 208 | **Returns:** 209 | 210 | Promotion related to coupon represented by line item 211 | 212 | --- 213 | 214 | ### getPromotionID 215 | 216 | **Signature:** `getPromotionID() : String` 217 | 218 | **Description:** Returns the id of the related promotion. 219 | 220 | **Deprecated:** 221 | 222 | A coupon code and it's coupon can be associated with multiple promotions. Therefore, this method is not appropriate anymore. For backward-compatibility, the method returns the ID of one of the promotions associated with the coupon code. 223 | 224 | **Returns:** 225 | 226 | the id of the related promotion. 227 | 228 | --- 229 | 230 | ### getStatusCode 231 | 232 | **Signature:** `getStatusCode() : String` 233 | 234 | **Description:** This method provides a detailed error status in case the coupon code of this coupon line item instance became invalid. 235 | 236 | **Returns:** 237 | 238 | Returns APPLIED if coupon is applied, and otherwise one of the codes defined in CouponStatusCodes 239 | 240 | --- 241 | 242 | ### isApplied 243 | 244 | **Signature:** `isApplied() : boolean` 245 | 246 | **Description:** Identifies if the coupon is currently applied in the basket. A coupon line is applied if there exists at least one price adjustment related to the coupon line item. 247 | 248 | **Returns:** 249 | 250 | true if the coupon is currently applied in the basket. 251 | 252 | --- 253 | 254 | ### isBasedOnCampaign 255 | 256 | **Signature:** `isBasedOnCampaign() : boolean` 257 | 258 | **Description:** Returns true if the line item represents a coupon of a campaign. If the coupon line item represents a custom coupon code, the method returns false. 259 | 260 | --- 261 | 262 | ### isValid 263 | 264 | **Signature:** `isValid() : boolean` 265 | 266 | **Description:** Allows to check whether the coupon code of this coupon line item instance is valid. Coupon line item is valid, if status code is one of the following: CouponStatusCodes.APPLIED CouponStatusCodes.NO_APPLICABLE_PROMOTION 267 | 268 | **Returns:** 269 | 270 | true if the coupon code is valid, false otherwise. 271 | 272 | --- ``` -------------------------------------------------------------------------------- /tests/servers/sfcc-mock-server/mock-data/ocapi/system-object-attributes-product.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "_v": "23.2", 3 | "_type": "object_attribute_definition_search_result", 4 | "count": 20, 5 | "hits": [ 6 | { 7 | "_type": "object_attribute_definition", 8 | "_resource_state": "47de03c012d48eee975077f45131088fe24f34660ecf4dc69de5737257836fda", 9 | "id": "EAN", 10 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/EAN" 11 | }, 12 | { 13 | "_type": "object_attribute_definition", 14 | "_resource_state": "d9215260b911efb2f40c78cb1b9a7134feca85bf429a9462371db6a16d22e456", 15 | "id": "ID", 16 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/ID" 17 | }, 18 | { 19 | "_type": "object_attribute_definition", 20 | "_resource_state": "5d41eb23dc9228d397af90560aaa1b8b0ff825e6d8699a56977366d3534c5cc6", 21 | "id": "UPC", 22 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/UPC" 23 | }, 24 | { 25 | "_type": "object_attribute_definition", 26 | "_resource_state": "461201495377a8c0e50340bbce3ce929cecfbb74022d1ba87ff3bfeb2501b295", 27 | "id": "UUID", 28 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/UUID" 29 | }, 30 | { 31 | "_type": "object_attribute_definition", 32 | "_resource_state": "94d3911611a738b687448c2742b6b61216925f45e60627906e871da0d752f35b", 33 | "id": "Wool", 34 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/Wool" 35 | }, 36 | { 37 | "_type": "object_attribute_definition", 38 | "_resource_state": "f3714641f6cd57c36db45c8976a743e21dafdb52d753ea67013ef9a9209488f3", 39 | "id": "available", 40 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/available" 41 | }, 42 | { 43 | "_type": "object_attribute_definition", 44 | "_resource_state": "5945247ee819586780982084e8099326c6cc04499492ff82f8603ecb224172d0", 45 | "id": "availableForInStorePickup", 46 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/availableForInStorePickup" 47 | }, 48 | { 49 | "_type": "object_attribute_definition", 50 | "_resource_state": "835703bec9a082f3525872afaa1d371c985c70359812e1e4a751fb2d9b200df6", 51 | "id": "batteryLife", 52 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/batteryLife" 53 | }, 54 | { 55 | "_type": "object_attribute_definition", 56 | "_resource_state": "c9b45424b52db1a01c9bcd6f2ae1919fe6a2262c3cb28ea2fbfb02324e5455b5", 57 | "id": "batteryType", 58 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/batteryType" 59 | }, 60 | { 61 | "_type": "object_attribute_definition", 62 | "_resource_state": "725a285570d393052705c7cec8cdc689b808a455ab269a79eba2b9b945b79b5b", 63 | "id": "bootType", 64 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/bootType" 65 | }, 66 | { 67 | "_type": "object_attribute_definition", 68 | "_resource_state": "d9c7203446e6892ca1359b6db401418f7de92065ee5a117cc3e3d7dfeef89cfc", 69 | "id": "bottomType", 70 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/bottomType" 71 | }, 72 | { 73 | "_type": "object_attribute_definition", 74 | "_resource_state": "aa8ad7704c3818641e179362b17cdca0b56a411e0b0c2bbcd99689bc54193554", 75 | "id": "brand", 76 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/brand" 77 | }, 78 | { 79 | "_type": "object_attribute_definition", 80 | "_resource_state": "503a227e5ed4449c29e36df3d093f000f5da55a8c3f15d50136e3a6371a0aa0a", 81 | "id": "color", 82 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/color" 83 | }, 84 | { 85 | "_type": "object_attribute_definition", 86 | "_resource_state": "899c76f81068c25aa2ed6f38087f3247cd6452c4633bf1c261e608e21fda838f", 87 | "id": "consoleWarranty", 88 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/consoleWarranty" 89 | }, 90 | { 91 | "_type": "object_attribute_definition", 92 | "_resource_state": "004d9acfb27ca3e2fa335ae09c02a07fd6c060c140e58ce2e6e4aa915d2afcd0", 93 | "id": "creationDate", 94 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/creationDate" 95 | }, 96 | { 97 | "_type": "object_attribute_definition", 98 | "_resource_state": "dacb68edca840f891239ee0b21c3f49a837868a1711b7a1eaf62e4d33e468214", 99 | "id": "customCSSFile", 100 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/customCSSFile" 101 | }, 102 | { 103 | "_type": "object_attribute_definition", 104 | "_resource_state": "743064fb382bc45d6af651418323da1cca6b7224a852267e2484fc68e442d496", 105 | "id": "digitalCameraFeatures", 106 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/digitalCameraFeatures" 107 | }, 108 | { 109 | "_type": "object_attribute_definition", 110 | "_resource_state": "afc1313f41b50bfd537bae069415cfb31b04075fd03cae98a2983a3a13a31372", 111 | "id": "digitalCameraPixels", 112 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/digitalCameraPixels" 113 | }, 114 | { 115 | "_type": "object_attribute_definition", 116 | "_resource_state": "94726ddc9bb160d07151aa07311b1bddea4caead2be714b6c658830faa60019b", 117 | "id": "digitalCameraType", 118 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/digitalCameraType" 119 | }, 120 | { 121 | "_type": "object_attribute_definition", 122 | "_resource_state": "127032df7c9398dfa107757c42579619096b8864874fa63f60a1852487068bee", 123 | "id": "digitalCameraWarranty", 124 | "link": "https://localhost:3000/s/-/dw/data/v23_2/system_object_definitions/Product/attribute_definitions/digitalCameraWarranty" 125 | } 126 | ], 127 | "next": { 128 | "_type": "result_page", 129 | "count": 20, 130 | "start": 20 131 | }, 132 | "query": { 133 | "match_all_query": { 134 | "_type": "match_all_query" 135 | } 136 | }, 137 | "start": 0, 138 | "total": 113 139 | } ``` -------------------------------------------------------------------------------- /tests/mcp/node/list-log-files.full-mode.programmatic.test.js: -------------------------------------------------------------------------------- ```javascript 1 | import { test, describe, before, after, beforeEach } from 'node:test'; 2 | import { strict as assert } from 'node:assert'; 3 | import { connect } from 'mcp-aegis'; 4 | 5 | describe('list_log_files - Full Mode Programmatic Tests - Optimized', () => { 6 | let client; 7 | 8 | before(async () => { 9 | client = await connect('./aegis.config.with-dw.json'); 10 | }); 11 | 12 | after(async () => { 13 | if (client?.connected) { 14 | await client.disconnect(); 15 | } 16 | }); 17 | 18 | beforeEach(() => { 19 | // CRITICAL: Clear all buffers to prevent leaking into next tests 20 | client.clearAllBuffers(); // Recommended - comprehensive protection 21 | }); 22 | 23 | // Optimized helper functions 24 | function assertValidMCPResponse(result) { 25 | assert.ok(result.content, 'Should have content'); 26 | assert.ok(Array.isArray(result.content), 'Content should be array'); 27 | assert.equal(typeof result.isError, 'boolean', 'isError should be boolean'); 28 | assert.equal(result.isError, false, 'Should not be an error response'); 29 | assert.equal(result.content[0].type, 'text'); 30 | } 31 | 32 | function parseResponseText(text) { 33 | return text.startsWith('"') && text.endsWith('"') ? JSON.parse(text) : text; 34 | } 35 | 36 | function assertCompleteLogFileFormat(result) { 37 | assertValidMCPResponse(result); 38 | const text = parseResponseText(result.content[0].text); 39 | 40 | // Header validation 41 | assert.ok(text.includes('Available log files:'), 'Should contain header'); 42 | 43 | // All log levels present with correct patterns 44 | const logTypes = ['debug', 'error', 'info', 'warn']; 45 | logTypes.forEach(logType => { 46 | assert.ok(new RegExp(`${logType}-blade-\\d{8}-\\d{6}\\.log`).test(text), 47 | `Should contain ${logType} log file pattern`); 48 | }); 49 | 50 | // File structure validation (emoji, paths, metadata) 51 | assert.ok(text.includes('📄'), 'Should contain file emoji icons'); 52 | assert.ok(/📄 \/[\w-]+\.log/.test(text), 'Should have proper file path format'); 53 | 54 | // Metadata validation (sizes and timestamps) 55 | const sizeMatches = text.match(/Size: [\d.,]+ (Bytes|KB|MB)/g); 56 | assert.ok(sizeMatches && sizeMatches.length >= 4, 'Should have size info for all files'); 57 | 58 | const timestampMatches = text.match(/Modified: [A-Za-z]{3}, \d{1,2} [A-Za-z]{3} \d{4} \d{2}:\d{2}:\d{2} GMT/g); 59 | assert.ok(timestampMatches && timestampMatches.length >= 4, 'Should have timestamps for all files'); 60 | 61 | return text; 62 | } 63 | 64 | // Core functionality tests 65 | describe('Core Functionality', () => { 66 | test('should list all log files with complete metadata and formatting', async () => { 67 | const result = await client.callTool('list_log_files', {}); 68 | const text = assertCompleteLogFileFormat(result); 69 | 70 | // Validate comprehensive structure in one test 71 | assert.ok(text.startsWith('Available log files:\n\n'), 'Should have proper header format'); 72 | assert.ok((text.match(/\n\n/g) || []).length >= 4, 'Should have proper spacing between entries'); 73 | 74 | // Validate each log type has complete structure 75 | const logTypes = ['debug', 'error', 'info', 'warn']; 76 | logTypes.forEach(logType => { 77 | const pattern = new RegExp(`📄 \\/${logType}-blade-\\d{8}-\\d{6}\\.log[\\s\\S]*?Size: [\\d.,]+ (Bytes|KB|MB)[\\s\\S]*?Modified: [A-Za-z]{3}, \\d{1,2} [A-Za-z]{3} \\d{4} \\d{2}:\\d{2}:\\d{2} GMT`); 78 | assert.ok(pattern.test(text), `Should have complete structure for ${logType} files`); 79 | }); 80 | }); 81 | 82 | test('should handle various parameter scenarios gracefully', async () => { 83 | // Test multiple parameter scenarios in one test 84 | const scenarios = [ 85 | {}, // Empty object 86 | { unknownParam: 'value', anotherParam: 123 }, // Unknown parameters 87 | { param: null }, // Null values 88 | { param: '' } // Empty strings 89 | ]; 90 | 91 | for (const params of scenarios) { 92 | const result = await client.callTool('list_log_files', params); 93 | assertValidMCPResponse(result); 94 | assert.ok(result.content[0].text.includes('Available log files:'), 95 | `Should work with params: ${JSON.stringify(params)}`); 96 | } 97 | }); 98 | }); 99 | 100 | // Advanced validation tests 101 | describe('Integration and Reliability', () => { 102 | test('should provide SFCC-compatible file information for analysis workflows', async () => { 103 | const result = await client.callTool('list_log_files', {}); 104 | const text = assertCompleteLogFileFormat(result); 105 | 106 | // SFCC-specific validation 107 | assert.ok(/blade-\d{8}-\d{6}\.log/.test(text), 'Should match SFCC blade naming convention'); 108 | 109 | // AI analysis compatibility 110 | const lines = text.split('\n'); 111 | const fileLines = lines.filter(line => line.includes('📄')); 112 | assert.ok(fileLines.length >= 4, 'Should have identifiable file entries for parsing'); 113 | 114 | // Metadata usefulness for log analysis 115 | assert.ok(/Size: [\d.,]+ (Bytes|KB|MB)/.test(text), 'Should have parseable size information'); 116 | assert.ok(/Modified: .+ GMT/.test(text), 'Should have parseable timestamp information'); 117 | }); 118 | 119 | test('should maintain consistency and reliability across multiple operations', async () => { 120 | const results = []; 121 | 122 | // Test consistency across 3 sequential calls 123 | for (let i = 0; i < 3; i++) { 124 | const result = await client.callTool('list_log_files', {}); 125 | results.push(result); 126 | assertCompleteLogFileFormat(result); 127 | } 128 | 129 | // Validate all results are structurally consistent 130 | const firstText = parseResponseText(results[0].content[0].text); 131 | results.slice(1).forEach((result, index) => { 132 | const text = parseResponseText(result.content[0].text); 133 | assert.ok(text.includes('debug-blade-'), `Call ${index + 2} should include debug logs`); 134 | assert.ok(text.includes('error-blade-'), `Call ${index + 2} should include error logs`); 135 | assert.equal(text.split('\n').length, firstText.split('\n').length, 136 | `Call ${index + 2} should have same number of lines as first call`); 137 | }); 138 | }); 139 | 140 | test('should execute without generating stderr and maintain clean state', async () => { 141 | client.clearStderr(); 142 | 143 | const result = await client.callTool('list_log_files', {}); 144 | assertValidMCPResponse(result); 145 | 146 | const stderr = client.getStderr(); 147 | assert.equal(stderr.trim(), '', 'Should not generate stderr output'); 148 | }); 149 | }); 150 | }); 151 | ``` -------------------------------------------------------------------------------- /.github/workflows/update-docs.yml: -------------------------------------------------------------------------------- ```yaml 1 | name: Update SFCC Documentation 2 | 3 | on: 4 | schedule: 5 | # Run weekly on Sundays at 3 AM UTC 6 | - cron: '0 3 * * 0' 7 | workflow_dispatch: 8 | # Allow manual triggering 9 | 10 | jobs: 11 | update-docs: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: write 15 | pull-requests: write 16 | 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v5 20 | with: 21 | # Use a token with write permissions for creating PRs 22 | token: ${{ secrets.GITHUB_TOKEN }} 23 | fetch-depth: 0 24 | 25 | - name: Setup Node.js 26 | uses: actions/setup-node@v5 27 | with: 28 | node-version: '20' 29 | cache: 'npm' 30 | 31 | - name: Install dependencies 32 | run: npm ci 33 | 34 | - name: Run lint checks 35 | run: npm run lint:check 36 | 37 | - name: Build project 38 | run: npm run build 39 | 40 | - name: Setup SFCC mock server 41 | run: | 42 | cd tests/servers/sfcc-mock-server 43 | npm install 44 | npm run setup:logs 45 | node server.js --port 3000 & 46 | SERVER_PID=$! 47 | echo "SERVER_PID=$SERVER_PID" >> $GITHUB_ENV 48 | sleep 5 49 | 50 | - name: Run tests 51 | run: npm test 52 | 53 | - name: Install convert-docs dependencies 54 | run: | 55 | echo "Installing additional dependencies for docs conversion..." 56 | npm install axios cheerio 57 | 58 | - name: Configure Git 59 | run: | 60 | git config user.name "github-actions[bot]" 61 | git config user.email "github-actions[bot]@users.noreply.github.com" 62 | 63 | - name: Create update branch 64 | run: | 65 | # Create a unique branch name with timestamp 66 | BRANCH_NAME="docs/automated-update-$(date +'%Y%m%d-%H%M%S')" 67 | echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV 68 | git checkout -b "$BRANCH_NAME" 69 | 70 | - name: Run docs conversion 71 | run: | 72 | echo "Starting SFCC documentation conversion..." 73 | npm run convert-docs 74 | echo "Documentation conversion completed" 75 | 76 | - name: Check for changes 77 | id: check_changes 78 | run: | 79 | # Check if there are any changes in the docs directory 80 | if git diff --quiet HEAD -- docs/; then 81 | echo "No changes detected in documentation" 82 | echo "has_changes=false" >> $GITHUB_OUTPUT 83 | else 84 | echo "Changes detected in documentation" 85 | echo "has_changes=true" >> $GITHUB_OUTPUT 86 | 87 | # Show summary of changes 88 | echo "Changed files:" 89 | git diff --name-only HEAD -- docs/ 90 | 91 | # Count changes 92 | ADDED=$(git diff --numstat HEAD -- docs/ | awk '{sum += $1} END {print sum}') 93 | DELETED=$(git diff --numstat HEAD -- docs/ | awk '{sum += $2} END {print sum}') 94 | FILES_CHANGED=$(git diff --name-only HEAD -- docs/ | wc -l) 95 | 96 | echo "files_changed=$FILES_CHANGED" >> $GITHUB_OUTPUT 97 | echo "lines_added=$ADDED" >> $GITHUB_OUTPUT 98 | echo "lines_deleted=$DELETED" >> $GITHUB_OUTPUT 99 | fi 100 | 101 | - name: Commit changes 102 | if: steps.check_changes.outputs.has_changes == 'true' 103 | run: | 104 | git add docs/ 105 | git commit -m "docs: automated update of SFCC documentation 106 | 107 | - Updated SFCC API documentation from latest sources 108 | - Files changed: ${{ steps.check_changes.outputs.files_changed }} 109 | - Lines added: ${{ steps.check_changes.outputs.lines_added }} 110 | - Lines deleted: ${{ steps.check_changes.outputs.lines_deleted }} 111 | 112 | Generated by automated workflow on $(date -u '+%Y-%m-%d %H:%M:%S UTC')" 113 | 114 | - name: Push changes 115 | if: steps.check_changes.outputs.has_changes == 'true' 116 | run: | 117 | git push origin "$BRANCH_NAME" 118 | 119 | - name: Create Pull Request 120 | if: steps.check_changes.outputs.has_changes == 'true' 121 | run: | 122 | gh pr create \ 123 | --title "📚 Automated SFCC Documentation Update" \ 124 | --body "## 🤖 Automated Documentation Update 125 | 126 | This pull request contains automated updates to the SFCC documentation scraped from the latest Salesforce Commerce Cloud documentation sources. 127 | 128 | ### 📊 Summary 129 | - **Files changed:** ${{ steps.check_changes.outputs.files_changed }} 130 | - **Lines added:** ${{ steps.check_changes.outputs.lines_added }} 131 | - **Lines deleted:** ${{ steps.check_changes.outputs.lines_deleted }} 132 | - **Generated on:** $(date -u '+%Y-%m-%d %H:%M:%S UTC') 133 | 134 | ### 🔍 What's Updated 135 | This update includes changes to the SFCC API documentation in the \`docs/\` directory, which may include: 136 | - New or updated class documentation 137 | - Method signature changes 138 | - Property documentation updates 139 | - New API additions or deprecations 140 | 141 | ### ✅ Review Checklist 142 | - [ ] Review the changed files for accuracy 143 | - [ ] Verify that no important documentation was accidentally removed 144 | - [ ] Check that the documentation format is consistent 145 | - [ ] Ensure all links and references are working correctly 146 | 147 | ### 🚀 Auto-merge 148 | This PR can be safely merged if the documentation changes look correct and don't break any existing functionality. 149 | 150 | --- 151 | *This PR was automatically created by the \`update-docs\` GitHub Action workflow.*" \ 152 | --base develop \ 153 | --head "$BRANCH_NAME" \ 154 | --label "documentation,automated,dependencies" \ 155 | --assignee taurgis \ 156 | --reviewer taurgis 157 | env: 158 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 159 | 160 | - name: Summary 161 | if: steps.check_changes.outputs.has_changes == 'false' 162 | run: | 163 | echo "✅ No documentation changes detected. The SFCC documentation is up to date." 164 | echo "Workflow completed successfully without creating a pull request." 165 | 166 | - name: Cleanup on failure 167 | if: failure() 168 | run: | 169 | echo "❌ Workflow failed. Cleaning up..." 170 | # Delete the branch if it was created but the workflow failed 171 | if [ -n "$BRANCH_NAME" ]; then 172 | git push origin --delete "$BRANCH_NAME" || echo "Branch cleanup failed or branch doesn't exist remotely" 173 | fi 174 | 175 | - name: Stop SFCC mock server 176 | if: always() 177 | run: | 178 | if [ -n "${SERVER_PID:-}" ]; then 179 | kill "$SERVER_PID" || true 180 | fi 181 | pkill -f "node.*tests/servers/sfcc-mock-server/server.js" || true 182 | lsof -ti :3000 | xargs kill -9 2>/dev/null || true 183 | ``` -------------------------------------------------------------------------------- /docs-site/utils/search.ts: -------------------------------------------------------------------------------- ```typescript 1 | 2 | import { GENERATED_SEARCH_INDEX, SearchableItem } from '../src/generated-search-index'; 3 | 4 | export interface SearchResult { 5 | path: string; 6 | pageTitle: string; 7 | heading: string; 8 | headingId?: string; 9 | snippet: string; 10 | // FIX: Add optional score property to be used for ranking search results. 11 | score?: number; 12 | } 13 | 14 | // Fallback search index (manually maintained for development/emergency use) 15 | const FALLBACK_SEARCH_INDEX: SearchableItem[] = [ 16 | // HomePage 17 | { path: '/', pageTitle: 'Introduction', heading: 'SFCC Development MCP Server', content: 'AI-powered Model Context Protocol server for Salesforce B2C Commerce Cloud development with comprehensive documentation, log analysis, best practices, and cartridge generation tools.' }, 18 | { path: '/', pageTitle: 'Introduction', heading: 'Quick Start', content: 'Get up and running with SFCC Development MCP Server in minutes. Install and configure to start using AI-assisted SFCC development tools.' }, 19 | { path: '/', pageTitle: 'Introduction', heading: 'Key Features', content: 'SFCC Documentation Access, Log Analysis, Best Practices Guides, Cartridge Generation, System Object Management, Code Version Control.' }, 20 | { path: '/', pageTitle: 'Introduction', heading: 'Why Choose SFCC Development MCP Server?', content: 'The comprehensive solution for AI-assisted SFCC development. Complete SFCC API Coverage, Real-time Log Analysis, Production Ready, Developer Friendly.' }, 21 | 22 | // AIInterfacesPage 23 | { path: '/ai-interfaces/', pageTitle: 'AI Assistant Setup', heading: 'AI Assistant Setup Guide', content: 'Set up the SFCC Development MCP Server with your AI assistant. Connect Claude Desktop, Cursor AI, or other MCP-compatible tools.' }, 24 | { path: '/ai-interfaces/', pageTitle: 'AI Assistant Setup', heading: 'Claude Desktop', content: 'Configure Claude Desktop to use the SFCC Development MCP Server for enhanced SFCC development assistance.' }, 25 | { path: '/ai-interfaces/', pageTitle: 'AI Assistant Setup', heading: 'Cursor AI', content: 'Set up Cursor AI editor with the MCP server for intelligent code completion and SFCC guidance.' }, 26 | 27 | // ConfigurationPage 28 | { path: '/configuration/', pageTitle: 'Configuration', heading: 'Configuration Guide', content: 'Configure SFCC Development MCP Server for your Commerce Cloud environment.' }, 29 | { path: '/configuration/', pageTitle: 'Configuration', heading: 'Operating Modes', content: 'Documentation-only mode or full mode with SFCC credentials for complete functionality.' }, 30 | 31 | // AI InterfacesPage 32 | { path: '/ai-interfaces/', pageTitle: 'AI Interfaces', heading: 'AI Interface Setup', content: 'Configure your AI assistant to work with SFCC Development MCP Server.' }, 33 | 34 | // FeaturesPage 35 | { path: '/features/', pageTitle: 'Features', heading: 'Features Overview', content: 'Comprehensive SFCC development tools powered by AI assistance.' }, 36 | 37 | // ToolsPage 38 | { path: '/tools/', pageTitle: 'Tools', heading: 'Available Tools', content: 'Complete list of available tools for SFCC development assistance.' }, 39 | 40 | // ExamplesPage 41 | { path: '/examples/', pageTitle: 'Examples', heading: 'Examples & Use Cases', content: 'Real-world examples of using SFCC Development MCP Server for various development tasks.' }, 42 | 43 | // SecurityPage 44 | { path: '/security/', pageTitle: 'Security', heading: 'Security Guidelines', content: 'Security best practices for using SFCC Development MCP Server.' }, 45 | 46 | // DevelopmentPage 47 | { path: '/development/', pageTitle: 'Development', heading: 'Development Guide', content: 'Contributing to SFCC Development MCP Server development.' }, 48 | 49 | // TroubleshootingPage 50 | { path: '/troubleshooting/', pageTitle: 'Troubleshooting', heading: 'Troubleshooting & Debugging', content: 'Common issues and solutions for SFCC Development MCP Server.' }, 51 | ]; 52 | 53 | // Use generated index if available, otherwise fall back to manual index 54 | const getSearchIndex = (): SearchableItem[] => { 55 | try { 56 | // Check if the generated index has meaningful content 57 | if (GENERATED_SEARCH_INDEX.length > 1 || 58 | (GENERATED_SEARCH_INDEX.length === 1 && 59 | GENERATED_SEARCH_INDEX[0].content !== 'AI-powered Model Context Protocol server for Salesforce B2C Commerce Cloud development.')) { 60 | return GENERATED_SEARCH_INDEX; 61 | } 62 | } catch (error) { 63 | console.warn('Failed to load generated search index, using fallback:', error); 64 | } 65 | 66 | return FALLBACK_SEARCH_INDEX; 67 | }; 68 | 69 | // Manually populated search index from all documentation pages 70 | const createSnippet = (text: string, query: string): string => { 71 | const queryLower = query.toLowerCase(); 72 | const textLower = text.toLowerCase(); 73 | const index = textLower.indexOf(queryLower); 74 | 75 | if (index === -1) { 76 | return text.length > 150 ? text.substring(0, 150) + '...' : text; 77 | } 78 | 79 | const start = Math.max(0, index - 50); 80 | const end = Math.min(text.length, index + query.length + 50); 81 | 82 | let snippet = text.substring(start, end); 83 | if (start > 0) snippet = '...' + snippet; 84 | if (end < text.length) snippet = snippet + '...'; 85 | 86 | return snippet; 87 | }; 88 | 89 | export function searchDocs(query: string): SearchResult[] { 90 | if (!query) return []; 91 | 92 | const queryLower = query.toLowerCase(); 93 | const searchIndex = getSearchIndex(); 94 | const results: SearchResult[] = []; 95 | 96 | searchIndex.forEach(item => { 97 | const contentLower = item.content.toLowerCase(); 98 | const headingLower = item.heading.toLowerCase(); 99 | const titleLower = item.pageTitle.toLowerCase(); 100 | 101 | let score = 0; 102 | if (titleLower.includes(queryLower)) score += 5; 103 | if (headingLower.includes(queryLower)) score += 3; 104 | if (contentLower.includes(queryLower)) score += 1; 105 | 106 | if (score > 0) { 107 | results.push({ 108 | path: item.path, 109 | pageTitle: item.pageTitle, 110 | heading: item.heading, 111 | headingId: item.headingId, 112 | snippet: createSnippet(item.content, query), 113 | score: score, 114 | }); 115 | } 116 | }); 117 | 118 | // Remove duplicates by path and heading, keeping the one with the highest score 119 | const uniqueResults = Array.from( 120 | results.reduce((map, item) => { 121 | const key = `${item.path}-${item.heading}`; 122 | if (!map.has(key) || (map.get(key)?.score ?? 0) < (item.score ?? 0)) { 123 | map.set(key, item); 124 | } 125 | return map; 126 | }, new Map<string, SearchResult>()).values() 127 | ); 128 | 129 | return uniqueResults 130 | .sort((a, b) => (b.score ?? 0) - (a.score ?? 0)) 131 | .slice(0, 20); 132 | } 133 | ```