@preprio/toolkit 0.5.0-rc.2 → 0.6.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +415 -27
- package/dist/astro/chunk-O7N6GPAH.js +173 -0
- package/dist/astro/graphql.cjs +1030 -0
- package/dist/astro/graphql.d.cts +305 -0
- package/dist/astro/graphql.d.ts +305 -0
- package/dist/astro/graphql.js +936 -0
- package/dist/astro/index-XT_z-RYT.d.cts +130 -0
- package/dist/astro/index-XT_z-RYT.d.ts +130 -0
- package/dist/astro/index.cjs +14 -1
- package/dist/astro/index.d.cts +1 -120
- package/dist/astro/index.d.ts +1 -120
- package/dist/astro/index.js +15 -153
- package/dist/chunk-3JLWZQ37.js +179 -0
- package/dist/chunk-3NCEVJJ3.js +10 -0
- package/dist/chunk-S5RWVMDJ.js +148 -0
- package/dist/chunk-TBKSBXGH.js +452 -0
- package/dist/{chunk-FLPNN3CV.js → chunk-VI6QZTBM.js} +73 -276
- package/dist/chunk-YWIKKWBR.js +26 -0
- package/dist/graphql/codegen.cjs +510 -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 +941 -0
- package/dist/graphql.d.cts +305 -0
- package/dist/graphql.d.ts +305 -0
- package/dist/graphql.js +419 -0
- package/dist/index.cjs +76 -119
- package/dist/index.d.cts +12 -64
- package/dist/index.d.ts +12 -64
- package/dist/index.js +27 -167
- package/dist/nextjs/chunk-BQ6IGSH6.js +231 -0
- package/dist/nextjs/components.cjs +190 -122
- package/dist/nextjs/components.d.cts +33 -2
- package/dist/nextjs/components.d.ts +33 -2
- package/dist/nextjs/components.js +133 -4
- package/dist/nextjs/graphql.cjs +1362 -0
- package/dist/nextjs/graphql.d.cts +435 -0
- package/dist/nextjs/graphql.d.ts +435 -0
- package/dist/nextjs/graphql.js +1261 -0
- package/dist/nextjs/index.cjs +126 -6
- package/dist/nextjs/index.d.cts +53 -147
- package/dist/nextjs/index.d.ts +53 -147
- package/dist/nextjs/index.js +113 -203
- package/dist/nextjs/server-CjpELYvq.d.cts +156 -0
- package/dist/nextjs/server-CjpELYvq.d.ts +156 -0
- package/dist/nuxt/chunk-IQDSBPDN.js +417 -0
- package/dist/nuxt/graphql.cjs +1037 -0
- package/dist/nuxt/graphql.d.cts +302 -0
- package/dist/nuxt/graphql.d.ts +302 -0
- package/dist/nuxt/graphql.js +937 -0
- package/dist/nuxt/index.cjs +14 -1
- package/dist/nuxt/index.d.cts +3 -148
- package/dist/nuxt/index.d.ts +3 -148
- package/dist/nuxt/index.js +15 -391
- package/dist/nuxt/server-8v6OHbsw.d.cts +158 -0
- package/dist/nuxt/server-8v6OHbsw.d.ts +158 -0
- package/dist/pixel-DwW7cXJm.d.cts +49 -0
- package/dist/pixel-DwW7cXJm.d.ts +49 -0
- package/dist/react/components.cjs +88 -120
- package/dist/react/components.d.cts +2 -8
- package/dist/react/components.d.ts +2 -8
- package/dist/react/components.js +88 -120
- package/dist/server-Brr1UgtW.d.ts +59 -0
- package/dist/server-DJuS3YU0.d.cts +59 -0
- package/dist/sveltekit/chunk-OKYZ6HPH.js +413 -0
- package/dist/sveltekit/graphql.cjs +1043 -0
- package/dist/sveltekit/graphql.d.cts +307 -0
- package/dist/sveltekit/graphql.d.ts +307 -0
- package/dist/sveltekit/graphql.js +943 -0
- package/dist/sveltekit/index.cjs +14 -1
- package/dist/sveltekit/index.d.cts +3 -88
- package/dist/sveltekit/index.d.ts +3 -88
- package/dist/sveltekit/index.js +15 -387
- package/dist/sveltekit/server-CO847mEV.d.cts +98 -0
- package/dist/sveltekit/server-CO847mEV.d.ts +98 -0
- package/dist/{pixel-B3oQNbZ3.d.cts → types-BYH9XqmN.d.cts} +4 -58
- package/dist/{pixel-B3oQNbZ3.d.ts → types-BYH9XqmN.d.ts} +4 -58
- package/package.json +36 -1
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { DocumentNode } from 'graphql';
|
|
2
|
+
import { P as PreprHeaders, a as PreprErrorCode, A as AstroLikeContext } from './index-XT_z-RYT.cjs';
|
|
3
|
+
export { i as isPersonalizedResponse } from './index-XT_z-RYT.cjs';
|
|
4
|
+
|
|
5
|
+
/** Prepr's variant id for visitors outside every targeted segment. */
|
|
6
|
+
declare const PREPR_DEFAULT_VARIANT = "ALL_OTHER_USERS";
|
|
7
|
+
|
|
8
|
+
/** The variant ids Prepr chose for one visitor, per personalization group. */
|
|
9
|
+
type PreprDecisions = ReadonlyMap<string, readonly string[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Variant ids per group from a decision response, de-duplicated and in
|
|
12
|
+
* Prepr's order. A visitor in several segments can get more than one variant
|
|
13
|
+
* of the same group, so each entry is a list.
|
|
14
|
+
*/
|
|
15
|
+
declare function decisionsFrom(data: unknown): PreprDecisions;
|
|
16
|
+
interface ResolveVariantsOptions {
|
|
17
|
+
/**
|
|
18
|
+
* The visitor's per-group variants (from a decision query). Without it,
|
|
19
|
+
* personalization groups show their default variant.
|
|
20
|
+
*/
|
|
21
|
+
decisions?: PreprDecisions;
|
|
22
|
+
/** The visitor's A/B bucket. Without it, A/B groups use the decision, then `A`. */
|
|
23
|
+
bucket?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Keeps, in every list of a variants query result, only the variants this
|
|
27
|
+
* visitor gets, at any depth (page stacks, nested stacks, personalized
|
|
28
|
+
* buttons). Items outside a group are kept as they are.
|
|
29
|
+
*/
|
|
30
|
+
declare function resolveVariants<T>(data: T, options?: ResolveVariantsOptions): T;
|
|
31
|
+
|
|
32
|
+
interface FieldInfo {
|
|
33
|
+
/** Named type of the field, without list/non-null wrappers. */
|
|
34
|
+
type: string;
|
|
35
|
+
/** The field accepts Prepr's `personalize` argument (a stack). */
|
|
36
|
+
personalizable: boolean;
|
|
37
|
+
}
|
|
38
|
+
interface TypeInfo {
|
|
39
|
+
fields: Record<string, FieldInfo>;
|
|
40
|
+
/** Members of a union or implementations of an interface. */
|
|
41
|
+
possibleTypes: string[];
|
|
42
|
+
hasContext: boolean;
|
|
43
|
+
}
|
|
44
|
+
/** The slice of the schema the variant transforms need. */
|
|
45
|
+
interface PreprSchemaInfo {
|
|
46
|
+
queryType: string;
|
|
47
|
+
types: Record<string, TypeInfo>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** A run of stack items that renders the same way: see {@link splitStack}. */
|
|
51
|
+
interface PreprStackBlock<T> {
|
|
52
|
+
key: string;
|
|
53
|
+
items: T[];
|
|
54
|
+
/**
|
|
55
|
+
* Rendered position of the block's first item: a group (whichever variant
|
|
56
|
+
* shows) takes one position, any other item one each. Use it for anything
|
|
57
|
+
* that depends on page position, like which section owns the h1.
|
|
58
|
+
*/
|
|
59
|
+
index: number;
|
|
60
|
+
/**
|
|
61
|
+
* Some item in the block (or nested inside one) is a segment variant, so
|
|
62
|
+
* the block depends on the visitor and is decided per request.
|
|
63
|
+
*/
|
|
64
|
+
personalized: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Some item in the block (or nested inside one) is an A/B variant. Without
|
|
67
|
+
* a known bucket, such a block renders once per bucket and the visitor's
|
|
68
|
+
* bucket is picked in the browser before first paint.
|
|
69
|
+
*/
|
|
70
|
+
abTest: boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Splits a variants-query stack into blocks. Each personalization or A/B
|
|
74
|
+
* group becomes one block (a variant can hold a different number of items
|
|
75
|
+
* than the default); consecutive items that never vary are merged.
|
|
76
|
+
*/
|
|
77
|
+
declare function splitStack<T>(items: readonly T[]): PreprStackBlock<T>[];
|
|
78
|
+
|
|
79
|
+
/** The attribute Prepr's tracking pixel reads impressions and conversions from. */
|
|
80
|
+
interface PreprVariantProps {
|
|
81
|
+
'data-prepr-variant-key'?: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Attributes that let Prepr's tracking pixel count impressions of this item's
|
|
85
|
+
* variant, for an item from a query run with `variants: true`. Spread them on
|
|
86
|
+
* the element that shows the item; an item outside any personalization or A/B
|
|
87
|
+
* group gets none.
|
|
88
|
+
*
|
|
89
|
+
* Items rendered by the Next.js `PreprStack` are tagged for you. Reach for this
|
|
90
|
+
* for items nested inside them (cards, buttons, models in a section) and in
|
|
91
|
+
* frameworks without `PreprStack`.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* <article {...preprVariantProps(card)}>…</article>
|
|
95
|
+
*/
|
|
96
|
+
declare function preprVariantProps(item: unknown): PreprVariantProps;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The schema facts the query rewrites need, from `loadPreprSchema`. Pass it
|
|
100
|
+
* along; its shape is not part of the public API.
|
|
101
|
+
*/
|
|
102
|
+
type PreprSchema = PreprSchemaInfo;
|
|
103
|
+
/**
|
|
104
|
+
* Your query, asking for every personalization and A/B variant: what
|
|
105
|
+
* `query(..., { variants: true })` sends, as a string for your own GraphQL
|
|
106
|
+
* client. The result is the same for every visitor, so cache it like any
|
|
107
|
+
* other content query, and render it with `resolveVariants` or `PreprStack`.
|
|
108
|
+
*
|
|
109
|
+
* A query without personalizable fields comes back unchanged (minified).
|
|
110
|
+
*/
|
|
111
|
+
declare function toVariantsQuery(document: PreprDocument<unknown, unknown> | string, schema: PreprSchema): string;
|
|
112
|
+
/**
|
|
113
|
+
* The per-visitor decision query for the same query: send it with the
|
|
114
|
+
* visitor's Prepr headers, never cached, and pass the response's `data` to
|
|
115
|
+
* `decisionsFrom`.
|
|
116
|
+
*
|
|
117
|
+
* Pass the variants result as `from` whenever you have it: the query then
|
|
118
|
+
* asks only about the lists that hold segment groups on this page, which is
|
|
119
|
+
* a few hundred bytes instead of the whole page and markedly faster for a
|
|
120
|
+
* visitor Prepr has not seen before. Without `from` it asks about every
|
|
121
|
+
* personalizable list. `topLevelOnly` stops at the first personalizable list
|
|
122
|
+
* on each path, for middleware that decides only the top of a stack.
|
|
123
|
+
*
|
|
124
|
+
* Null when there is nothing to decide: send no request then.
|
|
125
|
+
*/
|
|
126
|
+
declare function toDecisionQuery(document: PreprDocument<unknown, unknown> | string, schema: PreprSchema, options?: {
|
|
127
|
+
from?: unknown;
|
|
128
|
+
topLevelOnly?: boolean;
|
|
129
|
+
}): string | null;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* A GraphQL document accepted by `query`: a plain string, graphql-codegen's
|
|
133
|
+
* `TypedDocumentString` (`documentMode: 'string'`), or any `DocumentNode`,
|
|
134
|
+
* including codegen's default `TypedDocumentNode` output.
|
|
135
|
+
*
|
|
136
|
+
* The phantom `__apiType` field is how codegen attaches result and variable
|
|
137
|
+
* types; matching it structurally keeps `@graphql-typed-document-node/core`
|
|
138
|
+
* out of this package.
|
|
139
|
+
*/
|
|
140
|
+
type PreprDocument<TResult, TVariables> = string | ({
|
|
141
|
+
__apiType?: (variables: TVariables) => TResult;
|
|
142
|
+
} & (String | DocumentNode));
|
|
143
|
+
/**
|
|
144
|
+
* How stega markers are stripped from the response:
|
|
145
|
+
* - `'urls'`: only from values under URL-like keys (`url`, `slug`, `link`,
|
|
146
|
+
* `href`), where markers break links. Text keeps its markers for
|
|
147
|
+
* click-to-edit.
|
|
148
|
+
* - `'all'`: from every string.
|
|
149
|
+
* - `'none'`: never.
|
|
150
|
+
*/
|
|
151
|
+
type PreprStegaMode = 'urls' | 'all' | 'none';
|
|
152
|
+
interface PreprClientOptions {
|
|
153
|
+
/** Full Prepr GraphQL URL, `https://graphql.prepr.io/<token>`. */
|
|
154
|
+
url: string;
|
|
155
|
+
/**
|
|
156
|
+
* Fetch implementation. Defaults to the global `fetch`, read at call time so
|
|
157
|
+
* framework-patched versions (such as Next.js's) are used.
|
|
158
|
+
*/
|
|
159
|
+
fetch?: typeof fetch;
|
|
160
|
+
/**
|
|
161
|
+
* Preview mode: every query skips the HTTP cache so editors see each edit,
|
|
162
|
+
* and stega defaults to `'urls'` so click-to-edit keeps working.
|
|
163
|
+
*/
|
|
164
|
+
preview?: boolean;
|
|
165
|
+
/** Default: `'urls'` when `preview` is true, otherwise `'all'`. */
|
|
166
|
+
stega?: PreprStegaMode;
|
|
167
|
+
/**
|
|
168
|
+
* Send queries as a GET with the request body base64-encoded in a
|
|
169
|
+
* `Fastly-Query` header, which Prepr's edge serves from the nearest point
|
|
170
|
+
* of presence (about half the latency of a POST in our measurements).
|
|
171
|
+
* Queries too large for a header still go as a POST. Off by default: it
|
|
172
|
+
* relies on Prepr edge behavior that is not part of the documented API.
|
|
173
|
+
*/
|
|
174
|
+
fastlyQuery?: boolean;
|
|
175
|
+
/**
|
|
176
|
+
* @internal Fetch options for the one-time schema introspection, so a
|
|
177
|
+
* framework wrapper can put it in its data cache.
|
|
178
|
+
*/
|
|
179
|
+
schemaInit?: RequestInit;
|
|
180
|
+
/**
|
|
181
|
+
* Headers sent with every request, such as a header a proxy in front of the
|
|
182
|
+
* API requires. They are fixed when the client is created, so they cannot
|
|
183
|
+
* vary per visitor and do not stop responses from being cached. Put
|
|
184
|
+
* per-request values in the query's `headers` instead.
|
|
185
|
+
*/
|
|
186
|
+
headers?: HeadersInit;
|
|
187
|
+
}
|
|
188
|
+
interface PreprQueryOptions {
|
|
189
|
+
/**
|
|
190
|
+
* Prepr headers to forward, typically from `getPreprHeaders`. Passing any
|
|
191
|
+
* headers object, even an empty one, makes the request `no-store`: the
|
|
192
|
+
* response may be personalized and must not be shared between visitors.
|
|
193
|
+
*/
|
|
194
|
+
headers?: PreprHeaders | HeadersInit;
|
|
195
|
+
/**
|
|
196
|
+
* Extra fetch options such as `signal`. `method` and `body` are set by the
|
|
197
|
+
* client. `init.headers` are merged like `headers`, and also make the
|
|
198
|
+
* request `no-store`.
|
|
199
|
+
*/
|
|
200
|
+
init?: RequestInit;
|
|
201
|
+
/** Per-query fetch, overriding the client's (e.g. SvelteKit's `event.fetch`). */
|
|
202
|
+
fetch?: typeof fetch;
|
|
203
|
+
/**
|
|
204
|
+
* Fetch every variant instead of the visitor's: `personalize: false` is
|
|
205
|
+
* added to every personalizable field in the query, at any depth, and each
|
|
206
|
+
* item gets its `_context` (under `_preprContext`). The result is the same
|
|
207
|
+
* for every visitor, so it can be cached; pass it to `resolveVariants` with
|
|
208
|
+
* the visitor's `decide()` result to get what they see.
|
|
209
|
+
*
|
|
210
|
+
* The client learns which fields are personalizable from one schema
|
|
211
|
+
* introspection request, made on first use.
|
|
212
|
+
*/
|
|
213
|
+
variants?: boolean;
|
|
214
|
+
}
|
|
215
|
+
/** Options for `decide()`. */
|
|
216
|
+
interface PreprDecideOptions extends Omit<PreprQueryOptions, 'variants'> {
|
|
217
|
+
/**
|
|
218
|
+
* The `variants: true` result this decision is for (the whole `data`
|
|
219
|
+
* object). The decision query then asks only about the fields that hold
|
|
220
|
+
* segment personalization groups, and is skipped entirely when there are
|
|
221
|
+
* none, e.g. on pages with only A/B tests or no personalization.
|
|
222
|
+
*/
|
|
223
|
+
from?: unknown;
|
|
224
|
+
/**
|
|
225
|
+
* @internal Ask only about the first personalizable list on each path,
|
|
226
|
+
* without `from`: what middleware needs for groups at the top of a stack.
|
|
227
|
+
*/
|
|
228
|
+
topLevelOnly?: boolean;
|
|
229
|
+
}
|
|
230
|
+
interface PreprQueryResult<TResult> {
|
|
231
|
+
data: TResult;
|
|
232
|
+
/**
|
|
233
|
+
* True when Prepr reports, through the response's `Vary` header, that the
|
|
234
|
+
* queried fields hold segment variants or A/B tests.
|
|
235
|
+
*/
|
|
236
|
+
personalized: boolean;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Query options for frameworks without an implicit request scope.
|
|
241
|
+
* `personalize: true` requires the request `event`; the compiler enforces it.
|
|
242
|
+
*/
|
|
243
|
+
type PreprEventQueryOptions<TEvent> = PreprQueryOptions & ({
|
|
244
|
+
personalize?: false;
|
|
245
|
+
event?: TEvent;
|
|
246
|
+
} | {
|
|
247
|
+
personalize: true;
|
|
248
|
+
event: TEvent;
|
|
249
|
+
});
|
|
250
|
+
interface PreprEventClient<TEvent> {
|
|
251
|
+
/**
|
|
252
|
+
* Run a GraphQL query against Prepr. With `personalize: true`, the Prepr
|
|
253
|
+
* headers of `event` are forwarded and the request is `no-store`; without
|
|
254
|
+
* it the request is identical for every visitor.
|
|
255
|
+
*
|
|
256
|
+
* @throws PreprError — as `PreprClient.query`, plus `CONTEXT_ERROR` when
|
|
257
|
+
* `personalize` is true and no `event` is passed.
|
|
258
|
+
*/
|
|
259
|
+
query<TResult, TVariables>(document: PreprDocument<TResult, TVariables>, variables?: TVariables, options?: PreprEventQueryOptions<TEvent>): Promise<PreprQueryResult<TResult>>;
|
|
260
|
+
/**
|
|
261
|
+
* Which variant of each group this visitor gets, for the query you render
|
|
262
|
+
* with `variants: true`. Forwards the Prepr headers of `event`.
|
|
263
|
+
*
|
|
264
|
+
* @throws PreprError — `CONTEXT_ERROR` without an `event`.
|
|
265
|
+
*/
|
|
266
|
+
decide<TVariables>(document: PreprDocument<unknown, TVariables>, variables: TVariables | undefined, options: PreprDecideOptions & {
|
|
267
|
+
event: TEvent;
|
|
268
|
+
}): Promise<PreprDecisions>;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Loads what `toVariantsQuery` and `toDecisionQuery` need to know about your
|
|
273
|
+
* Prepr schema (which fields take `personalize`, which types can hold
|
|
274
|
+
* variants) with one introspection request, kept in memory per URL. For a
|
|
275
|
+
* site that uses its own GraphQL client; `createPreprClient` does this
|
|
276
|
+
* itself.
|
|
277
|
+
*
|
|
278
|
+
* Load it once at startup or lazily before the first rewrite. Schema changes
|
|
279
|
+
* in Prepr take effect after a restart or redeploy.
|
|
280
|
+
*
|
|
281
|
+
* @throws PreprError when the URL is invalid or the request fails; the URL,
|
|
282
|
+
* which holds your access token, is never part of the message.
|
|
283
|
+
*/
|
|
284
|
+
declare function loadPreprSchema(url: string, options?: {
|
|
285
|
+
fetch?: typeof fetch;
|
|
286
|
+
}): Promise<PreprSchemaInfo>;
|
|
287
|
+
|
|
288
|
+
/** Error thrown by the token helpers and the segments fetch. */
|
|
289
|
+
declare class PreprError extends Error {
|
|
290
|
+
readonly code: PreprErrorCode;
|
|
291
|
+
readonly context?: string | undefined;
|
|
292
|
+
readonly originalError?: Error | undefined;
|
|
293
|
+
constructor(message: string, code: PreprErrorCode, context?: string | undefined, originalError?: Error | undefined);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Prepr GraphQL client for Astro. Pass `Astro` (in a page or component) or
|
|
298
|
+
* the endpoint or middleware context as `event`. With `personalize: true`,
|
|
299
|
+
* the Prepr headers `onPreprRequest` set on the request are forwarded.
|
|
300
|
+
*
|
|
301
|
+
* Requires the `graphql` package, which graphql-codegen already installs.
|
|
302
|
+
*/
|
|
303
|
+
declare function createPreprClient(options: PreprClientOptions): PreprEventClient<AstroLikeContext>;
|
|
304
|
+
|
|
305
|
+
export { AstroLikeContext, PREPR_DEFAULT_VARIANT, type PreprClientOptions, type PreprDecideOptions, type PreprDecisions, type PreprDocument, PreprError, type PreprEventClient, type PreprEventQueryOptions, type PreprQueryResult, type PreprSchema, type PreprStackBlock, type PreprStegaMode, type PreprVariantProps, type ResolveVariantsOptions, createPreprClient, decisionsFrom, loadPreprSchema, preprVariantProps, resolveVariants, splitStack, toDecisionQuery, toVariantsQuery };
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { DocumentNode } from 'graphql';
|
|
2
|
+
import { P as PreprHeaders, a as PreprErrorCode, A as AstroLikeContext } from './index-XT_z-RYT.js';
|
|
3
|
+
export { i as isPersonalizedResponse } from './index-XT_z-RYT.js';
|
|
4
|
+
|
|
5
|
+
/** Prepr's variant id for visitors outside every targeted segment. */
|
|
6
|
+
declare const PREPR_DEFAULT_VARIANT = "ALL_OTHER_USERS";
|
|
7
|
+
|
|
8
|
+
/** The variant ids Prepr chose for one visitor, per personalization group. */
|
|
9
|
+
type PreprDecisions = ReadonlyMap<string, readonly string[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Variant ids per group from a decision response, de-duplicated and in
|
|
12
|
+
* Prepr's order. A visitor in several segments can get more than one variant
|
|
13
|
+
* of the same group, so each entry is a list.
|
|
14
|
+
*/
|
|
15
|
+
declare function decisionsFrom(data: unknown): PreprDecisions;
|
|
16
|
+
interface ResolveVariantsOptions {
|
|
17
|
+
/**
|
|
18
|
+
* The visitor's per-group variants (from a decision query). Without it,
|
|
19
|
+
* personalization groups show their default variant.
|
|
20
|
+
*/
|
|
21
|
+
decisions?: PreprDecisions;
|
|
22
|
+
/** The visitor's A/B bucket. Without it, A/B groups use the decision, then `A`. */
|
|
23
|
+
bucket?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Keeps, in every list of a variants query result, only the variants this
|
|
27
|
+
* visitor gets, at any depth (page stacks, nested stacks, personalized
|
|
28
|
+
* buttons). Items outside a group are kept as they are.
|
|
29
|
+
*/
|
|
30
|
+
declare function resolveVariants<T>(data: T, options?: ResolveVariantsOptions): T;
|
|
31
|
+
|
|
32
|
+
interface FieldInfo {
|
|
33
|
+
/** Named type of the field, without list/non-null wrappers. */
|
|
34
|
+
type: string;
|
|
35
|
+
/** The field accepts Prepr's `personalize` argument (a stack). */
|
|
36
|
+
personalizable: boolean;
|
|
37
|
+
}
|
|
38
|
+
interface TypeInfo {
|
|
39
|
+
fields: Record<string, FieldInfo>;
|
|
40
|
+
/** Members of a union or implementations of an interface. */
|
|
41
|
+
possibleTypes: string[];
|
|
42
|
+
hasContext: boolean;
|
|
43
|
+
}
|
|
44
|
+
/** The slice of the schema the variant transforms need. */
|
|
45
|
+
interface PreprSchemaInfo {
|
|
46
|
+
queryType: string;
|
|
47
|
+
types: Record<string, TypeInfo>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** A run of stack items that renders the same way: see {@link splitStack}. */
|
|
51
|
+
interface PreprStackBlock<T> {
|
|
52
|
+
key: string;
|
|
53
|
+
items: T[];
|
|
54
|
+
/**
|
|
55
|
+
* Rendered position of the block's first item: a group (whichever variant
|
|
56
|
+
* shows) takes one position, any other item one each. Use it for anything
|
|
57
|
+
* that depends on page position, like which section owns the h1.
|
|
58
|
+
*/
|
|
59
|
+
index: number;
|
|
60
|
+
/**
|
|
61
|
+
* Some item in the block (or nested inside one) is a segment variant, so
|
|
62
|
+
* the block depends on the visitor and is decided per request.
|
|
63
|
+
*/
|
|
64
|
+
personalized: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Some item in the block (or nested inside one) is an A/B variant. Without
|
|
67
|
+
* a known bucket, such a block renders once per bucket and the visitor's
|
|
68
|
+
* bucket is picked in the browser before first paint.
|
|
69
|
+
*/
|
|
70
|
+
abTest: boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Splits a variants-query stack into blocks. Each personalization or A/B
|
|
74
|
+
* group becomes one block (a variant can hold a different number of items
|
|
75
|
+
* than the default); consecutive items that never vary are merged.
|
|
76
|
+
*/
|
|
77
|
+
declare function splitStack<T>(items: readonly T[]): PreprStackBlock<T>[];
|
|
78
|
+
|
|
79
|
+
/** The attribute Prepr's tracking pixel reads impressions and conversions from. */
|
|
80
|
+
interface PreprVariantProps {
|
|
81
|
+
'data-prepr-variant-key'?: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Attributes that let Prepr's tracking pixel count impressions of this item's
|
|
85
|
+
* variant, for an item from a query run with `variants: true`. Spread them on
|
|
86
|
+
* the element that shows the item; an item outside any personalization or A/B
|
|
87
|
+
* group gets none.
|
|
88
|
+
*
|
|
89
|
+
* Items rendered by the Next.js `PreprStack` are tagged for you. Reach for this
|
|
90
|
+
* for items nested inside them (cards, buttons, models in a section) and in
|
|
91
|
+
* frameworks without `PreprStack`.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* <article {...preprVariantProps(card)}>…</article>
|
|
95
|
+
*/
|
|
96
|
+
declare function preprVariantProps(item: unknown): PreprVariantProps;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The schema facts the query rewrites need, from `loadPreprSchema`. Pass it
|
|
100
|
+
* along; its shape is not part of the public API.
|
|
101
|
+
*/
|
|
102
|
+
type PreprSchema = PreprSchemaInfo;
|
|
103
|
+
/**
|
|
104
|
+
* Your query, asking for every personalization and A/B variant: what
|
|
105
|
+
* `query(..., { variants: true })` sends, as a string for your own GraphQL
|
|
106
|
+
* client. The result is the same for every visitor, so cache it like any
|
|
107
|
+
* other content query, and render it with `resolveVariants` or `PreprStack`.
|
|
108
|
+
*
|
|
109
|
+
* A query without personalizable fields comes back unchanged (minified).
|
|
110
|
+
*/
|
|
111
|
+
declare function toVariantsQuery(document: PreprDocument<unknown, unknown> | string, schema: PreprSchema): string;
|
|
112
|
+
/**
|
|
113
|
+
* The per-visitor decision query for the same query: send it with the
|
|
114
|
+
* visitor's Prepr headers, never cached, and pass the response's `data` to
|
|
115
|
+
* `decisionsFrom`.
|
|
116
|
+
*
|
|
117
|
+
* Pass the variants result as `from` whenever you have it: the query then
|
|
118
|
+
* asks only about the lists that hold segment groups on this page, which is
|
|
119
|
+
* a few hundred bytes instead of the whole page and markedly faster for a
|
|
120
|
+
* visitor Prepr has not seen before. Without `from` it asks about every
|
|
121
|
+
* personalizable list. `topLevelOnly` stops at the first personalizable list
|
|
122
|
+
* on each path, for middleware that decides only the top of a stack.
|
|
123
|
+
*
|
|
124
|
+
* Null when there is nothing to decide: send no request then.
|
|
125
|
+
*/
|
|
126
|
+
declare function toDecisionQuery(document: PreprDocument<unknown, unknown> | string, schema: PreprSchema, options?: {
|
|
127
|
+
from?: unknown;
|
|
128
|
+
topLevelOnly?: boolean;
|
|
129
|
+
}): string | null;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* A GraphQL document accepted by `query`: a plain string, graphql-codegen's
|
|
133
|
+
* `TypedDocumentString` (`documentMode: 'string'`), or any `DocumentNode`,
|
|
134
|
+
* including codegen's default `TypedDocumentNode` output.
|
|
135
|
+
*
|
|
136
|
+
* The phantom `__apiType` field is how codegen attaches result and variable
|
|
137
|
+
* types; matching it structurally keeps `@graphql-typed-document-node/core`
|
|
138
|
+
* out of this package.
|
|
139
|
+
*/
|
|
140
|
+
type PreprDocument<TResult, TVariables> = string | ({
|
|
141
|
+
__apiType?: (variables: TVariables) => TResult;
|
|
142
|
+
} & (String | DocumentNode));
|
|
143
|
+
/**
|
|
144
|
+
* How stega markers are stripped from the response:
|
|
145
|
+
* - `'urls'`: only from values under URL-like keys (`url`, `slug`, `link`,
|
|
146
|
+
* `href`), where markers break links. Text keeps its markers for
|
|
147
|
+
* click-to-edit.
|
|
148
|
+
* - `'all'`: from every string.
|
|
149
|
+
* - `'none'`: never.
|
|
150
|
+
*/
|
|
151
|
+
type PreprStegaMode = 'urls' | 'all' | 'none';
|
|
152
|
+
interface PreprClientOptions {
|
|
153
|
+
/** Full Prepr GraphQL URL, `https://graphql.prepr.io/<token>`. */
|
|
154
|
+
url: string;
|
|
155
|
+
/**
|
|
156
|
+
* Fetch implementation. Defaults to the global `fetch`, read at call time so
|
|
157
|
+
* framework-patched versions (such as Next.js's) are used.
|
|
158
|
+
*/
|
|
159
|
+
fetch?: typeof fetch;
|
|
160
|
+
/**
|
|
161
|
+
* Preview mode: every query skips the HTTP cache so editors see each edit,
|
|
162
|
+
* and stega defaults to `'urls'` so click-to-edit keeps working.
|
|
163
|
+
*/
|
|
164
|
+
preview?: boolean;
|
|
165
|
+
/** Default: `'urls'` when `preview` is true, otherwise `'all'`. */
|
|
166
|
+
stega?: PreprStegaMode;
|
|
167
|
+
/**
|
|
168
|
+
* Send queries as a GET with the request body base64-encoded in a
|
|
169
|
+
* `Fastly-Query` header, which Prepr's edge serves from the nearest point
|
|
170
|
+
* of presence (about half the latency of a POST in our measurements).
|
|
171
|
+
* Queries too large for a header still go as a POST. Off by default: it
|
|
172
|
+
* relies on Prepr edge behavior that is not part of the documented API.
|
|
173
|
+
*/
|
|
174
|
+
fastlyQuery?: boolean;
|
|
175
|
+
/**
|
|
176
|
+
* @internal Fetch options for the one-time schema introspection, so a
|
|
177
|
+
* framework wrapper can put it in its data cache.
|
|
178
|
+
*/
|
|
179
|
+
schemaInit?: RequestInit;
|
|
180
|
+
/**
|
|
181
|
+
* Headers sent with every request, such as a header a proxy in front of the
|
|
182
|
+
* API requires. They are fixed when the client is created, so they cannot
|
|
183
|
+
* vary per visitor and do not stop responses from being cached. Put
|
|
184
|
+
* per-request values in the query's `headers` instead.
|
|
185
|
+
*/
|
|
186
|
+
headers?: HeadersInit;
|
|
187
|
+
}
|
|
188
|
+
interface PreprQueryOptions {
|
|
189
|
+
/**
|
|
190
|
+
* Prepr headers to forward, typically from `getPreprHeaders`. Passing any
|
|
191
|
+
* headers object, even an empty one, makes the request `no-store`: the
|
|
192
|
+
* response may be personalized and must not be shared between visitors.
|
|
193
|
+
*/
|
|
194
|
+
headers?: PreprHeaders | HeadersInit;
|
|
195
|
+
/**
|
|
196
|
+
* Extra fetch options such as `signal`. `method` and `body` are set by the
|
|
197
|
+
* client. `init.headers` are merged like `headers`, and also make the
|
|
198
|
+
* request `no-store`.
|
|
199
|
+
*/
|
|
200
|
+
init?: RequestInit;
|
|
201
|
+
/** Per-query fetch, overriding the client's (e.g. SvelteKit's `event.fetch`). */
|
|
202
|
+
fetch?: typeof fetch;
|
|
203
|
+
/**
|
|
204
|
+
* Fetch every variant instead of the visitor's: `personalize: false` is
|
|
205
|
+
* added to every personalizable field in the query, at any depth, and each
|
|
206
|
+
* item gets its `_context` (under `_preprContext`). The result is the same
|
|
207
|
+
* for every visitor, so it can be cached; pass it to `resolveVariants` with
|
|
208
|
+
* the visitor's `decide()` result to get what they see.
|
|
209
|
+
*
|
|
210
|
+
* The client learns which fields are personalizable from one schema
|
|
211
|
+
* introspection request, made on first use.
|
|
212
|
+
*/
|
|
213
|
+
variants?: boolean;
|
|
214
|
+
}
|
|
215
|
+
/** Options for `decide()`. */
|
|
216
|
+
interface PreprDecideOptions extends Omit<PreprQueryOptions, 'variants'> {
|
|
217
|
+
/**
|
|
218
|
+
* The `variants: true` result this decision is for (the whole `data`
|
|
219
|
+
* object). The decision query then asks only about the fields that hold
|
|
220
|
+
* segment personalization groups, and is skipped entirely when there are
|
|
221
|
+
* none, e.g. on pages with only A/B tests or no personalization.
|
|
222
|
+
*/
|
|
223
|
+
from?: unknown;
|
|
224
|
+
/**
|
|
225
|
+
* @internal Ask only about the first personalizable list on each path,
|
|
226
|
+
* without `from`: what middleware needs for groups at the top of a stack.
|
|
227
|
+
*/
|
|
228
|
+
topLevelOnly?: boolean;
|
|
229
|
+
}
|
|
230
|
+
interface PreprQueryResult<TResult> {
|
|
231
|
+
data: TResult;
|
|
232
|
+
/**
|
|
233
|
+
* True when Prepr reports, through the response's `Vary` header, that the
|
|
234
|
+
* queried fields hold segment variants or A/B tests.
|
|
235
|
+
*/
|
|
236
|
+
personalized: boolean;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Query options for frameworks without an implicit request scope.
|
|
241
|
+
* `personalize: true` requires the request `event`; the compiler enforces it.
|
|
242
|
+
*/
|
|
243
|
+
type PreprEventQueryOptions<TEvent> = PreprQueryOptions & ({
|
|
244
|
+
personalize?: false;
|
|
245
|
+
event?: TEvent;
|
|
246
|
+
} | {
|
|
247
|
+
personalize: true;
|
|
248
|
+
event: TEvent;
|
|
249
|
+
});
|
|
250
|
+
interface PreprEventClient<TEvent> {
|
|
251
|
+
/**
|
|
252
|
+
* Run a GraphQL query against Prepr. With `personalize: true`, the Prepr
|
|
253
|
+
* headers of `event` are forwarded and the request is `no-store`; without
|
|
254
|
+
* it the request is identical for every visitor.
|
|
255
|
+
*
|
|
256
|
+
* @throws PreprError — as `PreprClient.query`, plus `CONTEXT_ERROR` when
|
|
257
|
+
* `personalize` is true and no `event` is passed.
|
|
258
|
+
*/
|
|
259
|
+
query<TResult, TVariables>(document: PreprDocument<TResult, TVariables>, variables?: TVariables, options?: PreprEventQueryOptions<TEvent>): Promise<PreprQueryResult<TResult>>;
|
|
260
|
+
/**
|
|
261
|
+
* Which variant of each group this visitor gets, for the query you render
|
|
262
|
+
* with `variants: true`. Forwards the Prepr headers of `event`.
|
|
263
|
+
*
|
|
264
|
+
* @throws PreprError — `CONTEXT_ERROR` without an `event`.
|
|
265
|
+
*/
|
|
266
|
+
decide<TVariables>(document: PreprDocument<unknown, TVariables>, variables: TVariables | undefined, options: PreprDecideOptions & {
|
|
267
|
+
event: TEvent;
|
|
268
|
+
}): Promise<PreprDecisions>;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Loads what `toVariantsQuery` and `toDecisionQuery` need to know about your
|
|
273
|
+
* Prepr schema (which fields take `personalize`, which types can hold
|
|
274
|
+
* variants) with one introspection request, kept in memory per URL. For a
|
|
275
|
+
* site that uses its own GraphQL client; `createPreprClient` does this
|
|
276
|
+
* itself.
|
|
277
|
+
*
|
|
278
|
+
* Load it once at startup or lazily before the first rewrite. Schema changes
|
|
279
|
+
* in Prepr take effect after a restart or redeploy.
|
|
280
|
+
*
|
|
281
|
+
* @throws PreprError when the URL is invalid or the request fails; the URL,
|
|
282
|
+
* which holds your access token, is never part of the message.
|
|
283
|
+
*/
|
|
284
|
+
declare function loadPreprSchema(url: string, options?: {
|
|
285
|
+
fetch?: typeof fetch;
|
|
286
|
+
}): Promise<PreprSchemaInfo>;
|
|
287
|
+
|
|
288
|
+
/** Error thrown by the token helpers and the segments fetch. */
|
|
289
|
+
declare class PreprError extends Error {
|
|
290
|
+
readonly code: PreprErrorCode;
|
|
291
|
+
readonly context?: string | undefined;
|
|
292
|
+
readonly originalError?: Error | undefined;
|
|
293
|
+
constructor(message: string, code: PreprErrorCode, context?: string | undefined, originalError?: Error | undefined);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Prepr GraphQL client for Astro. Pass `Astro` (in a page or component) or
|
|
298
|
+
* the endpoint or middleware context as `event`. With `personalize: true`,
|
|
299
|
+
* the Prepr headers `onPreprRequest` set on the request are forwarded.
|
|
300
|
+
*
|
|
301
|
+
* Requires the `graphql` package, which graphql-codegen already installs.
|
|
302
|
+
*/
|
|
303
|
+
declare function createPreprClient(options: PreprClientOptions): PreprEventClient<AstroLikeContext>;
|
|
304
|
+
|
|
305
|
+
export { AstroLikeContext, PREPR_DEFAULT_VARIANT, type PreprClientOptions, type PreprDecideOptions, type PreprDecisions, type PreprDocument, PreprError, type PreprEventClient, type PreprEventQueryOptions, type PreprQueryResult, type PreprSchema, type PreprStackBlock, type PreprStegaMode, type PreprVariantProps, type ResolveVariantsOptions, createPreprClient, decisionsFrom, loadPreprSchema, preprVariantProps, resolveVariants, splitStack, toDecisionQuery, toVariantsQuery };
|