@coveo/headless 3.28.4-pre.d32ce92b15 → 3.28.4-pre.d4e891a69f

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.
Files changed (47) hide show
  1. package/dist/cjs/case-assist/headless.cjs +1 -1
  2. package/dist/cjs/commerce/headless.cjs +61 -25
  3. package/dist/cjs/commerce/node.cjs.stats.json +1 -1
  4. package/dist/cjs/headless.cjs +1 -1
  5. package/dist/cjs/insight/headless.cjs +1 -1
  6. package/dist/cjs/recommendation/headless.cjs +1 -1
  7. package/dist/cjs/ssr/headless.cjs +1 -1
  8. package/dist/cjs/ssr-commerce/headless.cjs +61 -25
  9. package/dist/cjs/ssr-commerce/node.cjs.stats.json +1 -1
  10. package/dist/cjs/ssr-commerce-next/headless.cjs +61 -25
  11. package/dist/cjs/ssr-commerce-next/node.cjs.stats.json +1 -1
  12. package/dist/cjs/ssr-next/headless.cjs +1 -1
  13. package/dist/definitions/api/commerce/common/product.d.ts +4 -0
  14. package/dist/definitions/ssr-commerce-next.index.d.ts +1 -1
  15. package/dist/definitions/ssr-next/commerce/controller-utils.d.ts +6 -7
  16. package/dist/definitions/ssr-next/commerce/controllers/context/headless-context.ssr.d.ts +3 -1
  17. package/dist/definitions/ssr-next/commerce/controllers/parameter-manager/headless-core-parameter-manager.ssr.d.ts +2 -1
  18. package/dist/definitions/ssr-next/commerce/types/controller-inference.d.ts +3 -2
  19. package/dist/definitions/ssr-next/common/builders/controller-builder.d.ts +17 -0
  20. package/dist/definitions/ssr-next/common/builders/static-controller-builder.d.ts +24 -0
  21. package/dist/definitions/ssr-next/common/controller-utils.d.ts +6 -6
  22. package/dist/definitions/ssr-next/common/types/controllers.d.ts +6 -0
  23. package/dist/definitions/ssr-next/common/types/inference.d.ts +3 -2
  24. package/dist/definitions/test/mock-controller.d.ts +9 -0
  25. package/dist/definitions/test/mock-ssr-controller-definitions.d.ts +38 -0
  26. package/dist/esm/controllers/commerce/core/interactive-product/headless-core-interactive-product.js +2 -1
  27. package/dist/esm/features/commerce/instant-products/instant-products-slice.js +6 -3
  28. package/dist/esm/features/commerce/product-listing/product-listing-slice.js +7 -4
  29. package/dist/esm/features/commerce/recommendations/recommendations-slice.js +7 -4
  30. package/dist/esm/features/commerce/search/search-slice.js +7 -4
  31. package/dist/esm/ssr-next/commerce/controller-utils.js +6 -18
  32. package/dist/esm/ssr-next/commerce/controllers/cart/headless-cart.ssr.js +3 -5
  33. package/dist/esm/ssr-next/commerce/controllers/context/headless-context.ssr.js +1 -1
  34. package/dist/esm/ssr-next/common/builders/controller-builder.js +38 -0
  35. package/dist/esm/ssr-next/common/builders/static-controller-builder.js +46 -0
  36. package/dist/esm/ssr-next/common/controller-utils.js +7 -13
  37. package/dist/esm/test/mock-controller.js +13 -0
  38. package/dist/esm/test/mock-ssr-controller-definitions.js +43 -0
  39. package/dist/esm/utils/version.js +1 -1
  40. package/dist/quantic/case-assist/headless.js +1 -1
  41. package/dist/quantic/commerce/browser.cjs.stats.json +1 -1
  42. package/dist/quantic/commerce/headless.js +7 -7
  43. package/dist/quantic/commerce/headless.js.map +3 -3
  44. package/dist/quantic/headless.js +1 -1
  45. package/dist/quantic/insight/headless.js +1 -1
  46. package/dist/quantic/recommendation/headless.js +1 -1
  47. package/package.json +1 -1
@@ -1306,7 +1306,7 @@ var import_toolkit2 = require("@reduxjs/toolkit");
1306
1306
  var import_toolkit = require("@reduxjs/toolkit");
1307
1307
 
1308
1308
  // src/utils/version.ts
1309
- var VERSION = "3.28.4-pre.d32ce92b15";
1309
+ var VERSION = "3.28.4-pre.d4e891a69f";
1310
1310
  var COVEO_FRAMEWORK = ["@coveo/atomic", "@coveo/quantic"];
1311
1311
 
1312
1312
  // src/api/analytics/analytics-selectors.ts
@@ -130,6 +130,10 @@ export interface BaseProduct {
130
130
  * The length and offset of each word to highlight in the product excerpt string.
131
131
  */
132
132
  excerptsHighlights?: HighlightKeyword[];
133
+ /**
134
+ * The ID of the response that returned the product.
135
+ */
136
+ responseId?: string;
133
137
  }
134
138
  export interface Product extends BaseProduct {
135
139
  /**
@@ -93,7 +93,7 @@ export type { InstantProducts, InstantProductsDefinition, InstantProductsOptions
93
93
  export { defineInstantProducts } from './ssr-next/commerce/controllers/instant-products/headless-instant-products.ssr.js';
94
94
  export type { CorePaginationOptions, Pagination, PaginationOptions, PaginationProps, PaginationState, } from './ssr-next/commerce/controllers/pagination/headless-core-commerce-pagination.ssr.js';
95
95
  export { definePagination } from './ssr-next/commerce/controllers/pagination/headless-core-commerce-pagination.ssr.js';
96
- export type { CommerceSearchParameters, ParameterManager, ParameterManagerProps, ParameterManagerState, Parameters, ProductListingParameters, SSRParameterManagerProps, } from './ssr-next/commerce/controllers/parameter-manager/headless-core-parameter-manager.ssr.js';
96
+ export type { CommerceSearchParameters, ParameterManager, ParameterManagerDefinition, ParameterManagerProps, ParameterManagerState, Parameters, ProductListingParameters, SSRParameterManagerProps, } from './ssr-next/commerce/controllers/parameter-manager/headless-core-parameter-manager.ssr.js';
97
97
  export { defineParameterManager } from './ssr-next/commerce/controllers/parameter-manager/headless-core-parameter-manager.ssr.js';
98
98
  export type { ProductList, ProductListing, ProductListState, Search, } from './ssr-next/commerce/controllers/product-list/headless-product-list.ssr.js';
99
99
  export { defineProductList } from './ssr-next/commerce/controllers/product-list/headless-product-list.ssr.js';
@@ -1,19 +1,18 @@
1
1
  import type { UnknownAction } from '@reduxjs/toolkit';
2
2
  import type { Controller } from '../../controllers/controller/headless-controller.js';
3
- import type { ControllersMap } from '../common/types/controllers.js';
4
3
  import type { SSRCommerceEngine } from './factories/build-factory.js';
5
4
  import type { SolutionType } from './types/controller-constants.js';
6
- import type { ControllerDefinitionOption, ControllerDefinitionsMap, InferControllerStaticStateMapFromControllers } from './types/controller-definitions.js';
7
- import type { InferControllerPropsMapFromDefinitions, InferControllersMapFromDefinition } from './types/controller-inference.js';
5
+ import type { ControllerDefinitionOption, ControllerDefinitionsMap } from './types/controller-definitions.js';
6
+ import type { InferControllerPropsMapFromDefinitions, InferControllerStaticStateMapFromDefinitionsWithSolutionType, InferControllersMapFromDefinition } from './types/controller-inference.js';
8
7
  import type { EngineStaticState } from './types/engine.js';
9
- export declare function createStaticState<TSearchAction extends UnknownAction>({ searchActions, controllers, }: {
8
+ export declare function createStaticState<TSearchAction extends UnknownAction, TControllerDefinitions extends ControllerDefinitionsMap<Controller>>({ searchActions, controllers, }: {
10
9
  searchActions: TSearchAction[];
11
- controllers: ControllersMap;
12
- }): EngineStaticState<TSearchAction, InferControllerStaticStateMapFromControllers<ControllersMap>>;
10
+ controllers: InferControllersMapFromDefinition<TControllerDefinitions, SolutionType>;
11
+ }): EngineStaticState<TSearchAction, InferControllerStaticStateMapFromDefinitionsWithSolutionType<TControllerDefinitions, SolutionType>>;
13
12
  export declare function buildControllerDefinitions<TControllerDefinitionsMap extends ControllerDefinitionsMap<Controller>, TSolutionType extends SolutionType>({ definitionsMap, engine, solutionType, propsMap, }: {
14
13
  definitionsMap: TControllerDefinitionsMap;
15
14
  engine: SSRCommerceEngine;
16
15
  solutionType: TSolutionType;
17
- propsMap: InferControllerPropsMapFromDefinitions<TControllerDefinitionsMap>;
16
+ propsMap?: InferControllerPropsMapFromDefinitions<TControllerDefinitionsMap>;
18
17
  }): InferControllersMapFromDefinition<TControllerDefinitionsMap, TSolutionType>;
19
18
  export declare function ensureAtLeastOneSolutionType(options?: ControllerDefinitionOption): void;
@@ -1,7 +1,9 @@
1
1
  import { type Context, type ContextOptions, type ContextProps, type ContextState, type UserLocation, type View } from '../../../../controllers/commerce/context/headless-context.js';
2
2
  import type { UniversalControllerDefinitionWithProps } from '../../types/controller-definitions.js';
3
3
  export type { Context, ContextProps, ContextState, View, UserLocation, ContextOptions, };
4
- export interface ContextDefinition extends UniversalControllerDefinitionWithProps<Context, ContextOptions> {
4
+ export interface ContextDefinition extends UniversalControllerDefinitionWithProps<Context, {
5
+ initialState: ContextOptions;
6
+ }> {
5
7
  }
6
8
  /**
7
9
  * Defines a `Context` controller instance.
@@ -4,13 +4,14 @@ import type { ProductListingParameters } from '../../../../features/commerce/pro
4
4
  import type { CommerceSearchParameters } from '../../../../features/commerce/search-parameters/search-parameters-actions.js';
5
5
  import type { ControllerDefinitionOption, SubControllerDefinitionWithProps } from '../../types/controller-definitions.js';
6
6
  export type { ParameterManager, ParameterManagerProps, ParameterManagerState, Parameters, ProductListingParameters, CommerceSearchParameters, };
7
+ export type ParameterManagerDefinition<TOptions extends ControllerDefinitionOption | undefined> = SubControllerDefinitionWithProps<ParameterManager<MappedParameterTypes<TOptions>>, TOptions, SSRParameterManagerProps<MappedParameterTypes<TOptions>>>;
7
8
  /**
8
9
  * Defines a `ParameterManager` controller instance.
9
10
  * @group Definers
10
11
  *
11
12
  * @returns The `ParameterManager` controller definition.
12
13
  */
13
- export declare function defineParameterManager<TOptions extends ControllerDefinitionOption | undefined>(options?: TOptions): SubControllerDefinitionWithProps<ParameterManager<MappedParameterTypes<TOptions>>, TOptions, SSRParameterManagerProps<MappedParameterTypes<TOptions>>>;
14
+ export declare function defineParameterManager<TOptions extends ControllerDefinitionOption | undefined>(options?: TOptions): ParameterManagerDefinition<TOptions>;
14
15
  export interface SSRParameterManagerProps<T extends Parameters> extends Omit<ParameterManagerProps<T>, 'excludeDefaultParameters'> {
15
16
  }
16
17
  type MappedParameterTypes<TOptions extends ControllerDefinitionOption | undefined> = TOptions extends {
@@ -8,7 +8,7 @@ export type InferStaticState<T extends {
8
8
  export type InferHydratedState<T extends {
9
9
  hydrateStaticState(...args: unknown[]): Promise<unknown>;
10
10
  }> = Awaited<ReturnType<T['hydrateStaticState']>>;
11
- export type InferControllerPropsFromDefinition<TController extends ControllerDefinition<Controller>> = TController extends ControllerDefinitionWithProps<Controller, infer Props> ? HasKey<TController, typeof recommendationInternalOptionKey> extends never ? Props : Props & RecommendationControllerSettings : TController extends ControllerDefinitionWithoutProps<Controller> ? HasKey<TController, typeof recommendationInternalOptionKey> extends never ? {} : RecommendationControllerSettings : unknown;
11
+ type InferControllerPropsFromDefinition<TController extends ControllerDefinition<Controller>> = TController extends ControllerDefinitionWithProps<Controller, infer Props> ? HasKey<TController, typeof recommendationInternalOptionKey> extends never ? Props : Props & RecommendationControllerSettings : TController extends ControllerDefinitionWithoutProps<Controller> ? HasKey<TController, typeof recommendationInternalOptionKey> extends never ? {} : RecommendationControllerSettings : unknown;
12
12
  export type InferControllerPropsMapFromDefinitions<TControllers extends ControllerDefinitionsMap<Controller>> = {
13
13
  [K in keyof TControllers as HasKeys<InferControllerPropsFromDefinition<TControllers[K]>> extends false ? never : K]: InferControllerPropsFromDefinition<TControllers[K]>;
14
14
  };
@@ -17,5 +17,6 @@ export type InferControllersMapFromDefinition<TControllers extends ControllerDef
17
17
  [K in keyof TControllers as HasKey<TControllers[K], TSolutionType> extends never ? never : K]: InferControllerFromDefinition<TControllers[K]>;
18
18
  };
19
19
  export type InferControllerStaticStateMapFromDefinitionsWithSolutionType<TControllers extends ControllerDefinitionsMap<Controller>, TSolutionType extends SolutionType> = {
20
- [K in keyof TControllers as HasKey<TControllers[K], TSolutionType> extends never ? never : K]: InferControllerStaticStateFromController<InferControllerFromDefinition<TControllers[K]>>;
20
+ [K in keyof TControllers as HasKey<TControllers[K], TSolutionType> extends never ? never : K]: InferControllerStaticStateFromController<InferControllerFromDefinition<TControllers[K]>> & InferControllerPropsFromDefinition<TControllers[K]>;
21
21
  };
22
+ export {};
@@ -0,0 +1,17 @@
1
+ import type { CoreEngine, CoreEngineNext } from '../../../app/engine.js';
2
+ import type { Controller } from '../../../controllers/controller/headless-controller.js';
3
+ import type { BaseControllerDefinitionWithoutProps, BaseControllerDefinitionWithProps } from '../types/controllers.js';
4
+ /**
5
+ * Builder class for creating controllers from definitions
6
+ */
7
+ export declare class ControllerBuilder<TDefinition extends Partial<BaseControllerDefinitionWithoutProps<TEngine, TController>> & Partial<BaseControllerDefinitionWithProps<TEngine, TController, TProps>>, TEngine extends CoreEngine | CoreEngineNext, TProps, TController extends Controller = Controller> {
8
+ private _definition;
9
+ private _engine;
10
+ private _props?;
11
+ private _additionalArgs;
12
+ constructor(definition: TDefinition, engine: TEngine, props?: TProps);
13
+ withAdditionalArgs(additionalArgs?: unknown[]): this;
14
+ build(): TController;
15
+ private buildWithoutProps;
16
+ private buildWithProps;
17
+ }
@@ -0,0 +1,24 @@
1
+ import type { Controller } from '../../../controllers/controller/headless-controller.js';
2
+ import type { ControllerWithKind } from '../../commerce/types/controller-definitions.js';
3
+ import type { Kind } from '../../commerce/types/kind.js';
4
+ export type StaticControllerState = {
5
+ initialState?: Controller['state'];
6
+ _kind?: Kind;
7
+ } & Pick<ControllerWithKind, 'state'>;
8
+ /**
9
+ * Builder class for creating static controller
10
+ */
11
+ declare class StaticControllerBuilder {
12
+ private _state?;
13
+ private _kind?;
14
+ private _initialState?;
15
+ withState(state: StaticControllerState['state']): this;
16
+ withKind(kind: Kind): this;
17
+ withInitialState(initialState: StaticControllerState['initialState']): this;
18
+ /**
19
+ * Builds and returns the static controller state object
20
+ */
21
+ build(): StaticControllerState;
22
+ }
23
+ export declare function createStaticControllerBuilder<TController extends Controller>(controller: TController): StaticControllerBuilder;
24
+ export {};
@@ -1,15 +1,15 @@
1
1
  import type { UnknownAction } from '@reduxjs/toolkit';
2
2
  import type { CoreEngine, CoreEngineNext } from '../../app/engine.js';
3
3
  import type { Controller } from '../../controllers/controller/headless-controller.js';
4
- import type { ControllerDefinitionsMap, ControllersMap } from './types/controllers.js';
4
+ import type { ControllerDefinitionsMap } from './types/controllers.js';
5
5
  import type { EngineStaticState } from './types/engine.js';
6
- import type { InferControllerPropsMapFromDefinitions, InferControllerStaticStateMapFromControllers, InferControllersMapFromDefinition } from './types/inference.js';
6
+ import type { InferControllerPropsMapFromDefinitions, InferControllerStaticStateMapFromDefinitions, InferControllersMapFromDefinition } from './types/inference.js';
7
7
  export declare function buildControllerDefinitions<TControllerDefinitionsMap extends ControllerDefinitionsMap<CoreEngine | CoreEngineNext, Controller>, TEngine extends CoreEngine | CoreEngineNext>({ definitionsMap, engine, propsMap, }: {
8
8
  definitionsMap: TControllerDefinitionsMap;
9
9
  engine: TEngine;
10
- propsMap: InferControllerPropsMapFromDefinitions<TControllerDefinitionsMap>;
10
+ propsMap?: InferControllerPropsMapFromDefinitions<TControllerDefinitionsMap>;
11
11
  }): InferControllersMapFromDefinition<TControllerDefinitionsMap>;
12
- export declare function createStaticState<TSearchAction extends UnknownAction>({ searchAction, controllers, }: {
12
+ export declare function createStaticState<TSearchAction extends UnknownAction, TControllerDefinitions extends ControllerDefinitionsMap<CoreEngine | CoreEngineNext, Controller>>({ searchAction, controllers, }: {
13
13
  searchAction: TSearchAction;
14
- controllers: ControllersMap;
15
- }): EngineStaticState<TSearchAction, InferControllerStaticStateMapFromControllers<ControllersMap>>;
14
+ controllers: InferControllersMapFromDefinition<TControllerDefinitions>;
15
+ }): EngineStaticState<TSearchAction, InferControllerStaticStateMapFromDefinitions<TControllerDefinitions>>;
@@ -9,6 +9,12 @@ export interface ControllerStaticState<TState> {
9
9
  export interface ControllerStaticStateMap {
10
10
  [customName: string]: ControllerStaticState<unknown>;
11
11
  }
12
+ export interface BaseControllerDefinitionWithoutProps<TEngine, TController extends Controller> {
13
+ build(engine: TEngine, ...args: unknown[]): TController;
14
+ }
15
+ export interface BaseControllerDefinitionWithProps<TEngine, TController extends Controller, TProps> {
16
+ buildWithProps(engine: TEngine, props?: TProps, ...args: unknown[]): TController;
17
+ }
12
18
  export interface ControllerDefinitionWithoutProps<TEngine extends CoreEngine | CoreEngineNext, TController extends Controller> {
13
19
  /**
14
20
  * Creates an instance of the given controller.
@@ -2,7 +2,7 @@ import type { CoreEngine, CoreEngineNext } from '../../../app/engine.js';
2
2
  import type { Controller } from '../../../controllers/controller/headless-controller.js';
3
3
  import type { ControllerDefinition, ControllerDefinitionsMap, ControllerDefinitionWithoutProps, ControllerDefinitionWithProps, ControllerStaticState, ControllersMap } from './controllers.js';
4
4
  import type { HasKeys } from './utilities.js';
5
- export type InferControllerPropsFromDefinition<TController extends ControllerDefinition<CoreEngine | CoreEngineNext, Controller>> = TController extends ControllerDefinitionWithProps<CoreEngine | CoreEngineNext, Controller, infer Props> ? Props : TController extends ControllerDefinitionWithoutProps<CoreEngine | CoreEngineNext, Controller> ? {} : unknown;
5
+ type InferControllerPropsFromDefinition<TController extends ControllerDefinition<CoreEngine | CoreEngineNext, Controller>> = TController extends ControllerDefinitionWithProps<CoreEngine | CoreEngineNext, Controller, infer Props> ? Props : TController extends ControllerDefinitionWithoutProps<CoreEngine | CoreEngineNext, Controller> ? {} : unknown;
6
6
  export type InferControllerPropsMapFromDefinitions<TControllers extends ControllerDefinitionsMap<CoreEngine | CoreEngineNext, Controller>> = {
7
7
  [K in keyof TControllers as HasKeys<InferControllerPropsFromDefinition<TControllers[K]>> extends false ? never : K]: InferControllerPropsFromDefinition<TControllers[K]>;
8
8
  };
@@ -12,8 +12,9 @@ export type InferControllersMapFromDefinition<TControllers extends ControllerDef
12
12
  };
13
13
  export type InferControllerStaticStateFromController<TController extends Controller> = ControllerStaticState<TController['state']>;
14
14
  export type InferControllerStaticStateMapFromDefinitions<TControllers extends ControllerDefinitionsMap<CoreEngine | CoreEngineNext, Controller>> = {
15
- [K in keyof TControllers]: InferControllerStaticStateFromController<InferControllerFromDefinition<TControllers[K]>>;
15
+ [K in keyof TControllers]: InferControllerStaticStateFromController<InferControllerFromDefinition<TControllers[K]>> & InferControllerPropsFromDefinition<TControllers[K]>;
16
16
  };
17
17
  export type InferControllerStaticStateMapFromControllers<TControllers extends ControllersMap> = {
18
18
  [K in keyof TControllers]: InferControllerStaticStateFromController<TControllers[K]>;
19
19
  };
20
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { CoreEngine, CoreEngineNext } from '../app/engine.js';
2
+ import type { Controller } from '../controllers/controller/headless-controller.js';
3
+ import type { SSRCommerceEngine } from '../ssr/commerce/factories/build-factory.js';
4
+ interface MockController {
5
+ initialState?: Record<string, unknown>;
6
+ }
7
+ export declare function buildMockController(): Controller;
8
+ export declare function buildMockControllerWithInitialState(_engine: CoreEngine | CoreEngineNext | SSRCommerceEngine, props: MockController): Controller;
9
+ export {};
@@ -0,0 +1,38 @@
1
+ import type { SearchEngine } from '../app/search-engine/search-engine.js';
2
+ import type { Controller } from '../controllers/controller/headless-controller.js';
3
+ import type { Kind } from '../ssr/commerce/types/kind.js';
4
+ import type { ControllerDefinitionWithoutProps, ControllerDefinitionWithProps } from '../ssr-next/common/types/controllers.js';
5
+ interface MockController {
6
+ initialState?: Record<string, unknown>;
7
+ }
8
+ interface MockControllerDefinitionWithoutProps extends ControllerDefinitionWithoutProps<SearchEngine, Controller> {
9
+ }
10
+ interface MockControllerDefinitionWithProps extends ControllerDefinitionWithProps<SearchEngine, Controller, MockController> {
11
+ }
12
+ type SolutionTypeAvailabilities = {
13
+ listing?: boolean;
14
+ search?: boolean;
15
+ standalone?: boolean;
16
+ recommendation?: boolean;
17
+ };
18
+ export declare function defineMockController(): MockControllerDefinitionWithoutProps;
19
+ export declare function defineMockControllerWithProps(): MockControllerDefinitionWithProps;
20
+ export declare function defineMockCommerceController(options?: SolutionTypeAvailabilities): {
21
+ build: import("vitest").Mock<(_engine: any) => Controller>;
22
+ listing: boolean;
23
+ search: boolean;
24
+ standalone: boolean;
25
+ recommendation: boolean;
26
+ };
27
+ export declare function defineMockCommerceControllerWithProps(options?: SolutionTypeAvailabilities): {
28
+ buildWithProps: import("vitest").Mock<(engine: any, props: any) => {
29
+ state: {};
30
+ subscribe(listener: () => void): import("redux").Unsubscribe;
31
+ _kind: Kind;
32
+ }>;
33
+ listing: boolean;
34
+ search: boolean;
35
+ standalone: boolean;
36
+ recommendation: boolean;
37
+ };
38
+ export {};
@@ -49,7 +49,8 @@ permanentid '${props.options.product.permanentid}':\n\n${warnings.join('\n')}\n\
49
49
  props.options.product.permanentid,
50
50
  },
51
51
  position: props.options.product.position,
52
- responseId: props.responseIdSelector(engine[stateKey]),
52
+ responseId: props.options.product.responseId ??
53
+ props.responseIdSelector(engine[stateKey]),
53
54
  }));
54
55
  };
55
56
  return {
@@ -25,7 +25,7 @@ export const instantProductsReducer = createReducer(getInstantProductsInitialSta
25
25
  totalCountFiltered: totalEntries,
26
26
  ...action.meta.arg,
27
27
  }, state, {
28
- products: products.map((product, index) => preprocessProduct(product, index + 1)),
28
+ products: products.map((product, index) => preprocessProduct(product, index + 1, responseId)),
29
29
  });
30
30
  })
31
31
  .addCase(fetchInstantProducts.rejected, (state, action) => {
@@ -45,6 +45,7 @@ export const instantProductsReducer = createReducer(getInstantProductsInitialSta
45
45
  if (currentParentIndex === -1 || childToPromote === undefined) {
46
46
  return;
47
47
  }
48
+ const responseId = products[currentParentIndex].responseId;
48
49
  const position = products[currentParentIndex].position;
49
50
  const { children, totalNumberOfChildren } = products[currentParentIndex];
50
51
  const newParent = {
@@ -52,21 +53,23 @@ export const instantProductsReducer = createReducer(getInstantProductsInitialSta
52
53
  children,
53
54
  totalNumberOfChildren,
54
55
  position,
56
+ responseId,
55
57
  };
56
58
  const newProducts = [...products];
57
59
  newProducts.splice(currentParentIndex, 1, newParent);
58
60
  cache.products = newProducts;
59
61
  });
60
62
  });
61
- function preprocessProduct(product, position) {
63
+ function preprocessProduct(product, position, responseId) {
62
64
  const isParentAlreadyInChildren = product.children.some((child) => child.permanentid === product.permanentid);
63
65
  if (product.children.length === 0 || isParentAlreadyInChildren) {
64
- return { ...product, position };
66
+ return { ...product, position, responseId };
65
67
  }
66
68
  const { children, totalNumberOfChildren: _totalNumberOfChildren, ...restOfProduct } = product;
67
69
  return {
68
70
  ...product,
69
71
  children: [restOfProduct, ...children],
70
72
  position,
73
+ responseId,
71
74
  };
72
75
  }
@@ -14,7 +14,7 @@ export const productListingReducer = createReducer(getProductListingInitialState
14
14
  .addCase(fetchProductListing.fulfilled, (state, action) => {
15
15
  const paginationOffset = getPaginationOffset(action.payload);
16
16
  handleFullfilled(state, action.payload.response);
17
- state.products = action.payload.response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1));
17
+ state.products = action.payload.response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1, action.payload.response.responseId));
18
18
  })
19
19
  .addCase(fetchMoreProducts.fulfilled, (state, action) => {
20
20
  if (!action.payload) {
@@ -22,7 +22,7 @@ export const productListingReducer = createReducer(getProductListingInitialState
22
22
  }
23
23
  const paginationOffset = getPaginationOffset(action.payload);
24
24
  handleFullfilled(state, action.payload.response);
25
- state.products = state.products.concat(action.payload.response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1)));
25
+ state.products = state.products.concat(action.payload.response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1, action.payload?.response.responseId)));
26
26
  })
27
27
  .addCase(fetchProductListing.pending, (state, action) => {
28
28
  handlePending(state, action.meta.requestId);
@@ -40,6 +40,7 @@ export const productListingReducer = createReducer(getProductListingInitialState
40
40
  if (currentParentIndex === -1 || childToPromote === undefined) {
41
41
  return;
42
42
  }
43
+ const responseId = products[currentParentIndex].responseId;
43
44
  const position = products[currentParentIndex].position;
44
45
  const { children, totalNumberOfChildren } = products[currentParentIndex];
45
46
  const newParent = {
@@ -47,6 +48,7 @@ export const productListingReducer = createReducer(getProductListingInitialState
47
48
  children,
48
49
  totalNumberOfChildren,
49
50
  position,
51
+ responseId,
50
52
  };
51
53
  products.splice(currentParentIndex, 1, newParent);
52
54
  })
@@ -74,15 +76,16 @@ function getPaginationOffset(payload) {
74
76
  const pagination = payload.response.pagination;
75
77
  return pagination.page * pagination.perPage;
76
78
  }
77
- function preprocessProduct(product, position) {
79
+ function preprocessProduct(product, position, responseId) {
78
80
  const isParentAlreadyInChildren = product.children.some((child) => child.permanentid === product.permanentid);
79
81
  if (product.children.length === 0 || isParentAlreadyInChildren) {
80
- return { ...product, position };
82
+ return { ...product, position, responseId };
81
83
  }
82
84
  const { children, totalNumberOfChildren: _totalNumberOfChildren, ...restOfProduct } = product;
83
85
  return {
84
86
  ...product,
85
87
  children: [restOfProduct, ...children],
86
88
  position,
89
+ responseId,
87
90
  };
88
91
  }
@@ -31,7 +31,7 @@ export const recommendationsReducer = createReducer(getRecommendationsInitialSta
31
31
  return;
32
32
  }
33
33
  const paginationOffset = getPaginationOffset(action.payload);
34
- recommendations.products = response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1));
34
+ recommendations.products = response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1, response.responseId));
35
35
  })
36
36
  .addCase(fetchMoreRecommendations.fulfilled, (state, action) => {
37
37
  if (!action.payload) {
@@ -45,7 +45,7 @@ export const recommendationsReducer = createReducer(getRecommendationsInitialSta
45
45
  return;
46
46
  }
47
47
  const paginationOffset = getPaginationOffset(action.payload);
48
- recommendations.products = recommendations.products.concat(response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1)));
48
+ recommendations.products = recommendations.products.concat(response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1, response.responseId)));
49
49
  })
50
50
  .addCase(fetchRecommendations.pending, (state, action) => {
51
51
  handlePending(state, action.meta.arg.slotId);
@@ -67,6 +67,7 @@ export const recommendationsReducer = createReducer(getRecommendationsInitialSta
67
67
  if (currentParentIndex === -1 || childToPromote === undefined) {
68
68
  return;
69
69
  }
70
+ const responseId = products[currentParentIndex].responseId;
70
71
  const position = products[currentParentIndex].position;
71
72
  const { children, totalNumberOfChildren } = products[currentParentIndex];
72
73
  const newParent = {
@@ -74,6 +75,7 @@ export const recommendationsReducer = createReducer(getRecommendationsInitialSta
74
75
  children,
75
76
  totalNumberOfChildren,
76
77
  position,
78
+ responseId,
77
79
  };
78
80
  products.splice(currentParentIndex, 1, newParent);
79
81
  })
@@ -119,15 +121,16 @@ function getPaginationOffset(actionPayload) {
119
121
  const pagination = actionPayload.response.pagination;
120
122
  return pagination.page * pagination.perPage;
121
123
  }
122
- function preprocessProduct(product, position) {
124
+ function preprocessProduct(product, position, responseId) {
123
125
  const isParentAlreadyInChildren = product.children.some((child) => child.permanentid === product.permanentid);
124
126
  if (product.children.length === 0 || isParentAlreadyInChildren) {
125
- return { ...product, position };
127
+ return { ...product, position, responseId };
126
128
  }
127
129
  const { children, totalNumberOfChildren: _totalNumberOfChildren, ...restOfProduct } = product;
128
130
  return {
129
131
  ...product,
130
132
  children: [restOfProduct, ...children],
131
133
  position,
134
+ responseId,
132
135
  };
133
136
  }
@@ -14,7 +14,7 @@ export const commerceSearchReducer = createReducer(getCommerceSearchInitialState
14
14
  .addCase(executeSearch.fulfilled, (state, action) => {
15
15
  const paginationOffset = getPaginationOffset(action.payload);
16
16
  handleFulfilled(state, action.payload.response, action.payload.queryExecuted);
17
- state.products = action.payload.response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1));
17
+ state.products = action.payload.response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1, action.payload.response.responseId));
18
18
  })
19
19
  .addCase(fetchMoreProducts.fulfilled, (state, action) => {
20
20
  if (!action.payload) {
@@ -22,7 +22,7 @@ export const commerceSearchReducer = createReducer(getCommerceSearchInitialState
22
22
  }
23
23
  const paginationOffset = getPaginationOffset(action.payload);
24
24
  handleFulfilled(state, action.payload.response, action.payload.queryExecuted);
25
- state.products = state.products.concat(action.payload.response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1)));
25
+ state.products = state.products.concat(action.payload.response.products.map((product, index) => preprocessProduct(product, paginationOffset + index + 1, action.payload?.response.responseId)));
26
26
  })
27
27
  .addCase(executeSearch.pending, (state, action) => {
28
28
  handlePending(state, action.meta.requestId);
@@ -40,6 +40,7 @@ export const commerceSearchReducer = createReducer(getCommerceSearchInitialState
40
40
  if (currentParentIndex === -1 || childToPromote === undefined) {
41
41
  return;
42
42
  }
43
+ const responseId = products[currentParentIndex].responseId;
43
44
  const position = products[currentParentIndex].position;
44
45
  const { children, totalNumberOfChildren } = products[currentParentIndex];
45
46
  const newParent = {
@@ -47,6 +48,7 @@ export const commerceSearchReducer = createReducer(getCommerceSearchInitialState
47
48
  children,
48
49
  totalNumberOfChildren,
49
50
  position,
51
+ responseId,
50
52
  };
51
53
  products.splice(currentParentIndex, 1, newParent);
52
54
  })
@@ -76,15 +78,16 @@ function getPaginationOffset(payload) {
76
78
  const pagination = payload.response.pagination;
77
79
  return pagination.page * pagination.perPage;
78
80
  }
79
- function preprocessProduct(product, position) {
81
+ function preprocessProduct(product, position, responseId) {
80
82
  const isParentAlreadyInChildren = product.children.some((child) => child.permanentid === product.permanentid);
81
83
  if (product.children.length === 0 || isParentAlreadyInChildren) {
82
- return { ...product, position };
84
+ return { ...product, position, responseId };
83
85
  }
84
86
  const { children, totalNumberOfChildren: _totalNumberOfChildren, ...restOfProduct } = product;
85
87
  return {
86
88
  ...product,
87
89
  children: [restOfProduct, ...children],
88
90
  position,
91
+ responseId,
89
92
  };
90
93
  }
@@ -1,22 +1,13 @@
1
1
  import { clone, filterObject, mapObject } from '../../utils/utils.js';
2
+ import { ControllerBuilder } from '../common/builders/controller-builder.js';
3
+ import { createStaticControllerBuilder } from '../common/builders/static-controller-builder.js';
2
4
  import { InvalidControllerDefinition } from '../common/errors.js';
3
- function hasKindProperty(controller) {
4
- return '_kind' in controller;
5
- }
6
5
  export function createStaticState({ searchActions, controllers, }) {
7
6
  return {
8
- controllers: mapObject(controllers, (controller) => ({
9
- state: clone(controller.state),
10
- ...(hasKindProperty(controller) && { _kind: controller._kind }),
11
- })),
7
+ controllers: mapObject(controllers, (controller) => createStaticControllerBuilder(controller).build()),
12
8
  searchActions: searchActions.map((action) => clone(action)),
13
9
  };
14
10
  }
15
- function buildControllerFromDefinition({ definition, engine, solutionType, props, }) {
16
- return ('build' in definition
17
- ? definition.build(engine, solutionType)
18
- : definition.buildWithProps(engine, props, solutionType));
19
- }
20
11
  export function buildControllerDefinitions({ definitionsMap, engine, solutionType, propsMap, }) {
21
12
  const controllerMap = mapObject(definitionsMap, (definition, key) => {
22
13
  const unavailableInSolutionType = () => !(solutionType in definition) ||
@@ -26,12 +17,9 @@ export function buildControllerDefinitions({ definitionsMap, engine, solutionTyp
26
17
  if (unavailableInSolutionType()) {
27
18
  return null;
28
19
  }
29
- return buildControllerFromDefinition({
30
- definition,
31
- engine,
32
- solutionType,
33
- props,
34
- });
20
+ return new ControllerBuilder(definition, engine, props)
21
+ .withAdditionalArgs([solutionType])
22
+ .build();
35
23
  });
36
24
  return filterObject(controllerMap, (value) => value !== null);
37
25
  }
@@ -1,5 +1,4 @@
1
1
  import { buildCart, } from '../../../../controllers/commerce/context/cart/headless-cart.js';
2
- import { MissingControllerProps } from '../../../common/errors.js';
3
2
  import { createControllerWithKind, Kind } from '../../types/kind.js';
4
3
  /**
5
4
  * Defines a `Cart` controller instance.
@@ -14,10 +13,9 @@ export function defineCart() {
14
13
  standalone: true,
15
14
  recommendation: true,
16
15
  buildWithProps: (engine, props) => {
17
- if (props === undefined) {
18
- throw new MissingControllerProps(Kind.Cart);
19
- }
20
- const controller = buildCart(engine, { initialState: props.initialState });
16
+ const controller = buildCart(engine, {
17
+ initialState: props ? props.initialState : {},
18
+ });
21
19
  return createControllerWithKind(controller, Kind.Cart);
22
20
  },
23
21
  };
@@ -17,7 +17,7 @@ export function defineContext() {
17
17
  if (props === undefined) {
18
18
  throw new MissingControllerProps(Kind.Context);
19
19
  }
20
- const controller = buildContext(engine, { options: props });
20
+ const controller = buildContext(engine, { options: props.initialState });
21
21
  return createControllerWithKind(controller, Kind.Context);
22
22
  },
23
23
  };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Builder class for creating controllers from definitions
3
+ */
4
+ export class ControllerBuilder {
5
+ _definition;
6
+ _engine;
7
+ _props;
8
+ _additionalArgs = [];
9
+ constructor(definition, engine, props) {
10
+ this._definition = definition;
11
+ this._engine = engine;
12
+ this._props = props;
13
+ }
14
+ withAdditionalArgs(additionalArgs = []) {
15
+ this._additionalArgs = additionalArgs;
16
+ return this;
17
+ }
18
+ build() {
19
+ if ('build' in this._definition &&
20
+ typeof this._definition.build === 'function') {
21
+ return this.buildWithoutProps();
22
+ }
23
+ if ('buildWithProps' in this._definition &&
24
+ typeof this._definition.buildWithProps === 'function') {
25
+ return this.buildWithProps();
26
+ }
27
+ throw new Error('Controller definition must have a build or buildWithProps method.');
28
+ }
29
+ buildWithoutProps() {
30
+ const buildFn = this._definition.build;
31
+ return buildFn(this._engine, ...this._additionalArgs);
32
+ }
33
+ buildWithProps() {
34
+ const buildWithPropsFn = this._definition.buildWithProps;
35
+ const controller = buildWithPropsFn(this._engine, this._props, ...this._additionalArgs);
36
+ return { ...controller, initialState: controller.state };
37
+ }
38
+ }
@@ -0,0 +1,46 @@
1
+ import { clone } from '../../../utils/utils.js';
2
+ /**
3
+ * Builder class for creating static controller
4
+ */
5
+ class StaticControllerBuilder {
6
+ _state;
7
+ _kind;
8
+ _initialState;
9
+ withState(state) {
10
+ this._state = clone(state);
11
+ return this;
12
+ }
13
+ withKind(kind) {
14
+ this._kind = kind;
15
+ return this;
16
+ }
17
+ withInitialState(initialState) {
18
+ this._initialState = clone(initialState);
19
+ return this;
20
+ }
21
+ /**
22
+ * Builds and returns the static controller state object
23
+ */
24
+ build() {
25
+ const result = {
26
+ state: this._state,
27
+ };
28
+ if (this._kind) {
29
+ result._kind = this._kind;
30
+ }
31
+ if (this._initialState) {
32
+ result.initialState = this._initialState;
33
+ }
34
+ return result;
35
+ }
36
+ }
37
+ export function createStaticControllerBuilder(controller) {
38
+ const builder = new StaticControllerBuilder().withState(controller.state);
39
+ if ('_kind' in controller) {
40
+ builder.withKind(controller._kind);
41
+ }
42
+ if ('initialState' in controller) {
43
+ builder.withInitialState(controller.initialState);
44
+ }
45
+ return builder;
46
+ }