@uniformdev/next-app-router 20.81.1-alpha.12.sha-5d72d595dc → 20.81.1-alpha.15.sha-2b5fd446ca
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/{createCachedManifestProvider-DUuhXeA4.d.ts → createCachedManifestProvider-DrlaCKdm.d.ts} +24 -12
- package/dist/{createCachedManifestProvider-Bpv56Ou-.d.mts → createCachedManifestProvider-VL1HGJ-J.d.mts} +24 -12
- package/dist/edge.d.mts +3 -3
- package/dist/edge.d.ts +3 -3
- package/dist/edge.js +72 -27
- package/dist/edge.mjs +72 -27
- package/dist/index.d.mts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.esm.js +1 -2
- package/dist/index.js +1 -2
- package/dist/index.mjs +1 -2
- package/dist/{models-D8YUMc4L.d.mts → models-DKZtopoy.d.mts} +2 -1
- package/dist/{models-D8YUMc4L.d.ts → models-DKZtopoy.d.ts} +2 -1
- package/dist/vercel.d.mts +4 -3
- package/dist/vercel.d.ts +4 -3
- package/dist/vercel.js +72 -27
- package/dist/vercel.mjs +72 -27
- package/package.json +11 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ManifestV2 } from '@uniformdev/context';
|
|
2
2
|
import { TransformEdgeStreamOptions } from '@uniformdev/context-edge';
|
|
3
3
|
import { NextRequest, NextFetchEvent } from 'next/server';
|
|
4
|
-
import { f as ManifestProvider, E as EdgeRouteFilter, d as EdgeRouteStore, g as ManifestProviderOptions, e as EdgeRouteStoreCache, M as ManifestCache } from './models-
|
|
4
|
+
import { f as ManifestProvider, E as EdgeRouteFilter, d as EdgeRouteStore, g as ManifestProviderOptions, e as EdgeRouteStoreCache, M as ManifestCache } from './models-DKZtopoy.js';
|
|
5
5
|
import { HandleOptions } from './middleware.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -42,11 +42,19 @@ type UniformEdgeMiddlewareOptions = HandleOptions & {
|
|
|
42
42
|
/**
|
|
43
43
|
* Records what the transform learns about each processed page, such as `vercelEdgeRouteStore`
|
|
44
44
|
* from `@uniformdev/next-app-router/vercel` or one made with `createEdgeRouteStore`. Filters
|
|
45
|
-
* read the record, and processed pages get per-visitor ETags
|
|
45
|
+
* read the record, and processed pages get per-visitor ETags unless `etags` is `false`.
|
|
46
46
|
*
|
|
47
47
|
* @defaultValue nothing is recorded, and responses get no ETag
|
|
48
48
|
*/
|
|
49
49
|
store?: EdgeRouteStore;
|
|
50
|
+
/**
|
|
51
|
+
* Gives processed pages per-visitor ETags, from the page placements the `store` records. `false`
|
|
52
|
+
* sends every processed page in full with `private, no-store`, never hashes the page, and records
|
|
53
|
+
* only whether each page has placements.
|
|
54
|
+
*
|
|
55
|
+
* @defaultValue `true`
|
|
56
|
+
*/
|
|
57
|
+
etags?: boolean;
|
|
50
58
|
};
|
|
51
59
|
/**
|
|
52
60
|
* Returns middleware that rewrites each request to its Uniform code like `uniformMiddleware`, and
|
|
@@ -63,17 +71,20 @@ declare const uniformEdgeMiddleware: (options: UniformEdgeMiddlewareOptions) =>
|
|
|
63
71
|
* Handles one request the way {@link uniformEdgeMiddleware} does. The transformed response is
|
|
64
72
|
* personalized, so it is marked `private, no-store`.
|
|
65
73
|
*
|
|
66
|
-
* When the origin answers 200
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
74
|
+
* When `etags` is on, the origin answers 200 and the `store` recorded the page's placements for
|
|
75
|
+
* its current version, the variants are chosen before the headers are sent. The version is the
|
|
76
|
+
* origin's ETag or, without one, a hash of the untransformed page that the last full response
|
|
77
|
+
* recorded. A page that changed without a new origin ETag is detected when a full response hashes
|
|
78
|
+
* differently, and until then a matching request is answered `304`. The response gets an ETag
|
|
79
|
+
* built from the version and the choices, and `private, no-cache`. A request whose
|
|
80
|
+
* `If-None-Match` matches it gets a `304`. A response that changes the visitor's stored data, such
|
|
81
|
+
* as a score from a signal or a test assignment, carries the visitor state and an ETag that never
|
|
82
|
+
* matches, so the visitor's next request is answered in full.
|
|
72
83
|
*
|
|
73
84
|
* `waitUntil` is handed to the manifest provider, the filter and the store for background work, and
|
|
74
85
|
* defaults to letting the promise run unobserved.
|
|
75
86
|
*/
|
|
76
|
-
declare const handleUniformEdgeRoute: ({ request, manifest, onError, filter, store, waitUntil, ...options }: UniformEdgeMiddlewareOptions & {
|
|
87
|
+
declare const handleUniformEdgeRoute: ({ request, manifest, onError, filter, store, etags, waitUntil, ...options }: UniformEdgeMiddlewareOptions & {
|
|
77
88
|
request: NextRequest;
|
|
78
89
|
waitUntil?: ManifestProviderOptions["waitUntil"];
|
|
79
90
|
}) => Promise<Response>;
|
|
@@ -110,9 +121,10 @@ type CreateEdgeRouteStoreOptions = {
|
|
|
110
121
|
* Creates an edge route store for `uniformEdgeMiddleware`. Records live in memory for `maxAge`,
|
|
111
122
|
* then in the platform's shared `cache`, tagged with the page's `path:` tag.
|
|
112
123
|
*
|
|
113
|
-
* A page's record keeps whether it has placements and, when the
|
|
114
|
-
* placements visitors reached on
|
|
115
|
-
* yet are added as visitors reach them, and a new
|
|
124
|
+
* A page's record keeps whether it has placements and, when the middleware sends ETags, the
|
|
125
|
+
* placements visitors reached on the page's version: its origin ETag or a hash of its content.
|
|
126
|
+
* Placements in variants no visitor was shown yet are added as visitors reach them, and a new
|
|
127
|
+
* version replaces them.
|
|
116
128
|
*
|
|
117
129
|
* Publishing a pattern or entry does not expire the pages that use it. Until the record expires,
|
|
118
130
|
* a page that gained a placement that way is skipped by `learnedEdgeRouteFilter`.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ManifestV2 } from '@uniformdev/context';
|
|
2
2
|
import { TransformEdgeStreamOptions } from '@uniformdev/context-edge';
|
|
3
3
|
import { NextRequest, NextFetchEvent } from 'next/server';
|
|
4
|
-
import { f as ManifestProvider, E as EdgeRouteFilter, d as EdgeRouteStore, g as ManifestProviderOptions, e as EdgeRouteStoreCache, M as ManifestCache } from './models-
|
|
4
|
+
import { f as ManifestProvider, E as EdgeRouteFilter, d as EdgeRouteStore, g as ManifestProviderOptions, e as EdgeRouteStoreCache, M as ManifestCache } from './models-DKZtopoy.mjs';
|
|
5
5
|
import { HandleOptions } from './middleware.mjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -42,11 +42,19 @@ type UniformEdgeMiddlewareOptions = HandleOptions & {
|
|
|
42
42
|
/**
|
|
43
43
|
* Records what the transform learns about each processed page, such as `vercelEdgeRouteStore`
|
|
44
44
|
* from `@uniformdev/next-app-router/vercel` or one made with `createEdgeRouteStore`. Filters
|
|
45
|
-
* read the record, and processed pages get per-visitor ETags
|
|
45
|
+
* read the record, and processed pages get per-visitor ETags unless `etags` is `false`.
|
|
46
46
|
*
|
|
47
47
|
* @defaultValue nothing is recorded, and responses get no ETag
|
|
48
48
|
*/
|
|
49
49
|
store?: EdgeRouteStore;
|
|
50
|
+
/**
|
|
51
|
+
* Gives processed pages per-visitor ETags, from the page placements the `store` records. `false`
|
|
52
|
+
* sends every processed page in full with `private, no-store`, never hashes the page, and records
|
|
53
|
+
* only whether each page has placements.
|
|
54
|
+
*
|
|
55
|
+
* @defaultValue `true`
|
|
56
|
+
*/
|
|
57
|
+
etags?: boolean;
|
|
50
58
|
};
|
|
51
59
|
/**
|
|
52
60
|
* Returns middleware that rewrites each request to its Uniform code like `uniformMiddleware`, and
|
|
@@ -63,17 +71,20 @@ declare const uniformEdgeMiddleware: (options: UniformEdgeMiddlewareOptions) =>
|
|
|
63
71
|
* Handles one request the way {@link uniformEdgeMiddleware} does. The transformed response is
|
|
64
72
|
* personalized, so it is marked `private, no-store`.
|
|
65
73
|
*
|
|
66
|
-
* When the origin answers 200
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
74
|
+
* When `etags` is on, the origin answers 200 and the `store` recorded the page's placements for
|
|
75
|
+
* its current version, the variants are chosen before the headers are sent. The version is the
|
|
76
|
+
* origin's ETag or, without one, a hash of the untransformed page that the last full response
|
|
77
|
+
* recorded. A page that changed without a new origin ETag is detected when a full response hashes
|
|
78
|
+
* differently, and until then a matching request is answered `304`. The response gets an ETag
|
|
79
|
+
* built from the version and the choices, and `private, no-cache`. A request whose
|
|
80
|
+
* `If-None-Match` matches it gets a `304`. A response that changes the visitor's stored data, such
|
|
81
|
+
* as a score from a signal or a test assignment, carries the visitor state and an ETag that never
|
|
82
|
+
* matches, so the visitor's next request is answered in full.
|
|
72
83
|
*
|
|
73
84
|
* `waitUntil` is handed to the manifest provider, the filter and the store for background work, and
|
|
74
85
|
* defaults to letting the promise run unobserved.
|
|
75
86
|
*/
|
|
76
|
-
declare const handleUniformEdgeRoute: ({ request, manifest, onError, filter, store, waitUntil, ...options }: UniformEdgeMiddlewareOptions & {
|
|
87
|
+
declare const handleUniformEdgeRoute: ({ request, manifest, onError, filter, store, etags, waitUntil, ...options }: UniformEdgeMiddlewareOptions & {
|
|
77
88
|
request: NextRequest;
|
|
78
89
|
waitUntil?: ManifestProviderOptions["waitUntil"];
|
|
79
90
|
}) => Promise<Response>;
|
|
@@ -110,9 +121,10 @@ type CreateEdgeRouteStoreOptions = {
|
|
|
110
121
|
* Creates an edge route store for `uniformEdgeMiddleware`. Records live in memory for `maxAge`,
|
|
111
122
|
* then in the platform's shared `cache`, tagged with the page's `path:` tag.
|
|
112
123
|
*
|
|
113
|
-
* A page's record keeps whether it has placements and, when the
|
|
114
|
-
* placements visitors reached on
|
|
115
|
-
* yet are added as visitors reach them, and a new
|
|
124
|
+
* A page's record keeps whether it has placements and, when the middleware sends ETags, the
|
|
125
|
+
* placements visitors reached on the page's version: its origin ETag or a hash of its content.
|
|
126
|
+
* Placements in variants no visitor was shown yet are added as visitors reach them, and a new
|
|
127
|
+
* version replaces them.
|
|
116
128
|
*
|
|
117
129
|
* Publishing a pattern or entry does not expire the pages that use it. Until the record expires,
|
|
118
130
|
* a page that gained a placement that way is skipped by `learnedEdgeRouteFilter`.
|
package/dist/edge.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { C as CreateCachedManifestProviderOptions, a as CreateEdgeRouteStoreOptions, U as UNIFORM_EDGE_ORIGIN_HEADER, b as UniformEdgeMiddlewareOptions, c as createCachedManifestProvider, d as createEdgeRouteStore, h as handleUniformEdgeRoute, u as uniformEdgeMiddleware } from './createCachedManifestProvider-
|
|
2
|
-
import { E as EdgeRouteFilter } from './models-
|
|
3
|
-
export { a as EdgeRouteFilterOptions, b as EdgeRoutePage, c as EdgeRouteRecord, d as EdgeRouteStore, e as EdgeRouteStoreCache, M as ManifestCache, f as ManifestProvider, g as ManifestProviderOptions, R as RecordedPersonalizationOptions, h as RecordedPlacement, i as RecordedTestOptions } from './models-
|
|
1
|
+
export { C as CreateCachedManifestProviderOptions, a as CreateEdgeRouteStoreOptions, U as UNIFORM_EDGE_ORIGIN_HEADER, b as UniformEdgeMiddlewareOptions, c as createCachedManifestProvider, d as createEdgeRouteStore, h as handleUniformEdgeRoute, u as uniformEdgeMiddleware } from './createCachedManifestProvider-VL1HGJ-J.mjs';
|
|
2
|
+
import { E as EdgeRouteFilter } from './models-DKZtopoy.mjs';
|
|
3
|
+
export { a as EdgeRouteFilterOptions, b as EdgeRoutePage, c as EdgeRouteRecord, d as EdgeRouteStore, e as EdgeRouteStoreCache, M as ManifestCache, f as ManifestProvider, g as ManifestProviderOptions, R as RecordedPersonalizationOptions, h as RecordedPlacement, i as RecordedTestOptions } from './models-DKZtopoy.mjs';
|
|
4
4
|
import '@uniformdev/context';
|
|
5
5
|
import '@uniformdev/context-edge';
|
|
6
6
|
import 'next/server';
|
package/dist/edge.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { C as CreateCachedManifestProviderOptions, a as CreateEdgeRouteStoreOptions, U as UNIFORM_EDGE_ORIGIN_HEADER, b as UniformEdgeMiddlewareOptions, c as createCachedManifestProvider, d as createEdgeRouteStore, h as handleUniformEdgeRoute, u as uniformEdgeMiddleware } from './createCachedManifestProvider-
|
|
2
|
-
import { E as EdgeRouteFilter } from './models-
|
|
3
|
-
export { a as EdgeRouteFilterOptions, b as EdgeRoutePage, c as EdgeRouteRecord, d as EdgeRouteStore, e as EdgeRouteStoreCache, M as ManifestCache, f as ManifestProvider, g as ManifestProviderOptions, R as RecordedPersonalizationOptions, h as RecordedPlacement, i as RecordedTestOptions } from './models-
|
|
1
|
+
export { C as CreateCachedManifestProviderOptions, a as CreateEdgeRouteStoreOptions, U as UNIFORM_EDGE_ORIGIN_HEADER, b as UniformEdgeMiddlewareOptions, c as createCachedManifestProvider, d as createEdgeRouteStore, h as handleUniformEdgeRoute, u as uniformEdgeMiddleware } from './createCachedManifestProvider-DrlaCKdm.js';
|
|
2
|
+
import { E as EdgeRouteFilter } from './models-DKZtopoy.js';
|
|
3
|
+
export { a as EdgeRouteFilterOptions, b as EdgeRoutePage, c as EdgeRouteRecord, d as EdgeRouteStore, e as EdgeRouteStoreCache, M as ManifestCache, f as ManifestProvider, g as ManifestProviderOptions, R as RecordedPersonalizationOptions, h as RecordedPlacement, i as RecordedTestOptions } from './models-DKZtopoy.js';
|
|
4
4
|
import '@uniformdev/context';
|
|
5
5
|
import '@uniformdev/context-edge';
|
|
6
6
|
import 'next/server';
|
package/dist/edge.js
CHANGED
|
@@ -700,15 +700,37 @@ var buildPlacementTree = (events) => {
|
|
|
700
700
|
return roots;
|
|
701
701
|
};
|
|
702
702
|
|
|
703
|
+
// src/edge/createContentHasher.ts
|
|
704
|
+
var createContentHasher = () => {
|
|
705
|
+
let h1 = 3735928559;
|
|
706
|
+
let h2 = 1103547991;
|
|
707
|
+
return {
|
|
708
|
+
update: (chunk) => {
|
|
709
|
+
for (let index = 0; index < chunk.length; index++) {
|
|
710
|
+
const byte = chunk[index];
|
|
711
|
+
h1 = Math.imul(h1 ^ byte, 2654435761);
|
|
712
|
+
h2 = Math.imul(h2 ^ byte, 1597334677);
|
|
713
|
+
}
|
|
714
|
+
},
|
|
715
|
+
digest: () => {
|
|
716
|
+
let a = Math.imul(h1 ^ h1 >>> 16, 2246822507);
|
|
717
|
+
a ^= Math.imul(h2 ^ h2 >>> 13, 3266489909);
|
|
718
|
+
let b = Math.imul(h2 ^ h2 >>> 16, 2246822507);
|
|
719
|
+
b ^= Math.imul(a ^ a >>> 13, 3266489909);
|
|
720
|
+
return `${(b >>> 0).toString(16).padStart(8, "0")}${(a >>> 0).toString(16).padStart(8, "0")}`;
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
};
|
|
724
|
+
|
|
703
725
|
// src/edge/createEdgeEtag.ts
|
|
704
726
|
var createEdgeEtag = async ({
|
|
705
|
-
|
|
727
|
+
version,
|
|
706
728
|
chosen,
|
|
707
729
|
oneShot
|
|
708
730
|
}) => {
|
|
709
731
|
const digest = await crypto.subtle.digest(
|
|
710
732
|
"SHA-1",
|
|
711
|
-
new TextEncoder().encode(`${
|
|
733
|
+
new TextEncoder().encode(`${version}
|
|
712
734
|
${JSON.stringify(chosen)}`)
|
|
713
735
|
);
|
|
714
736
|
const hash = btoa(String.fromCharCode(...new Uint8Array(digest))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -716,19 +738,23 @@ ${JSON.stringify(chosen)}`)
|
|
|
716
738
|
};
|
|
717
739
|
|
|
718
740
|
// src/edge/hasNewVisitorState.ts
|
|
741
|
+
var import_dequal = require("dequal");
|
|
719
742
|
var hasNewVisitorState = (context) => {
|
|
720
|
-
var _a
|
|
721
|
-
const
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
}
|
|
731
|
-
|
|
743
|
+
var _a;
|
|
744
|
+
const before = normalize((_a = context.storage.options.transitionStore) == null ? void 0 : _a.initialData);
|
|
745
|
+
const after = normalize(context.storage.data);
|
|
746
|
+
return !(0, import_dequal.dequal)(before, after);
|
|
747
|
+
};
|
|
748
|
+
var normalize = (data) => {
|
|
749
|
+
var _a, _b, _c, _d, _e, _f;
|
|
750
|
+
return {
|
|
751
|
+
tests: (_a = data == null ? void 0 : data.tests) != null ? _a : {},
|
|
752
|
+
scores: (_b = data == null ? void 0 : data.scores) != null ? _b : {},
|
|
753
|
+
sessionScores: (_c = data == null ? void 0 : data.sessionScores) != null ? _c : {},
|
|
754
|
+
goals: (_d = data == null ? void 0 : data.goals) != null ? _d : {},
|
|
755
|
+
controlGroup: (_e = data == null ? void 0 : data.controlGroup) != null ? _e : false,
|
|
756
|
+
personalizeVariants: (_f = data == null ? void 0 : data.personalizeVariants) != null ? _f : {}
|
|
757
|
+
};
|
|
732
758
|
};
|
|
733
759
|
|
|
734
760
|
// src/edge/matchesIfNoneMatch.ts
|
|
@@ -785,6 +811,7 @@ var choose = (context, placement) => {
|
|
|
785
811
|
|
|
786
812
|
// src/edge/uniformEdgeMiddleware.ts
|
|
787
813
|
var UNIFORM_EDGE_ORIGIN_HEADER = "x-uniform-edge-origin";
|
|
814
|
+
var CONTENT_VERSION_PREFIX = "content:";
|
|
788
815
|
var uniformEdgeMiddleware = (options) => {
|
|
789
816
|
return async (request, event) => {
|
|
790
817
|
return handleUniformEdgeRoute({
|
|
@@ -800,10 +827,11 @@ var handleUniformEdgeRoute = async ({
|
|
|
800
827
|
onError,
|
|
801
828
|
filter,
|
|
802
829
|
store,
|
|
830
|
+
etags = true,
|
|
803
831
|
waitUntil = ignorePromise,
|
|
804
832
|
...options
|
|
805
833
|
}) => {
|
|
806
|
-
var _a, _b, _c;
|
|
834
|
+
var _a, _b, _c, _d;
|
|
807
835
|
if (request.headers.has(UNIFORM_EDGE_ORIGIN_HEADER)) {
|
|
808
836
|
return import_server2.NextResponse.next();
|
|
809
837
|
}
|
|
@@ -853,18 +881,20 @@ var handleUniformEdgeRoute = async ({
|
|
|
853
881
|
headers.delete("content-encoding");
|
|
854
882
|
headers.delete("etag");
|
|
855
883
|
headers.delete("last-modified");
|
|
856
|
-
const
|
|
857
|
-
const
|
|
884
|
+
const isOk = originResponse.status === 200;
|
|
885
|
+
const originEtag = etags && isOk ? originResponse.headers.get("etag") : null;
|
|
886
|
+
const version = originEtag != null ? originEtag : etags && isOk ? (_b = record == null ? void 0 : record.page) == null ? void 0 : _b.etag : void 0;
|
|
887
|
+
const chosen = version && ((_c = record == null ? void 0 : record.page) == null ? void 0 : _c.etag) === version ? replayRecordedPage(context, record.page) : void 0;
|
|
858
888
|
let includeTransitionState = true;
|
|
859
|
-
if (
|
|
889
|
+
if (version && chosen) {
|
|
860
890
|
const newState = hasNewVisitorState(context);
|
|
861
|
-
const etag = await createEdgeEtag({
|
|
891
|
+
const etag = await createEdgeEtag({ version, chosen, oneShot: newState });
|
|
862
892
|
headers.set("etag", etag);
|
|
863
893
|
headers.set("cache-control", "private, no-cache");
|
|
864
894
|
if (!newState) {
|
|
865
895
|
includeTransitionState = false;
|
|
866
896
|
if (matchesIfNoneMatch(request.headers.get("if-none-match"), etag)) {
|
|
867
|
-
(
|
|
897
|
+
(_d = originResponse.body) == null ? void 0 : _d.cancel().catch(() => {
|
|
868
898
|
});
|
|
869
899
|
const notModifiedHeaders = new Headers(result.headers);
|
|
870
900
|
notModifiedHeaders.set("etag", etag);
|
|
@@ -875,14 +905,25 @@ var handleUniformEdgeRoute = async ({
|
|
|
875
905
|
} else {
|
|
876
906
|
headers.set("cache-control", "private, no-store");
|
|
877
907
|
}
|
|
878
|
-
const
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
908
|
+
const hasher = etags && store && isOk && !originEtag ? createContentHasher() : void 0;
|
|
909
|
+
const onComplete = store && isOk ? (placements) => {
|
|
910
|
+
const pageVersion = originEtag != null ? originEtag : hasher ? `${CONTENT_VERSION_PREFIX}${hasher.digest()}` : void 0;
|
|
911
|
+
store.observe({
|
|
912
|
+
pageState: result.pageState,
|
|
913
|
+
hasPlacements: placements.some((placement) => !placement.parent),
|
|
914
|
+
...pageVersion ? { page: { etag: pageVersion, placements: buildPlacementTree(placements) } } : {},
|
|
915
|
+
waitUntil
|
|
916
|
+
});
|
|
917
|
+
} : void 0;
|
|
884
918
|
return new Response(
|
|
885
|
-
transformBody({
|
|
919
|
+
transformBody({
|
|
920
|
+
body: originResponse.body,
|
|
921
|
+
context,
|
|
922
|
+
onError,
|
|
923
|
+
onComplete,
|
|
924
|
+
onChunk: hasher == null ? void 0 : hasher.update,
|
|
925
|
+
includeTransitionState
|
|
926
|
+
}),
|
|
886
927
|
{
|
|
887
928
|
status: originResponse.status,
|
|
888
929
|
statusText: originResponse.statusText,
|
|
@@ -926,6 +967,7 @@ var transformBody = ({
|
|
|
926
967
|
context,
|
|
927
968
|
onError,
|
|
928
969
|
onComplete,
|
|
970
|
+
onChunk,
|
|
929
971
|
includeTransitionState
|
|
930
972
|
}) => {
|
|
931
973
|
if (!body) {
|
|
@@ -950,6 +992,9 @@ var transformBody = ({
|
|
|
950
992
|
await writer.ready.catch(() => {
|
|
951
993
|
});
|
|
952
994
|
const { done, value } = await reader.read();
|
|
995
|
+
if (value) {
|
|
996
|
+
onChunk == null ? void 0 : onChunk(value);
|
|
997
|
+
}
|
|
953
998
|
return { done, value };
|
|
954
999
|
}
|
|
955
1000
|
},
|
package/dist/edge.mjs
CHANGED
|
@@ -668,15 +668,37 @@ var buildPlacementTree = (events) => {
|
|
|
668
668
|
return roots;
|
|
669
669
|
};
|
|
670
670
|
|
|
671
|
+
// src/edge/createContentHasher.ts
|
|
672
|
+
var createContentHasher = () => {
|
|
673
|
+
let h1 = 3735928559;
|
|
674
|
+
let h2 = 1103547991;
|
|
675
|
+
return {
|
|
676
|
+
update: (chunk) => {
|
|
677
|
+
for (let index = 0; index < chunk.length; index++) {
|
|
678
|
+
const byte = chunk[index];
|
|
679
|
+
h1 = Math.imul(h1 ^ byte, 2654435761);
|
|
680
|
+
h2 = Math.imul(h2 ^ byte, 1597334677);
|
|
681
|
+
}
|
|
682
|
+
},
|
|
683
|
+
digest: () => {
|
|
684
|
+
let a = Math.imul(h1 ^ h1 >>> 16, 2246822507);
|
|
685
|
+
a ^= Math.imul(h2 ^ h2 >>> 13, 3266489909);
|
|
686
|
+
let b = Math.imul(h2 ^ h2 >>> 16, 2246822507);
|
|
687
|
+
b ^= Math.imul(a ^ a >>> 13, 3266489909);
|
|
688
|
+
return `${(b >>> 0).toString(16).padStart(8, "0")}${(a >>> 0).toString(16).padStart(8, "0")}`;
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
};
|
|
692
|
+
|
|
671
693
|
// src/edge/createEdgeEtag.ts
|
|
672
694
|
var createEdgeEtag = async ({
|
|
673
|
-
|
|
695
|
+
version,
|
|
674
696
|
chosen,
|
|
675
697
|
oneShot
|
|
676
698
|
}) => {
|
|
677
699
|
const digest = await crypto.subtle.digest(
|
|
678
700
|
"SHA-1",
|
|
679
|
-
new TextEncoder().encode(`${
|
|
701
|
+
new TextEncoder().encode(`${version}
|
|
680
702
|
${JSON.stringify(chosen)}`)
|
|
681
703
|
);
|
|
682
704
|
const hash = btoa(String.fromCharCode(...new Uint8Array(digest))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -684,19 +706,23 @@ ${JSON.stringify(chosen)}`)
|
|
|
684
706
|
};
|
|
685
707
|
|
|
686
708
|
// src/edge/hasNewVisitorState.ts
|
|
709
|
+
import { dequal } from "dequal";
|
|
687
710
|
var hasNewVisitorState = (context) => {
|
|
688
|
-
var _a
|
|
689
|
-
const
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
}
|
|
699
|
-
|
|
711
|
+
var _a;
|
|
712
|
+
const before = normalize((_a = context.storage.options.transitionStore) == null ? void 0 : _a.initialData);
|
|
713
|
+
const after = normalize(context.storage.data);
|
|
714
|
+
return !dequal(before, after);
|
|
715
|
+
};
|
|
716
|
+
var normalize = (data) => {
|
|
717
|
+
var _a, _b, _c, _d, _e, _f;
|
|
718
|
+
return {
|
|
719
|
+
tests: (_a = data == null ? void 0 : data.tests) != null ? _a : {},
|
|
720
|
+
scores: (_b = data == null ? void 0 : data.scores) != null ? _b : {},
|
|
721
|
+
sessionScores: (_c = data == null ? void 0 : data.sessionScores) != null ? _c : {},
|
|
722
|
+
goals: (_d = data == null ? void 0 : data.goals) != null ? _d : {},
|
|
723
|
+
controlGroup: (_e = data == null ? void 0 : data.controlGroup) != null ? _e : false,
|
|
724
|
+
personalizeVariants: (_f = data == null ? void 0 : data.personalizeVariants) != null ? _f : {}
|
|
725
|
+
};
|
|
700
726
|
};
|
|
701
727
|
|
|
702
728
|
// src/edge/matchesIfNoneMatch.ts
|
|
@@ -753,6 +779,7 @@ var choose = (context, placement) => {
|
|
|
753
779
|
|
|
754
780
|
// src/edge/uniformEdgeMiddleware.ts
|
|
755
781
|
var UNIFORM_EDGE_ORIGIN_HEADER = "x-uniform-edge-origin";
|
|
782
|
+
var CONTENT_VERSION_PREFIX = "content:";
|
|
756
783
|
var uniformEdgeMiddleware = (options) => {
|
|
757
784
|
return async (request, event) => {
|
|
758
785
|
return handleUniformEdgeRoute({
|
|
@@ -768,10 +795,11 @@ var handleUniformEdgeRoute = async ({
|
|
|
768
795
|
onError,
|
|
769
796
|
filter,
|
|
770
797
|
store,
|
|
798
|
+
etags = true,
|
|
771
799
|
waitUntil = ignorePromise,
|
|
772
800
|
...options
|
|
773
801
|
}) => {
|
|
774
|
-
var _a, _b, _c;
|
|
802
|
+
var _a, _b, _c, _d;
|
|
775
803
|
if (request.headers.has(UNIFORM_EDGE_ORIGIN_HEADER)) {
|
|
776
804
|
return NextResponse2.next();
|
|
777
805
|
}
|
|
@@ -821,18 +849,20 @@ var handleUniformEdgeRoute = async ({
|
|
|
821
849
|
headers.delete("content-encoding");
|
|
822
850
|
headers.delete("etag");
|
|
823
851
|
headers.delete("last-modified");
|
|
824
|
-
const
|
|
825
|
-
const
|
|
852
|
+
const isOk = originResponse.status === 200;
|
|
853
|
+
const originEtag = etags && isOk ? originResponse.headers.get("etag") : null;
|
|
854
|
+
const version = originEtag != null ? originEtag : etags && isOk ? (_b = record == null ? void 0 : record.page) == null ? void 0 : _b.etag : void 0;
|
|
855
|
+
const chosen = version && ((_c = record == null ? void 0 : record.page) == null ? void 0 : _c.etag) === version ? replayRecordedPage(context, record.page) : void 0;
|
|
826
856
|
let includeTransitionState = true;
|
|
827
|
-
if (
|
|
857
|
+
if (version && chosen) {
|
|
828
858
|
const newState = hasNewVisitorState(context);
|
|
829
|
-
const etag = await createEdgeEtag({
|
|
859
|
+
const etag = await createEdgeEtag({ version, chosen, oneShot: newState });
|
|
830
860
|
headers.set("etag", etag);
|
|
831
861
|
headers.set("cache-control", "private, no-cache");
|
|
832
862
|
if (!newState) {
|
|
833
863
|
includeTransitionState = false;
|
|
834
864
|
if (matchesIfNoneMatch(request.headers.get("if-none-match"), etag)) {
|
|
835
|
-
(
|
|
865
|
+
(_d = originResponse.body) == null ? void 0 : _d.cancel().catch(() => {
|
|
836
866
|
});
|
|
837
867
|
const notModifiedHeaders = new Headers(result.headers);
|
|
838
868
|
notModifiedHeaders.set("etag", etag);
|
|
@@ -843,14 +873,25 @@ var handleUniformEdgeRoute = async ({
|
|
|
843
873
|
} else {
|
|
844
874
|
headers.set("cache-control", "private, no-store");
|
|
845
875
|
}
|
|
846
|
-
const
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
876
|
+
const hasher = etags && store && isOk && !originEtag ? createContentHasher() : void 0;
|
|
877
|
+
const onComplete = store && isOk ? (placements) => {
|
|
878
|
+
const pageVersion = originEtag != null ? originEtag : hasher ? `${CONTENT_VERSION_PREFIX}${hasher.digest()}` : void 0;
|
|
879
|
+
store.observe({
|
|
880
|
+
pageState: result.pageState,
|
|
881
|
+
hasPlacements: placements.some((placement) => !placement.parent),
|
|
882
|
+
...pageVersion ? { page: { etag: pageVersion, placements: buildPlacementTree(placements) } } : {},
|
|
883
|
+
waitUntil
|
|
884
|
+
});
|
|
885
|
+
} : void 0;
|
|
852
886
|
return new Response(
|
|
853
|
-
transformBody({
|
|
887
|
+
transformBody({
|
|
888
|
+
body: originResponse.body,
|
|
889
|
+
context,
|
|
890
|
+
onError,
|
|
891
|
+
onComplete,
|
|
892
|
+
onChunk: hasher == null ? void 0 : hasher.update,
|
|
893
|
+
includeTransitionState
|
|
894
|
+
}),
|
|
854
895
|
{
|
|
855
896
|
status: originResponse.status,
|
|
856
897
|
statusText: originResponse.statusText,
|
|
@@ -894,6 +935,7 @@ var transformBody = ({
|
|
|
894
935
|
context,
|
|
895
936
|
onError,
|
|
896
937
|
onComplete,
|
|
938
|
+
onChunk,
|
|
897
939
|
includeTransitionState
|
|
898
940
|
}) => {
|
|
899
941
|
if (!body) {
|
|
@@ -918,6 +960,9 @@ var transformBody = ({
|
|
|
918
960
|
await writer.ready.catch(() => {
|
|
919
961
|
});
|
|
920
962
|
const { done, value } = await reader.read();
|
|
963
|
+
if (value) {
|
|
964
|
+
onChunk == null ? void 0 : onChunk(value);
|
|
965
|
+
}
|
|
921
966
|
return { done, value };
|
|
922
967
|
}
|
|
923
968
|
},
|
package/dist/index.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ import { ClientContextComponent } from '@uniformdev/next-app-router-client';
|
|
|
8
8
|
import React from 'react';
|
|
9
9
|
import { a as ResolvedRouteResult, b as ResolvedComposition, R as ResolvedCompositionResult } from './composition-CGU7iH-k.mjs';
|
|
10
10
|
export { c as ResolvedNotFound, d as ResolvedRedirect } from './composition-CGU7iH-k.mjs';
|
|
11
|
-
import { E as EdgeRouteFilter } from './models-
|
|
11
|
+
import { E as EdgeRouteFilter } from './models-DKZtopoy.mjs';
|
|
12
12
|
import { b as ResolveRouteFromCodeOptions } from './resolveRouteFromPath-_rauUskz.mjs';
|
|
13
13
|
export { P as PageStateSource, R as ResolveCompositionByIdOptions, a as ResolveCompositionBySlugOptions, c as ResolveRouteFromPathOptions, d as ResolveRouteFunction, r as resolveCompositionById, e as resolveCompositionBySlug, f as resolveRouteFromCode, g as resolveRouteFromPath } from './resolveRouteFromPath-_rauUskz.mjs';
|
|
14
14
|
import '@uniformdev/context';
|
|
@@ -300,8 +300,9 @@ type ResolveRedirectHrefOptions = {
|
|
|
300
300
|
};
|
|
301
301
|
/**
|
|
302
302
|
* Builds the URL a redirect route sends the visitor to. Path variables in the target, such as
|
|
303
|
-
* `/new/:id`,
|
|
304
|
-
* absolute targets on another domain come back
|
|
303
|
+
* `/new/:id`, and a trailing splat, written `*` or `:splat`, are filled from `routePath`. Targets
|
|
304
|
+
* on the same domain come back as relative paths; absolute targets on another domain come back
|
|
305
|
+
* unchanged.
|
|
305
306
|
*/
|
|
306
307
|
declare const resolveRedirectHref: ({ route, routePath }: ResolveRedirectHrefOptions) => string;
|
|
307
308
|
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { ClientContextComponent } from '@uniformdev/next-app-router-client';
|
|
|
8
8
|
import React from 'react';
|
|
9
9
|
import { a as ResolvedRouteResult, b as ResolvedComposition, R as ResolvedCompositionResult } from './composition-CGU7iH-k.js';
|
|
10
10
|
export { c as ResolvedNotFound, d as ResolvedRedirect } from './composition-CGU7iH-k.js';
|
|
11
|
-
import { E as EdgeRouteFilter } from './models-
|
|
11
|
+
import { E as EdgeRouteFilter } from './models-DKZtopoy.js';
|
|
12
12
|
import { b as ResolveRouteFromCodeOptions } from './resolveRouteFromPath-CnfnaxY2.js';
|
|
13
13
|
export { P as PageStateSource, R as ResolveCompositionByIdOptions, a as ResolveCompositionBySlugOptions, c as ResolveRouteFromPathOptions, d as ResolveRouteFunction, r as resolveCompositionById, e as resolveCompositionBySlug, f as resolveRouteFromCode, g as resolveRouteFromPath } from './resolveRouteFromPath-CnfnaxY2.js';
|
|
14
14
|
import '@uniformdev/context';
|
|
@@ -300,8 +300,9 @@ type ResolveRedirectHrefOptions = {
|
|
|
300
300
|
};
|
|
301
301
|
/**
|
|
302
302
|
* Builds the URL a redirect route sends the visitor to. Path variables in the target, such as
|
|
303
|
-
* `/new/:id`,
|
|
304
|
-
* absolute targets on another domain come back
|
|
303
|
+
* `/new/:id`, and a trailing splat, written `*` or `:splat`, are filled from `routePath`. Targets
|
|
304
|
+
* on the same domain come back as relative paths; absolute targets on another domain come back
|
|
305
|
+
* unchanged.
|
|
305
306
|
*/
|
|
306
307
|
declare const resolveRedirectHref: ({ route, routePath }: ResolveRedirectHrefOptions) => string;
|
|
307
308
|
|
package/dist/index.esm.js
CHANGED
|
@@ -3289,8 +3289,7 @@ var REDIRECT_ORIGIN_PLACEHOLDER = "http://uniform.local";
|
|
|
3289
3289
|
var resolveRedirectHref = ({ route, routePath }) => {
|
|
3290
3290
|
const expanded = getTargetVariableExpandedUrl(
|
|
3291
3291
|
new URL(routePath, REDIRECT_ORIGIN_PLACEHOLDER).toString(),
|
|
3292
|
-
route.redirect
|
|
3293
|
-
(pathSegment) => pathSegment.startsWith(":")
|
|
3292
|
+
route.redirect
|
|
3294
3293
|
);
|
|
3295
3294
|
return expanded.startsWith(REDIRECT_ORIGIN_PLACEHOLDER) ? expanded.slice(REDIRECT_ORIGIN_PLACEHOLDER.length) || "/" : expanded;
|
|
3296
3295
|
};
|
package/dist/index.js
CHANGED
|
@@ -3303,8 +3303,7 @@ var REDIRECT_ORIGIN_PLACEHOLDER = "http://uniform.local";
|
|
|
3303
3303
|
var resolveRedirectHref = ({ route, routePath }) => {
|
|
3304
3304
|
const expanded = (0, import_redirect.getTargetVariableExpandedUrl)(
|
|
3305
3305
|
new URL(routePath, REDIRECT_ORIGIN_PLACEHOLDER).toString(),
|
|
3306
|
-
route.redirect
|
|
3307
|
-
(pathSegment) => pathSegment.startsWith(":")
|
|
3306
|
+
route.redirect
|
|
3308
3307
|
);
|
|
3309
3308
|
return expanded.startsWith(REDIRECT_ORIGIN_PLACEHOLDER) ? expanded.slice(REDIRECT_ORIGIN_PLACEHOLDER.length) || "/" : expanded;
|
|
3310
3309
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -3289,8 +3289,7 @@ var REDIRECT_ORIGIN_PLACEHOLDER = "http://uniform.local";
|
|
|
3289
3289
|
var resolveRedirectHref = ({ route, routePath }) => {
|
|
3290
3290
|
const expanded = getTargetVariableExpandedUrl(
|
|
3291
3291
|
new URL(routePath, REDIRECT_ORIGIN_PLACEHOLDER).toString(),
|
|
3292
|
-
route.redirect
|
|
3293
|
-
(pathSegment) => pathSegment.startsWith(":")
|
|
3292
|
+
route.redirect
|
|
3294
3293
|
);
|
|
3295
3294
|
return expanded.startsWith(REDIRECT_ORIGIN_PLACEHOLDER) ? expanded.slice(REDIRECT_ORIGIN_PLACEHOLDER.length) || "/" : expanded;
|
|
3296
3295
|
};
|
|
@@ -58,8 +58,9 @@ type EdgeRouteRecord = {
|
|
|
58
58
|
hasPlacements: boolean;
|
|
59
59
|
page?: EdgeRoutePage;
|
|
60
60
|
};
|
|
61
|
-
/** The placements recorded for one version of a page
|
|
61
|
+
/** The placements recorded for one version of a page. */
|
|
62
62
|
type EdgeRoutePage = {
|
|
63
|
+
/** The page version: the origin's ETag, or a hash of the page when the origin sends none. */
|
|
63
64
|
etag: string;
|
|
64
65
|
placements: RecordedPlacement[];
|
|
65
66
|
};
|
|
@@ -58,8 +58,9 @@ type EdgeRouteRecord = {
|
|
|
58
58
|
hasPlacements: boolean;
|
|
59
59
|
page?: EdgeRoutePage;
|
|
60
60
|
};
|
|
61
|
-
/** The placements recorded for one version of a page
|
|
61
|
+
/** The placements recorded for one version of a page. */
|
|
62
62
|
type EdgeRoutePage = {
|
|
63
|
+
/** The page version: the origin's ETag, or a hash of the page when the origin sends none. */
|
|
63
64
|
etag: string;
|
|
64
65
|
placements: RecordedPlacement[];
|
|
65
66
|
};
|
package/dist/vercel.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as CreateEdgeRouteStoreOptions, C as CreateCachedManifestProviderOptions, b as UniformEdgeMiddlewareOptions } from './createCachedManifestProvider-
|
|
2
|
-
import { d as EdgeRouteStore, f as ManifestProvider, E as EdgeRouteFilter } from './models-
|
|
1
|
+
import { a as CreateEdgeRouteStoreOptions, C as CreateCachedManifestProviderOptions, b as UniformEdgeMiddlewareOptions } from './createCachedManifestProvider-VL1HGJ-J.mjs';
|
|
2
|
+
import { d as EdgeRouteStore, f as ManifestProvider, E as EdgeRouteFilter } from './models-DKZtopoy.mjs';
|
|
3
3
|
import * as next_server from 'next/server';
|
|
4
4
|
import '@uniformdev/context';
|
|
5
5
|
import '@uniformdev/context-edge';
|
|
@@ -53,7 +53,8 @@ type VercelUniformEdgeMiddlewareOptions = Omit<UniformEdgeMiddlewareOptions, 'ma
|
|
|
53
53
|
filter?: EdgeRouteFilter | false;
|
|
54
54
|
/**
|
|
55
55
|
* Records what the transform learns about each page. `false` records nothing, so the default
|
|
56
|
-
* filter processes every published page and responses get no ETag.
|
|
56
|
+
* filter processes every published page and responses get no ETag. To keep the filter and drop
|
|
57
|
+
* only the ETags, set `etags: false`.
|
|
57
58
|
*
|
|
58
59
|
* @defaultValue `vercelEdgeRouteStore()`
|
|
59
60
|
*/
|
package/dist/vercel.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as CreateEdgeRouteStoreOptions, C as CreateCachedManifestProviderOptions, b as UniformEdgeMiddlewareOptions } from './createCachedManifestProvider-
|
|
2
|
-
import { d as EdgeRouteStore, f as ManifestProvider, E as EdgeRouteFilter } from './models-
|
|
1
|
+
import { a as CreateEdgeRouteStoreOptions, C as CreateCachedManifestProviderOptions, b as UniformEdgeMiddlewareOptions } from './createCachedManifestProvider-DrlaCKdm.js';
|
|
2
|
+
import { d as EdgeRouteStore, f as ManifestProvider, E as EdgeRouteFilter } from './models-DKZtopoy.js';
|
|
3
3
|
import * as next_server from 'next/server';
|
|
4
4
|
import '@uniformdev/context';
|
|
5
5
|
import '@uniformdev/context-edge';
|
|
@@ -53,7 +53,8 @@ type VercelUniformEdgeMiddlewareOptions = Omit<UniformEdgeMiddlewareOptions, 'ma
|
|
|
53
53
|
filter?: EdgeRouteFilter | false;
|
|
54
54
|
/**
|
|
55
55
|
* Records what the transform learns about each page. `false` records nothing, so the default
|
|
56
|
-
* filter processes every published page and responses get no ETag.
|
|
56
|
+
* filter processes every published page and responses get no ETag. To keep the filter and drop
|
|
57
|
+
* only the ETags, set `etags: false`.
|
|
57
58
|
*
|
|
58
59
|
* @defaultValue `vercelEdgeRouteStore()`
|
|
59
60
|
*/
|
package/dist/vercel.js
CHANGED
|
@@ -1165,15 +1165,37 @@ var buildPlacementTree = (events) => {
|
|
|
1165
1165
|
return roots;
|
|
1166
1166
|
};
|
|
1167
1167
|
|
|
1168
|
+
// src/edge/createContentHasher.ts
|
|
1169
|
+
var createContentHasher = () => {
|
|
1170
|
+
let h1 = 3735928559;
|
|
1171
|
+
let h2 = 1103547991;
|
|
1172
|
+
return {
|
|
1173
|
+
update: (chunk) => {
|
|
1174
|
+
for (let index = 0; index < chunk.length; index++) {
|
|
1175
|
+
const byte = chunk[index];
|
|
1176
|
+
h1 = Math.imul(h1 ^ byte, 2654435761);
|
|
1177
|
+
h2 = Math.imul(h2 ^ byte, 1597334677);
|
|
1178
|
+
}
|
|
1179
|
+
},
|
|
1180
|
+
digest: () => {
|
|
1181
|
+
let a = Math.imul(h1 ^ h1 >>> 16, 2246822507);
|
|
1182
|
+
a ^= Math.imul(h2 ^ h2 >>> 13, 3266489909);
|
|
1183
|
+
let b = Math.imul(h2 ^ h2 >>> 16, 2246822507);
|
|
1184
|
+
b ^= Math.imul(a ^ a >>> 13, 3266489909);
|
|
1185
|
+
return `${(b >>> 0).toString(16).padStart(8, "0")}${(a >>> 0).toString(16).padStart(8, "0")}`;
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1168
1190
|
// src/edge/createEdgeEtag.ts
|
|
1169
1191
|
var createEdgeEtag = async ({
|
|
1170
|
-
|
|
1192
|
+
version,
|
|
1171
1193
|
chosen,
|
|
1172
1194
|
oneShot
|
|
1173
1195
|
}) => {
|
|
1174
1196
|
const digest = await crypto.subtle.digest(
|
|
1175
1197
|
"SHA-1",
|
|
1176
|
-
new TextEncoder().encode(`${
|
|
1198
|
+
new TextEncoder().encode(`${version}
|
|
1177
1199
|
${JSON.stringify(chosen)}`)
|
|
1178
1200
|
);
|
|
1179
1201
|
const hash = btoa(String.fromCharCode(...new Uint8Array(digest))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -1181,19 +1203,23 @@ ${JSON.stringify(chosen)}`)
|
|
|
1181
1203
|
};
|
|
1182
1204
|
|
|
1183
1205
|
// src/edge/hasNewVisitorState.ts
|
|
1206
|
+
var import_dequal = require("dequal");
|
|
1184
1207
|
var hasNewVisitorState = (context) => {
|
|
1185
|
-
var _a
|
|
1186
|
-
const
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1208
|
+
var _a;
|
|
1209
|
+
const before = normalize((_a = context.storage.options.transitionStore) == null ? void 0 : _a.initialData);
|
|
1210
|
+
const after = normalize(context.storage.data);
|
|
1211
|
+
return !(0, import_dequal.dequal)(before, after);
|
|
1212
|
+
};
|
|
1213
|
+
var normalize = (data) => {
|
|
1214
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1215
|
+
return {
|
|
1216
|
+
tests: (_a = data == null ? void 0 : data.tests) != null ? _a : {},
|
|
1217
|
+
scores: (_b = data == null ? void 0 : data.scores) != null ? _b : {},
|
|
1218
|
+
sessionScores: (_c = data == null ? void 0 : data.sessionScores) != null ? _c : {},
|
|
1219
|
+
goals: (_d = data == null ? void 0 : data.goals) != null ? _d : {},
|
|
1220
|
+
controlGroup: (_e = data == null ? void 0 : data.controlGroup) != null ? _e : false,
|
|
1221
|
+
personalizeVariants: (_f = data == null ? void 0 : data.personalizeVariants) != null ? _f : {}
|
|
1222
|
+
};
|
|
1197
1223
|
};
|
|
1198
1224
|
|
|
1199
1225
|
// src/edge/matchesIfNoneMatch.ts
|
|
@@ -1250,6 +1276,7 @@ var choose = (context, placement) => {
|
|
|
1250
1276
|
|
|
1251
1277
|
// src/edge/uniformEdgeMiddleware.ts
|
|
1252
1278
|
var UNIFORM_EDGE_ORIGIN_HEADER = "x-uniform-edge-origin";
|
|
1279
|
+
var CONTENT_VERSION_PREFIX = "content:";
|
|
1253
1280
|
var uniformEdgeMiddleware = (options) => {
|
|
1254
1281
|
return async (request, event) => {
|
|
1255
1282
|
return handleUniformEdgeRoute({
|
|
@@ -1265,10 +1292,11 @@ var handleUniformEdgeRoute = async ({
|
|
|
1265
1292
|
onError,
|
|
1266
1293
|
filter,
|
|
1267
1294
|
store,
|
|
1295
|
+
etags = true,
|
|
1268
1296
|
waitUntil = ignorePromise,
|
|
1269
1297
|
...options
|
|
1270
1298
|
}) => {
|
|
1271
|
-
var _a, _b, _c;
|
|
1299
|
+
var _a, _b, _c, _d;
|
|
1272
1300
|
if (request.headers.has(UNIFORM_EDGE_ORIGIN_HEADER)) {
|
|
1273
1301
|
return import_server2.NextResponse.next();
|
|
1274
1302
|
}
|
|
@@ -1318,18 +1346,20 @@ var handleUniformEdgeRoute = async ({
|
|
|
1318
1346
|
headers.delete("content-encoding");
|
|
1319
1347
|
headers.delete("etag");
|
|
1320
1348
|
headers.delete("last-modified");
|
|
1321
|
-
const
|
|
1322
|
-
const
|
|
1349
|
+
const isOk = originResponse.status === 200;
|
|
1350
|
+
const originEtag = etags && isOk ? originResponse.headers.get("etag") : null;
|
|
1351
|
+
const version = originEtag != null ? originEtag : etags && isOk ? (_b = record == null ? void 0 : record.page) == null ? void 0 : _b.etag : void 0;
|
|
1352
|
+
const chosen = version && ((_c = record == null ? void 0 : record.page) == null ? void 0 : _c.etag) === version ? replayRecordedPage(context, record.page) : void 0;
|
|
1323
1353
|
let includeTransitionState = true;
|
|
1324
|
-
if (
|
|
1354
|
+
if (version && chosen) {
|
|
1325
1355
|
const newState = hasNewVisitorState(context);
|
|
1326
|
-
const etag = await createEdgeEtag({
|
|
1356
|
+
const etag = await createEdgeEtag({ version, chosen, oneShot: newState });
|
|
1327
1357
|
headers.set("etag", etag);
|
|
1328
1358
|
headers.set("cache-control", "private, no-cache");
|
|
1329
1359
|
if (!newState) {
|
|
1330
1360
|
includeTransitionState = false;
|
|
1331
1361
|
if (matchesIfNoneMatch(request.headers.get("if-none-match"), etag)) {
|
|
1332
|
-
(
|
|
1362
|
+
(_d = originResponse.body) == null ? void 0 : _d.cancel().catch(() => {
|
|
1333
1363
|
});
|
|
1334
1364
|
const notModifiedHeaders = new Headers(result.headers);
|
|
1335
1365
|
notModifiedHeaders.set("etag", etag);
|
|
@@ -1340,14 +1370,25 @@ var handleUniformEdgeRoute = async ({
|
|
|
1340
1370
|
} else {
|
|
1341
1371
|
headers.set("cache-control", "private, no-store");
|
|
1342
1372
|
}
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1373
|
+
const hasher = etags && store && isOk && !originEtag ? createContentHasher() : void 0;
|
|
1374
|
+
const onComplete = store && isOk ? (placements) => {
|
|
1375
|
+
const pageVersion = originEtag != null ? originEtag : hasher ? `${CONTENT_VERSION_PREFIX}${hasher.digest()}` : void 0;
|
|
1376
|
+
store.observe({
|
|
1377
|
+
pageState: result.pageState,
|
|
1378
|
+
hasPlacements: placements.some((placement) => !placement.parent),
|
|
1379
|
+
...pageVersion ? { page: { etag: pageVersion, placements: buildPlacementTree(placements) } } : {},
|
|
1380
|
+
waitUntil
|
|
1381
|
+
});
|
|
1382
|
+
} : void 0;
|
|
1349
1383
|
return new Response(
|
|
1350
|
-
transformBody({
|
|
1384
|
+
transformBody({
|
|
1385
|
+
body: originResponse.body,
|
|
1386
|
+
context,
|
|
1387
|
+
onError,
|
|
1388
|
+
onComplete,
|
|
1389
|
+
onChunk: hasher == null ? void 0 : hasher.update,
|
|
1390
|
+
includeTransitionState
|
|
1391
|
+
}),
|
|
1351
1392
|
{
|
|
1352
1393
|
status: originResponse.status,
|
|
1353
1394
|
statusText: originResponse.statusText,
|
|
@@ -1391,6 +1432,7 @@ var transformBody = ({
|
|
|
1391
1432
|
context,
|
|
1392
1433
|
onError,
|
|
1393
1434
|
onComplete,
|
|
1435
|
+
onChunk,
|
|
1394
1436
|
includeTransitionState
|
|
1395
1437
|
}) => {
|
|
1396
1438
|
if (!body) {
|
|
@@ -1415,6 +1457,9 @@ var transformBody = ({
|
|
|
1415
1457
|
await writer.ready.catch(() => {
|
|
1416
1458
|
});
|
|
1417
1459
|
const { done, value } = await reader.read();
|
|
1460
|
+
if (value) {
|
|
1461
|
+
onChunk == null ? void 0 : onChunk(value);
|
|
1462
|
+
}
|
|
1418
1463
|
return { done, value };
|
|
1419
1464
|
}
|
|
1420
1465
|
},
|
package/dist/vercel.mjs
CHANGED
|
@@ -1136,15 +1136,37 @@ var buildPlacementTree = (events) => {
|
|
|
1136
1136
|
return roots;
|
|
1137
1137
|
};
|
|
1138
1138
|
|
|
1139
|
+
// src/edge/createContentHasher.ts
|
|
1140
|
+
var createContentHasher = () => {
|
|
1141
|
+
let h1 = 3735928559;
|
|
1142
|
+
let h2 = 1103547991;
|
|
1143
|
+
return {
|
|
1144
|
+
update: (chunk) => {
|
|
1145
|
+
for (let index = 0; index < chunk.length; index++) {
|
|
1146
|
+
const byte = chunk[index];
|
|
1147
|
+
h1 = Math.imul(h1 ^ byte, 2654435761);
|
|
1148
|
+
h2 = Math.imul(h2 ^ byte, 1597334677);
|
|
1149
|
+
}
|
|
1150
|
+
},
|
|
1151
|
+
digest: () => {
|
|
1152
|
+
let a = Math.imul(h1 ^ h1 >>> 16, 2246822507);
|
|
1153
|
+
a ^= Math.imul(h2 ^ h2 >>> 13, 3266489909);
|
|
1154
|
+
let b = Math.imul(h2 ^ h2 >>> 16, 2246822507);
|
|
1155
|
+
b ^= Math.imul(a ^ a >>> 13, 3266489909);
|
|
1156
|
+
return `${(b >>> 0).toString(16).padStart(8, "0")}${(a >>> 0).toString(16).padStart(8, "0")}`;
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
};
|
|
1160
|
+
|
|
1139
1161
|
// src/edge/createEdgeEtag.ts
|
|
1140
1162
|
var createEdgeEtag = async ({
|
|
1141
|
-
|
|
1163
|
+
version,
|
|
1142
1164
|
chosen,
|
|
1143
1165
|
oneShot
|
|
1144
1166
|
}) => {
|
|
1145
1167
|
const digest = await crypto.subtle.digest(
|
|
1146
1168
|
"SHA-1",
|
|
1147
|
-
new TextEncoder().encode(`${
|
|
1169
|
+
new TextEncoder().encode(`${version}
|
|
1148
1170
|
${JSON.stringify(chosen)}`)
|
|
1149
1171
|
);
|
|
1150
1172
|
const hash = btoa(String.fromCharCode(...new Uint8Array(digest))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -1152,19 +1174,23 @@ ${JSON.stringify(chosen)}`)
|
|
|
1152
1174
|
};
|
|
1153
1175
|
|
|
1154
1176
|
// src/edge/hasNewVisitorState.ts
|
|
1177
|
+
import { dequal } from "dequal";
|
|
1155
1178
|
var hasNewVisitorState = (context) => {
|
|
1156
|
-
var _a
|
|
1157
|
-
const
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1179
|
+
var _a;
|
|
1180
|
+
const before = normalize((_a = context.storage.options.transitionStore) == null ? void 0 : _a.initialData);
|
|
1181
|
+
const after = normalize(context.storage.data);
|
|
1182
|
+
return !dequal(before, after);
|
|
1183
|
+
};
|
|
1184
|
+
var normalize = (data) => {
|
|
1185
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1186
|
+
return {
|
|
1187
|
+
tests: (_a = data == null ? void 0 : data.tests) != null ? _a : {},
|
|
1188
|
+
scores: (_b = data == null ? void 0 : data.scores) != null ? _b : {},
|
|
1189
|
+
sessionScores: (_c = data == null ? void 0 : data.sessionScores) != null ? _c : {},
|
|
1190
|
+
goals: (_d = data == null ? void 0 : data.goals) != null ? _d : {},
|
|
1191
|
+
controlGroup: (_e = data == null ? void 0 : data.controlGroup) != null ? _e : false,
|
|
1192
|
+
personalizeVariants: (_f = data == null ? void 0 : data.personalizeVariants) != null ? _f : {}
|
|
1193
|
+
};
|
|
1168
1194
|
};
|
|
1169
1195
|
|
|
1170
1196
|
// src/edge/matchesIfNoneMatch.ts
|
|
@@ -1221,6 +1247,7 @@ var choose = (context, placement) => {
|
|
|
1221
1247
|
|
|
1222
1248
|
// src/edge/uniformEdgeMiddleware.ts
|
|
1223
1249
|
var UNIFORM_EDGE_ORIGIN_HEADER = "x-uniform-edge-origin";
|
|
1250
|
+
var CONTENT_VERSION_PREFIX = "content:";
|
|
1224
1251
|
var uniformEdgeMiddleware = (options) => {
|
|
1225
1252
|
return async (request, event) => {
|
|
1226
1253
|
return handleUniformEdgeRoute({
|
|
@@ -1236,10 +1263,11 @@ var handleUniformEdgeRoute = async ({
|
|
|
1236
1263
|
onError,
|
|
1237
1264
|
filter,
|
|
1238
1265
|
store,
|
|
1266
|
+
etags = true,
|
|
1239
1267
|
waitUntil = ignorePromise,
|
|
1240
1268
|
...options
|
|
1241
1269
|
}) => {
|
|
1242
|
-
var _a, _b, _c;
|
|
1270
|
+
var _a, _b, _c, _d;
|
|
1243
1271
|
if (request.headers.has(UNIFORM_EDGE_ORIGIN_HEADER)) {
|
|
1244
1272
|
return NextResponse2.next();
|
|
1245
1273
|
}
|
|
@@ -1289,18 +1317,20 @@ var handleUniformEdgeRoute = async ({
|
|
|
1289
1317
|
headers.delete("content-encoding");
|
|
1290
1318
|
headers.delete("etag");
|
|
1291
1319
|
headers.delete("last-modified");
|
|
1292
|
-
const
|
|
1293
|
-
const
|
|
1320
|
+
const isOk = originResponse.status === 200;
|
|
1321
|
+
const originEtag = etags && isOk ? originResponse.headers.get("etag") : null;
|
|
1322
|
+
const version = originEtag != null ? originEtag : etags && isOk ? (_b = record == null ? void 0 : record.page) == null ? void 0 : _b.etag : void 0;
|
|
1323
|
+
const chosen = version && ((_c = record == null ? void 0 : record.page) == null ? void 0 : _c.etag) === version ? replayRecordedPage(context, record.page) : void 0;
|
|
1294
1324
|
let includeTransitionState = true;
|
|
1295
|
-
if (
|
|
1325
|
+
if (version && chosen) {
|
|
1296
1326
|
const newState = hasNewVisitorState(context);
|
|
1297
|
-
const etag = await createEdgeEtag({
|
|
1327
|
+
const etag = await createEdgeEtag({ version, chosen, oneShot: newState });
|
|
1298
1328
|
headers.set("etag", etag);
|
|
1299
1329
|
headers.set("cache-control", "private, no-cache");
|
|
1300
1330
|
if (!newState) {
|
|
1301
1331
|
includeTransitionState = false;
|
|
1302
1332
|
if (matchesIfNoneMatch(request.headers.get("if-none-match"), etag)) {
|
|
1303
|
-
(
|
|
1333
|
+
(_d = originResponse.body) == null ? void 0 : _d.cancel().catch(() => {
|
|
1304
1334
|
});
|
|
1305
1335
|
const notModifiedHeaders = new Headers(result.headers);
|
|
1306
1336
|
notModifiedHeaders.set("etag", etag);
|
|
@@ -1311,14 +1341,25 @@ var handleUniformEdgeRoute = async ({
|
|
|
1311
1341
|
} else {
|
|
1312
1342
|
headers.set("cache-control", "private, no-store");
|
|
1313
1343
|
}
|
|
1314
|
-
const
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1344
|
+
const hasher = etags && store && isOk && !originEtag ? createContentHasher() : void 0;
|
|
1345
|
+
const onComplete = store && isOk ? (placements) => {
|
|
1346
|
+
const pageVersion = originEtag != null ? originEtag : hasher ? `${CONTENT_VERSION_PREFIX}${hasher.digest()}` : void 0;
|
|
1347
|
+
store.observe({
|
|
1348
|
+
pageState: result.pageState,
|
|
1349
|
+
hasPlacements: placements.some((placement) => !placement.parent),
|
|
1350
|
+
...pageVersion ? { page: { etag: pageVersion, placements: buildPlacementTree(placements) } } : {},
|
|
1351
|
+
waitUntil
|
|
1352
|
+
});
|
|
1353
|
+
} : void 0;
|
|
1320
1354
|
return new Response(
|
|
1321
|
-
transformBody({
|
|
1355
|
+
transformBody({
|
|
1356
|
+
body: originResponse.body,
|
|
1357
|
+
context,
|
|
1358
|
+
onError,
|
|
1359
|
+
onComplete,
|
|
1360
|
+
onChunk: hasher == null ? void 0 : hasher.update,
|
|
1361
|
+
includeTransitionState
|
|
1362
|
+
}),
|
|
1322
1363
|
{
|
|
1323
1364
|
status: originResponse.status,
|
|
1324
1365
|
statusText: originResponse.statusText,
|
|
@@ -1362,6 +1403,7 @@ var transformBody = ({
|
|
|
1362
1403
|
context,
|
|
1363
1404
|
onError,
|
|
1364
1405
|
onComplete,
|
|
1406
|
+
onChunk,
|
|
1365
1407
|
includeTransitionState
|
|
1366
1408
|
}) => {
|
|
1367
1409
|
if (!body) {
|
|
@@ -1386,6 +1428,9 @@ var transformBody = ({
|
|
|
1386
1428
|
await writer.ready.catch(() => {
|
|
1387
1429
|
});
|
|
1388
1430
|
const { done, value } = await reader.read();
|
|
1431
|
+
if (value) {
|
|
1432
|
+
onChunk == null ? void 0 : onChunk(value);
|
|
1433
|
+
}
|
|
1389
1434
|
return { done, value };
|
|
1390
1435
|
}
|
|
1391
1436
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniformdev/next-app-router",
|
|
3
|
-
"version": "20.81.1-alpha.
|
|
3
|
+
"version": "20.81.1-alpha.15.sha-2b5fd446ca",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsup",
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"@types/node": "26.0.0",
|
|
109
109
|
"@types/react": "19.2.17",
|
|
110
110
|
"@types/react-dom": "19.2.3",
|
|
111
|
-
"@uniformdev/context-edge": "20.81.1-alpha.
|
|
111
|
+
"@uniformdev/context-edge": "20.81.1-alpha.15.sha-2b5fd446ca",
|
|
112
112
|
"@vercel/functions": "^3.7.2",
|
|
113
113
|
"next": "16.3.1",
|
|
114
114
|
"react": "19.2.1",
|
|
@@ -118,13 +118,14 @@
|
|
|
118
118
|
"vitest": "4.1.11"
|
|
119
119
|
},
|
|
120
120
|
"dependencies": {
|
|
121
|
-
"@uniformdev/canvas-react": "20.81.1-alpha.
|
|
122
|
-
"@uniformdev/context": "20.81.1-alpha.
|
|
123
|
-
"@uniformdev/next-app-router-client": "20.81.1-alpha.
|
|
124
|
-
"@uniformdev/next-app-router-shared": "20.81.1-alpha.
|
|
125
|
-
"@uniformdev/redirect": "20.81.1-alpha.
|
|
126
|
-
"@uniformdev/richtext": "20.81.1-alpha.
|
|
127
|
-
"@uniformdev/webhooks": "20.81.1-alpha.
|
|
121
|
+
"@uniformdev/canvas-react": "20.81.1-alpha.15.sha-2b5fd446ca",
|
|
122
|
+
"@uniformdev/context": "20.81.1-alpha.15.sha-2b5fd446ca",
|
|
123
|
+
"@uniformdev/next-app-router-client": "20.81.1-alpha.15.sha-2b5fd446ca",
|
|
124
|
+
"@uniformdev/next-app-router-shared": "20.81.1-alpha.15.sha-2b5fd446ca",
|
|
125
|
+
"@uniformdev/redirect": "20.81.1-alpha.15.sha-2b5fd446ca",
|
|
126
|
+
"@uniformdev/richtext": "20.81.1-alpha.15.sha-2b5fd446ca",
|
|
127
|
+
"@uniformdev/webhooks": "20.81.1-alpha.15.sha-2b5fd446ca",
|
|
128
|
+
"dequal": "^2.0.3",
|
|
128
129
|
"encoding": "^0.1.13",
|
|
129
130
|
"server-only": "^0.0.1",
|
|
130
131
|
"svix": "^1.96.0"
|
|
@@ -150,5 +151,5 @@
|
|
|
150
151
|
"publishConfig": {
|
|
151
152
|
"access": "public"
|
|
152
153
|
},
|
|
153
|
-
"gitHead": "
|
|
154
|
+
"gitHead": "2b5fd446caf0ba7503b06dedef66fcdf2d8c8f39"
|
|
154
155
|
}
|