@pack/hydrogen 1.0.5 → 1.0.6-ab-test.2
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/dist/create-pack-client.d.ts +29 -5
- package/dist/create-pack-client.d.ts.map +1 -1
- package/dist/create-pack-client.js +103 -30
- package/dist/handle-request.d.ts.map +1 -1
- package/dist/handle-request.js +2 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/preview/preview-mode.d.ts.map +1 -1
- package/dist/preview/preview-mode.js +3 -1
- package/dist/session/cookies-utils.js +1 -1
- package/dist/tests/test.d.ts +2 -1
- package/dist/tests/test.d.ts.map +1 -1
- package/dist/tests/test.js +88 -85
- package/package.json +6 -3
|
@@ -2,6 +2,7 @@
|
|
|
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";
|
|
5
6
|
/** @see https://shopify.dev/docs/custom-storefronts/hydrogen/data-fetching/cache#caching-strategies */
|
|
6
7
|
type CachingStrategy = ReturnType<typeof CacheCustom>;
|
|
7
8
|
interface EnvironmentOptions {
|
|
@@ -16,7 +17,7 @@ interface EnvironmentOptions {
|
|
|
16
17
|
*/
|
|
17
18
|
waitUntil: ExecutionContext["waitUntil"];
|
|
18
19
|
}
|
|
19
|
-
interface CreatePackClientOptions extends EnvironmentOptions {
|
|
20
|
+
export interface CreatePackClientOptions extends EnvironmentOptions {
|
|
20
21
|
apiUrl?: string;
|
|
21
22
|
token?: string;
|
|
22
23
|
storeId?: string;
|
|
@@ -29,6 +30,7 @@ type Variables = Record<string, any>;
|
|
|
29
30
|
interface QueryOptions {
|
|
30
31
|
variables?: Variables;
|
|
31
32
|
cache?: CachingStrategy;
|
|
33
|
+
test?: TestInput;
|
|
32
34
|
}
|
|
33
35
|
interface QueryError {
|
|
34
36
|
message: string;
|
|
@@ -39,18 +41,40 @@ interface QueryError {
|
|
|
39
41
|
interface QueryResponse<T> {
|
|
40
42
|
data: T | null;
|
|
41
43
|
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;
|
|
42
53
|
}
|
|
43
54
|
export interface Pack {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
abTest: Test | null | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* @deprecated The method should not be used
|
|
58
|
+
*/
|
|
48
59
|
getPackSessionData(): {
|
|
49
60
|
storeId: string;
|
|
50
61
|
sessionId: string;
|
|
62
|
+
abTest: Test | null | undefined;
|
|
51
63
|
isPreviewModeEnabled: boolean;
|
|
52
64
|
customizerMeta: any;
|
|
53
65
|
};
|
|
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;
|
|
54
78
|
}
|
|
55
79
|
interface DefaultThemeData {
|
|
56
80
|
data: Record<string, any>;
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
1
|
+
{"version":3,"file":"create-pack-client.d.ts","sourceRoot":"","sources":["../src/create-pack-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
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";
|
|
3
5
|
/**
|
|
4
6
|
* Create an SHA-256 hash as a hex string
|
|
5
7
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string
|
|
@@ -113,16 +115,71 @@ export function createPackClient(options) {
|
|
|
113
115
|
const previewEnabled = !!session.get("previewEnabled");
|
|
114
116
|
const previewEnvironment = session.get("environment");
|
|
115
117
|
const clientContentEnvironment = previewEnvironment || contentEnvironment;
|
|
118
|
+
let packClient;
|
|
119
|
+
let testFromQueryParams = null;
|
|
120
|
+
let testInfoForRequest = undefined;
|
|
116
121
|
if (!token && !defaultThemeData) {
|
|
117
122
|
throw new Error("The Pack client token is missing or empty. Please provide a valid token or default theme data.");
|
|
118
123
|
}
|
|
119
124
|
if (!storeId) {
|
|
120
125
|
throw new Error("The Pack Store ID is missing or empty. Please provide a valid Store ID.");
|
|
121
126
|
}
|
|
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
|
+
};
|
|
122
159
|
if (!token) {
|
|
123
160
|
return {
|
|
124
|
-
session,
|
|
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
|
+
},
|
|
125
181
|
isPreviewModeEnabled: () => previewEnabled,
|
|
182
|
+
isValidEditToken: () => new Promise(() => false),
|
|
126
183
|
async query(query, { variables } = {}) {
|
|
127
184
|
if (!defaultThemeData?.data) {
|
|
128
185
|
console.warn("Invalid default theme data provided to Pack client.");
|
|
@@ -131,18 +188,10 @@ export function createPackClient(options) {
|
|
|
131
188
|
const data = resolveQuery({ query, variables, defaultThemeData });
|
|
132
189
|
return { data: data, error: null };
|
|
133
190
|
},
|
|
134
|
-
|
|
135
|
-
getPackSessionData: () => {
|
|
136
|
-
return {
|
|
137
|
-
storeId: storeId,
|
|
138
|
-
sessionId: session.id,
|
|
139
|
-
isPreviewModeEnabled: previewEnabled,
|
|
140
|
-
customizerMeta: session.get("customizerMeta"),
|
|
141
|
-
};
|
|
142
|
-
},
|
|
191
|
+
session,
|
|
143
192
|
};
|
|
144
193
|
}
|
|
145
|
-
|
|
194
|
+
packClient = new PackClient({
|
|
146
195
|
// Use apiUrl, it is configured
|
|
147
196
|
// Use active API URL if preview mode is enabled
|
|
148
197
|
// Otherwise, Live PackClient uses its internal configuration
|
|
@@ -158,14 +207,39 @@ export function createPackClient(options) {
|
|
|
158
207
|
clientName: "HydrogenClient",
|
|
159
208
|
});
|
|
160
209
|
return {
|
|
161
|
-
session,
|
|
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,
|
|
162
230
|
isPreviewModeEnabled: () => previewEnabled,
|
|
163
|
-
|
|
231
|
+
isValidEditToken: (token) => packClient.isValidEditToken(token),
|
|
232
|
+
async query(query, { variables, cache: strategy = cacheCustom, test } = {}) {
|
|
233
|
+
let headers = {};
|
|
164
234
|
const withCache = createWithCache({
|
|
165
235
|
cache,
|
|
166
236
|
waitUntil,
|
|
167
237
|
});
|
|
168
|
-
|
|
238
|
+
headers = setTestHeaders(headers, {
|
|
239
|
+
previewEnabled,
|
|
240
|
+
testInfoForRequest,
|
|
241
|
+
testFromQueryParams: testFromQueryParams || test,
|
|
242
|
+
});
|
|
169
243
|
const queryVariables = variables ? { ...variables } : {};
|
|
170
244
|
if (previewEnabled) {
|
|
171
245
|
queryVariables.version = "CURRENT";
|
|
@@ -173,23 +247,27 @@ export function createPackClient(options) {
|
|
|
173
247
|
else {
|
|
174
248
|
queryVariables.version = "PUBLISHED";
|
|
175
249
|
}
|
|
250
|
+
const testInfoForLoader = getTestInfoForLoader();
|
|
176
251
|
// Preview mode always bypasses the cache
|
|
177
252
|
if (previewEnabled) {
|
|
178
253
|
try {
|
|
179
|
-
return
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
254
|
+
return {
|
|
255
|
+
...(await packClient.fetch(query, {
|
|
256
|
+
variables: queryVariables,
|
|
257
|
+
headers: headers,
|
|
258
|
+
})),
|
|
259
|
+
packTestInfo: testInfoForLoader,
|
|
260
|
+
};
|
|
183
261
|
}
|
|
184
262
|
catch (error) {
|
|
185
|
-
return { error, data:
|
|
263
|
+
return { error: error, data: null };
|
|
186
264
|
}
|
|
187
265
|
}
|
|
188
266
|
const queryHash = await getCacheKey(withCache, query, token, {
|
|
189
267
|
variables: queryVariables,
|
|
190
268
|
headers,
|
|
191
269
|
});
|
|
192
|
-
|
|
270
|
+
const response = await withCache(queryHash, strategy, async () => {
|
|
193
271
|
try {
|
|
194
272
|
return await packClient.fetch(query, {
|
|
195
273
|
variables: queryVariables,
|
|
@@ -197,18 +275,13 @@ export function createPackClient(options) {
|
|
|
197
275
|
});
|
|
198
276
|
}
|
|
199
277
|
catch (error) {
|
|
200
|
-
return { error, data:
|
|
278
|
+
return { error, data: null };
|
|
201
279
|
}
|
|
202
280
|
});
|
|
281
|
+
return response.error
|
|
282
|
+
? response
|
|
283
|
+
: { ...response, packTestInfo: testInfoForLoader };
|
|
203
284
|
},
|
|
204
|
-
|
|
205
|
-
getPackSessionData: () => {
|
|
206
|
-
return {
|
|
207
|
-
storeId: storeId,
|
|
208
|
-
sessionId: session.id,
|
|
209
|
-
isPreviewModeEnabled: previewEnabled,
|
|
210
|
-
customizerMeta: session.get("customizerMeta"),
|
|
211
|
-
};
|
|
212
|
-
},
|
|
285
|
+
session,
|
|
213
286
|
};
|
|
214
287
|
}
|
|
@@ -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,
|
|
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"}
|
package/dist/handle-request.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { packlytics } from "@pack/packlytics";
|
|
2
2
|
export async function handleRequest(pack, request, handleRequest) {
|
|
3
|
+
const packHandleResponse = await pack.handleRequest(request);
|
|
3
4
|
const response = await packlytics(pack, request, () => {
|
|
4
5
|
return handleRequest(request);
|
|
5
6
|
});
|
|
7
|
+
packHandleResponse(response);
|
|
6
8
|
response.headers.append("powered-by", "Shopify, Hydrogen + Pack Digital");
|
|
7
9
|
response.headers.append("Set-Cookie", await pack.session.commit());
|
|
8
10
|
return response;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { handleRequest } from "./handle-request";
|
|
2
2
|
import { usePackCookies } from "./session/usePackCookies";
|
|
3
3
|
import { PackSession } from "./session/session";
|
|
4
|
-
import { createPackClient } from "./create-pack-client";
|
|
4
|
+
import { Pack, createPackClient } from "./create-pack-client";
|
|
5
5
|
import { action as previewModeAction, loader as previewModeLoader } from "./preview/preview-mode";
|
|
6
|
-
|
|
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, };
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,gBAAgB,EAAE,MAAM,sBAAsB,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,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"}
|
package/dist/index.js
CHANGED
|
@@ -3,4 +3,5 @@ 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
|
-
|
|
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, };
|
|
@@ -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;
|
|
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,cAkBpB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,cA0CpB,CAAC"}
|
|
@@ -88,7 +88,9 @@ export const loader = async function ({ request, context }) {
|
|
|
88
88
|
}
|
|
89
89
|
let customizerMetaJson;
|
|
90
90
|
try {
|
|
91
|
-
customizerMetaJson = customizerMeta
|
|
91
|
+
customizerMetaJson = customizerMeta
|
|
92
|
+
? JSON.parse(customizerMeta)
|
|
93
|
+
: null;
|
|
92
94
|
}
|
|
93
95
|
catch (_error) {
|
|
94
96
|
customizerMetaJson = null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PACK_USER_CONSENT_COOKIE_ID } from "../constants";
|
|
2
|
-
|
|
2
|
+
import cookie from "cookie";
|
|
3
3
|
const tokenHash = "xxxx-4xxx-xxxx-xxxxxxxxxxxx";
|
|
4
4
|
export function hasUserConsent(request) {
|
|
5
5
|
const cookies = cookie.parse(request.headers.get("Cookie"));
|
package/dist/tests/test.d.ts
CHANGED
|
@@ -29,11 +29,12 @@ export interface GetTestInfoOptions {
|
|
|
29
29
|
testTargetAudienceAttributes: TestTargetAudienceAttributes | null;
|
|
30
30
|
packClient: PackClient;
|
|
31
31
|
session: PackSession | undefined;
|
|
32
|
+
token: string;
|
|
32
33
|
}
|
|
33
34
|
export interface TestInfo extends Test {
|
|
34
35
|
isFirstExposure?: boolean;
|
|
35
36
|
}
|
|
36
|
-
export declare function getTestInfo({ request, testTargetAudienceAttributes, packClient, session, }: GetTestInfoOptions): Promise<TestInfo | undefined>;
|
|
37
|
+
export declare function getTestInfo({ request, testTargetAudienceAttributes, packClient, session, token, }: GetTestInfoOptions): Promise<TestInfo | undefined>;
|
|
37
38
|
export declare function getTestSession(session: PackSession | undefined, testFromQueryParams: TestInput | null, previewEnabled: boolean): Test | null | undefined;
|
|
38
39
|
export declare function getTestTargetingAttributesFromRequest(request: Request): TestTargetAudienceAttributes;
|
|
39
40
|
export declare function getTestFromQueryParams(request: Request): TestInput | null;
|
package/dist/tests/test.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;AAqBD,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;
|
|
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;AAqBD,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;AAmFD,wBAAsB,WAAW,CAAC,EAChC,OAAO,EACP,4BAA4B,EAC5B,UAAU,EACV,OAAO,EACP,KAAK,GACN,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CA6DpD;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"}
|
package/dist/tests/test.js
CHANGED
|
@@ -16,99 +16,102 @@ const QUERY_TEST_VARIANT_IS_RUNNING = `#graphql
|
|
|
16
16
|
testVariantIsRunning(handle: $handle, testId: $testId)
|
|
17
17
|
}
|
|
18
18
|
`;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
async function packClientFetchTestByRules(packClient, testTargetAudienceAttributes, token) {
|
|
20
|
+
if (!packClient.storeId) {
|
|
21
|
+
console.error("Pack error: Store ID is required to fetch a test.");
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
let resp = undefined;
|
|
25
|
+
const URL = "https://tests-service-production.packdigital.workers.dev/tests/assign";
|
|
26
|
+
const assignByRulesResp = await fetch(URL, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: {
|
|
29
|
+
Authorization: `Bearer ${token}`,
|
|
30
|
+
"X-Pack-Storefront-Id": packClient.storeId,
|
|
31
|
+
...(packClient.contentEnvironment
|
|
32
|
+
? { "X-Environment": packClient.contentEnvironment }
|
|
33
|
+
: {}),
|
|
34
|
+
"Content-Type": "application/json",
|
|
35
|
+
},
|
|
36
|
+
body: JSON.stringify({
|
|
37
|
+
attributes: testTargetAudienceAttributes,
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
const { status } = assignByRulesResp;
|
|
41
|
+
if (status !== 200) {
|
|
42
|
+
let message;
|
|
43
|
+
if (status === 401) {
|
|
44
|
+
message =
|
|
45
|
+
"Pack error: Unauthorized request to test assignment service. Please check your token.";
|
|
27
46
|
}
|
|
28
|
-
|
|
47
|
+
else {
|
|
48
|
+
message = `Pack error: Request to test assignment service failed with status ${status}`;
|
|
49
|
+
}
|
|
50
|
+
console.error(message);
|
|
51
|
+
return resp;
|
|
52
|
+
}
|
|
53
|
+
const assignByRulesRespJson = await assignByRulesResp.json();
|
|
54
|
+
if (assignByRulesRespJson?.data) {
|
|
55
|
+
resp = {
|
|
56
|
+
...assignByRulesRespJson.data,
|
|
57
|
+
isFirstExposure: true,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return resp;
|
|
61
|
+
}
|
|
62
|
+
async function packClientCheckTestIsRunning(packClient, testSession) {
|
|
63
|
+
try {
|
|
64
|
+
const resp = await packClient.fetch(QUERY_TEST_VARIANT_IS_RUNNING, {
|
|
29
65
|
variables: {
|
|
30
|
-
|
|
66
|
+
handle: testSession.testVariant.handle,
|
|
67
|
+
testId: testSession.id,
|
|
31
68
|
},
|
|
32
69
|
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
return !!resp.data.testVariantIsRunning;
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
console.error(e);
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
export async function getTestInfo({ request, testTargetAudienceAttributes, packClient, session, token, }) {
|
|
78
|
+
let testInfo = undefined;
|
|
79
|
+
let exposedTest = undefined;
|
|
80
|
+
if (!session) {
|
|
81
|
+
return testInfo;
|
|
82
|
+
}
|
|
83
|
+
const testSession = session.get("test");
|
|
84
|
+
const exposedTestCookieString = cookie.parse(request.headers.get("cookie") || "")?.exposedTest;
|
|
85
|
+
if (exposedTestCookieString) {
|
|
86
|
+
exposedTest = JSON.parse(exposedTestCookieString);
|
|
87
|
+
}
|
|
88
|
+
// If there is test on session, check if the test on session is still running.
|
|
89
|
+
if (testSession && testSession.data?.id && testSession.data?.testVariant) {
|
|
90
|
+
const testVariantIsRunning = await packClientCheckTestIsRunning(packClient, testSession.data);
|
|
91
|
+
// If true, set testInfo to the testSession assigned test.
|
|
92
|
+
if (testVariantIsRunning) {
|
|
93
|
+
testInfo = testSession.data;
|
|
51
94
|
}
|
|
95
|
+
}
|
|
96
|
+
else if (exposedTest) {
|
|
52
97
|
// If there is no assigned test on the session and an exposed test in the
|
|
53
|
-
// incoming request cookie it means that the user was exposed to a test
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
handle: exposedTest.testVariant.handle,
|
|
60
|
-
testId: exposedTest.id,
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
// If the test is still running, set testInfo to the exposed test
|
|
64
|
-
if (!!resp.data.testVariantIsRunning) {
|
|
65
|
-
const { id, handle, testVariant } = exposedTest;
|
|
66
|
-
testInfo = {
|
|
67
|
-
id,
|
|
68
|
-
handle,
|
|
69
|
-
testVariant,
|
|
70
|
-
};
|
|
71
|
-
session.set("test", {
|
|
72
|
-
data: testInfo,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
// If the test is not running anymore, fetch a new test for the user
|
|
77
|
-
await fetchTestByRulesSetTestInfoAsFirstExposure();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
if (!testSession ||
|
|
82
|
-
!(testSession.data?.id && testSession.data?.testVariant)) {
|
|
83
|
-
// If there is no assigned test on the session, check if there is a test
|
|
84
|
-
// for attributes, then assign to session and return value.
|
|
85
|
-
await fetchTestByRulesSetTestInfoAsFirstExposure();
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
// If there is test on session, check if the test on session is still running.
|
|
89
|
-
const packClientFetchTestVariantIsRunning = packClient.fetch(QUERY_TEST_VARIANT_IS_RUNNING, {
|
|
90
|
-
variables: {
|
|
91
|
-
handle: testSession.data.testVariant.handle,
|
|
92
|
-
testId: testSession.data.id,
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
const resp = await packClientFetchTestVariantIsRunning;
|
|
96
|
-
if (!!resp.data.testVariantIsRunning) {
|
|
97
|
-
// If true, set testInfo to the testSession assigned test.
|
|
98
|
-
testInfo = testSession.data;
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
// If not running, clear test session and fetch a new test for the user
|
|
102
|
-
session.set("test", undefined);
|
|
103
|
-
await fetchTestByRulesSetTestInfoAsFirstExposure();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (isUsingCdn) {
|
|
108
|
-
// Return to CDN
|
|
109
|
-
packClient.apiUrl = "https://apicdn.packdigital.com/graphql";
|
|
98
|
+
// incoming request cookie it means that the user was exposed to a test previously.
|
|
99
|
+
// Verify test is still running
|
|
100
|
+
const testVariantIsRunning = await packClientCheckTestIsRunning(packClient, exposedTest);
|
|
101
|
+
// If the test is still running, set testInfo to the exposed test
|
|
102
|
+
if (testVariantIsRunning) {
|
|
103
|
+
testInfo = exposedTest;
|
|
110
104
|
}
|
|
111
105
|
}
|
|
106
|
+
// If the testInfo is not setup that means that is not a valid test
|
|
107
|
+
// on the session or on the cookie, then fetch a new test for the user
|
|
108
|
+
if (!testInfo) {
|
|
109
|
+
testInfo = await packClientFetchTestByRules(packClient, testTargetAudienceAttributes, token);
|
|
110
|
+
}
|
|
111
|
+
// save this test on the session
|
|
112
|
+
session.set("test", {
|
|
113
|
+
data: testInfo,
|
|
114
|
+
});
|
|
112
115
|
return testInfo;
|
|
113
116
|
}
|
|
114
117
|
export function getTestSession(session, testFromQueryParams, previewEnabled) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pack/hydrogen",
|
|
3
3
|
"description": "Pack Hydrogen",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.6-ab-test.2",
|
|
5
5
|
"exports": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"engines": {
|
|
@@ -22,14 +22,17 @@
|
|
|
22
22
|
"dist"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@pack/client": "^1.0.1",
|
|
25
|
+
"@pack/client": "^1.0.1-ab-test.0",
|
|
26
26
|
"@pack/packlytics": "^1.0.1",
|
|
27
|
-
"@shopify/hydrogen": "^2023.10.2"
|
|
27
|
+
"@shopify/hydrogen": "^2023.10.2",
|
|
28
|
+
"cookie": "^0.6.0",
|
|
29
|
+
"js-cookie": "^3.0.5"
|
|
28
30
|
},
|
|
29
31
|
"devDependencies": {
|
|
30
32
|
"@remix-run/server-runtime": "^2.0.0",
|
|
31
33
|
"@shopify/oxygen-workers-types": "^4.0.0",
|
|
32
34
|
"@shopify/remix-oxygen": "^2.0.1",
|
|
35
|
+
"@types/js-cookie": "^3.0.6",
|
|
33
36
|
"@types/node": "^20.11.17"
|
|
34
37
|
},
|
|
35
38
|
"peerDependencies": {
|