@pack/hydrogen 3.1.1 → 3.2.1
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 +54 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +66 -18
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1 +1,54 @@
|
|
|
1
|
-
# hydrogen
|
|
1
|
+
# `@pack/hydrogen`
|
|
2
|
+
|
|
3
|
+
Hydrogen runtime integration for Pack content, preview, A/B testing, and server-side error tracking.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @pack/hydrogen
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Main exports
|
|
12
|
+
|
|
13
|
+
- `createPackClient`
|
|
14
|
+
- `handleRequest`
|
|
15
|
+
- `PackSession`, `PackTestSession`
|
|
16
|
+
- `previewModeAction`, `previewModeLoader`
|
|
17
|
+
- A/B test helpers (`PackTestProvider`, `useAbTest`, etc.)
|
|
18
|
+
|
|
19
|
+
## Minimal setup
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import {
|
|
23
|
+
createPackClient,
|
|
24
|
+
handleRequest,
|
|
25
|
+
} from '@pack/hydrogen';
|
|
26
|
+
import { createServerErrorHandler } from '@pack/errors';
|
|
27
|
+
|
|
28
|
+
// Optional if you want route-level error capture in addition to handleRequest wrapping.
|
|
29
|
+
// Duplicate reports for the same Error instance are deduplicated automatically.
|
|
30
|
+
export const handleError = createServerErrorHandler();
|
|
31
|
+
|
|
32
|
+
export default async function fetch(request: Request, env: Env, ctx: ExecutionContext) {
|
|
33
|
+
const pack = createPackClient({
|
|
34
|
+
cache: caches.default,
|
|
35
|
+
waitUntil: ctx.waitUntil.bind(ctx),
|
|
36
|
+
storeId: env.PACK_STORE_ID,
|
|
37
|
+
token: env.PACK_API_TOKEN,
|
|
38
|
+
errorTracking: {
|
|
39
|
+
dsn: env.PUBLIC_PACK_ERROR_TRACKING_DSN,
|
|
40
|
+
},
|
|
41
|
+
session,
|
|
42
|
+
testSession,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return handleRequest(pack, request, (req) => storefrontHandler(req));
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Development
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
yarn
|
|
53
|
+
yarn build
|
|
54
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PackClient } from '@pack/client';
|
|
2
|
+
import { ErrorTrackingOptions } from '@pack/errors';
|
|
2
3
|
import { CacheCustom } from '@shopify/hydrogen';
|
|
3
4
|
import { SessionStorage, Session, ActionFunctionArgs, LoaderFunctionArgs } from 'react-router';
|
|
4
5
|
import * as react from 'react';
|
|
@@ -85,6 +86,8 @@ interface CreatePackClientOptions extends EnvironmentOptions {
|
|
|
85
86
|
i18n?: I18nOptions;
|
|
86
87
|
/** Default theme data to use when no token is provided */
|
|
87
88
|
defaultThemeData?: DefaultThemeData;
|
|
89
|
+
/** Configuration for server-side error tracking */
|
|
90
|
+
errorTracking?: ErrorTrackingOptions;
|
|
88
91
|
/**
|
|
89
92
|
* Initial request to extract query parameters from.
|
|
90
93
|
* If not provided, it will be captured from the first handleRequest call.
|
|
@@ -142,12 +145,14 @@ interface Pack {
|
|
|
142
145
|
packAbTest: Test$1 | null | undefined;
|
|
143
146
|
packIsPreviewMode: boolean;
|
|
144
147
|
packCustomizerMeta: PackCustomizerMeta | null;
|
|
148
|
+
packErrorTracking?: ErrorTrackingOptions;
|
|
145
149
|
};
|
|
146
150
|
handleRequest(request: Request): Promise<(response: Response) => void>;
|
|
147
151
|
isPreviewModeEnabled: () => boolean;
|
|
148
152
|
isValidEditToken: PackClient["isValidEditToken"];
|
|
149
153
|
query: <T = any>(query: string, options: QueryOptions) => Promise<QueryResponse<T>>;
|
|
150
154
|
session: PackSession;
|
|
155
|
+
errorTracking?: ErrorTrackingOptions;
|
|
151
156
|
testSession: PackTestSession;
|
|
152
157
|
}
|
|
153
158
|
interface DefaultThemeData {
|
package/dist/index.js
CHANGED
|
@@ -4356,6 +4356,9 @@ var require_dist = __commonJS({
|
|
|
4356
4356
|
}
|
|
4357
4357
|
});
|
|
4358
4358
|
|
|
4359
|
+
// src/handle-request.ts
|
|
4360
|
+
import { sendServerErrorEvent } from "@pack/errors";
|
|
4361
|
+
|
|
4359
4362
|
// ../packlytics/dist/utils/get-packlytics-id.js
|
|
4360
4363
|
function sha256(ascii) {
|
|
4361
4364
|
function rightRotate(value, amount) {
|
|
@@ -4668,11 +4671,28 @@ async function packlytics(pack, request, next) {
|
|
|
4668
4671
|
}
|
|
4669
4672
|
|
|
4670
4673
|
// src/handle-request.ts
|
|
4674
|
+
function getServerStatusError(request, status) {
|
|
4675
|
+
let pathname = request.url;
|
|
4676
|
+
try {
|
|
4677
|
+
pathname = new URL(request.url).pathname;
|
|
4678
|
+
} catch {
|
|
4679
|
+
}
|
|
4680
|
+
return new Error(`HTTP ${status} response for ${request.method} ${pathname}`);
|
|
4681
|
+
}
|
|
4671
4682
|
async function handleRequest(pack, request, handleRequest2) {
|
|
4672
4683
|
const packHandleResponse = await pack.handleRequest(request);
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4684
|
+
let response;
|
|
4685
|
+
try {
|
|
4686
|
+
response = await packlytics(pack, request, () => {
|
|
4687
|
+
return handleRequest2(request);
|
|
4688
|
+
});
|
|
4689
|
+
} catch (error) {
|
|
4690
|
+
sendServerErrorEvent(error, request, pack);
|
|
4691
|
+
throw error;
|
|
4692
|
+
}
|
|
4693
|
+
if (response.status >= 500 && !request.signal.aborted) {
|
|
4694
|
+
sendServerErrorEvent(getServerStatusError(request, response.status), request, pack);
|
|
4695
|
+
}
|
|
4676
4696
|
packHandleResponse(response);
|
|
4677
4697
|
response.headers.append("powered-by", "Shopify, Hydrogen + Pack Digital");
|
|
4678
4698
|
response.headers.append("Set-Cookie", await pack.session.commit());
|
|
@@ -5026,11 +5046,26 @@ var cookie2 = __toESM(require_cookie(), 1);
|
|
|
5026
5046
|
// src/tests/local-test-resolver.ts
|
|
5027
5047
|
var import_json_rules_engine = __toESM(require_dist(), 1);
|
|
5028
5048
|
var import_debug2 = __toESM(require_browser(), 1);
|
|
5029
|
-
|
|
5030
|
-
|
|
5049
|
+
|
|
5050
|
+
// src/tests/impression.ts
|
|
5051
|
+
function getVariantImpressionSectionIds(testVariant) {
|
|
5031
5052
|
const sectionIds = testVariant?.sectionTestVariants?.map((variant) => variant?.section?.id).filter((id) => Boolean(id)) || [];
|
|
5032
5053
|
return [...new Set(sectionIds)];
|
|
5033
5054
|
}
|
|
5055
|
+
function getImpressionSectionIdsForVariant(test, testVariant) {
|
|
5056
|
+
const selectedVariantSectionIds = getVariantImpressionSectionIds(testVariant);
|
|
5057
|
+
if (selectedVariantSectionIds.length > 0) {
|
|
5058
|
+
return selectedVariantSectionIds;
|
|
5059
|
+
}
|
|
5060
|
+
if (testVariant?.handle !== "control") {
|
|
5061
|
+
return [];
|
|
5062
|
+
}
|
|
5063
|
+
const fallbackSectionIds = test?.testVariants?.filter((variant) => variant.handle !== "control").flatMap((variant) => getVariantImpressionSectionIds(variant)) || [];
|
|
5064
|
+
return [...new Set(fallbackSectionIds)];
|
|
5065
|
+
}
|
|
5066
|
+
|
|
5067
|
+
// src/tests/local-test-resolver.ts
|
|
5068
|
+
var debug2 = (0, import_debug2.default)("pack:ab-testing:local-resolver");
|
|
5034
5069
|
var LocalTestResolver = class {
|
|
5035
5070
|
testRules = [];
|
|
5036
5071
|
constructor() {
|
|
@@ -5134,7 +5169,10 @@ var LocalTestResolver = class {
|
|
|
5134
5169
|
})
|
|
5135
5170
|
);
|
|
5136
5171
|
if (accumulatedPercentage >= randomPercentage) {
|
|
5137
|
-
const impressionSectionIds =
|
|
5172
|
+
const impressionSectionIds = getImpressionSectionIdsForVariant(
|
|
5173
|
+
selectedTest,
|
|
5174
|
+
variant
|
|
5175
|
+
);
|
|
5138
5176
|
const result = {
|
|
5139
5177
|
id: selectedTest.id,
|
|
5140
5178
|
handle: selectedTest.handle,
|
|
@@ -5346,10 +5384,6 @@ var QUERY_TESTS_BY_RULES = `#graphql
|
|
|
5346
5384
|
}
|
|
5347
5385
|
}
|
|
5348
5386
|
`;
|
|
5349
|
-
function getImpressionSectionIds2(testVariant) {
|
|
5350
|
-
const sectionIds = testVariant?.sectionTestVariants?.map((variant) => variant?.section?.id).filter((id) => Boolean(id)) || [];
|
|
5351
|
-
return [...new Set(sectionIds)];
|
|
5352
|
-
}
|
|
5353
5387
|
var localTestResolver = new LocalTestResolver();
|
|
5354
5388
|
function generateTestRulesCacheKey(storeId, contentEnvironment) {
|
|
5355
5389
|
return `pack-tests:${storeId}:${contentEnvironment || "default"}`;
|
|
@@ -5563,7 +5597,10 @@ async function packClientFetchTestByRules(packClient, testTargetAudienceAttribut
|
|
|
5563
5597
|
(v) => v.id === currentTestData.testVariant.id
|
|
5564
5598
|
);
|
|
5565
5599
|
if (currentVariant) {
|
|
5566
|
-
const impressionSectionIds =
|
|
5600
|
+
const impressionSectionIds = getImpressionSectionIdsForVariant(
|
|
5601
|
+
freshTestData,
|
|
5602
|
+
currentVariant
|
|
5603
|
+
);
|
|
5567
5604
|
const refreshedTest = {
|
|
5568
5605
|
id: freshTestData.id,
|
|
5569
5606
|
handle: freshTestData.handle,
|
|
@@ -5575,7 +5612,10 @@ async function packClientFetchTestByRules(packClient, testTargetAudienceAttribut
|
|
|
5575
5612
|
impression: impressionSectionIds.length > 0 ? { sectionIds: impressionSectionIds } : void 0,
|
|
5576
5613
|
isFirstExposure: void 0
|
|
5577
5614
|
};
|
|
5578
|
-
const {
|
|
5615
|
+
const {
|
|
5616
|
+
isFirstExposure: _isFirstExposure2,
|
|
5617
|
+
...testDataWithoutFlag2
|
|
5618
|
+
} = refreshedTest;
|
|
5579
5619
|
testSession.setTestData(testDataWithoutFlag2);
|
|
5580
5620
|
testSession.setExpireAt(getExpireAtDate().toISOString());
|
|
5581
5621
|
return refreshedTest;
|
|
@@ -5620,7 +5660,10 @@ async function packClientFetchTestByRules(packClient, testTargetAudienceAttribut
|
|
|
5620
5660
|
(v) => v.id === exposedTest.testVariant?.id
|
|
5621
5661
|
);
|
|
5622
5662
|
if (exposedVariant) {
|
|
5623
|
-
const impressionSectionIds =
|
|
5663
|
+
const impressionSectionIds = getImpressionSectionIdsForVariant(
|
|
5664
|
+
freshTestData,
|
|
5665
|
+
exposedVariant
|
|
5666
|
+
);
|
|
5624
5667
|
const result2 = {
|
|
5625
5668
|
id: freshTestData.id,
|
|
5626
5669
|
handle: freshTestData.handle,
|
|
@@ -5632,7 +5675,7 @@ async function packClientFetchTestByRules(packClient, testTargetAudienceAttribut
|
|
|
5632
5675
|
impression: impressionSectionIds.length > 0 ? { sectionIds: impressionSectionIds } : void 0,
|
|
5633
5676
|
isFirstExposure: void 0
|
|
5634
5677
|
};
|
|
5635
|
-
const { isFirstExposure:
|
|
5678
|
+
const { isFirstExposure: _isFirstExposure2, ...testDataWithoutFlag2 } = result2;
|
|
5636
5679
|
testSession.setTestData(testDataWithoutFlag2);
|
|
5637
5680
|
testSession.setExpireAt(getExpireAtDate().toISOString());
|
|
5638
5681
|
return result2;
|
|
@@ -5687,7 +5730,7 @@ async function packClientFetchTestByRules(packClient, testTargetAudienceAttribut
|
|
|
5687
5730
|
variantHandle: result.testVariant.handle
|
|
5688
5731
|
})
|
|
5689
5732
|
);
|
|
5690
|
-
const { isFirstExposure, ...testDataWithoutFlag } = result;
|
|
5733
|
+
const { isFirstExposure: _isFirstExposure, ...testDataWithoutFlag } = result;
|
|
5691
5734
|
testSession.setTestData(testDataWithoutFlag);
|
|
5692
5735
|
testSession.setExpireAt(getExpireAtDate().toISOString());
|
|
5693
5736
|
debug3("[Pack Test] Returning test info with first exposure flag");
|
|
@@ -6160,6 +6203,7 @@ function createPackClient(options) {
|
|
|
6160
6203
|
token,
|
|
6161
6204
|
apiUrl,
|
|
6162
6205
|
defaultThemeData,
|
|
6206
|
+
errorTracking,
|
|
6163
6207
|
i18n,
|
|
6164
6208
|
request
|
|
6165
6209
|
} = options;
|
|
@@ -6234,7 +6278,8 @@ function createPackClient(options) {
|
|
|
6234
6278
|
previewEnabled
|
|
6235
6279
|
),
|
|
6236
6280
|
packIsPreviewMode: previewEnabled,
|
|
6237
|
-
packCustomizerMeta: session.get("customizerMeta")
|
|
6281
|
+
packCustomizerMeta: session.get("customizerMeta"),
|
|
6282
|
+
packErrorTracking: errorTracking
|
|
6238
6283
|
};
|
|
6239
6284
|
},
|
|
6240
6285
|
isPreviewModeEnabled: () => previewEnabled,
|
|
@@ -6249,6 +6294,7 @@ function createPackClient(options) {
|
|
|
6249
6294
|
return { data, error: null };
|
|
6250
6295
|
},
|
|
6251
6296
|
session,
|
|
6297
|
+
errorTracking,
|
|
6252
6298
|
testSession
|
|
6253
6299
|
};
|
|
6254
6300
|
}
|
|
@@ -6298,7 +6344,8 @@ function createPackClient(options) {
|
|
|
6298
6344
|
previewEnabled
|
|
6299
6345
|
),
|
|
6300
6346
|
packIsPreviewMode: previewEnabled,
|
|
6301
|
-
packCustomizerMeta: session.get("customizerMeta")
|
|
6347
|
+
packCustomizerMeta: session.get("customizerMeta"),
|
|
6348
|
+
packErrorTracking: errorTracking
|
|
6302
6349
|
};
|
|
6303
6350
|
},
|
|
6304
6351
|
handleRequest: handleRequest2,
|
|
@@ -6363,7 +6410,7 @@ function createPackClient(options) {
|
|
|
6363
6410
|
}
|
|
6364
6411
|
}
|
|
6365
6412
|
if (testInfoForRequest?.isFirstExposure) {
|
|
6366
|
-
const { isFirstExposure, ...testInfo } = testInfoForRequest;
|
|
6413
|
+
const { isFirstExposure: _isFirstExposure, ...testInfo } = testInfoForRequest;
|
|
6367
6414
|
testInfoForLoader = testInfo;
|
|
6368
6415
|
}
|
|
6369
6416
|
headers = setTestHeaders(headers, {
|
|
@@ -6425,6 +6472,7 @@ function createPackClient(options) {
|
|
|
6425
6472
|
}
|
|
6426
6473
|
},
|
|
6427
6474
|
session,
|
|
6475
|
+
errorTracking,
|
|
6428
6476
|
testSession
|
|
6429
6477
|
};
|
|
6430
6478
|
}
|