@coveo/headless 3.29.1 → 3.29.2-pre.027eeece31

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 (57) hide show
  1. package/dist/cjs/case-assist/headless.cjs +1 -1
  2. package/dist/cjs/case-assist/node.cjs.stats.json +1 -1
  3. package/dist/cjs/commerce/headless.cjs +1 -1
  4. package/dist/cjs/commerce/node.cjs.stats.json +1 -1
  5. package/dist/cjs/headless.cjs +1 -1
  6. package/dist/cjs/insight/headless.cjs +1 -1
  7. package/dist/cjs/insight/node.cjs.stats.json +1 -1
  8. package/dist/cjs/node.cjs.stats.json +1 -1
  9. package/dist/cjs/recommendation/headless.cjs +1 -1
  10. package/dist/cjs/recommendation/node.cjs.stats.json +1 -1
  11. package/dist/cjs/ssr/headless.cjs +1 -1
  12. package/dist/cjs/ssr/node.cjs.stats.json +1 -1
  13. package/dist/cjs/ssr-commerce/headless.cjs +1 -1
  14. package/dist/cjs/ssr-commerce/node.cjs.stats.json +1 -1
  15. package/dist/cjs/ssr-commerce-next/headless.cjs +1 -1
  16. package/dist/cjs/ssr-commerce-next/node.cjs.stats.json +1 -1
  17. package/dist/cjs/ssr-next/headless.cjs +1 -1
  18. package/dist/cjs/ssr-next/node.cjs.stats.json +1 -1
  19. package/dist/definitions/ssr-next/commerce/controllers/recommendations/headless-recommendations.ssr.d.ts +8 -4
  20. package/dist/definitions/ssr-next/commerce/factories/hydrated-state-factory.d.ts +2 -1
  21. package/dist/definitions/ssr-next/commerce/types/build.d.ts +60 -16
  22. package/dist/definitions/ssr-next/commerce/types/controller-definitions.d.ts +4 -119
  23. package/dist/definitions/ssr-next/commerce/types/controller-inference.d.ts +3 -3
  24. package/dist/definitions/ssr-next/commerce/types/fetch-static-state.d.ts +1 -1
  25. package/dist/definitions/ssr-next/commerce/types/hydrate-static-state.d.ts +2 -1
  26. package/dist/definitions/ssr-next/commerce/utils/controller-wiring.d.ts +29 -2
  27. package/dist/definitions/ssr-next/commerce/utils/engine-wiring.d.ts +1 -1
  28. package/dist/definitions/ssr-next/commerce/utils/recommendation-filter.d.ts +14 -1
  29. package/dist/definitions/ssr-next/common/types/utilities.d.ts +0 -3
  30. package/dist/definitions/test/mock-ssr-controller-definitions.d.ts +12 -0
  31. package/dist/esm/ssr-next/commerce/controllers/recommendations/headless-recommendations.ssr.js +1 -1
  32. package/dist/esm/ssr-next/commerce/factories/build-factory.js +4 -9
  33. package/dist/esm/ssr-next/commerce/factories/hydrated-state-factory.js +1 -3
  34. package/dist/esm/ssr-next/commerce/factories/recommendation-hydrated-state-factory.js +1 -3
  35. package/dist/esm/ssr-next/commerce/factories/recommendation-static-state-factory.js +6 -10
  36. package/dist/esm/ssr-next/commerce/factories/static-state-factory.js +4 -1
  37. package/dist/esm/ssr-next/commerce/utils/controller-wiring.js +161 -3
  38. package/dist/esm/ssr-next/commerce/utils/engine-wiring.js +9 -3
  39. package/dist/esm/ssr-next/commerce/utils/recommendation-filter.js +27 -8
  40. package/dist/esm/test/mock-ssr-controller-definitions.js +15 -0
  41. package/dist/esm/utils/version.js +1 -1
  42. package/dist/quantic/browser.cjs.stats.json +1 -1
  43. package/dist/quantic/case-assist/browser.cjs.stats.json +1 -1
  44. package/dist/quantic/case-assist/headless.js +1 -1
  45. package/dist/quantic/case-assist/headless.js.map +1 -1
  46. package/dist/quantic/commerce/browser.cjs.stats.json +1 -1
  47. package/dist/quantic/commerce/headless.js +1 -1
  48. package/dist/quantic/commerce/headless.js.map +1 -1
  49. package/dist/quantic/headless.js +1 -1
  50. package/dist/quantic/headless.js.map +1 -1
  51. package/dist/quantic/insight/browser.cjs.stats.json +1 -1
  52. package/dist/quantic/insight/headless.js +1 -1
  53. package/dist/quantic/insight/headless.js.map +1 -1
  54. package/dist/quantic/recommendation/browser.cjs.stats.json +1 -1
  55. package/dist/quantic/recommendation/headless.js +1 -1
  56. package/dist/quantic/recommendation/headless.js.map +1 -1
  57. package/package.json +1 -1
@@ -1,4 +1,162 @@
1
- export function wireControllerParams(_solutionType, _controllerDefinitions, _paramsObject) {
2
- // TODO: KIT-4742: Implement
3
- return {};
1
+ import { ArrayValue, RecordValue, Schema, StringValue } from '@coveo/bueno';
2
+ import { contextDefinition } from '../../../features/commerce/context/context-validation.js';
3
+ import { parametersDefinition } from '../../../features/commerce/parameters/parameters-schema.js';
4
+ import { nonEmptyString, requiredEmptyAllowedString, } from '../../../utils/validate-payload.js';
5
+ import { SolutionType } from '../types/controller-constants.js';
6
+ import { getRecommendationDefinitions, isRecommendationDefinition, } from './recommendation-filter.js';
7
+ const requiredDefinition = {
8
+ context: new RecordValue({
9
+ options: { required: true },
10
+ values: contextDefinition,
11
+ }),
12
+ };
13
+ const listingDefinition = {
14
+ ...requiredDefinition,
15
+ searchParams: new RecordValue({
16
+ values: parametersDefinition,
17
+ }),
18
+ };
19
+ const standaloneDefinition = {
20
+ ...requiredDefinition,
21
+ };
22
+ const searchDefinition = {
23
+ ...requiredDefinition,
24
+ searchParams: new RecordValue({
25
+ options: { required: true },
26
+ values: { query: requiredEmptyAllowedString, ...parametersDefinition },
27
+ }),
28
+ };
29
+ const recommendationsDefinition = (recommendationName) => ({
30
+ ...requiredDefinition,
31
+ recommendations: new ArrayValue({
32
+ each: new StringValue({
33
+ required: true,
34
+ constrainTo: recommendationName,
35
+ emptyAllowed: false,
36
+ }),
37
+ required: true,
38
+ }),
39
+ productId: nonEmptyString,
40
+ });
41
+ export const listingDefinitionSchema = new Schema(listingDefinition);
42
+ export const searchDefinitionSchema = new Schema(searchDefinition);
43
+ export const standaloneDefinitionSchema = new Schema(standaloneDefinition);
44
+ export const recommendationsDefinitionSchema = (recommendationName) => new Schema(recommendationsDefinition(recommendationName));
45
+ /**
46
+ * Validates the build configuration based on the solution type.
47
+ */
48
+ function validateBuildConfig(solutionType, controllerDefinitions, buildConfig) {
49
+ const validationMap = {
50
+ [SolutionType.listing]: listingDefinitionSchema,
51
+ [SolutionType.search]: searchDefinitionSchema,
52
+ [SolutionType.standalone]: standaloneDefinitionSchema,
53
+ [SolutionType.recommendation]: recommendationsDefinitionSchema(Object.keys(getRecommendationDefinitions(controllerDefinitions))),
54
+ };
55
+ const schema = validationMap[solutionType];
56
+ schema.validate(buildConfig);
57
+ }
58
+ /**
59
+ * Controller wiring class that handles the complete wiring process.
60
+ * Transforms simple user configuration into complex internal controller structures.
61
+ */
62
+ class ControllerWirer {
63
+ buildConfig;
64
+ controllerDefinitions;
65
+ controllerProps;
66
+ constructor(buildConfig, controllerDefinitions, controllerProps) {
67
+ this.buildConfig = buildConfig;
68
+ this.controllerDefinitions = controllerDefinitions;
69
+ this.controllerProps = controllerProps;
70
+ }
71
+ wireParameterManager() {
72
+ if (!this.controllerDefinitions?.parameterManager)
73
+ return;
74
+ const { searchParams } = this.buildConfig;
75
+ const { query, ...rest } = searchParams || {};
76
+ const parameters = {
77
+ ...(query && { q: query }),
78
+ ...(rest && typeof rest === 'object' ? rest : {}),
79
+ };
80
+ this.controllerProps.parameterManager = {
81
+ initialState: { parameters },
82
+ };
83
+ }
84
+ wireContext() {
85
+ if (!this.controllerDefinitions?.context)
86
+ return;
87
+ const { context } = this.buildConfig;
88
+ this.controllerProps.context = {
89
+ initialState: {
90
+ ...context,
91
+ },
92
+ };
93
+ }
94
+ wireCart() {
95
+ if (!this.controllerDefinitions?.cart || !this.buildConfig.cart)
96
+ return;
97
+ this.controllerProps.cart = {
98
+ initialState: this.buildConfig.cart,
99
+ };
100
+ }
101
+ wireRecommendations() {
102
+ if (!('recommendations' in this.buildConfig)) {
103
+ return;
104
+ }
105
+ for (const recController in this.controllerDefinitions) {
106
+ if (isRecommendationDefinition(this.controllerDefinitions[recController])) {
107
+ this.controllerProps[recController] = {
108
+ initialState: {
109
+ ...('productId' in this.buildConfig && {
110
+ productId: this.buildConfig.productId,
111
+ }),
112
+ },
113
+ };
114
+ }
115
+ }
116
+ }
117
+ /**
118
+ * Wires all controllers based on solution type and controller definitions.
119
+ * Handles the complete wiring process in a sequential manner.
120
+ */
121
+ wire(solutionType) {
122
+ // Wire common controllers that apply to all solution types
123
+ this.wireCart();
124
+ this.wireContext();
125
+ // Wire solution-specific controllers
126
+ switch (solutionType) {
127
+ case SolutionType.search:
128
+ case SolutionType.listing: {
129
+ this.wireParameterManager();
130
+ break;
131
+ }
132
+ case SolutionType.recommendation: {
133
+ this.wireRecommendations();
134
+ break;
135
+ }
136
+ case SolutionType.standalone:
137
+ // No additional wiring needed for standalone
138
+ break;
139
+ default: {
140
+ // Exhaustive check - TypeScript will error if we miss a case
141
+ const _exhaustiveCheck = solutionType;
142
+ throw new Error(`Unsupported solution type: ${_exhaustiveCheck}`);
143
+ }
144
+ }
145
+ }
146
+ }
147
+ /**
148
+ * Converts simple user configuration (URL, language, currency, query) into the
149
+ * nested structure required by the internal {@link Build} method. Automatically generates
150
+ * appropriate controllers (context, cart, parameterManager) transparently.
151
+ *
152
+ * @param solutionType - The type of solution (search, listing, recommendation, standalone)
153
+ * @param controllerDefinitions - Map of controller definitions to be initialized
154
+ * @param buildConfig - Simple configuration object with simplified controller properties
155
+ * @returns Formatted and validated controller properties map defined for the controller in the definition
156
+ */
157
+ export function wireControllerParams(solutionType, controllerDefinitions, buildConfig) {
158
+ validateBuildConfig(solutionType, controllerDefinitions, buildConfig);
159
+ const controllerProps = buildConfig.controllers ?? {};
160
+ new ControllerWirer(buildConfig, controllerDefinitions, controllerProps).wire(solutionType);
161
+ return controllerProps;
4
162
  }
@@ -1,4 +1,10 @@
1
- export function extendEngineConfiguration(_configuration, _commonBuildOptions) {
2
- // TODO: KIT-4742: Implement: wire engine configuration with validation
3
- return {};
1
+ export function extendEngineConfiguration(configuration, commonBuildOptions) {
2
+ const { cart, context } = commonBuildOptions;
3
+ return {
4
+ ...configuration,
5
+ context: {
6
+ ...context,
7
+ },
8
+ cart,
9
+ };
4
10
  }
@@ -1,15 +1,34 @@
1
1
  import { MultipleRecommendationError } from '../../common/errors.js';
2
2
  import { recommendationInternalOptionKey } from '../types/controller-constants.js';
3
+ /**
4
+ * Type guard to check if a controller definition is a recommendation controller.
5
+ * A recommendation controller must have both the recommendation flag and a slotId.
6
+ */
7
+ export function isRecommendationDefinition(controllerDefinition) {
8
+ const hasRecommendationFlag = 'recommendation' in controllerDefinition &&
9
+ controllerDefinition.recommendation === true;
10
+ const hasValidSlotId = recommendationInternalOptionKey in controllerDefinition &&
11
+ 'slotId' in
12
+ controllerDefinition[recommendationInternalOptionKey];
13
+ return hasRecommendationFlag && hasValidSlotId;
14
+ }
15
+ /**
16
+ * Extracts recommendation controller definitions from a controller definitions map.
17
+ *
18
+ * @param controllerDefinitions - Map of controller definitions
19
+ * @returns Object containing only the recommendation controller definitions
20
+ */
21
+ export function getRecommendationDefinitions(controllerDefinitions) {
22
+ const recommendationMap = {};
23
+ for (const [name, definition] of Object.entries(controllerDefinitions)) {
24
+ if (isRecommendationDefinition(definition)) {
25
+ recommendationMap[name] = definition;
26
+ }
27
+ }
28
+ return recommendationMap;
29
+ }
3
30
  export function filterRecommendationControllers(controllers, controllerDefinitions) {
4
31
  const slotIdSet = new Set();
5
- const isRecommendationDefinition = (controllerDefinition) => {
6
- const isControllerRecommendation = 'recommendation' in controllerDefinition &&
7
- controllerDefinition.recommendation === true;
8
- const hasSlotId = recommendationInternalOptionKey in controllerDefinition &&
9
- 'slotId' in
10
- controllerDefinition[recommendationInternalOptionKey];
11
- return isControllerRecommendation && hasSlotId;
12
- };
13
32
  const ensureSingleRecommendationPerSlot = (slotId) => {
14
33
  throw new MultipleRecommendationError(slotId);
15
34
  };
@@ -1,4 +1,5 @@
1
1
  import { vi } from 'vitest';
2
+ import { recommendationInternalOptionKey } from '../ssr-next/commerce/types/controller-constants.js';
2
3
  import { buildMockController, buildMockControllerWithInitialState, } from './mock-controller.js';
3
4
  export function defineMockController() {
4
5
  return {
@@ -41,3 +42,17 @@ export function defineMockCommerceControllerWithProps(options) {
41
42
  recommendation: options?.recommendation ?? true,
42
43
  };
43
44
  }
45
+ export function defineMockRecommendationDefinition(slotId) {
46
+ return {
47
+ recommendation: true,
48
+ [recommendationInternalOptionKey]: {
49
+ slotId,
50
+ },
51
+ buildWithProps: vi.fn((engine, props) => ({
52
+ _kind: 'some-kind',
53
+ ...buildMockControllerWithInitialState(engine, {
54
+ initialState: props?.initialState,
55
+ }),
56
+ })),
57
+ };
58
+ }
@@ -1,2 +1,2 @@
1
- export const VERSION = "3.29.1" || 'Test version';
1
+ export const VERSION = "3.29.2-pre.027eeece31" || 'Test version';
2
2
  export const COVEO_FRAMEWORK = ['@coveo/atomic', '@coveo/quantic'];