#
tokens: 45785/50000 5/825 files (page 40/61)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 40 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/dw_net/WebDAVClient.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.net
  2 | 
  3 | # Class WebDAVClient
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.net.WebDAVClient
  9 | 
 10 | ## Description
 11 | 
 12 | The WebDAVClient class supports the WebDAV methods GET, PUT, MKCOL, MOVE, COPY, PROPFIND,OPTIONS and DELETE. Note: when this class is used with sensitive data, be careful in persisting sensitive information to disk. The client can be used as shown in the following example: var webdavClient : WebDAVClient = new WebDAVClient("http://mywebdav.server.com","myusername", "mypassword"); var getString : String = webdavClient.get("myData.xml","UTF-8"); var message : String; if (webdavClient.succeeded()) { message = webDavClient.statusText; } else { // error handling message="An error occurred with status code "+webdavClient.statusCode; } var data : XML = new XML(getString); The WebDAV client supports the following authentication schemes: Basic authentication Digest authentication The methods of this class do not generally throw exceptions if the underlying WebDAV operation do not succeed.The result of a WebDAV operation can be checked using the methods succeeded(), getStatusCode(), and getStatusText(). Important note: This WebDAV client cannot be used to access the Commerce Cloud Digital server via WebDAV protocol.
 13 | 
 14 | ## Constants
 15 | 
 16 | ### DEFAULT_ENCODING
 17 | 
 18 | **Type:** String = "UTF-8"
 19 | 
 20 | The default encoding character set.
 21 | 
 22 | ### DEFAULT_GET_FILE_SIZE
 23 | 
 24 | **Type:** Number = 5242880
 25 | 
 26 | The default size for get() returning a File is 5MB.
 27 | 
 28 | ### DEFAULT_GET_STRING_SIZE
 29 | 
 30 | **Type:** Number = 2097152
 31 | 
 32 | The default size for get() returning a String is 2MB.
 33 | 
 34 | ### DEPTH_0
 35 | 
 36 | **Type:** Number = 0
 37 | 
 38 | The depth of searching a WebDAV destination using the PROPFIND method - if that depth is given to the PROPFIND method as an input parameter the destination will be searched only on the level of the given path and a list of all containing files on that level will be returned [is not supported by every server].
 39 | 
 40 | ### DEPTH_1
 41 | 
 42 | **Type:** Number = 1
 43 | 
 44 | The depth of searching a WebDAV destination using the PROPFIND method - if that depth is given to the PROPFIND method as an input parameter the destination will be searched until one level under the given path and a list of all containing files in that two levels [/path and one level underneath] will be returned [is not supported by every server].
 45 | 
 46 | ### DEPTH_INIFINITY
 47 | 
 48 | **Type:** Number = 2147483647
 49 | 
 50 | The depth of searching a WebDAV destination using the PROPFIND method - if that depth is given to the PROPFIND method as an input parameter the destination will be fully searched and a list of all containing files will be returned [is not supported by every server].
 51 | 
 52 | ### MAX_GET_FILE_SIZE
 53 | 
 54 | **Type:** Number = 209715200
 55 | 
 56 | The maximum size for get() returning a File is forty times the default size for getting a file. The largest file allowed is 200MB.
 57 | 
 58 | ### MAX_GET_STRING_SIZE
 59 | 
 60 | **Type:** Number = 10485760
 61 | 
 62 | The maximum size for get() returning a String is five times the default size for getting a String. The largest String allowed is 10MB.
 63 | 
 64 | ## Properties
 65 | 
 66 | ### allResponseHeaders
 67 | 
 68 | **Type:** HashMap (Read Only)
 69 | 
 70 | A HashMap of all response headers.
 71 | 
 72 | ### statusCode
 73 | 
 74 | **Type:** Number (Read Only)
 75 | 
 76 | The status code after the execution of a method.
 77 | 
 78 | ### statusText
 79 | 
 80 | **Type:** String (Read Only)
 81 | 
 82 | The status text after the execution of a method.
 83 | 
 84 | ## Constructor Summary
 85 | 
 86 | WebDAVClient(rootUrl : String, username : String, password : String) Creates a new client for the use at a server which requires authentication.
 87 | 
 88 | WebDAVClient(rootUrl : String) Creates a new client for the use at a server which does not require authentication.
 89 | 
 90 | ## Method Summary
 91 | 
 92 | ### addRequestHeader
 93 | 
 94 | **Signature:** `addRequestHeader(headerName : String, headerValue : String) : void`
 95 | 
 96 | Adds a request header to the next WebDAV call.
 97 | 
 98 | ### close
 99 | 
100 | **Signature:** `close() : void`
101 | 
102 | Closes the current connection to the server.
103 | 
104 | ### copy
105 | 
106 | **Signature:** `copy(origin : String, destination : String) : boolean`
107 | 
108 | Copies a file on the server from one place rootUrl/origin to the other rootUrl/destination.
109 | 
110 | ### copy
111 | 
112 | **Signature:** `copy(origin : String, destination : String, overwrite : boolean) : boolean`
113 | 
114 | Copies a file on the server from one place rootUrl/origin to the other rootUrl/destination.
115 | 
116 | ### copy
117 | 
118 | **Signature:** `copy(origin : String, destination : String, overwrite : boolean, shallow : boolean) : boolean`
119 | 
120 | Copies a file on the server from one place rootUrl/origin to the other rootUrl/destination.
121 | 
122 | ### del
123 | 
124 | **Signature:** `del(path : String) : boolean`
125 | 
126 | Deletes a file or directory from the remote server that can be found under rootUrl/path.
127 | 
128 | ### get
129 | 
130 | **Signature:** `get(path : String) : String`
131 | 
132 | Reads the content of a remote file or directory that can be found under rootUrl/path and returns a string representation of the data found in the DEFAULT_ENCODING encoding.
133 | 
134 | ### get
135 | 
136 | **Signature:** `get(path : String, encoding : String) : String`
137 | 
138 | Reads the content of a remote file or directory that can be found under rootUrl/path and returns a string representation of the data found in the given encoding.
139 | 
140 | ### get
141 | 
142 | **Signature:** `get(path : String, encoding : String, maxGetSize : Number) : String`
143 | 
144 | Reads the content of a remote file or directory that can be found under rootUrl/path and returns a string representation of the data found in the given encoding.
145 | 
146 | ### get
147 | 
148 | **Signature:** `get(path : String, file : File) : boolean`
149 | 
150 | Reads the content of a remote file or directory that can be found under rootUrl/path in DEFAULT_ENCODING encoding and writes a File in the system's standard encoding, which is "UTF-8".
151 | 
152 | ### get
153 | 
154 | **Signature:** `get(path : String, file : File, maxFileSize : Number) : boolean`
155 | 
156 | Reads the content of a remote file or directory that can be found under rootUrl/path in DEFAULT_ENCODING encoding and writes a File in the system's standard encoding, which is "UTF-8".
157 | 
158 | ### get
159 | 
160 | **Signature:** `get(path : String, file : File, encoding : String, maxFileSize : Number) : boolean`
161 | 
162 | Reads the content of a remote file or directory that can be found under rootUrl/path in the passed encoding and writes a File in the system standard encoding, which is "UTF-8".
163 | 
164 | ### getAllResponseHeaders
165 | 
166 | **Signature:** `getAllResponseHeaders() : HashMap`
167 | 
168 | Returns a HashMap of all response headers.
169 | 
170 | ### getBinary
171 | 
172 | **Signature:** `getBinary(path : String, file : File) : boolean`
173 | 
174 | Reads the content of a remote binary file that can be found under rootUrl/path and creates a local copy in File.
175 | 
176 | ### getBinary
177 | 
178 | **Signature:** `getBinary(path : String, file : File, maxFileSize : Number) : boolean`
179 | 
180 | Reads the content of a remote binary file that can be found under rootUrl/path and creates a local copy in File.
181 | 
182 | ### getResponseHeader
183 | 
184 | **Signature:** `getResponseHeader(header : String) : String`
185 | 
186 | Returns a specified response header - multiple headers are separated by CRLF.
187 | 
188 | ### getStatusCode
189 | 
190 | **Signature:** `getStatusCode() : Number`
191 | 
192 | Returns the status code after the execution of a method.
193 | 
194 | ### getStatusText
195 | 
196 | **Signature:** `getStatusText() : String`
197 | 
198 | Returns the status text after the execution of a method.
199 | 
200 | ### mkcol
201 | 
202 | **Signature:** `mkcol(path : String) : boolean`
203 | 
204 | Creates a directory on the remote server on the location rootUrl/path.
205 | 
206 | ### move
207 | 
208 | **Signature:** `move(origin : String, destination : String) : boolean`
209 | 
210 | Moves a file on the server from one place rootUrl + "/" +origin to the other rootUrl/destination.
211 | 
212 | ### move
213 | 
214 | **Signature:** `move(origin : String, destination : String, overwrite : boolean) : boolean`
215 | 
216 | Moves a file on the server from one place rootUrl/origin to the other rootUrl/destination Can also be used to rename a remote file.
217 | 
218 | ### options
219 | 
220 | **Signature:** `options(path : String) : String[]`
221 | 
222 | Returns a list of methods which can be executed on the server location rootUrl/path.
223 | 
224 | ### propfind
225 | 
226 | **Signature:** `propfind(path : String) : WebDAVFileInfo[]`
227 | 
228 | Get file listing of a remote location.
229 | 
230 | ### propfind
231 | 
232 | **Signature:** `propfind(path : String, depth : Number) : WebDAVFileInfo[]`
233 | 
234 | Get file listing of a remote location.
235 | 
236 | ### put
237 | 
238 | **Signature:** `put(path : String, content : String) : boolean`
239 | 
240 | Puts content encoded with DEFAULT_ENCODING into a remote located file at rootUrl/path.
241 | 
242 | ### put
243 | 
244 | **Signature:** `put(path : String, content : String, encoding : String) : boolean`
245 | 
246 | Puts content encoded with the passed encoding into a remote located file at rootUrl/path.
247 | 
248 | ### put
249 | 
250 | **Signature:** `put(path : String, file : File) : boolean`
251 | 
252 | Puts content out of a passed local file into a remote located file at rootUrl/path.
253 | 
254 | ### succeeded
255 | 
256 | **Signature:** `succeeded() : boolean`
257 | 
258 | Returns true if the last executed WebDAV method was executed successfully - otherwise false.
259 | 
260 | ## Constructor Detail
261 | 
262 | ## Method Detail
263 | 
264 | ## Method Details
265 | 
266 | ### addRequestHeader
267 | 
268 | **Signature:** `addRequestHeader(headerName : String, headerValue : String) : void`
269 | 
270 | **Description:** Adds a request header to the next WebDAV call.
271 | 
272 | **Parameters:**
273 | 
274 | - `headerName`: name of the header.
275 | - `headerValue`: value of the header.
276 | 
277 | ---
278 | 
279 | ### close
280 | 
281 | **Signature:** `close() : void`
282 | 
283 | **Description:** Closes the current connection to the server.
284 | 
285 | ---
286 | 
287 | ### copy
288 | 
289 | **Signature:** `copy(origin : String, destination : String) : boolean`
290 | 
291 | **Description:** Copies a file on the server from one place rootUrl/origin to the other rootUrl/destination. If destination already exists it gets overwritten. Returns true if succeeded, otherwise false.
292 | 
293 | **Parameters:**
294 | 
295 | - `origin`: The origin where a file is located, relative to the rootUrl stated when instantiating the client.
296 | - `destination`: The destination where the file should be copied to, relative to the rootUrl stated when instantiating the client.
297 | 
298 | **Returns:**
299 | 
300 | true if succeeded, otherwise false.
301 | 
302 | ---
303 | 
304 | ### copy
305 | 
306 | **Signature:** `copy(origin : String, destination : String, overwrite : boolean) : boolean`
307 | 
308 | **Description:** Copies a file on the server from one place rootUrl/origin to the other rootUrl/destination. If the passed parameter overwrite is true and destination already exists it gets overwritten. Returns true if succeeded, otherwise false.
309 | 
310 | **Parameters:**
311 | 
312 | - `origin`: The origin where a file is located, relative to the rootUrl stated when instantiating the client.
313 | - `destination`: The destination where the file should be copied to, relative to the rootUrl stated when instantiating the client.
314 | - `overwrite`: A flag which determines whether the destination gets overwritten if it exists before copying.
315 | 
316 | **Returns:**
317 | 
318 | true if succeeded, otherwise false.
319 | 
320 | ---
321 | 
322 | ### copy
323 | 
324 | **Signature:** `copy(origin : String, destination : String, overwrite : boolean, shallow : boolean) : boolean`
325 | 
326 | **Description:** Copies a file on the server from one place rootUrl/origin to the other rootUrl/destination. If the passed parameter overwrite is true and destination already exists it gets overwritten. If the passed parameter shallow is true a flat copy mechanism is used. Returns true if succeeded, otherwise false.
327 | 
328 | **Parameters:**
329 | 
330 | - `origin`: The origin where a file is located, relative to the rootUrl stated when instantiating the client.
331 | - `destination`: The destination where the file should be copied to, relative to the rootUrl stated when instantiating the client.
332 | - `overwrite`: A flag which determines whether the destination gets overwritten if it exits before copying
333 | - `shallow`: A flag which determines how to copy the given data.
334 | 
335 | **Returns:**
336 | 
337 | true if succeeded, otherwise false.
338 | 
339 | ---
340 | 
341 | ### del
342 | 
343 | **Signature:** `del(path : String) : boolean`
344 | 
345 | **Description:** Deletes a file or directory from the remote server that can be found under rootUrl/path. Returns true if succeeded, otherwise false.
346 | 
347 | **Parameters:**
348 | 
349 | - `path`: The path of the file or collection to delete, relative to the rootUrl stated when instantiating the client.
350 | 
351 | **Returns:**
352 | 
353 | true if succeeded, otherwise false.
354 | 
355 | ---
356 | 
357 | ### get
358 | 
359 | **Signature:** `get(path : String) : String`
360 | 
361 | **Description:** Reads the content of a remote file or directory that can be found under rootUrl/path and returns a string representation of the data found in the DEFAULT_ENCODING encoding. If the remote location is a directory the result depends on the server configuration, some return an HTML formatted directory listing. Returns at most DEFAULT_GET_STRING_SIZE bytes.
362 | 
363 | **Parameters:**
364 | 
365 | - `path`: The path of the collection or file one wants to get, relative to the rootUrl stated when instantiating the client.
366 | 
367 | **Returns:**
368 | 
369 | returns the String representation of the data found on the given path.
370 | 
371 | ---
372 | 
373 | ### get
374 | 
375 | **Signature:** `get(path : String, encoding : String) : String`
376 | 
377 | **Description:** Reads the content of a remote file or directory that can be found under rootUrl/path and returns a string representation of the data found in the given encoding. If the remote location is a directory the result depends on the server configuration, some return an HTML formatted directory listing. Returns at most DEFAULT_GET_STRING_SIZE bytes.
378 | 
379 | **Parameters:**
380 | 
381 | - `path`: The path of the collection or file one wants to get - relative to the rootUrl stated when instantiating the client.
382 | - `encoding`: The encoding of the resulting String.
383 | 
384 | **Returns:**
385 | 
386 | returns the String representation of the data found on the given path in the given encoding.
387 | 
388 | ---
389 | 
390 | ### get
391 | 
392 | **Signature:** `get(path : String, encoding : String, maxGetSize : Number) : String`
393 | 
394 | **Description:** Reads the content of a remote file or directory that can be found under rootUrl/path and returns a string representation of the data found in the given encoding. If the remote location is a directory the result depends on the server configuration, some return an HTML formatted directory listing. Returns at most maxGetSize bytes.
395 | 
396 | **Parameters:**
397 | 
398 | - `path`: The path of the collection or file one wants to get - relative to the rootUrl stated when instantiating the client.
399 | - `encoding`: The encoding of the resulting String.
400 | - `maxGetSize`: The maximum size of data in bytes. Not to exceed MAX_GET_STRING_SIZE.
401 | 
402 | **Returns:**
403 | 
404 | returns the String representation of the data found on the given path in the given encoding.
405 | 
406 | ---
407 | 
408 | ### get
409 | 
410 | **Signature:** `get(path : String, file : File) : boolean`
411 | 
412 | **Description:** Reads the content of a remote file or directory that can be found under rootUrl/path in DEFAULT_ENCODING encoding and writes a File in the system's standard encoding, which is "UTF-8". If the remote location is a directory the result depends on the server configuration, some return an HTML formatted directory listing. Receives at most DEFAULT_GET_FILE_SIZE bytes which determines the file size of the local file. Returns true if succeeded otherwise false.
413 | 
414 | **Parameters:**
415 | 
416 | - `path`: The path of the collection or file one wants to get - relative to the rootUrl stated when instantiating the client.
417 | - `file`: The file to save the received data in.
418 | 
419 | **Returns:**
420 | 
421 | returns true if succeeded, otherwise false.
422 | 
423 | ---
424 | 
425 | ### get
426 | 
427 | **Signature:** `get(path : String, file : File, maxFileSize : Number) : boolean`
428 | 
429 | **Description:** Reads the content of a remote file or directory that can be found under rootUrl/path in DEFAULT_ENCODING encoding and writes a File in the system's standard encoding, which is "UTF-8". If the remote location is a directory the result depends on the server configuration, some return an HTML formatted directory listing. Receives at most maxFileSize bytes which determines the file size of the local file. Returns true if succeeded, otherwise false.
430 | 
431 | **Parameters:**
432 | 
433 | - `path`: The path of the collection or file one wants to get - relative to the rootUrl stated when instantiating the client.
434 | - `file`: The file to save the received data in.
435 | - `maxFileSize`: The maximum size of bytes to stream into the file. Not to exceed MAX_GET_FILE_SIZE.
436 | 
437 | **Returns:**
438 | 
439 | returns true if succeeded, otherwise false.
440 | 
441 | ---
442 | 
443 | ### get
444 | 
445 | **Signature:** `get(path : String, file : File, encoding : String, maxFileSize : Number) : boolean`
446 | 
447 | **Description:** Reads the content of a remote file or directory that can be found under rootUrl/path in the passed encoding and writes a File in the system standard encoding, which is "UTF-8". If the remote location is a directory the result depends on the server configuration, some return an HTML formatted directory listing. Receives at most maxFileSize bytes which determines the file size of the local file. Returns true if succeeded, otherwise false.
448 | 
449 | **Parameters:**
450 | 
451 | - `path`: The path of the collection or file one wants to get - relative to the rootUrl stated when instantiating the client.
452 | - `file`: The file to save the received data in.
453 | - `encoding`: The encoding to use when reading the remote file.
454 | - `maxFileSize`: The maximum number of bytes to stream into the file. Not to exceed MAX_GET_FILE_SIZE.
455 | 
456 | **Returns:**
457 | 
458 | returns true if succeeded, otherwise false.
459 | 
460 | ---
461 | 
462 | ### getAllResponseHeaders
463 | 
464 | **Signature:** `getAllResponseHeaders() : HashMap`
465 | 
466 | **Description:** Returns a HashMap of all response headers.
467 | 
468 | **Returns:**
469 | 
470 | all headers in a HashMap.
471 | 
472 | ---
473 | 
474 | ### getBinary
475 | 
476 | **Signature:** `getBinary(path : String, file : File) : boolean`
477 | 
478 | **Description:** Reads the content of a remote binary file that can be found under rootUrl/path and creates a local copy in File. If the remote location is a directory the result depends on the server configuration, some return an HTML formatted directory listing. Copies at most DEFAULT_GET_FILE_SIZE bytes. Returns true if succeeded, otherwise false.
479 | 
480 | **Parameters:**
481 | 
482 | - `path`: The path relative to rootUrl on the remote server including the file name.
483 | - `file`: The local file where the received binary data should be stored.
484 | 
485 | **Returns:**
486 | 
487 | true if succeeded, otherwise false.
488 | 
489 | ---
490 | 
491 | ### getBinary
492 | 
493 | **Signature:** `getBinary(path : String, file : File, maxFileSize : Number) : boolean`
494 | 
495 | **Description:** Reads the content of a remote binary file that can be found under rootUrl/path and creates a local copy in File. If the remote location is a directory the result depends on the server configuration, some return an HTML formatted directory listing. Copies at most maxFileSize bytes. Returns true if succeeded, otherwise false.
496 | 
497 | **Parameters:**
498 | 
499 | - `path`: The path relative to rootUrl on the remote server including the file name.
500 | - `file`: The file local file where the received binary data should be stored.
501 | - `maxFileSize`: The maximum number of bytes to stream into the file. Not to exceed MAX_GET_FILE_SIZE.
502 | 
503 | **Returns:**
504 | 
505 | true if succeeded, otherwise false.
506 | 
507 | ---
508 | 
509 | ### getResponseHeader
510 | 
511 | **Signature:** `getResponseHeader(header : String) : String`
512 | 
513 | **Description:** Returns a specified response header - multiple headers are separated by CRLF.
514 | 
515 | **Parameters:**
516 | 
517 | - `header`: The name of the header.
518 | 
519 | **Returns:**
520 | 
521 | The header - in case of multiple headers separated by CRLF.
522 | 
523 | ---
524 | 
525 | ### getStatusCode
526 | 
527 | **Signature:** `getStatusCode() : Number`
528 | 
529 | **Description:** Returns the status code after the execution of a method.
530 | 
531 | **Returns:**
532 | 
533 | the statusCode.
534 | 
535 | ---
536 | 
537 | ### getStatusText
538 | 
539 | **Signature:** `getStatusText() : String`
540 | 
541 | **Description:** Returns the status text after the execution of a method.
542 | 
543 | **Returns:**
544 | 
545 | the statusText.
546 | 
547 | ---
548 | 
549 | ### mkcol
550 | 
551 | **Signature:** `mkcol(path : String) : boolean`
552 | 
553 | **Description:** Creates a directory on the remote server on the location rootUrl/path.
554 | 
555 | **Parameters:**
556 | 
557 | - `path`: The path relative to the rootUrl stated when instantiating the client where the new collection should be created.
558 | 
559 | **Returns:**
560 | 
561 | true if succeeded, otherwise false.
562 | 
563 | ---
564 | 
565 | ### move
566 | 
567 | **Signature:** `move(origin : String, destination : String) : boolean`
568 | 
569 | **Description:** Moves a file on the server from one place rootUrl + "/" +origin to the other rootUrl/destination. If destination already exists it gets overwritten. Can also be used to rename a remote file. Returns true if succeeded, otherwise false.
570 | 
571 | **Parameters:**
572 | 
573 | - `origin`: The origin where a file is located, relative to the rootUrl stated when instantiating the client.
574 | - `destination`: The destination where the file should be moved to, relative to the rootUrl stated when instantiating the client.
575 | 
576 | **Returns:**
577 | 
578 | true if succeeded, otherwise false.
579 | 
580 | ---
581 | 
582 | ### move
583 | 
584 | **Signature:** `move(origin : String, destination : String, overwrite : boolean) : boolean`
585 | 
586 | **Description:** Moves a file on the server from one place rootUrl/origin to the other rootUrl/destination Can also be used to rename a remote file. If overwrite is true and destination already exists it gets overwritten. Returns true if succeeded, otherwise false.
587 | 
588 | **Parameters:**
589 | 
590 | - `origin`: The origin where a file is located, relative to the rootUrl stated when instantiating the client.
591 | - `destination`: The destination where the file should be moved to, relative to the rootUrl stated when instantiating the client.
592 | - `overwrite`: A flag which determines whether the destination gets overwritten if it exists before moving.
593 | 
594 | **Returns:**
595 | 
596 | true if succeeded, otherwise false.
597 | 
598 | ---
599 | 
600 | ### options
601 | 
602 | **Signature:** `options(path : String) : String[]`
603 | 
604 | **Description:** Returns a list of methods which can be executed on the server location rootUrl/path.
605 | 
606 | **Parameters:**
607 | 
608 | - `path`: The path relative to the rootUrl stated when instantiating the client one wants to get the options for.
609 | 
610 | **Returns:**
611 | 
612 | list of WebDav methods which can be executed on the given path.
613 | 
614 | ---
615 | 
616 | ### propfind
617 | 
618 | **Signature:** `propfind(path : String) : WebDAVFileInfo[]`
619 | 
620 | **Description:** Get file listing of a remote location. Returns a list of WebDAVFileInfo objects which contain information about the files and directories located on rootUrl/path and DEPTH_1 (1) level underneath.
621 | 
622 | **Parameters:**
623 | 
624 | - `path`: The path relative to the rootUrl stated when instantiating the client where to get information about the containing files from.
625 | 
626 | **Returns:**
627 | 
628 | an Array of WebDAVFileInfo objects which hold information about the files located on the server at the location.
629 | 
630 | ---
631 | 
632 | ### propfind
633 | 
634 | **Signature:** `propfind(path : String, depth : Number) : WebDAVFileInfo[]`
635 | 
636 | **Description:** Get file listing of a remote location. Returns a list of WebDAVFileInfo objects which contain information about the files and directories located on rootUrl/path and the passed depth underneath.
637 | 
638 | **Parameters:**
639 | 
640 | - `path`: The path relative to the rootUrl stated when instantiating the client where to get information about the containing files from.
641 | - `depth`: The level starting from rootUrl down to which the file information gets collected.
642 | 
643 | **Returns:**
644 | 
645 | an Array of WebDAVFileInfo objects which hold information about the files located on the server at the location.
646 | 
647 | ---
648 | 
649 | ### put
650 | 
651 | **Signature:** `put(path : String, content : String) : boolean`
652 | 
653 | **Description:** Puts content encoded with DEFAULT_ENCODING into a remote located file at rootUrl/path. Returns true if succeeded, otherwise false. If the content of a local file is to be uploaded, please use method put(String, File) instead.
654 | 
655 | **Parameters:**
656 | 
657 | - `path`: The path to put given content up to, relative to the rootUrl stated when instantiating the client.
658 | - `content`: The content that has to be pushed on to the server.
659 | 
660 | **Returns:**
661 | 
662 | true if succeeded, otherwise false.
663 | 
664 | ---
665 | 
666 | ### put
667 | 
668 | **Signature:** `put(path : String, content : String, encoding : String) : boolean`
669 | 
670 | **Description:** Puts content encoded with the passed encoding into a remote located file at rootUrl/path. Returns true if succeeded, otherwise false. If the content of a local file is to be uploaded, please use method put(String, File) instead.
671 | 
672 | **Parameters:**
673 | 
674 | - `path`: The path to put a given content up to, relative to the rootUrl stated when instantiating the client.
675 | - `content`: The content that has to be pushed on to a remote location.
676 | - `encoding`: The encoding in which the data should be stored on the server.
677 | 
678 | **Returns:**
679 | 
680 | true if succeeded, otherwise false.
681 | 
682 | ---
683 | 
684 | ### put
685 | 
686 | **Signature:** `put(path : String, file : File) : boolean`
687 | 
688 | **Description:** Puts content out of a passed local file into a remote located file at rootUrl/path. This method performs a binary file transfer. Returns true if succeeded, otherwise false.
689 | 
690 | **Parameters:**
691 | 
692 | - `path`: The path to put given content up to, relative to the rootUrl stated when instantiating the client.
693 | - `file`: The file to push up to the server.
694 | 
695 | **Returns:**
696 | 
697 | true if succeeded, otherwise false.
698 | 
699 | ---
700 | 
701 | ### succeeded
702 | 
703 | **Signature:** `succeeded() : boolean`
704 | 
705 | **Description:** Returns true if the last executed WebDAV method was executed successfully - otherwise false. See the code snippet above for an example how to use the succeed() method.
706 | 
707 | **Returns:**
708 | 
709 | true if the last executed WebDAV method was successful - otherwise false.
710 | 
711 | **See Also:**
712 | 
713 | WebDAVClient
714 | 
715 | ---
```

--------------------------------------------------------------------------------
/ai-instructions/github-copilot/copilot-instructions.md:
--------------------------------------------------------------------------------

```markdown
  1 | # SFCC Development AI Assistant Instructions
  2 | 
  3 | ## 👨‍💻 Agent Persona
  4 | 
  5 | You are a **Senior Salesforce B2C Commerce Cloud (Demandware) Developer** with 8+ years of hands-on experience building enterprise-grade ecommerce solutions. Your expertise includes:
  6 | 
  7 | ### 🏗️ Core Development Areas
  8 | - **SFRA Controllers**: Expert in creating performant, maintainable controllers following MVC patterns
  9 | - **SFRA Models**: Deep knowledge of JSON object layer design, model architecture, and data transformation patterns
 10 | - **LocalServiceRegistry**: Expert in server-to-server integrations, OAuth flows, and reusable service module patterns
 11 | - **OCAPI Hooks**: Deep knowledge of extending Open Commerce APIs with custom business logic
 12 | - **SCAPI Hooks**: Specialized in Shop API extensions and modern headless commerce patterns
 13 | - **Custom SCAPI Endpoints**: Building secure, scalable REST APIs for custom integrations
 14 | - **Cartridge Development**: Architecting modular, reusable cartridge solutions
 15 | - **ISML Templates**: Expert in template development with security and performance optimization
 16 | 
 17 | ### 🔒 Security & Best Practices
 18 | - **Secure Coding**: OWASP compliance, input validation, XSS/CSRF prevention
 19 | - **Performance Optimization**: Query optimization, caching strategies, code profiling
 20 | - **Accessibility**: WCAG 2.1 AA compliance, semantic HTML, keyboard navigation
 21 | - **Code Quality**: Clean code principles, design patterns, code reviews
 22 | - **Testing**: Unit testing, integration testing, performance testing
 23 | 
 24 | ### 💼 Professional Approach
 25 | - **Solution-Oriented**: Always provide practical, implementable solutions
 26 | - **Best Practice Focused**: Follow SFCC development standards and industry conventions
 27 | - **Security-First**: Consider security implications in every recommendation
 28 | - **Performance-Aware**: Optimize for scalability and user experience
 29 | - **Documentation-Driven**: Provide clear explanations and code comments
 30 | 
 31 | When providing assistance:
 32 | 1. **Always use the MCP tools** to get current, accurate SFCC information
 33 | 2. **Consider the full context** - security, performance, maintainability
 34 | 4. **Explain the "why"** behind architectural decisions
 35 | 5. **Reference official documentation** and best practices
 36 | 6. **Cartridge Creation**: When asked to create a cartridge, follow the instructions in the MCP (especially creating the structure using sgmf-scripts, don't try to do this yourself)
 37 | 
 38 | ### 🔧 Code Quality & Linting
 39 | 
 40 | **SFCC Class Verification**: Before using any SFCC class, verify its existence and check for information about its methods and properties. Pay attention to deprecations and changes in the API.
 41 | 
 42 | **ESLint Integration**: Before manually fixing linting errors:
 43 | 1. **First attempt automatic fixes**: Run `npm run lint:fix` or `eslint --fix` if available
 44 | 2. **Check results**: Use `get_errors` tool to verify what remains after auto-fix
 45 | 3. **Manual fixes only**: Apply manual corrections only for issues that auto-fix couldn't resolve
 46 | 4. **Validate changes**: Always run error checking after making manual corrections
 47 | 
 48 | This approach ensures:
 49 | - ✅ Consistent formatting and style enforcement
 50 | - ✅ Automatic resolution of common linting issues
 51 | - ✅ Reduced manual intervention for routine fixes
 52 | - ✅ Focus on logic errors that require human judgment
 53 | 
 54 | ---
 55 | 
 56 | This project uses the **SFCC Development MCP Server** to provide accurate, up-to-date information about Salesforce B2C Commerce Cloud (SFCC) development. When working on SFCC-related tasks, **always use the available MCP tools** instead of relying on potentially outdated or inaccurate information from your training data.
 57 | 
 58 | ## 🎯 Why Use the MCP Tools
 59 | 
 60 | - **Accuracy**: Get current, verified SFCC API documentation and best practices
 61 | - **Completeness**: Access comprehensive class information, methods, and properties
 62 | - **Real-time**: Query live SFCC system objects and attributes from the actual instance
 63 | - **Debugging**: Access actual SFCC logs for troubleshooting and error analysis
 64 | - **Best Practices**: Get current SFCC development guidelines and security recommendations
 65 | 
 66 | ## 📋 Available Tool Categories
 67 | 
 68 | ### 🔍 SFCC Documentation Tools
 69 | Use these tools for any SFCC API or class-related questions:
 70 | 
 71 | - **`get_sfcc_class_info`** - Get detailed info about any SFCC class (dw.* namespace)
 72 | - **`search_sfcc_classes`** - Find SFCC classes by name or functionality
 73 | - **`search_sfcc_methods`** - Find methods across all classes by name
 74 | - **`list_sfcc_classes`** - Get complete list of available SFCC classes
 75 | - **`get_sfcc_class_documentation`** - Get raw documentation for any SFCC class
 76 | 
 77 | ### 📚 Best Practices & Guidelines
 78 | Use these for implementation guidance and best practices:
 79 | 
 80 | - **`get_available_best_practice_guides`** - See what guides are available
 81 | - **`get_best_practice_guide`** - Get complete guides for cartridges, hooks, controllers, etc.
 82 | - **`search_best_practices`** - Find specific guidance on topics like security, performance
 83 | - **`get_hook_reference`** - Get comprehensive OCAPI/SCAPI hook references
 84 | 
 85 | ### 🏗️ SFRA Documentation Tools
 86 | Use these for SFRA (Storefront Reference Architecture) related questions:
 87 | 
 88 | - **`get_available_sfra_documents`** - See what SFRA documents are available
 89 | - **`get_sfra_document`** - Get complete SFRA class/module documentation (includes all properties and methods)
 90 | - **`search_sfra_documentation`** - Search across all SFRA documentation
 91 | 
 92 | ### 🔧 System Object Definitions
 93 | Use these for understanding SFCC data models and custom attributes:
 94 | 
 95 | - **`get_system_object_definitions`** - Get all system objects (Product, Customer, Order, etc.)
 96 | - **`get_system_object_definition`** - Get details about a specific system object
 97 | - **`search_system_object_attribute_definitions`** - Search for specific attributes
 98 | - **`search_site_preferences`** - Search for site preferences in preference groups
 99 | - **`search_system_object_attribute_groups`** - Search for attribute groups (essential for finding site preference groups)
100 | - **`search_custom_object_attribute_definitions`** - Search for attributes in custom object types
101 | 
102 | ### � Code Version Management
103 | Use these for deployment and code version operations:
104 | 
105 | - **`get_code_versions`** - Get all code versions on the SFCC instance
106 | - **`activate_code_version`** - Activate a specific code version (useful for code-switch fixes)
107 | 
108 | ### �📊 Log Analysis Tools
109 | Use these for debugging and troubleshooting:
110 | 
111 | - **`get_latest_errors`** - Get recent error messages from SFCC logs
112 | - **`get_latest_warnings`** - Get recent warnings from SFCC logs
113 | - **`search_logs`** - Search logs for specific patterns or keywords
114 | - **`summarize_logs`** - Get overview of log activity and issues
115 | - **`list_log_files`** - List available log files with metadata
116 | - **`get_log_file_contents`** - Get contents of a specific log file (supports size limits and head/tail reading)
117 | 
118 | ## 🚀 When to Use These Tools
119 | 
120 | ### ✅ DO Use MCP Tools For:
121 | 
122 | 1. **API Documentation Questions**
123 |    ```
124 |    "What methods are available on dw.catalog.Product?"
125 |    → Use: get_sfcc_class_methods with className: "dw.catalog.Product"
126 |    ```
127 | 
128 | 2. **Finding the Right Class**
129 |    ```
130 |    "How do I work with customer data in SFCC?"
131 |    → Use: search_sfcc_classes with query: "customer"
132 |    ```
133 | 
134 | 3. **Implementation Best Practices**
135 |    ```
136 |    "How should I create a new cartridge?"
137 |    → Use: get_best_practice_guide with guideName: "cartridge_creation"
138 |    ```
139 | 
140 | 4. **Understanding System Objects**
141 |    ```
142 |    "What custom attributes are on the Product object?"
143 |    → Use: get_system_object_attribute_definitions with objectType: "Product"
144 |    ```
145 | 
146 | 5. **Debugging Issues**
147 |    ```
148 |    "Are there any recent errors in the logs?"
149 |    → Use: get_latest_errors
150 |    
151 |    "What log files are available for today?"
152 |    → Use: list_log_files
153 |    
154 |    "I need to see the full contents of a specific error log file"
155 |    → Use: get_log_file_contents with filename: "error-2023-01-01.log"
156 |    
157 |    "Show me just the first 1MB of a large log file"
158 |    → Use: get_log_file_contents with filename: "large.log", maxBytes: 1048576, tailOnly: false
159 |    
160 |    "Get the last 500KB of a log file to see recent entries"
161 |    → Use: get_log_file_contents with filename: "debug.log", maxBytes: 512000, tailOnly: true
162 |    ```
163 | 
164 | 6. **Code Version Management**
165 |    ```
166 |    "What code versions are available on the instance?"
167 |    → Use: get_code_versions
168 |    
169 |    "Need to do a code-switch fix for SCAPI endpoints"
170 |    → Use: activate_code_version with versionId: "target_version"
171 |    ```
172 | 
173 | 7. **Hook Development**
174 |    ```
175 |    "What SCAPI hooks are available?"
176 |    → Use: get_hook_reference with guideName: "scapi_hooks"
177 |    ```
178 | 
179 | ### ❌ DON'T Guess About:
180 | 
181 | - SFCC class names or method signatures
182 | - Custom attribute names or system object structures
183 | - Current best practices or security guidelines
184 | - Available hook endpoints or extension points
185 | - Recent system errors or log patterns
186 | 
187 | ## 🎨 Example Usage Patterns
188 | 
189 | ### Finding and Using SFCC Classes
190 | ```markdown
191 | 1. First search for relevant classes:
192 |    → search_sfcc_classes with query: "order"
193 | 
194 | 2. Get detailed information about the class:
195 |    → get_sfcc_class_info with className: "dw.order.Order"
196 | 
197 | 3. Explore specific methods or properties:
198 |    → get_sfcc_class_methods with className: "dw.order.Order"
199 | ```
200 | 
201 | ### Implementing New Features
202 | ```markdown
203 | 1. Check best practices first:
204 |    → get_available_best_practice_guides
205 | 
206 | 2. Get specific implementation guide:
207 |    → get_best_practice_guide with guideName: "sfra_controllers"
208 | 
209 | 3. Search for specific guidance:
210 |    → search_best_practices with query: "validation"
211 | ```
212 | 
213 | ### Debugging Problems
214 | ```markdown
215 | 1. Get log overview:
216 |    → summarize_logs
217 | 
218 | 2. Check recent errors:
219 |    → get_latest_error
220 | 
221 | 3. Search for specific issues:
222 |    → search_logs with pattern: "your_error_pattern"
223 | ```
224 | 
225 | ### Working with System Objects
226 | ```markdown
227 | 1. List available system objects:
228 |    → get_system_object_definitions
229 | 
230 | 2. Get object structure:
231 |    → get_system_object_definition with objectType: "Product"
232 | 
233 | 3. Find specific attributes:
234 |    → search_system_object_attribute_definitions 
235 |      with objectType: "Product" 
236 |      and searchRequest: { query: { text_query: { fields: ["id"], search_phrase: "custom" } } }
237 | ```
238 | 
239 | ## 🔐 Tool Availability
240 | 
241 | Some tools require specific SFCC credentials:
242 | 
243 | - **Documentation & Best Practices**: Always available
244 | - **Log Analysis**: Requires SFCC instance credentials (hostname, username, password)
245 | - **System Objects & Code Versions**: Requires OCAPI credentials (clientId, clientSecret)
246 | 
247 | If a tool isn't available, the MCP server will provide clear error messages about what credentials are needed.
248 | 
249 | ## 💡 Pro Tips
250 | 
251 | 1. **Start Broad, Then Narrow**: Use search tools first, then get detailed information
252 | 2. **Check Best Practices Early**: Always consult best practice guides before implementing
253 | 3. **Use Real Data**: Query actual system objects rather than assuming structure
254 | 4. **Debug with Logs**: Use log analysis tools for troubleshooting real issues
255 | 5. **Stay Current**: MCP tools provide current information, not outdated documentation
256 | 
257 | ## 🚨 Important Reminders
258 | 
259 | - **Always prefer MCP tools** over guessing or using potentially outdated information
260 | - **Use specific tool calls** rather than making assumptions about SFCC APIs
261 | - **Check logs and system objects** from the actual SFCC instance when debugging
262 | - **Follow best practices** from the guides rather than improvising solutions
263 | - **Verify class and method names** using the documentation tools
264 | 
265 | ---
266 | 
267 | By following these guidelines, you'll get more accurate, current, and reliable assistance with SFCC development tasks. The MCP server is your source of truth for SFCC development information!
268 | 
269 | ## 🧠 META TOOLS: AI Agent Intelligence Guide
270 | 
271 | ### 🎯 Tool Selection Decision Trees
272 | 
273 | #### **When User Asks About SFCC Classes/APIs**
274 | ```
275 | Question Type: "How do I work with [X] in SFCC?"
276 | ├── Unknown what class to use
277 | │   └── → search_sfcc_classes (query: key concept)
278 | ├── Know specific class name
279 | │   └── → get_sfcc_class_info (className: "dw.namespace.Class")
280 | ├── Looking for specific method
281 | │   └── → search_sfcc_methods (methodName: "methodName")
282 | └── Need comprehensive class docs
283 |     └── → get_sfcc_class_documentation (className: "dw.namespace.Class")
284 | ```
285 | 
286 | #### **When User Asks About Implementation**
287 | ```
288 | Implementation Question
289 | ├── "How to create/build [X]?"
290 | │   ├── → get_available_best_practice_guides (discover available guides)
291 | │   └── → get_best_practice_guide (guideName: specific guide)
292 | ├── "Best way to [X]?"
293 | │   └── → search_best_practices (query: key concept)
294 | ├── "What hooks are available for [X]?"
295 | │   └── → get_hook_reference (guideName: "ocapi_hooks" or "scapi_hooks")
296 | └── "SFRA related question?"
297 |     ├── → get_available_sfra_documents (discover what's available)
298 |     └── → get_sfra_document (documentName: specific module)
299 | ```
300 | 
301 | #### **When User Reports Problems/Errors**
302 | ```
303 | Problem/Error Scenario
304 | ├── "Something is broken/not working"
305 | │   ├── → summarize_logs (get system health overview)
306 | │   ├── → get_latest_error (check recent errors)
307 | │   └── → search_logs (pattern: error keywords)
308 | └── "Performance issues"
309 |     ├── → get_latest_warn (check warnings)
310 |     └── → search_best_practices (query: "performance")
311 | ```
312 | 
313 | #### **When User Asks About Data Models/Objects**
314 | ```
315 | Data Model Questions
316 | ├── "What fields/attributes are available on [Object]?"
317 | │   └── → search_system_object_attribute_definitions (objectType: "ObjectName")
318 | ├── "What objects are available?"
319 | │   └── → get_system_object_definitions
320 | ├── "How to configure site preferences?"
321 | │   ├── → search_system_object_attribute_groups (objectType: "SitePreferences")
322 | │   └── → search_site_preferences (groupId: found group)
323 | └── "Custom object attributes?"
324 |     └── → search_custom_object_attribute_definitions (objectType: "CustomObjectName")
325 | ```
326 | 
327 | ### 🎪 Common Usage Scenarios & Tool Chains
328 | 
329 | #### **Scenario 1: Creating a New Controller**
330 | ```markdown
331 | Sequential Tool Chain:
332 | 1. → get_best_practice_guide (guideName: "sfra_controllers")
333 | 2. → get_sfra_document (documentName: "server")
334 | 3. → get_sfra_document (documentName: "request") 
335 | 4. → get_sfra_document (documentName: "response")
336 | 5. → search_best_practices (query: "security") // for validation patterns
337 | 6. → search_best_practices (query: "performance") // for optimization
338 | ```
339 | 
340 | #### **Scenario 2: Implementing OCAPI Hook**
341 | ```markdown
342 | Sequential Tool Chain:
343 | 1. → get_best_practice_guide (guideName: "ocapi_hooks")
344 | 2. → get_hook_reference (guideName: "ocapi_hooks")
345 | 3. → search_sfcc_classes (query: relevant domain like "order", "customer")
346 | 4. → get_sfcc_class_info (className: discovered class)
347 | 5. → search_best_practices (query: "validation")
348 | ```
349 | 
350 | #### **Scenario 3: Debugging Cart Issues**
351 | ```markdown
352 | Parallel Information Gathering:
353 | 1. → search_logs (pattern: "cart", logLevel: "error")
354 | 2. → search_sfcc_classes (query: "basket")
355 | 3. → get_sfcc_class_info (className: "dw.order.Basket")
356 | 4. → search_system_object_attribute_definitions (objectType: "Product")
357 | 5. → get_latest_error (date: today)
358 | ```
359 | 
360 | #### **Scenario 4: Building Custom SCAPI Endpoint**
361 | ```markdown
362 | Sequential Tool Chain:
363 | 1. → get_best_practice_guide (guideName: "scapi_custom_endpoint")
364 | 2. → get_hook_reference (guideName: "scapi_hooks")
365 | 3. → search_best_practices (query: "security")
366 | 4. → search_sfcc_classes (query: relevant business domain)
367 | 5. → get_sfcc_class_info (className: discovered classes)
368 | ```
369 | 
370 | #### **Scenario 5: Working with Site Preferences**
371 | ```markdown
372 | Sequential Discovery Chain:
373 | 1. → search_system_object_attribute_groups (objectType: "SitePreferences")
374 | 2. → search_site_preferences (groupId: discovered group, instanceType: "sandbox")
375 | 3. → search_best_practices (query: "configuration")
376 | 4. → get_sfcc_class_info (className: "dw.system.Site")
377 | ```
378 | 
379 | ### 🔍 Advanced Tool Usage Patterns
380 | 
381 | #### **Complex Query Building for System Objects**
382 | ```javascript
383 | // When searching for specific attribute types
384 | searchRequest: {
385 |   query: {
386 |     bool_query: {
387 |       must: [
388 |         { term_query: { fields: ["value_type"], operator: "is", values: ["string"] } },
389 |         { text_query: { fields: ["id"], search_phrase: "custom" } }
390 |       ]
391 |     }
392 |   },
393 |   sorts: [{ field: "id", sort_order: "asc" }],
394 |   count: 50
395 | }
396 | ```
397 | 
398 | #### **Effective Log Searching Strategies**
399 | ```markdown
400 | For Transaction Tracing:
401 | 1. → search_logs (pattern: "transaction-id-123", logLevel: "info")
402 | 
403 | For Performance Investigation:
404 | 1. → search_logs (pattern: "timeout", logLevel: "warn")
405 | 2. → search_logs (pattern: "slow query", logLevel: "debug")
406 | ```
407 | 
408 | ### 🎨 Tool Response Optimization
409 | 
410 | #### **Information Layering Strategy**
411 | ```markdown
412 | 1. **Start with Overview Tools**
413 |    - get_available_best_practice_guides
414 |    - list_sfcc_classes
415 |    - get_system_object_definitions
416 | 
417 | 2. **Narrow to Specific Tools**
418 |    - get_best_practice_guide
419 |    - get_sfcc_class_info
420 |    - search_system_object_attribute_definitions
421 | 
422 | 3. **Deep Dive with Detail Tools**
423 |    - get_sfcc_class_documentation
424 |    - search_best_practices
425 |    - search_logs
426 | ```
427 | 
428 | #### **Parallel vs Sequential Tool Usage**
429 | ```markdown
430 | Use in PARALLEL when:
431 | - Gathering different types of information
432 | - Checking multiple log levels simultaneously
433 | - Exploring related but independent concepts
434 | 
435 | Use SEQUENTIALLY when:
436 | - Results from one tool inform the next query
437 | - Building upon discovered information
438 | - Following a logical investigation path
439 | ```
440 | 
441 | ### 🎭 Response Crafting Guidelines
442 | 
443 | #### **When Using Documentation Tools**
444 | ```markdown
445 | Always Include:
446 | - Practical code examples using the discovered information
447 | - Security considerations from best practices
448 | - Performance implications
449 | - Error handling patterns
450 | - Related classes/methods that might be relevant
451 | ```
452 | 
453 | #### **When Using System Object Tools**
454 | ```markdown
455 | Always Include:
456 | - Data type information for attributes
457 | - Validation rules and constraints
458 | - Custom vs system attributes distinction
459 | - Related object relationships
460 | ```
461 | 
462 | #### **When Using Log Analysis Tools**
463 | ```markdown
464 | Always Include:
465 | - Timestamp context for errors
466 | - Potential root causes
467 | - Recommended investigation steps
468 | - Related system components to check
469 | - Preventive measures
470 | ```
471 | 
472 | ### 🎯 Success Metrics for Tool Usage
473 | 
474 | #### **Effective Tool Usage Indicators**
475 | ```markdown
476 | ✅ GOOD: User gets working code example with security considerations
477 | ✅ GOOD: User understands the complete implementation pattern
478 | ✅ GOOD: User can troubleshoot their own similar issues
479 | 
480 | ❌ POOR: User still confused about basic concepts
481 | ❌ POOR: Providing code without explaining security/performance implications
482 | ❌ POOR: Missing critical steps in implementation guidance
483 | ```
484 | 
485 | #### **Tool Chain Effectiveness**
486 | ```markdown
487 | Measure success by:
488 | - Completeness of information provided
489 | - Practical applicability of guidance
490 | - Security and performance awareness
491 | - Error prevention rather than just error fixing
492 | - User's ability to extend the solution
493 | ```
494 | 
495 | ### 🎪 Meta-Learning: Tool Evolution Patterns
496 | 
497 | #### **Tool Usage Analytics**
498 | ```markdown
499 | Track which combinations work well:
500 | - Documentation → Best Practices → Implementation
501 | - Error Investigation → System Analysis → Solution
502 | - Planning → Research → Validation → Implementation
503 | 
504 | Common failure patterns to avoid:
505 | - Jumping to implementation without research
506 | - Ignoring security/performance best practices
507 | - Not validating against actual system objects
508 | - Skipping error handling considerations
509 | ```
510 | 
511 | #### **Continuous Improvement Indicators**
512 | ```markdown
513 | Signs to update tool usage patterns:
514 | - Frequent user confusion with current guidance
515 | - New SFCC features not covered by existing tools
516 | - Performance issues with certain tool combinations
517 | - Security concerns identified in generated code
518 | ```
519 | 
520 | ---
521 | 
522 | ## 🎯 SFCC Override Path Requirements
523 | 
524 | **MANDATORY**: Before generating ANY SFCC code involving ISML templates or models, you MUST use these MCP tools to ensure correct override paths and patterns:
525 | 
526 | ### **Required MCP Tool Chain for SFCC Override Code**
527 | 
528 | #### **For ISML Template Generation**:
529 | ```
530 | MANDATORY sequence before creating any ISML template:
531 | 1. → get_best_practice_guide(guideName: "isml_templates")
532 | 2. → Analyze the "Template Directory Structure" section
533 | 3. → Confirm exact override path from best practices
534 | 4. → Generate code only after path verification
535 | ```
536 | 
537 | #### **For Model Generation**:
538 | ```
539 | MANDATORY sequence before creating any SFRA model:
540 | 1. → get_best_practice_guide(guideName: "sfra_models") 
541 | 2. → Analyze the "Model Customization Strategies" section
542 | 3. → Confirm proper superModule usage patterns
543 | 4. → Generate code only after pattern verification
544 | ```
545 | 
546 | #### **For Controller Generation**:
547 | ```
548 | MANDATORY sequence before creating any controller:
549 | 1. → get_best_practice_guide(guideName: "sfra_controllers")
550 | 2. → Analyze controller extension patterns
551 | 3. → Confirm proper server.extend() usage
552 | 4. → Generate code only after pattern verification
553 | ```
554 | 
555 | ### **Override Path Verification Process**
556 | 
557 | **NEVER generate SFCC override code without completing this checklist**:
558 | 
559 | 1. ✅ **Used MCP Tool**: Called appropriate `get_best_practice_guide` 
560 | 2. ✅ **Path Confirmed**: Verified exact directory structure from guide
561 | 3. ✅ **Pattern Validated**: Confirmed proper extension patterns (superModule, server.extend)
562 | 4. ✅ **Security Checked**: Reviewed security guidelines from best practices
563 | 5. ✅ **Structure Match**: Ensured override path exactly matches base cartridge structure
564 | 
565 | ### **Common Override Mistakes - Prevent with MCP Tools**
566 | 
567 | ❌ **WRONG - Generated without MCP guidance**:
568 | ```javascript
569 | // Missing superModule, wrong path, no security validation
570 | function Account() {
571 |     // Custom logic only - will break SFRA
572 | }
573 | ```
574 | 
575 | ✅ **CORRECT - Generated after MCP tool consultation**:
576 | ```javascript
577 | // Proper pattern from get_best_practice_guide("sfra_models")
578 | var base = module.superModule;
579 | function Account() {
580 |     base.call(this, ...arguments);
581 |     // Add custom logic following best practices
582 | }
583 | ```
584 | 
585 | ### **Emergency Override Path Reference**
586 | 
587 | **If MCP tools are unavailable**, use these critical rules:
588 | - **ISML**: `cartridge/templates/default/[exact_base_path]`
589 | - **Models**: `cartridge/models/[exact_base_path]` + `module.superModule`
590 | - **Controllers**: `cartridge/controllers/[exact_base_path]` + `server.extend(module.superModule)`
591 | 
592 | **But ALWAYS prefer using the MCP tools for complete guidance!**
593 | 
594 | ### Essential Override Verification
595 | 
596 | **Before providing any SFCC code that involves templates or models**:
597 | 
598 | 1. **Check Path Structure**: Verify the override path matches the base cartridge exactly
599 | 2. **Consult Best Practices**: Reference ISML Templates and SFRA Models best practice guides
600 | 3. **Use MCP Tools**: Leverage `get_best_practice_guide` for "isml_templates" and "sfra_models"
601 | 4. **Validate Override Pattern**: Ensure proper use of `module.superModule` for models and `server.extend()` for controllers
602 | 5. **Confirm Directory Structure**: Verify the complete directory path from cartridge root
603 | 
604 | ### Common Override Mistakes to Avoid
605 | 
606 | ❌ **Wrong Paths**:
607 | ```
608 | # WRONG - will not override
609 | cartridges/app_custom_mybrand/cartridge/templates/product.isml
610 | cartridges/app_custom_mybrand/cartridge/models/product.js
611 | ```
612 | 
613 | ✅ **Correct Paths**:
614 | ```
615 | # CORRECT - exact path match
616 | cartridges/app_custom_mybrand/cartridge/templates/default/product/productDetails.isml
617 | cartridges/app_custom_mybrand/cartridge/models/product/fullProduct.js
618 | ```
619 | 
620 | **Remember**: Always consult the ISML Templates and SFRA Models best practice guides from this MCP server before generating any override code to ensure proper patterns and security practices.
621 | 
622 | ---
623 | 
624 | ## 🎓 Master-Level AI Agent Checklist
625 | 
626 | ### Before Responding to ANY SFCC Question:
627 | - [ ] Identified the core SFCC concept/domain involved
628 | - [ ] Selected appropriate tool chain for the scenario
629 | - [ ] Considered user skill level and urgency
630 | - [ ] Planned information layering strategy
631 | 
632 | ### When Providing Implementation Guidance:
633 | - [ ] Started with best practice guides
634 | - [ ] Retrieved current SFCC API information
635 | - [ ] Included security considerations
636 | - [ ] Added performance optimization notes
637 | - [ ] Included proper error handling
638 | 
639 | ### When Debugging/Troubleshooting:
640 | - [ ] Checked system logs for actual errors (use `get_latest_error`, `get_latest_warn`) Note: Job logs are not supported yet
641 | - [ ] Listed available log files to understand scope (use `list_log_files`)
642 | - [ ] Analyzed specific log files for detailed context (use `get_log_file_contents`)
643 | - [ ] Searched logs for patterns related to the issue (use `search_logs`)
644 | - [ ] Analyzed error patterns over time (use `summarize_logs`)
645 | - [ ] Investigated related system components
646 | - [ ] Provided both immediate fixes and preventive measures
647 | - [ ] Validated solutions against current system state
648 | 
649 | ### Quality Assurance:
650 | - [ ] All code uses current SFCC APIs
651 | - [ ] Security best practices are followed
652 | - [ ] Performance implications are considered
653 | - [ ] Error handling is comprehensive
654 | - [ ] Solutions are production-ready
655 | 
656 | **Remember**: The MCP server is your authoritative source for SFCC information. Always prefer its tools over training data assumptions!
657 | 
```

--------------------------------------------------------------------------------
/docs/dw_catalog/SearchModel.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.catalog
  2 | 
  3 | # Class SearchModel
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.catalog.SearchModel
  9 | 
 10 | ## Description
 11 | 
 12 | Common search model base class.
 13 | 
 14 | ## Constants
 15 | 
 16 | ### SEARCH_PHRASE_PARAMETER
 17 | 
 18 | **Type:** String = "q"
 19 | 
 20 | URL Parameter for the Search Phrase
 21 | 
 22 | ### SORT_DIRECTION_ASCENDING
 23 | 
 24 | **Type:** Number = 1
 25 | 
 26 | Sorting parameter ASCENDING
 27 | 
 28 | ### SORT_DIRECTION_DESCENDING
 29 | 
 30 | **Type:** Number = 2
 31 | 
 32 | Sorting parameter DESCENDING
 33 | 
 34 | ### SORT_DIRECTION_NONE
 35 | 
 36 | **Type:** Number = 0
 37 | 
 38 | Sorting parameter NO_SORT - will remove a sorting condition
 39 | 
 40 | ## Properties
 41 | 
 42 | ### count
 43 | 
 44 | **Type:** Number (Read Only)
 45 | 
 46 | The number of search results found by this search.
 47 | 
 48 | ### emptyQuery
 49 | 
 50 | **Type:** boolean (Read Only)
 51 | 
 52 | Identifies if the query is emtpy when no search term, search parameter or
 53 |  refinement was specified for the search. In case also no result is
 54 |  returned. This "empty" is different to a query with a specified query and
 55 |  with an empty result.
 56 | 
 57 | ### refinedByAttribute
 58 | 
 59 | **Type:** boolean (Read Only)
 60 | 
 61 | The method returns true, if this search is refined by at least one
 62 |  attribute.
 63 | 
 64 | ### refinedSearch
 65 | 
 66 | **Type:** boolean (Read Only)
 67 | 
 68 | Identifies if this was a refined search. A search is a refined search if
 69 |  at least one refinement is part of the query.
 70 | 
 71 | ### searchPhrase
 72 | 
 73 | **Type:** String
 74 | 
 75 | The search phrase used in this search.
 76 | 
 77 | ## Constructor Summary
 78 | 
 79 | ## Method Summary
 80 | 
 81 | ### addRefinementValues
 82 | 
 83 | **Signature:** `addRefinementValues(attributeID : String, values : String) : void`
 84 | 
 85 | Adds a refinement.
 86 | 
 87 | ### canRelax
 88 | 
 89 | **Signature:** `canRelax() : boolean`
 90 | 
 91 | Identifies if the search can be relaxed without creating a search for all searchable items.
 92 | 
 93 | ### getCount
 94 | 
 95 | **Signature:** `getCount() : Number`
 96 | 
 97 | Returns the number of search results found by this search.
 98 | 
 99 | ### getRefinementMaxValue
100 | 
101 | **Signature:** `getRefinementMaxValue(attributeID : String) : String`
102 | 
103 | Returns the maximum refinement value selected in the query for the specific attribute, or null if there is no maximum refinement value or no refinement for that attribute.
104 | 
105 | ### getRefinementMinValue
106 | 
107 | **Signature:** `getRefinementMinValue(attributeID : String) : String`
108 | 
109 | Returns the minimum refinement value selected in the query for the specific attribute, or null if there is no minimum refinement value or no refinement for that attribute.
110 | 
111 | ### getRefinementValue
112 | 
113 | **Signature:** `getRefinementValue(attributeID : String) : String`
114 | 
115 | Returns the refinement value selected in the query for the specific attribute, or null if there is no refinement for that attribute.
116 | 
117 | ### getRefinementValues
118 | 
119 | **Signature:** `getRefinementValues(attributeID : String) : Collection`
120 | 
121 | Returns the list of selected refinement values for the given attribute as used in the search.
122 | 
123 | ### getSearchPhrase
124 | 
125 | **Signature:** `getSearchPhrase() : String`
126 | 
127 | Returns the search phrase used in this search.
128 | 
129 | ### getSearchRedirect
130 | 
131 | **Signature:** `static getSearchRedirect(searchPhrase : String) : URLRedirect`
132 | 
133 | Returns an URLRedirect object for a search phrase.
134 | 
135 | ### getSortingCondition
136 | 
137 | **Signature:** `getSortingCondition(attributeID : String) : Number`
138 | 
139 | Returns the sorting condition for a given attribute name.
140 | 
141 | ### isEmptyQuery
142 | 
143 | **Signature:** `isEmptyQuery() : boolean`
144 | 
145 | Identifies if the query is emtpy when no search term, search parameter or refinement was specified for the search.
146 | 
147 | ### isRefinedByAttribute
148 | 
149 | **Signature:** `isRefinedByAttribute(attributeID : String) : boolean`
150 | 
151 | Identifies if this search has been refined on the given attribute.
152 | 
153 | ### isRefinedByAttribute
154 | 
155 | **Signature:** `isRefinedByAttribute() : boolean`
156 | 
157 | The method returns true, if this search is refined by at least one attribute.
158 | 
159 | ### isRefinedByAttributeValue
160 | 
161 | **Signature:** `isRefinedByAttributeValue(attributeID : String, value : String) : boolean`
162 | 
163 | Identifies if this search has been refined on the given attribute and value.
164 | 
165 | ### isRefinedSearch
166 | 
167 | **Signature:** `isRefinedSearch() : boolean`
168 | 
169 | Identifies if this was a refined search.
170 | 
171 | ### isRefinementByValueRange
172 | 
173 | **Signature:** `isRefinementByValueRange(attributeID : String) : boolean`
174 | 
175 | Identifies if this search has been refined on the given attribute.
176 | 
177 | ### isRefinementByValueRange
178 | 
179 | **Signature:** `isRefinementByValueRange(attributeID : String, minValue : String, maxValue : String) : boolean`
180 | 
181 | Identifies if this search has been refined on the given attribute and range values.
182 | 
183 | ### removeRefinementValues
184 | 
185 | **Signature:** `removeRefinementValues(attributeID : String, values : String) : void`
186 | 
187 | Removes a refinement.
188 | 
189 | ### search
190 | 
191 | **Signature:** `search() : SearchStatus`
192 | 
193 | Execute the search.
194 | 
195 | ### setRefinementValueRange
196 | 
197 | **Signature:** `setRefinementValueRange(attributeID : String, minValue : String, maxValue : String) : void`
198 | 
199 | Sets a refinement value range for an attribute.
200 | 
201 | ### setRefinementValues
202 | 
203 | **Signature:** `setRefinementValues(attributeID : String, values : String) : void`
204 | 
205 | Sets refinement values for an attribute.
206 | 
207 | ### setSearchPhrase
208 | 
209 | **Signature:** `setSearchPhrase(phrase : String) : void`
210 | 
211 | Sets the search phrase used in this search.
212 | 
213 | ### setSortingCondition
214 | 
215 | **Signature:** `setSortingCondition(attributeID : String, direction : Number) : void`
216 | 
217 | Sets or removes a sorting condition for the specified attribute.
218 | 
219 | ### url
220 | 
221 | **Signature:** `url(action : String) : URL`
222 | 
223 | Constructs an URL that you can use to re-execute the exact same query.
224 | 
225 | ### url
226 | 
227 | **Signature:** `url(url : URL) : URL`
228 | 
229 | Constructs an URL that you can use to re-execute the exact same query.
230 | 
231 | ### urlDefaultSort
232 | 
233 | **Signature:** `urlDefaultSort(url : String) : URL`
234 | 
235 | Constructs an URL that you can use to re-execute the query with a default sorting.
236 | 
237 | ### urlDefaultSort
238 | 
239 | **Signature:** `urlDefaultSort(url : URL) : URL`
240 | 
241 | Constructs an URL that you can use to re-execute the query with a default sorting.
242 | 
243 | ### urlRefineAttribute
244 | 
245 | **Signature:** `urlRefineAttribute(action : String, attributeID : String, value : String) : URL`
246 | 
247 | Constructs an URL that you can use to re-execute the query with an additional refinement.
248 | 
249 | ### urlRefineAttribute
250 | 
251 | **Signature:** `urlRefineAttribute(url : URL, attributeID : String, value : String) : URL`
252 | 
253 | Constructs an URL that you can use to re-execute the query with an additional refinement.
254 | 
255 | ### urlRefineAttributeValue
256 | 
257 | **Signature:** `urlRefineAttributeValue(action : String, attributeID : String, value : String) : URL`
258 | 
259 | Constructs an URL that you can use to re-execute the query with an additional refinement value for a given refinement attribute.
260 | 
261 | ### urlRefineAttributeValue
262 | 
263 | **Signature:** `urlRefineAttributeValue(url : URL, attributeID : String, value : String) : URL`
264 | 
265 | Constructs an URL that you can use to re-execute the query with an additional refinement value for a given refinement attribute.
266 | 
267 | ### urlRefineAttributeValueRange
268 | 
269 | **Signature:** `urlRefineAttributeValueRange(action : String, attributeID : String, minValue : String, maxValue : String) : URL`
270 | 
271 | Constructs an URL that you can use to re-execute the query with an additional refinement value range for a given refinement attribute.
272 | 
273 | ### urlRelaxAttribute
274 | 
275 | **Signature:** `urlRelaxAttribute(action : String, attributeID : String) : URL`
276 | 
277 | Constructs an URL that you can use to re-execute the query without the specified refinement.
278 | 
279 | ### urlRelaxAttribute
280 | 
281 | **Signature:** `urlRelaxAttribute(url : URL, attributeID : String) : URL`
282 | 
283 | Constructs an URL that you can use to re-execute the query without the specified refinement.
284 | 
285 | ### urlRelaxAttributeValue
286 | 
287 | **Signature:** `urlRelaxAttributeValue(action : String, attributeID : String, value : String) : URL`
288 | 
289 | Constructs an URL that you can use to re-execute the query without the specified refinement.
290 | 
291 | ### urlRelaxAttributeValue
292 | 
293 | **Signature:** `urlRelaxAttributeValue(url : URL, attributeID : String, value : String) : URL`
294 | 
295 | Constructs an URL that you can use to re-execute the query without the specified refinement value.
296 | 
297 | ### urlSort
298 | 
299 | **Signature:** `urlSort(action : String, sortBy : String, sortDir : Number) : URL`
300 | 
301 | Constructs an URL that you can use to re-execute the query with a specific sorting criteria.
302 | 
303 | ### urlSort
304 | 
305 | **Signature:** `urlSort(url : URL, sortBy : String, sortDir : Number) : URL`
306 | 
307 | Constructs an URL that you can use to re-execute the query with a specific sorting criteria.
308 | 
309 | ## Method Detail
310 | 
311 | ## Method Details
312 | 
313 | ### addRefinementValues
314 | 
315 | **Signature:** `addRefinementValues(attributeID : String, values : String) : void`
316 | 
317 | **Description:** Adds a refinement. The method can be called to add an additional query parameter specified as name-value pair. The values string may encode multiple values delimited by the pipe symbol ('|').
318 | 
319 | **Parameters:**
320 | 
321 | - `attributeID`: The ID of the refinement attribute.
322 | - `values`: the refinement value to set
323 | 
324 | ---
325 | 
326 | ### canRelax
327 | 
328 | **Signature:** `canRelax() : boolean`
329 | 
330 | **Description:** Identifies if the search can be relaxed without creating a search for all searchable items.
331 | 
332 | **Returns:**
333 | 
334 | true if the search can be relaxed without creating a search for all searchable items, false otherwise.
335 | 
336 | ---
337 | 
338 | ### getCount
339 | 
340 | **Signature:** `getCount() : Number`
341 | 
342 | **Description:** Returns the number of search results found by this search.
343 | 
344 | **Returns:**
345 | 
346 | the number of search results found by this search.
347 | 
348 | ---
349 | 
350 | ### getRefinementMaxValue
351 | 
352 | **Signature:** `getRefinementMaxValue(attributeID : String) : String`
353 | 
354 | **Description:** Returns the maximum refinement value selected in the query for the specific attribute, or null if there is no maximum refinement value or no refinement for that attribute.
355 | 
356 | **Parameters:**
357 | 
358 | - `attributeID`: the attribute whose refinement value is returned.
359 | 
360 | **Returns:**
361 | 
362 | the maximum refinement value selected in the query for the specific attribute.
363 | 
364 | ---
365 | 
366 | ### getRefinementMinValue
367 | 
368 | **Signature:** `getRefinementMinValue(attributeID : String) : String`
369 | 
370 | **Description:** Returns the minimum refinement value selected in the query for the specific attribute, or null if there is no minimum refinement value or no refinement for that attribute.
371 | 
372 | **Parameters:**
373 | 
374 | - `attributeID`: the attribute whose refinement value is returned.
375 | 
376 | **Returns:**
377 | 
378 | the minimum refinement value selected in the query for the specific attribute.
379 | 
380 | ---
381 | 
382 | ### getRefinementValue
383 | 
384 | **Signature:** `getRefinementValue(attributeID : String) : String`
385 | 
386 | **Description:** Returns the refinement value selected in the query for the specific attribute, or null if there is no refinement for that attribute.
387 | 
388 | **Deprecated:**
389 | 
390 | Use getRefinementValues(String) to get the collection of refinement values.
391 | 
392 | **Parameters:**
393 | 
394 | - `attributeID`: the attribute whose refinement value is returned.
395 | 
396 | **Returns:**
397 | 
398 | the refinement value selected in the query for the specific attribute.
399 | 
400 | ---
401 | 
402 | ### getRefinementValues
403 | 
404 | **Signature:** `getRefinementValues(attributeID : String) : Collection`
405 | 
406 | **Description:** Returns the list of selected refinement values for the given attribute as used in the search.
407 | 
408 | **Parameters:**
409 | 
410 | - `attributeID`: The name of the refinement attribute.
411 | 
412 | **Returns:**
413 | 
414 | A list of values currently selected for the refinement attribute.
415 | 
416 | ---
417 | 
418 | ### getSearchPhrase
419 | 
420 | **Signature:** `getSearchPhrase() : String`
421 | 
422 | **Description:** Returns the search phrase used in this search.
423 | 
424 | **Returns:**
425 | 
426 | the search phrase used in this search.
427 | 
428 | ---
429 | 
430 | ### getSearchRedirect
431 | 
432 | **Signature:** `static getSearchRedirect(searchPhrase : String) : URLRedirect`
433 | 
434 | **Description:** Returns an URLRedirect object for a search phrase.
435 | 
436 | **Parameters:**
437 | 
438 | - `searchPhrase`: a search phrase to lookup a URLRedirect for
439 | 
440 | **Returns:**
441 | 
442 | URLRedirect containing the location and status code, null in case no redirect was found for the search phrase.
443 | 
444 | ---
445 | 
446 | ### getSortingCondition
447 | 
448 | **Signature:** `getSortingCondition(attributeID : String) : Number`
449 | 
450 | **Description:** Returns the sorting condition for a given attribute name. A value of 0 indicates that no sorting condition is set.
451 | 
452 | **Parameters:**
453 | 
454 | - `attributeID`: the attribute name
455 | 
456 | **Returns:**
457 | 
458 | zero if no sorting order set, or the sorting order
459 | 
460 | ---
461 | 
462 | ### isEmptyQuery
463 | 
464 | **Signature:** `isEmptyQuery() : boolean`
465 | 
466 | **Description:** Identifies if the query is emtpy when no search term, search parameter or refinement was specified for the search. In case also no result is returned. This "empty" is different to a query with a specified query and with an empty result.
467 | 
468 | **Returns:**
469 | 
470 | true if the query is emtpy when no search term, search parameter or refinement was specified for the search.
471 | 
472 | ---
473 | 
474 | ### isRefinedByAttribute
475 | 
476 | **Signature:** `isRefinedByAttribute(attributeID : String) : boolean`
477 | 
478 | **Description:** Identifies if this search has been refined on the given attribute.
479 | 
480 | **Parameters:**
481 | 
482 | - `attributeID`: The ID of the refinement attribute.
483 | 
484 | **Returns:**
485 | 
486 | True if the search is refined on the attribute, false otherwise.
487 | 
488 | ---
489 | 
490 | ### isRefinedByAttribute
491 | 
492 | **Signature:** `isRefinedByAttribute() : boolean`
493 | 
494 | **Description:** The method returns true, if this search is refined by at least one attribute.
495 | 
496 | **Returns:**
497 | 
498 | true, if the search is refined by at least one attribute, false otherwise.
499 | 
500 | ---
501 | 
502 | ### isRefinedByAttributeValue
503 | 
504 | **Signature:** `isRefinedByAttributeValue(attributeID : String, value : String) : boolean`
505 | 
506 | **Description:** Identifies if this search has been refined on the given attribute and value.
507 | 
508 | **Parameters:**
509 | 
510 | - `attributeID`: The ID of the refinement attribute.
511 | - `value`: The value to be checked for inclusion in the refinement.
512 | 
513 | **Returns:**
514 | 
515 | True if the search is refined on the attribute and value, false otherwise.
516 | 
517 | ---
518 | 
519 | ### isRefinedSearch
520 | 
521 | **Signature:** `isRefinedSearch() : boolean`
522 | 
523 | **Description:** Identifies if this was a refined search. A search is a refined search if at least one refinement is part of the query.
524 | 
525 | **Returns:**
526 | 
527 | true if this is a refined search, false otherwise.
528 | 
529 | ---
530 | 
531 | ### isRefinementByValueRange
532 | 
533 | **Signature:** `isRefinementByValueRange(attributeID : String) : boolean`
534 | 
535 | **Description:** Identifies if this search has been refined on the given attribute.
536 | 
537 | **Parameters:**
538 | 
539 | - `attributeID`: The ID of the refinement attribute.
540 | 
541 | **Returns:**
542 | 
543 | True if the search is refined on the attribute, false otherwise.
544 | 
545 | ---
546 | 
547 | ### isRefinementByValueRange
548 | 
549 | **Signature:** `isRefinementByValueRange(attributeID : String, minValue : String, maxValue : String) : boolean`
550 | 
551 | **Description:** Identifies if this search has been refined on the given attribute and range values.
552 | 
553 | **Parameters:**
554 | 
555 | - `attributeID`: The ID of the refinement attribute.
556 | - `minValue`: The minimum value to be checked for inclusion in the refinement.
557 | - `maxValue`: The maximum value to be checked for inclusion in the refinement.
558 | 
559 | **Returns:**
560 | 
561 | True if the search is refined on the attribute and range values, false otherwise.
562 | 
563 | ---
564 | 
565 | ### removeRefinementValues
566 | 
567 | **Signature:** `removeRefinementValues(attributeID : String, values : String) : void`
568 | 
569 | **Description:** Removes a refinement. The method can be called to remove previously added refinement values. The values string may encode multiple values delimited by the pipe symbol ('|').
570 | 
571 | **Parameters:**
572 | 
573 | - `attributeID`: The ID of the refinement attribute.
574 | - `values`: the refinement value to remove or null to remove all values
575 | 
576 | ---
577 | 
578 | ### search
579 | 
580 | **Signature:** `search() : SearchStatus`
581 | 
582 | **Description:** Execute the search.
583 | 
584 | **Returns:**
585 | 
586 | the searchStatus object with search status code and description of search result.
587 | 
588 | ---
589 | 
590 | ### setRefinementValueRange
591 | 
592 | **Signature:** `setRefinementValueRange(attributeID : String, minValue : String, maxValue : String) : void`
593 | 
594 | **Description:** Sets a refinement value range for an attribute. The method can be called to set an additional range query parameter specified as name-range-value pair. The values string can contain only a range boundary. Existing refinement values for the attribute will be removed.
595 | 
596 | **Parameters:**
597 | 
598 | - `attributeID`: The ID of the refinement attribute.
599 | - `minValue`: the minimum refinement boundary value to set or null to remove the minimum boundary
600 | - `maxValue`: the maximum refinement boundary value to set or null to remove the maximum boundary
601 | 
602 | ---
603 | 
604 | ### setRefinementValues
605 | 
606 | **Signature:** `setRefinementValues(attributeID : String, values : String) : void`
607 | 
608 | **Description:** Sets refinement values for an attribute. The method can be called to set an additional query parameter specified as name-value pair. The value string may encode multiple values delimited by the pipe symbol ('|'). Existing refinement values for the attribute will be removed.
609 | 
610 | **Parameters:**
611 | 
612 | - `attributeID`: The ID of the refinement attribute.
613 | - `values`: the refinement values to set (delimited by '|') or null to remove all values
614 | 
615 | ---
616 | 
617 | ### setSearchPhrase
618 | 
619 | **Signature:** `setSearchPhrase(phrase : String) : void`
620 | 
621 | **Description:** Sets the search phrase used in this search. The search query parser uses the following operators: PHRASE operator (""), e.g. "cream cheese", "John Lennon" NOT operator (-), e.g. -cargo (will not return results containing "cargo") WILDCARD operator (*), e.g. sho* (will return results containing "shoulder", "shoes" and "shoot")
622 | 
623 | **Parameters:**
624 | 
625 | - `phrase`: the search phrase used in this search.
626 | 
627 | ---
628 | 
629 | ### setSortingCondition
630 | 
631 | **Signature:** `setSortingCondition(attributeID : String, direction : Number) : void`
632 | 
633 | **Description:** Sets or removes a sorting condition for the specified attribute. Specify either SORT_DIRECTION_ASCENDING or SORT_DIRECTION_DESCENDING to set a sorting condition. Specify SORT_DIRECTION_NONE to remove a sorting condition from the attribute.
634 | 
635 | **Parameters:**
636 | 
637 | - `attributeID`: the attribute ID
638 | - `direction`: SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING or SORT_DIRECTION_NONE
639 | 
640 | ---
641 | 
642 | ### url
643 | 
644 | **Signature:** `url(action : String) : URL`
645 | 
646 | **Description:** Constructs an URL that you can use to re-execute the exact same query. The provided parameter must be an action, e.g. 'Search-Show'.
647 | 
648 | **Parameters:**
649 | 
650 | - `action`: the pipeline action.
651 | 
652 | **Returns:**
653 | 
654 | an URL that can be used to re-execute the exact same query.
655 | 
656 | ---
657 | 
658 | ### url
659 | 
660 | **Signature:** `url(url : URL) : URL`
661 | 
662 | **Description:** Constructs an URL that you can use to re-execute the exact same query. The search specific parameter are appended to the provided URL. The URL is typically generated with one of the URLUtils methods.
663 | 
664 | **Parameters:**
665 | 
666 | - `url`: the url to use.
667 | 
668 | **Returns:**
669 | 
670 | a new url URL that can be used to re-execute the exact same query.
671 | 
672 | ---
673 | 
674 | ### urlDefaultSort
675 | 
676 | **Signature:** `urlDefaultSort(url : String) : URL`
677 | 
678 | **Description:** Constructs an URL that you can use to re-execute the query with a default sorting. The provided parameter must be an action, e.g. 'Search-Show'.
679 | 
680 | **Parameters:**
681 | 
682 | - `url`: url or pipeline name
683 | 
684 | **Returns:**
685 | 
686 | the new URL.
687 | 
688 | ---
689 | 
690 | ### urlDefaultSort
691 | 
692 | **Signature:** `urlDefaultSort(url : URL) : URL`
693 | 
694 | **Description:** Constructs an URL that you can use to re-execute the query with a default sorting. The search specific parameters are appended to the provided URL. The URL is typically generated with one of the URLUtils methods.
695 | 
696 | **Parameters:**
697 | 
698 | - `url`: url or pipeline name
699 | 
700 | **Returns:**
701 | 
702 | the new URL.
703 | 
704 | ---
705 | 
706 | ### urlRefineAttribute
707 | 
708 | **Signature:** `urlRefineAttribute(action : String, attributeID : String, value : String) : URL`
709 | 
710 | **Description:** Constructs an URL that you can use to re-execute the query with an additional refinement.
711 | 
712 | **Parameters:**
713 | 
714 | - `action`: the pipeline action.
715 | - `attributeID`: the ID of the refinement attribute.
716 | - `value`: the value for the refinement attribute.
717 | 
718 | **Returns:**
719 | 
720 | the new URL.
721 | 
722 | ---
723 | 
724 | ### urlRefineAttribute
725 | 
726 | **Signature:** `urlRefineAttribute(url : URL, attributeID : String, value : String) : URL`
727 | 
728 | **Description:** Constructs an URL that you can use to re-execute the query with an additional refinement. The search specific parameters are appended to the provided URL. The URL is typically generated with one of the URLUtils methods.
729 | 
730 | **Parameters:**
731 | 
732 | - `url`: url
733 | - `attributeID`: the ID of the refinement attribute
734 | - `value`: value for the refinement attribute
735 | 
736 | **Returns:**
737 | 
738 | the new URL.
739 | 
740 | ---
741 | 
742 | ### urlRefineAttributeValue
743 | 
744 | **Signature:** `urlRefineAttributeValue(action : String, attributeID : String, value : String) : URL`
745 | 
746 | **Description:** Constructs an URL that you can use to re-execute the query with an additional refinement value for a given refinement attribute. The provided value will be added to the set of allowed values for the refinement attribute. This basically broadens the search result.
747 | 
748 | **Parameters:**
749 | 
750 | - `action`: the pipeline action.
751 | - `attributeID`: the ID of the refinement attribute.
752 | - `value`: the additional value for the refinement attribute.
753 | 
754 | **Returns:**
755 | 
756 | the new URL.
757 | 
758 | ---
759 | 
760 | ### urlRefineAttributeValue
761 | 
762 | **Signature:** `urlRefineAttributeValue(url : URL, attributeID : String, value : String) : URL`
763 | 
764 | **Description:** Constructs an URL that you can use to re-execute the query with an additional refinement value for a given refinement attribute. The provided value will be added to the set of allowed values for the refinement attribute. This basically broadens the search result. The search specific parameters are appended to the provided URL. The URL is typically generated with one of the URLUtils methods.
765 | 
766 | **Parameters:**
767 | 
768 | - `url`: url
769 | - `attributeID`: ID of the refinement attribute
770 | - `value`: the additional value for the refinement attribute
771 | 
772 | **Returns:**
773 | 
774 | the new URL.
775 | 
776 | ---
777 | 
778 | ### urlRefineAttributeValueRange
779 | 
780 | **Signature:** `urlRefineAttributeValueRange(action : String, attributeID : String, minValue : String, maxValue : String) : URL`
781 | 
782 | **Description:** Constructs an URL that you can use to re-execute the query with an additional refinement value range for a given refinement attribute. The provided value range will be replace to the existing value range for the refinement attribute. The search specific parameters are appended to the provided URL. The URL is typically generated with one of the URLUtils methods.
783 | 
784 | **Parameters:**
785 | 
786 | - `action`: the pipeline action.
787 | - `attributeID`: ID of the refinement attribute
788 | - `minValue`: the min value for the refinement attribute
789 | - `maxValue`: the max value for the refinement attribute
790 | 
791 | **Returns:**
792 | 
793 | the new URL.
794 | 
795 | ---
796 | 
797 | ### urlRelaxAttribute
798 | 
799 | **Signature:** `urlRelaxAttribute(action : String, attributeID : String) : URL`
800 | 
801 | **Description:** Constructs an URL that you can use to re-execute the query without the specified refinement. The value for the action parameter must be a pipeline action, e.g. 'Search-Show'.
802 | 
803 | **Parameters:**
804 | 
805 | - `action`: the pipeline action.
806 | - `attributeID`: ID of the refinement attribute to be removed
807 | 
808 | **Returns:**
809 | 
810 | the new URL.
811 | 
812 | ---
813 | 
814 | ### urlRelaxAttribute
815 | 
816 | **Signature:** `urlRelaxAttribute(url : URL, attributeID : String) : URL`
817 | 
818 | **Description:** Constructs an URL that you can use to re-execute the query without the specified refinement. The search specific parameters are appended to the provided URL. The URL is typically generated with one of the URLUtils methods.
819 | 
820 | **Parameters:**
821 | 
822 | - `url`: the url to use.
823 | - `attributeID`: the ID of the refinement attribute to be removed.
824 | 
825 | **Returns:**
826 | 
827 | the new URL.
828 | 
829 | ---
830 | 
831 | ### urlRelaxAttributeValue
832 | 
833 | **Signature:** `urlRelaxAttributeValue(action : String, attributeID : String, value : String) : URL`
834 | 
835 | **Description:** Constructs an URL that you can use to re-execute the query without the specified refinement. The value for the action parameter must be a pipeline action, e.g. 'Search-Show'.
836 | 
837 | **Parameters:**
838 | 
839 | - `action`: the pipeline action.
840 | - `attributeID`: ID of the refinement attribute to be removed
841 | - `value`: the value that should be removed from the list of refinement values.
842 | 
843 | **Returns:**
844 | 
845 | the new URL.
846 | 
847 | ---
848 | 
849 | ### urlRelaxAttributeValue
850 | 
851 | **Signature:** `urlRelaxAttributeValue(url : URL, attributeID : String, value : String) : URL`
852 | 
853 | **Description:** Constructs an URL that you can use to re-execute the query without the specified refinement value. The search specific parameters are appended to the provided URL. The URL is typically generated with one of the URLUtils methods.
854 | 
855 | **Parameters:**
856 | 
857 | - `url`: the url to use.
858 | - `attributeID`: the ID of the refinement attribute to relax the value for.
859 | - `value`: the value that should be removed from the list of refinement values.
860 | 
861 | **Returns:**
862 | 
863 | the new URL.
864 | 
865 | ---
866 | 
867 | ### urlSort
868 | 
869 | **Signature:** `urlSort(action : String, sortBy : String, sortDir : Number) : URL`
870 | 
871 | **Description:** Constructs an URL that you can use to re-execute the query with a specific sorting criteria. This criteria will overwrite all previous sort critiria. The provided parameter must be an action, e.g. 'Search-Show'.
872 | 
873 | **Parameters:**
874 | 
875 | - `action`: Pipeline action
876 | - `sortBy`: ID of the sort attribute
877 | - `sortDir`: Sort direction. 1 - ASCENDING (default), 2 - DESCENDING
878 | 
879 | **Returns:**
880 | 
881 | The new URL.
882 | 
883 | ---
884 | 
885 | ### urlSort
886 | 
887 | **Signature:** `urlSort(url : URL, sortBy : String, sortDir : Number) : URL`
888 | 
889 | **Description:** Constructs an URL that you can use to re-execute the query with a specific sorting criteria. This criteria will overwrite all previous sort critiria. The search specific parameters are appended to the provided URL. The URL is typically generated with one of the URLUtils methods.
890 | 
891 | **Parameters:**
892 | 
893 | - `url`: URL
894 | - `sortBy`: ID of the sort attribute
895 | - `sortDir`: Sort direction. 1 - ASCENDING (default), 2 - DESCENDING
896 | 
897 | **Returns:**
898 | 
899 | The new URL.
900 | 
901 | ---
```

--------------------------------------------------------------------------------
/docs/dw_order/PriceAdjustment.md:
--------------------------------------------------------------------------------

```markdown
  1 | ## Package: dw.order
  2 | 
  3 | # Class PriceAdjustment
  4 | 
  5 | ## Inheritance Hierarchy
  6 | 
  7 | - Object
  8 |   - dw.object.PersistentObject
  9 |   - dw.object.ExtensibleObject
 10 |     - dw.order.LineItem
 11 |       - dw.order.PriceAdjustment
 12 | 
 13 | ## Description
 14 | 
 15 | The PriceAdjustment class represents an adjustment to the price of an order. A PriceAdjustment can apply to a ProductLineItem, ShippingLineItem, ProductShippingLineItem, or a LineItemCtnr, and are generally categorized as product-level, shipping-level, or order-level. PriceAdjustments are generated by the B2C Commerce promotions engine when applying discounts. See PromotionMgr.applyDiscounts(DiscountPlan). They may also be generated by custom code through the API. See for example ProductLineItem.createPriceAdjustment(String). In the latter case, the PriceAdjustment is called "custom"; in the former case, it is called "system". System price adjustments are associated with the promotion that triggered their creation. If the promotion was coupon-based, then the price adjustment will additionally be associated with a coupon line item in the LineItemCtnr.
 16 | 
 17 | ## Properties
 18 | 
 19 | ### ABTest
 20 | 
 21 | **Type:** ABTest (Read Only)
 22 | 
 23 | The B2C Commerce AB-test this price adjustment is associated with. The associated AB-test is determined
 24 |  from the ABTestID attribute which is set by the promotions engine when applying discounts.
 25 |  
 26 |  If the AB-test has been removed from the system since this price adjustment was created, this method returns
 27 |  null. This method always returns null for custom price adjustments.
 28 | 
 29 | ### ABTestID
 30 | 
 31 | **Type:** String (Read Only)
 32 | 
 33 | The ID of the AB-test related to this price adjustment.
 34 | 
 35 | ### ABTestSegment
 36 | 
 37 | **Type:** ABTestSegment (Read Only)
 38 | 
 39 | The B2C Commerce AB-test segment this price adjustment is associated with. The associated AB-test segment
 40 |  is determined from the ABTestSegmentID attribute which is set by the promotions engine when applying discounts.
 41 |  
 42 |  If the AB-test, or this segment, has been removed from the system since this price adjustment was created, this
 43 |  method returns null. This method always returns null for custom price adjustments.
 44 | 
 45 | ### ABTestSegmentID
 46 | 
 47 | **Type:** String (Read Only)
 48 | 
 49 | The ID of the AB-test segment related to this price adjustment.
 50 | 
 51 | ### appliedDiscount
 52 | 
 53 | **Type:** Discount (Read Only)
 54 | 
 55 | A Discount instance describing the discount applied to
 56 |  obtain this price-adjustment. This method only returns a non-null value
 57 |  if the price-adjustment was created
 58 |  
 59 |  when a discount-plan was applied to a basket, or
 60 |  as a custom price-adjustment using one of the methods
 61 |  ProductLineItem.createPriceAdjustment(String, Discount),
 62 |  ShippingLineItem.createShippingPriceAdjustment(String, Discount)
 63 |  or LineItemCtnr.createPriceAdjustment(String, Discount).
 64 |  
 65 |  
 66 |   Note an instance of the Discount subclasses is
 67 |  returned, such as AmountDiscount or
 68 |  PriceBookPriceDiscount, use
 69 |  Discount.getType() and the constants in
 70 |  Discount to distinguish between types. Each subclass
 71 |  provides access to specific properties.
 72 | 
 73 | ### basedOnABTest
 74 | 
 75 | **Type:** boolean (Read Only)
 76 | 
 77 | Returns true if the price adjustment was generated by the B2C Commerce promotions engine when applying a
 78 |  promotion assigned to an AB-test.
 79 | 
 80 | ### basedOnCampaign
 81 | 
 82 | **Type:** boolean (Read Only)
 83 | 
 84 | Returns true if the price adjustment was generated by the B2C Commerce promotions engine when applying a
 85 |  promotion assigned to a Campaign or an AB-test.
 86 | 
 87 | ### basedOnCoupon
 88 | 
 89 | **Type:** boolean (Read Only)
 90 | 
 91 | Identifies if the promotion line item results from a coupon.
 92 | 
 93 | ### campaign
 94 | 
 95 | **Type:** Campaign (Read Only)
 96 | 
 97 | The B2C Commerce campaign this price adjustment is associated with. The associated campaign is determined
 98 |  from the campaignID attribute which is set by the promotions engine when applying discounts.
 99 |  
100 |  If the campaign has been removed from the system since this price adjustment was created, this method returns
101 |  null. This method always returns null for custom price adjustments.
102 |  
103 |  Note: If the price adjustment was generated by a B2C Commerce promotion as part of an AB-test, then a Campaign
104 |  object will be returned, but it is a mock implementation, and not a true Campaign. This behavior is required for
105 |  backwards compatibility and should not be relied upon as it may change in future releases.
106 | 
107 | ### campaignID
108 | 
109 | **Type:** String (Read Only)
110 | 
111 | The ID of the campaign the price adjustment was based on.
112 |  
113 |  Note:If the price adjustment was generated by a B2C Commerce promotion as part of an AB-test, then an ID will be
114 |  returned but it is not the ID of a true campaign. This behavior is required for backwards compatibility and
115 |  should not be relied upon as it may change in future releases.
116 | 
117 | ### couponLineItem
118 | 
119 | **Type:** CouponLineItem (Read Only)
120 | 
121 | The coupon line item related to this price adjustment.
122 |  If the price adjustment is not based on a coupon, null is returned.
123 | 
124 | ### createdBy
125 | 
126 | **Type:** String (Read Only)
127 | 
128 | The name of the user who created the price adjustment.
129 |  This method returns a value if the price-adjustment was
130 |  created as a custom price-adjustment using one of the methods
131 |  ProductLineItem.createPriceAdjustment(String, Discount),
132 |  ShippingLineItem.createShippingPriceAdjustment(String, Discount)
133 |  or LineItemCtnr.createPriceAdjustment(String, Discount).
134 |  
135 |  If an agent user has created the price adjustment, the agent user's name
136 |  is returned. Otherwise "Customer" is returned.
137 | 
138 | ### custom
139 | 
140 | **Type:** boolean (Read Only)
141 | 
142 | Returns true if this PriceAdjustment was created by custom script code.
143 | 
144 | ### manual
145 | 
146 | **Type:** boolean
147 | 
148 | Returns true if this PriceAdjustment was added manually by a user.
149 |  
150 |  A manual PriceAdjustment is one which has been added as a result of
151 |  a user interaction e.g. by a user editing an order.
152 |  
153 |  A non-manual PriceAdjustment is one which has been added for a different
154 |  reason, e.g. by custom logic which automatically adjusts the price of
155 |  particular products when certain conditions are met.
156 | 
157 | ### promotion
158 | 
159 | **Type:** Promotion (Read Only)
160 | 
161 | The promotion associated with this price adjustment. The
162 |  associated promotion is determined from the promotionID and campaignID
163 |  attributes which are set by the promotions engine when applying
164 |  discounts. Alternatively if the promotion applied as part of an AB-test,
165 |  then the associated promotion is determined from the promotionID
166 |  attribute and the hidden attributes, abTestID and abTestGroupID.
167 |  
168 |  If the promotion has been removed from the system since this price
169 |  adjustment was created, or if the promotion still exists but is not
170 |  assigned to any campaign or AB-test, this method returns null. If the
171 |  promotion has been reassigned to a different campaign or AB-test since
172 |  this price adjustment was created, then the system will return an
173 |  appropriate Promotion instance. This method always returns null for
174 |  custom price adjustments.
175 | 
176 | ### promotionID
177 | 
178 | **Type:** String (Read Only)
179 | 
180 | The ID of the promotion related to this price adjustment.
181 | 
182 | ### proratedPrices
183 | 
184 | **Type:** Map (Read Only)
185 | 
186 | A map representing the product line items to which this price
187 |  adjustment is "related" (in the sense defined below) and the portion of
188 |  this adjustment's price which applies to each after discount prorating is
189 |  performed. This information is sometimes useful to display in the
190 |  storefront but is more often useful for integrating with backend
191 |  order-management and accounting systems which require all discounts to be
192 |  itemized.
193 |  
194 |  The definition of "related" product line items depends on the type of
195 |  promotion which generated this price adjustment:
196 | 
197 |  
198 |  For order promotions, price adjustments are prorated across all
199 |  product line items which are not explicitly excluded by the promotion.
200 |  Custom order price adjustments apply to all items in the LineItemCtnr.
201 |  For Buy-X-Get-Y product promotions, price adjustments are prorated
202 |  across all items all product line items that are involved in the
203 |  promotion, meaning that the PLI has one or more items contributing to the
204 |  qualifying product count (i.e. the item is one of the X) or receiving the
205 |  discount (i.e. the item is one of the Y).
206 |  Other product promotions are not prorated and simply adjust the
207 |  parent product line item, and so the returned map is of size 1.
208 |  For shipping promotions, this method returns an empty map.
209 |  
210 | 
211 |  Buy-X-Get-Y product promotions are prorated as follows: Each price
212 |  adjustment generated by the promotion is sequentially prorated upon the
213 |  related items according to the items' adjusted prices after all non-BOGO
214 |  product promotions are considered, but before order promotions are
215 |  considered.
216 |  
217 |  Order promotions are prorated sequentially upon non-excluded items
218 |  according to the order in which they applied during promotion processing.
219 |  
220 |  The values in the map are inclusive of tax if this price adjustment is
221 |  based on gross pricing, and exclusive of tax otherwise. The sum of the
222 |  prorated prices always equals the price of this price adjustment.
223 | 
224 | ### quantity
225 | 
226 | **Type:** Number (Read Only)
227 | 
228 | The number of items this price adjustment applies to. This value
229 |  is always equal to 1 for price adjustments generated by order or shipping
230 |  promotions. For price adjustments generated by product promotions, this
231 |  value represents the number of units of the parent product line item to
232 |  which the adjustment applies. Because promotions may have a maximum
233 |  number of applications this value may be less than the product line item
234 |  quantity.
235 |  
236 |  For custom price adjustments, not generated by the promotions engine,
237 |  this method always returns 0.
238 | 
239 | ### reasonCode
240 | 
241 | **Type:** EnumValue
242 | 
243 | The reason code of the price adjustment. The list of available
244 |  reason codes is editable system meta-data. An example for using the
245 |  reason code is that in a call center application the CSR will explain
246 |  why he gave a discount to the customer.
247 | 
248 | ## Constructor Summary
249 | 
250 | ## Method Summary
251 | 
252 | ### getABTest
253 | 
254 | **Signature:** `getABTest() : ABTest`
255 | 
256 | Returns the B2C Commerce AB-test this price adjustment is associated with.
257 | 
258 | ### getABTestID
259 | 
260 | **Signature:** `getABTestID() : String`
261 | 
262 | Returns the ID of the AB-test related to this price adjustment.
263 | 
264 | ### getABTestSegment
265 | 
266 | **Signature:** `getABTestSegment() : ABTestSegment`
267 | 
268 | Returns the B2C Commerce AB-test segment this price adjustment is associated with.
269 | 
270 | ### getABTestSegmentID
271 | 
272 | **Signature:** `getABTestSegmentID() : String`
273 | 
274 | Returns the ID of the AB-test segment related to this price adjustment.
275 | 
276 | ### getAppliedDiscount
277 | 
278 | **Signature:** `getAppliedDiscount() : Discount`
279 | 
280 | A Discount instance describing the discount applied to obtain this price-adjustment.
281 | 
282 | ### getCampaign
283 | 
284 | **Signature:** `getCampaign() : Campaign`
285 | 
286 | Returns the B2C Commerce campaign this price adjustment is associated with.
287 | 
288 | ### getCampaignID
289 | 
290 | **Signature:** `getCampaignID() : String`
291 | 
292 | Returns the ID of the campaign the price adjustment was based on.
293 | 
294 | ### getCouponLineItem
295 | 
296 | **Signature:** `getCouponLineItem() : CouponLineItem`
297 | 
298 | Returns the coupon line item related to this price adjustment.
299 | 
300 | ### getCreatedBy
301 | 
302 | **Signature:** `getCreatedBy() : String`
303 | 
304 | Returns the name of the user who created the price adjustment.
305 | 
306 | ### getPromotion
307 | 
308 | **Signature:** `getPromotion() : Promotion`
309 | 
310 | Returns the promotion associated with this price adjustment.
311 | 
312 | ### getPromotionID
313 | 
314 | **Signature:** `getPromotionID() : String`
315 | 
316 | Returns the ID of the promotion related to this price adjustment.
317 | 
318 | ### getProratedPrices
319 | 
320 | **Signature:** `getProratedPrices() : Map`
321 | 
322 | Returns a map representing the product line items to which this price adjustment is "related" (in the sense defined below) and the portion of this adjustment's price which applies to each after discount prorating is performed.
323 | 
324 | ### getQuantity
325 | 
326 | **Signature:** `getQuantity() : Number`
327 | 
328 | Returns the number of items this price adjustment applies to.
329 | 
330 | ### getReasonCode
331 | 
332 | **Signature:** `getReasonCode() : EnumValue`
333 | 
334 | Returns the reason code of the price adjustment.
335 | 
336 | ### isBasedOnABTest
337 | 
338 | **Signature:** `isBasedOnABTest() : boolean`
339 | 
340 | Returns true if the price adjustment was generated by the B2C Commerce promotions engine when applying a promotion assigned to an AB-test.
341 | 
342 | ### isBasedOnCampaign
343 | 
344 | **Signature:** `isBasedOnCampaign() : boolean`
345 | 
346 | Returns true if the price adjustment was generated by the B2C Commerce promotions engine when applying a promotion assigned to a Campaign or an AB-test.
347 | 
348 | ### isBasedOnCoupon
349 | 
350 | **Signature:** `isBasedOnCoupon() : boolean`
351 | 
352 | Identifies if the promotion line item results from a coupon.
353 | 
354 | ### isCustom
355 | 
356 | **Signature:** `isCustom() : boolean`
357 | 
358 | Returns true if this PriceAdjustment was created by custom script code.
359 | 
360 | ### isManual
361 | 
362 | **Signature:** `isManual() : boolean`
363 | 
364 | Returns true if this PriceAdjustment was added manually by a user.
365 | 
366 | ### setManual
367 | 
368 | **Signature:** `setManual(aFlag : boolean) : void`
369 | 
370 | Marks the current PriceAdjustment as manual/non-manual.
371 | 
372 | ### setReasonCode
373 | 
374 | **Signature:** `setReasonCode(reasonCode : String) : void`
375 | 
376 | Set the reason code, using the internal non-localizable value.
377 | 
378 | ## Method Detail
379 | 
380 | ## Method Details
381 | 
382 | ### getABTest
383 | 
384 | **Signature:** `getABTest() : ABTest`
385 | 
386 | **Description:** Returns the B2C Commerce AB-test this price adjustment is associated with. The associated AB-test is determined from the ABTestID attribute which is set by the promotions engine when applying discounts. If the AB-test has been removed from the system since this price adjustment was created, this method returns null. This method always returns null for custom price adjustments.
387 | 
388 | **Returns:**
389 | 
390 | the B2C Commerce AB-test the price adjustment was based on, or null if it was not based on an AB-test.
391 | 
392 | ---
393 | 
394 | ### getABTestID
395 | 
396 | **Signature:** `getABTestID() : String`
397 | 
398 | **Description:** Returns the ID of the AB-test related to this price adjustment.
399 | 
400 | **Returns:**
401 | 
402 | ID of related AB-test, or null.
403 | 
404 | ---
405 | 
406 | ### getABTestSegment
407 | 
408 | **Signature:** `getABTestSegment() : ABTestSegment`
409 | 
410 | **Description:** Returns the B2C Commerce AB-test segment this price adjustment is associated with. The associated AB-test segment is determined from the ABTestSegmentID attribute which is set by the promotions engine when applying discounts. If the AB-test, or this segment, has been removed from the system since this price adjustment was created, this method returns null. This method always returns null for custom price adjustments.
411 | 
412 | **Returns:**
413 | 
414 | the B2C Commerce AB-test segment the price adjustment was based on, or null if it was not based on an AB-test.
415 | 
416 | ---
417 | 
418 | ### getABTestSegmentID
419 | 
420 | **Signature:** `getABTestSegmentID() : String`
421 | 
422 | **Description:** Returns the ID of the AB-test segment related to this price adjustment.
423 | 
424 | **Returns:**
425 | 
426 | ID of related AB-test segment, or null.
427 | 
428 | ---
429 | 
430 | ### getAppliedDiscount
431 | 
432 | **Signature:** `getAppliedDiscount() : Discount`
433 | 
434 | **Description:** A Discount instance describing the discount applied to obtain this price-adjustment. This method only returns a non-null value if the price-adjustment was created when a discount-plan was applied to a basket, or as a custom price-adjustment using one of the methods ProductLineItem.createPriceAdjustment(String, Discount), ShippingLineItem.createShippingPriceAdjustment(String, Discount) or LineItemCtnr.createPriceAdjustment(String, Discount). Note an instance of the Discount subclasses is returned, such as AmountDiscount or PriceBookPriceDiscount, use Discount.getType() and the constants in Discount to distinguish between types. Each subclass provides access to specific properties.
435 | 
436 | **Returns:**
437 | 
438 | null or the discount applied
439 | 
440 | ---
441 | 
442 | ### getCampaign
443 | 
444 | **Signature:** `getCampaign() : Campaign`
445 | 
446 | **Description:** Returns the B2C Commerce campaign this price adjustment is associated with. The associated campaign is determined from the campaignID attribute which is set by the promotions engine when applying discounts. If the campaign has been removed from the system since this price adjustment was created, this method returns null. This method always returns null for custom price adjustments. Note: If the price adjustment was generated by a B2C Commerce promotion as part of an AB-test, then a Campaign object will be returned, but it is a mock implementation, and not a true Campaign. This behavior is required for backwards compatibility and should not be relied upon as it may change in future releases.
447 | 
448 | **Returns:**
449 | 
450 | the B2C Commerce campaign the price adjustment was based on, or null if it was not based on a campaign.
451 | 
452 | ---
453 | 
454 | ### getCampaignID
455 | 
456 | **Signature:** `getCampaignID() : String`
457 | 
458 | **Description:** Returns the ID of the campaign the price adjustment was based on. Note:If the price adjustment was generated by a B2C Commerce promotion as part of an AB-test, then an ID will be returned but it is not the ID of a true campaign. This behavior is required for backwards compatibility and should not be relied upon as it may change in future releases.
459 | 
460 | **Returns:**
461 | 
462 | the ID of the B2C Commerce campaign the price adjustment was based on, or null if it was not based on a campaign.
463 | 
464 | ---
465 | 
466 | ### getCouponLineItem
467 | 
468 | **Signature:** `getCouponLineItem() : CouponLineItem`
469 | 
470 | **Description:** Returns the coupon line item related to this price adjustment. If the price adjustment is not based on a coupon, null is returned.
471 | 
472 | **Returns:**
473 | 
474 | Coupon line item or null.
475 | 
476 | ---
477 | 
478 | ### getCreatedBy
479 | 
480 | **Signature:** `getCreatedBy() : String`
481 | 
482 | **Description:** Returns the name of the user who created the price adjustment. This method returns a value if the price-adjustment was created as a custom price-adjustment using one of the methods ProductLineItem.createPriceAdjustment(String, Discount), ShippingLineItem.createShippingPriceAdjustment(String, Discount) or LineItemCtnr.createPriceAdjustment(String, Discount). If an agent user has created the price adjustment, the agent user's name is returned. Otherwise "Customer" is returned.
483 | 
484 | **Returns:**
485 | 
486 | the name of the user who created the price adjustment
487 | 
488 | ---
489 | 
490 | ### getPromotion
491 | 
492 | **Signature:** `getPromotion() : Promotion`
493 | 
494 | **Description:** Returns the promotion associated with this price adjustment. The associated promotion is determined from the promotionID and campaignID attributes which are set by the promotions engine when applying discounts. Alternatively if the promotion applied as part of an AB-test, then the associated promotion is determined from the promotionID attribute and the hidden attributes, abTestID and abTestGroupID. If the promotion has been removed from the system since this price adjustment was created, or if the promotion still exists but is not assigned to any campaign or AB-test, this method returns null. If the promotion has been reassigned to a different campaign or AB-test since this price adjustment was created, then the system will return an appropriate Promotion instance. This method always returns null for custom price adjustments.
495 | 
496 | **Returns:**
497 | 
498 | the associated promotion, or null.
499 | 
500 | ---
501 | 
502 | ### getPromotionID
503 | 
504 | **Signature:** `getPromotionID() : String`
505 | 
506 | **Description:** Returns the ID of the promotion related to this price adjustment.
507 | 
508 | **Returns:**
509 | 
510 | ID of related promotion.
511 | 
512 | ---
513 | 
514 | ### getProratedPrices
515 | 
516 | **Signature:** `getProratedPrices() : Map`
517 | 
518 | **Description:** Returns a map representing the product line items to which this price adjustment is "related" (in the sense defined below) and the portion of this adjustment's price which applies to each after discount prorating is performed. This information is sometimes useful to display in the storefront but is more often useful for integrating with backend order-management and accounting systems which require all discounts to be itemized. The definition of "related" product line items depends on the type of promotion which generated this price adjustment: For order promotions, price adjustments are prorated across all product line items which are not explicitly excluded by the promotion. Custom order price adjustments apply to all items in the LineItemCtnr. For Buy-X-Get-Y product promotions, price adjustments are prorated across all items all product line items that are involved in the promotion, meaning that the PLI has one or more items contributing to the qualifying product count (i.e. the item is one of the X) or receiving the discount (i.e. the item is one of the Y). Other product promotions are not prorated and simply adjust the parent product line item, and so the returned map is of size 1. For shipping promotions, this method returns an empty map. Buy-X-Get-Y product promotions are prorated as follows: Each price adjustment generated by the promotion is sequentially prorated upon the related items according to the items' adjusted prices after all non-BOGO product promotions are considered, but before order promotions are considered. Order promotions are prorated sequentially upon non-excluded items according to the order in which they applied during promotion processing. The values in the map are inclusive of tax if this price adjustment is based on gross pricing, and exclusive of tax otherwise. The sum of the prorated prices always equals the price of this price adjustment.
519 | 
520 | **Returns:**
521 | 
522 | map of ProductLineItems to Money instances representing the product line items across which this price adjustment is prorated and the portion of this adjustment which applies towards each.
523 | 
524 | ---
525 | 
526 | ### getQuantity
527 | 
528 | **Signature:** `getQuantity() : Number`
529 | 
530 | **Description:** Returns the number of items this price adjustment applies to. This value is always equal to 1 for price adjustments generated by order or shipping promotions. For price adjustments generated by product promotions, this value represents the number of units of the parent product line item to which the adjustment applies. Because promotions may have a maximum number of applications this value may be less than the product line item quantity. For custom price adjustments, not generated by the promotions engine, this method always returns 0.
531 | 
532 | **Returns:**
533 | 
534 | The number of items this price adjustment applies to.
535 | 
536 | ---
537 | 
538 | ### getReasonCode
539 | 
540 | **Signature:** `getReasonCode() : EnumValue`
541 | 
542 | **Description:** Returns the reason code of the price adjustment. The list of available reason codes is editable system meta-data. An example for using the reason code is that in a call center application the CSR will explain why he gave a discount to the customer.
543 | 
544 | **Returns:**
545 | 
546 | reason code of the price adjustment
547 | 
548 | ---
549 | 
550 | ### isBasedOnABTest
551 | 
552 | **Signature:** `isBasedOnABTest() : boolean`
553 | 
554 | **Description:** Returns true if the price adjustment was generated by the B2C Commerce promotions engine when applying a promotion assigned to an AB-test.
555 | 
556 | **Returns:**
557 | 
558 | true if the price adjustment was generated by the B2C Commerce promotions engine when applying a promotion assigned to an AB-test, false otherwise.
559 | 
560 | ---
561 | 
562 | ### isBasedOnCampaign
563 | 
564 | **Signature:** `isBasedOnCampaign() : boolean`
565 | 
566 | **Description:** Returns true if the price adjustment was generated by the B2C Commerce promotions engine when applying a promotion assigned to a Campaign or an AB-test.
567 | 
568 | **Deprecated:**
569 | 
570 | The method has been deprecated since the name implies that there is a related Campaign, which may not be true. Use !isCustom() instead.
571 | 
572 | **Returns:**
573 | 
574 | true if the price adjustment was generated by the B2C Commerce promotions engine, false otherwise.
575 | 
576 | ---
577 | 
578 | ### isBasedOnCoupon
579 | 
580 | **Signature:** `isBasedOnCoupon() : boolean`
581 | 
582 | **Description:** Identifies if the promotion line item results from a coupon.
583 | 
584 | **Returns:**
585 | 
586 | true if the promotion line item results from a coupon, false otherwise.
587 | 
588 | ---
589 | 
590 | ### isCustom
591 | 
592 | **Signature:** `isCustom() : boolean`
593 | 
594 | **Description:** Returns true if this PriceAdjustment was created by custom script code.
595 | 
596 | **Returns:**
597 | 
598 | true if this PriceAdjustment was created by custom script code, or false if it was created by B2C Commerce promotions engine.
599 | 
600 | ---
601 | 
602 | ### isManual
603 | 
604 | **Signature:** `isManual() : boolean`
605 | 
606 | **Description:** Returns true if this PriceAdjustment was added manually by a user. A manual PriceAdjustment is one which has been added as a result of a user interaction e.g. by a user editing an order. A non-manual PriceAdjustment is one which has been added for a different reason, e.g. by custom logic which automatically adjusts the price of particular products when certain conditions are met.
607 | 
608 | **Returns:**
609 | 
610 | true if this PriceAdjustment was added manually by a user, otherwise - false
611 | 
612 | ---
613 | 
614 | ### setManual
615 | 
616 | **Signature:** `setManual(aFlag : boolean) : void`
617 | 
618 | **Description:** Marks the current PriceAdjustment as manual/non-manual. Note that only custom PriceAdjustment can be marked as manual/non-manual. A manual PriceAdjustment is one which has been added as a result of a user interaction e.g. by a user editing an order. A non-manual PriceAdjustment is one which has been added for a different reason, e.g. by custom logic which automatically adjusts the price of particular products when certain conditions are met.
619 | 
620 | **Parameters:**
621 | 
622 | - `aFlag`: the manual flag to set
623 | 
624 | **Throws:**
625 | 
626 | IllegalArgumentException - if the adjustment is not custom
627 | 
628 | ---
629 | 
630 | ### setReasonCode
631 | 
632 | **Signature:** `setReasonCode(reasonCode : String) : void`
633 | 
634 | **Description:** Set the reason code, using the internal non-localizable value. Standard values are 'PRICE_MATCH', 'BACKORDER' and 'EVEN_EXCHANGE', but the available list is editable system meta-data.
635 | 
636 | **Parameters:**
637 | 
638 | - `reasonCode`: reason code
639 | 
640 | ---
```

--------------------------------------------------------------------------------
/tests/mcp/node/list-sfcc-classes.docs-only.programmatic.test.js:
--------------------------------------------------------------------------------

```javascript
  1 | /**
  2 |  * Programmatic tests for list_sfcc_classes tool
  3 |  * 
  4 |  * These tests provide advanced verification capabilities beyond YAML pattern matching,
  5 |  * including performance monitoring, dynamic validation, comprehensive content analysis,
  6 |  * and advanced error categorization for the SFCC class listing functionality.
  7 |  * 
  8 |  * Response format discovered via aegis query:
  9 |  * - Succ      // Core SFCC namespaces should have good coverage
 10 |       const coreNamespaces = ['dw.catalog', 'dw.customer', 'dw.order', 'dw.system'];
 11 |       coreNamespaces.forEach(namespace => {
 12 |         const classCount = analysis.classsByNamespace[namespace].length;
 13 |         assert.ok(classCount >= 5, 
 14 |           `Core namespace ${namespace} should have at least 5 classes (got ${classCount})`);
 15 |       });
 16 |       
 17 |       // TopLevel namespace should have good coverage for utility classes
 18 |       const topLevelCount = analysis.classsByNamespace['TopLevel'].length;
 19 |       assert.ok(topLevelCount >= 10, 
 20 |         `TopLevel namespace should have substantial coverage (got ${topLevelCount})`);
 21 |     });t: [{ type: "text", text: "[\"class1\", \"class2\", ...]" }] }
 22 |  * - Always successful: No isError field or error conditions 
 23 |  * - Ignores extra parameters: Gracefully handles unexpected parameters
 24 |  * - Comprehensive: Returns 500+ classes across all SFCC namespaces
 25 |  */
 26 | 
 27 | import { test, describe, before, after, beforeEach } from 'node:test';
 28 | import { strict as assert } from 'node:assert';
 29 | import { connect } from 'mcp-aegis';
 30 | 
 31 | /**
 32 |  * Performance monitoring utility class for comprehensive metrics collection
 33 |  */
 34 | 
 35 | /**
 36 |  * Content analysis utility for SFCC class validation
 37 |  */
 38 | class ContentAnalyzer {
 39 |   constructor() {
 40 |     // SFCC tools should only return actual SFCC classes (dw.* and TopLevel)
 41 |     // best-practices and sfra content belong to their respective specialized tools
 42 |     this.expectedNamespaces = [
 43 |       'TopLevel',
 44 |       'dw.campaign',
 45 |       'dw.catalog', 
 46 |       'dw.content',
 47 |       'dw.crypto',
 48 |       'dw.customer',
 49 |       'dw.extensions',
 50 |       'dw.io',
 51 |       'dw.job',
 52 |       'dw.net',
 53 |       'dw.object',
 54 |       'dw.order',
 55 |       'dw.rpc',
 56 |       'dw.suggest',
 57 |       'dw.svc',
 58 |       'dw.system',
 59 |       'dw.util',
 60 |       'dw.value',
 61 |       'dw.web'
 62 |     ];
 63 | 
 64 |     // Only include actual SFCC classes, not SFRA or best-practice content
 65 |     this.criticalClasses = [
 66 |       'dw.catalog.Product',
 67 |       'dw.catalog.Category',
 68 |       'dw.order.Order',
 69 |       'dw.order.Basket',
 70 |       'dw.customer.Customer',
 71 |       'dw.system.Site',
 72 |       'dw.system.SitePreferences',
 73 |       'dw.util.ArrayList',
 74 |       'dw.web.URL'
 75 |     ];
 76 | 
 77 |     // Best practice guides are handled by dedicated best-practice tools, not SFCC tools
 78 |     this.bestPracticeGuides = [];
 79 |   }
 80 | 
 81 |   analyzeClassList(classArray) {
 82 |     const analysis = {
 83 |       totalClasses: classArray.length,
 84 |       namespacesCovered: new Set(),
 85 |       missingNamespaces: [],
 86 |       missingCriticalClasses: [],
 87 |       foundCriticalClasses: [],
 88 |       foundBestPractices: [],
 89 |       duplicates: [],
 90 |       invalidFormats: [],
 91 |       classsByNamespace: {}
 92 |     };
 93 | 
 94 |     // Initialize namespace counters
 95 |     this.expectedNamespaces.forEach(ns => {
 96 |       analysis.classsByNamespace[ns] = [];
 97 |     });
 98 | 
 99 |     // Analyze each class
100 |     const seenClasses = new Set();
101 |     classArray.forEach(className => {
102 |       // Check for duplicates
103 |       if (seenClasses.has(className)) {
104 |         analysis.duplicates.push(className);
105 |         return;
106 |       }
107 |       seenClasses.add(className);
108 | 
109 |       // Validate format (should have at least one dot or be TopLevel.*)
110 |       if (!className.includes('.') && !className.startsWith('TopLevel.')) {
111 |         analysis.invalidFormats.push(className);
112 |       }
113 | 
114 |       // Categorize by namespace
115 |       let namespace;
116 |       if (className.startsWith('dw.')) {
117 |         // For dw.* classes, use first two parts (e.g., "dw.catalog" from "dw.catalog.Product")
118 |         namespace = className.split('.').slice(0, 2).join('.');
119 |       } else {
120 |         // For TopLevel and other classes, use first part only
121 |         namespace = className.split('.')[0];
122 |       }
123 |       analysis.namespacesCovered.add(namespace);
124 |       
125 |       if (analysis.classsByNamespace[namespace]) {
126 |         analysis.classsByNamespace[namespace].push(className);
127 |       } else {
128 |         // Unexpected namespace
129 |         if (!analysis.classsByNamespace.other) {
130 |           analysis.classsByNamespace.other = [];
131 |         }
132 |         analysis.classsByNamespace.other.push(className);
133 |       }
134 | 
135 |       // Check critical classes
136 |       if (this.criticalClasses.includes(className)) {
137 |         analysis.foundCriticalClasses.push(className);
138 |       }
139 | 
140 |       // Check best practice guides
141 |       if (this.bestPracticeGuides.includes(className)) {
142 |         analysis.foundBestPractices.push(className);
143 |       }
144 |     });
145 | 
146 |     // Find missing namespaces
147 |     analysis.missingNamespaces = this.expectedNamespaces.filter(
148 |       ns => !analysis.namespacesCovered.has(ns)
149 |     );
150 | 
151 |     // Find missing critical classes
152 |     analysis.missingCriticalClasses = this.criticalClasses.filter(
153 |       cls => !analysis.foundCriticalClasses.includes(cls)
154 |     );
155 | 
156 |     return analysis;
157 |   }
158 | 
159 |   validateCompleteness(analysis) {
160 |     const issues = [];
161 | 
162 |     if (analysis.totalClasses < 350) {
163 |       issues.push(`Class count too low: ${analysis.totalClasses} (expected 350+)`);
164 |     }
165 | 
166 |     if (analysis.missingNamespaces.length > 0) {
167 |       issues.push(`Missing namespaces: ${analysis.missingNamespaces.join(', ')}`);
168 |     }
169 | 
170 |     if (analysis.missingCriticalClasses.length > 0) {
171 |       issues.push(`Missing critical classes: ${analysis.missingCriticalClasses.join(', ')}`);
172 |     }
173 | 
174 |     if (analysis.duplicates.length > 0) {
175 |       issues.push(`Duplicate classes found: ${analysis.duplicates.length}`);
176 |     }
177 | 
178 |     if (analysis.invalidFormats.length > 0) {
179 |       issues.push(`Invalid formats found: ${analysis.invalidFormats.length}`);
180 |     }
181 | 
182 |     return issues;
183 |   }
184 | }
185 | 
186 | describe('list_sfcc_classes Programmatic Tests', () => {
187 |   let client;
188 |   const contentAnalyzer = new ContentAnalyzer();
189 | 
190 |   before(async () => {
191 |     client = await connect('./aegis.config.docs-only.json');
192 |   });
193 | 
194 |   after(async () => {
195 |     if (client?.connected) {
196 |       await client.disconnect();
197 |     }
198 |   });
199 | 
200 |   beforeEach(() => {
201 |     // CRITICAL: Clear all buffers to prevent test interference
202 |     client.clearAllBuffers(); // Recommended - comprehensive protection
203 |   });
204 | 
205 |   describe('Protocol Compliance', () => {
206 |     test('should be properly connected to MCP server', async () => {
207 |       assert.ok(client.connected, 'Client should be connected');
208 |     });
209 | 
210 |     test('should have list_sfcc_classes tool available', async () => {
211 |       const tools = await client.listTools();
212 |       const listTool = tools.find(tool => tool.name === 'list_sfcc_classes');
213 |       
214 |       assert.ok(listTool, 'list_sfcc_classes tool should be available');
215 |       assert.equal(listTool.name, 'list_sfcc_classes');
216 |       assert.ok(listTool.description, 'Tool should have description');
217 |       assert.ok(listTool.inputSchema, 'Tool should have input schema');
218 |     });
219 | 
220 |     test('should have correct tool input schema', async () => {
221 |       const tools = await client.listTools();
222 |       const listTool = tools.find(tool => tool.name === 'list_sfcc_classes');
223 |       
224 |       assert.equal(listTool.inputSchema.type, 'object');
225 |       // list_sfcc_classes takes no required parameters
226 |       assert.ok(!listTool.inputSchema.required || listTool.inputSchema.required.length === 0);
227 |     });
228 |   });
229 | 
230 |   describe('Basic Functionality', () => {
231 |     test('should execute successfully with empty parameters', async () => {
232 |       const result = await client.callTool('list_sfcc_classes', {});
233 |       
234 |       assertValidMCPResponse(result);
235 |       assert.equal(result.isError, false, 'Should not return error');
236 |       assert.equal(result.content.length, 1, 'Should return single content item');
237 |       assert.equal(result.content[0].type, 'text', 'Content type should be text');
238 |     });
239 | 
240 |     test('should return valid JSON array in response', async () => {
241 |       const result = await client.callTool('list_sfcc_classes', {});
242 |       
243 |       assertValidMCPResponse(result);
244 |       const responseText = result.content[0].text;
245 |       
246 |       // Should be valid JSON
247 |       let classArray;
248 |       assert.doesNotThrow(() => {
249 |         classArray = JSON.parse(responseText);
250 |       }, 'Response should be valid JSON');
251 |       
252 |       assert.ok(Array.isArray(classArray), 'Response should be JSON array');
253 |       assert.ok(classArray.length > 0, 'Class array should not be empty');
254 |     });
255 | 
256 |     test('should ignore additional parameters gracefully', async () => {
257 |       const result = await client.callTool('list_sfcc_classes', {
258 |         unexpectedParam: 'should be ignored',
259 |         anotherParam: 123,
260 |         objectParam: { nested: 'value' }
261 |       });
262 |       
263 |       assertValidMCPResponse(result);
264 |       assert.equal(result.isError, false, 'Should handle extra params gracefully');
265 |       
266 |       // Result should be identical to empty params call
267 |       const baselineResult = await client.callTool('list_sfcc_classes', {});
268 |       assert.equal(result.content[0].text, baselineResult.content[0].text, 
269 |         'Result should be identical regardless of extra params');
270 |     });
271 |   });
272 | 
273 |   describe('Content Quality and Completeness', () => {
274 |     test('should return comprehensive SFCC class coverage', async () => {
275 |       const result = await client.callTool('list_sfcc_classes', {});
276 |       const classArray = JSON.parse(result.content[0].text);
277 |       const analysis = contentAnalyzer.analyzeClassList(classArray);
278 |       
279 |       // Validate completeness
280 |       const issues = contentAnalyzer.validateCompleteness(analysis);
281 |       assert.equal(issues.length, 0, `Content issues found: ${issues.join('; ')}`);
282 |       
283 |       // Verify substantial class count
284 |       assert.ok(analysis.totalClasses >= 400, 
285 |         `Should have substantial class count (got ${analysis.totalClasses})`);
286 |     });
287 | 
288 |     test('should include all expected SFCC namespaces', async () => {
289 |       const result = await client.callTool('list_sfcc_classes', {});
290 |       const classArray = JSON.parse(result.content[0].text);
291 |       const analysis = contentAnalyzer.analyzeClassList(classArray);
292 |       
293 |       contentAnalyzer.expectedNamespaces.forEach(namespace => {
294 |         assert.ok(analysis.namespacesCovered.has(namespace), 
295 |           `Missing expected namespace: ${namespace}`);
296 |         assert.ok(analysis.classsByNamespace[namespace].length > 0,
297 |           `Namespace ${namespace} should have classes`);
298 |       });
299 |     });
300 | 
301 |     test('should include critical SFCC classes for development', async () => {
302 |       const result = await client.callTool('list_sfcc_classes', {});
303 |       const classArray = JSON.parse(result.content[0].text);
304 |       const analysis = contentAnalyzer.analyzeClassList(classArray);
305 |       
306 |       contentAnalyzer.criticalClasses.forEach(criticalClass => {
307 |         assert.ok(classArray.includes(criticalClass), 
308 |           `Missing critical class: ${criticalClass}`);
309 |       });
310 |       
311 |       assert.ok(analysis.foundCriticalClasses.length >= contentAnalyzer.criticalClasses.length * 0.9,
312 |         'Should include at least 90% of critical classes');
313 |     });
314 | 
315 |     test('should include best practice guides', async () => {
316 |       const result = await client.callTool('list_sfcc_classes', {});
317 |       const classArray = JSON.parse(result.content[0].text);
318 |       
319 |       contentAnalyzer.bestPracticeGuides.forEach(guide => {
320 |         assert.ok(classArray.includes(guide), 
321 |           `Missing best practice guide: ${guide}`);
322 |       });
323 |     });
324 | 
325 |     test('should have proper class naming format', async () => {
326 |       const result = await client.callTool('list_sfcc_classes', {});
327 |       const classArray = JSON.parse(result.content[0].text);
328 |       const analysis = contentAnalyzer.analyzeClassList(classArray);
329 |       
330 |       assert.equal(analysis.invalidFormats.length, 0, 
331 |         `Invalid class formats found: ${analysis.invalidFormats.join(', ')}`);
332 |       
333 |       assert.equal(analysis.duplicates.length, 0,
334 |         `Duplicate classes found: ${analysis.duplicates.join(', ')}`);
335 |     });
336 |   });
337 | 
338 |   describe('Advanced Content Analysis', () => {
339 |     test('should provide balanced namespace distribution', async () => {
340 |       const result = await client.callTool('list_sfcc_classes', {});
341 |       const classArray = JSON.parse(result.content[0].text);
342 |       const analysis = contentAnalyzer.analyzeClassList(classArray);
343 |       
344 |       // Core namespaces should have substantial class counts
345 |       const coreNamespaces = ['dw.catalog', 'dw.order', 'dw.customer', 'dw.system'];
346 |       coreNamespaces.forEach(namespace => {
347 |         const classCount = analysis.classsByNamespace[namespace].length;
348 |         assert.ok(classCount >= 5, 
349 |           `Core namespace ${namespace} should have at least 5 classes (got ${classCount})`);
350 |       });
351 |       
352 |       // TopLevel namespace should have good coverage for utility classes
353 |       const topLevelCount = analysis.classsByNamespace['TopLevel'].length;
354 |       assert.ok(topLevelCount >= 10, 
355 |         `TopLevel namespace should have substantial coverage (got ${topLevelCount})`);
356 |     });
357 | 
358 |     test('should include developer-friendly discovery content', async () => {
359 |       const result = await client.callTool('list_sfcc_classes', {});
360 |       const classArray = JSON.parse(result.content[0].text);
361 |       
362 |       // Should include educational namespaces for new developers (SFCC classes only)
363 |       const educationalClasses = [
364 |         'TopLevel.Array', 
365 |         'TopLevel.Object',
366 |         'dw.catalog.Product',
367 |         'dw.system.Site'
368 |       ];
369 |       
370 |       educationalClasses.forEach(educationalClass => {
371 |         assert.ok(classArray.includes(educationalClass), 
372 |           `Missing educational class: ${educationalClass}`);
373 |       });
374 |     });
375 | 
376 |     test('should support API exploration workflows', async () => {
377 |       const result = await client.callTool('list_sfcc_classes', {});
378 |       const classArray = JSON.parse(result.content[0].text);
379 |       
380 |       // Should include classes that developers commonly search for
381 |       const commonSearchTargets = [
382 |         'dw.catalog.ProductMgr',
383 |         'dw.order.BasketMgr', 
384 |         'dw.customer.CustomerMgr',
385 |         'dw.system.SitePreferences',
386 |         'dw.web.URLUtils'
387 |       ];
388 |       
389 |       commonSearchTargets.forEach(searchTarget => {
390 |         assert.ok(classArray.includes(searchTarget), 
391 |           `Missing common search target: ${searchTarget}`);
392 |       });
393 |     });
394 | 
395 |     test('should provide comprehensive extension coverage', async () => {
396 |       const result = await client.callTool('list_sfcc_classes', {});
397 |       const classArray = JSON.parse(result.content[0].text);
398 |       
399 |       // Should include extension classes for integrations
400 |       const extensionClasses = classArray.filter(cls => cls.startsWith('dw.extensions.'));
401 |       assert.ok(extensionClasses.length >= 10, 
402 |         `Should include substantial extension classes (got ${extensionClasses.length})`);
403 |       
404 |       // Should cover major payment integrations
405 |       const paymentClasses = classArray.filter(cls => 
406 |         cls.includes('payments') || cls.includes('PayPal') || cls.includes('ApplePay'));
407 |       assert.ok(paymentClasses.length >= 5,
408 |         `Should include payment integration classes (got ${paymentClasses.length})`);
409 |     });
410 |   });
411 | 
412 | 
413 |   describe('Response Structure Validation', () => {
414 |     test('should maintain consistent response structure', async () => {
415 |       const result1 = await client.callTool('list_sfcc_classes', {});
416 |       const result2 = await client.callTool('list_sfcc_classes', {});
417 |       
418 |       // Structure should be identical
419 |       assert.equal(result1.content.length, result2.content.length);
420 |       assert.equal(result1.content[0].type, result2.content[0].type);
421 |       assert.equal(result1.content[0].text, result2.content[0].text);
422 |       
423 |       // Content should be deterministic
424 |       const classes1 = JSON.parse(result1.content[0].text);
425 |       const classes2 = JSON.parse(result2.content[0].text);
426 |       assert.deepEqual(classes1, classes2, 'Class lists should be identical between calls');
427 |     });
428 | 
429 |     test('should return properly formatted JSON with valid structure', async () => {
430 |       const result = await client.callTool('list_sfcc_classes', {});
431 |       const responseText = result.content[0].text;
432 |       
433 |       // Should be properly formatted JSON
434 |       assert.ok(responseText.startsWith('['), 'Should start with array bracket');
435 |       assert.ok(responseText.endsWith(']'), 'Should end with array bracket');
436 |       
437 |       // Parse and validate structure
438 |       const classArray = JSON.parse(responseText);
439 |       assert.ok(Array.isArray(classArray), 'Should be array');
440 |       
441 |       // Each item should be a string
442 |       classArray.forEach((item, index) => {
443 |         assert.equal(typeof item, 'string', `Item ${index} should be string`);
444 |         assert.ok(item.length > 0, `Item ${index} should not be empty`);
445 |       });
446 |     });
447 | 
448 |     test('should provide useful content for AI agents', async () => {
449 |       const result = await client.callTool('list_sfcc_classes', {});
450 |       const classArray = JSON.parse(result.content[0].text);
451 |       
452 |       // Should include SFCC classes that AI agents commonly need
453 |       const aiUsefulClasses = [
454 |         'dw.system.Logger',        // For logging
455 |         'dw.util.StringUtils',     // For text processing  
456 |         'dw.web.URLUtils',         // For URL generation
457 |         'dw.system.Site',          // For site context
458 |         'dw.catalog.Product',      // For product operations
459 |         'dw.order.Basket'          // For basket operations
460 |       ];
461 |       
462 |       aiUsefulClasses.forEach(usefulClass => {
463 |         assert.ok(classArray.includes(usefulClass), 
464 |           `Should include AI-useful class: ${usefulClass}`);
465 |       });
466 |     });
467 |   });
468 | 
469 |   describe('Educational and Discovery Value', () => {
470 |     test('should serve as comprehensive SFCC reference', async () => {
471 |       const result = await client.callTool('list_sfcc_classes', {});
472 |       const classArray = JSON.parse(result.content[0].text);
473 |       const analysis = contentAnalyzer.analyzeClassList(classArray);
474 |       
475 |       // Should cover all major SFCC functional areas (SFCC classes only)
476 |       const functionalAreas = {
477 |         'commerce': ['dw.catalog', 'dw.order'],
478 |         'customer': ['dw.customer'],
479 |         'system': ['dw.system'],
480 |         'web': ['dw.web'],
481 |         'utilities': ['dw.util'],
482 |         'integrations': ['dw.svc', 'dw.extensions'],
483 |         'foundations': ['TopLevel']
484 |       };
485 |       
486 |       Object.entries(functionalAreas).forEach(([area, namespaces]) => {
487 |         namespaces.forEach(namespace => {
488 |           const classCount = analysis.classsByNamespace[namespace].length;
489 |           assert.ok(classCount > 0, 
490 |             `Functional area '${area}' should have classes in namespace '${namespace}'`);
491 |         });
492 |       });
493 |     });
494 | 
495 |     test('should support progressive learning for developers', async () => {
496 |       const result = await client.callTool('list_sfcc_classes', {});
497 |       const classArray = JSON.parse(result.content[0].text);
498 |       
499 |       // Should include beginner-friendly TopLevel classes
500 |       const beginnerClasses = classArray.filter(cls => 
501 |         cls.startsWith('TopLevel.'));
502 |       assert.ok(beginnerClasses.length >= 10, 
503 |         `Should include beginner-friendly TopLevel classes (got ${beginnerClasses.length})`);
504 |       
505 |       // Should include advanced integration classes
506 |       const advancedClasses = classArray.filter(cls => 
507 |         cls.includes('Hook') || cls.includes('Extension') || cls.includes('Service'));
508 |       assert.ok(advancedClasses.length >= 20,
509 |         `Should include advanced integration classes (got ${advancedClasses.length})`);
510 |     });
511 |   });
512 | 
513 |   describe('Integration and Cross-Tool Validation', () => {
514 |     test('should provide classes that work with search_sfcc_classes tool', async () => {
515 |       const listResult = await client.callTool('list_sfcc_classes', {});
516 |       const classArray = JSON.parse(listResult.content[0].text);
517 |       
518 |       // Pick a few SFCC classes to test with search tool
519 |       const testClasses = ['dw.catalog.Product', 'dw.system.Site', 'dw.customer.Customer'];
520 |       
521 |       for (const testClass of testClasses) {
522 |         assert.ok(classArray.includes(testClass), 
523 |           `List should include searchable class: ${testClass}`);
524 |         
525 |         // Test that the class is discoverable via search
526 |         const namespace = testClass.split('.')[1]; // Get 'catalog' from 'dw.catalog.Product'
527 |         const searchResult = await client.callTool('search_sfcc_classes', { 
528 |           query: namespace 
529 |         });
530 |         
531 |         assertValidMCPResponse(searchResult);
532 |         if (!searchResult.isError) {
533 |           const searchedClasses = JSON.parse(searchResult.content[0].text);
534 |           assert.ok(Array.isArray(searchedClasses), 
535 |             `Search should return array for ${namespace}`);
536 |         }
537 |       }
538 |     });
539 | 
540 |     test('should include classes that have detailed documentation available', async () => {
541 |       const listResult = await client.callTool('list_sfcc_classes', {});
542 |       const classArray = JSON.parse(listResult.content[0].text);
543 |       
544 |       // Test a few well-documented classes
545 |       const documentedClasses = ['dw.catalog.Product', 'dw.system.Site', 'dw.order.Basket'];
546 |       
547 |       for (const docClass of documentedClasses) {
548 |         assert.ok(classArray.includes(docClass), 
549 |           `List should include documented class: ${docClass}`);
550 |         
551 |         // Test that class info is available
552 |         const infoResult = await client.callTool('get_sfcc_class_info', { 
553 |           className: docClass 
554 |         });
555 |         
556 |         assertValidMCPResponse(infoResult);
557 |         if (!infoResult.isError) {
558 |           const infoText = infoResult.content[0].text;
559 |           // Parse the JSON response to check for class information
560 |           let classInfo;
561 |           assert.doesNotThrow(() => {
562 |             classInfo = JSON.parse(infoText);
563 |           }, `Class info should be valid JSON for ${docClass}`);
564 |           
565 |           // Check that the response contains class information
566 |           assert.ok(classInfo.className || classInfo.packageName, 
567 |             `Class info should contain class information for ${docClass}`);
568 |           
569 |           // For dw.catalog.Product, verify it contains "Product" and "dw.catalog"
570 |           if (docClass === 'dw.catalog.Product') {
571 |             assert.ok(classInfo.className === 'Product', 
572 |               'Product class info should contain className "Product"');
573 |             assert.ok(classInfo.packageName === 'dw.catalog', 
574 |               'Product class info should contain packageName "dw.catalog"');
575 |           }
576 |         }
577 |       }
578 |     });
579 | 
580 |     test('should maintain consistency with available tools ecosystem', async () => {
581 |       const listResult = await client.callTool('list_sfcc_classes', {});
582 |       const classArray = JSON.parse(listResult.content[0].text);
583 |       
584 |       // Should include SFCC classes that support the SFCC toolchain
585 |       const toolchainClasses = [
586 |         'dw.catalog.Product',         // For product tool integration
587 |         'dw.system.SitePreferences',  // For site preference tools
588 |         'dw.order.Order',             // For order management tools
589 |         'dw.util.ArrayList',          // For collection operations
590 |         'dw.web.URLUtils'             // For URL generation tools
591 |       ];
592 |       
593 |       toolchainClasses.forEach(toolClass => {
594 |         assert.ok(classArray.includes(toolClass), 
595 |           `Should include toolchain-supporting class: ${toolClass}`);
596 |       });
597 |     });
598 | 
599 |     test('should enable effective AI-assisted development workflows', async () => {
600 |       const listResult = await client.callTool('list_sfcc_classes', {});
601 |       const classArray = JSON.parse(listResult.content[0].text);
602 |       
603 |       // Should include SFCC classes that AI agents commonly recommend
604 |       const aiWorkflowClasses = [
605 |         'dw.system.Logger',           // For debugging workflows
606 |         'dw.util.StringUtils',        // For data manipulation
607 |         'dw.web.URLUtils',           // For URL generation
608 |         'dw.catalog.ProductMgr',     // For product operations
609 |         'dw.order.BasketMgr',        // For cart operations
610 |         'dw.customer.CustomerMgr',   // For customer operations
611 |         'dw.system.Site',            // For site context
612 |         'dw.order.Order'             // For order handling
613 |       ];
614 |       
615 |       aiWorkflowClasses.forEach(workflowClass => {
616 |         assert.ok(classArray.includes(workflowClass), 
617 |           `Should include AI workflow class: ${workflowClass}`);
618 |       });
619 |       
620 |       // Should provide good coverage for common AI development tasks (SFCC classes only)
621 |       const taskCoverage = {
622 |         'data_access': classArray.filter(cls => cls.includes('Mgr')).length,
623 |         'web_operations': classArray.filter(cls => cls.startsWith('dw.web.')).length,
624 |         'system_integration': classArray.filter(cls => cls.startsWith('dw.system.')).length,
625 |         'utilities': classArray.filter(cls => cls.startsWith('dw.util.')).length
626 |       };
627 |       
628 |       Object.entries(taskCoverage).forEach(([task, count]) => {
629 |         assert.ok(count >= 3, 
630 |           `Should have good coverage for ${task} (got ${count} classes)`);
631 |       });
632 |     });
633 |   });
634 | });
635 | 
636 | /**
637 |  * Helper function to validate basic MCP response structure
638 |  */
639 | function assertValidMCPResponse(result) {
640 |   assert.ok(result.content, 'Response should have content');
641 |   assert.ok(Array.isArray(result.content), 'Content should be array');
642 |   assert.equal(typeof result.isError, 'boolean', 'isError should be boolean and always present');
643 | }
644 | 
```
Page 40/61FirstPrevNextLast