@preprio/toolkit 0.6.0-alpha.1 → 0.6.0-alpha.3
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 +46 -30
- package/dist/astro/{chunk-O7N6GPAH.js → chunk-CUDYSNJD.js} +1 -1
- package/dist/astro/graphql.js +1 -1
- package/dist/astro/index.cjs +1 -1
- package/dist/astro/index.js +1 -1
- package/dist/{chunk-VI6QZTBM.js → chunk-3YZANSVY.js} +1 -1
- package/dist/{chunk-TBKSBXGH.js → chunk-FC53KN4H.js} +1 -1
- package/dist/{chunk-3JLWZQ37.js → chunk-UH2OK4XC.js} +1 -1
- package/dist/{chunk-YWIKKWBR.js → chunk-VY5D3IED.js} +1 -1
- package/dist/graphql/codegen.js +3 -3
- package/dist/graphql.js +3 -3
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/nextjs/chunk-5XGJJVGX.js +544 -0
- package/dist/nextjs/components.cjs +166 -9
- package/dist/nextjs/components.d.cts +31 -3
- package/dist/nextjs/components.d.ts +31 -3
- package/dist/nextjs/components.js +166 -10
- package/dist/nextjs/graphql.cjs +588 -50
- package/dist/nextjs/graphql.d.cts +95 -28
- package/dist/nextjs/graphql.d.ts +95 -28
- package/dist/nextjs/graphql.js +287 -50
- package/dist/nextjs/index.cjs +3 -1
- package/dist/nextjs/index.d.cts +32 -3
- package/dist/nextjs/index.d.ts +32 -3
- package/dist/nextjs/index.js +8 -313
- package/dist/nextjs/{server-CjpELYvq.d.ts → server-BL-sqZvu.d.cts} +1 -1
- package/dist/nextjs/{server-CjpELYvq.d.cts → server-BL-sqZvu.d.ts} +1 -1
- package/dist/nuxt/{chunk-IQDSBPDN.js → chunk-KROR7RXW.js} +1 -1
- package/dist/nuxt/graphql.js +1 -1
- package/dist/nuxt/index.cjs +1 -1
- package/dist/nuxt/index.js +1 -1
- package/dist/react/components.cjs +1 -1
- package/dist/react/components.js +1 -1
- package/dist/sveltekit/{chunk-OKYZ6HPH.js → chunk-INDMNPEM.js} +1 -1
- package/dist/sveltekit/graphql.js +1 -1
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/package.json +1 -1
- package/dist/nextjs/chunk-BQ6IGSH6.js +0 -231
package/dist/nextjs/graphql.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PreprError,
|
|
3
|
+
createPreprMiddleware,
|
|
3
4
|
getPreprHeaders,
|
|
4
5
|
getPreprHeadersFromHeaders,
|
|
5
6
|
isPersonalizedResponse,
|
|
7
|
+
preprDraftRedirect,
|
|
8
|
+
resolvePreprBucket,
|
|
6
9
|
validatePreprToken
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5XGJJVGX.js";
|
|
8
11
|
|
|
9
12
|
// src/core/variants/constants.ts
|
|
10
13
|
var PREPR_CONTEXT_ALIAS = "_preprContext";
|
|
@@ -871,6 +874,49 @@ async function loadPreprSchema(url, options = {}) {
|
|
|
871
874
|
return schema;
|
|
872
875
|
}
|
|
873
876
|
|
|
877
|
+
// src/core/refresh.ts
|
|
878
|
+
var PREPR_REFRESH_COOKIE = "prepr_refresh";
|
|
879
|
+
var PREPR_REFRESH_HEADER = "Prepr-Refresh";
|
|
880
|
+
var REFRESH_MAX_PATHS = 5;
|
|
881
|
+
var SAFE_PATH = /^\/(?![/\\])[\w\-./%]{0,200}$/;
|
|
882
|
+
function safePath(path) {
|
|
883
|
+
return SAFE_PATH.test(path) ? path : void 0;
|
|
884
|
+
}
|
|
885
|
+
function isFresh(at, freshFor, now = Date.now()) {
|
|
886
|
+
const age = now - at;
|
|
887
|
+
return at > 0 && age >= 0 && age < freshFor;
|
|
888
|
+
}
|
|
889
|
+
function cleanEntries(entries) {
|
|
890
|
+
const out = [];
|
|
891
|
+
for (const entry of entries) {
|
|
892
|
+
if (out.length === REFRESH_MAX_PATHS) break;
|
|
893
|
+
if (safePath(entry.path) && !out.some((e) => e.path === entry.path)) {
|
|
894
|
+
out.push(entry);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
return out;
|
|
898
|
+
}
|
|
899
|
+
function parseRefresh(raw) {
|
|
900
|
+
return cleanEntries(
|
|
901
|
+
(raw ?? "").split("|").map((pair) => {
|
|
902
|
+
const split = pair.lastIndexOf("~");
|
|
903
|
+
const at = Number(split < 0 ? "" : pair.slice(split + 1));
|
|
904
|
+
return {
|
|
905
|
+
path: split < 0 ? pair : pair.slice(0, split),
|
|
906
|
+
at: Number.isFinite(at) && at > 0 ? Math.floor(at) : 0
|
|
907
|
+
};
|
|
908
|
+
})
|
|
909
|
+
);
|
|
910
|
+
}
|
|
911
|
+
function serializeRefresh(entries) {
|
|
912
|
+
return cleanEntries(entries).map((entry) => `${entry.path}~${Math.floor(entry.at)}`).join("|");
|
|
913
|
+
}
|
|
914
|
+
function parseRefreshPaths(header) {
|
|
915
|
+
return cleanEntries(
|
|
916
|
+
(header ?? "").split("|").map((path) => ({ path, at: 0 }))
|
|
917
|
+
).map((entry) => entry.path);
|
|
918
|
+
}
|
|
919
|
+
|
|
874
920
|
// src/nextjs/decisions.ts
|
|
875
921
|
var PREPR_DECISIONS_COOKIE = "prepr_decisions";
|
|
876
922
|
var DECISIONS_MAX_GROUPS = 40;
|
|
@@ -902,61 +948,230 @@ function forwardedHeaders(request, response) {
|
|
|
902
948
|
}
|
|
903
949
|
return getPreprHeadersFromHeaders(headers);
|
|
904
950
|
}
|
|
951
|
+
var preprClientInternals = /* @__PURE__ */ new WeakMap();
|
|
952
|
+
var DEFAULT_FRESH_FOR_MS = 1e4;
|
|
953
|
+
async function decidePage(client, seenGroups, headers, document2, variables, timeoutMs = 1e3) {
|
|
954
|
+
if (!await client.hasSegments(document2, variables)) return void 0;
|
|
955
|
+
const decided = await client.decide(document2, variables, {
|
|
956
|
+
topLevelOnly: true,
|
|
957
|
+
headers,
|
|
958
|
+
init: { signal: AbortSignal.timeout(timeoutMs) }
|
|
959
|
+
});
|
|
960
|
+
let byVariables = seenGroups.get(document2);
|
|
961
|
+
if (!byVariables) {
|
|
962
|
+
byVariables = /* @__PURE__ */ new Map();
|
|
963
|
+
seenGroups.set(document2, byVariables);
|
|
964
|
+
}
|
|
965
|
+
const pageKey = JSON.stringify(variables ?? null);
|
|
966
|
+
let groups = byVariables.get(pageKey);
|
|
967
|
+
if (!groups) {
|
|
968
|
+
if (byVariables.size >= SEEN_MAX_PAGES) {
|
|
969
|
+
byVariables.delete(byVariables.keys().next().value);
|
|
970
|
+
}
|
|
971
|
+
groups = /* @__PURE__ */ new Set();
|
|
972
|
+
byVariables.set(pageKey, groups);
|
|
973
|
+
}
|
|
974
|
+
for (const group of decided.keys()) groups.add(group);
|
|
975
|
+
return decided;
|
|
976
|
+
}
|
|
977
|
+
function writeDecisions(request, response, decided, paths) {
|
|
978
|
+
const next = /* @__PURE__ */ new Map();
|
|
979
|
+
for (const decisions of decided) {
|
|
980
|
+
for (const [group, variants] of decisions) {
|
|
981
|
+
if (SAFE_ID.test(group) && !next.has(group)) {
|
|
982
|
+
next.set(
|
|
983
|
+
group,
|
|
984
|
+
variants.filter((v) => SAFE_ID.test(v))
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
for (const [group, variants] of parseDecisions(
|
|
990
|
+
request.cookies.get(PREPR_DECISIONS_COOKIE)?.value
|
|
991
|
+
)) {
|
|
992
|
+
if (!next.has(group)) next.set(group, variants);
|
|
993
|
+
}
|
|
994
|
+
const options = {
|
|
995
|
+
path: "/",
|
|
996
|
+
sameSite: "lax",
|
|
997
|
+
httpOnly: false,
|
|
998
|
+
secure: request.nextUrl.protocol === "https:"
|
|
999
|
+
};
|
|
1000
|
+
if (next.size > 0) {
|
|
1001
|
+
response.cookies.set(
|
|
1002
|
+
PREPR_DECISIONS_COOKIE,
|
|
1003
|
+
serializeDecisions(next),
|
|
1004
|
+
options
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
1007
|
+
if (paths.length > 0) {
|
|
1008
|
+
const at = Date.now();
|
|
1009
|
+
response.cookies.set(
|
|
1010
|
+
PREPR_REFRESH_COOKIE,
|
|
1011
|
+
serializeRefresh([
|
|
1012
|
+
...paths.map((path) => ({ path, at })),
|
|
1013
|
+
...parseRefresh(request.cookies.get(PREPR_REFRESH_COOKIE)?.value)
|
|
1014
|
+
]),
|
|
1015
|
+
options
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
function pagePath(request) {
|
|
1020
|
+
return request.nextUrl.basePath + request.nextUrl.pathname;
|
|
1021
|
+
}
|
|
1022
|
+
function contextChanged(request, headers) {
|
|
1023
|
+
return headers.get("Prepr-Customer-Id-Created") === "true" || headers.has("Prepr-Segments") || [...request.nextUrl.searchParams.keys()].some(
|
|
1024
|
+
(key) => key.startsWith("utm_")
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
905
1027
|
async function resolveDecisionsWith(client, seenGroups, request, response, document2, variables, options) {
|
|
906
1028
|
try {
|
|
907
1029
|
if (options?.onlyIf && !await options.onlyIf()) return;
|
|
908
|
-
|
|
1030
|
+
const known = seenGroups.get(document2)?.get(JSON.stringify(variables ?? null));
|
|
1031
|
+
const path = pagePath(request);
|
|
909
1032
|
const headers = mergePreprHeaders(forwardedHeaders(request, response));
|
|
910
1033
|
const stored = parseDecisions(
|
|
911
1034
|
request.cookies.get(PREPR_DECISIONS_COOKIE)?.value
|
|
912
1035
|
);
|
|
913
|
-
const
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
}
|
|
919
|
-
const known = byVariables.get(pageKey);
|
|
920
|
-
const isNewVisitor = headers.get("Prepr-Customer-Id-Created") === "true";
|
|
921
|
-
const contextChanged = isNewVisitor || headers.has("Prepr-Segments") || [...request.nextUrl.searchParams.keys()].some(
|
|
922
|
-
(key) => key.startsWith("utm_")
|
|
923
|
-
);
|
|
924
|
-
if (options?.reuse !== false && !contextChanged && known && [...known].every((group) => stored.has(group))) {
|
|
1036
|
+
const decidedAt = parseRefresh(request.cookies.get(PREPR_REFRESH_COOKIE)?.value).find(
|
|
1037
|
+
(entry) => entry.path === path
|
|
1038
|
+
)?.at ?? 0;
|
|
1039
|
+
const fresh = isFresh(decidedAt, options?.freshFor ?? DEFAULT_FRESH_FOR_MS);
|
|
1040
|
+
if (fresh && known && !contextChanged(request, headers) && [...known].every((group) => stored.has(group))) {
|
|
925
1041
|
return;
|
|
926
1042
|
}
|
|
927
|
-
const decided = await
|
|
928
|
-
|
|
1043
|
+
const decided = await decidePage(
|
|
1044
|
+
client,
|
|
1045
|
+
seenGroups,
|
|
929
1046
|
headers,
|
|
930
|
-
|
|
1047
|
+
document2,
|
|
1048
|
+
variables,
|
|
1049
|
+
options?.timeoutMs
|
|
1050
|
+
);
|
|
1051
|
+
if (!decided || decided.size === 0) return;
|
|
1052
|
+
writeDecisions(request, response, [decided], [path]);
|
|
1053
|
+
} catch (error) {
|
|
1054
|
+
if (isFrameworkSignal(error)) throw error;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// src/nextjs/proxy.ts
|
|
1059
|
+
import { NextResponse } from "next/server";
|
|
1060
|
+
function isPagePath(pathname) {
|
|
1061
|
+
return !pathname.startsWith("/_next/") && !pathname.startsWith("/api/") && !/\.[^/]*$/.test(pathname);
|
|
1062
|
+
}
|
|
1063
|
+
function createPreprProxy(options) {
|
|
1064
|
+
const internals = preprClientInternals.get(options.client);
|
|
1065
|
+
if (!internals) {
|
|
1066
|
+
throw new PreprError(
|
|
1067
|
+
"createPreprProxy needs a client made by createPreprClient from @preprio/toolkit/nextjs/graphql",
|
|
1068
|
+
"CONTEXT_ERROR",
|
|
1069
|
+
"createPreprProxy"
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
const { client, seenGroups, url } = internals;
|
|
1073
|
+
const preview = options.preview ?? false;
|
|
1074
|
+
const allowed = async (request) => {
|
|
1075
|
+
if (!options.onlyIf) return true;
|
|
1076
|
+
try {
|
|
1077
|
+
return await options.onlyIf(request);
|
|
1078
|
+
} catch {
|
|
1079
|
+
return false;
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
const lookup = (target) => {
|
|
1083
|
+
try {
|
|
1084
|
+
return options.page(target) ?? null;
|
|
1085
|
+
} catch {
|
|
1086
|
+
return null;
|
|
1087
|
+
}
|
|
1088
|
+
};
|
|
1089
|
+
async function refresh(request, response, paths) {
|
|
1090
|
+
const answer = new NextResponse(null, {
|
|
1091
|
+
status: 204,
|
|
1092
|
+
headers: { "Cache-Control": "no-store" }
|
|
931
1093
|
});
|
|
932
|
-
|
|
933
|
-
|
|
1094
|
+
for (const cookie of response.cookies.getAll()) answer.cookies.set(cookie);
|
|
1095
|
+
const site = request.headers.get("sec-fetch-site");
|
|
1096
|
+
if (request.method !== "GET" || site !== null && site !== "same-origin" || !await allowed(request)) {
|
|
1097
|
+
return answer;
|
|
934
1098
|
}
|
|
935
|
-
const
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
);
|
|
945
|
-
|
|
1099
|
+
const own = new Set(
|
|
1100
|
+
parseRefresh(request.cookies.get(PREPR_REFRESH_COOKIE)?.value).map(
|
|
1101
|
+
(entry) => entry.path
|
|
1102
|
+
)
|
|
1103
|
+
);
|
|
1104
|
+
const basePath = request.nextUrl.basePath;
|
|
1105
|
+
const headers = mergePreprHeaders(forwardedHeaders(request, response));
|
|
1106
|
+
const decided = await Promise.all(
|
|
1107
|
+
paths.map(async (path) => {
|
|
1108
|
+
if (!own.has(path) || !path.startsWith(basePath)) return void 0;
|
|
1109
|
+
const pathname = path.slice(basePath.length) || "/";
|
|
1110
|
+
if (!isPagePath(pathname)) return void 0;
|
|
1111
|
+
const target = lookup(new URL(pathname, request.url));
|
|
1112
|
+
if (!target) return void 0;
|
|
1113
|
+
try {
|
|
1114
|
+
const decisions = await decidePage(
|
|
1115
|
+
client,
|
|
1116
|
+
seenGroups,
|
|
1117
|
+
headers,
|
|
1118
|
+
target.document,
|
|
1119
|
+
target.variables,
|
|
1120
|
+
options.timeoutMs
|
|
1121
|
+
);
|
|
1122
|
+
return decisions?.size ? [path, decisions] : void 0;
|
|
1123
|
+
} catch (error) {
|
|
1124
|
+
if (isFrameworkSignal(error)) throw error;
|
|
1125
|
+
return void 0;
|
|
1126
|
+
}
|
|
1127
|
+
})
|
|
1128
|
+
);
|
|
1129
|
+
const found = decided.filter((entry) => entry !== void 0);
|
|
1130
|
+
writeDecisions(
|
|
1131
|
+
request,
|
|
1132
|
+
answer,
|
|
1133
|
+
found.map(([, decisions]) => decisions),
|
|
1134
|
+
found.map(([path]) => path)
|
|
1135
|
+
);
|
|
1136
|
+
return answer;
|
|
1137
|
+
}
|
|
1138
|
+
return async (request) => {
|
|
1139
|
+
if (request.headers.has(PREPR_REFRESH_HEADER)) {
|
|
1140
|
+
return refresh(
|
|
1141
|
+
request,
|
|
1142
|
+
createPreprMiddleware(request, { preview, features: options.features }),
|
|
1143
|
+
parseRefreshPaths(request.headers.get(PREPR_REFRESH_HEADER))
|
|
1144
|
+
);
|
|
946
1145
|
}
|
|
947
|
-
|
|
948
|
-
|
|
1146
|
+
const target = isPagePath(request.nextUrl.pathname) ? lookup(request.nextUrl) : null;
|
|
1147
|
+
if (target && preview) {
|
|
1148
|
+
const draft = preprDraftRedirect(request, { preview });
|
|
1149
|
+
if (draft) return draft;
|
|
949
1150
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
sameSite: "lax",
|
|
954
|
-
// Read by the inline switch script before first paint.
|
|
955
|
-
httpOnly: false
|
|
1151
|
+
const response = createPreprMiddleware(request, {
|
|
1152
|
+
preview,
|
|
1153
|
+
features: options.features
|
|
956
1154
|
});
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1155
|
+
if (target && await allowed(request)) {
|
|
1156
|
+
await Promise.all([
|
|
1157
|
+
resolvePreprBucket(request, response, {
|
|
1158
|
+
url,
|
|
1159
|
+
preview,
|
|
1160
|
+
onlyIf: () => options.client.hasAbTests(target.document, target.variables)
|
|
1161
|
+
}),
|
|
1162
|
+
resolveDecisionsWith(
|
|
1163
|
+
client,
|
|
1164
|
+
seenGroups,
|
|
1165
|
+
request,
|
|
1166
|
+
response,
|
|
1167
|
+
target.document,
|
|
1168
|
+
target.variables,
|
|
1169
|
+
{ freshFor: options.freshFor, timeoutMs: options.timeoutMs }
|
|
1170
|
+
)
|
|
1171
|
+
]);
|
|
1172
|
+
}
|
|
1173
|
+
return response;
|
|
1174
|
+
};
|
|
960
1175
|
}
|
|
961
1176
|
|
|
962
1177
|
// src/nextjs/stack.ts
|
|
@@ -989,7 +1204,11 @@ function applyPreprAbBucket() {
|
|
|
989
1204
|
state.__preprAbSheet.textContent = css;
|
|
990
1205
|
}
|
|
991
1206
|
}
|
|
992
|
-
function applyPreprDecisions() {
|
|
1207
|
+
function applyPreprDecisions(view) {
|
|
1208
|
+
const viewState = window;
|
|
1209
|
+
const current = view === void 0 ? location.pathname + location.search : view;
|
|
1210
|
+
if (viewState.__preprDecisionsView === current) return;
|
|
1211
|
+
viewState.__preprDecisionsView = current;
|
|
993
1212
|
const match = document.cookie.match(/(?:^|; )prepr_decisions=([^;]*)/);
|
|
994
1213
|
let raw;
|
|
995
1214
|
try {
|
|
@@ -1031,7 +1250,11 @@ function applyPreprDecisions() {
|
|
|
1031
1250
|
}
|
|
1032
1251
|
|
|
1033
1252
|
// src/nextjs/stack.ts
|
|
1034
|
-
import {
|
|
1253
|
+
import {
|
|
1254
|
+
PreprAbSwitch,
|
|
1255
|
+
PreprPersonalizationSwitch,
|
|
1256
|
+
PreprVariantTracking
|
|
1257
|
+
} from "./components.js";
|
|
1035
1258
|
var AB_ATTRIBUTE = "data-prepr-ab";
|
|
1036
1259
|
var AB_BUCKETS = ["A", "B"];
|
|
1037
1260
|
var AB_BASE_CSS = `[${AB_ATTRIBUTE}]{display:contents}[${AB_ATTRIBUTE}]:not([${AB_ATTRIBUTE}="A"]){display:none}`;
|
|
@@ -1053,13 +1276,18 @@ function renderBuckets(items, render, options) {
|
|
|
1053
1276
|
abTest,
|
|
1054
1277
|
index,
|
|
1055
1278
|
track,
|
|
1056
|
-
placeholder = false
|
|
1279
|
+
placeholder = false,
|
|
1280
|
+
defaultVariant = true
|
|
1057
1281
|
} = options;
|
|
1058
1282
|
const renderVariant = (variant, key) => {
|
|
1059
1283
|
const resolved = resolveVariants(items, { decisions, bucket: variant });
|
|
1060
|
-
const content = render(resolved, { index, placeholder });
|
|
1061
|
-
const variantKeys = track ? variantKeysOf(resolved) : [];
|
|
1062
1284
|
const ab = abTest && !bucket ? variant : void 0;
|
|
1285
|
+
const content = render(resolved, {
|
|
1286
|
+
index,
|
|
1287
|
+
placeholder,
|
|
1288
|
+
defaultVariant: defaultVariant && (ab === void 0 || ab === "A")
|
|
1289
|
+
});
|
|
1290
|
+
const variantKeys = track ? variantKeysOf(resolved) : [];
|
|
1063
1291
|
if (variantKeys.length > 0) {
|
|
1064
1292
|
return createElement(
|
|
1065
1293
|
PreprVariantTracking,
|
|
@@ -1097,7 +1325,8 @@ function renderAllVariants(block, render, options) {
|
|
|
1097
1325
|
decisions: /* @__PURE__ */ new Map([[group, [variant]]]),
|
|
1098
1326
|
abTest: false,
|
|
1099
1327
|
index: block.index,
|
|
1100
|
-
track: options.track
|
|
1328
|
+
track: options.track,
|
|
1329
|
+
defaultVariant: variant === PREPR_DEFAULT_VARIANT
|
|
1101
1330
|
})
|
|
1102
1331
|
)
|
|
1103
1332
|
);
|
|
@@ -1130,7 +1359,7 @@ function PreprStack({
|
|
|
1130
1359
|
bucket,
|
|
1131
1360
|
nonce,
|
|
1132
1361
|
trackVariants = false,
|
|
1133
|
-
aboveTheFold =
|
|
1362
|
+
aboveTheFold = 1
|
|
1134
1363
|
}) {
|
|
1135
1364
|
decisions.catch(() => void 0);
|
|
1136
1365
|
const blocks = splitStack(items);
|
|
@@ -1153,7 +1382,8 @@ function PreprStack({
|
|
|
1153
1382
|
nonce,
|
|
1154
1383
|
dangerouslySetInnerHTML: { __html: AB_SWITCH_SCRIPT }
|
|
1155
1384
|
}),
|
|
1156
|
-
createElement(PreprAbSwitch)
|
|
1385
|
+
createElement(PreprAbSwitch),
|
|
1386
|
+
hasDecided && createElement(PreprPersonalizationSwitch, { refresh: false })
|
|
1157
1387
|
),
|
|
1158
1388
|
...blocks.map((block) => {
|
|
1159
1389
|
if (decidedInProxy(block)) {
|
|
@@ -1202,7 +1432,7 @@ function createPreprClient2(options) {
|
|
|
1202
1432
|
...coreOptions
|
|
1203
1433
|
});
|
|
1204
1434
|
const seenGroups = /* @__PURE__ */ new Map();
|
|
1205
|
-
|
|
1435
|
+
const nextClient = {
|
|
1206
1436
|
async query(document2, variables, queryOptions = {}) {
|
|
1207
1437
|
const { personalize = false, ...rest } = queryOptions;
|
|
1208
1438
|
const init = rest.init;
|
|
@@ -1243,6 +1473,12 @@ function createPreprClient2(options) {
|
|
|
1243
1473
|
options2
|
|
1244
1474
|
)
|
|
1245
1475
|
};
|
|
1476
|
+
preprClientInternals.set(nextClient, {
|
|
1477
|
+
client,
|
|
1478
|
+
seenGroups,
|
|
1479
|
+
url: coreOptions.url
|
|
1480
|
+
});
|
|
1481
|
+
return nextClient;
|
|
1246
1482
|
}
|
|
1247
1483
|
export {
|
|
1248
1484
|
PREPR_DECISIONS_COOKIE,
|
|
@@ -1250,6 +1486,7 @@ export {
|
|
|
1250
1486
|
PreprError,
|
|
1251
1487
|
PreprStack,
|
|
1252
1488
|
createPreprClient2 as createPreprClient,
|
|
1489
|
+
createPreprProxy,
|
|
1253
1490
|
decisionsFrom,
|
|
1254
1491
|
isPersonalizedResponse,
|
|
1255
1492
|
loadPreprSchema,
|
package/dist/nextjs/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var nextjs_exports = {};
|
|
|
22
22
|
__export(nextjs_exports, {
|
|
23
23
|
PREPR_BUCKET_COOKIE: () => PREPR_BUCKET_COOKIE,
|
|
24
24
|
PreprError: () => PreprError,
|
|
25
|
+
PreprPersonalizationSwitch: () => import_components.PreprPersonalizationSwitch,
|
|
25
26
|
PreprToolbar: () => import_components.PreprToolbar,
|
|
26
27
|
PreprTrackingPixel: () => import_components.PreprTrackingPixel,
|
|
27
28
|
createPreprDraftRoute: () => createPreprDraftRoute,
|
|
@@ -43,7 +44,7 @@ module.exports = __toCommonJS(nextjs_exports);
|
|
|
43
44
|
var import_server = require("next/server");
|
|
44
45
|
|
|
45
46
|
// src/version.ts
|
|
46
|
-
var VERSION = "0.6.0-alpha.
|
|
47
|
+
var VERSION = "0.6.0-alpha.3";
|
|
47
48
|
|
|
48
49
|
// src/core/constants.ts
|
|
49
50
|
var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
|
|
@@ -574,6 +575,7 @@ var import_components = require("./components.cjs");
|
|
|
574
575
|
0 && (module.exports = {
|
|
575
576
|
PREPR_BUCKET_COOKIE,
|
|
576
577
|
PreprError,
|
|
578
|
+
PreprPersonalizationSwitch,
|
|
577
579
|
PreprToolbar,
|
|
578
580
|
PreprTrackingPixel,
|
|
579
581
|
createPreprDraftRoute,
|
package/dist/nextjs/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
2
|
+
import { a as PreprFeatures, P as PreprHeaders, c as PreprToolbarProps, d as PreprToolbarComponentProps } from './server-BL-sqZvu.cjs';
|
|
3
|
+
export { b as PreprError, e as extractAccessToken, i as isPersonalizedResponse, v as validatePreprToken } from './server-BL-sqZvu.cjs';
|
|
4
4
|
|
|
5
5
|
interface PreprMiddlewareOptions {
|
|
6
6
|
/** Enable preview-mode headers (segment/AB overrides, preview bar). */
|
|
@@ -153,5 +153,34 @@ declare function PreprTrackingPixel({ id, config, }: PreprTrackingPixelProps): n
|
|
|
153
153
|
* `createPreprPreview` mounts imperatively.
|
|
154
154
|
*/
|
|
155
155
|
declare function PreprToolbar({ options, ...props }: PreprToolbarComponentProps): null;
|
|
156
|
+
interface PreprPersonalizationSwitchProps {
|
|
157
|
+
/**
|
|
158
|
+
* Keep segment decisions fresh in the background. Default `true`. Leave it
|
|
159
|
+
* on for the instance in your root layout; `PreprStack` renders its own
|
|
160
|
+
* with `false`.
|
|
161
|
+
*/
|
|
162
|
+
refresh?: boolean;
|
|
163
|
+
/** Same as `createPreprProxy`'s `freshFor`. Default 10 000 ms. */
|
|
164
|
+
freshFor?: number;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Shows the segment variants decided in the proxy for the groups above the
|
|
168
|
+
* fold, before the page paints, and keeps those decisions fresh while the
|
|
169
|
+
* visitor browses: a short while after each page view, when the visitor
|
|
170
|
+
* points at a link to a personalized page, and when the tab comes back.
|
|
171
|
+
* Because the next page's decision is already in place when it opens, a
|
|
172
|
+
* visitor who joins a segment mid-visit sees it on their next page view,
|
|
173
|
+
* without anything on screen changing.
|
|
174
|
+
*
|
|
175
|
+
* Mount it once in the root layout. The background refreshes are answered by
|
|
176
|
+
* `createPreprProxy`; with a proxy that calls `resolveDecisions` itself, the
|
|
177
|
+
* first refresh gets a page back and refreshing stops for the browser
|
|
178
|
+
* session. The decisions themselves come from `createPreprProxy` or
|
|
179
|
+
* `resolveDecisions` in `proxy.ts`.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* <PreprPersonalizationSwitch />
|
|
183
|
+
*/
|
|
184
|
+
declare function PreprPersonalizationSwitch({ refresh, freshFor, }: PreprPersonalizationSwitchProps): null;
|
|
156
185
|
|
|
157
|
-
export { PREPR_BUCKET_COOKIE, type PreprBucket, type PreprDraftOptions, type PreprMiddlewareOptions, PreprToolbar, PreprTrackingPixel, type PreprTrackingPixelProps, type ResolvePreprBucketOptions, createPreprDraftRoute, createPreprMiddleware, getActiveSegment, getActiveVariant, getPreprHeaders, getPreprUUID, getToolbarProps, preprDraftRedirect, resolvePreprBucket };
|
|
186
|
+
export { PREPR_BUCKET_COOKIE, type PreprBucket, type PreprDraftOptions, type PreprMiddlewareOptions, PreprPersonalizationSwitch, type PreprPersonalizationSwitchProps, PreprToolbar, PreprTrackingPixel, type PreprTrackingPixelProps, type ResolvePreprBucketOptions, createPreprDraftRoute, createPreprMiddleware, getActiveSegment, getActiveVariant, getPreprHeaders, getPreprUUID, getToolbarProps, preprDraftRedirect, resolvePreprBucket };
|
package/dist/nextjs/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
2
|
+
import { a as PreprFeatures, P as PreprHeaders, c as PreprToolbarProps, d as PreprToolbarComponentProps } from './server-BL-sqZvu.js';
|
|
3
|
+
export { b as PreprError, e as extractAccessToken, i as isPersonalizedResponse, v as validatePreprToken } from './server-BL-sqZvu.js';
|
|
4
4
|
|
|
5
5
|
interface PreprMiddlewareOptions {
|
|
6
6
|
/** Enable preview-mode headers (segment/AB overrides, preview bar). */
|
|
@@ -153,5 +153,34 @@ declare function PreprTrackingPixel({ id, config, }: PreprTrackingPixelProps): n
|
|
|
153
153
|
* `createPreprPreview` mounts imperatively.
|
|
154
154
|
*/
|
|
155
155
|
declare function PreprToolbar({ options, ...props }: PreprToolbarComponentProps): null;
|
|
156
|
+
interface PreprPersonalizationSwitchProps {
|
|
157
|
+
/**
|
|
158
|
+
* Keep segment decisions fresh in the background. Default `true`. Leave it
|
|
159
|
+
* on for the instance in your root layout; `PreprStack` renders its own
|
|
160
|
+
* with `false`.
|
|
161
|
+
*/
|
|
162
|
+
refresh?: boolean;
|
|
163
|
+
/** Same as `createPreprProxy`'s `freshFor`. Default 10 000 ms. */
|
|
164
|
+
freshFor?: number;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Shows the segment variants decided in the proxy for the groups above the
|
|
168
|
+
* fold, before the page paints, and keeps those decisions fresh while the
|
|
169
|
+
* visitor browses: a short while after each page view, when the visitor
|
|
170
|
+
* points at a link to a personalized page, and when the tab comes back.
|
|
171
|
+
* Because the next page's decision is already in place when it opens, a
|
|
172
|
+
* visitor who joins a segment mid-visit sees it on their next page view,
|
|
173
|
+
* without anything on screen changing.
|
|
174
|
+
*
|
|
175
|
+
* Mount it once in the root layout. The background refreshes are answered by
|
|
176
|
+
* `createPreprProxy`; with a proxy that calls `resolveDecisions` itself, the
|
|
177
|
+
* first refresh gets a page back and refreshing stops for the browser
|
|
178
|
+
* session. The decisions themselves come from `createPreprProxy` or
|
|
179
|
+
* `resolveDecisions` in `proxy.ts`.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* <PreprPersonalizationSwitch />
|
|
183
|
+
*/
|
|
184
|
+
declare function PreprPersonalizationSwitch({ refresh, freshFor, }: PreprPersonalizationSwitchProps): null;
|
|
156
185
|
|
|
157
|
-
export { PREPR_BUCKET_COOKIE, type PreprBucket, type PreprDraftOptions, type PreprMiddlewareOptions, PreprToolbar, PreprTrackingPixel, type PreprTrackingPixelProps, type ResolvePreprBucketOptions, createPreprDraftRoute, createPreprMiddleware, getActiveSegment, getActiveVariant, getPreprHeaders, getPreprUUID, getToolbarProps, preprDraftRedirect, resolvePreprBucket };
|
|
186
|
+
export { PREPR_BUCKET_COOKIE, type PreprBucket, type PreprDraftOptions, type PreprMiddlewareOptions, PreprPersonalizationSwitch, type PreprPersonalizationSwitchProps, PreprToolbar, PreprTrackingPixel, type PreprTrackingPixelProps, type ResolvePreprBucketOptions, createPreprDraftRoute, createPreprMiddleware, getActiveSegment, getActiveVariant, getPreprHeaders, getPreprUUID, getToolbarProps, preprDraftRedirect, resolvePreprBucket };
|