@salesforce/storefront-next-runtime 0.2.0-alpha.2 → 0.3.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DesignFrame.js +6 -2
- package/dist/DesignFrame.js.map +1 -1
- package/dist/DesignRegion.js +2 -1
- package/dist/DesignRegion.js.map +1 -1
- package/dist/component.types.d.ts +6 -0
- package/dist/component.types.d.ts.map +1 -1
- package/dist/config-load.d.ts +27 -0
- package/dist/config-load.d.ts.map +1 -0
- package/dist/config-load.js +3 -0
- package/dist/config.d.ts +248 -1
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +429 -0
- package/dist/config.js.map +1 -0
- package/dist/design-data.d.ts +40 -27
- package/dist/design-data.d.ts.map +1 -1
- package/dist/design-data.js +50 -26
- package/dist/design-data.js.map +1 -1
- package/dist/design-react-core.d.ts +2 -2
- package/dist/design-react-core.js +3 -1
- package/dist/design-react-core.js.map +1 -1
- package/dist/events.d.ts +9 -4
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +6 -6
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/load-config.js +41 -0
- package/dist/load-config.js.map +1 -0
- package/dist/multi-site.d.ts +68 -43
- package/dist/multi-site.d.ts.map +1 -1
- package/dist/multi-site.js +36 -10
- package/dist/multi-site.js.map +1 -1
- package/dist/routing.d.ts.map +1 -1
- package/dist/routing.js +4 -37
- package/dist/routing.js.map +1 -1
- package/dist/scapi.d.ts +8 -0
- package/dist/scapi.d.ts.map +1 -1
- package/dist/scapi.js +1 -1
- package/dist/scapi.js.map +1 -1
- package/dist/schema.d.ts +78 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -1
package/dist/design-data.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"design-data.js","names":["context: {\n /** The current node being visited. */\n node: TNode;\n /** The node type */\n type: VisitorContextType;\n /** The visitor being used to transform the page tree. */\n visitor: PageVisitor;\n /** The root page being traversed. */\n page?: ShopperExperience.schemas['Page'];\n /** The parent region of the current node, if traversing within a region. */\n parentRegion?: ShopperExperience.schemas['Region'];\n /** The parent component of the current node, if traversing within a component's nested regions. */\n parentComponent?: ShopperExperience.schemas['Component'];\n }","record: ResolvedDataBinding | undefined","resolvedData: Record<string, unknown>","currentCategoryId: string | undefined","context: QualifierContext | null","resolvedVariation: VariationEntry | null","resolvedId: string | null","context: QualifierContext | null"],"sources":["../src/design/data/errors/visitor-context-error.ts","../src/design/data/page/transform.ts","../src/design/data/page/resolve-data-bindings.ts","../src/design/data/validate-rule.ts","../src/design/data/page/process-page.ts","../src/design/data/errors/required.ts","../src/design/data/manifest/content-assignment-resolvers.ts","../src/design/data/manifest/resolve-dynamic-page-id.ts","../src/design/data/manifest/get-page.ts","../src/design/data/page/resolve-page.ts"],"sourcesContent":["/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { VisitorContextType } from '../types';\n\nexport class VisitorContextError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'VisitorContextError';\n }\n\n static assert(parentType: VisitorContextType, childType: VisitorContextType) {\n if (\n (parentType === 'component' && childType !== 'region') ||\n (parentType === 'page' && childType !== 'region') ||\n (parentType === 'region' && childType !== 'component')\n ) {\n throw new VisitorContextError(\n `Invalid child context type ${childType} for parent context type ${parentType}`\n );\n }\n }\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { ShopperExperience } from '@/scapi-client/types';\nimport { VisitorContextError } from '../errors/visitor-context-error';\nimport type { InferNodeFromType, VisitorContextType } from '../types';\n\n/**\n * Context object passed to {@link PageVisitor} handler methods during page tree\n * traversal. Provides access to the current node via {@link node}, the tree\n * position via {@link page}, {@link parentRegion}, and {@link parentComponent},\n * and traversal methods ({@link visitRegions}, {@link visitComponents}) for\n * continuing into child nodes.\n *\n * When a visitor handler is defined, the handler is responsible for traversing\n * into children by calling the appropriate context method. If the handler does\n * not call these methods, children will not be visited.\n */\nexport class VisitorContext<TNode> {\n constructor(\n private readonly context: {\n /** The current node being visited. */\n node: TNode;\n /** The node type */\n type: VisitorContextType;\n /** The visitor being used to transform the page tree. */\n visitor: PageVisitor;\n /** The root page being traversed. */\n page?: ShopperExperience.schemas['Page'];\n /** The parent region of the current node, if traversing within a region. */\n parentRegion?: ShopperExperience.schemas['Region'];\n /** The parent component of the current node, if traversing within a component's nested regions. */\n parentComponent?: ShopperExperience.schemas['Component'];\n }\n ) {}\n\n get type(): VisitorContextType {\n return this.context.type;\n }\n\n /**\n * The current node being visited.\n */\n get node(): TNode {\n return this.context.node;\n }\n\n /**\n * The root page being traversed.\n */\n get page(): ShopperExperience.schemas['Page'] | undefined {\n return this.context.page;\n }\n\n /**\n * The parent region of the current node, if traversing within a region.\n */\n get parentRegion(): ShopperExperience.schemas['Region'] | undefined {\n return this.context.parentRegion;\n }\n\n /**\n * The parent component of the current node, if traversing within a component's nested regions.\n */\n get parentComponent(): ShopperExperience.schemas['Component'] | undefined {\n return this.context.parentComponent;\n }\n\n /**\n * Traverses an array of regions, invoking the visitor's `visitRegion` handler\n * on each one. Regions for which the handler returns `null` are excluded from\n * the result. Call this from within a `visitPage` or `visitComponent` handler\n * to continue traversal into child regions.\n *\n * @param regions - The regions to traverse.\n * @returns The filtered array of transformed regions.\n *\n * @example\n * ```ts\n * transformPage(page, {\n * visitPage(context) {\n * // Traverse into regions explicitly\n * const regions = context.visitRegions(context.node.regions);\n * return { ...context.node, regions };\n * },\n * });\n * ```\n */\n visitRegions(regions: ShopperExperience.schemas['Region'][] = []): ShopperExperience.schemas['Region'][] {\n const newRegions = [];\n\n for (const region of regions) {\n const newRegion = this.visitRegion(region);\n\n if (newRegion) {\n newRegions.push(newRegion);\n }\n }\n\n return newRegions;\n }\n\n /**\n * Traverses a single region. If the visitor has a `visitRegion` handler, the\n * handler is called with a new {@link VisitorContext} for the region. Otherwise,\n * the region's child components are traversed automatically.\n *\n * @param region - The region to visit.\n * @returns The transformed region, or `null` to exclude it.\n */\n visitRegion(region: ShopperExperience.schemas['Region']): ShopperExperience.schemas['Region'] | null {\n const regionContext = this.toChildContext('region', region);\n\n if (this.context.visitor.visitRegion) {\n return this.context.visitor.visitRegion(regionContext);\n } else if (region.components) {\n return {\n ...region,\n components: regionContext.visitComponents(region.components),\n };\n }\n\n return region;\n }\n\n /**\n * Traverses an array of components, invoking the visitor's `visitComponent`\n * handler on each one. Components for which the handler returns `null` are\n * excluded from the result. Call this from within a `visitRegion` handler to\n * continue traversal into child components.\n *\n * @param components - The components to traverse.\n * @returns The filtered array of transformed components.\n *\n * @example\n * ```ts\n * transformPage(page, {\n * visitRegion(context) {\n * // Traverse into components explicitly\n * const components = context.visitComponents(context.node.components);\n * return { ...context.node, components };\n * },\n * });\n * ```\n */\n visitComponents(\n components: ShopperExperience.schemas['Component'][] = []\n ): ShopperExperience.schemas['Component'][] {\n const newComponents = [];\n\n for (const component of components) {\n const newComponent = this.visitComponent(component);\n\n if (newComponent) {\n newComponents.push(newComponent);\n }\n }\n\n return newComponents;\n }\n\n /**\n * Traverses a single component. If the visitor has a `visitComponent` handler,\n * the handler is called with a new {@link VisitorContext} for the component.\n * Otherwise, the component's nested regions are traversed automatically.\n *\n * @param component - The component to visit.\n * @returns The transformed component, or `null` to exclude it.\n */\n visitComponent(component: ShopperExperience.schemas['Component']): ShopperExperience.schemas['Component'] | null {\n const componentContext = this.toChildContext('component', component);\n\n if (this.context.visitor.visitComponent) {\n return this.context.visitor.visitComponent(componentContext);\n } else if (component.regions) {\n return {\n ...component,\n regions: componentContext.visitRegions(component.regions),\n };\n }\n\n return component;\n }\n\n /**\n * Traverses a single page. If the visitor has a `visitPage` handler, the\n * handler is called with a new {@link VisitorContext} for the page. Otherwise,\n * the page's regions are traversed automatically.\n *\n * @param page - The page to visit.\n * @returns The transformed page, or `null` to exclude it.\n */\n visitPage(page: ShopperExperience.schemas['Page']): ShopperExperience.schemas['Page'] | null {\n const pageContext = new VisitorContext({\n type: 'page',\n visitor: this.context.visitor,\n page,\n parentComponent: undefined,\n parentRegion: undefined,\n node: page,\n });\n\n if (this.context.visitor.visitPage) {\n return this.context.visitor.visitPage(pageContext);\n } else if (page.regions) {\n const newPage = {\n ...page,\n regions: pageContext.visitRegions(page.regions),\n };\n\n return newPage;\n }\n\n return page;\n }\n\n private toChildContext<TType extends VisitorContextType>(\n type: TType,\n node: InferNodeFromType<TType>\n ): VisitorContext<InferNodeFromType<TType>> {\n VisitorContextError.assert(this.context.type, type);\n\n if (type === 'region') {\n return new VisitorContext({\n type: 'region',\n visitor: this.context.visitor,\n page: this.page,\n node,\n parentComponent: this.node as ShopperExperience.schemas['Component'],\n parentRegion: this.parentRegion,\n });\n }\n\n return new VisitorContext({\n type: 'component',\n visitor: this.context.visitor,\n page: this.page,\n node,\n parentComponent: this.parentComponent,\n parentRegion: this.node as ShopperExperience.schemas['Region'],\n });\n }\n}\n\nclass RootVisitorContext extends VisitorContext<null> {\n constructor(visitor: PageVisitor) {\n super({\n node: null,\n type: 'root',\n visitor,\n });\n }\n}\n\n/**\n * Visitor interface for traversing and transforming a Page Designer page tree.\n * Implement any combination of visit methods to intercept pages, regions, or\n * components during traversal. Return `null` from `visitRegion` or\n * `visitComponent` to remove that element from the tree.\n */\nexport interface PageVisitor {\n visitPage?(context: VisitorContext<ShopperExperience.schemas['Page']>): ShopperExperience.schemas['Page'];\n visitRegion?(\n context: VisitorContext<ShopperExperience.schemas['Region']>\n ): ShopperExperience.schemas['Region'] | null;\n visitComponent?(\n component: VisitorContext<ShopperExperience.schemas['Component']>\n ): ShopperExperience.schemas['Component'] | null;\n}\n\n/**\n * Traverses a page tree using the visitor pattern, applying the visitor's\n * callbacks to the page, its regions, and their nested components. This is\n * the top-level entry point for page tree transformation.\n *\n * When a visitor handler is defined, it receives a {@link VisitorContext} and\n * is responsible for traversing into children using the context's traversal\n * methods (`visitRegions`, `visitComponents`). If the handler does not call\n * these methods, children will not be visited. When no handler is defined for\n * a node type, children are traversed automatically.\n *\n * Returning `null` from a `visitRegion` or `visitComponent` callback removes\n * that element and its children from the resulting tree.\n *\n * @param page - The page to traverse.\n * @param visitor - The visitor with callbacks to apply at each tree node.\n * @returns A new page with visitor transformations applied, or `null`.\n *\n * @example\n * ```ts\n * import { transformPage } from '@salesforce/storefront-next-runtime/design/data';\n *\n * const page = { id: 'homepage', typeId: 'storePage', regions: [\n * { id: 'header', components: [\n * { id: 'hero-banner', typeId: 'commerce_assets.heroBanner', regions: [] },\n * { id: 'promo-tile', typeId: 'commerce_assets.promoTile', regions: [] },\n * ]},\n * ]};\n *\n * // When only visitComponent is defined, regions are traversed automatically.\n * // The handler receives a VisitorContext — use context.node to access the component.\n * transformPage(page, {\n * visitComponent(context) {\n * console.log(`Component: ${context.node.typeId} in region ${context.parentRegion?.id}`);\n * return context.node;\n * },\n * });\n *\n * // When visitRegion is defined, the handler must traverse into children explicitly.\n * // Without calling context.visitComponents(), components inside the region are skipped.\n * transformPage(page, {\n * visitRegion(context) {\n * console.log(`Entering region: ${context.node.id}`);\n * const components = context.visitComponents(context.node.components);\n * return { ...context.node, components };\n * },\n * visitComponent(context) {\n * console.log(` Component: ${context.node.typeId}`);\n * return context.node;\n * },\n * });\n * ```\n */\nexport function transformPage(\n page: ShopperExperience.schemas['Page'],\n visitor: PageVisitor\n): ShopperExperience.schemas['Page'] | null {\n return new RootVisitorContext(visitor).visitPage(page);\n}\n\n/**\n * Applies the visitor to a single component. If the visitor's `visitComponent`\n * handler is defined, it receives a {@link VisitorContext} and is responsible\n * for traversing into the component's nested regions using `context.visitRegions()`.\n * If no `visitComponent` handler is defined, nested regions are traversed\n * automatically. Returns `null` to exclude the component from the result.\n *\n * @param component - The component to transform.\n * @param visitor - The visitor with callbacks.\n * @returns The transformed component, or `null` to exclude it.\n *\n * @example\n * ```ts\n * import { transformComponent } from '@salesforce/storefront-next-runtime/design/data';\n *\n * // Replace the image URL in a hero banner component and traverse its nested regions\n * const heroBanner = {\n * id: 'hero-1',\n * typeId: 'commerce_assets.heroBanner',\n * data: { imageUrl: '/images/summer-sale.jpg' },\n * regions: [{ id: 'banner-content', components: [] }],\n * };\n *\n * const result = transformComponent(heroBanner, {\n * visitComponent(context) {\n * // Traverse into nested regions using the context API\n * const regions = context.visitRegions(context.node.regions);\n *\n * if (context.node.typeId === 'commerce_assets.heroBanner') {\n * return { ...context.node, regions, data: { ...context.node.data, imageUrl: '/images/winter-sale.jpg' } };\n * }\n * return { ...context.node, regions };\n * },\n * });\n * ```\n */\nexport function transformComponent(\n component: ShopperExperience.schemas['Component'],\n visitor: PageVisitor\n): ShopperExperience.schemas['Component'] | null {\n return new RootVisitorContext(visitor).visitComponent(component);\n}\n\n/**\n * Applies the visitor to a single region. If the visitor's `visitRegion`\n * handler is defined, it receives a {@link VisitorContext} and is responsible\n * for traversing into the region's child components using `context.visitComponents()`.\n * If no `visitRegion` handler is defined, child components are traversed\n * automatically. Returns `null` to exclude the region and all its children\n * from the result.\n *\n * @param region - The region to transform.\n * @param visitor - The visitor with callbacks.\n * @returns The transformed region, or `null` to exclude it.\n *\n * @example\n * ```ts\n * import { transformRegion } from '@salesforce/storefront-next-runtime/design/data';\n *\n * // Filter empty regions and traverse into non-empty ones\n * const emptyRegion = { id: 'sidebar', components: [] };\n * const populatedRegion = { id: 'main', components: [\n * { id: 'product-grid', typeId: 'commerce_assets.productGrid', regions: [] },\n * ]};\n *\n * const visitor = {\n * visitRegion(context) {\n * if (!context.node.components?.length) {\n * return null; // Remove empty regions\n * }\n * // Traverse into child components using the context API\n * const components = context.visitComponents(context.node.components);\n * return { ...context.node, components };\n * },\n * };\n *\n * transformRegion(emptyRegion, visitor); // => null (removed)\n * transformRegion(populatedRegion, visitor); // => { id: 'main', components: [...] }\n * ```\n */\nexport function transformRegion(\n region: ShopperExperience.schemas['Region'],\n visitor: PageVisitor\n): ShopperExperience.schemas['Region'] | null {\n return new RootVisitorContext(visitor).visitRegion(region);\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { QualifierContext, ResolvedDataBinding } from '../types';\nimport type { ShopperExperience } from '@/scapi-client/types';\n\n/**\n * Data binding metadata attached to a component instance. Stored in the\n * component's `custom.dataBinding` field by ECOM when the author binds a\n * data source to the component in Page Designer.\n */\nexport interface ComponentDataBinding {\n /** Maps attribute names to expression strings (e.g. `\"content_asset.body\"`). */\n expressions: Record<string, string>;\n /** The data contexts bound to this component, identifying the records to resolve against. */\n contexts: DataBindingContext[];\n}\n\n/**\n * A data context reference on a component instance, identifying a specific\n * record from a data provider.\n */\nexport interface DataBindingContext {\n /** The data provider type (e.g. `\"content_asset\"`). */\n type: string;\n /** The record identifier (e.g. a content asset UUID). */\n id: string;\n}\n\n/**\n * Pattern matching bare expressions: `type.field`.\n */\nconst BARE_EXPRESSION_PATTERN = /^(\\w+)\\.(\\w+)$/;\n\n/**\n * Parses a binding expression string into its provider type and field name.\n * Supports the bare `type.field` format.\n *\n * @param expression - The expression string to parse.\n * @returns The parsed type and field, or `null` if the expression is invalid.\n *\n * @example\n * ```ts\n * parseExpression('content_asset.title'); // { type: 'content_asset', field: 'title' }\n * parseExpression('invalid'); // null\n * ```\n */\nexport function parseExpression(expression: string): { type: string; field: string } | null {\n const match = expression.trim().match(BARE_EXPRESSION_PATTERN);\n if (match) {\n return { type: match[1], field: match[2] };\n }\n\n return null;\n}\n\n/**\n * Resolves a single binding expression against the component's data contexts\n * and the resolved data bindings from context resolution.\n *\n * Returns the resolved field value, or an empty string if the expression is\n * invalid, the matching context or record is not found, or the field does not\n * exist on the resolved record.\n *\n * @param expression - The expression string (e.g. `\"content_asset.body\"`).\n * @param contexts - The component's data binding contexts.\n * @param dataBindings - The resolved data bindings from {@link QualifierContext}.\n * @returns The resolved value, or `''` if resolution fails.\n */\nexport function resolveExpression(\n expression: string,\n contexts: DataBindingContext[],\n dataBindings: NonNullable<QualifierContext['dataBindings']>\n): unknown {\n const parsed = parseExpression(expression);\n if (!parsed) return '';\n\n const context = contexts.find((c) => c.type === parsed.type);\n if (!context) return '';\n\n const record: ResolvedDataBinding | undefined = dataBindings[context.type]?.[context.id];\n if (!record) return '';\n\n return record[parsed.field] ?? '';\n}\n\n/**\n * Extracts the {@link ComponentDataBinding} metadata from a component's\n * `custom` field. Returns `undefined` if the component has no data binding\n * configuration.\n */\nfunction getDataBinding(component: ShopperExperience.schemas['Component']): ComponentDataBinding | undefined {\n const custom = component.custom as Record<string, unknown> | undefined;\n return custom?.dataBinding as ComponentDataBinding | undefined;\n}\n\n/**\n * Resolves data binding expressions for a single component. Replaces attribute\n * values in the component's `data` with the resolved values from context\n * resolution. Attributes without a matching expression are preserved as-is.\n * When an expression cannot be resolved, the attribute value is set to an\n * empty string.\n *\n * Returns the component unchanged if it has no data binding metadata or if\n * `dataBindings` is `undefined`.\n *\n * @param component - The component to resolve data bindings for.\n * @param dataBindings - The resolved data bindings from {@link QualifierContext}, or `undefined` if no bindings were resolved.\n * @returns The component with resolved attribute values, or the original component if no bindings apply.\n *\n * @example\n * ```ts\n * import { resolveComponentDataBindings } from '@salesforce/storefront-next-runtime/design/data';\n *\n * const component = {\n * id: 'banner',\n * typeId: 'commerce_assets.contentBanner',\n * data: { heading: 'Fallback Title', body: 'Fallback Body' },\n * custom: {\n * dataBinding: {\n * expressions: {\n * heading: 'content_asset.title',\n * body: 'content_asset.body',\n * },\n * contexts: [{ type: 'content_asset', id: 'winter-sale-uuid' }],\n * },\n * },\n * regions: [],\n * };\n *\n * const dataBindings = {\n * content_asset: {\n * 'winter-sale-uuid': {\n * title: 'Winter Sale',\n * body: '<div>Free Shipping on all orders!</div>',\n * },\n * },\n * };\n *\n * const resolved = resolveComponentDataBindings(component, dataBindings);\n * // resolved.data.heading === 'Winter Sale'\n * // resolved.data.body === '<div>Free Shipping on all orders!</div>'\n * ```\n */\nexport function resolveComponentDataBindings(\n component: ShopperExperience.schemas['Component'],\n dataBindings: QualifierContext['dataBindings']\n): ShopperExperience.schemas['Component'] {\n if (!dataBindings) {\n return component;\n }\n\n const binding = getDataBinding(component);\n if (!binding?.contexts?.length) return component;\n\n const expressionEntries = Object.entries(binding.expressions ?? {});\n if (expressionEntries.length === 0) return component;\n\n const resolvedData: Record<string, unknown> = {\n ...(component.data as Record<string, unknown> | undefined),\n };\n\n for (const [attrName, expression] of expressionEntries) {\n resolvedData[attrName] = resolveExpression(expression, binding.contexts, dataBindings);\n }\n\n return {\n ...component,\n data: resolvedData as typeof component.data,\n };\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { QualifierContext, VisibilityRuleDef } from './types';\n\n/**\n * Evaluates a visibility rule against a shopper's qualifier context.\n *\n * Campaign-based and non-campaign rules are **mutually exclusive** paths,\n * matching the server's `VisibilityDefinition.isVisible()` logic:\n *\n * - **Campaign-based rule** (has `campaignQualifiers`): only the campaign\n * qualifiers are checked. Schedule and customer-group fields are ignored\n * because the campaign qualification already incorporates those checks\n * server-side.\n * - **Non-campaign rule**: schedule AND customer groups are checked. All\n * specified conditions must pass.\n *\n * When no context is provided and the rule requires campaign or customer group\n * checks, those checks will fail (returning `false`). Schedule checks do not\n * require context and are evaluated against `Date.now()`.\n *\n * @param rule - The visibility rule to evaluate.\n * @param context - The shopper's active qualifiers, or `null`/`undefined` if not yet resolved.\n * @returns `true` if the rule's conditions pass, `false` otherwise.\n *\n * @example\n * ```ts\n * import { validateRule } from '@salesforce/storefront-next-runtime/design/data';\n *\n * // Campaign-based rule — only campaign qualifiers are evaluated\n * const campaignRule = {\n * campaignQualifiers: [{ campaignId: 'holiday-sale-2026', promotionId: 'free-shipping' }],\n * };\n *\n * // Non-campaign rule — schedule AND customer groups are evaluated\n * const segmentRule = {\n * customerGroups: ['vip-customers'],\n * schedule: {\n * start: new Date('2026-12-01').toISOString(),\n * end: new Date('2026-12-31').toISOString(),\n * },\n * };\n * ```\n */\nexport function validateRule(rule: VisibilityRuleDef, context?: QualifierContext | null): boolean {\n // Campaign-based rules and non-campaign rules are mutually exclusive\n // paths, mirroring the server's if/else-if branching.\n if (rule.campaignQualifiers) {\n for (const campaignQualifier of rule.campaignQualifiers) {\n if (!context?.campaignQualifiers[campaignQualifier.campaignId]?.[campaignQualifier.promotionId]) {\n return false;\n }\n }\n } else {\n if (!rule.isActiveForLocale) {\n return false;\n }\n\n // Rule schedule times are in ISO 8601 format, so we need to convert them to milliseconds\n if (rule.schedule) {\n const now = Date.now();\n\n if (rule.schedule.start) {\n const startTimeInMillis = new Date(rule.schedule.start).getTime();\n\n // If the start time is invalid, the rule fails\n if (Number.isNaN(startTimeInMillis) || startTimeInMillis >= now) {\n return false;\n }\n }\n\n if (rule.schedule.end) {\n const endTimeInMillis = new Date(rule.schedule.end).getTime();\n\n // If the end time is invalid, the rule fails\n if (Number.isNaN(endTimeInMillis) || endTimeInMillis <= now) {\n return false;\n }\n }\n }\n\n if (rule.customerGroups) {\n for (const customerGroup of rule.customerGroups) {\n if (!context?.customerGroups[customerGroup]) {\n return false;\n }\n }\n }\n }\n\n return true;\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { transformPage } from './transform';\nimport { resolveComponentDataBindings } from './resolve-data-bindings';\nimport { validateRule } from '../validate-rule';\nimport type { QualifierContext, PageManifest } from '../types';\nimport type { ShopperExperience } from '@/scapi-client/types';\n\n/**\n * Context required for page processing. Contains the shopper's runtime\n * qualifiers and the component-level visibility rules from the page manifest.\n */\nexport interface PageProcessorContext {\n /** The shopper's active qualifiers (campaigns, customer groups), or `null` if not resolved. */\n qualifiers: QualifierContext | null;\n /** Component visibility rule definitions extracted from the page layout. */\n componentInfo: PageManifest['componentInfo'];\n}\n\n/**\n * Filters a page's components based on their visibility rules and resolves\n * data binding expressions in a single traversal. Traverses the page tree\n * using the visitor pattern and:\n *\n * 1. Removes any component whose visibility rules do not pass against the\n * shopper's qualifier context.\n * 2. Resolves data binding expressions in each surviving component's `data`\n * attributes using the resolved data bindings from context resolution.\n *\n * A component is visible if **any** of its visibility rules pass (OR logic).\n * If a component has rules and none of them pass, it is removed. Components\n * without rules are always included.\n *\n * @param page - The page to process.\n * @param context - The processing context with qualifier data, visibility rules, and resolved data bindings.\n * @returns A new page with invisible components filtered out and data binding expressions resolved.\n *\n * @example\n * ```ts\n * import { processPage } from '@salesforce/storefront-next-runtime/design/data';\n *\n * const page = {\n * id: 'homepage',\n * typeId: 'storePage',\n * regions: [{\n * id: 'main',\n * components: [\n * { id: 'public-banner', typeId: 'commerce_assets.heroBanner', regions: [] },\n * { id: 'loyalty-offer', typeId: 'commerce_assets.promoTile', regions: [] },\n * ],\n * }],\n * };\n *\n * // The \"loyalty-offer\" component requires the shopper to be in \"loyalty-members\"\n * const componentInfo = {\n * 'public-banner': { visibilityRules: [], hasVisibilityRules: false },\n * 'loyalty-offer': {\n * visibilityRules: [{ customerGroups: ['loyalty-members'] }],\n * hasVisibilityRules: true,\n * },\n * };\n *\n * // Guest shopper — not in any customer group\n * const filtered = processPage(page, {\n * qualifiers: { customerGroups: {}, campaignQualifiers: {} },\n * componentInfo,\n * });\n * // filtered.regions[0].components has only \"public-banner\"\n * // \"loyalty-offer\" was removed because the shopper isn't a loyalty member\n * ```\n */\nexport function processPage(\n page: ShopperExperience.schemas['Page'],\n processorContext: PageProcessorContext\n): ShopperExperience.schemas['Page'] {\n return transformPage(page, {\n visitComponent(ctx) {\n const componentInfo = processorContext.componentInfo[ctx.node.id];\n const visibilityRules = componentInfo?.visibilityRules ?? [];\n\n // Visibility rules use OR logic: the component is visible\n // if ANY rule passes. Only remove it when it has its own\n // rules and none of them pass.\n if (visibilityRules.length > 0) {\n const anyRulePassed = visibilityRules.some((rule) => validateRule(rule, processorContext.qualifiers));\n\n if (!anyRulePassed) {\n return null;\n }\n }\n\n const resolved = resolveComponentDataBindings(ctx.node, processorContext.qualifiers?.dataBindings);\n\n // If this component and any of it's children don't have visibility rules or data bindings,\n // we can skip processing them and just return the node.\n // If we can't determine any component info, we can't assume any descendants don't have rules or data bindings.\n if (\n !componentInfo ||\n componentInfo.hasAnyDescendantVisibilityRules ||\n componentInfo.hasAnyDescendantDataBindings\n ) {\n return {\n ...resolved,\n regions: ctx.visitRegions(ctx.node.regions),\n };\n }\n\n return resolved;\n },\n }) as ShopperExperience.schemas['Page'];\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport class RequiredError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RequiredError';\n }\n\n static assert<TValue>(\n value: TValue,\n message: string,\n isEmpty: (value: TValue) => boolean = (v) => v == null\n ): asserts value is NonNullable<TValue> {\n if (isEmpty(value)) {\n throw new RequiredError(message);\n }\n }\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { SiteManifest } from '../types';\n\n/**\n * The result of resolving an identifier through a content assignment resolver.\n * Contains the object type, aspect type, and ordered list of keys to search\n * in the site manifest's content assignments.\n */\nexport interface ResolvedContentAssignmentLookup {\n /** The type of commerce object (e.g. `'product'`, `'category'`). */\n objectType: string;\n /** Ordered list of object IDs to search in the site manifest's content assignments. */\n keys: string[];\n}\n\n/**\n * A function that converts an identifier key (e.g., a product or category ID)\n * into a {@link ResolvedContentAssignmentLookup} describing where to search\n * in the site manifest for the assigned page ID.\n */\nexport type ContentAssignmentResolver = (key: string, manifest?: SiteManifest) => ResolvedContentAssignmentLookup;\n\n/**\n * Registry of content assignment resolvers keyed by {@link IdentifierType}.\n * Each resolver knows how to convert its identifier type into a set of lookup\n * keys for the site manifest.\n *\n * Built-in resolvers:\n * - **`'product'`** — Maps a product ID to a single PDP lookup key.\n * - **`'category'`** — Maps a category ID to an ordered list of keys that\n * traverses the category hierarchy from child to root, enabling inherited\n * page assignments.\n *\n * The `'page'` identifier type has no resolver — page IDs are used directly.\n *\n * @example\n * ```ts\n * import { ContentAssignmentResolvers } from '@salesforce/storefront-next-runtime/design/data';\n *\n * // Resolve a product identifier for PDP lookup\n * const productResolver = ContentAssignmentResolvers.get('product');\n * productResolver('nike-air-max-90');\n * // => { objectType: 'product', aspectType: 'pdp', keys: ['nike-air-max-90'] }\n *\n * // Resolve a category identifier — traverses hierarchy to find inherited assignments\n * const categoryResolver = ContentAssignmentResolvers.get('category');\n * const siteManifest = {\n * categories: {\n * 'mens-running-shoes': { name: 'Running Shoes', parentCategory: 'mens-shoes' },\n * 'mens-shoes': { name: \"Men's Shoes\", parentCategory: 'mens' },\n * 'mens': { name: 'Men' },\n * },\n * contentObjectAssignments: {},\n * };\n * categoryResolver('mens-running-shoes', siteManifest);\n * // => { objectType: 'category', aspectType: 'plp', keys: ['mens-running-shoes', 'mens-shoes', 'mens'] }\n * ```\n */\nexport const ContentAssignmentResolvers = new Map<string, ContentAssignmentResolver>([\n [\n 'product',\n (key) => ({\n objectType: 'product',\n keys: [key],\n }),\n ],\n [\n 'category',\n (key, manifest) => {\n const keys = [];\n const visited = new Set<string>();\n\n let currentCategoryId: string | undefined = key;\n\n while (currentCategoryId && !visited.has(currentCategoryId)) {\n visited.add(currentCategoryId);\n keys.push(currentCategoryId);\n currentCategoryId = manifest?.categories[currentCategoryId]?.parentCategory;\n }\n\n return {\n objectType: 'category',\n keys,\n };\n },\n ],\n]);\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { SiteManifest, IdentifierType } from '../types';\nimport { ContentAssignmentResolvers } from './content-assignment-resolvers';\n\n/**\n * Converts a product or category identifier into a page ID by looking up\n * content assignments in the site manifest. For categories, the lookup\n * traverses the category hierarchy from the given category up to the root,\n * returning the first matching assignment.\n *\n * Returns `null` if no content assignment is found for the identifier or if\n * the identifier type has no registered resolver.\n *\n * @param options - The resolution options.\n * @param options.id - The identifier to resolve (product ID, category ID, or page ID).\n * @param options.identifierType - The type of identifier: `'product'`, `'category'`, or `'page'`.\n * @param options.siteManifest - The site manifest containing content assignments and category hierarchy.\n * @returns The resolved page ID, or `null` if no assignment was found.\n *\n * @example\n * ```ts\n * import { resolveDynamicPageId } from '@salesforce/storefront-next-runtime/design/data';\n *\n * const siteManifest = {\n * contentObjectAssignments: {\n * plp: {\n * category: {\n * 'mens-shoes': {\n * lookupMode: 'category-explicit',\n * contentId: 'page-mens-shoes-plp',\n * },\n * },\n * },\n * },\n * categories: {\n * 'mens-running-shoes': { name: 'Running Shoes', parentCategory: 'mens-shoes' },\n * 'mens-shoes': { name: \"Men's Shoes\" },\n * },\n * };\n *\n * // Direct match\n * resolveDynamicPageId({ id: 'mens-shoes', identifierType: 'category', siteManifest });\n * // => 'page-mens-shoes-plp'\n *\n * // Inherited from parent category\n * resolveDynamicPageId({ id: 'mens-running-shoes', identifierType: 'category', siteManifest });\n * // => 'page-mens-shoes-plp' (found via parent traversal)\n *\n * // No assignment found\n * resolveDynamicPageId({ id: 'womens-shoes', identifierType: 'category', siteManifest });\n * // => null\n * ```\n */\nexport function resolveDynamicPageId<TIdentifier extends IdentifierType = IdentifierType>({\n id,\n identifierType,\n siteManifest,\n aspectType,\n}: {\n id: string;\n identifierType: TIdentifier;\n aspectType: string;\n siteManifest?: SiteManifest;\n}): string | null {\n const resolvedContentAssignmentLookup = ContentAssignmentResolvers.get(identifierType)?.(id, siteManifest);\n\n if (resolvedContentAssignmentLookup) {\n for (const key of resolvedContentAssignmentLookup.keys) {\n const contentAssignment =\n siteManifest?.contentObjectAssignments?.[aspectType]?.[resolvedContentAssignmentLookup.objectType]?.[\n key\n ];\n\n if (contentAssignment) {\n return contentAssignment.contentId;\n }\n }\n }\n\n return null;\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { PageManifest, QualifierContext, VariationEntry } from '../types';\nimport { validateRule } from '../validate-rule';\n\n/**\n * Selects the appropriate page variation from a manifest by evaluating each\n * variation's visibility rule in order. Returns the first variation whose rule\n * passes, or falls back to the manifest's default variation.\n *\n * The qualifier context is resolved lazily — the `contextResolver` is only\n * called when a variation's `ruleRequiresContext` flag is `true`, and only\n * once (the result is cached for subsequent variations).\n *\n * @param manifest - The page manifest containing all variations.\n * @param options - Resolution options.\n * @param options.contextResolver - Optional async function that returns the shopper's qualifier context. Only called if a variation's rule needs it.\n * @returns The selected variation entry and resolved context, or `null` if no variation (including default) exists.\n *\n * @example\n * ```ts\n * import { getPageFromManifest } from '@salesforce/storefront-next-runtime/design/data';\n *\n * const manifest = {\n * pageId: 'homepage',\n * locale: 'en-US',\n * context: { campaignQualifiers: [], customerGroups: ['vip-customers'], dataBindings: [] },\n * variationOrder: ['vip-homepage', 'holiday-homepage'],\n * variations: {\n * 'vip-homepage': {\n * ruleRequiresContext: true,\n * pageRequiresContext: false,\n * visibilityRule: { customerGroups: ['vip-customers'] },\n * page: { id: 'homepage', typeId: 'storePage', regions: [] },\n * },\n * 'holiday-homepage': {\n * ruleRequiresContext: false,\n * pageRequiresContext: false,\n * visibilityRule: {\n * schedule: {\n * start: new Date('2026-12-01').getTime(),\n * end: new Date('2026-12-31').getTime(),\n * },\n * },\n * page: { id: 'homepage', typeId: 'storePage', regions: [] },\n * },\n * 'default-homepage': {\n * ruleRequiresContext: false,\n * pageRequiresContext: false,\n * page: { id: 'homepage', typeId: 'storePage', regions: [] },\n * },\n * },\n * defaultVariation: 'default-homepage',\n * visibilityRules: {},\n * };\n *\n * // VIP shopper — matches first variation\n * const result = await getPageFromManifest(manifest, {\n * contextResolver: async () => ({\n * customerGroups: { 'vip-customers': true },\n * campaignQualifiers: {},\n * }),\n * });\n * // result.entry === manifest.variations['vip-homepage']\n *\n * // Non-VIP shopper outside holiday window — falls back to default\n * const fallback = await getPageFromManifest(manifest, {\n * contextResolver: async () => ({\n * customerGroups: {},\n * campaignQualifiers: {},\n * }),\n * });\n * // fallback.entry === manifest.variations['default-homepage']\n * ```\n */\nexport async function getPageFromManifest(\n manifest: PageManifest,\n {\n contextResolver,\n }: {\n contextResolver?: () => Promise<QualifierContext>;\n }\n): Promise<{\n entry: VariationEntry;\n context: QualifierContext | null;\n} | null> {\n let context: QualifierContext | null = null;\n let resolvedVariation: VariationEntry | null = null;\n\n for (const variationId of manifest.variationOrder) {\n const variation = manifest.variations[variationId];\n\n if (variation?.ruleRequiresContext && !context) {\n context = (await contextResolver?.()) ?? null;\n }\n\n if (!variation?.visibilityRule || validateRule(variation.visibilityRule, context)) {\n resolvedVariation = variation;\n break;\n }\n }\n\n if (!resolvedVariation) {\n resolvedVariation = manifest.variations[manifest.defaultVariation];\n }\n\n if (!resolvedVariation) {\n return null;\n }\n\n return {\n entry: resolvedVariation,\n context,\n };\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { IdentifierType, ManifestStorage, QualifierContext } from '../types';\nimport type { ShopperExperience } from '@/scapi-client/types';\nimport { ContentAssignmentResolvers } from '../manifest/content-assignment-resolvers';\nimport { resolveDynamicPageId } from '../manifest/resolve-dynamic-page-id';\nimport { getPageFromManifest } from '../manifest/get-page';\nimport { processPage } from './process-page';\nimport { RequiredError } from '../errors/required';\n\n/**\n * Main entry point for the page resolution pipeline. Orchestrates the full flow:\n *\n * 1. **Resolve dynamic page ID** — For product/category identifiers, looks up\n * the assigned page ID via content assignments in the site manifest.\n * 2. **Fetch page manifest** — Loads all variations for the resolved page.\n * 3. **Select variation** — Evaluates visibility rules to pick the right variation.\n * 4. **Load qualifier context** — Lazily fetches the shopper's context only if needed.\n * 5. **Process page** — Filters out components that fail visibility rules.\n *\n * Returns `null` if the page ID cannot be resolved, the manifest doesn't exist,\n * or no variation is available.\n *\n * @param options - The resolution options.\n * @param options.id - The identifier to resolve (product ID, category ID, or page ID).\n * @param options.identifierType - The type of identifier: `'product'`, `'category'`, or `'page'`.\n * @param options.locale - The locale to resolve the page for (e.g. `\"en-US\"`).\n * @param options.manifestStorage - Storage implementation for fetching manifests.\n * @param options.contextResolver - Optional async function that returns the shopper's qualifier context. Only called if a visibility rule needs it.\n * @param options.aspectType - The aspect type to resolve the page for when the identifier type is `'product'` or `'category'`.\n * @returns The fully resolved and filtered page, or `null`.\n *\n * @example\n * ```ts\n * import { resolvePage } from '@salesforce/storefront-next-runtime/design/data';\n *\n * // Resolve the PDP page for a specific product with an active holiday campaign\n * const page = await resolvePage({\n * id: 'nike-air-max-90',\n * identifierType: 'product',\n * aspectType: 'pdp',\n * locale: 'en-US',\n * manifestStorage: {\n * async getPageManifest(id, locale) {\n * // Fetch from CDN, filesystem, or database\n * return fetchManifest(`/manifests/${locale}/${id}.json`);\n * },\n * async getSiteManifest(locale) {\n * return fetchManifest(`/manifests/${locale}/site.json`);\n * },\n * },\n * contextResolver: async () => ({\n * customerGroups: { 'vip-customers': true },\n * campaignQualifiers: {\n * 'holiday-sale-2026': { 'free-shipping': true },\n * },\n * }),\n * });\n *\n * if (page) {\n * // page.regions contains only components visible to this VIP shopper\n * // during the holiday sale campaign\n * renderPage(page);\n * }\n * ```\n */\nexport async function resolvePage({\n id,\n identifierType,\n aspectType,\n locale,\n manifestStorage,\n contextResolver,\n}: {\n id: string;\n identifierType: IdentifierType;\n aspectType?: string;\n locale: string;\n manifestStorage: ManifestStorage;\n contextResolver?: () => Promise<QualifierContext>;\n}): Promise<ShopperExperience.schemas['Page'] | null> {\n let resolvedId: string | null = null;\n\n if (ContentAssignmentResolvers.has(identifierType)) {\n const siteManifest = await manifestStorage.getSiteManifest(locale);\n\n RequiredError.assert(aspectType, `Aspect type is required for identifier type ${identifierType}`, (v) => !v);\n\n resolvedId = resolveDynamicPageId({ id, identifierType, aspectType, siteManifest });\n } else {\n resolvedId = id;\n }\n\n if (!resolvedId) {\n return null;\n }\n\n const pageManifest = await manifestStorage.getPageManifest(resolvedId, locale);\n\n if (!pageManifest) {\n return null;\n }\n\n const pageResults = await getPageFromManifest(pageManifest, {\n contextResolver,\n });\n\n if (!pageResults) {\n return null;\n }\n\n let context: QualifierContext | null = null;\n\n if (pageResults.entry.pageRequiresContext) {\n context = pageResults.context ?? (await contextResolver?.()) ?? null;\n }\n\n return processPage(pageResults.entry.page, {\n qualifiers: context,\n componentInfo: pageManifest.componentInfo,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"design-data.js","names":["context: {\n /** The current node being visited. */\n node: TNode;\n /** The node type */\n type: VisitorContextType;\n /** The visitor being used to transform the page tree. */\n visitor: PageVisitor;\n /** The root page being traversed. */\n page?: ShopperExperience.schemas['Page'];\n /** The parent region of the current node, if traversing within a region. */\n parentRegion?: ShopperExperience.schemas['Region'];\n /** The parent component of the current node, if traversing within a component's nested regions. */\n parentComponent?: ShopperExperience.schemas['Component'];\n }","record: ResolvedDataBinding | undefined","resolvedData: Record<string, unknown>","node: ShopperExperience.schemas['Component']","currentCategoryId: string | undefined","context: QualifierContext | null","resolvedVariation: VariationEntry | null","resolvedId: string | null","context: QualifierContext | null"],"sources":["../src/design/data/errors/visitor-context-error.ts","../src/design/data/page/transform.ts","../src/design/data/page/resolve-data-bindings.ts","../src/design/data/validate-rule.ts","../src/design/data/page/process-page.ts","../src/design/data/errors/required.ts","../src/design/data/manifest/content-assignment-resolvers.ts","../src/design/data/manifest/resolve-dynamic-page-id.ts","../src/design/data/manifest/get-page.ts","../src/design/data/page/resolve-page.ts"],"sourcesContent":["/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { VisitorContextType } from '../types';\n\nexport class VisitorContextError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'VisitorContextError';\n }\n\n static assert(parentType: VisitorContextType, childType: VisitorContextType) {\n if (\n (parentType === 'component' && childType !== 'region') ||\n (parentType === 'page' && childType !== 'region') ||\n (parentType === 'region' && childType !== 'component')\n ) {\n throw new VisitorContextError(\n `Invalid child context type ${childType} for parent context type ${parentType}`\n );\n }\n }\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { ShopperExperience } from '@/scapi-client/types';\nimport { VisitorContextError } from '../errors/visitor-context-error';\nimport type { InferNodeFromType, VisitorContextType } from '../types';\n\n/**\n * Context object passed to {@link PageVisitor} handler methods during page tree\n * traversal. Provides access to the current node via {@link node}, the tree\n * position via {@link page}, {@link parentRegion}, and {@link parentComponent},\n * and traversal methods ({@link visitRegions}, {@link visitComponents}) for\n * continuing into child nodes.\n *\n * When a visitor handler is defined, the handler is responsible for traversing\n * into children by calling the appropriate context method. If the handler does\n * not call these methods, children will not be visited.\n */\nexport class VisitorContext<TNode> {\n constructor(\n private readonly context: {\n /** The current node being visited. */\n node: TNode;\n /** The node type */\n type: VisitorContextType;\n /** The visitor being used to transform the page tree. */\n visitor: PageVisitor;\n /** The root page being traversed. */\n page?: ShopperExperience.schemas['Page'];\n /** The parent region of the current node, if traversing within a region. */\n parentRegion?: ShopperExperience.schemas['Region'];\n /** The parent component of the current node, if traversing within a component's nested regions. */\n parentComponent?: ShopperExperience.schemas['Component'];\n }\n ) {}\n\n get type(): VisitorContextType {\n return this.context.type;\n }\n\n /**\n * The current node being visited.\n */\n get node(): TNode {\n return this.context.node;\n }\n\n /**\n * The root page being traversed.\n */\n get page(): ShopperExperience.schemas['Page'] | undefined {\n return this.context.page;\n }\n\n /**\n * The parent region of the current node, if traversing within a region.\n */\n get parentRegion(): ShopperExperience.schemas['Region'] | undefined {\n return this.context.parentRegion;\n }\n\n /**\n * The parent component of the current node, if traversing within a component's nested regions.\n */\n get parentComponent(): ShopperExperience.schemas['Component'] | undefined {\n return this.context.parentComponent;\n }\n\n /**\n * Traverses an array of regions, invoking the visitor's `visitRegion` handler\n * on each one. Regions for which the handler returns `null` are excluded from\n * the result. Call this from within a `visitPage` or `visitComponent` handler\n * to continue traversal into child regions.\n *\n * @param regions - The regions to traverse.\n * @returns The filtered array of transformed regions.\n *\n * @example\n * ```ts\n * transformPage(page, {\n * visitPage(context) {\n * // Traverse into regions explicitly\n * const regions = context.visitRegions(context.node.regions);\n * return { ...context.node, regions };\n * },\n * });\n * ```\n */\n visitRegions(regions: ShopperExperience.schemas['Region'][] = []): ShopperExperience.schemas['Region'][] {\n const newRegions = [];\n\n for (const region of regions) {\n const newRegion = this.visitRegion(region);\n\n if (newRegion) {\n newRegions.push(newRegion);\n }\n }\n\n return newRegions;\n }\n\n /**\n * Traverses a single region. If the visitor has a `visitRegion` handler, the\n * handler is called with a new {@link VisitorContext} for the region. Otherwise,\n * the region's child components are traversed automatically.\n *\n * @param region - The region to visit.\n * @returns The transformed region, or `null` to exclude it.\n */\n visitRegion(region: ShopperExperience.schemas['Region']): ShopperExperience.schemas['Region'] | null {\n const regionContext = this.toChildContext('region', region);\n\n if (this.context.visitor.visitRegion) {\n return this.context.visitor.visitRegion(regionContext);\n } else if (region.components) {\n return {\n ...region,\n components: regionContext.visitComponents(region.components),\n };\n }\n\n return region;\n }\n\n /**\n * Traverses an array of components, invoking the visitor's `visitComponent`\n * handler on each one. Components for which the handler returns `null` are\n * excluded from the result. Call this from within a `visitRegion` handler to\n * continue traversal into child components.\n *\n * @param components - The components to traverse.\n * @returns The filtered array of transformed components.\n *\n * @example\n * ```ts\n * transformPage(page, {\n * visitRegion(context) {\n * // Traverse into components explicitly\n * const components = context.visitComponents(context.node.components);\n * return { ...context.node, components };\n * },\n * });\n * ```\n */\n visitComponents(\n components: ShopperExperience.schemas['Component'][] = []\n ): ShopperExperience.schemas['Component'][] {\n const newComponents = [];\n\n for (const component of components) {\n const newComponent = this.visitComponent(component);\n\n if (newComponent) {\n newComponents.push(newComponent);\n }\n }\n\n return newComponents;\n }\n\n /**\n * Traverses a single component. If the visitor has a `visitComponent` handler,\n * the handler is called with a new {@link VisitorContext} for the component.\n * Otherwise, the component's nested regions are traversed automatically.\n *\n * @param component - The component to visit.\n * @returns The transformed component, or `null` to exclude it.\n */\n visitComponent(component: ShopperExperience.schemas['Component']): ShopperExperience.schemas['Component'] | null {\n const componentContext = this.toChildContext('component', component);\n\n if (this.context.visitor.visitComponent) {\n return this.context.visitor.visitComponent(componentContext);\n } else if (component.regions) {\n return {\n ...component,\n regions: componentContext.visitRegions(component.regions),\n };\n }\n\n return component;\n }\n\n /**\n * Traverses a single page. If the visitor has a `visitPage` handler, the\n * handler is called with a new {@link VisitorContext} for the page. Otherwise,\n * the page's regions are traversed automatically.\n *\n * @param page - The page to visit.\n * @returns The transformed page, or `null` to exclude it.\n */\n visitPage(page: ShopperExperience.schemas['Page']): ShopperExperience.schemas['Page'] | null {\n const pageContext = new VisitorContext({\n type: 'page',\n visitor: this.context.visitor,\n page,\n parentComponent: undefined,\n parentRegion: undefined,\n node: page,\n });\n\n if (this.context.visitor.visitPage) {\n return this.context.visitor.visitPage(pageContext);\n } else if (page.regions) {\n const newPage = {\n ...page,\n regions: pageContext.visitRegions(page.regions),\n };\n\n return newPage;\n }\n\n return page;\n }\n\n private toChildContext<TType extends VisitorContextType>(\n type: TType,\n node: InferNodeFromType<TType>\n ): VisitorContext<InferNodeFromType<TType>> {\n VisitorContextError.assert(this.context.type, type);\n\n if (type === 'region') {\n return new VisitorContext({\n type: 'region',\n visitor: this.context.visitor,\n page: this.page,\n node,\n parentComponent: this.node as ShopperExperience.schemas['Component'],\n parentRegion: this.parentRegion,\n });\n }\n\n return new VisitorContext({\n type: 'component',\n visitor: this.context.visitor,\n page: this.page,\n node,\n parentComponent: this.parentComponent,\n parentRegion: this.node as ShopperExperience.schemas['Region'],\n });\n }\n}\n\nclass RootVisitorContext extends VisitorContext<null> {\n constructor(visitor: PageVisitor) {\n super({\n node: null,\n type: 'root',\n visitor,\n });\n }\n}\n\n/**\n * Visitor interface for traversing and transforming a Page Designer page tree.\n * Implement any combination of visit methods to intercept pages, regions, or\n * components during traversal. Return `null` from `visitRegion` or\n * `visitComponent` to remove that element from the tree.\n */\nexport interface PageVisitor {\n visitPage?(context: VisitorContext<ShopperExperience.schemas['Page']>): ShopperExperience.schemas['Page'];\n visitRegion?(\n context: VisitorContext<ShopperExperience.schemas['Region']>\n ): ShopperExperience.schemas['Region'] | null;\n visitComponent?(\n component: VisitorContext<ShopperExperience.schemas['Component']>\n ): ShopperExperience.schemas['Component'] | null;\n}\n\n/**\n * Traverses a page tree using the visitor pattern, applying the visitor's\n * callbacks to the page, its regions, and their nested components. This is\n * the top-level entry point for page tree transformation.\n *\n * When a visitor handler is defined, it receives a {@link VisitorContext} and\n * is responsible for traversing into children using the context's traversal\n * methods (`visitRegions`, `visitComponents`). If the handler does not call\n * these methods, children will not be visited. When no handler is defined for\n * a node type, children are traversed automatically.\n *\n * Returning `null` from a `visitRegion` or `visitComponent` callback removes\n * that element and its children from the resulting tree.\n *\n * @param page - The page to traverse.\n * @param visitor - The visitor with callbacks to apply at each tree node.\n * @returns A new page with visitor transformations applied, or `null`.\n *\n * @example\n * ```ts\n * import { transformPage } from '@salesforce/storefront-next-runtime/design/data';\n *\n * const page = { id: 'homepage', typeId: 'storePage', regions: [\n * { id: 'header', components: [\n * { id: 'hero-banner', typeId: 'commerce_assets.heroBanner', regions: [] },\n * { id: 'promo-tile', typeId: 'commerce_assets.promoTile', regions: [] },\n * ]},\n * ]};\n *\n * // When only visitComponent is defined, regions are traversed automatically.\n * // The handler receives a VisitorContext — use context.node to access the component.\n * transformPage(page, {\n * visitComponent(context) {\n * console.log(`Component: ${context.node.typeId} in region ${context.parentRegion?.id}`);\n * return context.node;\n * },\n * });\n *\n * // When visitRegion is defined, the handler must traverse into children explicitly.\n * // Without calling context.visitComponents(), components inside the region are skipped.\n * transformPage(page, {\n * visitRegion(context) {\n * console.log(`Entering region: ${context.node.id}`);\n * const components = context.visitComponents(context.node.components);\n * return { ...context.node, components };\n * },\n * visitComponent(context) {\n * console.log(` Component: ${context.node.typeId}`);\n * return context.node;\n * },\n * });\n * ```\n */\nexport function transformPage(\n page: ShopperExperience.schemas['Page'],\n visitor: PageVisitor\n): ShopperExperience.schemas['Page'] | null {\n return new RootVisitorContext(visitor).visitPage(page);\n}\n\n/**\n * Applies the visitor to a single component. If the visitor's `visitComponent`\n * handler is defined, it receives a {@link VisitorContext} and is responsible\n * for traversing into the component's nested regions using `context.visitRegions()`.\n * If no `visitComponent` handler is defined, nested regions are traversed\n * automatically. Returns `null` to exclude the component from the result.\n *\n * @param component - The component to transform.\n * @param visitor - The visitor with callbacks.\n * @returns The transformed component, or `null` to exclude it.\n *\n * @example\n * ```ts\n * import { transformComponent } from '@salesforce/storefront-next-runtime/design/data';\n *\n * // Replace the image URL in a hero banner component and traverse its nested regions\n * const heroBanner = {\n * id: 'hero-1',\n * typeId: 'commerce_assets.heroBanner',\n * data: { imageUrl: '/images/summer-sale.jpg' },\n * regions: [{ id: 'banner-content', components: [] }],\n * };\n *\n * const result = transformComponent(heroBanner, {\n * visitComponent(context) {\n * // Traverse into nested regions using the context API\n * const regions = context.visitRegions(context.node.regions);\n *\n * if (context.node.typeId === 'commerce_assets.heroBanner') {\n * return { ...context.node, regions, data: { ...context.node.data, imageUrl: '/images/winter-sale.jpg' } };\n * }\n * return { ...context.node, regions };\n * },\n * });\n * ```\n */\nexport function transformComponent(\n component: ShopperExperience.schemas['Component'],\n visitor: PageVisitor\n): ShopperExperience.schemas['Component'] | null {\n return new RootVisitorContext(visitor).visitComponent(component);\n}\n\n/**\n * Applies the visitor to a single region. If the visitor's `visitRegion`\n * handler is defined, it receives a {@link VisitorContext} and is responsible\n * for traversing into the region's child components using `context.visitComponents()`.\n * If no `visitRegion` handler is defined, child components are traversed\n * automatically. Returns `null` to exclude the region and all its children\n * from the result.\n *\n * @param region - The region to transform.\n * @param visitor - The visitor with callbacks.\n * @returns The transformed region, or `null` to exclude it.\n *\n * @example\n * ```ts\n * import { transformRegion } from '@salesforce/storefront-next-runtime/design/data';\n *\n * // Filter empty regions and traverse into non-empty ones\n * const emptyRegion = { id: 'sidebar', components: [] };\n * const populatedRegion = { id: 'main', components: [\n * { id: 'product-grid', typeId: 'commerce_assets.productGrid', regions: [] },\n * ]};\n *\n * const visitor = {\n * visitRegion(context) {\n * if (!context.node.components?.length) {\n * return null; // Remove empty regions\n * }\n * // Traverse into child components using the context API\n * const components = context.visitComponents(context.node.components);\n * return { ...context.node, components };\n * },\n * };\n *\n * transformRegion(emptyRegion, visitor); // => null (removed)\n * transformRegion(populatedRegion, visitor); // => { id: 'main', components: [...] }\n * ```\n */\nexport function transformRegion(\n region: ShopperExperience.schemas['Region'],\n visitor: PageVisitor\n): ShopperExperience.schemas['Region'] | null {\n return new RootVisitorContext(visitor).visitRegion(region);\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { QualifierContext, ResolvedDataBinding } from '../types';\nimport type { ShopperExperience } from '@/scapi-client/types';\n\n/**\n * Data binding metadata attached to a component instance. Stored in the\n * component's `custom.dataBinding` field by ECOM when the author binds a\n * data source to the component in Page Designer.\n */\nexport interface ComponentDataBinding {\n /** Maps attribute names to expression strings (e.g. `\"content_asset.body\"`). */\n expressions: Record<string, string>;\n /** The data contexts bound to this component, identifying the records to resolve against. */\n contexts: DataBindingContext[];\n}\n\n/**\n * A data context reference on a component instance, identifying a specific\n * record from a data provider.\n */\nexport interface DataBindingContext {\n /** The data provider type (e.g. `\"content_asset\"`). */\n type: string;\n /** The record identifier (e.g. a content asset UUID). */\n id: string;\n}\n\n/**\n * Pattern matching bare expressions: `type.field`.\n */\nconst BARE_EXPRESSION_PATTERN = /^(\\w+)\\.(\\w+)$/;\n\n/**\n * Parses a binding expression string into its provider type and field name.\n * Supports the bare `type.field` format.\n *\n * @param expression - The expression string to parse.\n * @returns The parsed type and field, or `null` if the expression is invalid.\n *\n * @example\n * ```ts\n * parseExpression('content_asset.title'); // { type: 'content_asset', field: 'title' }\n * parseExpression('invalid'); // null\n * ```\n */\nexport function parseExpression(expression: string): { type: string; field: string } | null {\n const match = expression.trim().match(BARE_EXPRESSION_PATTERN);\n if (match) {\n return { type: match[1], field: match[2] };\n }\n\n return null;\n}\n\n/**\n * Resolves a single binding expression against the component's data contexts\n * and the resolved data bindings from context resolution.\n *\n * Returns the resolved field value, or an empty string if the expression is\n * invalid, the matching context or record is not found, or the field does not\n * exist on the resolved record.\n *\n * @param expression - The expression string (e.g. `\"content_asset.body\"`).\n * @param contexts - The component's data binding contexts.\n * @param dataBindings - The resolved data bindings from {@link QualifierContext}.\n * @returns The resolved value, or `''` if resolution fails.\n */\nexport function resolveExpression(\n expression: string,\n contexts: DataBindingContext[],\n dataBindings: NonNullable<QualifierContext['dataBindings']>\n): unknown {\n const parsed = parseExpression(expression);\n if (!parsed) return '';\n\n const context = contexts.find((c) => c.type === parsed.type);\n if (!context) return '';\n\n const record: ResolvedDataBinding | undefined = dataBindings[context.type]?.[context.id];\n if (!record) return '';\n\n return record[parsed.field] ?? '';\n}\n\n/**\n * Extracts the {@link ComponentDataBinding} metadata from a component's\n * `custom` field. Returns `undefined` if the component has no data binding\n * configuration.\n */\nfunction getDataBinding(component: ShopperExperience.schemas['Component']): ComponentDataBinding | undefined {\n const custom = component.custom as Record<string, unknown> | undefined;\n return custom?.dataBinding as ComponentDataBinding | undefined;\n}\n\n/**\n * Resolves data binding expressions for a single component. Replaces attribute\n * values in the component's `data` with the resolved values from context\n * resolution. Attributes without a matching expression are preserved as-is.\n * When an expression cannot be resolved, the attribute value is set to an\n * empty string.\n *\n * Returns the component unchanged if it has no data binding metadata or if\n * `dataBindings` is `undefined`.\n *\n * @param component - The component to resolve data bindings for.\n * @param dataBindings - The resolved data bindings from {@link QualifierContext}, or `undefined` if no bindings were resolved.\n * @returns The component with resolved attribute values, or the original component if no bindings apply.\n *\n * @example\n * ```ts\n * import { resolveComponentDataBindings } from '@salesforce/storefront-next-runtime/design/data';\n *\n * const component = {\n * id: 'banner',\n * typeId: 'commerce_assets.contentBanner',\n * data: { heading: 'Fallback Title', body: 'Fallback Body' },\n * custom: {\n * dataBinding: {\n * expressions: {\n * heading: 'content_asset.title',\n * body: 'content_asset.body',\n * },\n * contexts: [{ type: 'content_asset', id: 'winter-sale-uuid' }],\n * },\n * },\n * regions: [],\n * };\n *\n * const dataBindings = {\n * content_asset: {\n * 'winter-sale-uuid': {\n * title: 'Winter Sale',\n * body: '<div>Free Shipping on all orders!</div>',\n * },\n * },\n * };\n *\n * const resolved = resolveComponentDataBindings(component, dataBindings);\n * // resolved.data.heading === 'Winter Sale'\n * // resolved.data.body === '<div>Free Shipping on all orders!</div>'\n * ```\n */\nexport function resolveComponentDataBindings(\n component: ShopperExperience.schemas['Component'],\n dataBindings: QualifierContext['dataBindings']\n): ShopperExperience.schemas['Component'] {\n if (!dataBindings) {\n return component;\n }\n\n const binding = getDataBinding(component);\n if (!binding?.contexts?.length) return component;\n\n const expressionEntries = Object.entries(binding.expressions ?? {});\n if (expressionEntries.length === 0) return component;\n\n const resolvedData: Record<string, unknown> = {\n ...(component.data as Record<string, unknown> | undefined),\n };\n\n for (const [attrName, expression] of expressionEntries) {\n resolvedData[attrName] = resolveExpression(expression, binding.contexts, dataBindings);\n }\n\n return {\n ...component,\n data: resolvedData as typeof component.data,\n };\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { QualifierContext, VisibilityRuleDef } from './types';\n\n/**\n * Evaluates a visibility rule against a shopper's qualifier context.\n *\n * Campaign-based and non-campaign rules are **mutually exclusive** paths,\n * matching the server's `VisibilityDefinition.isVisible()` logic:\n *\n * - **Campaign-based rule** (has `campaignQualifiers`): only the campaign\n * qualifiers are checked. Schedule, locale, and customer-group fields are\n * ignored because the campaign qualification already incorporates those\n * checks server-side.\n * - **Non-campaign rule**: locale, schedule, AND customer groups are checked.\n * All specified conditions must pass.\n *\n * When no context is provided and the rule requires campaign or customer group\n * checks, those checks will fail (returning `false`). Schedule checks do not\n * require context and are evaluated against `Date.now()`.\n *\n * @param rule - The visibility rule to evaluate.\n * @param locale - The current locale (e.g. `\"en_US\"`). Used to check whether the rule applies to this locale.\n * @param context - The shopper's active qualifiers, or `null`/`undefined` if not yet resolved.\n * @returns `true` if the rule's conditions pass, `false` otherwise.\n *\n * @example\n * ```ts\n * import { validateRule } from '@salesforce/storefront-next-runtime/design/data';\n *\n * // Campaign-based rule — only campaign qualifiers are evaluated\n * const campaignRule = {\n * activeLocales: ['en_US'],\n * campaignQualifiers: [{ campaignId: 'holiday-sale-2026', promotionId: 'free-shipping' }],\n * };\n *\n * // Non-campaign rule — locale, schedule AND customer groups are evaluated\n * const segmentRule = {\n * activeLocales: ['en_US', 'fr_FR'],\n * customerGroups: ['vip-customers'],\n * schedule: {\n * start: new Date('2026-12-01').toISOString(),\n * end: new Date('2026-12-31').toISOString(),\n * },\n * };\n * ```\n */\nexport function validateRule(rule: VisibilityRuleDef, locale: string, context?: QualifierContext | null): boolean {\n // Campaign-based rules and non-campaign rules are mutually exclusive\n // paths, mirroring the server's if/else-if branching.\n if (rule.campaignQualifiers) {\n for (const campaignQualifier of rule.campaignQualifiers) {\n if (!context?.campaignQualifiers[campaignQualifier.campaignId]?.[campaignQualifier.promotionId]) {\n return false;\n }\n }\n } else {\n if (rule.activeLocales && !rule.activeLocales.includes(locale)) {\n return false;\n }\n\n // Rule schedule times are in ISO 8601 format, so we need to convert them to milliseconds\n if (rule.schedule) {\n const now = Date.now();\n\n if (rule.schedule.start) {\n const startTimeInMillis = new Date(rule.schedule.start).getTime();\n\n // If the start time is invalid, the rule fails\n if (Number.isNaN(startTimeInMillis) || startTimeInMillis >= now) {\n return false;\n }\n }\n\n if (rule.schedule.end) {\n const endTimeInMillis = new Date(rule.schedule.end).getTime();\n\n // If the end time is invalid, the rule fails\n if (Number.isNaN(endTimeInMillis) || endTimeInMillis <= now) {\n return false;\n }\n }\n }\n\n if (rule.customerGroups) {\n for (const customerGroup of rule.customerGroups) {\n if (!context?.customerGroups[customerGroup]) {\n return false;\n }\n }\n }\n }\n\n return true;\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { transformPage } from './transform';\nimport { resolveComponentDataBindings } from './resolve-data-bindings';\nimport { validateRule } from '../validate-rule';\nimport type { QualifierContext, PageManifest } from '../types';\nimport type { ShopperExperience } from '@/scapi-client/types';\n\n/**\n * Context required for page processing. Contains the shopper's runtime\n * qualifiers, the component-level visibility rules, and the locale used\n * to resolve locale-specific component content from the page manifest.\n */\nexport interface PageProcessorContext {\n /** The shopper's active qualifiers (campaigns, customer groups), or `null` if not resolved. */\n qualifiers: QualifierContext | null;\n /** Component visibility rule definitions extracted from the page layout. */\n componentInfo: PageManifest['componentInfo'];\n /** The locale to use when resolving locale-specific component content (e.g. `\"en_US\"`). */\n locale: string;\n}\n\n/**\n * Filters a page's components based on their visibility rules and resolves\n * data binding expressions in a single traversal. Traverses the page tree\n * using the visitor pattern and:\n *\n * 1. Removes any component whose visibility rules do not pass against the\n * shopper's qualifier context.\n * 2. Resolves data binding expressions in each surviving component's `data`\n * attributes using the resolved data bindings from context resolution.\n *\n * A component is visible if **any** of its visibility rules pass (OR logic).\n * If a component has rules and none of them pass, it is removed. Components\n * without rules are always included.\n *\n * @param page - The page to process.\n * @param context - The processing context with qualifier data, visibility rules, and resolved data bindings.\n * @returns A new page with invisible components filtered out and data binding expressions resolved.\n *\n * @example\n * ```ts\n * import { processPage } from '@salesforce/storefront-next-runtime/design/data';\n *\n * const page = {\n * id: 'homepage',\n * typeId: 'storePage',\n * regions: [{\n * id: 'main',\n * components: [\n * { id: 'public-banner', typeId: 'commerce_assets.heroBanner', regions: [] },\n * { id: 'loyalty-offer', typeId: 'commerce_assets.promoTile', regions: [] },\n * ],\n * }],\n * };\n *\n * // The \"loyalty-offer\" component requires the shopper to be in \"loyalty-members\"\n * const componentInfo = {\n * 'public-banner': { visibilityRules: [] },\n * 'loyalty-offer': {\n * visibilityRules: [{ customerGroups: ['loyalty-members'] }],\n * },\n * };\n *\n * // Guest shopper — not in any customer group\n * const filtered = processPage(page, {\n * qualifiers: { customerGroups: {}, campaignQualifiers: {} },\n * componentInfo,\n * });\n * // filtered.regions[0].components has only \"public-banner\"\n * // \"loyalty-offer\" was removed because the shopper isn't a loyalty member\n * ```\n */\nexport function processPage(\n page: ShopperExperience.schemas['Page'],\n processorContext: PageProcessorContext\n): ShopperExperience.schemas['Page'] {\n return transformPage(page, {\n visitComponent(ctx) {\n const componentInfo = processorContext.componentInfo[ctx.node.id];\n const visibilityRules = componentInfo?.visibilityRules ?? [];\n\n // Visibility rules use OR logic: the component is visible\n // if ANY rule passes. Only remove it when it has its own\n // rules and none of them pass.\n if (visibilityRules.length > 0) {\n const anyRulePassed = visibilityRules.some((rule) =>\n validateRule(rule, processorContext.locale, processorContext.qualifiers)\n );\n\n if (!anyRulePassed) {\n return null;\n }\n }\n\n // Apply locale-specific content from the manifest to the component's data.\n // The \"default\" locale provides base values; the current locale overrides them.\n const defaultContent = componentInfo?.content?.default ?? {};\n const localeContent = componentInfo?.content?.[processorContext.locale] ?? {};\n const content = { ...defaultContent, ...localeContent };\n const isLocalized = Boolean(componentInfo?.content?.[processorContext.locale]);\n\n let node: ShopperExperience.schemas['Component'] = {\n ...ctx.node,\n // @ts-expect-error - This isn't updated in the schema yet.\n localized: isLocalized,\n // Always true here — this processing logic only runs in live/published mode\n // where invisible components are already filtered out above. The `visible`\n // flag is only false in design/preview mode, which returns all components\n // unfiltered and bypasses this code path entirely.\n visible: true,\n data: {\n ...(ctx.node.data as Record<string, unknown>),\n ...content,\n } as typeof ctx.node.data,\n };\n\n // Resolve data binding expressions (overrides content for bound attributes).\n node = resolveComponentDataBindings(node, processorContext.qualifiers?.dataBindings);\n\n return {\n ...node,\n regions: ctx.visitRegions(ctx.node.regions),\n };\n },\n }) as ShopperExperience.schemas['Page'];\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport class RequiredError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RequiredError';\n }\n\n static assert<TValue>(\n value: TValue,\n message: string,\n isEmpty: (value: TValue) => boolean = (v) => v == null\n ): asserts value is NonNullable<TValue> {\n if (isEmpty(value)) {\n throw new RequiredError(message);\n }\n }\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { SiteManifest } from '../types';\n\n/**\n * The result of resolving an identifier through a content assignment resolver.\n * Contains the object type, aspect type, and ordered list of keys to search\n * in the site manifest's content assignments.\n */\nexport interface ResolvedContentAssignmentLookup {\n /** The type of commerce object (e.g. `'product'`, `'category'`). */\n objectType: string;\n /** Ordered list of object IDs to search in the site manifest's content assignments. */\n keys: string[];\n}\n\n/**\n * A function that converts an identifier key (e.g., a product or category ID)\n * into a {@link ResolvedContentAssignmentLookup} describing where to search\n * in the site manifest for the assigned page ID.\n */\nexport type ContentAssignmentResolver = (key: string, manifest?: SiteManifest) => ResolvedContentAssignmentLookup;\n\n/**\n * Registry of content assignment resolvers keyed by {@link IdentifierType}.\n * Each resolver knows how to convert its identifier type into a set of lookup\n * keys for the site manifest.\n *\n * Built-in resolvers:\n * - **`'product'`** — Maps a product ID to a single PDP lookup key.\n * - **`'category'`** — Maps a category ID to an ordered list of keys that\n * traverses the category hierarchy from child to root, enabling inherited\n * page assignments.\n *\n * The `'page'` identifier type has no resolver — page IDs are used directly.\n *\n * @example\n * ```ts\n * import { ContentAssignmentResolvers } from '@salesforce/storefront-next-runtime/design/data';\n *\n * // Resolve a product identifier for PDP lookup\n * const productResolver = ContentAssignmentResolvers.get('product');\n * productResolver('nike-air-max-90');\n * // => { objectType: 'product', aspectType: 'pdp', keys: ['nike-air-max-90'] }\n *\n * // Resolve a category identifier — traverses hierarchy to find inherited assignments\n * const categoryResolver = ContentAssignmentResolvers.get('category');\n * const siteManifest = {\n * categories: {\n * 'mens-running-shoes': { name: 'Running Shoes', parentCategory: 'mens-shoes' },\n * 'mens-shoes': { name: \"Men's Shoes\", parentCategory: 'mens' },\n * 'mens': { name: 'Men' },\n * },\n * contentObjectAssignments: {},\n * };\n * categoryResolver('mens-running-shoes', siteManifest);\n * // => { objectType: 'category', aspectType: 'plp', keys: ['mens-running-shoes', 'mens-shoes', 'mens'] }\n * ```\n */\nexport const ContentAssignmentResolvers = new Map<string, ContentAssignmentResolver>([\n [\n 'product',\n (key) => ({\n objectType: 'product',\n keys: [key],\n }),\n ],\n [\n 'category',\n (key, manifest) => {\n const keys = [];\n const visited = new Set<string>();\n\n let currentCategoryId: string | undefined = key;\n\n while (currentCategoryId && !visited.has(currentCategoryId)) {\n visited.add(currentCategoryId);\n keys.push(currentCategoryId);\n currentCategoryId = manifest?.categories[currentCategoryId]?.parentCategory;\n }\n\n return {\n objectType: 'category',\n keys,\n };\n },\n ],\n]);\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { SiteManifest, IdentifierType } from '../types';\nimport { ContentAssignmentResolvers } from './content-assignment-resolvers';\n\n/**\n * Converts a product or category identifier into a page ID by looking up\n * content assignments in the site manifest. For categories, the lookup\n * traverses the category hierarchy from the given category up to the root,\n * returning the first matching assignment.\n *\n * Returns `null` if no content assignment is found for the identifier or if\n * the identifier type has no registered resolver.\n *\n * @param options - The resolution options.\n * @param options.id - The identifier to resolve (product ID, category ID, or page ID).\n * @param options.identifierType - The type of identifier: `'product'`, `'category'`, or `'page'`.\n * @param options.siteManifest - The site manifest containing content assignments and category hierarchy.\n * @returns The resolved page ID, or `null` if no assignment was found.\n *\n * @example\n * ```ts\n * import { resolveDynamicPageId } from '@salesforce/storefront-next-runtime/design/data';\n *\n * const siteManifest = {\n * contentObjectAssignments: {\n * plp: {\n * category: {\n * 'mens-shoes': {\n * lookupMode: 'category-explicit',\n * contentId: 'page-mens-shoes-plp',\n * },\n * },\n * },\n * },\n * categories: {\n * 'mens-running-shoes': { name: 'Running Shoes', parentCategory: 'mens-shoes' },\n * 'mens-shoes': { name: \"Men's Shoes\" },\n * },\n * };\n *\n * // Direct match\n * resolveDynamicPageId({ id: 'mens-shoes', identifierType: 'category', siteManifest });\n * // => 'page-mens-shoes-plp'\n *\n * // Inherited from parent category\n * resolveDynamicPageId({ id: 'mens-running-shoes', identifierType: 'category', siteManifest });\n * // => 'page-mens-shoes-plp' (found via parent traversal)\n *\n * // No assignment found\n * resolveDynamicPageId({ id: 'womens-shoes', identifierType: 'category', siteManifest });\n * // => null\n * ```\n */\nexport function resolveDynamicPageId<TIdentifier extends IdentifierType = IdentifierType>({\n id,\n identifierType,\n siteManifest,\n aspectType,\n}: {\n id: string;\n identifierType: TIdentifier;\n aspectType: string;\n siteManifest?: SiteManifest;\n}): string | null {\n const resolvedContentAssignmentLookup = ContentAssignmentResolvers.get(identifierType)?.(id, siteManifest);\n\n if (resolvedContentAssignmentLookup) {\n for (const key of resolvedContentAssignmentLookup.keys) {\n const contentAssignment =\n siteManifest?.contentObjectAssignments?.[aspectType]?.[resolvedContentAssignmentLookup.objectType]?.[\n key\n ];\n\n if (contentAssignment) {\n return contentAssignment.contentId;\n }\n }\n }\n\n return null;\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { ContextResolver, PageManifest, QualifierContext, VariationEntry } from '../types';\nimport { validateRule } from '../validate-rule';\n\n/**\n * Selects the appropriate page variation from a manifest by evaluating each\n * variation's visibility rule in order. Returns the first variation whose rule\n * passes, or falls back to the manifest's default variation.\n *\n * The qualifier context is resolved lazily — the `contextResolver` is only\n * called when a variation's `ruleRequiresContext` flag is `true`, and only\n * once (the result is cached for subsequent variations).\n *\n * @param manifest - The page manifest containing all variations.\n * @param options - Resolution options.\n * @param options.contextResolver - Optional async function that returns the shopper's qualifier context. Only called if a variation's rule needs it.\n * @param options.locale - The current locale (e.g. `\"en_US\"`). Used to evaluate locale-based visibility rules.\n * @returns The selected variation entry and resolved context, or `null` if no variation (including default) exists.\n *\n * @example\n * ```ts\n * import { getPageFromManifest } from '@salesforce/storefront-next-runtime/design/data';\n *\n * const manifest = {\n * pageId: 'homepage',\n * context: { campaignQualifiers: [], customerGroups: ['vip-customers'], dataBindings: [] },\n * variationOrder: ['vip-homepage', 'holiday-homepage'],\n * variations: {\n * 'vip-homepage': {\n * ruleRequiresContext: true,\n * pageRequiresContext: false,\n * visibilityRule: { activeLocales: ['en-US'], customerGroups: ['vip-customers'] },\n * page: { id: 'homepage', typeId: 'storePage', regions: [] },\n * },\n * 'holiday-homepage': {\n * ruleRequiresContext: false,\n * pageRequiresContext: false,\n * visibilityRule: {\n * activeLocales: ['en-US'],\n * schedule: {\n * start: new Date('2026-12-01').toISOString(),\n * end: new Date('2026-12-31').toISOString(),\n * },\n * },\n * page: { id: 'homepage', typeId: 'storePage', regions: [] },\n * },\n * 'default-homepage': {\n * ruleRequiresContext: false,\n * pageRequiresContext: false,\n * page: { id: 'homepage', typeId: 'storePage', regions: [] },\n * },\n * },\n * defaultVariation: 'default-homepage',\n * componentInfo: {},\n * };\n *\n * // VIP shopper — matches first variation\n * const result = await getPageFromManifest(manifest, {\n * locale: 'en-US',\n * contextResolver: async () => ({\n * customerGroups: { 'vip-customers': true },\n * campaignQualifiers: {},\n * }),\n * });\n * // result.entry === manifest.variations['vip-homepage']\n *\n * // Non-VIP shopper outside holiday window — falls back to default\n * const fallback = await getPageFromManifest(manifest, {\n * locale: 'en-US',\n * contextResolver: async () => ({\n * customerGroups: {},\n * campaignQualifiers: {},\n * }),\n * });\n * // fallback.entry === manifest.variations['default-homepage']\n * ```\n */\nexport async function getPageFromManifest(\n manifest: PageManifest,\n {\n contextResolver,\n locale,\n }: {\n contextResolver?: ContextResolver;\n locale: string;\n }\n): Promise<{\n entry: VariationEntry;\n context: QualifierContext | null;\n} | null> {\n let context: QualifierContext | null = null;\n let resolvedVariation: VariationEntry | null = null;\n\n for (const variationId of manifest.variationOrder) {\n const variation = manifest.variations[variationId];\n\n if (variation?.ruleRequiresContext && !context) {\n context = (await contextResolver?.(manifest.context)) ?? null;\n }\n\n if (!variation?.visibilityRule || validateRule(variation.visibilityRule, locale, context)) {\n resolvedVariation = variation;\n break;\n }\n }\n\n if (!resolvedVariation) {\n resolvedVariation = manifest.variations[manifest.defaultVariation];\n }\n\n if (!resolvedVariation) {\n return null;\n }\n\n return {\n entry: resolvedVariation,\n context,\n };\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport type { IdentifierType, ManifestStorage, ContextResolver, QualifierContext } from '../types';\nimport type { ShopperExperience } from '@/scapi-client/types';\nimport { ContentAssignmentResolvers } from '../manifest/content-assignment-resolvers';\nimport { resolveDynamicPageId } from '../manifest/resolve-dynamic-page-id';\nimport { getPageFromManifest } from '../manifest/get-page';\nimport { processPage } from './process-page';\nimport { RequiredError } from '../errors/required';\n\n/**\n * Main entry point for the page resolution pipeline. Orchestrates the full flow:\n *\n * 1. **Resolve dynamic page ID** — For product/category identifiers, looks up\n * the assigned page ID via content assignments in the site manifest.\n * 2. **Fetch page manifest** — Loads all variations for the resolved page.\n * 3. **Select variation** — Evaluates visibility rules to pick the right variation.\n * 4. **Load qualifier context** — Lazily fetches the shopper's context only if needed.\n * 5. **Process page** — Filters out components that fail visibility rules.\n *\n * Returns `null` if the page ID cannot be resolved, the manifest doesn't exist,\n * or no variation is available.\n *\n * @param options - The resolution options.\n * @param options.id - The identifier to resolve (product ID, category ID, or page ID).\n * @param options.identifierType - The type of identifier: `'product'`, `'category'`, or `'page'`.\n * @param options.locale - The locale to resolve the page for (e.g. `\"en-US\"`).\n * @param options.manifestStorage - Storage implementation for fetching manifests.\n * @param options.contextResolver - Optional async function that returns the shopper's qualifier context. Only called if a visibility rule needs it.\n * @param options.aspectType - The aspect type to resolve the page for when the identifier type is `'product'` or `'category'`.\n * @returns The fully resolved and filtered page, or `null`.\n *\n * @example\n * ```ts\n * import { resolvePage } from '@salesforce/storefront-next-runtime/design/data';\n *\n * // Resolve the PDP page for a specific product with an active holiday campaign\n * const page = await resolvePage({\n * id: 'nike-air-max-90',\n * identifierType: 'product',\n * aspectType: 'pdp',\n * locale: 'en-US',\n * manifestStorage: {\n * async getPageManifest(id, locale) {\n * // Fetch from CDN, filesystem, or database\n * return fetchManifest(`/manifests/${locale}/${id}.json`);\n * },\n * async getSiteManifest(locale) {\n * return fetchManifest(`/manifests/${locale}/site.json`);\n * },\n * },\n * contextResolver: async () => ({\n * customerGroups: { 'vip-customers': true },\n * campaignQualifiers: {\n * 'holiday-sale-2026': { 'free-shipping': true },\n * },\n * }),\n * });\n *\n * if (page) {\n * // page.regions contains only components visible to this VIP shopper\n * // during the holiday sale campaign\n * renderPage(page);\n * }\n * ```\n */\nexport async function resolvePage({\n id,\n identifierType,\n aspectType,\n locale,\n manifestStorage,\n contextResolver,\n}: {\n id: string;\n identifierType: IdentifierType;\n aspectType?: string;\n locale: string;\n manifestStorage: ManifestStorage;\n contextResolver?: ContextResolver;\n}): Promise<ShopperExperience.schemas['Page'] | null> {\n let resolvedId: string | null = null;\n\n if (ContentAssignmentResolvers.has(identifierType)) {\n const siteManifest = await manifestStorage.getSiteManifest(locale);\n\n RequiredError.assert(aspectType, `Aspect type is required for identifier type ${identifierType}`, (v) => !v);\n\n resolvedId = resolveDynamicPageId({ id, identifierType, aspectType, siteManifest });\n } else {\n resolvedId = id;\n }\n\n if (!resolvedId) {\n return null;\n }\n\n const pageManifest = await manifestStorage.getPageManifest(resolvedId, locale);\n\n if (!pageManifest) {\n return null;\n }\n\n const pageResults = await getPageFromManifest(pageManifest, {\n contextResolver,\n locale,\n });\n\n if (!pageResults) {\n return null;\n }\n\n let context: QualifierContext | null = null;\n\n if (pageResults.entry.pageRequiresContext) {\n context = pageResults.context ?? (await contextResolver?.(pageManifest.context)) ?? null;\n }\n\n return processPage(pageResults.entry.page, {\n qualifiers: context,\n componentInfo: pageManifest.componentInfo,\n locale,\n });\n}\n"],"mappings":";AAiBA,IAAa,sBAAb,MAAa,4BAA4B,MAAM;CAC3C,YAAY,SAAiB;AACzB,QAAM,QAAQ;AACd,OAAK,OAAO;;CAGhB,OAAO,OAAO,YAAgC,WAA+B;AACzE,MACK,eAAe,eAAe,cAAc,YAC5C,eAAe,UAAU,cAAc,YACvC,eAAe,YAAY,cAAc,YAE1C,OAAM,IAAI,oBACN,8BAA8B,UAAU,2BAA2B,aACtE;;;;;;;;;;;;;;;;;ACDb,IAAa,iBAAb,MAAa,eAAsB;CAC/B,YACI,AAAiBA,SAcnB;EAdmB;;CAgBrB,IAAI,OAA2B;AAC3B,SAAO,KAAK,QAAQ;;;;;CAMxB,IAAI,OAAc;AACd,SAAO,KAAK,QAAQ;;;;;CAMxB,IAAI,OAAsD;AACtD,SAAO,KAAK,QAAQ;;;;;CAMxB,IAAI,eAAgE;AAChE,SAAO,KAAK,QAAQ;;;;;CAMxB,IAAI,kBAAsE;AACtE,SAAO,KAAK,QAAQ;;;;;;;;;;;;;;;;;;;;;;CAuBxB,aAAa,UAAiD,EAAE,EAAyC;EACrG,MAAM,aAAa,EAAE;AAErB,OAAK,MAAM,UAAU,SAAS;GAC1B,MAAM,YAAY,KAAK,YAAY,OAAO;AAE1C,OAAI,UACA,YAAW,KAAK,UAAU;;AAIlC,SAAO;;;;;;;;;;CAWX,YAAY,QAAyF;EACjG,MAAM,gBAAgB,KAAK,eAAe,UAAU,OAAO;AAE3D,MAAI,KAAK,QAAQ,QAAQ,YACrB,QAAO,KAAK,QAAQ,QAAQ,YAAY,cAAc;WAC/C,OAAO,WACd,QAAO;GACH,GAAG;GACH,YAAY,cAAc,gBAAgB,OAAO,WAAW;GAC/D;AAGL,SAAO;;;;;;;;;;;;;;;;;;;;;;CAuBX,gBACI,aAAuD,EAAE,EACjB;EACxC,MAAM,gBAAgB,EAAE;AAExB,OAAK,MAAM,aAAa,YAAY;GAChC,MAAM,eAAe,KAAK,eAAe,UAAU;AAEnD,OAAI,aACA,eAAc,KAAK,aAAa;;AAIxC,SAAO;;;;;;;;;;CAWX,eAAe,WAAkG;EAC7G,MAAM,mBAAmB,KAAK,eAAe,aAAa,UAAU;AAEpE,MAAI,KAAK,QAAQ,QAAQ,eACrB,QAAO,KAAK,QAAQ,QAAQ,eAAe,iBAAiB;WACrD,UAAU,QACjB,QAAO;GACH,GAAG;GACH,SAAS,iBAAiB,aAAa,UAAU,QAAQ;GAC5D;AAGL,SAAO;;;;;;;;;;CAWX,UAAU,MAAmF;EACzF,MAAM,cAAc,IAAI,eAAe;GACnC,MAAM;GACN,SAAS,KAAK,QAAQ;GACtB;GACA,iBAAiB;GACjB,cAAc;GACd,MAAM;GACT,CAAC;AAEF,MAAI,KAAK,QAAQ,QAAQ,UACrB,QAAO,KAAK,QAAQ,QAAQ,UAAU,YAAY;WAC3C,KAAK,QAMZ,QALgB;GACZ,GAAG;GACH,SAAS,YAAY,aAAa,KAAK,QAAQ;GAClD;AAKL,SAAO;;CAGX,AAAQ,eACJ,MACA,MACwC;AACxC,sBAAoB,OAAO,KAAK,QAAQ,MAAM,KAAK;AAEnD,MAAI,SAAS,SACT,QAAO,IAAI,eAAe;GACtB,MAAM;GACN,SAAS,KAAK,QAAQ;GACtB,MAAM,KAAK;GACX;GACA,iBAAiB,KAAK;GACtB,cAAc,KAAK;GACtB,CAAC;AAGN,SAAO,IAAI,eAAe;GACtB,MAAM;GACN,SAAS,KAAK,QAAQ;GACtB,MAAM,KAAK;GACX;GACA,iBAAiB,KAAK;GACtB,cAAc,KAAK;GACtB,CAAC;;;AAIV,IAAM,qBAAN,cAAiC,eAAqB;CAClD,YAAY,SAAsB;AAC9B,QAAM;GACF,MAAM;GACN,MAAM;GACN;GACH,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyEV,SAAgB,cACZ,MACA,SACwC;AACxC,QAAO,IAAI,mBAAmB,QAAQ,CAAC,UAAU,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuC1D,SAAgB,mBACZ,WACA,SAC6C;AAC7C,QAAO,IAAI,mBAAmB,QAAQ,CAAC,eAAe,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCpE,SAAgB,gBACZ,QACA,SAC0C;AAC1C,QAAO,IAAI,mBAAmB,QAAQ,CAAC,YAAY,OAAO;;;;;;;;AC9X9D,MAAM,0BAA0B;;;;;;;;;;;;;;AAehC,SAAgB,gBAAgB,YAA4D;CACxF,MAAM,QAAQ,WAAW,MAAM,CAAC,MAAM,wBAAwB;AAC9D,KAAI,MACA,QAAO;EAAE,MAAM,MAAM;EAAI,OAAO,MAAM;EAAI;AAG9C,QAAO;;;;;;;;;;;;;;;AAgBX,SAAgB,kBACZ,YACA,UACA,cACO;CACP,MAAM,SAAS,gBAAgB,WAAW;AAC1C,KAAI,CAAC,OAAQ,QAAO;CAEpB,MAAM,UAAU,SAAS,MAAM,MAAM,EAAE,SAAS,OAAO,KAAK;AAC5D,KAAI,CAAC,QAAS,QAAO;CAErB,MAAMC,SAA0C,aAAa,QAAQ,QAAQ,QAAQ;AACrF,KAAI,CAAC,OAAQ,QAAO;AAEpB,QAAO,OAAO,OAAO,UAAU;;;;;;;AAQnC,SAAS,eAAe,WAAqF;AAEzG,QADe,UAAU,QACV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDnB,SAAgB,6BACZ,WACA,cACsC;AACtC,KAAI,CAAC,aACD,QAAO;CAGX,MAAM,UAAU,eAAe,UAAU;AACzC,KAAI,CAAC,SAAS,UAAU,OAAQ,QAAO;CAEvC,MAAM,oBAAoB,OAAO,QAAQ,QAAQ,eAAe,EAAE,CAAC;AACnE,KAAI,kBAAkB,WAAW,EAAG,QAAO;CAE3C,MAAMC,eAAwC,EAC1C,GAAI,UAAU,MACjB;AAED,MAAK,MAAM,CAAC,UAAU,eAAe,kBACjC,cAAa,YAAY,kBAAkB,YAAY,QAAQ,UAAU,aAAa;AAG1F,QAAO;EACH,GAAG;EACH,MAAM;EACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACzHL,SAAgB,aAAa,MAAyB,QAAgB,SAA4C;AAG9G,KAAI,KAAK,oBACL;OAAK,MAAM,qBAAqB,KAAK,mBACjC,KAAI,CAAC,SAAS,mBAAmB,kBAAkB,cAAc,kBAAkB,aAC/E,QAAO;QAGZ;AACH,MAAI,KAAK,iBAAiB,CAAC,KAAK,cAAc,SAAS,OAAO,CAC1D,QAAO;AAIX,MAAI,KAAK,UAAU;GACf,MAAM,MAAM,KAAK,KAAK;AAEtB,OAAI,KAAK,SAAS,OAAO;IACrB,MAAM,oBAAoB,IAAI,KAAK,KAAK,SAAS,MAAM,CAAC,SAAS;AAGjE,QAAI,OAAO,MAAM,kBAAkB,IAAI,qBAAqB,IACxD,QAAO;;AAIf,OAAI,KAAK,SAAS,KAAK;IACnB,MAAM,kBAAkB,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,SAAS;AAG7D,QAAI,OAAO,MAAM,gBAAgB,IAAI,mBAAmB,IACpD,QAAO;;;AAKnB,MAAI,KAAK,gBACL;QAAK,MAAM,iBAAiB,KAAK,eAC7B,KAAI,CAAC,SAAS,eAAe,eACzB,QAAO;;;AAMvB,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpBX,SAAgB,YACZ,MACA,kBACiC;AACjC,QAAO,cAAc,MAAM,EACvB,eAAe,KAAK;EAChB,MAAM,gBAAgB,iBAAiB,cAAc,IAAI,KAAK;EAC9D,MAAM,kBAAkB,eAAe,mBAAmB,EAAE;AAK5D,MAAI,gBAAgB,SAAS,GAKzB;OAAI,CAJkB,gBAAgB,MAAM,SACxC,aAAa,MAAM,iBAAiB,QAAQ,iBAAiB,WAAW,CAC3E,CAGG,QAAO;;EAMf,MAAM,iBAAiB,eAAe,SAAS,WAAW,EAAE;EAC5D,MAAM,gBAAgB,eAAe,UAAU,iBAAiB,WAAW,EAAE;EAC7E,MAAM,UAAU;GAAE,GAAG;GAAgB,GAAG;GAAe;EACvD,MAAM,cAAc,QAAQ,eAAe,UAAU,iBAAiB,QAAQ;EAE9E,IAAIC,OAA+C;GAC/C,GAAG,IAAI;GAEP,WAAW;GAKX,SAAS;GACT,MAAM;IACF,GAAI,IAAI,KAAK;IACb,GAAG;IACN;GACJ;AAGD,SAAO,6BAA6B,MAAM,iBAAiB,YAAY,aAAa;AAEpF,SAAO;GACH,GAAG;GACH,SAAS,IAAI,aAAa,IAAI,KAAK,QAAQ;GAC9C;IAER,CAAC;;;;;;;;;;;;;;;;;;;;AC3HN,IAAa,gBAAb,MAAa,sBAAsB,MAAM;CACrC,YAAY,SAAiB;AACzB,QAAM,QAAQ;AACd,OAAK,OAAO;;CAGhB,OAAO,OACH,OACA,SACA,WAAuC,MAAM,KAAK,MACd;AACpC,MAAI,QAAQ,MAAM,CACd,OAAM,IAAI,cAAc,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC6C5C,MAAa,6BAA6B,IAAI,IAAuC,CACjF,CACI,YACC,SAAS;CACN,YAAY;CACZ,MAAM,CAAC,IAAI;CACd,EACJ,EACD,CACI,aACC,KAAK,aAAa;CACf,MAAM,OAAO,EAAE;CACf,MAAM,0BAAU,IAAI,KAAa;CAEjC,IAAIC,oBAAwC;AAE5C,QAAO,qBAAqB,CAAC,QAAQ,IAAI,kBAAkB,EAAE;AACzD,UAAQ,IAAI,kBAAkB;AAC9B,OAAK,KAAK,kBAAkB;AAC5B,sBAAoB,UAAU,WAAW,oBAAoB;;AAGjE,QAAO;EACH,YAAY;EACZ;EACH;EAER,CACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjCF,SAAgB,qBAA0E,EACtF,IACA,gBACA,cACA,cAMc;CACd,MAAM,kCAAkC,2BAA2B,IAAI,eAAe,GAAG,IAAI,aAAa;AAE1G,KAAI,gCACA,MAAK,MAAM,OAAO,gCAAgC,MAAM;EACpD,MAAM,oBACF,cAAc,2BAA2B,cAAc,gCAAgC,cACnF;AAGR,MAAI,kBACA,QAAO,kBAAkB;;AAKrC,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACFX,eAAsB,oBAClB,UACA,EACI,iBACA,UAQE;CACN,IAAIC,UAAmC;CACvC,IAAIC,oBAA2C;AAE/C,MAAK,MAAM,eAAe,SAAS,gBAAgB;EAC/C,MAAM,YAAY,SAAS,WAAW;AAEtC,MAAI,WAAW,uBAAuB,CAAC,QACnC,WAAW,MAAM,kBAAkB,SAAS,QAAQ,IAAK;AAG7D,MAAI,CAAC,WAAW,kBAAkB,aAAa,UAAU,gBAAgB,QAAQ,QAAQ,EAAE;AACvF,uBAAoB;AACpB;;;AAIR,KAAI,CAAC,kBACD,qBAAoB,SAAS,WAAW,SAAS;AAGrD,KAAI,CAAC,kBACD,QAAO;AAGX,QAAO;EACH,OAAO;EACP;EACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpDL,eAAsB,YAAY,EAC9B,IACA,gBACA,YACA,QACA,iBACA,mBAQkD;CAClD,IAAIC,aAA4B;AAEhC,KAAI,2BAA2B,IAAI,eAAe,EAAE;EAChD,MAAM,eAAe,MAAM,gBAAgB,gBAAgB,OAAO;AAElE,gBAAc,OAAO,YAAY,+CAA+C,mBAAmB,MAAM,CAAC,EAAE;AAE5G,eAAa,qBAAqB;GAAE;GAAI;GAAgB;GAAY;GAAc,CAAC;OAEnF,cAAa;AAGjB,KAAI,CAAC,WACD,QAAO;CAGX,MAAM,eAAe,MAAM,gBAAgB,gBAAgB,YAAY,OAAO;AAE9E,KAAI,CAAC,aACD,QAAO;CAGX,MAAM,cAAc,MAAM,oBAAoB,cAAc;EACxD;EACA;EACH,CAAC;AAEF,KAAI,CAAC,YACD,QAAO;CAGX,IAAIC,UAAmC;AAEvC,KAAI,YAAY,MAAM,oBAClB,WAAU,YAAY,WAAY,MAAM,kBAAkB,aAAa,QAAQ,IAAK;AAGxF,QAAO,YAAY,YAAY,MAAM,MAAM;EACvC,YAAY;EACZ,eAAe,aAAa;EAC5B;EACH,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { n as ComponentModule, o as FrameworkAdapter } from "./types3.js";
|
|
|
3
3
|
import { g as IsomorphicConfiguration } from "./index.js";
|
|
4
4
|
import { i as RegionDecoratorProps, t as ComponentDecoratorProps } from "./component.types.js";
|
|
5
5
|
import React$1 from "react";
|
|
6
|
-
import * as
|
|
6
|
+
import * as react_jsx_runtime2 from "react/jsx-runtime";
|
|
7
7
|
|
|
8
8
|
//#region src/design/react/core/PageDesignerProvider.d.ts
|
|
9
9
|
type PageDesignerContextType = {
|
|
@@ -49,7 +49,7 @@ declare function PageDesignerPageMetadataProvider({
|
|
|
49
49
|
children
|
|
50
50
|
}: React.PropsWithChildren<{
|
|
51
51
|
page: ShopperExperience.schemas['Page'];
|
|
52
|
-
}>):
|
|
52
|
+
}>): react_jsx_runtime2.JSX.Element;
|
|
53
53
|
//#endregion
|
|
54
54
|
//#region src/design/react/core/RegionContext.d.ts
|
|
55
55
|
interface RegionContextType {
|
|
@@ -52,16 +52,18 @@ function createReactComponentDesignDecorator(Component) {
|
|
|
52
52
|
const LazyDesignRegion = lazy(() => import("./DesignRegion.js").then((module) => ({ default: module.DesignRegion })));
|
|
53
53
|
function createReactRegionDesignDecorator(Region) {
|
|
54
54
|
return function DesignDecoratedRegion(props) {
|
|
55
|
-
const { designMetadata, children,...componentProps } = props;
|
|
55
|
+
const { designMetadata, children, className,...componentProps } = props;
|
|
56
56
|
const { isDesignMode } = usePageDesignerMode();
|
|
57
57
|
return isDesignMode ? /* @__PURE__ */ jsx(LazyDesignRegion, {
|
|
58
58
|
designMetadata,
|
|
59
|
+
className,
|
|
59
60
|
children: /* @__PURE__ */ jsx(Region, {
|
|
60
61
|
...componentProps,
|
|
61
62
|
children
|
|
62
63
|
})
|
|
63
64
|
}) : /* @__PURE__ */ jsx(Region, {
|
|
64
65
|
...componentProps,
|
|
66
|
+
className,
|
|
65
67
|
children
|
|
66
68
|
});
|
|
67
69
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"design-react-core.js","names":[],"sources":["../src/design/react/core/PageDesignerPageMetadataProvider.tsx","../src/design/react/core/ComponentDecorator.tsx","../src/design/react/core/RegionDecorator.tsx","../src/design/react/core/adapter.ts"],"sourcesContent":["/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { lazy } from 'react';\nimport { usePageDesignerMode } from './PageDesignerProvider';\nimport type { ShopperExperience } from '@/scapi-client/types';\n\nconst LazyPageRegistration = lazy(() =>\n import('../components/PageRegistration').then((module) => ({ default: module.PageRegistration }))\n);\n\n/**\n * Provides the page metadata for Page Designer.\n */\nexport function PageDesignerPageMetadataProvider({\n page,\n children,\n}: React.PropsWithChildren<{ page: ShopperExperience.schemas['Page'] }>) {\n const { isDesignMode } = usePageDesignerMode();\n\n if (!isDesignMode) {\n return <>{children}</>;\n }\n\n return <LazyPageRegistration page={page}>{children}</LazyPageRegistration>;\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { lazy } from 'react';\nimport type { ComponentDecoratorProps } from './component.types';\nimport { usePageDesignerMode } from './PageDesignerProvider';\n\n// Lazy load so we don't include all design code when not in design mode\nconst LazyDesignComponent = lazy(() =>\n import('../components/DesignComponent').then((module) => ({ default: module.DesignComponent }))\n);\n\n/**\n * Creates a higher-order component that wraps React components with design-time functionality.\n * In design mode, adds visual indicators, selection handling, and host communication.\n * In normal mode, renders the component unchanged for optimal performance.\n *\n * @template TProps - The props type of the component being decorated\n * @param Component - The React component to wrap with design functionality\n * @returns A new component with design-time capabilities\n */\nexport function createReactComponentDesignDecorator<TProps>(\n Component: React.ComponentType<TProps>\n): (props: ComponentDecoratorProps<TProps>) => React.JSX.Element {\n return function DesignDecoratedComponent(props: ComponentDecoratorProps<TProps>) {\n const { designMetadata, children, ...componentProps } = props;\n\n // Only use design context if in design mode\n const { isDesignMode } = usePageDesignerMode();\n\n return isDesignMode ? (\n <LazyDesignComponent designMetadata={designMetadata}>\n <Component {...(componentProps as unknown as TProps)}>{children}</Component>\n </LazyDesignComponent>\n ) : (\n <Component {...(componentProps as unknown as TProps)}>{children}</Component>\n );\n };\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { lazy } from 'react';\nimport type { RegionDecoratorProps } from './component.types';\nimport { usePageDesignerMode } from './PageDesignerProvider';\n\nconst LazyDesignRegion = lazy(() =>\n import('../components/DesignRegion').then((module) => ({ default: module.DesignRegion }))\n);\n\nexport function createReactRegionDesignDecorator<TProps>(\n Region: React.ComponentType<TProps>\n): (props: RegionDecoratorProps<TProps>) => React.JSX.Element {\n return function DesignDecoratedRegion(props: RegionDecoratorProps<TProps>) {\n const { designMetadata, children, ...componentProps } = props;\n const { isDesignMode } = usePageDesignerMode();\n\n return isDesignMode ? (\n <LazyDesignRegion designMetadata={designMetadata}>\n <Region {...(componentProps as unknown as TProps)}>{children}</Region>\n </LazyDesignRegion>\n ) : (\n <Region {...(componentProps as unknown as TProps)}
|
|
1
|
+
{"version":3,"file":"design-react-core.js","names":[],"sources":["../src/design/react/core/PageDesignerPageMetadataProvider.tsx","../src/design/react/core/ComponentDecorator.tsx","../src/design/react/core/RegionDecorator.tsx","../src/design/react/core/adapter.ts"],"sourcesContent":["/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { lazy } from 'react';\nimport { usePageDesignerMode } from './PageDesignerProvider';\nimport type { ShopperExperience } from '@/scapi-client/types';\n\nconst LazyPageRegistration = lazy(() =>\n import('../components/PageRegistration').then((module) => ({ default: module.PageRegistration }))\n);\n\n/**\n * Provides the page metadata for Page Designer.\n */\nexport function PageDesignerPageMetadataProvider({\n page,\n children,\n}: React.PropsWithChildren<{ page: ShopperExperience.schemas['Page'] }>) {\n const { isDesignMode } = usePageDesignerMode();\n\n if (!isDesignMode) {\n return <>{children}</>;\n }\n\n return <LazyPageRegistration page={page}>{children}</LazyPageRegistration>;\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { lazy } from 'react';\nimport type { ComponentDecoratorProps } from './component.types';\nimport { usePageDesignerMode } from './PageDesignerProvider';\n\n// Lazy load so we don't include all design code when not in design mode\nconst LazyDesignComponent = lazy(() =>\n import('../components/DesignComponent').then((module) => ({ default: module.DesignComponent }))\n);\n\n/**\n * Creates a higher-order component that wraps React components with design-time functionality.\n * In design mode, adds visual indicators, selection handling, and host communication.\n * In normal mode, renders the component unchanged for optimal performance.\n *\n * @template TProps - The props type of the component being decorated\n * @param Component - The React component to wrap with design functionality\n * @returns A new component with design-time capabilities\n */\nexport function createReactComponentDesignDecorator<TProps>(\n Component: React.ComponentType<TProps>\n): (props: ComponentDecoratorProps<TProps>) => React.JSX.Element {\n return function DesignDecoratedComponent(props: ComponentDecoratorProps<TProps>) {\n const { designMetadata, children, ...componentProps } = props;\n\n // Only use design context if in design mode\n const { isDesignMode } = usePageDesignerMode();\n\n return isDesignMode ? (\n <LazyDesignComponent designMetadata={designMetadata}>\n <Component {...(componentProps as unknown as TProps)}>{children}</Component>\n </LazyDesignComponent>\n ) : (\n <Component {...(componentProps as unknown as TProps)}>{children}</Component>\n );\n };\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { lazy } from 'react';\nimport type { RegionDecoratorProps } from './component.types';\nimport { usePageDesignerMode } from './PageDesignerProvider';\n\nconst LazyDesignRegion = lazy(() =>\n import('../components/DesignRegion').then((module) => ({ default: module.DesignRegion }))\n);\n\nexport function createReactRegionDesignDecorator<TProps>(\n Region: React.ComponentType<TProps>\n): (props: RegionDecoratorProps<TProps>) => React.JSX.Element {\n return function DesignDecoratedRegion(props: RegionDecoratorProps<TProps>) {\n const { designMetadata, children, className, ...componentProps } = props;\n const { isDesignMode } = usePageDesignerMode();\n\n return isDesignMode ? (\n <LazyDesignRegion designMetadata={designMetadata} className={className}>\n <Region {...(componentProps as unknown as TProps)}>{children}</Region>\n </LazyDesignRegion>\n ) : (\n <Region {...(componentProps as unknown as TProps)} className={className}>\n {children}\n </Region>\n );\n };\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { type ComponentModule, type FrameworkAdapter } from '../../registry/types';\nimport { createReactComponentDesignDecorator } from './ComponentDecorator';\n\n/* ==================== React-Specific Types ==================== */\n\nexport type ReactComponentModule<TProps> = ComponentModule<TProps, ReactDesignComponentType<TProps>>;\n\n/**\n * A React component that optionally accepts design metadata.\n * Any component returned from the registry could potentially accept design metadata.\n * This includes both regular components and lazy components with their React-specific properties.\n */\nexport type ReactDesignComponentType<TProps> =\n | React.ComponentType<TProps>\n | React.LazyExoticComponent<React.ComponentType<TProps>>;\n\n/* ==================== React Adapter Implementation ==================== */\n\n/**\n * React framework adapter that implements React-specific behavior\n * for the framework-agnostic component registry.\n */\nexport class ReactAdapter<TProps> implements FrameworkAdapter<TProps, ReactDesignComponentType<TProps>> {\n /**\n * Creates a React lazy component from an importer function.\n */\n createLazyComponent(importer: () => Promise<ReactComponentModule<TProps>>): ReactDesignComponentType<TProps> {\n const lazyComp = React.lazy(async () => {\n const m = await importer();\n\n const component = m.default as React.ComponentType<TProps>;\n\n return { default: component };\n });\n\n return lazyComp as ReactDesignComponentType<TProps>;\n }\n\n /**\n * Decorates a React component with design-time capabilities.\n * Uses the React-specific design decorator directly.\n */\n decorateComponent(component: ReactDesignComponentType<TProps>): ReactDesignComponentType<TProps> {\n const reactComponent = component as React.ComponentType<TProps>;\n\n return createReactComponentDesignDecorator(reactComponent) as ReactDesignComponentType<TProps>;\n }\n}\n\n/**\n * Creates a React adapter instance with optional configuration.\n */\nexport function createReactAdapter<TProps>(): ReactAdapter<TProps> {\n return new ReactAdapter<TProps>();\n}\n"],"mappings":";;;;;;;AAmBA,MAAM,uBAAuB,WACzB,OAAO,yBAAkC,MAAM,YAAY,EAAE,SAAS,OAAO,kBAAkB,EAAE,CACpG;;;;AAKD,SAAgB,iCAAiC,EAC7C,MACA,YACqE;CACrE,MAAM,EAAE,iBAAiB,qBAAqB;AAE9C,KAAI,CAAC,aACD,QAAO,gCAAG,WAAY;AAG1B,QAAO,oBAAC;EAA2B;EAAO;GAAgC;;;;;AChB9E,MAAM,sBAAsB,WACxB,OAAO,wBAAiC,MAAM,YAAY,EAAE,SAAS,OAAO,iBAAiB,EAAE,CAClG;;;;;;;;;;AAWD,SAAgB,oCACZ,WAC6D;AAC7D,QAAO,SAAS,yBAAyB,OAAwC;EAC7E,MAAM,EAAE,gBAAgB,SAAU,GAAG,mBAAmB;EAGxD,MAAM,EAAE,iBAAiB,qBAAqB;AAE9C,SAAO,eACH,oBAAC;GAAoC;aACjC,oBAAC;IAAU,GAAK;IAAuC;KAAqB;IAC1D,GAEtB,oBAAC;GAAU,GAAK;GAAuC;IAAqB;;;;;;AC5BxF,MAAM,mBAAmB,WACrB,OAAO,qBAA8B,MAAM,YAAY,EAAE,SAAS,OAAO,cAAc,EAAE,CAC5F;AAED,SAAgB,iCACZ,QAC0D;AAC1D,QAAO,SAAS,sBAAsB,OAAqC;EACvE,MAAM,EAAE,gBAAgB,UAAU,UAAW,GAAG,mBAAmB;EACnE,MAAM,EAAE,iBAAiB,qBAAqB;AAE9C,SAAO,eACH,oBAAC;GAAiC;GAA2B;aACzD,oBAAC;IAAO,GAAK;IAAuC;KAAkB;IACvD,GAEnB,oBAAC;GAAO,GAAK;GAAiD;GACzD;IACI;;;;;;;;;;ACErB,IAAa,eAAb,MAAwG;;;;CAIpG,oBAAoB,UAAyF;AASzG,SARiB,MAAM,KAAK,YAAY;AAKpC,UAAO,EAAE,UAJC,MAAM,UAAU,EAEN,SAES;IAC/B;;;;;;CASN,kBAAkB,WAA+E;AAG7F,SAAO,oCAFgB,UAEmC;;;;;;AAOlE,SAAgB,qBAAmD;AAC/D,QAAO,IAAI,cAAsB"}
|
package/dist/events.d.ts
CHANGED
|
@@ -144,20 +144,25 @@ type EventTypeMap = { [K in AnalyticsEvent as K['eventType']]: K };
|
|
|
144
144
|
type EventPayload<T extends AnalyticsEvent['eventType']> = Omit<EventTypeMap[T], 'eventType' | 'payload'> & {
|
|
145
145
|
payload: AnalyticsPayload;
|
|
146
146
|
};
|
|
147
|
+
/** Site identification passed to adapters at event-send time */
|
|
148
|
+
type EventSiteInfo = {
|
|
149
|
+
siteId: string;
|
|
150
|
+
localeId: string;
|
|
151
|
+
};
|
|
147
152
|
/**
|
|
148
153
|
* Minimal interface for engagement adapters that can send analytics events.
|
|
149
154
|
* Engagemet Adapters must implement this interface to work with the event mediator.
|
|
150
155
|
*/
|
|
151
156
|
interface EventAdapter {
|
|
152
157
|
name: string;
|
|
153
|
-
sendEvent?: (event: AnalyticsEvent) => Promise<unknown>;
|
|
158
|
+
sendEvent?: (event: AnalyticsEvent, siteInfo?: EventSiteInfo) => Promise<unknown>;
|
|
154
159
|
}
|
|
155
160
|
/**
|
|
156
161
|
* Generic event mediator interface for tracking events.
|
|
157
162
|
* This can be used for analytics, telemetry, or any other event tracking system.
|
|
158
163
|
*/
|
|
159
164
|
type EventMediator = {
|
|
160
|
-
track: (event: AnalyticsEvent) => void;
|
|
165
|
+
track: (event: AnalyticsEvent, siteInfo?: EventSiteInfo) => void;
|
|
161
166
|
};
|
|
162
167
|
//#endregion
|
|
163
168
|
//#region src/events/events.d.ts
|
|
@@ -185,7 +190,7 @@ declare function createEvent<T extends AnalyticsEvent['eventType']>(eventType: T
|
|
|
185
190
|
* @param event - The view page event to send
|
|
186
191
|
* @param eventMediator - The event mediator to send the event to
|
|
187
192
|
*/
|
|
188
|
-
declare function sendViewPageEvent(event: ViewPageEvent, eventMediator: EventMediator): void;
|
|
193
|
+
declare function sendViewPageEvent(event: ViewPageEvent, eventMediator: EventMediator, siteInfo?: EventSiteInfo): void;
|
|
189
194
|
//#endregion
|
|
190
195
|
//#region src/events/mediator.d.ts
|
|
191
196
|
/**
|
|
@@ -204,5 +209,5 @@ declare function getEventMediator(getAdapters: () => EventAdapter[]): EventMedia
|
|
|
204
209
|
*/
|
|
205
210
|
declare function resetEventMediator(): void;
|
|
206
211
|
//#endregion
|
|
207
|
-
export { AnalyticsEvent, AnalyticsEventExtensions, AnalyticsPayload, AnalyticsUser, BaseEvent, CartItemAddEvent, CheckoutStartEvent, CheckoutStepEvent, ClickProductInCategoryEvent, ClickProductInRecommenderEvent, ClickProductInSearchEvent, ClickSearchSuggestionEvent, EventAdapter, EventMediator, EventPayload, EventTypeMap, PayloadTbd, ViewCategoryEvent, ViewPageEvent, ViewProductEvent, ViewRecommenderEvent, ViewSearchEvent, ViewSearchSuggestionEvent, createEvent, getEventMediator, resetEventMediator, sendViewPageEvent };
|
|
212
|
+
export { AnalyticsEvent, AnalyticsEventExtensions, AnalyticsPayload, AnalyticsUser, BaseEvent, CartItemAddEvent, CheckoutStartEvent, CheckoutStepEvent, ClickProductInCategoryEvent, ClickProductInRecommenderEvent, ClickProductInSearchEvent, ClickSearchSuggestionEvent, EventAdapter, EventMediator, EventPayload, EventSiteInfo, EventTypeMap, PayloadTbd, ViewCategoryEvent, ViewPageEvent, ViewProductEvent, ViewRecommenderEvent, ViewSearchEvent, ViewSearchSuggestionEvent, createEvent, getEventMediator, resetEventMediator, sendViewPageEvent };
|
|
208
213
|
//# sourceMappingURL=events.d.ts.map
|
package/dist/events.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","names":[],"sources":["../src/events/types.ts","../src/events/events.ts","../src/events/mediator.ts"],"sourcesContent":[],"mappings":";;;;;KAmBK,iBAAA,GAAoB,gBAAA,CAAiB,OAqEQ,CAAA,aAAA,CAAA,GArEiB,gBAAA,CAAiB,OAqElC,CAAA,aAAA,CAAA;AAQlD,KA5EK,MAAA,GAAS,gBAAA,CAAiB,OA4EI,CAAA,QAAA,CAAA,GA5EgB,gBAAA,CAAiB,OA4EjC,CAAA,QAAA,CAAA;;;;;;AAQnC;AAOA;;;;;AAMA;AAMA;AAOA;;AAEe,UA3FE,aAAA,CA2FF;EAF2B,QAAA,EAAA,YAAA,GAAA,OAAA;EAAS,IAAA,CAAA,EAAA,MAAA;EAKlC,GAAA,CAAA,EAAA,MAAA;EAKA,SAAA,CAAA,EAAA,MAAA;EAOA,UAAA,CAAA,EAAA,MAAA;EAMA,UAAA,CAAA,EAAA,MAAA;EAoBA,SAAA,CAAA,EAAA,MAAA;EASL,QAAA,CAAA,EAAA,MAAc;EACpB,KAAA,CAAA,EAAA,MAAA;;;;;;AAMA,UAnIW,UAAA,CAmIX;;;;;AAMA,KAjIM,gBAAA,GAAmB,aAiIzB,GAjIyC,UAiIzC;AACA,KA5HM,SAAA,GA4HN;EAA+B,SAAA,EAAA,MAAA;EAAwB,OAAA,EA1HhD,gBA0HgD;EAKjD,UAAA,CAAA,EAAA,MAAY;CACd;AAAkB,UA5HX,aAAA,SAAsB,SA4HX,CAAA;EAAiB,SAAA,EAAA,WAAA;EAAC,IAAA,EAAA,MAAA;AAM9C;AAAmC,UA7HlB,gBAAA,SAAyB,SA6HP,CAAA;EAAoC,SAAA,EAAA,cAAA;EAAa,OAAA,EA3HvE,eAAA,CAAgB,OA2HuD,CAAA,SAAA,CAAA;;AACvE,UAzHI,eAAA,SAAwB,SAyH5B,CAAA;EAAgB,SAAA,EAAA,aAAA;
|
|
1
|
+
{"version":3,"file":"events.d.ts","names":[],"sources":["../src/events/types.ts","../src/events/events.ts","../src/events/mediator.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/events.js
CHANGED
|
@@ -28,8 +28,8 @@ function createEvent(eventType, data) {
|
|
|
28
28
|
* @param event - The view page event to send
|
|
29
29
|
* @param eventMediator - The event mediator to send the event to
|
|
30
30
|
*/
|
|
31
|
-
function sendViewPageEvent(event, eventMediator) {
|
|
32
|
-
eventMediator.track(event);
|
|
31
|
+
function sendViewPageEvent(event, eventMediator, siteInfo) {
|
|
32
|
+
eventMediator.track(event, siteInfo);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
//#endregion
|
|
@@ -48,8 +48,8 @@ let mediatorInstance;
|
|
|
48
48
|
* @returns EventMediator instance
|
|
49
49
|
*/
|
|
50
50
|
function createEventMediator(getAdapters) {
|
|
51
|
-
return { track: (event) => {
|
|
52
|
-
processEventWithAdapters(event, getAdapters).catch((error) => {
|
|
51
|
+
return { track: (event, siteInfo) => {
|
|
52
|
+
processEventWithAdapters(event, getAdapters, siteInfo).catch((error) => {
|
|
53
53
|
console.error("Analytics tracking failed:", error);
|
|
54
54
|
});
|
|
55
55
|
} };
|
|
@@ -82,7 +82,7 @@ function resetEventMediator() {
|
|
|
82
82
|
* @param event - The analytics event to process
|
|
83
83
|
* @param getAdapters - Function that returns the current array of event adapters
|
|
84
84
|
*/
|
|
85
|
-
async function processEventWithAdapters(event, getAdapters) {
|
|
85
|
+
async function processEventWithAdapters(event, getAdapters, siteInfo) {
|
|
86
86
|
const eventAdapters = getAdapters();
|
|
87
87
|
if (eventAdapters.length === 0) {
|
|
88
88
|
console.warn(`There are no active adapters to send the event to`);
|
|
@@ -90,7 +90,7 @@ async function processEventWithAdapters(event, getAdapters) {
|
|
|
90
90
|
}
|
|
91
91
|
const promises = eventAdapters.map(async (adapter) => {
|
|
92
92
|
try {
|
|
93
|
-
if (typeof adapter.sendEvent === "function") await adapter.sendEvent(event);
|
|
93
|
+
if (typeof adapter.sendEvent === "function") await adapter.sendEvent(event, siteInfo);
|
|
94
94
|
else console.warn(`Adapter ${adapter.name} does not implement sendEvent`);
|
|
95
95
|
} catch (error) {
|
|
96
96
|
console.error(`Failed to send event to ${adapter.name}:`, error);
|
package/dist/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","names":["mediatorInstance: EventMediator | undefined"],"sources":["../src/events/events.ts","../src/events/mediator.ts"],"sourcesContent":["/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { AnalyticsEvent, EventMediator, EventPayload, EventTypeMap, ViewPageEvent } from './types';\n\n/**\n * Type-safe event creation function\n *\n * This generic function allows creating any event type under AnalyticsEvent\n * with full type safety. The event type is inferred from the string literal\n * passed as the first parameter, and TypeScript will enforce the correct\n * data properties for that specific event type.\n *\n * @example\n * ```typescript\n * const viewPageEvent = createEvent('view_page', { path: '/products', payload });\n * const viewProductEvent = createEvent('view_product', { product, payload });\n * ```\n */\nexport function createEvent<T extends AnalyticsEvent['eventType']>(\n eventType: T,\n data: EventPayload<T>\n): EventTypeMap[T] {\n return {\n eventType,\n ...data,\n } as EventTypeMap[T];\n}\n\n/**\n * Send a view page event to the event mediator\n *\n * This wrapper function is used in the automated page view event tracking client middleware.\n * This function exists to support build-time checks and type safety.\n *\n * @param event - The view page event to send\n * @param eventMediator - The event mediator to send the event to\n */\nexport function sendViewPageEvent(event: ViewPageEvent, eventMediator: EventMediator): void {\n eventMediator.track(event);\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { EventMediator, AnalyticsEvent, EventAdapter } from './types';\n\n// Module-level storage for the event mediator singleton\n// This ensures a single mediator instance across all usages\nlet mediatorInstance: EventMediator | undefined;\n\n/**\n * Create an event mediator instance\n *\n * Creates a new EventMediator that processes events through the provided adapters.\n * The mediator uses the getAdapters function on each track() invocation to ensure\n * it always uses the latest adapters from the adapter registry.\n *\n * @param getAdapters - Function that returns the current array of engagement adapters.\n * This function is called on each track() invocation to ensure\n * the mediator always uses the latest adapters from the adapter registry.\n * @returns EventMediator instance\n */\nfunction createEventMediator(getAdapters: () => EventAdapter[]): EventMediator {\n return {\n track: (event: AnalyticsEvent) => {\n processEventWithAdapters(event, getAdapters).catch((error) => {\n // eslint-disable-next-line no-console\n console.error('Analytics tracking failed:', error);\n });\n },\n };\n}\n\n/**\n * Get the event mediator singleton instance\n *\n * Returns the singleton EventMediator instance, creating it if it doesn't exist.\n *\n * @param getAdapters - Function that returns the current array of engagement adapters.\n * @returns EventMediator instance (singleton) or undefined if not on client side\n */\nexport function getEventMediator(getAdapters: () => EventAdapter[]): EventMediator | undefined {\n // If mediator already exists, return it\n if (mediatorInstance) {\n return mediatorInstance;\n }\n\n // Only create on client side\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n // Create the event mediator singleton\n mediatorInstance = createEventMediator(getAdapters);\n return mediatorInstance;\n}\n\n/**\n * Reset the event mediator singleton (for testing only)\n *\n * This function clears the singleton instance, allowing tests to create a fresh mediator.\n */\nexport function resetEventMediator(): void {\n mediatorInstance = undefined;\n}\n\n/**\n * Process an event with all registered adapters\n *\n * @param event - The analytics event to process\n * @param getAdapters - Function that returns the current array of event adapters\n */\nasync function processEventWithAdapters(event: AnalyticsEvent
|
|
1
|
+
{"version":3,"file":"events.js","names":["mediatorInstance: EventMediator | undefined"],"sources":["../src/events/events.ts","../src/events/mediator.ts"],"sourcesContent":["/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { AnalyticsEvent, EventMediator, EventPayload, EventSiteInfo, EventTypeMap, ViewPageEvent } from './types';\n\n/**\n * Type-safe event creation function\n *\n * This generic function allows creating any event type under AnalyticsEvent\n * with full type safety. The event type is inferred from the string literal\n * passed as the first parameter, and TypeScript will enforce the correct\n * data properties for that specific event type.\n *\n * @example\n * ```typescript\n * const viewPageEvent = createEvent('view_page', { path: '/products', payload });\n * const viewProductEvent = createEvent('view_product', { product, payload });\n * ```\n */\nexport function createEvent<T extends AnalyticsEvent['eventType']>(\n eventType: T,\n data: EventPayload<T>\n): EventTypeMap[T] {\n return {\n eventType,\n ...data,\n } as EventTypeMap[T];\n}\n\n/**\n * Send a view page event to the event mediator\n *\n * This wrapper function is used in the automated page view event tracking client middleware.\n * This function exists to support build-time checks and type safety.\n *\n * @param event - The view page event to send\n * @param eventMediator - The event mediator to send the event to\n */\nexport function sendViewPageEvent(event: ViewPageEvent, eventMediator: EventMediator, siteInfo?: EventSiteInfo): void {\n eventMediator.track(event, siteInfo);\n}\n","/**\n * Copyright 2026 Salesforce, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { EventMediator, AnalyticsEvent, EventAdapter, EventSiteInfo } from './types';\n\n// Module-level storage for the event mediator singleton\n// This ensures a single mediator instance across all usages\nlet mediatorInstance: EventMediator | undefined;\n\n/**\n * Create an event mediator instance\n *\n * Creates a new EventMediator that processes events through the provided adapters.\n * The mediator uses the getAdapters function on each track() invocation to ensure\n * it always uses the latest adapters from the adapter registry.\n *\n * @param getAdapters - Function that returns the current array of engagement adapters.\n * This function is called on each track() invocation to ensure\n * the mediator always uses the latest adapters from the adapter registry.\n * @returns EventMediator instance\n */\nfunction createEventMediator(getAdapters: () => EventAdapter[]): EventMediator {\n return {\n track: (event: AnalyticsEvent, siteInfo?: EventSiteInfo) => {\n processEventWithAdapters(event, getAdapters, siteInfo).catch((error) => {\n // eslint-disable-next-line no-console\n console.error('Analytics tracking failed:', error);\n });\n },\n };\n}\n\n/**\n * Get the event mediator singleton instance\n *\n * Returns the singleton EventMediator instance, creating it if it doesn't exist.\n *\n * @param getAdapters - Function that returns the current array of engagement adapters.\n * @returns EventMediator instance (singleton) or undefined if not on client side\n */\nexport function getEventMediator(getAdapters: () => EventAdapter[]): EventMediator | undefined {\n // If mediator already exists, return it\n if (mediatorInstance) {\n return mediatorInstance;\n }\n\n // Only create on client side\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n // Create the event mediator singleton\n mediatorInstance = createEventMediator(getAdapters);\n return mediatorInstance;\n}\n\n/**\n * Reset the event mediator singleton (for testing only)\n *\n * This function clears the singleton instance, allowing tests to create a fresh mediator.\n */\nexport function resetEventMediator(): void {\n mediatorInstance = undefined;\n}\n\n/**\n * Process an event with all registered adapters\n *\n * @param event - The analytics event to process\n * @param getAdapters - Function that returns the current array of event adapters\n */\nasync function processEventWithAdapters(\n event: AnalyticsEvent,\n getAdapters: () => EventAdapter[],\n siteInfo?: EventSiteInfo\n): Promise<void> {\n // Get the current array of event adapters\n const eventAdapters = getAdapters();\n if (eventAdapters.length === 0) {\n // eslint-disable-next-line no-console\n console.warn(`There are no active adapters to send the event to`);\n return;\n }\n\n // Send event to all registered adapters that implement sendEvent in parallel\n const promises = eventAdapters.map(async (adapter) => {\n try {\n if (typeof adapter.sendEvent === 'function') {\n await adapter.sendEvent(event, siteInfo);\n } else {\n // eslint-disable-next-line no-console\n console.warn(`Adapter ${adapter.name} does not implement sendEvent`);\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(`Failed to send event to ${adapter.name}:`, error);\n }\n });\n\n await Promise.allSettled(promises);\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgCA,SAAgB,YACZ,WACA,MACe;AACf,QAAO;EACH;EACA,GAAG;EACN;;;;;;;;;;;AAYL,SAAgB,kBAAkB,OAAsB,eAA8B,UAAgC;AAClH,eAAc,MAAM,OAAO,SAAS;;;;;AChCxC,IAAIA;;;;;;;;;;;;;AAcJ,SAAS,oBAAoB,aAAkD;AAC3E,QAAO,EACH,QAAQ,OAAuB,aAA6B;AACxD,2BAAyB,OAAO,aAAa,SAAS,CAAC,OAAO,UAAU;AAEpE,WAAQ,MAAM,8BAA8B,MAAM;IACpD;IAET;;;;;;;;;;AAWL,SAAgB,iBAAiB,aAA8D;AAE3F,KAAI,iBACA,QAAO;AAIX,KAAI,OAAO,WAAW,YAClB;AAIJ,oBAAmB,oBAAoB,YAAY;AACnD,QAAO;;;;;;;AAQX,SAAgB,qBAA2B;AACvC,oBAAmB;;;;;;;;AASvB,eAAe,yBACX,OACA,aACA,UACa;CAEb,MAAM,gBAAgB,aAAa;AACnC,KAAI,cAAc,WAAW,GAAG;AAE5B,UAAQ,KAAK,oDAAoD;AACjE;;CAIJ,MAAM,WAAW,cAAc,IAAI,OAAO,YAAY;AAClD,MAAI;AACA,OAAI,OAAO,QAAQ,cAAc,WAC7B,OAAM,QAAQ,UAAU,OAAO,SAAS;OAGxC,SAAQ,KAAK,WAAW,QAAQ,KAAK,+BAA+B;WAEnE,OAAO;AAEZ,WAAQ,MAAM,2BAA2B,QAAQ,KAAK,IAAI,MAAM;;GAEtE;AAEF,OAAM,QAAQ,WAAW,SAAS"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/design/messaging-api/domain-types.ts","../src/design/messaging-api/api-types.ts","../src/design/messaging-api/client.ts","../src/design/messaging-api/host.ts"],"sourcesContent":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/design/messaging-api/domain-types.ts","../src/design/messaging-api/api-types.ts","../src/design/messaging-api/client.ts","../src/design/messaging-api/host.ts"],"sourcesContent":[],"mappings":"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"}
|