@preprio/toolkit 0.1.0-beta.6 → 0.2.0-beta.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 +178 -13
- package/dist/astro/index.cjs +37 -15
- package/dist/astro/index.d.cts +38 -8
- package/dist/astro/index.d.ts +38 -8
- package/dist/astro/index.js +37 -15
- package/dist/{chunk-NLQIRN5O.js → chunk-6OOGNVJ4.js} +83 -41
- package/dist/index.cjs +102 -55
- package/dist/index.d.cts +59 -16
- package/dist/index.d.ts +59 -16
- package/dist/index.js +22 -16
- package/dist/nextjs/components.cjs +103 -50
- package/dist/nextjs/components.d.cts +16 -9
- package/dist/nextjs/components.d.ts +16 -9
- package/dist/nextjs/components.js +23 -11
- package/dist/nextjs/index.cjs +37 -15
- package/dist/nextjs/index.d.cts +46 -16
- package/dist/nextjs/index.d.ts +46 -16
- package/dist/nextjs/index.js +37 -15
- package/dist/nuxt/index.cjs +37 -15
- package/dist/nuxt/index.d.cts +62 -32
- package/dist/nuxt/index.d.ts +62 -32
- package/dist/nuxt/index.js +37 -15
- package/dist/{pixel-DVSJQC0K.d.cts → pixel-763p7m6A.d.cts} +64 -1
- package/dist/{pixel-DVSJQC0K.d.ts → pixel-763p7m6A.d.ts} +64 -1
- package/dist/react/components.cjs +2237 -0
- package/dist/react/components.d.cts +167 -0
- package/dist/react/components.d.ts +167 -0
- package/dist/react/components.js +2212 -0
- package/dist/react/index.cjs +32 -0
- package/dist/react/index.d.cts +1 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +9 -0
- package/dist/sveltekit/index.cjs +37 -15
- package/dist/sveltekit/index.d.cts +62 -32
- package/dist/sveltekit/index.d.ts +62 -32
- package/dist/sveltekit/index.js +37 -15
- package/package.json +13 -2
- package/src/astro/PreprToolbar.astro +16 -10
- package/src/nuxt/PreprToolbar.vue +10 -8
- package/src/sveltekit/PreprToolbar.svelte +11 -4
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/react/index.ts
|
|
21
|
+
var react_exports = {};
|
|
22
|
+
__export(react_exports, {
|
|
23
|
+
PreprPreview: () => import_components.PreprPreview,
|
|
24
|
+
PreprTrackingPixel: () => import_components.PreprTrackingPixel
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(react_exports);
|
|
27
|
+
var import_components = require("./components.js");
|
|
28
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
29
|
+
0 && (module.exports = {
|
|
30
|
+
PreprPreview,
|
|
31
|
+
PreprTrackingPixel
|
|
32
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PreprPreview, PreprPreviewProps, PreprTrackingPixel, PreprTrackingPixelProps } from './components.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PreprPreview, PreprPreviewProps, PreprTrackingPixel, PreprTrackingPixelProps } from './components.js';
|
package/dist/sveltekit/index.cjs
CHANGED
|
@@ -35,7 +35,7 @@ __export(sveltekit_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(sveltekit_exports);
|
|
36
36
|
|
|
37
37
|
// src/version.ts
|
|
38
|
-
var VERSION = "0.
|
|
38
|
+
var VERSION = "0.2.0-beta.3";
|
|
39
39
|
|
|
40
40
|
// src/core/constants.ts
|
|
41
41
|
var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
|
|
@@ -48,6 +48,24 @@ var PARAM_VARIANT = "prepr_preview_ab";
|
|
|
48
48
|
var PARAM_HIDE_BAR = "prepr_hide_bar";
|
|
49
49
|
var ONE_YEAR_SECONDS = 60 * 60 * 24 * 365;
|
|
50
50
|
|
|
51
|
+
// src/core/features.ts
|
|
52
|
+
function isEnabled(config) {
|
|
53
|
+
if (typeof config === "boolean") return config;
|
|
54
|
+
return config?.enabled ?? true;
|
|
55
|
+
}
|
|
56
|
+
function resolveFeatures(features) {
|
|
57
|
+
return {
|
|
58
|
+
segments: isEnabled(features?.segments),
|
|
59
|
+
abTesting: isEnabled(features?.abTesting),
|
|
60
|
+
editMode: isEnabled(features?.editMode)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
var ALL_FEATURES_ENABLED = Object.freeze({
|
|
64
|
+
segments: true,
|
|
65
|
+
abTesting: true,
|
|
66
|
+
editMode: true
|
|
67
|
+
});
|
|
68
|
+
|
|
51
69
|
// src/core/middleware.ts
|
|
52
70
|
var UTM_PARAMS = [
|
|
53
71
|
"utm_source",
|
|
@@ -131,7 +149,8 @@ function processPreprRequest(request, opts) {
|
|
|
131
149
|
if (!opts?.preview) {
|
|
132
150
|
return { requestHeaders, responseCookies };
|
|
133
151
|
}
|
|
134
|
-
const
|
|
152
|
+
const features = resolveFeatures(opts?.features);
|
|
153
|
+
const hasPreviewParams = features.segments && searchParams.has(PARAM_SEGMENT) || features.abTesting && searchParams.has(PARAM_VARIANT);
|
|
135
154
|
if (!hasPreviewParams) {
|
|
136
155
|
const previewModeCookie = requestCookies.get(COOKIE_PREVIEW_MODE);
|
|
137
156
|
const previewModeEnabled = previewModeCookie !== "false";
|
|
@@ -151,16 +170,16 @@ function processPreprRequest(request, opts) {
|
|
|
151
170
|
});
|
|
152
171
|
}
|
|
153
172
|
if (!isLivePreview) {
|
|
154
|
-
const segmentCookie = requestCookies.get(COOKIE_SEGMENT);
|
|
173
|
+
const segmentCookie = features.segments ? requestCookies.get(COOKIE_SEGMENT) : void 0;
|
|
155
174
|
if (segmentCookie) {
|
|
156
175
|
requestHeaders.set("Prepr-Segments", segmentCookie);
|
|
157
176
|
}
|
|
158
|
-
const abCookie = requestCookies.get(COOKIE_VARIANT);
|
|
177
|
+
const abCookie = features.abTesting ? requestCookies.get(COOKIE_VARIANT) : void 0;
|
|
159
178
|
if (abCookie) {
|
|
160
179
|
requestHeaders.set("Prepr-ABtesting", abCookie);
|
|
161
180
|
}
|
|
162
181
|
}
|
|
163
|
-
const previewAb = searchParams.get(PARAM_VARIANT);
|
|
182
|
+
const previewAb = features.abTesting ? searchParams.get(PARAM_VARIANT) : null;
|
|
164
183
|
if (previewAb !== null) {
|
|
165
184
|
requestHeaders.set("Prepr-ABtesting", previewAb);
|
|
166
185
|
if (!isLivePreview) {
|
|
@@ -173,7 +192,7 @@ function processPreprRequest(request, opts) {
|
|
|
173
192
|
});
|
|
174
193
|
}
|
|
175
194
|
}
|
|
176
|
-
const previewSegment = searchParams.get(PARAM_SEGMENT);
|
|
195
|
+
const previewSegment = features.segments ? searchParams.get(PARAM_SEGMENT) : null;
|
|
177
196
|
if (previewSegment !== null) {
|
|
178
197
|
requestHeaders.set("Prepr-Segments", previewSegment);
|
|
179
198
|
if (!isLivePreview) {
|
|
@@ -348,16 +367,19 @@ async function getPreprEnvironmentSegments(token) {
|
|
|
348
367
|
);
|
|
349
368
|
}
|
|
350
369
|
}
|
|
351
|
-
async function getToolbarPropsFromHeaders(headers, token) {
|
|
370
|
+
async function getToolbarPropsFromHeaders(headers, token, features) {
|
|
371
|
+
const resolved = resolveFeatures(features);
|
|
352
372
|
let segments = [];
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
373
|
+
if (resolved.segments) {
|
|
374
|
+
try {
|
|
375
|
+
segments = await getPreprEnvironmentSegments(token);
|
|
376
|
+
} catch {
|
|
377
|
+
segments = [];
|
|
378
|
+
}
|
|
357
379
|
}
|
|
358
380
|
return {
|
|
359
|
-
activeSegment: getActiveSegmentFromHeaders(headers),
|
|
360
|
-
activeVariant: getActiveVariantFromHeaders(headers),
|
|
381
|
+
activeSegment: resolved.segments ? getActiveSegmentFromHeaders(headers) : null,
|
|
382
|
+
activeVariant: resolved.abTesting ? getActiveVariantFromHeaders(headers) : null,
|
|
361
383
|
segments,
|
|
362
384
|
data: segments
|
|
363
385
|
};
|
|
@@ -376,8 +398,8 @@ function getActiveVariant(headers) {
|
|
|
376
398
|
function getPreprHeaders(headers) {
|
|
377
399
|
return getPreprHeadersFromHeaders(headers);
|
|
378
400
|
}
|
|
379
|
-
async function getToolbarProps(headers, token) {
|
|
380
|
-
return getToolbarPropsFromHeaders(headers, token);
|
|
401
|
+
async function getToolbarProps(headers, token, features) {
|
|
402
|
+
return getToolbarPropsFromHeaders(headers, token, features);
|
|
381
403
|
}
|
|
382
404
|
// Annotate the CommonJS export names for ESM import in node:
|
|
383
405
|
0 && (module.exports = {
|
|
@@ -1,6 +1,67 @@
|
|
|
1
|
+
interface PreprSegment {
|
|
2
|
+
readonly _id: string;
|
|
3
|
+
readonly name: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Per-feature config. `false` is shorthand for `{ enabled: false }`; the object
|
|
7
|
+
* form leaves room for per-feature options later without a breaking change.
|
|
8
|
+
*/
|
|
9
|
+
type PreprFeatureConfig = boolean | {
|
|
10
|
+
enabled?: boolean;
|
|
11
|
+
};
|
|
12
|
+
/** Toolkit features a consumer can turn off. Omitted keys stay enabled. */
|
|
13
|
+
interface PreprFeatures {
|
|
14
|
+
/** Segment picker, `Prepr-Segments` header and its cookie/query param. */
|
|
15
|
+
segments?: PreprFeatureConfig;
|
|
16
|
+
/** A/B variant switch, `Prepr-ABtesting` header and its cookie/query param. */
|
|
17
|
+
abTesting?: PreprFeatureConfig;
|
|
18
|
+
/**
|
|
19
|
+
* The site's own click-to-edit: the toolbar's Edit mode control, the stega
|
|
20
|
+
* tooltip/overlay and the close-edit pill.
|
|
21
|
+
*
|
|
22
|
+
* NOT a security control, and NOT the Prepr editor's live preview. When the
|
|
23
|
+
* site is framed by the editor, `prepr:initVE` still activates edit mode —
|
|
24
|
+
* that is the CMS operating inside its own iframe, not an affordance offered
|
|
25
|
+
* to visitors. See iframe-bridge.ts.
|
|
26
|
+
*/
|
|
27
|
+
editMode?: PreprFeatureConfig;
|
|
28
|
+
}
|
|
29
|
+
interface PreprToolbarProps {
|
|
30
|
+
readonly activeSegment: string | null;
|
|
31
|
+
readonly activeVariant: string | null;
|
|
32
|
+
/** Available segments to personalize on. */
|
|
33
|
+
readonly segments?: readonly PreprSegment[];
|
|
34
|
+
/** @deprecated Alias for `segments`. */
|
|
35
|
+
readonly data?: readonly PreprSegment[];
|
|
36
|
+
}
|
|
37
|
+
type PreprVariant = 'A' | 'B';
|
|
38
|
+
interface PreprHeaders {
|
|
39
|
+
readonly 'prepr-customer-id'?: string;
|
|
40
|
+
readonly 'Prepr-Segments'?: string;
|
|
41
|
+
readonly 'Prepr-ABtesting'?: PreprVariant;
|
|
42
|
+
readonly 'Prepr-Preview-Bar'?: 'true';
|
|
43
|
+
readonly 'Prepr-Context-utm_source'?: string;
|
|
44
|
+
readonly 'Prepr-Context-utm_medium'?: string;
|
|
45
|
+
readonly 'Prepr-Context-utm_term'?: string;
|
|
46
|
+
readonly 'Prepr-Context-utm_content'?: string;
|
|
47
|
+
readonly 'Prepr-Context-utm_campaign'?: string;
|
|
48
|
+
readonly 'Prepr-Context-initial_referral'?: string;
|
|
49
|
+
readonly 'Prepr-Visitor-IP'?: string;
|
|
50
|
+
readonly 'Prepr-Hubspot-Id'?: string;
|
|
51
|
+
readonly 'Prepr-Customer-Id-Created'?: 'true';
|
|
52
|
+
readonly 'Prepr-User-Agent'?: string;
|
|
53
|
+
}
|
|
54
|
+
type PreprErrorCode = 'INVALID_TOKEN' | 'MISSING_TOKEN' | 'HTTP_ERROR' | 'FETCH_ERROR' | 'INVALID_RESPONSE' | 'CONTEXT_ERROR';
|
|
55
|
+
|
|
1
56
|
interface PreprMiddlewareOptions {
|
|
2
57
|
/** Enable preview-mode headers (segment/AB overrides, preview bar). */
|
|
3
58
|
preview?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Disable features app-wide. Pass the same object you give the toolbar: a
|
|
61
|
+
* disabled feature injects no header and persists no cookie, whatever the
|
|
62
|
+
* request carries.
|
|
63
|
+
*/
|
|
64
|
+
features?: PreprFeatures;
|
|
4
65
|
/** Override the version reported in Prepr-Package (mainly for tests). */
|
|
5
66
|
version?: string;
|
|
6
67
|
}
|
|
@@ -49,37 +110,6 @@ declare function preprHandle(options?: PreprMiddlewareOptions): Handle;
|
|
|
49
110
|
*/
|
|
50
111
|
declare function getPreprHeadersFromLocals(locals: Record<string, unknown>): Headers;
|
|
51
112
|
|
|
52
|
-
interface PreprSegment {
|
|
53
|
-
readonly _id: string;
|
|
54
|
-
readonly name: string;
|
|
55
|
-
}
|
|
56
|
-
interface PreprToolbarProps {
|
|
57
|
-
readonly activeSegment: string | null;
|
|
58
|
-
readonly activeVariant: string | null;
|
|
59
|
-
/** Available segments to personalize on. */
|
|
60
|
-
readonly segments?: readonly PreprSegment[];
|
|
61
|
-
/** @deprecated Alias for `segments`. */
|
|
62
|
-
readonly data?: readonly PreprSegment[];
|
|
63
|
-
}
|
|
64
|
-
type PreprVariant = 'A' | 'B';
|
|
65
|
-
interface PreprHeaders {
|
|
66
|
-
readonly 'prepr-customer-id'?: string;
|
|
67
|
-
readonly 'Prepr-Segments'?: string;
|
|
68
|
-
readonly 'Prepr-ABtesting'?: PreprVariant;
|
|
69
|
-
readonly 'Prepr-Preview-Bar'?: 'true';
|
|
70
|
-
readonly 'Prepr-Context-utm_source'?: string;
|
|
71
|
-
readonly 'Prepr-Context-utm_medium'?: string;
|
|
72
|
-
readonly 'Prepr-Context-utm_term'?: string;
|
|
73
|
-
readonly 'Prepr-Context-utm_content'?: string;
|
|
74
|
-
readonly 'Prepr-Context-utm_campaign'?: string;
|
|
75
|
-
readonly 'Prepr-Context-initial_referral'?: string;
|
|
76
|
-
readonly 'Prepr-Visitor-IP'?: string;
|
|
77
|
-
readonly 'Prepr-Hubspot-Id'?: string;
|
|
78
|
-
readonly 'Prepr-Customer-Id-Created'?: 'true';
|
|
79
|
-
readonly 'Prepr-User-Agent'?: string;
|
|
80
|
-
}
|
|
81
|
-
type PreprErrorCode = 'INVALID_TOKEN' | 'MISSING_TOKEN' | 'HTTP_ERROR' | 'FETCH_ERROR' | 'INVALID_RESPONSE' | 'CONTEXT_ERROR';
|
|
82
|
-
|
|
83
113
|
/** Returns the Prepr Customer ID from `event.request.headers`. */
|
|
84
114
|
declare function getPreprUUID(headers: Headers): string | null;
|
|
85
115
|
/** Returns the active segment from `event.request.headers`. */
|
|
@@ -93,7 +123,7 @@ declare function getPreprHeaders(headers: Headers): PreprHeaders;
|
|
|
93
123
|
* plus a Prepr GraphQL token. Ungated — gate on preview mode yourself in
|
|
94
124
|
* `+layout.server.ts`.
|
|
95
125
|
*/
|
|
96
|
-
declare function getToolbarProps(headers: Headers, token: string): Promise<PreprToolbarProps>;
|
|
126
|
+
declare function getToolbarProps(headers: Headers, token: string, features?: PreprFeatures): Promise<PreprToolbarProps>;
|
|
97
127
|
|
|
98
128
|
/** Error thrown by the token helpers and the segments fetch. */
|
|
99
129
|
declare class PreprError extends Error {
|
|
@@ -1,6 +1,67 @@
|
|
|
1
|
+
interface PreprSegment {
|
|
2
|
+
readonly _id: string;
|
|
3
|
+
readonly name: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Per-feature config. `false` is shorthand for `{ enabled: false }`; the object
|
|
7
|
+
* form leaves room for per-feature options later without a breaking change.
|
|
8
|
+
*/
|
|
9
|
+
type PreprFeatureConfig = boolean | {
|
|
10
|
+
enabled?: boolean;
|
|
11
|
+
};
|
|
12
|
+
/** Toolkit features a consumer can turn off. Omitted keys stay enabled. */
|
|
13
|
+
interface PreprFeatures {
|
|
14
|
+
/** Segment picker, `Prepr-Segments` header and its cookie/query param. */
|
|
15
|
+
segments?: PreprFeatureConfig;
|
|
16
|
+
/** A/B variant switch, `Prepr-ABtesting` header and its cookie/query param. */
|
|
17
|
+
abTesting?: PreprFeatureConfig;
|
|
18
|
+
/**
|
|
19
|
+
* The site's own click-to-edit: the toolbar's Edit mode control, the stega
|
|
20
|
+
* tooltip/overlay and the close-edit pill.
|
|
21
|
+
*
|
|
22
|
+
* NOT a security control, and NOT the Prepr editor's live preview. When the
|
|
23
|
+
* site is framed by the editor, `prepr:initVE` still activates edit mode —
|
|
24
|
+
* that is the CMS operating inside its own iframe, not an affordance offered
|
|
25
|
+
* to visitors. See iframe-bridge.ts.
|
|
26
|
+
*/
|
|
27
|
+
editMode?: PreprFeatureConfig;
|
|
28
|
+
}
|
|
29
|
+
interface PreprToolbarProps {
|
|
30
|
+
readonly activeSegment: string | null;
|
|
31
|
+
readonly activeVariant: string | null;
|
|
32
|
+
/** Available segments to personalize on. */
|
|
33
|
+
readonly segments?: readonly PreprSegment[];
|
|
34
|
+
/** @deprecated Alias for `segments`. */
|
|
35
|
+
readonly data?: readonly PreprSegment[];
|
|
36
|
+
}
|
|
37
|
+
type PreprVariant = 'A' | 'B';
|
|
38
|
+
interface PreprHeaders {
|
|
39
|
+
readonly 'prepr-customer-id'?: string;
|
|
40
|
+
readonly 'Prepr-Segments'?: string;
|
|
41
|
+
readonly 'Prepr-ABtesting'?: PreprVariant;
|
|
42
|
+
readonly 'Prepr-Preview-Bar'?: 'true';
|
|
43
|
+
readonly 'Prepr-Context-utm_source'?: string;
|
|
44
|
+
readonly 'Prepr-Context-utm_medium'?: string;
|
|
45
|
+
readonly 'Prepr-Context-utm_term'?: string;
|
|
46
|
+
readonly 'Prepr-Context-utm_content'?: string;
|
|
47
|
+
readonly 'Prepr-Context-utm_campaign'?: string;
|
|
48
|
+
readonly 'Prepr-Context-initial_referral'?: string;
|
|
49
|
+
readonly 'Prepr-Visitor-IP'?: string;
|
|
50
|
+
readonly 'Prepr-Hubspot-Id'?: string;
|
|
51
|
+
readonly 'Prepr-Customer-Id-Created'?: 'true';
|
|
52
|
+
readonly 'Prepr-User-Agent'?: string;
|
|
53
|
+
}
|
|
54
|
+
type PreprErrorCode = 'INVALID_TOKEN' | 'MISSING_TOKEN' | 'HTTP_ERROR' | 'FETCH_ERROR' | 'INVALID_RESPONSE' | 'CONTEXT_ERROR';
|
|
55
|
+
|
|
1
56
|
interface PreprMiddlewareOptions {
|
|
2
57
|
/** Enable preview-mode headers (segment/AB overrides, preview bar). */
|
|
3
58
|
preview?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Disable features app-wide. Pass the same object you give the toolbar: a
|
|
61
|
+
* disabled feature injects no header and persists no cookie, whatever the
|
|
62
|
+
* request carries.
|
|
63
|
+
*/
|
|
64
|
+
features?: PreprFeatures;
|
|
4
65
|
/** Override the version reported in Prepr-Package (mainly for tests). */
|
|
5
66
|
version?: string;
|
|
6
67
|
}
|
|
@@ -49,37 +110,6 @@ declare function preprHandle(options?: PreprMiddlewareOptions): Handle;
|
|
|
49
110
|
*/
|
|
50
111
|
declare function getPreprHeadersFromLocals(locals: Record<string, unknown>): Headers;
|
|
51
112
|
|
|
52
|
-
interface PreprSegment {
|
|
53
|
-
readonly _id: string;
|
|
54
|
-
readonly name: string;
|
|
55
|
-
}
|
|
56
|
-
interface PreprToolbarProps {
|
|
57
|
-
readonly activeSegment: string | null;
|
|
58
|
-
readonly activeVariant: string | null;
|
|
59
|
-
/** Available segments to personalize on. */
|
|
60
|
-
readonly segments?: readonly PreprSegment[];
|
|
61
|
-
/** @deprecated Alias for `segments`. */
|
|
62
|
-
readonly data?: readonly PreprSegment[];
|
|
63
|
-
}
|
|
64
|
-
type PreprVariant = 'A' | 'B';
|
|
65
|
-
interface PreprHeaders {
|
|
66
|
-
readonly 'prepr-customer-id'?: string;
|
|
67
|
-
readonly 'Prepr-Segments'?: string;
|
|
68
|
-
readonly 'Prepr-ABtesting'?: PreprVariant;
|
|
69
|
-
readonly 'Prepr-Preview-Bar'?: 'true';
|
|
70
|
-
readonly 'Prepr-Context-utm_source'?: string;
|
|
71
|
-
readonly 'Prepr-Context-utm_medium'?: string;
|
|
72
|
-
readonly 'Prepr-Context-utm_term'?: string;
|
|
73
|
-
readonly 'Prepr-Context-utm_content'?: string;
|
|
74
|
-
readonly 'Prepr-Context-utm_campaign'?: string;
|
|
75
|
-
readonly 'Prepr-Context-initial_referral'?: string;
|
|
76
|
-
readonly 'Prepr-Visitor-IP'?: string;
|
|
77
|
-
readonly 'Prepr-Hubspot-Id'?: string;
|
|
78
|
-
readonly 'Prepr-Customer-Id-Created'?: 'true';
|
|
79
|
-
readonly 'Prepr-User-Agent'?: string;
|
|
80
|
-
}
|
|
81
|
-
type PreprErrorCode = 'INVALID_TOKEN' | 'MISSING_TOKEN' | 'HTTP_ERROR' | 'FETCH_ERROR' | 'INVALID_RESPONSE' | 'CONTEXT_ERROR';
|
|
82
|
-
|
|
83
113
|
/** Returns the Prepr Customer ID from `event.request.headers`. */
|
|
84
114
|
declare function getPreprUUID(headers: Headers): string | null;
|
|
85
115
|
/** Returns the active segment from `event.request.headers`. */
|
|
@@ -93,7 +123,7 @@ declare function getPreprHeaders(headers: Headers): PreprHeaders;
|
|
|
93
123
|
* plus a Prepr GraphQL token. Ungated — gate on preview mode yourself in
|
|
94
124
|
* `+layout.server.ts`.
|
|
95
125
|
*/
|
|
96
|
-
declare function getToolbarProps(headers: Headers, token: string): Promise<PreprToolbarProps>;
|
|
126
|
+
declare function getToolbarProps(headers: Headers, token: string, features?: PreprFeatures): Promise<PreprToolbarProps>;
|
|
97
127
|
|
|
98
128
|
/** Error thrown by the token helpers and the segments fetch. */
|
|
99
129
|
declare class PreprError extends Error {
|
package/dist/sveltekit/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var VERSION = "0.
|
|
2
|
+
var VERSION = "0.2.0-beta.3";
|
|
3
3
|
|
|
4
4
|
// src/core/constants.ts
|
|
5
5
|
var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
|
|
@@ -12,6 +12,24 @@ var PARAM_VARIANT = "prepr_preview_ab";
|
|
|
12
12
|
var PARAM_HIDE_BAR = "prepr_hide_bar";
|
|
13
13
|
var ONE_YEAR_SECONDS = 60 * 60 * 24 * 365;
|
|
14
14
|
|
|
15
|
+
// src/core/features.ts
|
|
16
|
+
function isEnabled(config) {
|
|
17
|
+
if (typeof config === "boolean") return config;
|
|
18
|
+
return config?.enabled ?? true;
|
|
19
|
+
}
|
|
20
|
+
function resolveFeatures(features) {
|
|
21
|
+
return {
|
|
22
|
+
segments: isEnabled(features?.segments),
|
|
23
|
+
abTesting: isEnabled(features?.abTesting),
|
|
24
|
+
editMode: isEnabled(features?.editMode)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
var ALL_FEATURES_ENABLED = Object.freeze({
|
|
28
|
+
segments: true,
|
|
29
|
+
abTesting: true,
|
|
30
|
+
editMode: true
|
|
31
|
+
});
|
|
32
|
+
|
|
15
33
|
// src/core/middleware.ts
|
|
16
34
|
var UTM_PARAMS = [
|
|
17
35
|
"utm_source",
|
|
@@ -95,7 +113,8 @@ function processPreprRequest(request, opts) {
|
|
|
95
113
|
if (!opts?.preview) {
|
|
96
114
|
return { requestHeaders, responseCookies };
|
|
97
115
|
}
|
|
98
|
-
const
|
|
116
|
+
const features = resolveFeatures(opts?.features);
|
|
117
|
+
const hasPreviewParams = features.segments && searchParams.has(PARAM_SEGMENT) || features.abTesting && searchParams.has(PARAM_VARIANT);
|
|
99
118
|
if (!hasPreviewParams) {
|
|
100
119
|
const previewModeCookie = requestCookies.get(COOKIE_PREVIEW_MODE);
|
|
101
120
|
const previewModeEnabled = previewModeCookie !== "false";
|
|
@@ -115,16 +134,16 @@ function processPreprRequest(request, opts) {
|
|
|
115
134
|
});
|
|
116
135
|
}
|
|
117
136
|
if (!isLivePreview) {
|
|
118
|
-
const segmentCookie = requestCookies.get(COOKIE_SEGMENT);
|
|
137
|
+
const segmentCookie = features.segments ? requestCookies.get(COOKIE_SEGMENT) : void 0;
|
|
119
138
|
if (segmentCookie) {
|
|
120
139
|
requestHeaders.set("Prepr-Segments", segmentCookie);
|
|
121
140
|
}
|
|
122
|
-
const abCookie = requestCookies.get(COOKIE_VARIANT);
|
|
141
|
+
const abCookie = features.abTesting ? requestCookies.get(COOKIE_VARIANT) : void 0;
|
|
123
142
|
if (abCookie) {
|
|
124
143
|
requestHeaders.set("Prepr-ABtesting", abCookie);
|
|
125
144
|
}
|
|
126
145
|
}
|
|
127
|
-
const previewAb = searchParams.get(PARAM_VARIANT);
|
|
146
|
+
const previewAb = features.abTesting ? searchParams.get(PARAM_VARIANT) : null;
|
|
128
147
|
if (previewAb !== null) {
|
|
129
148
|
requestHeaders.set("Prepr-ABtesting", previewAb);
|
|
130
149
|
if (!isLivePreview) {
|
|
@@ -137,7 +156,7 @@ function processPreprRequest(request, opts) {
|
|
|
137
156
|
});
|
|
138
157
|
}
|
|
139
158
|
}
|
|
140
|
-
const previewSegment = searchParams.get(PARAM_SEGMENT);
|
|
159
|
+
const previewSegment = features.segments ? searchParams.get(PARAM_SEGMENT) : null;
|
|
141
160
|
if (previewSegment !== null) {
|
|
142
161
|
requestHeaders.set("Prepr-Segments", previewSegment);
|
|
143
162
|
if (!isLivePreview) {
|
|
@@ -312,16 +331,19 @@ async function getPreprEnvironmentSegments(token) {
|
|
|
312
331
|
);
|
|
313
332
|
}
|
|
314
333
|
}
|
|
315
|
-
async function getToolbarPropsFromHeaders(headers, token) {
|
|
334
|
+
async function getToolbarPropsFromHeaders(headers, token, features) {
|
|
335
|
+
const resolved = resolveFeatures(features);
|
|
316
336
|
let segments = [];
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
337
|
+
if (resolved.segments) {
|
|
338
|
+
try {
|
|
339
|
+
segments = await getPreprEnvironmentSegments(token);
|
|
340
|
+
} catch {
|
|
341
|
+
segments = [];
|
|
342
|
+
}
|
|
321
343
|
}
|
|
322
344
|
return {
|
|
323
|
-
activeSegment: getActiveSegmentFromHeaders(headers),
|
|
324
|
-
activeVariant: getActiveVariantFromHeaders(headers),
|
|
345
|
+
activeSegment: resolved.segments ? getActiveSegmentFromHeaders(headers) : null,
|
|
346
|
+
activeVariant: resolved.abTesting ? getActiveVariantFromHeaders(headers) : null,
|
|
325
347
|
segments,
|
|
326
348
|
data: segments
|
|
327
349
|
};
|
|
@@ -340,8 +362,8 @@ function getActiveVariant(headers) {
|
|
|
340
362
|
function getPreprHeaders(headers) {
|
|
341
363
|
return getPreprHeadersFromHeaders(headers);
|
|
342
364
|
}
|
|
343
|
-
async function getToolbarProps(headers, token) {
|
|
344
|
-
return getToolbarPropsFromHeaders(headers, token);
|
|
365
|
+
async function getToolbarProps(headers, token, features) {
|
|
366
|
+
return getToolbarPropsFromHeaders(headers, token, features);
|
|
345
367
|
}
|
|
346
368
|
export {
|
|
347
369
|
PREPR_LOCALS_KEY,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@preprio/toolkit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Prepr personalization, A/B testing and preview toolkit for Next.js, Nuxt, Astro, SvelteKit and Express",
|
|
3
|
+
"version": "0.2.0-beta.3",
|
|
4
|
+
"description": "Prepr personalization, A/B testing and preview toolkit for React, Next.js, Nuxt, Astro, SvelteKit and Express",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Prepr B.V. (https://prepr.io)",
|
|
7
7
|
"keywords": [
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"ab-testing",
|
|
13
13
|
"preview",
|
|
14
14
|
"visual-editing",
|
|
15
|
+
"react",
|
|
15
16
|
"nextjs",
|
|
16
17
|
"nuxt",
|
|
17
18
|
"astro",
|
|
@@ -38,6 +39,16 @@
|
|
|
38
39
|
"import": "./dist/index.js",
|
|
39
40
|
"require": "./dist/index.cjs"
|
|
40
41
|
},
|
|
42
|
+
"./react": {
|
|
43
|
+
"types": "./dist/react/index.d.ts",
|
|
44
|
+
"import": "./dist/react/index.js",
|
|
45
|
+
"require": "./dist/react/index.cjs"
|
|
46
|
+
},
|
|
47
|
+
"./react/components": {
|
|
48
|
+
"types": "./dist/react/components.d.ts",
|
|
49
|
+
"import": "./dist/react/components.js",
|
|
50
|
+
"require": "./dist/react/components.cjs"
|
|
51
|
+
},
|
|
41
52
|
"./nextjs": {
|
|
42
53
|
"types": "./dist/nextjs/index.d.ts",
|
|
43
54
|
"import": "./dist/nextjs/index.js",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
/**
|
|
3
3
|
* Server-renders nothing visible — mounts the framework-free Prepr toolbar
|
|
4
|
-
* custom element client-side via `
|
|
4
|
+
* custom element client-side via `createPreprPreview` (core).
|
|
5
5
|
*
|
|
6
6
|
* Ships as SOURCE: this file is compiled by the *consumer's* Astro/Vite
|
|
7
7
|
* pipeline (not by this package's own `tsup` build), matching how Astro
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Astro is multi-page (MPA) by default, so the default navigation adapter
|
|
12
12
|
* (core's `window.location.assign`, used when no `navigation` override is
|
|
13
|
-
* passed to `
|
|
13
|
+
* passed to `createPreprPreview`) is the correct choice here — a full page
|
|
14
14
|
* navigation re-runs Astro's server-rendered output (and this component's
|
|
15
15
|
* frontmatter) with the new query params, which is what drives segment /
|
|
16
16
|
* A/B query-param personalization. No client-router
|
|
@@ -22,33 +22,39 @@
|
|
|
22
22
|
* NON-inline `<script>` that Astro/Vite bundles. We deliberately do NOT use
|
|
23
23
|
* `define:vars`, which would force the mount script to be `is:inline` —
|
|
24
24
|
* Astro/Vite do not process bare `import` specifiers in inline scripts, so
|
|
25
|
-
* `import {
|
|
25
|
+
* `import { createPreprPreview } from '@preprio/toolkit'` would fail to
|
|
26
26
|
* resolve in the browser. A processed (bundled) module script gets its
|
|
27
27
|
* imports rewritten to real, hashed module URLs, so the import resolves.
|
|
28
28
|
* (JSON-serializable values only — matches `PreprToolbarProps`, a plain
|
|
29
29
|
* data shape of primitives/arrays.)
|
|
30
30
|
*/
|
|
31
|
-
import type {
|
|
31
|
+
import type { PreprToolbarComponentProps } from '@preprio/toolkit';
|
|
32
32
|
import { serializeForScriptTag } from '@preprio/toolkit/json-script';
|
|
33
33
|
|
|
34
|
-
type Props =
|
|
34
|
+
type Props = PreprToolbarComponentProps;
|
|
35
35
|
|
|
36
|
-
const { activeSegment, activeVariant, segments, data } =
|
|
36
|
+
const { activeSegment, activeVariant, segments, data, options } =
|
|
37
|
+
Astro.props as Props;
|
|
37
38
|
// `data` is the deprecated alias for `segments`; accept either.
|
|
38
|
-
|
|
39
|
+
// `options` travels in the same JSON payload — it is plain data too.
|
|
40
|
+
const payload = {
|
|
41
|
+
props: { activeSegment, activeVariant, segments: segments ?? data ?? [] },
|
|
42
|
+
options,
|
|
43
|
+
};
|
|
39
44
|
---
|
|
40
45
|
|
|
41
46
|
<script
|
|
42
47
|
type="application/json"
|
|
43
48
|
data-prepr-toolbar-props
|
|
44
|
-
set:html={serializeForScriptTag(
|
|
49
|
+
set:html={serializeForScriptTag(payload)}
|
|
45
50
|
/>
|
|
46
51
|
|
|
47
52
|
<script>
|
|
48
|
-
import {
|
|
53
|
+
import { createPreprPreview } from '@preprio/toolkit';
|
|
49
54
|
|
|
50
55
|
const el = document.querySelector('script[data-prepr-toolbar-props]');
|
|
51
56
|
if (el?.textContent) {
|
|
52
|
-
|
|
57
|
+
const { props, options } = JSON.parse(el.textContent);
|
|
58
|
+
createPreprPreview({ props, options });
|
|
53
59
|
}
|
|
54
60
|
</script>
|
|
@@ -7,26 +7,28 @@
|
|
|
7
7
|
* tsup build. See the `./nuxt/components/*` export in package.json.
|
|
8
8
|
*/
|
|
9
9
|
import { onMounted, onUnmounted } from 'vue';
|
|
10
|
-
import {
|
|
11
|
-
import type {
|
|
10
|
+
import { createPreprPreview } from '@preprio/toolkit';
|
|
11
|
+
import type { PreprToolbarComponentProps } from '@preprio/toolkit';
|
|
12
12
|
|
|
13
13
|
const props = defineProps<{
|
|
14
|
-
activeSegment:
|
|
15
|
-
activeVariant:
|
|
16
|
-
segments?:
|
|
17
|
-
data?:
|
|
14
|
+
activeSegment: PreprToolbarComponentProps['activeSegment'];
|
|
15
|
+
activeVariant: PreprToolbarComponentProps['activeVariant'];
|
|
16
|
+
segments?: PreprToolbarComponentProps['segments'];
|
|
17
|
+
data?: PreprToolbarComponentProps['data'];
|
|
18
|
+
options?: PreprToolbarComponentProps['options'];
|
|
18
19
|
}>();
|
|
19
20
|
|
|
20
|
-
let controller: ReturnType<typeof
|
|
21
|
+
let controller: ReturnType<typeof createPreprPreview> | null = null;
|
|
21
22
|
|
|
22
23
|
onMounted(() => {
|
|
23
|
-
controller =
|
|
24
|
+
controller = createPreprPreview({
|
|
24
25
|
props: {
|
|
25
26
|
activeSegment: props.activeSegment,
|
|
26
27
|
activeVariant: props.activeVariant,
|
|
27
28
|
segments: props.segments,
|
|
28
29
|
data: props.data,
|
|
29
30
|
},
|
|
31
|
+
options: props.options,
|
|
30
32
|
});
|
|
31
33
|
});
|
|
32
34
|
|
|
@@ -7,14 +7,21 @@
|
|
|
7
7
|
* our tsup build. See the `./sveltekit/components/*` export in package.json.
|
|
8
8
|
*/
|
|
9
9
|
import { onMount } from 'svelte';
|
|
10
|
-
import {
|
|
11
|
-
import type {
|
|
10
|
+
import { createPreprPreview } from '@preprio/toolkit';
|
|
11
|
+
import type { PreprToolbarComponentProps } from '@preprio/toolkit';
|
|
12
12
|
|
|
13
|
-
let {
|
|
13
|
+
let {
|
|
14
|
+
activeSegment,
|
|
15
|
+
activeVariant,
|
|
16
|
+
data,
|
|
17
|
+
segments,
|
|
18
|
+
options,
|
|
19
|
+
}: PreprToolbarComponentProps = $props();
|
|
14
20
|
|
|
15
21
|
onMount(() => {
|
|
16
|
-
const controller =
|
|
22
|
+
const controller = createPreprPreview({
|
|
17
23
|
props: { activeSegment, activeVariant, data, segments },
|
|
24
|
+
options,
|
|
18
25
|
});
|
|
19
26
|
return () => controller.destroy();
|
|
20
27
|
});
|