@coveo/headless 3.28.3-pre.467a471c62 → 3.28.3-pre.4fca7600f7

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.
@@ -800,7 +800,7 @@ var import_bueno5 = require("@coveo/bueno");
800
800
  var import_toolkit7 = require("@reduxjs/toolkit");
801
801
 
802
802
  // src/utils/version.ts
803
- var VERSION = "3.28.3-pre.467a471c62";
803
+ var VERSION = "3.28.3-pre.4fca7600f7";
804
804
  var COVEO_FRAMEWORK = ["@coveo/atomic", "@coveo/quantic"];
805
805
 
806
806
  // src/features/configuration/configuration-actions.ts
@@ -1148,7 +1148,7 @@ var import_bueno6 = require("@coveo/bueno");
1148
1148
  var import_toolkit4 = require("@reduxjs/toolkit");
1149
1149
 
1150
1150
  // src/utils/version.ts
1151
- var VERSION = "3.28.3-pre.467a471c62";
1151
+ var VERSION = "3.28.3-pre.4fca7600f7";
1152
1152
  var COVEO_FRAMEWORK = ["@coveo/atomic", "@coveo/quantic"];
1153
1153
 
1154
1154
  // src/features/configuration/configuration-actions.ts
@@ -1374,7 +1374,7 @@ var import_toolkit2 = require("@reduxjs/toolkit");
1374
1374
  var import_toolkit = require("@reduxjs/toolkit");
1375
1375
 
1376
1376
  // src/utils/version.ts
1377
- var VERSION = "3.28.3-pre.467a471c62";
1377
+ var VERSION = "3.28.3-pre.4fca7600f7";
1378
1378
  var COVEO_FRAMEWORK = ["@coveo/atomic", "@coveo/quantic"];
1379
1379
 
1380
1380
  // src/api/analytics/analytics-selectors.ts
@@ -1278,7 +1278,7 @@ var import_toolkit2 = require("@reduxjs/toolkit");
1278
1278
  var import_toolkit = require("@reduxjs/toolkit");
1279
1279
 
1280
1280
  // src/utils/version.ts
1281
- var VERSION = "3.28.3-pre.467a471c62";
1281
+ var VERSION = "3.28.3-pre.4fca7600f7";
1282
1282
  var COVEO_FRAMEWORK = ["@coveo/atomic", "@coveo/quantic"];
1283
1283
 
1284
1284
  // src/api/analytics/analytics-selectors.ts
@@ -881,7 +881,7 @@ var validateObject = (engine, schema, obj, validationMessage, errorMessage) => {
881
881
  };
882
882
 
883
883
  // src/utils/version.ts
884
- var VERSION = "3.28.3-pre.467a471c62";
884
+ var VERSION = "3.28.3-pre.4fca7600f7";
885
885
  var COVEO_FRAMEWORK = ["@coveo/atomic", "@coveo/quantic"];
886
886
 
887
887
  // src/features/configuration/configuration-actions.ts
@@ -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.3-pre.467a471c62";
1309
+ var VERSION = "3.28.3-pre.4fca7600f7";
1310
1310
  var COVEO_FRAMEWORK = ["@coveo/atomic", "@coveo/quantic"];
1311
1311
 
1312
1312
  // src/api/analytics/analytics-selectors.ts
@@ -468,7 +468,7 @@ var import_bueno8 = require("@coveo/bueno");
468
468
  var import_toolkit3 = require("@reduxjs/toolkit");
469
469
 
470
470
  // src/utils/version.ts
471
- var VERSION = "3.28.3-pre.467a471c62";
471
+ var VERSION = "3.28.3-pre.4fca7600f7";
472
472
  var COVEO_FRAMEWORK = ["@coveo/atomic", "@coveo/quantic"];
473
473
 
474
474
  // src/features/configuration/configuration-actions.ts
@@ -468,7 +468,7 @@ var import_bueno8 = require("@coveo/bueno");
468
468
  var import_toolkit3 = require("@reduxjs/toolkit");
469
469
 
470
470
  // src/utils/version.ts
471
- var VERSION = "3.28.3-pre.467a471c62";
471
+ var VERSION = "3.28.3-pre.4fca7600f7";
472
472
  var COVEO_FRAMEWORK = ["@coveo/atomic", "@coveo/quantic"];
473
473
 
474
474
  // src/features/configuration/configuration-actions.ts
@@ -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.3-pre.467a471c62";
1309
+ var VERSION = "3.28.3-pre.4fca7600f7";
1310
1310
  var COVEO_FRAMEWORK = ["@coveo/atomic", "@coveo/quantic"];
1311
1311
 
1312
1312
  // src/api/analytics/analytics-selectors.ts
@@ -9,8 +9,7 @@ import type { CommerceEngineDefinition } from '../types/engine.js';
9
9
  /**
10
10
  * Initializes a Commerce engine definition in SSR with given controllers definitions and commerce engine config.
11
11
  * @param options - The commerce engine definition
12
- * @returns Three utility functions to fetch the initial state of the engine in SSR, hydrate the state in CSR,
13
- * and a build function that can be used for edge cases requiring more control.
12
+ * @returns Engine definitions for different solution types that support per-call navigator context.
14
13
  *
15
14
  * @remarks
16
15
  * You can use the {@link InferStaticState} and {@link InferHydratedState} utility types with the returned engine definitions
@@ -18,9 +17,36 @@ import type { CommerceEngineDefinition } from '../types/engine.js';
18
17
  *
19
18
  * @example
20
19
  * ```ts
21
- * const engineDefinition = defineCommerceEngine(engineConfig);
22
- * type SearchStaticState = InferStaticState<typeof engineDefinition>;
23
- * type SearchHydratedState = InferHydratedState<typeof engineDefinition>;
20
+ * const { listingEngineDefinition } = defineCommerceEngine(engineConfig);
21
+ *
22
+ * // Pass navigator context directly to fetchStaticState
23
+ * const staticState = await listingEngineDefinition.fetchStaticState({
24
+ * navigatorContext: {
25
+ * forwardedFor: req.ip,
26
+ * referrer: req.headers.referer,
27
+ * userAgent: req.headers['user-agent'],
28
+ * location: req.url,
29
+ * clientId: 'unique-session-id'
30
+ * }
31
+ * });
32
+ *
33
+ * // Framework examples:
34
+ * // Express.js
35
+ * app.get('/api/listing', async (req, res) => {
36
+ * const state = await listingEngineDefinition.fetchStaticState({
37
+ * navigatorContext: {
38
+ * forwardedFor: req.ip,
39
+ * referrer: req.get('Referer'),
40
+ * userAgent: req.get('User-Agent'),
41
+ * location: req.originalUrl,
42
+ * clientId: req.sessionID
43
+ * }
44
+ * });
45
+ * res.json(state);
46
+ * });
47
+ *
48
+ * type SearchStaticState = InferStaticState<typeof listingEngineDefinition>;
49
+ * type SearchHydratedState = InferHydratedState<typeof listingEngineDefinition>;
24
50
  * ```
25
51
  *
26
52
  * @group Engine
@@ -1,7 +1,6 @@
1
1
  import type { UnknownAction } from '@reduxjs/toolkit';
2
2
  import type { CommerceEngineOptions } from '../../../app/commerce-engine/commerce-engine.js';
3
3
  import type { EngineConfiguration } from '../../../app/engine-configuration.js';
4
- import type { NavigatorContextProvider } from '../../../app/navigator-context-provider.js';
5
4
  import type { Controller } from '../../../controllers/controller/headless-controller.js';
6
5
  import type { ControllerStaticStateMap } from '../../common/types/controllers.js';
7
6
  import type { SSRCommerceEngine } from '../factories/build-factory.js';
@@ -33,13 +32,6 @@ export interface CommerceEngineDefinition<TControllers extends ControllerDefinit
33
32
  * Fetches the hydrated state on the client side using your engine definition and the static state.
34
33
  */
35
34
  hydrateStaticState: HydrateStaticState<InferControllersMapFromDefinition<TControllers, TSolutionType>, UnknownAction, InferControllerPropsMapFromDefinitions<TControllers>, TControllers, TSolutionType>;
36
- /**
37
- * Sets the navigator context provider.
38
- * This provider is essential for retrieving navigation-related data such as referrer, userAgent, location, and clientId, which are crucial for handling both server-side and client-side API requests effectively.
39
- *
40
- * Note: The implementation specifics of the navigator context provider depend on the Node.js framework being utilized. It is the developer's responsibility to appropriately define and implement the navigator context provider to ensure accurate navigation context is available throughout the application. If the user fails to provide a navigator context provider, a warning will be logged either on the server or the browser console.
41
- */
42
- setNavigatorContextProvider: (navigatorContextProvider: NavigatorContextProvider) => void;
43
35
  /**
44
36
  * Returns the access token.
45
37
  */
@@ -1,13 +1,47 @@
1
1
  import type { UnknownAction } from '@reduxjs/toolkit';
2
+ import type { NavigatorContext, NavigatorContextProvider } from '../../../app/navigator-context-provider.js';
2
3
  import type { Controller } from '../../../controllers/controller/headless-controller.js';
3
4
  import type { ControllerStaticStateMap, ControllersPropsMap } from '../../common/types/controllers.js';
4
5
  import type { SolutionType } from './controller-constants.js';
5
6
  import type { ControllerDefinitionsMap, EngineDefinitionControllersPropsOption, OptionsTuple } from './controller-definitions.js';
6
7
  import type { EngineStaticState } from './engine.js';
7
- export type FetchStaticStateOptions = {};
8
+ export interface FetchStaticStateOptions {
9
+ /**
10
+ * Navigator context for this request. Used to set headers like x-forwarded-for during SSR.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * // In your server route handler
15
+ * const staticState = await listingEngineDefinition.fetchStaticState({
16
+ * navigatorContext: {
17
+ * forwardedFor: req.ip,
18
+ * referrer: req.headers.referer || null,
19
+ * userAgent: req.headers['user-agent'] || null,
20
+ * location: req.url,
21
+ * clientId: req.sessionID || 'anonymous'
22
+ * }
23
+ * });
24
+ * ```
25
+ */
26
+ navigatorContext?: NavigatorContext | NavigatorContextProvider;
27
+ }
8
28
  /**
9
29
  * Executes only the initial search for a given configuration, then returns a resumable snapshot of engine state along with the state of the controllers.
10
30
  *
11
31
  * Useful for static generation and server-side rendering.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * // Pass navigator context directly in the options
36
+ * const staticState = await engineDefinition.fetchStaticState({
37
+ * navigatorContext: {
38
+ * forwardedFor: request.ip,
39
+ * referrer: request.headers.referer,
40
+ * userAgent: request.headers['user-agent'],
41
+ * location: request.url,
42
+ * clientId: 'session-123'
43
+ * }
44
+ * });
45
+ * ```
12
46
  */
13
47
  export type FetchStaticState<TSearchAction extends UnknownAction, TControllersStaticState extends ControllerStaticStateMap, TControllersProps extends ControllersPropsMap, TControllersDefinitionsMap extends ControllerDefinitionsMap<Controller>, TSolutionType extends SolutionType> = (...params: OptionsTuple<FetchStaticStateOptions & EngineDefinitionControllersPropsOption<TControllersDefinitionsMap, TControllersProps, TSolutionType>>) => Promise<EngineStaticState<TSearchAction, TControllersStaticState>>;
@@ -1,7 +1,6 @@
1
1
  import type { AnyAction, UnknownAction } from '@reduxjs/toolkit';
2
2
  import type { CoreEngine, CoreEngineNext } from '../../../app/engine.js';
3
3
  import type { EngineConfiguration } from '../../../app/engine-configuration.js';
4
- import type { NavigatorContextProvider } from '../../../app/navigator-context-provider.js';
5
4
  import type { Controller } from '../../../controllers/controller/headless-controller.js';
6
5
  import type { Build } from './build.js';
7
6
  import type { ControllerDefinitionsMap, ControllerStaticStateMap, ControllersMap, ControllersPropsMap } from './controllers.js';
@@ -27,13 +26,6 @@ export interface EngineDefinition<TEngine extends CoreEngine | CoreEngineNext, T
27
26
  * Fetches the hydrated state on the client side using your engine definition and the static state.
28
27
  */
29
28
  hydrateStaticState: HydrateStaticState<TEngine, InferControllersMapFromDefinition<TControllers>, AnyAction, InferControllerPropsMapFromDefinitions<TControllers>>;
30
- /**
31
- * Sets the navigator context provider.
32
- * This provider is essential for retrieving navigation-related data such as referrer, userAgent, location, and clientId, which are crucial for handling both server-side and client-side API requests effectively.
33
- *
34
- * Note: The implementation specifics of the navigator context provider depend on the Node.js framework being utilized. It is the developer's responsibility to appropriately define and implement the navigator context provider to ensure accurate navigation context is available throughout the application. If the user fails to provide a navigator context provider, a warning will be logged either on the server or the browser console.
35
- */
36
- setNavigatorContextProvider: (navigatorContextProvider: NavigatorContextProvider) => void;
37
29
  }
38
30
  export interface EngineDefinitionBuildResult<TEngine extends CoreEngine | CoreEngineNext, TControllers extends ControllersMap> {
39
31
  engine: TEngine;
@@ -1,12 +1,29 @@
1
1
  import type { UnknownAction } from '@reduxjs/toolkit';
2
+ import type { NavigatorContext, NavigatorContextProvider } from '../../../app/navigator-context-provider.js';
2
3
  import type { ControllerStaticStateMap, ControllersPropsMap } from './controllers.js';
3
4
  import type { EngineDefinitionControllersPropsOption, EngineStaticState } from './engine.js';
4
5
  import type { OptionsTuple } from './utilities.js';
5
- type FetchStaticStateOptions = {};
6
+ type FetchStaticStateOptions = {
7
+ navigatorContext?: NavigatorContext | NavigatorContextProvider;
8
+ };
6
9
  /**
7
10
  * Executes only the initial search for a given configuration, then returns a resumable snapshot of engine state along with the state of the controllers.
8
11
  *
9
12
  * Useful for static generation and server-side rendering.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // Pass navigator context directly in the options
17
+ * const staticState = await engineDefinition.fetchStaticState({
18
+ * navigatorContext: {
19
+ * forwardedFor: request.ip,
20
+ * referrer: request.headers.referer,
21
+ * userAgent: request.headers['user-agent'],
22
+ * location: request.url,
23
+ * clientId: 'session-123'
24
+ * }
25
+ * });
26
+ * ```
10
27
  */
11
28
  export type FetchStaticState<TSearchAction extends UnknownAction, TControllersStaticState extends ControllerStaticStateMap, TControllersProps extends ControllersPropsMap> = (...params: OptionsTuple<FetchStaticStateOptions & EngineDefinitionControllersPropsOption<TControllersProps>>) => Promise<EngineStaticState<TSearchAction, TControllersStaticState>>;
12
29
  export {};
@@ -1,40 +1,39 @@
1
- import type { NavigatorContextProvider } from '../../../app/navigator-context-provider.js';
2
1
  import { type SearchEngine, type SearchEngineOptions } from '../../../app/search-engine/search-engine.js';
3
2
  import type { Controller } from '../../../controllers/controller/headless-controller.js';
4
3
  import type { LegacySearchAction } from '../../../features/analytics/analytics-utils.js';
5
4
  import type { ControllerDefinitionsMap } from '../../common/types/controllers.js';
6
5
  import type { EngineDefinition, EngineDefinitionOptions } from '../../common/types/engine.js';
7
- import type { InferControllerPropsMapFromDefinitions, InferControllerStaticStateMapFromDefinitions } from '../../common/types/inference.js';
8
6
  /**
9
7
  * The SSR search engine.
10
- *
11
- * @group Engine
12
8
  */
13
9
  export interface SSRSearchEngine extends SearchEngine {
14
- /**
15
- * Waits for the search to be completed and returns a promise that resolves to a `SearchCompletedAction`.
16
- */
17
10
  waitForSearchCompletedAction(): Promise<SearchCompletedAction>;
18
11
  }
19
- /**
20
- * The options to create a search engine definition in SSR.
21
- *
22
- * @group Engine
23
- */
24
12
  export type SearchEngineDefinitionOptions<TControllers extends ControllerDefinitionsMap<SSRSearchEngine, Controller>> = EngineDefinitionOptions<SearchEngineOptions, TControllers>;
25
13
  export type SearchCompletedAction = ReturnType<LegacySearchAction['fulfilled' | 'rejected']>;
26
14
  export type SearchEngineDefinition<TControllers extends ControllerDefinitionsMap<SSRSearchEngine, Controller>> = EngineDefinition<SSRSearchEngine, TControllers>;
27
15
  /**
28
- * Initializes a Search engine definition in SSR with given controllers definitions and search engine config.
16
+ * Initializes a Search engine definition in SSR with per-call navigator context support.
29
17
  *
30
18
  * @param options - The search engine definition
31
- * @returns Three utility functions to fetch the initial state of the engine in SSR, hydrate the state in CSR,
32
- * and a build function that can be used for edge cases requiring more control.
19
+ * @returns Engine definition with support for per-call navigator context.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const searchEngine = defineSearchEngine(config);
24
+ *
25
+ * // Pass navigator context directly to fetchStaticState
26
+ * const staticState = await searchEngine.fetchStaticState({
27
+ * navigatorContext: {
28
+ * forwardedFor: req.ip,
29
+ * referrer: req.headers.referer,
30
+ * userAgent: req.headers['user-agent'],
31
+ * location: req.url,
32
+ * clientId: 'abc123'
33
+ * }
34
+ * });
35
+ * ```
33
36
  *
34
37
  * @group Engine
35
38
  */
36
- export declare function defineSearchEngine<TControllerDefinitions extends ControllerDefinitionsMap<SearchEngine, Controller>>(options: SearchEngineDefinitionOptions<TControllerDefinitions>): {
37
- fetchStaticState: import("../../common/types/fetch-static-state.js").FetchStaticState<import("redux").AnyAction, InferControllerStaticStateMapFromDefinitions<TControllerDefinitions>, InferControllerPropsMapFromDefinitions<TControllerDefinitions>>;
38
- hydrateStaticState: import("../../common/types/hydrate-static-state.js").HydrateStaticState<SSRSearchEngine, import("../../common/types/inference.js").InferControllersMapFromDefinition<TControllerDefinitions>, import("redux").AnyAction, InferControllerPropsMapFromDefinitions<TControllerDefinitions>>;
39
- setNavigatorContextProvider: (navigatorContextProvider: NavigatorContextProvider) => void;
40
- };
39
+ export declare function defineSearchEngine<TControllerDefinitions extends ControllerDefinitionsMap<SearchEngine, Controller>>(options: SearchEngineDefinitionOptions<TControllerDefinitions>): EngineDefinition<SSRSearchEngine, TControllerDefinitions>;
@@ -9,8 +9,7 @@ import { SolutionType } from '../types/controller-constants.js';
9
9
  /**
10
10
  * Initializes a Commerce engine definition in SSR with given controllers definitions and commerce engine config.
11
11
  * @param options - The commerce engine definition
12
- * @returns Three utility functions to fetch the initial state of the engine in SSR, hydrate the state in CSR,
13
- * and a build function that can be used for edge cases requiring more control.
12
+ * @returns Engine definitions for different solution types that support per-call navigator context.
14
13
  *
15
14
  * @remarks
16
15
  * You can use the {@link InferStaticState} and {@link InferHydratedState} utility types with the returned engine definitions
@@ -18,29 +17,51 @@ import { SolutionType } from '../types/controller-constants.js';
18
17
  *
19
18
  * @example
20
19
  * ```ts
21
- * const engineDefinition = defineCommerceEngine(engineConfig);
22
- * type SearchStaticState = InferStaticState<typeof engineDefinition>;
23
- * type SearchHydratedState = InferHydratedState<typeof engineDefinition>;
20
+ * const { listingEngineDefinition } = defineCommerceEngine(engineConfig);
21
+ *
22
+ * // Pass navigator context directly to fetchStaticState
23
+ * const staticState = await listingEngineDefinition.fetchStaticState({
24
+ * navigatorContext: {
25
+ * forwardedFor: req.ip,
26
+ * referrer: req.headers.referer,
27
+ * userAgent: req.headers['user-agent'],
28
+ * location: req.url,
29
+ * clientId: 'unique-session-id'
30
+ * }
31
+ * });
32
+ *
33
+ * // Framework examples:
34
+ * // Express.js
35
+ * app.get('/api/listing', async (req, res) => {
36
+ * const state = await listingEngineDefinition.fetchStaticState({
37
+ * navigatorContext: {
38
+ * forwardedFor: req.ip,
39
+ * referrer: req.get('Referer'),
40
+ * userAgent: req.get('User-Agent'),
41
+ * location: req.originalUrl,
42
+ * clientId: req.sessionID
43
+ * }
44
+ * });
45
+ * res.json(state);
46
+ * });
47
+ *
48
+ * type SearchStaticState = InferStaticState<typeof listingEngineDefinition>;
49
+ * type SearchHydratedState = InferHydratedState<typeof listingEngineDefinition>;
24
50
  * ```
25
51
  *
26
52
  * @group Engine
27
53
  */
28
54
  export function defineCommerceEngine(options) {
29
55
  const { controllers: controllerDefinitions, ...engineOptions } = options;
30
- const getOptions = () => engineOptions;
31
- const setNavigatorContextProvider = (navigatorContextProvider) => {
32
- engineOptions.navigatorContextProvider = navigatorContextProvider;
33
- };
34
56
  const getAccessToken = () => engineOptions.configuration.accessToken;
35
57
  const setAccessToken = (accessToken) => {
36
58
  engineOptions.configuration.accessToken = accessToken;
37
59
  };
38
- const fetchStaticState = fetchStaticStateFactory(controllerDefinitions, getOptions());
39
- const hydrateStaticState = hydratedStaticStateFactory(controllerDefinitions, getOptions());
40
- const fetchRecommendationStaticState = fetchRecommendationStaticStateFactory(controllerDefinitions, getOptions());
41
- const hydrateRecommendationStaticState = hydratedRecommendationStaticStateFactory(controllerDefinitions, getOptions());
60
+ const fetchStaticState = fetchStaticStateFactory(controllerDefinitions, engineOptions);
61
+ const hydrateStaticState = hydratedStaticStateFactory(controllerDefinitions, engineOptions);
62
+ const fetchRecommendationStaticState = fetchRecommendationStaticStateFactory(controllerDefinitions, engineOptions);
63
+ const hydrateRecommendationStaticState = hydratedRecommendationStaticStateFactory(controllerDefinitions, engineOptions);
42
64
  const commonMethods = {
43
- setNavigatorContextProvider,
44
65
  getAccessToken,
45
66
  setAccessToken,
46
67
  };
@@ -6,16 +6,30 @@ import { SolutionType } from '../types/controller-constants.js';
6
6
  import { buildFactory, } from './build-factory.js';
7
7
  export function fetchStaticStateFactory(controllerDefinitions, options) {
8
8
  return (solutionType) => async (...params) => {
9
- const solutionTypeBuild = await buildFactory(controllerDefinitions, {
9
+ const [callOptions] = params;
10
+ // Convert per-call navigator context to provider function
11
+ const navigatorContextProvider = callOptions?.navigatorContext
12
+ ? typeof callOptions.navigatorContext === 'function'
13
+ ? callOptions.navigatorContext
14
+ : () => callOptions.navigatorContext
15
+ : undefined;
16
+ // Create options for this call with navigator context
17
+ const callSpecificOptions = {
10
18
  ...options,
11
- })(solutionType);
19
+ navigatorContextProvider,
20
+ configuration: {
21
+ ...options.configuration,
22
+ preprocessRequest: navigatorContextProvider
23
+ ? augmentPreprocessRequestWithForwardedFor({
24
+ preprocessRequest: options.configuration.preprocessRequest,
25
+ navigatorContextProvider,
26
+ loggerOptions: options.loggerOptions,
27
+ })
28
+ : options.configuration.preprocessRequest,
29
+ },
30
+ };
31
+ const solutionTypeBuild = await buildFactory(controllerDefinitions, callSpecificOptions)(solutionType);
12
32
  const { engine, controllers } = await solutionTypeBuild(...params);
13
- options.configuration.preprocessRequest =
14
- augmentPreprocessRequestWithForwardedFor({
15
- preprocessRequest: options.configuration.preprocessRequest,
16
- navigatorContextProvider: options.navigatorContextProvider,
17
- loggerOptions: options.loggerOptions,
18
- });
19
33
  switch (solutionType) {
20
34
  case SolutionType.listing:
21
35
  buildProductListing(engine).executeFirstRequest();
@@ -1,4 +1,3 @@
1
- import { buildLogger } from '../../../app/logger.js';
2
1
  import { buildSearchEngine, } from '../../../app/search-engine/search-engine.js';
3
2
  import { createWaitForActionMiddleware } from '../../../utils/utils.js';
4
3
  import { augmentPreprocessRequestWithForwardedFor } from '../../common/augment-preprocess-request.js';
@@ -23,50 +22,76 @@ function buildSSRSearchEngine(options) {
23
22
  };
24
23
  }
25
24
  /**
26
- * Initializes a Search engine definition in SSR with given controllers definitions and search engine config.
25
+ * Initializes a Search engine definition in SSR with per-call navigator context support.
27
26
  *
28
27
  * @param options - The search engine definition
29
- * @returns Three utility functions to fetch the initial state of the engine in SSR, hydrate the state in CSR,
30
- * and a build function that can be used for edge cases requiring more control.
28
+ * @returns Engine definition with support for per-call navigator context.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const searchEngine = defineSearchEngine(config);
33
+ *
34
+ * // Pass navigator context directly to fetchStaticState
35
+ * const staticState = await searchEngine.fetchStaticState({
36
+ * navigatorContext: {
37
+ * forwardedFor: req.ip,
38
+ * referrer: req.headers.referer,
39
+ * userAgent: req.headers['user-agent'],
40
+ * location: req.url,
41
+ * clientId: 'abc123'
42
+ * }
43
+ * });
44
+ * ```
31
45
  *
32
46
  * @group Engine
33
47
  */
34
48
  export function defineSearchEngine(options) {
35
49
  const { controllers: controllerDefinitions, ...engineOptions } = options;
36
- const getOptions = () => {
37
- return engineOptions;
38
- };
39
- const setNavigatorContextProvider = (navigatorContextProvider) => {
40
- engineOptions.navigatorContextProvider = navigatorContextProvider;
41
- };
42
- const build = async (...[buildOptions]) => {
43
- const logger = buildLogger(options.loggerOptions);
44
- if (!getOptions().navigatorContextProvider) {
45
- logger.warn('[WARNING] Missing navigator context in server-side code. Make sure to set it with `setNavigatorContextProvider` before calling fetchStaticState()');
46
- }
47
- const engine = buildSSRSearchEngine(buildOptions?.extend
48
- ? await buildOptions.extend(getOptions())
49
- : getOptions());
50
+ // biome-ignore lint/suspicious/noExplicitAny: Complex parameter typing would require extensive refactoring
51
+ const hydrateStaticState = async (...params) => {
52
+ const engine = buildSSRSearchEngine(engineOptions);
50
53
  const controllers = buildControllerDefinitions({
51
54
  definitionsMap: (controllerDefinitions ?? {}),
52
55
  engine,
53
- propsMap: (buildOptions && 'controllers' in buildOptions
54
- ? buildOptions.controllers
55
- : {}),
56
+ propsMap: {},
56
57
  });
57
- return {
58
- engine,
59
- controllers,
60
- };
58
+ const [staticState] = params;
59
+ engine.dispatch(staticState.searchAction);
60
+ await engine.waitForSearchCompletedAction();
61
+ return { engine, controllers };
61
62
  };
63
+ // biome-ignore lint/suspicious/noExplicitAny: Parameter typing matches the interface contract
62
64
  const fetchStaticState = async (...params) => {
63
- const { engine, controllers } = await build(...params);
64
- options.configuration.preprocessRequest =
65
- augmentPreprocessRequestWithForwardedFor({
66
- preprocessRequest: options.configuration.preprocessRequest,
67
- navigatorContextProvider: options.navigatorContextProvider,
68
- loggerOptions: options.loggerOptions,
69
- });
65
+ const [callOptions] = params;
66
+ // Convert per-call navigator context to provider function
67
+ const navigatorContextProvider = callOptions?.navigatorContext
68
+ ? typeof callOptions.navigatorContext === 'function'
69
+ ? callOptions.navigatorContext
70
+ : () => callOptions.navigatorContext
71
+ : undefined;
72
+ // Create options for this call with navigator context
73
+ const callSpecificOptions = {
74
+ ...options,
75
+ navigatorContextProvider,
76
+ configuration: {
77
+ ...options.configuration,
78
+ preprocessRequest: navigatorContextProvider
79
+ ? augmentPreprocessRequestWithForwardedFor({
80
+ preprocessRequest: options.configuration.preprocessRequest,
81
+ navigatorContextProvider,
82
+ loggerOptions: options.loggerOptions,
83
+ })
84
+ : options.configuration.preprocessRequest,
85
+ },
86
+ };
87
+ const engine = buildSSRSearchEngine(callSpecificOptions);
88
+ const controllers = buildControllerDefinitions({
89
+ definitionsMap: (controllerDefinitions ?? {}),
90
+ engine,
91
+ propsMap: (callOptions && 'controllers' in callOptions
92
+ ? callOptions.controllers
93
+ : {}),
94
+ });
70
95
  engine.executeFirstSearch();
71
96
  const staticState = createStaticState({
72
97
  searchAction: await engine.waitForSearchCompletedAction(),
@@ -74,15 +99,8 @@ export function defineSearchEngine(options) {
74
99
  });
75
100
  return staticState;
76
101
  };
77
- const hydrateStaticState = async (...params) => {
78
- const { engine, controllers } = await build(...params);
79
- engine.dispatch(params[0].searchAction);
80
- await engine.waitForSearchCompletedAction();
81
- return { engine, controllers };
82
- };
83
102
  return {
84
103
  fetchStaticState,
85
104
  hydrateStaticState,
86
- setNavigatorContextProvider,
87
105
  };
88
106
  }
@@ -1,2 +1,2 @@
1
- export const VERSION = "3.28.3-pre.467a471c62" || 'Test version';
1
+ export const VERSION = "3.28.3-pre.4fca7600f7" || 'Test version';
2
2
  export const COVEO_FRAMEWORK = ['@coveo/atomic', '@coveo/quantic'];