@preprio/toolkit 0.6.0-alpha.0 → 0.6.0-alpha.10
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 +268 -59
- package/dist/astro/{chunk-3UVUDDNY.js → chunk-CG2QBHNU.js} +1 -1
- package/dist/astro/graphql.cjs +154 -59
- package/dist/astro/graphql.d.cts +75 -6
- package/dist/astro/graphql.d.ts +75 -6
- package/dist/astro/graphql.js +150 -59
- package/dist/astro/index.cjs +1 -1
- package/dist/astro/index.js +1 -1
- package/dist/chunk-3NCEVJJ3.js +10 -0
- package/dist/{chunk-BJ2LBLWO.js → chunk-LIDUJWWJ.js} +6 -4
- package/dist/chunk-M3RBYJ5J.js +499 -0
- package/dist/{chunk-DGZA7KX7.js → chunk-S5RWVMDJ.js} +0 -24
- package/dist/{chunk-YR7P4IWE.js → chunk-SF6TN4JR.js} +1 -9
- package/dist/chunk-TN6SNAR2.js +26 -0
- package/dist/graphql/codegen.cjs +557 -0
- package/dist/graphql/codegen.d.cts +23 -0
- package/dist/graphql/codegen.d.ts +23 -0
- package/dist/graphql/codegen.js +99 -0
- package/dist/graphql.cjs +185 -59
- package/dist/graphql.d.cts +110 -6
- package/dist/graphql.d.ts +110 -6
- package/dist/graphql.js +91 -430
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -6
- package/dist/nextjs/chunk-B4GVZEOL.js +549 -0
- package/dist/nextjs/components.cjs +297 -81
- package/dist/nextjs/components.d.cts +26 -11
- package/dist/nextjs/components.d.ts +26 -11
- package/dist/nextjs/components.js +289 -73
- package/dist/nextjs/graphql.cjs +952 -315
- package/dist/nextjs/graphql.d.cts +225 -83
- package/dist/nextjs/graphql.d.ts +225 -83
- package/dist/nextjs/graphql.js +634 -314
- package/dist/nextjs/index.cjs +116 -54
- package/dist/nextjs/index.d.cts +61 -23
- package/dist/nextjs/index.d.ts +61 -23
- package/dist/nextjs/index.js +97 -299
- 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-P6ENNAEE.js → chunk-FMC3DP7N.js} +1 -1
- package/dist/nuxt/graphql.cjs +154 -59
- package/dist/nuxt/graphql.d.cts +75 -6
- package/dist/nuxt/graphql.d.ts +75 -6
- package/dist/nuxt/graphql.js +150 -59
- 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-FSARVMG5.js → chunk-AJPKBAHO.js} +1 -1
- package/dist/sveltekit/graphql.cjs +154 -59
- package/dist/sveltekit/graphql.d.cts +75 -6
- package/dist/sveltekit/graphql.d.ts +75 -6
- package/dist/sveltekit/graphql.js +150 -59
- package/dist/sveltekit/index.cjs +1 -1
- package/dist/sveltekit/index.js +1 -1
- package/package.json +6 -1
- package/dist/nextjs/chunk-U4HXENF7.js +0 -231
package/dist/nextjs/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
+
PREPR_ANY_ITEM_TAG,
|
|
3
|
+
PREPR_SCHEMA_TAG,
|
|
2
4
|
PreprError,
|
|
3
|
-
|
|
5
|
+
createPreprDraftRoute,
|
|
6
|
+
createPreprMiddleware,
|
|
4
7
|
extractAccessToken,
|
|
5
8
|
getActiveSegment,
|
|
6
9
|
getActiveVariant,
|
|
@@ -8,332 +11,128 @@ import {
|
|
|
8
11
|
getPreprUUID,
|
|
9
12
|
getToolbarProps,
|
|
10
13
|
isPersonalizedResponse,
|
|
11
|
-
|
|
14
|
+
preprDraftRedirect,
|
|
15
|
+
preprItemTag,
|
|
16
|
+
preprModelTag,
|
|
12
17
|
validatePreprToken
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
|
|
15
|
-
// src/nextjs/middleware.ts
|
|
16
|
-
import { NextResponse } from "next/server";
|
|
18
|
+
} from "./chunk-B4GVZEOL.js";
|
|
17
19
|
|
|
18
|
-
// src/
|
|
19
|
-
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
var
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (!header) return cookies2;
|
|
46
|
-
for (const part of header.split(";")) {
|
|
47
|
-
const eq = part.indexOf("=");
|
|
48
|
-
if (eq === -1) continue;
|
|
49
|
-
const name = part.slice(0, eq).trim();
|
|
50
|
-
const value = part.slice(eq + 1).trim();
|
|
51
|
-
if (!name) continue;
|
|
52
|
-
try {
|
|
53
|
-
cookies2.set(name, decodeURIComponent(value));
|
|
54
|
-
} catch {
|
|
55
|
-
cookies2.set(name, value);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return cookies2;
|
|
59
|
-
}
|
|
60
|
-
function processFrameworkRequest(request, opts, framework) {
|
|
61
|
-
const requestHeaders = new Headers(request.headers);
|
|
62
|
-
const responseCookies = [];
|
|
63
|
-
const inboundPreprHeaders = [];
|
|
64
|
-
requestHeaders.forEach((_value, key) => {
|
|
65
|
-
if (key.toLowerCase().startsWith("prepr-")) {
|
|
66
|
-
inboundPreprHeaders.push(key);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
for (const key of inboundPreprHeaders) {
|
|
70
|
-
requestHeaders.delete(key);
|
|
71
|
-
}
|
|
72
|
-
const requestCookies = parseCookies(request);
|
|
73
|
-
const url = new URL(request.url);
|
|
74
|
-
const searchParams = url.searchParams;
|
|
75
|
-
const forwardedProto = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();
|
|
76
|
-
const isSecure = forwardedProto ? forwardedProto === "https" : url.protocol === "https:";
|
|
77
|
-
const crossSite = isSecure ? { sameSite: "None", secure: true } : {};
|
|
78
|
-
for (const key of UTM_PARAMS) {
|
|
79
|
-
const value = searchParams.get(key);
|
|
80
|
-
if (value !== null) {
|
|
81
|
-
requestHeaders.set(`Prepr-Context-${key}`, sanitizeHeaderValue(value));
|
|
20
|
+
// src/nextjs/webhook.ts
|
|
21
|
+
import { revalidateTag } from "next/cache";
|
|
22
|
+
var CONTENT_EVENTS = /* @__PURE__ */ new Set([
|
|
23
|
+
"content_item.published",
|
|
24
|
+
"content_item.unpublished",
|
|
25
|
+
"content_item.deleted",
|
|
26
|
+
"content_item.invalidated",
|
|
27
|
+
"asset.changed",
|
|
28
|
+
"asset.deleted"
|
|
29
|
+
]);
|
|
30
|
+
var MODEL_EVENTS = /* @__PURE__ */ new Set([
|
|
31
|
+
"content_item.published",
|
|
32
|
+
"content_item.unpublished",
|
|
33
|
+
"content_item.deleted"
|
|
34
|
+
]);
|
|
35
|
+
var MAX_AGE_MS = 5 * 60 * 1e3;
|
|
36
|
+
var HEX_SIGNATURE = /^[0-9a-f]{64}$/i;
|
|
37
|
+
var BASE64_SIGNATURE = /^[A-Za-z0-9+/]{43}=$/;
|
|
38
|
+
var SIGNATURE_PREFIX = /^sha256=/i;
|
|
39
|
+
var MAX_ID_LENGTH = 200;
|
|
40
|
+
var text = (body, status) => new Response(body, { status, headers: { "Content-Type": "text/plain" } });
|
|
41
|
+
function signatureBytes(header) {
|
|
42
|
+
const value = header.trim().replace(SIGNATURE_PREFIX, "");
|
|
43
|
+
if (HEX_SIGNATURE.test(value)) {
|
|
44
|
+
const bytes = new Uint8Array(32);
|
|
45
|
+
for (let i = 0; i < 32; i++) {
|
|
46
|
+
bytes[i] = parseInt(value.slice(i * 2, i * 2 + 2), 16);
|
|
82
47
|
}
|
|
48
|
+
return bytes;
|
|
83
49
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
requestHeaders.set(
|
|
87
|
-
"Prepr-Context-initial_referral",
|
|
88
|
-
sanitizeHeaderValue(referer)
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
const userAgent = request.headers.get("user-agent");
|
|
92
|
-
if (userAgent) {
|
|
93
|
-
requestHeaders.set("User-Agent", sanitizeHeaderValue(userAgent));
|
|
94
|
-
}
|
|
95
|
-
const packageParts = [`@preprio/toolkit@${opts?.version ?? VERSION}`];
|
|
96
|
-
if (framework) packageParts.push(`framework=${framework}`);
|
|
97
|
-
packageParts.push(`preview=${opts?.preview ? "true" : "false"}`);
|
|
98
|
-
requestHeaders.set("Prepr-Package", packageParts.join("; "));
|
|
99
|
-
const ip = request.headers.get("Cf-Connecting-Ip") ?? request.headers.get("x-real-ip");
|
|
100
|
-
if (ip) {
|
|
101
|
-
requestHeaders.set("Prepr-Visitor-IP", sanitizeHeaderValue(ip));
|
|
102
|
-
}
|
|
103
|
-
const hutkCookie = requestCookies.get(COOKIE_HUBSPOT);
|
|
104
|
-
if (hutkCookie) {
|
|
105
|
-
requestHeaders.set("Prepr-Hubspot-Id", sanitizeHeaderValue(hutkCookie));
|
|
106
|
-
}
|
|
107
|
-
let uid = sanitizeHeaderValue(requestCookies.get(COOKIE_UID) ?? "");
|
|
108
|
-
if (!uid) {
|
|
109
|
-
uid = crypto.randomUUID();
|
|
110
|
-
responseCookies.push({
|
|
111
|
-
name: COOKIE_UID,
|
|
112
|
-
value: uid,
|
|
113
|
-
maxAge: ONE_YEAR_SECONDS,
|
|
114
|
-
path: "/"
|
|
115
|
-
});
|
|
116
|
-
requestHeaders.set("Prepr-Customer-Id-Created", "true");
|
|
117
|
-
}
|
|
118
|
-
requestHeaders.set("Prepr-Customer-Id", uid);
|
|
119
|
-
if (!opts?.preview) {
|
|
120
|
-
return { requestHeaders, responseCookies };
|
|
121
|
-
}
|
|
122
|
-
const features = resolveFeatures(opts?.features);
|
|
123
|
-
const hasPreviewParams = features.segments && searchParams.has(PARAM_SEGMENT) || features.abTesting && searchParams.has(PARAM_VARIANT);
|
|
124
|
-
if (!hasPreviewParams) {
|
|
125
|
-
const previewModeCookie = requestCookies.get(COOKIE_PREVIEW_MODE);
|
|
126
|
-
const previewModeEnabled = previewModeCookie !== "false";
|
|
127
|
-
if (!previewModeEnabled) {
|
|
128
|
-
return { requestHeaders, responseCookies };
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
requestHeaders.set("Prepr-Preview-Bar", "true");
|
|
132
|
-
const isLivePreview = searchParams.get(PARAM_HIDE_BAR) === "true";
|
|
133
|
-
if (!isLivePreview && !requestCookies.has(COOKIE_PREVIEW_MODE)) {
|
|
134
|
-
responseCookies.push({
|
|
135
|
-
name: COOKIE_PREVIEW_MODE,
|
|
136
|
-
value: "true",
|
|
137
|
-
maxAge: ONE_YEAR_SECONDS,
|
|
138
|
-
path: "/",
|
|
139
|
-
...crossSite
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
if (!isLivePreview) {
|
|
143
|
-
const segmentCookie = features.segments ? requestCookies.get(COOKIE_SEGMENT) : void 0;
|
|
144
|
-
if (segmentCookie) {
|
|
145
|
-
requestHeaders.set("Prepr-Segments", sanitizeHeaderValue(segmentCookie));
|
|
146
|
-
}
|
|
147
|
-
const abCookie = features.abTesting ? requestCookies.get(COOKIE_VARIANT) : void 0;
|
|
148
|
-
if (abCookie) {
|
|
149
|
-
requestHeaders.set("Prepr-ABtesting", sanitizeHeaderValue(abCookie));
|
|
150
|
-
}
|
|
50
|
+
if (BASE64_SIGNATURE.test(value)) {
|
|
51
|
+
return Uint8Array.from(atob(value), (char) => char.charCodeAt(0));
|
|
151
52
|
}
|
|
152
|
-
|
|
153
|
-
if (previewAb !== null) {
|
|
154
|
-
requestHeaders.set("Prepr-ABtesting", sanitizeHeaderValue(previewAb));
|
|
155
|
-
if (!isLivePreview) {
|
|
156
|
-
responseCookies.push({
|
|
157
|
-
name: COOKIE_VARIANT,
|
|
158
|
-
value: previewAb,
|
|
159
|
-
maxAge: ONE_YEAR_SECONDS,
|
|
160
|
-
path: "/",
|
|
161
|
-
...crossSite
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
const previewSegment = features.segments ? searchParams.get(PARAM_SEGMENT) : null;
|
|
166
|
-
if (previewSegment !== null) {
|
|
167
|
-
requestHeaders.set("Prepr-Segments", sanitizeHeaderValue(previewSegment));
|
|
168
|
-
if (!isLivePreview) {
|
|
169
|
-
responseCookies.push({
|
|
170
|
-
name: COOKIE_SEGMENT,
|
|
171
|
-
value: previewSegment,
|
|
172
|
-
maxAge: ONE_YEAR_SECONDS,
|
|
173
|
-
path: "/",
|
|
174
|
-
...crossSite
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (requestHeaders.has("Prepr-Segments")) {
|
|
179
|
-
requestHeaders.delete("Prepr-Customer-Id");
|
|
180
|
-
requestHeaders.delete("Prepr-Customer-Id-Created");
|
|
181
|
-
}
|
|
182
|
-
return { requestHeaders, responseCookies };
|
|
53
|
+
return null;
|
|
183
54
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
options = maybeOptions;
|
|
192
|
-
} else {
|
|
193
|
-
options = responseOrOptions;
|
|
194
|
-
}
|
|
195
|
-
const { requestHeaders, responseCookies } = processFrameworkRequest(
|
|
196
|
-
request,
|
|
197
|
-
options,
|
|
198
|
-
"nextjs"
|
|
55
|
+
async function verify(secret, signature, body) {
|
|
56
|
+
const key = await crypto.subtle.importKey(
|
|
57
|
+
"raw",
|
|
58
|
+
new TextEncoder().encode(secret),
|
|
59
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
60
|
+
false,
|
|
61
|
+
["verify"]
|
|
199
62
|
);
|
|
200
|
-
|
|
201
|
-
if (chainedResponse) {
|
|
202
|
-
const existing = response.headers.get("x-middleware-override-headers");
|
|
203
|
-
const names = new Set(
|
|
204
|
-
existing ? existing.split(",").map((name) => name.trim()).filter(Boolean) : []
|
|
205
|
-
);
|
|
206
|
-
requestHeaders.forEach((value, key) => {
|
|
207
|
-
names.add(key);
|
|
208
|
-
response.headers.set(`x-middleware-request-${key}`, value);
|
|
209
|
-
});
|
|
210
|
-
response.headers.set("x-middleware-override-headers", [...names].join(","));
|
|
211
|
-
}
|
|
212
|
-
for (const cookie of responseCookies) {
|
|
213
|
-
response.cookies.set(cookie.name, cookie.value, {
|
|
214
|
-
maxAge: cookie.maxAge,
|
|
215
|
-
path: cookie.path,
|
|
216
|
-
// Lower-cased: Next's cookie API expects 'none' | 'lax' | 'strict'.
|
|
217
|
-
...cookie.sameSite ? {
|
|
218
|
-
sameSite: cookie.sameSite.toLowerCase()
|
|
219
|
-
} : {},
|
|
220
|
-
...cookie.secure ? { secure: true } : {}
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
return response;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// src/nextjs/bucket.ts
|
|
227
|
-
var PREPR_BUCKET_COOKIE = "prepr_ab_bucket";
|
|
228
|
-
var isBucket = (value) => value === "A" || value === "B";
|
|
229
|
-
function setBucketCookie(request, response, bucket) {
|
|
230
|
-
response.cookies.set(PREPR_BUCKET_COOKIE, bucket, {
|
|
231
|
-
path: "/",
|
|
232
|
-
sameSite: "lax",
|
|
233
|
-
// Readable on purpose: PreprStack's inline switch reads it before first
|
|
234
|
-
// paint. It holds only "A" or "B".
|
|
235
|
-
httpOnly: false,
|
|
236
|
-
secure: request.nextUrl.protocol === "https:",
|
|
237
|
-
maxAge: 60 * 60 * 24 * 365
|
|
238
|
-
});
|
|
63
|
+
return crypto.subtle.verify("HMAC", key, signature, body);
|
|
239
64
|
}
|
|
240
|
-
|
|
241
|
-
const stored = request.cookies.get(PREPR_BUCKET_COOKIE)?.value;
|
|
242
|
-
const forced = response.headers.get("x-middleware-request-prepr-abtesting") ?? request.cookies.get(COOKIE_VARIANT)?.value;
|
|
243
|
-
if (options.preview && isBucket(forced)) {
|
|
244
|
-
if (forced !== stored) setBucketCookie(request, response, forced);
|
|
245
|
-
return forced;
|
|
246
|
-
}
|
|
247
|
-
if (isBucket(stored)) return stored;
|
|
248
|
-
if (options.onlyIf) {
|
|
249
|
-
const needed = await Promise.resolve().then(options.onlyIf).catch(() => true);
|
|
250
|
-
if (!needed) return "A";
|
|
251
|
-
}
|
|
252
|
-
const customerId = request.cookies.get(COOKIE_UID)?.value ?? response.cookies.get(COOKIE_UID)?.value;
|
|
253
|
-
if (!customerId) return "A";
|
|
65
|
+
function parse(body) {
|
|
254
66
|
try {
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
headers: {
|
|
258
|
-
"Content-Type": "application/json",
|
|
259
|
-
"Prepr-Customer-Id": customerId
|
|
260
|
-
},
|
|
261
|
-
body: JSON.stringify({ query: "{ __typename }" }),
|
|
262
|
-
cache: "no-store",
|
|
263
|
-
signal: AbortSignal.timeout(options.timeoutMs ?? 1500)
|
|
264
|
-
});
|
|
265
|
-
const bucket = res.headers.get("x-prepr-customer-bucket");
|
|
266
|
-
if (isBucket(bucket)) {
|
|
267
|
-
setBucketCookie(request, response, bucket);
|
|
268
|
-
return bucket;
|
|
269
|
-
}
|
|
67
|
+
const value = JSON.parse(new TextDecoder().decode(body));
|
|
68
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
270
69
|
} catch {
|
|
70
|
+
return null;
|
|
271
71
|
}
|
|
272
|
-
return "A";
|
|
273
72
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
var DEFAULT_ROUTE = "/api/prepr/draft";
|
|
282
|
-
function preprDraftRedirect(request, options) {
|
|
283
|
-
if (!options.preview) return null;
|
|
284
|
-
if (request.method !== "GET" && request.method !== "HEAD") return null;
|
|
285
|
-
const url = request.nextUrl;
|
|
286
|
-
if (url.pathname === (options.route ?? DEFAULT_ROUTE)) return null;
|
|
287
|
-
if (request.cookies.has(DRAFT_COOKIE)) {
|
|
288
|
-
if (!url.searchParams.has(RETURN_PARAM)) return null;
|
|
289
|
-
const clean = url.clone();
|
|
290
|
-
clean.searchParams.delete(RETURN_PARAM);
|
|
291
|
-
return NextResponse2.redirect(clean, 307);
|
|
292
|
-
}
|
|
293
|
-
if (url.searchParams.has(RETURN_PARAM)) return null;
|
|
294
|
-
const target = new URL(options.route ?? DEFAULT_ROUTE, request.url);
|
|
295
|
-
target.searchParams.set("to", url.pathname + url.search);
|
|
296
|
-
return NextResponse2.redirect(target, 307);
|
|
73
|
+
function eventTime(value) {
|
|
74
|
+
if (typeof value === "number") return value * 1e3;
|
|
75
|
+
if (typeof value === "string") return Date.parse(value);
|
|
76
|
+
return NaN;
|
|
77
|
+
}
|
|
78
|
+
function field(value, key) {
|
|
79
|
+
return typeof value === "object" && value !== null ? value[key] : void 0;
|
|
297
80
|
}
|
|
298
|
-
|
|
81
|
+
var usable = (value) => typeof value === "string" && value !== "" && value.length <= MAX_ID_LENGTH;
|
|
82
|
+
function tagsFor(event) {
|
|
83
|
+
const name = event.event;
|
|
84
|
+
if (name === "schema.changed") return [PREPR_SCHEMA_TAG];
|
|
85
|
+
if (typeof name !== "string" || !CONTENT_EVENTS.has(name)) return [];
|
|
86
|
+
const tags = [PREPR_ANY_ITEM_TAG];
|
|
87
|
+
const id = field(event.payload, "id");
|
|
88
|
+
if (usable(id)) tags.push(preprItemTag(id));
|
|
89
|
+
const model = field(field(event.payload, "model"), "body_singular");
|
|
90
|
+
if (MODEL_EVENTS.has(name) && usable(model)) tags.push(preprModelTag(model));
|
|
91
|
+
return tags;
|
|
92
|
+
}
|
|
93
|
+
function createPreprWebhookRoute(options) {
|
|
94
|
+
const { profile = { expire: 0 } } = options;
|
|
299
95
|
return async (request) => {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
96
|
+
const { secret } = options;
|
|
97
|
+
if (!secret) return text("Webhook secret not configured", 500);
|
|
98
|
+
const signature = signatureBytes(
|
|
99
|
+
request.headers.get("prepr-signature") ?? ""
|
|
100
|
+
);
|
|
101
|
+
let body;
|
|
102
|
+
try {
|
|
103
|
+
body = await request.arrayBuffer();
|
|
104
|
+
} catch {
|
|
105
|
+
return text("Unreadable body", 400);
|
|
106
|
+
}
|
|
107
|
+
if (!signature || !await verify(secret, signature, body)) {
|
|
108
|
+
return text("Invalid signature", 401);
|
|
109
|
+
}
|
|
110
|
+
const event = parse(body);
|
|
111
|
+
if (!event) return text("Invalid body", 400);
|
|
112
|
+
const sentAt = eventTime(event.created_on);
|
|
113
|
+
if (Number.isFinite(sentAt) && Math.abs(Date.now() - sentAt) > MAX_AGE_MS) {
|
|
114
|
+
return text("Expired", 401);
|
|
317
115
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
redirect(to.pathname + to.search);
|
|
116
|
+
const tags = tagsFor(event);
|
|
117
|
+
for (const tag of tags) revalidateTag(tag, profile);
|
|
118
|
+
return Response.json({ revalidated: tags });
|
|
322
119
|
};
|
|
323
120
|
}
|
|
324
121
|
|
|
325
122
|
// src/nextjs/index.ts
|
|
326
123
|
import {
|
|
124
|
+
PreprPersonalizationSwitch,
|
|
327
125
|
PreprToolbar,
|
|
328
126
|
PreprTrackingPixel
|
|
329
127
|
} from "./components.js";
|
|
330
128
|
export {
|
|
331
|
-
PREPR_BUCKET_COOKIE,
|
|
332
129
|
PreprError,
|
|
130
|
+
PreprPersonalizationSwitch,
|
|
333
131
|
PreprToolbar,
|
|
334
132
|
PreprTrackingPixel,
|
|
335
133
|
createPreprDraftRoute,
|
|
336
134
|
createPreprMiddleware,
|
|
135
|
+
createPreprWebhookRoute,
|
|
337
136
|
extractAccessToken,
|
|
338
137
|
getActiveSegment,
|
|
339
138
|
getActiveVariant,
|
|
@@ -342,6 +141,5 @@ export {
|
|
|
342
141
|
getToolbarProps,
|
|
343
142
|
isPersonalizedResponse,
|
|
344
143
|
preprDraftRedirect,
|
|
345
|
-
resolvePreprBucket,
|
|
346
144
|
validatePreprToken
|
|
347
145
|
};
|
|
@@ -153,4 +153,4 @@ declare function validatePreprToken(token: string): void;
|
|
|
153
153
|
*/
|
|
154
154
|
declare function extractAccessToken(graphqlUrl: string): string;
|
|
155
155
|
|
|
156
|
-
export { type PreprHeaders as P,
|
|
156
|
+
export { type PreprHeaders as P, type PreprFeatures as a, PreprError as b, type PreprToolbarProps as c, type PreprToolbarComponentProps as d, extractAccessToken as e, isPersonalizedResponse as i, validatePreprToken as v };
|
|
@@ -153,4 +153,4 @@ declare function validatePreprToken(token: string): void;
|
|
|
153
153
|
*/
|
|
154
154
|
declare function extractAccessToken(graphqlUrl: string): string;
|
|
155
155
|
|
|
156
|
-
export { type PreprHeaders as P,
|
|
156
|
+
export { type PreprHeaders as P, type PreprFeatures as a, PreprError as b, type PreprToolbarProps as c, type PreprToolbarComponentProps as d, extractAccessToken as e, isPersonalizedResponse as i, validatePreprToken as v };
|