@coveo/shopify 1.6.1-pre.fda43fc695 → 1.7.0-pre.153636d7cb

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/README.md CHANGED
@@ -20,6 +20,52 @@ yarn add @coveo/shopify
20
20
 
21
21
  ## Features
22
22
 
23
+ ### `init`
24
+
25
+ Initializes the Coveo Shopify integration to ensure that web pixels work correctly. This function should be called on every page of your Shopify store to maintain consistent tracking and personalization.
26
+
27
+ The `init` function publishes a custom event with the configuration data that the web pixels need to function properly.
28
+
29
+ #### Parameters
30
+
31
+ - `options` (required): A `CoveoShopifyOptions` object containing:
32
+ - `accessToken` (required): The access token for the Coveo API.
33
+ - `organizationId` (required): The organization ID.
34
+ - `environment` (required): The environment configuration ('dev', 'stg', 'prod', etc.).
35
+ - `trackingId` (required): The tracking ID for analytics.
36
+
37
+ #### Returns
38
+
39
+ This function doesn't return a value but publishes a custom event that web pixels can listen to.
40
+
41
+ #### Example
42
+
43
+ ```typescript
44
+ import {init} from '@coveo/shopify/utilities';
45
+
46
+ // Initialize on every page
47
+ init({
48
+ accessToken: 'your-access-token',
49
+ organizationId: 'your-org-id',
50
+ environment: 'prod',
51
+ trackingId: 'your-tracking-id',
52
+ });
53
+ ```
54
+
55
+ #### Usage with App Proxy Configuration
56
+
57
+ You can combine the `init` function with `fetchAppProxyConfig` to initialize the integration:
58
+
59
+ ```typescript
60
+ import {init, fetchAppProxyConfig} from '@coveo/shopify/utilities';
61
+
62
+ const config = await fetchAppProxyConfig({
63
+ marketId: 'market_123432',
64
+ });
65
+
66
+ init(config);
67
+ ```
68
+
23
69
  ### `fetchAppProxyConfig`
24
70
 
25
71
  Fetches the app proxy configuration for a given Shopify market.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @license
3
+ *
4
+ * Copyright 2025 Coveo Solutions Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ // src/constants.ts
20
+ var COVEO_SHOPIFY_CONFIG_KEY = "coveo_shopify_config";
21
+ export {
22
+ COVEO_SHOPIFY_CONFIG_KEY
23
+ };
@@ -1,8 +1,8 @@
1
1
  import { CommerceEngineOptions } from '@coveo/headless/commerce';
2
- export { COVEO_SHOPIFY_CONFIG_KEY } from '../constants';
2
+ export type * from '../types';
3
3
  export * from '@coveo/headless/commerce';
4
+ export * from '../constants';
4
5
  export * from '../utilities';
5
- export type { AppProxyConfig, AppProxyResponse } from '../types';
6
6
  export interface BuildShopifyCommerceEngineOptions {
7
7
  commerceEngineOptions: CommerceEngineOptions;
8
8
  }
@@ -34,20 +34,82 @@ function publishCustomShopifyEvent(key, customData) {
34
34
  // src/headless/commerce.ts
35
35
  export * from "@coveo/headless/commerce";
36
36
 
37
+ // src/utilities/memoize.ts
38
+ function memoize(fn, getCacheKey) {
39
+ const cache = /* @__PURE__ */ new Map();
40
+ return {
41
+ fn: async (...args) => {
42
+ const key = getCacheKey(...args);
43
+ if (cache.has(key)) {
44
+ return cache.get(key);
45
+ }
46
+ const promise = fn(...args);
47
+ cache.set(key, promise);
48
+ try {
49
+ const result = await promise;
50
+ return result;
51
+ } catch (error) {
52
+ cache.delete(key);
53
+ throw error;
54
+ }
55
+ },
56
+ clearCache: () => {
57
+ cache.clear();
58
+ },
59
+ clearCacheEntry: (...args) => {
60
+ const key = getCacheKey(...args);
61
+ cache.delete(key);
62
+ }
63
+ };
64
+ }
65
+
37
66
  // src/utilities/app-proxy.ts
67
+ var memoizedFetch = memoize(
68
+ (...args) => global.fetch(...args),
69
+ (url) => url
70
+ );
38
71
  async function fetchAppProxyConfig({
39
72
  appProxyUrl = "/apps/coveo",
40
73
  marketId
41
74
  }) {
42
- const response = await fetch(`${appProxyUrl}?marketId=${marketId}]`);
75
+ const url = `${appProxyUrl}?marketId=${marketId}`;
76
+ const response = await memoizedFetch.fn(url);
77
+ if (!response.ok) {
78
+ memoizedFetch.clearCacheEntry(url);
79
+ throw new Error(
80
+ `Failed to fetch app proxy configuration from ${appProxyUrl} for marketId ${marketId}. Status: ${response.status}`
81
+ );
82
+ }
43
83
  return response.json();
44
84
  }
85
+ function clearAppProxyCache() {
86
+ memoizedFetch.clearCache();
87
+ }
88
+
89
+ // src/utilities/init.ts
90
+ import { getAnalyticsNextApiBaseUrl } from "@coveo/headless";
91
+ import { createRelay } from "@coveo/relay";
92
+ function init(options) {
93
+ const relay = createRelay({
94
+ url: getAnalyticsNextApiBaseUrl(
95
+ options.organizationId,
96
+ options.environment
97
+ ),
98
+ token: options.accessToken,
99
+ trackingId: options.trackingId
100
+ });
101
+ const clientId = relay.getMeta("").clientId;
102
+ publishCustomShopifyEvent(COVEO_SHOPIFY_CONFIG_KEY, {
103
+ ...options,
104
+ clientId
105
+ });
106
+ }
45
107
 
46
108
  // src/headless/commerce.ts
47
109
  function buildShopifyCommerceEngine({
48
110
  commerceEngineOptions
49
111
  }) {
50
- const appProxyResponse = {
112
+ const options = {
51
113
  accessToken: commerceEngineOptions.configuration.accessToken,
52
114
  organizationId: commerceEngineOptions.configuration.organizationId,
53
115
  environment: commerceEngineOptions.configuration.environment,
@@ -56,7 +118,7 @@ function buildShopifyCommerceEngine({
56
118
  const engine = buildCommerceEngine(commerceEngineOptions);
57
119
  const clientId = engine.relay.getMeta("").clientId;
58
120
  publishCustomShopifyEvent(COVEO_SHOPIFY_CONFIG_KEY, {
59
- ...appProxyResponse,
121
+ ...options,
60
122
  clientId
61
123
  });
62
124
  return engine;
@@ -64,6 +126,8 @@ function buildShopifyCommerceEngine({
64
126
  export {
65
127
  COVEO_SHOPIFY_CONFIG_KEY,
66
128
  buildShopifyCommerceEngine,
129
+ clearAppProxyCache,
67
130
  fetchAppProxyConfig,
131
+ init,
68
132
  publishCustomShopifyEvent
69
133
  };
@@ -1,8 +1,8 @@
1
1
  import { buildCommerceEngine, } from '@coveo/headless/commerce';
2
2
  import { COVEO_SHOPIFY_CONFIG_KEY } from '../constants';
3
3
  import { publishCustomShopifyEvent } from '../utilities/shopify';
4
- export { COVEO_SHOPIFY_CONFIG_KEY } from '../constants';
5
4
  export * from '@coveo/headless/commerce';
5
+ export * from '../constants';
6
6
  export * from '../utilities';
7
7
  /**
8
8
  * Builds the commerce engine for a Shopify store.
@@ -15,7 +15,7 @@ export * from '../utilities';
15
15
  * @returns The constructed commerce engine instance.
16
16
  */
17
17
  export function buildShopifyCommerceEngine({ commerceEngineOptions, }) {
18
- const appProxyResponse = {
18
+ const options = {
19
19
  accessToken: commerceEngineOptions.configuration.accessToken,
20
20
  organizationId: commerceEngineOptions.configuration.organizationId,
21
21
  environment: commerceEngineOptions.configuration.environment,
@@ -24,7 +24,7 @@ export function buildShopifyCommerceEngine({ commerceEngineOptions, }) {
24
24
  const engine = buildCommerceEngine(commerceEngineOptions);
25
25
  const clientId = engine.relay.getMeta('').clientId;
26
26
  publishCustomShopifyEvent(COVEO_SHOPIFY_CONFIG_KEY, {
27
- ...appProxyResponse,
27
+ ...options,
28
28
  clientId,
29
29
  });
30
30
  return engine;
@@ -1,7 +1,8 @@
1
1
  import { SearchEngineOptions } from '@coveo/headless';
2
2
  export { COVEO_SHOPIFY_CONFIG_KEY } from '../constants';
3
- export type { AppProxyConfig, AppProxyResponse } from '../types';
3
+ export type * from '../types';
4
4
  export * from '@coveo/headless';
5
+ export * from '../constants';
5
6
  export * from '../utilities';
6
7
  export interface BuildShopifySearchEngineOptions {
7
8
  searchEngineOptions: SearchEngineOptions;
@@ -32,14 +32,76 @@ function publishCustomShopifyEvent(key, customData) {
32
32
  // src/headless/search.ts
33
33
  export * from "@coveo/headless";
34
34
 
35
+ // src/utilities/memoize.ts
36
+ function memoize(fn, getCacheKey) {
37
+ const cache = /* @__PURE__ */ new Map();
38
+ return {
39
+ fn: async (...args) => {
40
+ const key = getCacheKey(...args);
41
+ if (cache.has(key)) {
42
+ return cache.get(key);
43
+ }
44
+ const promise = fn(...args);
45
+ cache.set(key, promise);
46
+ try {
47
+ const result = await promise;
48
+ return result;
49
+ } catch (error) {
50
+ cache.delete(key);
51
+ throw error;
52
+ }
53
+ },
54
+ clearCache: () => {
55
+ cache.clear();
56
+ },
57
+ clearCacheEntry: (...args) => {
58
+ const key = getCacheKey(...args);
59
+ cache.delete(key);
60
+ }
61
+ };
62
+ }
63
+
35
64
  // src/utilities/app-proxy.ts
65
+ var memoizedFetch = memoize(
66
+ (...args) => global.fetch(...args),
67
+ (url) => url
68
+ );
36
69
  async function fetchAppProxyConfig({
37
70
  appProxyUrl = "/apps/coveo",
38
71
  marketId
39
72
  }) {
40
- const response = await fetch(`${appProxyUrl}?marketId=${marketId}]`);
73
+ const url = `${appProxyUrl}?marketId=${marketId}`;
74
+ const response = await memoizedFetch.fn(url);
75
+ if (!response.ok) {
76
+ memoizedFetch.clearCacheEntry(url);
77
+ throw new Error(
78
+ `Failed to fetch app proxy configuration from ${appProxyUrl} for marketId ${marketId}. Status: ${response.status}`
79
+ );
80
+ }
41
81
  return response.json();
42
82
  }
83
+ function clearAppProxyCache() {
84
+ memoizedFetch.clearCache();
85
+ }
86
+
87
+ // src/utilities/init.ts
88
+ import { getAnalyticsNextApiBaseUrl } from "@coveo/headless";
89
+ import { createRelay } from "@coveo/relay";
90
+ function init(options) {
91
+ const relay = createRelay({
92
+ url: getAnalyticsNextApiBaseUrl(
93
+ options.organizationId,
94
+ options.environment
95
+ ),
96
+ token: options.accessToken,
97
+ trackingId: options.trackingId
98
+ });
99
+ const clientId = relay.getMeta("").clientId;
100
+ publishCustomShopifyEvent(COVEO_SHOPIFY_CONFIG_KEY, {
101
+ ...options,
102
+ clientId
103
+ });
104
+ }
43
105
 
44
106
  // src/headless/search.ts
45
107
  function buildShopifySearchEngine({
@@ -50,7 +112,7 @@ function buildShopifySearchEngine({
50
112
  "The configuration for the search engine must include an analytics tracking ID."
51
113
  );
52
114
  }
53
- const appProxyResponse = {
115
+ const options = {
54
116
  accessToken: searchEngineOptions.configuration.accessToken,
55
117
  organizationId: searchEngineOptions.configuration.organizationId,
56
118
  environment: searchEngineOptions.configuration.environment,
@@ -59,7 +121,7 @@ function buildShopifySearchEngine({
59
121
  const engine = buildSearchEngine(searchEngineOptions);
60
122
  const clientId = engine.relay.getMeta("").clientId;
61
123
  publishCustomShopifyEvent(COVEO_SHOPIFY_CONFIG_KEY, {
62
- ...appProxyResponse,
124
+ ...options,
63
125
  clientId
64
126
  });
65
127
  return engine;
@@ -67,6 +129,8 @@ function buildShopifySearchEngine({
67
129
  export {
68
130
  COVEO_SHOPIFY_CONFIG_KEY,
69
131
  buildShopifySearchEngine,
132
+ clearAppProxyCache,
70
133
  fetchAppProxyConfig,
134
+ init,
71
135
  publishCustomShopifyEvent
72
136
  };
@@ -3,6 +3,7 @@ import { COVEO_SHOPIFY_CONFIG_KEY } from '../constants';
3
3
  import { publishCustomShopifyEvent } from '../utilities/shopify';
4
4
  export { COVEO_SHOPIFY_CONFIG_KEY } from '../constants';
5
5
  export * from '@coveo/headless';
6
+ export * from '../constants';
6
7
  export * from '../utilities';
7
8
  /**
8
9
  * Builds the search engine for a Shopify store.
@@ -19,7 +20,7 @@ export function buildShopifySearchEngine({ searchEngineOptions, }) {
19
20
  if (!searchEngineOptions.configuration.analytics?.trackingId) {
20
21
  throw new Error('The configuration for the search engine must include an analytics tracking ID.');
21
22
  }
22
- const appProxyResponse = {
23
+ const options = {
23
24
  accessToken: searchEngineOptions.configuration.accessToken,
24
25
  organizationId: searchEngineOptions.configuration.organizationId,
25
26
  environment: searchEngineOptions.configuration.environment,
@@ -28,7 +29,7 @@ export function buildShopifySearchEngine({ searchEngineOptions, }) {
28
29
  const engine = buildSearchEngine(searchEngineOptions);
29
30
  const clientId = engine.relay.getMeta('').clientId;
30
31
  publishCustomShopifyEvent(COVEO_SHOPIFY_CONFIG_KEY, {
31
- ...appProxyResponse,
32
+ ...options,
32
33
  clientId,
33
34
  });
34
35
  return engine;
@@ -38,7 +38,9 @@ var index_exports = {};
38
38
  __export(index_exports, {
39
39
  COVEO_SHOPIFY_CONFIG_KEY: () => COVEO_SHOPIFY_CONFIG_KEY,
40
40
  buildShopifyCommerceEngine: () => buildShopifyCommerceEngine,
41
+ clearAppProxyCache: () => clearAppProxyCache,
41
42
  fetchAppProxyConfig: () => fetchAppProxyConfig,
43
+ init: () => init,
42
44
  publishCustomShopifyEvent: () => publishCustomShopifyEvent
43
45
  });
44
46
 
@@ -47,7 +49,9 @@ var commerce_exports = {};
47
49
  __export(commerce_exports, {
48
50
  COVEO_SHOPIFY_CONFIG_KEY: () => COVEO_SHOPIFY_CONFIG_KEY,
49
51
  buildShopifyCommerceEngine: () => buildShopifyCommerceEngine,
52
+ clearAppProxyCache: () => clearAppProxyCache,
50
53
  fetchAppProxyConfig: () => fetchAppProxyConfig,
54
+ init: () => init,
51
55
  publishCustomShopifyEvent: () => publishCustomShopifyEvent
52
56
  });
53
57
  import {
@@ -68,20 +72,82 @@ function publishCustomShopifyEvent(key, customData) {
68
72
  __reExport(commerce_exports, commerce_star);
69
73
  import * as commerce_star from "@coveo/headless/commerce";
70
74
 
75
+ // src/utilities/memoize.ts
76
+ function memoize(fn, getCacheKey) {
77
+ const cache = /* @__PURE__ */ new Map();
78
+ return {
79
+ fn: async (...args) => {
80
+ const key = getCacheKey(...args);
81
+ if (cache.has(key)) {
82
+ return cache.get(key);
83
+ }
84
+ const promise = fn(...args);
85
+ cache.set(key, promise);
86
+ try {
87
+ const result = await promise;
88
+ return result;
89
+ } catch (error) {
90
+ cache.delete(key);
91
+ throw error;
92
+ }
93
+ },
94
+ clearCache: () => {
95
+ cache.clear();
96
+ },
97
+ clearCacheEntry: (...args) => {
98
+ const key = getCacheKey(...args);
99
+ cache.delete(key);
100
+ }
101
+ };
102
+ }
103
+
71
104
  // src/utilities/app-proxy.ts
105
+ var memoizedFetch = memoize(
106
+ (...args) => global.fetch(...args),
107
+ (url) => url
108
+ );
72
109
  async function fetchAppProxyConfig({
73
110
  appProxyUrl = "/apps/coveo",
74
111
  marketId
75
112
  }) {
76
- const response = await fetch(`${appProxyUrl}?marketId=${marketId}]`);
113
+ const url = `${appProxyUrl}?marketId=${marketId}`;
114
+ const response = await memoizedFetch.fn(url);
115
+ if (!response.ok) {
116
+ memoizedFetch.clearCacheEntry(url);
117
+ throw new Error(
118
+ `Failed to fetch app proxy configuration from ${appProxyUrl} for marketId ${marketId}. Status: ${response.status}`
119
+ );
120
+ }
77
121
  return response.json();
78
122
  }
123
+ function clearAppProxyCache() {
124
+ memoizedFetch.clearCache();
125
+ }
126
+
127
+ // src/utilities/init.ts
128
+ import { getAnalyticsNextApiBaseUrl } from "@coveo/headless";
129
+ import { createRelay } from "@coveo/relay";
130
+ function init(options) {
131
+ const relay = createRelay({
132
+ url: getAnalyticsNextApiBaseUrl(
133
+ options.organizationId,
134
+ options.environment
135
+ ),
136
+ token: options.accessToken,
137
+ trackingId: options.trackingId
138
+ });
139
+ const clientId = relay.getMeta("").clientId;
140
+ publishCustomShopifyEvent(COVEO_SHOPIFY_CONFIG_KEY, {
141
+ ...options,
142
+ clientId
143
+ });
144
+ }
79
145
 
80
146
  // src/headless/commerce.ts
81
147
  function buildShopifyCommerceEngine({
82
148
  commerceEngineOptions
83
149
  }) {
84
- const appProxyResponse = {
150
+ const options = {
85
151
  accessToken: commerceEngineOptions.configuration.accessToken,
86
152
  organizationId: commerceEngineOptions.configuration.organizationId,
87
153
  environment: commerceEngineOptions.configuration.environment,
@@ -90,7 +156,7 @@ function buildShopifyCommerceEngine({
90
156
  const engine = buildCommerceEngine(commerceEngineOptions);
91
157
  const clientId = engine.relay.getMeta("").clientId;
92
158
  publishCustomShopifyEvent(COVEO_SHOPIFY_CONFIG_KEY, {
93
- ...appProxyResponse,
159
+ ...options,
94
160
  clientId
95
161
  });
96
162
  return engine;
@@ -101,6 +167,8 @@ __reExport(index_exports, commerce_exports);
101
167
  export {
102
168
  COVEO_SHOPIFY_CONFIG_KEY,
103
169
  buildShopifyCommerceEngine,
170
+ clearAppProxyCache,
104
171
  fetchAppProxyConfig,
172
+ init,
105
173
  publishCustomShopifyEvent
106
174
  };
package/dist/types.d.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  import { CommerceEngineOptions } from '@coveo/headless/commerce';
2
- export interface AppProxyConfig {
2
+ export interface AppProxyOptions {
3
3
  appProxyUrl?: string;
4
4
  marketId: string;
5
5
  }
6
- export interface AppProxyResponse {
6
+ export interface CoveoShopifyOptions {
7
7
  accessToken: string;
8
8
  organizationId: string;
9
9
  environment: CommerceEngineOptions['configuration']['environment'];
10
10
  trackingId: string;
11
11
  }
12
- export type CoveoShopifyCustomEvent = AppProxyResponse & {
12
+ export interface CoveoShopifyCustomEvent extends CoveoShopifyOptions {
13
13
  clientId: string;
14
- };
14
+ }
@@ -1,13 +1,14 @@
1
- import { AppProxyConfig, AppProxyResponse } from '../types';
1
+ import { AppProxyOptions, CoveoShopifyOptions } from '../types';
2
2
  /**
3
3
  * Fetches configuration from the app proxy.
4
4
  *
5
5
  * Performs an HTTP GET request to retrieve the app proxy configuration using the provided marketId.
6
- * The fetched response is parsed as JSON and returned.
6
+ * The fetched response is parsed as JSON and returned. Results are automatically memoized by URL.
7
7
  *
8
8
  * @param appProxyUrl - The URL template for the app proxy endpoint. Defaults to '/apps/coveo'.
9
9
  * @param marketId - The unique market identifier used as a query parameter.
10
10
  * @returns A promise that resolves to an object containing the access token, organization ID,
11
11
  * environment, and tracking ID.
12
12
  */
13
- export declare function fetchAppProxyConfig({ appProxyUrl, marketId, }: AppProxyConfig): Promise<AppProxyResponse>;
13
+ export declare function fetchAppProxyConfig({ appProxyUrl, marketId, }: AppProxyOptions): Promise<CoveoShopifyOptions>;
14
+ export declare function clearAppProxyCache(): void;
@@ -1,8 +1,10 @@
1
+ import { memoize } from './memoize';
2
+ const memoizedFetch = memoize((...args) => global.fetch(...args), (url) => url);
1
3
  /**
2
4
  * Fetches configuration from the app proxy.
3
5
  *
4
6
  * Performs an HTTP GET request to retrieve the app proxy configuration using the provided marketId.
5
- * The fetched response is parsed as JSON and returned.
7
+ * The fetched response is parsed as JSON and returned. Results are automatically memoized by URL.
6
8
  *
7
9
  * @param appProxyUrl - The URL template for the app proxy endpoint. Defaults to '/apps/coveo'.
8
10
  * @param marketId - The unique market identifier used as a query parameter.
@@ -10,6 +12,14 @@
10
12
  * environment, and tracking ID.
11
13
  */
12
14
  export async function fetchAppProxyConfig({ appProxyUrl = '/apps/coveo', marketId, }) {
13
- const response = await fetch(`${appProxyUrl}?marketId=${marketId}]`);
15
+ const url = `${appProxyUrl}?marketId=${marketId}`;
16
+ const response = await memoizedFetch.fn(url);
17
+ if (!response.ok) {
18
+ memoizedFetch.clearCacheEntry(url);
19
+ throw new Error(`Failed to fetch app proxy configuration from ${appProxyUrl} for marketId ${marketId}. Status: ${response.status}`);
20
+ }
14
21
  return response.json();
15
22
  }
23
+ export function clearAppProxyCache() {
24
+ memoizedFetch.clearCache();
25
+ }
@@ -1,4 +1,5 @@
1
- export type { CoveoShopifyCustomEvent } from '../types';
1
+ export type * from '../types';
2
2
  export { publishCustomShopifyEvent } from './shopify';
3
- export { fetchAppProxyConfig } from './app-proxy';
3
+ export * from './app-proxy';
4
+ export * from './init';
4
5
  export * from '../constants';
@@ -1,3 +1,4 @@
1
1
  export { publishCustomShopifyEvent } from './shopify';
2
- export { fetchAppProxyConfig } from './app-proxy';
2
+ export * from './app-proxy';
3
+ export * from './init';
3
4
  export * from '../constants';
@@ -0,0 +1,2 @@
1
+ import { CoveoShopifyOptions } from '../types';
2
+ export declare function init(options: CoveoShopifyOptions): void;
@@ -0,0 +1,16 @@
1
+ import { getAnalyticsNextApiBaseUrl } from '@coveo/headless';
2
+ import { createRelay } from '@coveo/relay';
3
+ import { COVEO_SHOPIFY_CONFIG_KEY } from '../constants';
4
+ import { publishCustomShopifyEvent } from './shopify';
5
+ export function init(options) {
6
+ const relay = createRelay({
7
+ url: getAnalyticsNextApiBaseUrl(options.organizationId, options.environment),
8
+ token: options.accessToken,
9
+ trackingId: options.trackingId,
10
+ });
11
+ const clientId = relay.getMeta('').clientId;
12
+ publishCustomShopifyEvent(COVEO_SHOPIFY_CONFIG_KEY, {
13
+ ...options,
14
+ clientId,
15
+ });
16
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Creates a memoized version of an async function with a custom cache key generator.
3
+ * Only successful results are cached - rejected promises are not remembered.
4
+ *
5
+ * @param fn - The async function to memoize
6
+ * @param getCacheKey - Function that generates a cache key from the function arguments
7
+ * @returns Object with the memoized function and cache clearing capability
8
+ */
9
+ export declare function memoize<TArgs extends unknown[], TReturn>(fn: (...args: TArgs) => Promise<TReturn>, getCacheKey: (...args: TArgs) => string): {
10
+ fn: (...args: TArgs) => Promise<TReturn>;
11
+ clearCache: () => void;
12
+ clearCacheEntry: (...args: TArgs) => void;
13
+ };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Creates a memoized version of an async function with a custom cache key generator.
3
+ * Only successful results are cached - rejected promises are not remembered.
4
+ *
5
+ * @param fn - The async function to memoize
6
+ * @param getCacheKey - Function that generates a cache key from the function arguments
7
+ * @returns Object with the memoized function and cache clearing capability
8
+ */
9
+ export function memoize(fn, getCacheKey) {
10
+ const cache = new Map();
11
+ return {
12
+ fn: async (...args) => {
13
+ const key = getCacheKey(...args);
14
+ if (cache.has(key)) {
15
+ return cache.get(key);
16
+ }
17
+ const promise = fn(...args);
18
+ cache.set(key, promise);
19
+ try {
20
+ const result = await promise;
21
+ return result;
22
+ }
23
+ catch (error) {
24
+ // Remove failed promises from cache so they can be retried
25
+ cache.delete(key);
26
+ throw error;
27
+ }
28
+ },
29
+ clearCache: () => {
30
+ cache.clear();
31
+ },
32
+ clearCacheEntry: (...args) => {
33
+ const key = getCacheKey(...args);
34
+ cache.delete(key);
35
+ },
36
+ };
37
+ }
@@ -23,19 +23,85 @@ function publishCustomShopifyEvent(key, customData) {
23
23
  }
24
24
  }
25
25
 
26
+ // src/utilities/memoize.ts
27
+ function memoize(fn, getCacheKey) {
28
+ const cache = /* @__PURE__ */ new Map();
29
+ return {
30
+ fn: async (...args) => {
31
+ const key = getCacheKey(...args);
32
+ if (cache.has(key)) {
33
+ return cache.get(key);
34
+ }
35
+ const promise = fn(...args);
36
+ cache.set(key, promise);
37
+ try {
38
+ const result = await promise;
39
+ return result;
40
+ } catch (error) {
41
+ cache.delete(key);
42
+ throw error;
43
+ }
44
+ },
45
+ clearCache: () => {
46
+ cache.clear();
47
+ },
48
+ clearCacheEntry: (...args) => {
49
+ const key = getCacheKey(...args);
50
+ cache.delete(key);
51
+ }
52
+ };
53
+ }
54
+
26
55
  // src/utilities/app-proxy.ts
56
+ var memoizedFetch = memoize(
57
+ (...args) => global.fetch(...args),
58
+ (url) => url
59
+ );
27
60
  async function fetchAppProxyConfig({
28
61
  appProxyUrl = "/apps/coveo",
29
62
  marketId
30
63
  }) {
31
- const response = await fetch(`${appProxyUrl}?marketId=${marketId}]`);
64
+ const url = `${appProxyUrl}?marketId=${marketId}`;
65
+ const response = await memoizedFetch.fn(url);
66
+ if (!response.ok) {
67
+ memoizedFetch.clearCacheEntry(url);
68
+ throw new Error(
69
+ `Failed to fetch app proxy configuration from ${appProxyUrl} for marketId ${marketId}. Status: ${response.status}`
70
+ );
71
+ }
32
72
  return response.json();
33
73
  }
74
+ function clearAppProxyCache() {
75
+ memoizedFetch.clearCache();
76
+ }
77
+
78
+ // src/utilities/init.ts
79
+ import { getAnalyticsNextApiBaseUrl } from "@coveo/headless";
80
+ import { createRelay } from "@coveo/relay";
34
81
 
35
82
  // src/constants.ts
36
83
  var COVEO_SHOPIFY_CONFIG_KEY = "coveo_shopify_config";
84
+
85
+ // src/utilities/init.ts
86
+ function init(options) {
87
+ const relay = createRelay({
88
+ url: getAnalyticsNextApiBaseUrl(
89
+ options.organizationId,
90
+ options.environment
91
+ ),
92
+ token: options.accessToken,
93
+ trackingId: options.trackingId
94
+ });
95
+ const clientId = relay.getMeta("").clientId;
96
+ publishCustomShopifyEvent(COVEO_SHOPIFY_CONFIG_KEY, {
97
+ ...options,
98
+ clientId
99
+ });
100
+ }
37
101
  export {
38
102
  COVEO_SHOPIFY_CONFIG_KEY,
103
+ clearAppProxyCache,
39
104
  fetchAppProxyConfig,
105
+ init,
40
106
  publishCustomShopifyEvent
41
107
  };
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "main": "./dist/headless.esm.js",
9
9
  "module": "./dist/headless.esm.js",
10
10
  "license": "Apache-2.0",
11
- "version": "1.6.1-pre.fda43fc695",
11
+ "version": "1.7.0-pre.153636d7cb",
12
12
  "files": [
13
13
  "dist/"
14
14
  ],
@@ -38,6 +38,11 @@
38
38
  "types": "./dist/utilities/index.d.ts",
39
39
  "import": "./dist/utilities.esm.js",
40
40
  "default": "./dist/utilities.esm.js"
41
+ },
42
+ "./constants": {
43
+ "types": "./dist/constants.d.ts",
44
+ "import": "./dist/constants.esm.js",
45
+ "default": "./dist/constants.esm.js"
41
46
  }
42
47
  },
43
48
  "scripts": {
@@ -56,7 +61,8 @@
56
61
  "vitest": "3.2.3"
57
62
  },
58
63
  "dependencies": {
59
- "@coveo/headless": "3.26.2-pre.fda43fc695",
64
+ "@coveo/relay": "1.2.1",
65
+ "@coveo/headless": "3.27.0-pre.153636d7cb",
60
66
  "uuid": "^11.0.0"
61
67
  },
62
68
  "engines": {