@pack/hydrogen 1.0.6-ab-test.9 → 1.0.7

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.
@@ -2,7 +2,6 @@
2
2
  import { PackClient } from "@pack/client";
3
3
  import { CacheCustom } from "@shopify/hydrogen";
4
4
  import { PackSession } from "./session/session";
5
- import { Test, TestInput } from "./tests/test";
6
5
  /** @see https://shopify.dev/docs/custom-storefronts/hydrogen/data-fetching/cache#caching-strategies */
7
6
  type CachingStrategy = ReturnType<typeof CacheCustom>;
8
7
  interface EnvironmentOptions {
@@ -17,7 +16,7 @@ interface EnvironmentOptions {
17
16
  */
18
17
  waitUntil: ExecutionContext["waitUntil"];
19
18
  }
20
- export interface CreatePackClientOptions extends EnvironmentOptions {
19
+ interface CreatePackClientOptions extends EnvironmentOptions {
21
20
  apiUrl?: string;
22
21
  token?: string;
23
22
  storeId?: string;
@@ -30,7 +29,6 @@ type Variables = Record<string, any>;
30
29
  interface QueryOptions {
31
30
  variables?: Variables;
32
31
  cache?: CachingStrategy;
33
- test?: TestInput;
34
32
  }
35
33
  interface QueryError {
36
34
  message: string;
@@ -41,40 +39,18 @@ interface QueryError {
41
39
  interface QueryResponse<T> {
42
40
  data: T | null;
43
41
  error: QueryError | null;
44
- packTestInfo?: Test;
45
- }
46
- export interface PackCustomizerMeta {
47
- environment?: string;
48
- overlay?: {
49
- src?: string;
50
- version?: string;
51
- };
52
- [key: string]: any;
53
42
  }
54
43
  export interface Pack {
55
- abTest: Test | null | undefined;
56
- /**
57
- * @deprecated The method should not be used
58
- */
44
+ isPreviewModeEnabled: () => boolean;
45
+ session: PackSession;
46
+ query: <T = any>(query: string, options?: QueryOptions) => Promise<QueryResponse<T>>;
47
+ isValidEditToken: PackClient["isValidEditToken"];
59
48
  getPackSessionData(): {
60
49
  storeId: string;
61
50
  sessionId: string;
62
- abTest: Test | null | undefined;
63
51
  isPreviewModeEnabled: boolean;
64
52
  customizerMeta: any;
65
53
  };
66
- getPackContextData(): {
67
- packStoreId: string;
68
- packSessionId: string;
69
- packAbTest: Test | null | undefined;
70
- packIsPreviewMode: boolean;
71
- packCustomizerMeta: PackCustomizerMeta | null;
72
- };
73
- handleRequest(request: Request): Promise<(response: Response) => void>;
74
- isPreviewModeEnabled: () => boolean;
75
- isValidEditToken: PackClient["isValidEditToken"];
76
- query: <T = any>(query: string, options?: QueryOptions) => Promise<QueryResponse<T>>;
77
- session: PackSession;
78
54
  }
79
55
  interface DefaultThemeData {
80
56
  data: Record<string, any>;
@@ -1 +1 @@
1
- {"version":3,"file":"create-pack-client.d.ts","sourceRoot":"","sources":["../src/create-pack-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create-pack-client.d.ts","sourceRoot":"","sources":["../src/create-pack-client.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAmB,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,uGAAuG;AACvG,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,UAAU,kBAAkB;IAC1B;;;OAGG;IACH,KAAK,EAAE,KAAK,CAAC;IACb;;;OAGG;IACH,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;CAC1C;AAED,UAAU,uBAAwB,SAAQ,kBAAkB;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,WAAW,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAErC,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,aAAa,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,IAAI;IACnB,oBAAoB,EAAE,MAAM,OAAO,CAAC;IACpC,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,CAAC,CAAC,GAAG,GAAG,EACb,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,YAAY,KACnB,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,gBAAgB,EAAE,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAEjD,kBAAkB,IAAI;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,oBAAoB,EAAE,OAAO,CAAC;QAC9B,cAAc,EAAE,GAAG,CAAC;KACrB,CAAC;CACH;AAED,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B;AAoJD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAsIvE"}
@@ -1,7 +1,5 @@
1
1
  import { PackClient } from "@pack/client";
2
2
  import { CacheCustom, createWithCache } from "@shopify/hydrogen";
3
- import cookie from "cookie";
4
- import { getTestInfo, getTestFromQueryParams, getTestSession, getTestTargetingAttributesFromRequest, setTestHeaders, } from "./tests/test";
5
3
  /**
6
4
  * Create an SHA-256 hash as a hex string
7
5
  * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string
@@ -115,71 +113,16 @@ export function createPackClient(options) {
115
113
  const previewEnabled = !!session.get("previewEnabled");
116
114
  const previewEnvironment = session.get("environment");
117
115
  const clientContentEnvironment = previewEnvironment || contentEnvironment;
118
- let packClient;
119
- let testFromQueryParams = null;
120
- let testInfoForRequest = undefined;
121
116
  if (!token && !defaultThemeData) {
122
- throw new Error("ERR_HY_MISSING_TOKEN: The Pack client token is missing or empty. Please provide a valid token or default theme data. Doc: https://docs.packdigital.com/err/ERR_HY_MISSING_TOKEN");
117
+ throw new Error("The Pack client token is missing or empty. Please provide a valid token or default theme data.");
123
118
  }
124
119
  if (!storeId) {
125
- throw new Error("ERR_HY_MISSING_STORE_ID: The Pack Store ID is missing or empty. Please provide a valid Store ID. Doc: https://docs.packdigital.com/err/ERR_HY_MISSING_STORE_ID");
120
+ throw new Error("The Pack Store ID is missing or empty. Please provide a valid Store ID.");
126
121
  }
127
- const handleRequest = async (request) => {
128
- testFromQueryParams = getTestFromQueryParams(request);
129
- const testTargetAudienceAttributes = getTestTargetingAttributesFromRequest(request);
130
- if (packClient && token) {
131
- testInfoForRequest = await getTestInfo({
132
- request,
133
- testTargetAudienceAttributes,
134
- packClient,
135
- session,
136
- token,
137
- });
138
- }
139
- return (response) => {
140
- const hasExposedTestCookie = request.headers
141
- .get("cookie")
142
- ?.includes("exposedTest");
143
- if (hasExposedTestCookie) {
144
- // Clear the exposedTest cookie
145
- response.headers.set("Set-Cookie", cookie.serialize("exposedTest", "", {
146
- maxAge: 0,
147
- }));
148
- }
149
- };
150
- };
151
- const getTestInfoForLoader = () => {
152
- let testInfoForLoader = undefined;
153
- if (testInfoForRequest?.isFirstExposure) {
154
- const { isFirstExposure, ...testInfo } = testInfoForRequest;
155
- testInfoForLoader = testInfo;
156
- }
157
- return testInfoForLoader;
158
- };
159
122
  if (!token) {
160
123
  return {
161
- abTest: getTestSession(session, testFromQueryParams, previewEnabled),
162
- handleRequest,
163
- getPackSessionData: () => {
164
- return {
165
- storeId: storeId,
166
- sessionId: session.id,
167
- abTest: getTestSession(session, testFromQueryParams, previewEnabled),
168
- isPreviewModeEnabled: previewEnabled,
169
- customizerMeta: session.get("customizerMeta"),
170
- };
171
- },
172
- getPackContextData: () => {
173
- return {
174
- packStoreId: storeId,
175
- packSessionId: session.id,
176
- packAbTest: getTestSession(session, testFromQueryParams, previewEnabled),
177
- packIsPreviewMode: previewEnabled,
178
- packCustomizerMeta: session.get("customizerMeta"),
179
- };
180
- },
124
+ session,
181
125
  isPreviewModeEnabled: () => previewEnabled,
182
- isValidEditToken: () => new Promise(() => false),
183
126
  async query(query, { variables } = {}) {
184
127
  if (!defaultThemeData?.data) {
185
128
  console.warn("Invalid default theme data provided to Pack client.");
@@ -188,10 +131,18 @@ export function createPackClient(options) {
188
131
  const data = resolveQuery({ query, variables, defaultThemeData });
189
132
  return { data: data, error: null };
190
133
  },
191
- session,
134
+ isValidEditToken: () => new Promise(() => false),
135
+ getPackSessionData: () => {
136
+ return {
137
+ storeId: storeId,
138
+ sessionId: session.id,
139
+ isPreviewModeEnabled: previewEnabled,
140
+ customizerMeta: session.get("customizerMeta"),
141
+ };
142
+ },
192
143
  };
193
144
  }
194
- packClient = new PackClient({
145
+ const packClient = new PackClient({
195
146
  // Use apiUrl, it is configured
196
147
  // Use active API URL if preview mode is enabled
197
148
  // Otherwise, Live PackClient uses its internal configuration
@@ -207,39 +158,14 @@ export function createPackClient(options) {
207
158
  clientName: "HydrogenClient",
208
159
  });
209
160
  return {
210
- abTest: getTestSession(session, testFromQueryParams, previewEnabled),
211
- getPackSessionData: () => {
212
- return {
213
- storeId: storeId,
214
- sessionId: session.id,
215
- abTest: getTestSession(session, testFromQueryParams, previewEnabled),
216
- isPreviewModeEnabled: previewEnabled,
217
- customizerMeta: session.get("customizerMeta"),
218
- };
219
- },
220
- getPackContextData: () => {
221
- return {
222
- packStoreId: storeId,
223
- packSessionId: session.id,
224
- packAbTest: getTestSession(session, testFromQueryParams, previewEnabled),
225
- packIsPreviewMode: previewEnabled,
226
- packCustomizerMeta: session.get("customizerMeta"),
227
- };
228
- },
229
- handleRequest,
161
+ session,
230
162
  isPreviewModeEnabled: () => previewEnabled,
231
- isValidEditToken: (token) => packClient.isValidEditToken(token),
232
- async query(query, { variables, cache: strategy = cacheCustom, test } = {}) {
233
- let headers = {};
163
+ async query(query, { variables, cache: strategy = cacheCustom } = {}) {
234
164
  const withCache = createWithCache({
235
165
  cache,
236
166
  waitUntil,
237
167
  });
238
- headers = setTestHeaders(headers, {
239
- previewEnabled,
240
- testInfoForRequest,
241
- testFromQueryParams: testFromQueryParams || test,
242
- });
168
+ let headers = {};
243
169
  const queryVariables = variables ? { ...variables } : {};
244
170
  if (previewEnabled) {
245
171
  queryVariables.version = "CURRENT";
@@ -247,27 +173,23 @@ export function createPackClient(options) {
247
173
  else {
248
174
  queryVariables.version = "PUBLISHED";
249
175
  }
250
- const testInfoForLoader = getTestInfoForLoader();
251
176
  // Preview mode always bypasses the cache
252
177
  if (previewEnabled) {
253
178
  try {
254
- return {
255
- ...(await packClient.fetch(query, {
256
- variables: queryVariables,
257
- headers: headers,
258
- })),
259
- packTestInfo: testInfoForLoader,
260
- };
179
+ return await packClient.fetch(query, {
180
+ variables: queryVariables,
181
+ headers: headers,
182
+ });
261
183
  }
262
184
  catch (error) {
263
- return { error: error, data: null };
185
+ return { error, data: {} };
264
186
  }
265
187
  }
266
188
  const queryHash = await getCacheKey(withCache, query, token, {
267
189
  variables: queryVariables,
268
190
  headers,
269
191
  });
270
- const response = await withCache(queryHash, strategy, async () => {
192
+ return withCache(queryHash, strategy, async () => {
271
193
  try {
272
194
  return await packClient.fetch(query, {
273
195
  variables: queryVariables,
@@ -275,13 +197,18 @@ export function createPackClient(options) {
275
197
  });
276
198
  }
277
199
  catch (error) {
278
- return { error, data: null };
200
+ return { error, data: {} };
279
201
  }
280
202
  });
281
- return response.error
282
- ? response
283
- : { ...response, packTestInfo: testInfoForLoader };
284
203
  },
285
- session,
204
+ isValidEditToken: (token) => packClient.isValidEditToken(token),
205
+ getPackSessionData: () => {
206
+ return {
207
+ storeId: storeId,
208
+ sessionId: session.id,
209
+ isPreviewModeEnabled: previewEnabled,
210
+ customizerMeta: session.get("customizerMeta"),
211
+ };
212
+ },
286
213
  };
287
214
  }
@@ -1 +1 @@
1
- {"version":3,"file":"handle-request.d.ts","sourceRoot":"","sources":["../src/handle-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAG5C,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,GACrD,OAAO,CAAC,QAAQ,CAAC,CAanB"}
1
+ {"version":3,"file":"handle-request.d.ts","sourceRoot":"","sources":["../src/handle-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAG5C,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,GACrD,OAAO,CAAC,QAAQ,CAAC,CASnB"}
@@ -1,10 +1,8 @@
1
1
  import { packlytics } from "@pack/packlytics";
2
2
  export async function handleRequest(pack, request, handleRequest) {
3
- const packHandleResponse = await pack.handleRequest(request);
4
3
  const response = await packlytics(pack, request, () => {
5
4
  return handleRequest(request);
6
5
  });
7
- packHandleResponse(response);
8
6
  response.headers.append("powered-by", "Shopify, Hydrogen + Pack Digital");
9
7
  response.headers.append("Set-Cookie", await pack.session.commit());
10
8
  return response;
package/dist/index.d.ts CHANGED
@@ -1,9 +1,7 @@
1
1
  import { handleRequest } from "./handle-request";
2
2
  import { usePackCookies } from "./session/usePackCookies";
3
3
  import { PackSession } from "./session/session";
4
- import { Pack, createPackClient } from "./create-pack-client";
4
+ import { createPackClient } from "./create-pack-client";
5
5
  import { action as previewModeAction, loader as previewModeLoader } from "./preview/preview-mode";
6
- import { PackTestContext, usePackTestContext, PackTestProvider, PackTestRoute, useAbTest, useAbTestId, useAbTestHandle, useAbTestSessionId, useAbTestVariantId, useAbTestVariantHandle } from "./tests";
7
- export type { Pack };
8
- export { PackSession, createPackClient, handleRequest, previewModeAction, previewModeLoader, usePackCookies, PackTestContext, usePackTestContext, PackTestProvider, PackTestRoute, useAbTest, useAbTestId, useAbTestHandle, useAbTestSessionId, useAbTestVariantId, useAbTestVariantHandle, };
6
+ export { PackSession, createPackClient, handleRequest, previewModeAction, previewModeLoader, usePackCookies, };
9
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EACL,MAAM,IAAI,iBAAiB,EAC3B,MAAM,IAAI,iBAAiB,EAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,IAAI,EAAE,CAAC;AAErB,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,GACvB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EACL,MAAM,IAAI,iBAAiB,EAC3B,MAAM,IAAI,iBAAiB,EAC5B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,GACf,CAAC"}
package/dist/index.js CHANGED
@@ -3,5 +3,4 @@ import { usePackCookies } from "./session/usePackCookies";
3
3
  import { PackSession } from "./session/session";
4
4
  import { createPackClient } from "./create-pack-client";
5
5
  import { action as previewModeAction, loader as previewModeLoader, } from "./preview/preview-mode";
6
- import { PackTestContext, usePackTestContext, PackTestProvider, PackTestRoute, useAbTest, useAbTestId, useAbTestHandle, useAbTestSessionId, useAbTestVariantId, useAbTestVariantHandle, } from "./tests";
7
- export { PackSession, createPackClient, handleRequest, previewModeAction, previewModeLoader, usePackCookies, PackTestContext, usePackTestContext, PackTestProvider, PackTestRoute, useAbTest, useAbTestId, useAbTestHandle, useAbTestSessionId, useAbTestVariantId, useAbTestVariantHandle, };
6
+ export { PackSession, createPackClient, handleRequest, previewModeAction, previewModeLoader, usePackCookies, };
@@ -1 +1 @@
1
- {"version":3,"file":"preview-mode.d.ts","sourceRoot":"","sources":["../../src/preview/preview-mode.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAKnC,KAAK,YAAY,GAAG,CAAC,IAAI,EACvB,IAAI,EAAE,IAAI,EACV,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,KACzB,aAAa,CAAC,IAAI,CAAC,CAAC;AAEzB,KAAK,gBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,KAAK,QAAQ,CAAC;AAIhF,KAAK,aAAa,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG;IACzD,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;CACpB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,IAAI,EAAE,YAYlB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,gBAetB,CAAC;AAoBF;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,cAcpB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,cAuCpB,CAAC"}
1
+ {"version":3,"file":"preview-mode.d.ts","sourceRoot":"","sources":["../../src/preview/preview-mode.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAInC,KAAK,YAAY,GAAG,CAAC,IAAI,EACvB,IAAI,EAAE,IAAI,EACV,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,KACzB,aAAa,CAAC,IAAI,CAAC,CAAC;AAEzB,KAAK,gBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,KAAK,QAAQ,CAAC;AAIhF,KAAK,aAAa,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG;IACzD,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;CACpB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,IAAI,EAAE,YAYlB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,gBAetB,CAAC;AAoBF;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,cAcpB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,cAqCpB,CAAC"}
@@ -84,9 +84,7 @@ export const loader = async function ({ request, context }) {
84
84
  }
85
85
  let customizerMetaJson;
86
86
  try {
87
- customizerMetaJson = customizerMeta
88
- ? JSON.parse(customizerMeta)
89
- : null;
87
+ customizerMetaJson = customizerMeta ? JSON.parse(customizerMeta) : null;
90
88
  }
91
89
  catch (_error) {
92
90
  customizerMetaJson = null;
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAiB/B,qBAAa,WAAW;;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAOtB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,OAAO;WAQL,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IA2B5E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,GAAG,CAAC,GAAG,EAAE,MAAM;IAIf,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAQ1B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAIlC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;CAG1B"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAI/B,qBAAa,WAAW;;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAOtB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,OAAO;WAQL,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAsB5E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,GAAG,CAAC,GAAG,EAAE,MAAM;IAIf,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAQ1B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAIlC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;CAG1B"}
@@ -1,16 +1,6 @@
1
1
  import { createCookie, createCookieSessionStorage, } from "@shopify/remix-oxygen";
2
2
  import { PACK_COOKIE_ID, PACK_COOKIE_MAX_AGE } from "../constants";
3
3
  import { buildRandomUUID, hasUserConsent } from "./cookies-utils";
4
- function isSafari(userAgent) {
5
- if (!userAgent)
6
- return false;
7
- // Check for iOS devices (iPhone/iPad) or macOS Safari
8
- return (/Safari\//.test(userAgent) &&
9
- !/Chrome\//.test(userAgent) &&
10
- !/Chromium\//.test(userAgent) &&
11
- !/Edg\//.test(userAgent) &&
12
- !/Firefox\//.test(userAgent));
13
- }
14
4
  export class PackSession {
15
5
  id;
16
6
  secret;
@@ -23,12 +13,9 @@ export class PackSession {
23
13
  this.#sessionStorage = sessionStorage;
24
14
  }
25
15
  static async init(request, secrets) {
26
- const userAgent = request.headers.get("User-Agent");
27
16
  const storage = createCookieSessionStorage({
28
17
  cookie: createCookie(PACK_COOKIE_ID, {
29
- secure: isSafari(userAgent) && process.env.NODE_ENV === "development"
30
- ? false
31
- : true,
18
+ secure: true,
32
19
  secrets,
33
20
  sameSite: "none",
34
21
  maxAge: PACK_COOKIE_MAX_AGE,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pack/hydrogen",
3
3
  "description": "Pack Hydrogen",
4
- "version": "1.0.6-ab-test.9",
4
+ "version": "1.0.7",
5
5
  "exports": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "engines": {
@@ -22,17 +22,14 @@
22
22
  "dist"
23
23
  ],
24
24
  "dependencies": {
25
- "@pack/client": "^1.0.2-ab-test.0",
25
+ "@pack/client": "^1.0.1",
26
26
  "@pack/packlytics": "^1.0.1",
27
- "@shopify/hydrogen": "^2023.10.2",
28
- "cookie": "^0.6.0",
29
- "js-cookie": "^3.0.5"
27
+ "@shopify/hydrogen": "^2023.10.2"
30
28
  },
31
29
  "devDependencies": {
32
30
  "@remix-run/server-runtime": "^2.0.0",
33
31
  "@shopify/oxygen-workers-types": "^4.0.0",
34
32
  "@shopify/remix-oxygen": "^2.0.1",
35
- "@types/js-cookie": "^3.0.6",
36
33
  "@types/node": "^20.11.17"
37
34
  },
38
35
  "peerDependencies": {
@@ -1,8 +0,0 @@
1
- import { Test } from "./test";
2
- export declare function useAbTest(): Test | null;
3
- export declare function useAbTestSessionId(): string;
4
- export declare function useAbTestId(): string | undefined;
5
- export declare function useAbTestHandle(): string | undefined;
6
- export declare function useAbTestVariantId(): string | undefined;
7
- export declare function useAbTestVariantHandle(): string | undefined;
8
- //# sourceMappingURL=hooks.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/tests/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,wBAAgB,SAAS,IAAI,IAAI,GAAG,IAAI,CAWvC;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAW3C;AAED,wBAAgB,WAAW,IAAI,MAAM,GAAG,SAAS,CAIhD;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAIpD;AAED,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAIvD;AAED,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAI3D"}
@@ -1,33 +0,0 @@
1
- import { useRouteLoaderData } from "@remix-run/react";
2
- export function useAbTest() {
3
- // @ts-ignore
4
- const { abTest, packAbTest } = useRouteLoaderData("root");
5
- if (abTest === undefined && packAbTest === undefined) {
6
- throw new Error("ERR_HY_MISSING_AB_TEST_CONTEXT: No A/B test found, are you sure you have call ...pack.getPackContextData() on root loader return? Doc: https://docs.packdigital.com/err/ERR_HY_MISSING_AB_TEST_CONTEXT");
7
- }
8
- return abTest || packAbTest;
9
- }
10
- export function useAbTestSessionId() {
11
- // @ts-ignore
12
- const { sessionId, packSessionId } = useRouteLoaderData("root");
13
- if (!sessionId && !packSessionId) {
14
- throw new Error("ERR_HY_MISSING_SESSION_ID: No Session ID found, are you sure you have call ...pack.getPackContextData() on root loader return? Doc: https://docs.packdigital.com/err/ERR_HY_MISSING_SESSION_ID");
15
- }
16
- return sessionId || packSessionId;
17
- }
18
- export function useAbTestId() {
19
- const test = useAbTest();
20
- return test?.id;
21
- }
22
- export function useAbTestHandle() {
23
- const test = useAbTest();
24
- return test?.handle;
25
- }
26
- export function useAbTestVariantId() {
27
- const test = useAbTest();
28
- return test?.testVariant?.id;
29
- }
30
- export function useAbTestVariantHandle() {
31
- const test = useAbTest();
32
- return test?.testVariant?.handle;
33
- }
@@ -1,6 +0,0 @@
1
- import { PackTestRoute } from "./pack-test-route";
2
- import { PackTestContext, usePackTestContext } from "./pack-test-context";
3
- import { PackTestProvider } from "./pack-test-provider";
4
- import { useAbTest, useAbTestHandle, useAbTestId, useAbTestSessionId, useAbTestVariantHandle, useAbTestVariantId } from "./hooks";
5
- export { PackTestContext, usePackTestContext, PackTestProvider, PackTestRoute, useAbTest, useAbTestId, useAbTestHandle, useAbTestSessionId, useAbTestVariantId, useAbTestVariantHandle, };
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tests/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EACL,SAAS,EACT,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,GACvB,CAAC"}
@@ -1,5 +0,0 @@
1
- import { PackTestRoute } from "./pack-test-route";
2
- import { PackTestContext, usePackTestContext } from "./pack-test-context";
3
- import { PackTestProvider } from "./pack-test-provider";
4
- import { useAbTest, useAbTestHandle, useAbTestId, useAbTestSessionId, useAbTestVariantHandle, useAbTestVariantId, } from "./hooks";
5
- export { PackTestContext, usePackTestContext, PackTestProvider, PackTestRoute, useAbTest, useAbTestId, useAbTestHandle, useAbTestSessionId, useAbTestVariantId, useAbTestVariantHandle, };
@@ -1,23 +0,0 @@
1
- import { Dispatch, SetStateAction } from "react";
2
- export interface Test {
3
- id: string;
4
- handle: string;
5
- testVariant: {
6
- id: string;
7
- handle: string;
8
- };
9
- }
10
- interface TestExposureCallbackArg extends Test {
11
- exposureTime: number;
12
- }
13
- type PackTestContextValue = {
14
- testExposureCallback?: (test: TestExposureCallbackArg) => void;
15
- hasUserConsent?: boolean | undefined;
16
- pendingExposureQueue?: Map<any, any>;
17
- setPendingExposureQueue?: Dispatch<SetStateAction<Map<any, any>>>;
18
- exposedExperiments?: Set<unknown>;
19
- };
20
- export declare const PackTestContext: import("react").Context<PackTestContextValue>;
21
- export declare const usePackTestContext: () => PackTestContextValue;
22
- export {};
23
- //# sourceMappingURL=pack-test-context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pack-test-context.d.ts","sourceRoot":"","sources":["../../src/tests/pack-test-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,QAAQ,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5E,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE;QACX,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,UAAU,uBAAwB,SAAQ,IAAI;IAC5C,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,KAAK,oBAAoB,GAAG;IAC1B,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC/D,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,oBAAoB,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACrC,uBAAuB,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAClE,kBAAkB,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,eAAe,+CAA0C,CAAC;AAEvE,eAAO,MAAM,kBAAkB,4BAAoC,CAAC"}
@@ -1,3 +0,0 @@
1
- import { createContext, useContext } from "react";
2
- export const PackTestContext = createContext({});
3
- export const usePackTestContext = () => useContext(PackTestContext);
@@ -1,9 +0,0 @@
1
- import React, { PropsWithChildren } from "react";
2
- import { Test } from "./pack-test-context";
3
- interface PackContentProps {
4
- testExposureCallback?: (test: Test) => void;
5
- hasUserConsent?: boolean;
6
- }
7
- export declare function PackTestProvider({ children, testExposureCallback, hasUserConsent, }: PropsWithChildren<PackContentProps>): React.JSX.Element;
8
- export {};
9
- //# sourceMappingURL=pack-test-provider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pack-test-provider.d.ts","sourceRoot":"","sources":["../../src/tests/pack-test-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAY,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAmB,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE5D,UAAU,gBAAgB;IACxB,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC5C,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,oBAAoB,EACpB,cAAsB,GACvB,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,qBAmBrC"}
@@ -1,15 +0,0 @@
1
- import React, { useState } from "react";
2
- import { PackTestContext } from "./pack-test-context";
3
- export function PackTestProvider({ children, testExposureCallback, hasUserConsent = false, }) {
4
- const [pendingExposureQueue, setPendingExposureQueue] = useState(new Map());
5
- const [exposedExperiments] = useState(new Set());
6
- return (React.createElement(PackTestContext.Provider, { value: {
7
- testExposureCallback: (test) => {
8
- testExposureCallback && testExposureCallback(test);
9
- },
10
- hasUserConsent,
11
- pendingExposureQueue,
12
- setPendingExposureQueue,
13
- exposedExperiments,
14
- } }, children));
15
- }
@@ -1,2 +0,0 @@
1
- export declare const PackTestRoute: () => null;
2
- //# sourceMappingURL=pack-test-route.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pack-test-route.d.ts","sourceRoot":"","sources":["../../src/tests/pack-test-route.ts"],"names":[],"mappings":"AA0GA,eAAO,MAAM,aAAa,YAIzB,CAAC"}
@@ -1,79 +0,0 @@
1
- import { useLoaderData, useMatches } from "@remix-run/react";
2
- import Cookies from "js-cookie";
3
- import { useEffect, useState } from "react";
4
- import { useRevalidator } from "react-router-dom";
5
- import { usePackTestContext } from "./pack-test-context";
6
- const usePackLoaderData = () => {
7
- const [exposedTestInfo, setExposedTestInfo] = useState();
8
- const { packTestInfo } = useLoaderData();
9
- const [root] = useMatches();
10
- const { packIsPreviewMode } = root?.data;
11
- const { testExposureCallback, hasUserConsent, pendingExposureQueue, setPendingExposureQueue, } = usePackTestContext();
12
- const revalidator = useRevalidator();
13
- const exposedTestCookieString = Cookies.get("exposedTest");
14
- useEffect(() => {
15
- if (packTestInfo &&
16
- !packIsPreviewMode &&
17
- !hasUserConsent &&
18
- exposedTestCookieString &&
19
- exposedTestInfo) {
20
- // Add to the pending exposure queue if no user consent
21
- setPendingExposureQueue?.((prev) => {
22
- const newQueue = new Map(prev);
23
- newQueue.set(packTestInfo.id, {
24
- packTestInfo,
25
- exposureTime: Date.now(),
26
- });
27
- return newQueue;
28
- });
29
- }
30
- }, [
31
- hasUserConsent,
32
- packTestInfo,
33
- packIsPreviewMode,
34
- exposedTestCookieString,
35
- exposedTestInfo,
36
- ]);
37
- useEffect(() => {
38
- if (packTestInfo &&
39
- hasUserConsent &&
40
- !exposedTestCookieString &&
41
- !packIsPreviewMode &&
42
- !exposedTestInfo) {
43
- // Set exposedTest cookie used by server to determine if session has been exposed to test
44
- const expires = new Date();
45
- expires.setHours(expires.getHours() + 24);
46
- Cookies.set("exposedTest", JSON.stringify(packTestInfo), {
47
- expires,
48
- });
49
- setExposedTestInfo(packTestInfo);
50
- console.log("=== TCB HAS USER CONSENT", hasUserConsent);
51
- // Need to go through current exposure tracking callback queue
52
- // call tracking callbacks for previous exposures
53
- pendingExposureQueue?.forEach((data, key) => {
54
- try {
55
- testExposureCallback?.({
56
- ...data.packTestInfo,
57
- exposureTime: data.exposureTime,
58
- });
59
- setPendingExposureQueue?.((prev) => {
60
- const newQueue = new Map(prev);
61
- newQueue.delete(key);
62
- return newQueue;
63
- });
64
- }
65
- catch (error) {
66
- console.error("Failed to call testExposure after consent:", error);
67
- }
68
- });
69
- testExposureCallback?.({ ...packTestInfo, exposureTime: Date.now() });
70
- // TODO: This results in flashing of UI driven by site settings data.
71
- // Need non-flashing solution.
72
- revalidator.revalidate();
73
- }
74
- }, [packTestInfo, testExposureCallback, exposedTestInfo, hasUserConsent]);
75
- };
76
- export const PackTestRoute = () => {
77
- usePackLoaderData();
78
- return null;
79
- };
@@ -1,46 +0,0 @@
1
- import { PackClient } from "@pack/client";
2
- import { PackSession } from "../session/session";
3
- export interface TestInput {
4
- testId?: string;
5
- testHandle?: string;
6
- testVariantId?: string;
7
- testVariantHandle?: string;
8
- }
9
- export interface Test {
10
- id: string;
11
- handle: string;
12
- testVariant: {
13
- id: string;
14
- handle: string;
15
- };
16
- }
17
- export interface TestTargetAudienceAttributes {
18
- url?: string;
19
- query?: string;
20
- path?: string;
21
- utmCampaign?: string;
22
- utmContent?: string;
23
- utmMedium?: string;
24
- utmSource?: string;
25
- utmTerm?: string;
26
- }
27
- export interface GetTestInfoOptions {
28
- request: Request;
29
- testTargetAudienceAttributes: TestTargetAudienceAttributes | null;
30
- packClient: PackClient;
31
- session: PackSession | undefined;
32
- token: string;
33
- }
34
- export interface TestInfo extends Test {
35
- isFirstExposure?: boolean;
36
- }
37
- export declare function getTestInfo({ request, testTargetAudienceAttributes, packClient, session, token, }: GetTestInfoOptions): Promise<TestInfo | undefined>;
38
- export declare function getTestSession(session: PackSession | undefined, testFromQueryParams: TestInput | null, previewEnabled: boolean): Test | null | undefined;
39
- export declare function getTestTargetingAttributesFromRequest(request: Request): TestTargetAudienceAttributes;
40
- export declare function getTestFromQueryParams(request: Request): TestInput | null;
41
- export declare function setTestHeaders(headers: any, options: {
42
- previewEnabled: boolean;
43
- testInfoForRequest?: TestInfo;
44
- testFromQueryParams?: TestInput;
45
- }): any;
46
- //# sourceMappingURL=test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/tests/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE;QACX,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAQD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,4BAA4B,EAAE,4BAA4B,GAAG,IAAI,CAAC;IAClE,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAS,SAAQ,IAAI;IACpC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AA2FD,wBAAsB,WAAW,CAAC,EAChC,OAAO,EACP,4BAA4B,EAC5B,UAAU,EACV,OAAO,EACP,KAAK,GACN,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAgGpD;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,mBAAmB,EAAE,SAAS,GAAG,IAAI,EACrC,cAAc,EAAE,OAAO,GACtB,IAAI,GAAG,IAAI,GAAG,SAAS,CA8BzB;AAED,wBAAgB,qCAAqC,CACnD,OAAO,EAAE,OAAO,GACf,4BAA4B,CA0B9B;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CA2CzE;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE;IACP,cAAc,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,QAAQ,CAAC;IAC9B,mBAAmB,CAAC,EAAE,SAAS,CAAC;CACjC,OA+BF"}
@@ -1,252 +0,0 @@
1
- import cookie from "cookie";
2
- const QUERY_TEST_VARIANT_IS_RUNNING = `#graphql
3
- query TestVariantIsRunning($handle: String!, $testId: ID!) {
4
- testVariantIsRunning(handle: $handle, testId: $testId)
5
- }
6
- `;
7
- async function packClientFetchTestByRules(packClient, testTargetAudienceAttributes, token) {
8
- if (!packClient.storeId) {
9
- console.error("Pack error: Store ID is required to fetch a test.");
10
- return undefined;
11
- }
12
- let resp = undefined;
13
- const URL = "https://tests-service-production.packdigital.workers.dev/tests/assign";
14
- const assignByRulesResp = await fetch(URL, {
15
- method: "POST",
16
- headers: {
17
- Authorization: `Bearer ${token}`,
18
- "X-Pack-Storefront-Id": packClient.storeId,
19
- ...(packClient.contentEnvironment
20
- ? { "X-Environment": packClient.contentEnvironment }
21
- : {}),
22
- "Content-Type": "application/json",
23
- },
24
- body: JSON.stringify({
25
- attributes: testTargetAudienceAttributes,
26
- }),
27
- });
28
- const { status } = assignByRulesResp;
29
- if (status !== 200) {
30
- let message;
31
- if (status === 401) {
32
- message =
33
- "Pack error: Unauthorized request to test assignment service. Please check your token.";
34
- }
35
- else {
36
- message = `Pack error: Request to test assignment service failed with status ${status}`;
37
- }
38
- console.error(message);
39
- return resp;
40
- }
41
- const assignByRulesRespJson = await assignByRulesResp.json();
42
- if (assignByRulesRespJson?.data) {
43
- resp = {
44
- ...assignByRulesRespJson.data,
45
- // `isFirstExposure` tells the `<PackTestRoute />` this will be the
46
- // first exposure on render and will be confirmed next request
47
- isFirstExposure: true,
48
- };
49
- }
50
- return resp;
51
- }
52
- async function packClientCheckTestIsRunning(packClient, testSession) {
53
- try {
54
- const resp = await packClient.fetch(QUERY_TEST_VARIANT_IS_RUNNING, {
55
- variables: {
56
- handle: testSession.testVariant.handle,
57
- testId: testSession.id,
58
- },
59
- });
60
- return !!resp.data.testVariantIsRunning;
61
- }
62
- catch (e) {
63
- console.error(e);
64
- }
65
- return false;
66
- }
67
- function getExpireAtDate() {
68
- const expireAt = new Date();
69
- expireAt.setHours(expireAt.getHours() + 4); // 4 hours
70
- return expireAt;
71
- }
72
- export async function getTestInfo({ request, testTargetAudienceAttributes, packClient, session, token, }) {
73
- let testInfo = undefined;
74
- let exposedTest = undefined;
75
- if (!session) {
76
- return testInfo;
77
- }
78
- const testSession = session.get("test");
79
- const exposedTestCookieString = cookie.parse(request.headers.get("cookie") || "")?.exposedTest;
80
- if (exposedTestCookieString) {
81
- exposedTest = JSON.parse(exposedTestCookieString);
82
- }
83
- if (exposedTest && !testSession) {
84
- // If there is no assigned test on the session and an exposed test in the
85
- // incoming request cookie it means that the user was exposed to a test previously.
86
- // Verify test is still running
87
- const testVariantIsRunning = await packClientCheckTestIsRunning(packClient, exposedTest);
88
- // If the test is still running, set testInfo for the client and store in session
89
- if (testVariantIsRunning) {
90
- const { id, handle, testVariant } = exposedTest;
91
- testInfo = {
92
- id,
93
- handle,
94
- testVariant,
95
- };
96
- // Only set the test to the session on exposure
97
- session.set("test", {
98
- data: testInfo,
99
- expireAt: getExpireAtDate(),
100
- });
101
- }
102
- else {
103
- // If the test is not running, fetch a new test for the client
104
- testInfo = await packClientFetchTestByRules(packClient, testTargetAudienceAttributes, token);
105
- }
106
- }
107
- else {
108
- // If there is no exposed test in the incoming request cookie
109
- if (testSession && testSession.data?.id && testSession.data?.testVariant) {
110
- // If there is a test on session, check if the test on session has expired
111
- if (!testSession.expireAt ||
112
- new Date(testSession.expireAt) < new Date()) {
113
- // If there is test on session, check if the test on session is still running
114
- const testVariantIsRunning = await packClientCheckTestIsRunning(packClient, testSession.data);
115
- // If true, set testInfo to the testSession assigned test.
116
- if (testVariantIsRunning) {
117
- testInfo = testSession.data;
118
- session.set("test", {
119
- data: testInfo,
120
- expireAt: getExpireAtDate(),
121
- });
122
- }
123
- else {
124
- // If not running, clear test session and fetch a new test for the client
125
- session.set("test", undefined);
126
- testInfo = await packClientFetchTestByRules(packClient, testTargetAudienceAttributes, token);
127
- }
128
- }
129
- else {
130
- testInfo = testSession.data;
131
- }
132
- }
133
- else {
134
- // If there is no test on session and no exposed test, check for a new test for client
135
- testInfo = await packClientFetchTestByRules(packClient, testTargetAudienceAttributes, token);
136
- }
137
- }
138
- return testInfo;
139
- }
140
- export function getTestSession(session, testFromQueryParams, previewEnabled) {
141
- if (testFromQueryParams) {
142
- return {
143
- id: testFromQueryParams.testId || "",
144
- handle: testFromQueryParams.testHandle || "",
145
- testVariant: {
146
- id: testFromQueryParams.testVariantId || "",
147
- handle: testFromQueryParams.testVariantHandle || "",
148
- },
149
- };
150
- }
151
- if (previewEnabled) {
152
- return {
153
- id: "",
154
- handle: "isPreview",
155
- testVariant: {
156
- id: "",
157
- handle: "isPreview",
158
- },
159
- };
160
- }
161
- if (!session) {
162
- return undefined;
163
- }
164
- const testSession = session.get("test");
165
- return testSession?.data || null;
166
- }
167
- export function getTestTargetingAttributesFromRequest(request) {
168
- let testTargetingAttributes = {};
169
- const requestUrl = new URL(request.url);
170
- const searchParams = requestUrl.searchParams;
171
- testTargetingAttributes.url = requestUrl.origin + requestUrl.pathname;
172
- testTargetingAttributes.query = requestUrl.search;
173
- testTargetingAttributes.path = requestUrl.pathname;
174
- searchParams.has("utm_campaign") &&
175
- (testTargetingAttributes.utmCampaign =
176
- searchParams.get("utm_campaign") || undefined);
177
- searchParams.has("utm_content") &&
178
- (testTargetingAttributes.utmContent =
179
- searchParams.get("utm_content") || undefined);
180
- searchParams.has("utm_medium") &&
181
- (testTargetingAttributes.utmMedium =
182
- searchParams.get("utm_medium") || undefined);
183
- searchParams.has("utm_source") &&
184
- (testTargetingAttributes.utmSource =
185
- searchParams.get("utm_source") || undefined);
186
- searchParams.has("utm_term") &&
187
- (testTargetingAttributes.utmTerm =
188
- searchParams.get("utm_term") || undefined);
189
- return testTargetingAttributes;
190
- }
191
- export function getTestFromQueryParams(request) {
192
- const requestUrl = new URL(request.url);
193
- const params = requestUrl.searchParams;
194
- if (params.has("testId") ||
195
- params.has("test_id") ||
196
- params.has("test-id") ||
197
- params.has("testHandle") ||
198
- params.has("test_handle") ||
199
- params.has("test-handle") ||
200
- params.has("testVariantId") ||
201
- params.has("test_variant_id") ||
202
- params.has("test-variant-id") ||
203
- params.has("testVariantHandle") ||
204
- params.has("test_variant_handle") ||
205
- params.has("test-variant-handle")) {
206
- return {
207
- testId: params.get("testId") ||
208
- params.get("test_id") ||
209
- params.get("test-id") ||
210
- "",
211
- testHandle: params.get("testHandle") ||
212
- params.get("test_handle") ||
213
- params.get("test-handle") ||
214
- "",
215
- testVariantId: params.get("testVariantId") ||
216
- params.get("test_variant_id") ||
217
- params.get("test-variant-id") ||
218
- "",
219
- testVariantHandle: params.get("testVariantHandle") ||
220
- params.get("test_variant_handle") ||
221
- params.get("test-variant-handle") ||
222
- "",
223
- };
224
- }
225
- return null;
226
- }
227
- export function setTestHeaders(headers, options) {
228
- const { previewEnabled, testFromQueryParams, testInfoForRequest } = options;
229
- if (testFromQueryParams) {
230
- headers["X-Pack-Test-Ignore-Test-Status"] = true;
231
- if (testFromQueryParams.testId) {
232
- headers["X-Pack-Test-Id"] = testFromQueryParams.testId;
233
- }
234
- if (testFromQueryParams.testHandle) {
235
- headers["X-Pack-Test-Handle"] = testFromQueryParams.testHandle;
236
- }
237
- if (testFromQueryParams.testVariantId) {
238
- headers["X-Pack-Test-Variant-Id"] = testFromQueryParams.testVariantId;
239
- }
240
- if (testFromQueryParams.testVariantHandle) {
241
- headers["X-Pack-Test-Variant-Handle"] =
242
- testFromQueryParams.testVariantHandle;
243
- }
244
- }
245
- else if (testInfoForRequest) {
246
- headers = {
247
- "X-Pack-Test-Id": testInfoForRequest?.id,
248
- "X-Pack-Test-Variant-Id": testInfoForRequest?.testVariant?.id,
249
- };
250
- }
251
- return headers;
252
- }