@preprio/toolkit 0.6.0-alpha.0 → 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.
Files changed (52) hide show
  1. package/README.md +107 -0
  2. package/dist/astro/{chunk-3UVUDDNY.js → chunk-O7N6GPAH.js} +1 -1
  3. package/dist/astro/graphql.cjs +96 -49
  4. package/dist/astro/graphql.d.cts +75 -1
  5. package/dist/astro/graphql.d.ts +75 -1
  6. package/dist/astro/graphql.js +92 -49
  7. package/dist/astro/index.cjs +1 -1
  8. package/dist/astro/index.js +1 -1
  9. package/dist/{chunk-YR7P4IWE.js → chunk-3JLWZQ37.js} +1 -9
  10. package/dist/chunk-3NCEVJJ3.js +10 -0
  11. package/dist/{chunk-DGZA7KX7.js → chunk-S5RWVMDJ.js} +0 -24
  12. package/dist/chunk-TBKSBXGH.js +452 -0
  13. package/dist/{chunk-BJ2LBLWO.js → chunk-VI6QZTBM.js} +6 -4
  14. package/dist/chunk-YWIKKWBR.js +26 -0
  15. package/dist/graphql/codegen.cjs +510 -0
  16. package/dist/graphql/codegen.d.cts +23 -0
  17. package/dist/graphql/codegen.d.ts +23 -0
  18. package/dist/graphql/codegen.js +99 -0
  19. package/dist/graphql.cjs +96 -49
  20. package/dist/graphql.d.cts +75 -1
  21. package/dist/graphql.d.ts +75 -1
  22. package/dist/graphql.js +60 -428
  23. package/dist/index.cjs +1 -1
  24. package/dist/index.d.cts +1 -1
  25. package/dist/index.d.ts +1 -1
  26. package/dist/index.js +10 -6
  27. package/dist/nextjs/{chunk-U4HXENF7.js → chunk-BQ6IGSH6.js} +1 -1
  28. package/dist/nextjs/components.cjs +1 -1
  29. package/dist/nextjs/components.js +3 -2
  30. package/dist/nextjs/graphql.cjs +96 -49
  31. package/dist/nextjs/graphql.d.cts +75 -1
  32. package/dist/nextjs/graphql.d.ts +75 -1
  33. package/dist/nextjs/graphql.js +92 -49
  34. package/dist/nextjs/index.cjs +1 -1
  35. package/dist/nextjs/index.js +1 -1
  36. package/dist/nuxt/{chunk-P6ENNAEE.js → chunk-IQDSBPDN.js} +1 -1
  37. package/dist/nuxt/graphql.cjs +96 -49
  38. package/dist/nuxt/graphql.d.cts +75 -1
  39. package/dist/nuxt/graphql.d.ts +75 -1
  40. package/dist/nuxt/graphql.js +92 -49
  41. package/dist/nuxt/index.cjs +1 -1
  42. package/dist/nuxt/index.js +1 -1
  43. package/dist/react/components.cjs +1 -1
  44. package/dist/react/components.js +1 -1
  45. package/dist/sveltekit/{chunk-FSARVMG5.js → chunk-OKYZ6HPH.js} +1 -1
  46. package/dist/sveltekit/graphql.cjs +96 -49
  47. package/dist/sveltekit/graphql.d.cts +75 -1
  48. package/dist/sveltekit/graphql.d.ts +75 -1
  49. package/dist/sveltekit/graphql.js +92 -49
  50. package/dist/sveltekit/index.cjs +1 -1
  51. package/dist/sveltekit/index.js +1 -1
  52. package/package.json +6 -1
@@ -25,10 +25,14 @@ __export(graphql_exports, {
25
25
  PreprError: () => PreprError,
26
26
  PreprStack: () => PreprStack,
27
27
  createPreprClient: () => createPreprClient2,
28
+ decisionsFrom: () => decisionsFrom,
28
29
  isPersonalizedResponse: () => isPersonalizedResponse,
30
+ loadPreprSchema: () => loadPreprSchema,
29
31
  preprVariantProps: () => preprVariantProps,
30
32
  resolveVariants: () => resolveVariants,
31
- splitStack: () => splitStack
33
+ splitStack: () => splitStack,
34
+ toDecisionQuery: () => toDecisionQuery,
35
+ toVariantsQuery: () => toVariantsQuery
32
36
  });
33
37
  module.exports = __toCommonJS(graphql_exports);
34
38
 
@@ -566,6 +570,63 @@ function toVariantsDocument(document2, schema) {
566
570
  };
567
571
  }
568
572
 
573
+ // src/core/graphql/document.ts
574
+ var import_printer = require("graphql/language/printer.js");
575
+ var import_stripIgnoredCharacters = require("graphql/utilities/stripIgnoredCharacters.js");
576
+ var printed = /* @__PURE__ */ new WeakMap();
577
+ function isDocumentNode(value) {
578
+ return typeof value === "object" && value !== null && value.kind === "Document" && Array.isArray(value.definitions);
579
+ }
580
+ function invalidDocument(originalError) {
581
+ return new PreprError(
582
+ "Expected a GraphQL query string, TypedDocumentString or DocumentNode",
583
+ "INVALID_DOCUMENT",
584
+ "createPreprClient",
585
+ originalError
586
+ );
587
+ }
588
+ var minified = /* @__PURE__ */ new Map();
589
+ var MINIFIED_CACHE_LIMIT = 500;
590
+ function minify(query) {
591
+ const cached = minified.get(query);
592
+ if (cached !== void 0) return cached;
593
+ let result = query;
594
+ try {
595
+ result = (0, import_stripIgnoredCharacters.stripIgnoredCharacters)(query);
596
+ } catch {
597
+ }
598
+ if (minified.size < MINIFIED_CACHE_LIMIT) minified.set(query, result);
599
+ return result;
600
+ }
601
+ function resolveQuery(document2) {
602
+ if (typeof document2 === "string") return minify(document2);
603
+ if (document2 instanceof String) return minify(document2.toString());
604
+ if (!isDocumentNode(document2)) throw invalidDocument();
605
+ let query = printed.get(document2);
606
+ if (query === void 0) {
607
+ try {
608
+ query = minify((0, import_printer.print)(document2));
609
+ } catch (error) {
610
+ throw invalidDocument(error instanceof Error ? error : void 0);
611
+ }
612
+ printed.set(document2, query);
613
+ }
614
+ return query;
615
+ }
616
+
617
+ // src/core/variants/queries.ts
618
+ function toVariantsQuery(document2, schema) {
619
+ return resolveQuery(toVariantsDocument(document2, schema));
620
+ }
621
+ function toDecisionQuery(document2, schema, options = {}) {
622
+ const paths = options.from === void 0 ? void 0 : personalizationPaths(options.from);
623
+ if (paths && paths.size === 0) return null;
624
+ const decision = toDecisionDocument(document2, schema, paths, {
625
+ topLevelOnly: !paths && options.topLevelOnly
626
+ });
627
+ return decision ? resolveQuery(decision) : null;
628
+ }
629
+
569
630
  // src/core/graphql/transport.ts
570
631
  var import_stega2 = require("@vercel/stega");
571
632
 
@@ -625,50 +686,6 @@ function stegaClean(text) {
625
686
  return (0, import_stega.vercelStegaClean)(text);
626
687
  }
627
688
 
628
- // src/core/graphql/document.ts
629
- var import_printer = require("graphql/language/printer.js");
630
- var import_stripIgnoredCharacters = require("graphql/utilities/stripIgnoredCharacters.js");
631
- var printed = /* @__PURE__ */ new WeakMap();
632
- function isDocumentNode(value) {
633
- return typeof value === "object" && value !== null && value.kind === "Document" && Array.isArray(value.definitions);
634
- }
635
- function invalidDocument(originalError) {
636
- return new PreprError(
637
- "Expected a GraphQL query string, TypedDocumentString or DocumentNode",
638
- "INVALID_DOCUMENT",
639
- "createPreprClient",
640
- originalError
641
- );
642
- }
643
- var minified = /* @__PURE__ */ new Map();
644
- var MINIFIED_CACHE_LIMIT = 500;
645
- function minify(query) {
646
- const cached = minified.get(query);
647
- if (cached !== void 0) return cached;
648
- let result = query;
649
- try {
650
- result = (0, import_stripIgnoredCharacters.stripIgnoredCharacters)(query);
651
- } catch {
652
- }
653
- if (minified.size < MINIFIED_CACHE_LIMIT) minified.set(query, result);
654
- return result;
655
- }
656
- function resolveQuery(document2) {
657
- if (typeof document2 === "string") return minify(document2);
658
- if (document2 instanceof String) return minify(document2.toString());
659
- if (!isDocumentNode(document2)) throw invalidDocument();
660
- let query = printed.get(document2);
661
- if (query === void 0) {
662
- try {
663
- query = minify((0, import_printer.print)(document2));
664
- } catch (error) {
665
- throw invalidDocument(error instanceof Error ? error : void 0);
666
- }
667
- printed.set(document2, query);
668
- }
669
- return query;
670
- }
671
-
672
689
  // src/core/graphql/transport.ts
673
690
  var OPERATION_NAME = /\b(?:query|mutation|subscription)\s+([_A-Za-z][_0-9A-Za-z]*)/;
674
691
  var STEGA_RAW = new RegExp(
@@ -855,16 +872,18 @@ function isParseableUrl(url) {
855
872
  return false;
856
873
  }
857
874
  }
858
- function createPreprClient(options) {
859
- const { url } = options;
875
+ function assertPreprUrl(url, source) {
860
876
  validatePreprToken(url);
861
877
  if (!isParseableUrl(url)) {
862
878
  throw new PreprError(
863
879
  "Prepr GraphQL URL is not a valid URL",
864
880
  "INVALID_TOKEN",
865
- "createPreprClient"
881
+ source
866
882
  );
867
883
  }
884
+ }
885
+ function createPreprClient(options) {
886
+ assertPreprUrl(options.url, "createPreprClient");
868
887
  const run = createTransport(options);
869
888
  const probeVary = createVaryProbe(run, options);
870
889
  let schema;
@@ -922,6 +941,30 @@ function createPreprClient(options) {
922
941
  };
923
942
  }
924
943
 
944
+ // src/core/graphql/schema-loader.ts
945
+ var schemas = /* @__PURE__ */ new Map();
946
+ async function loadPreprSchema(url, options = {}) {
947
+ assertPreprUrl(url, "loadPreprSchema");
948
+ let schema = schemas.get(url);
949
+ if (!schema) {
950
+ const run = createTransport({ url, fetch: options.fetch, stega: "none" });
951
+ schema = run(
952
+ PREPR_SCHEMA_QUERY
953
+ ).then((result) => toSchemaInfo(result.data)).catch((error) => {
954
+ schemas.delete(url);
955
+ if (error instanceof PreprError) throw error;
956
+ throw new PreprError(
957
+ "Prepr schema response is not an introspection result",
958
+ "INVALID_RESPONSE",
959
+ "loadPreprSchema",
960
+ error instanceof Error ? error : void 0
961
+ );
962
+ });
963
+ schemas.set(url, schema);
964
+ }
965
+ return schema;
966
+ }
967
+
925
968
  // src/nextjs/decisions.ts
926
969
  var PREPR_DECISIONS_COOKIE = "prepr_decisions";
927
970
  var DECISIONS_MAX_GROUPS = 40;
@@ -1308,8 +1351,12 @@ function createPreprClient2(options) {
1308
1351
  PreprError,
1309
1352
  PreprStack,
1310
1353
  createPreprClient,
1354
+ decisionsFrom,
1311
1355
  isPersonalizedResponse,
1356
+ loadPreprSchema,
1312
1357
  preprVariantProps,
1313
1358
  resolveVariants,
1314
- splitStack
1359
+ splitStack,
1360
+ toDecisionQuery,
1361
+ toVariantsQuery
1315
1362
  });
@@ -9,6 +9,12 @@ declare const PREPR_DEFAULT_VARIANT = "ALL_OTHER_USERS";
9
9
 
10
10
  /** The variant ids Prepr chose for one visitor, per personalization group. */
11
11
  type PreprDecisions = ReadonlyMap<string, readonly string[]>;
12
+ /**
13
+ * Variant ids per group from a decision response, de-duplicated and in
14
+ * Prepr's order. A visitor in several segments can get more than one variant
15
+ * of the same group, so each entry is a list.
16
+ */
17
+ declare function decisionsFrom(data: unknown): PreprDecisions;
12
18
  interface ResolveVariantsOptions {
13
19
  /**
14
20
  * The visitor's per-group variants (from a decision query). Without it,
@@ -25,6 +31,24 @@ interface ResolveVariantsOptions {
25
31
  */
26
32
  declare function resolveVariants<T>(data: T, options?: ResolveVariantsOptions): T;
27
33
 
34
+ interface FieldInfo {
35
+ /** Named type of the field, without list/non-null wrappers. */
36
+ type: string;
37
+ /** The field accepts Prepr's `personalize` argument (a stack). */
38
+ personalizable: boolean;
39
+ }
40
+ interface TypeInfo {
41
+ fields: Record<string, FieldInfo>;
42
+ /** Members of a union or implementations of an interface. */
43
+ possibleTypes: string[];
44
+ hasContext: boolean;
45
+ }
46
+ /** The slice of the schema the variant transforms need. */
47
+ interface PreprSchemaInfo {
48
+ queryType: string;
49
+ types: Record<string, TypeInfo>;
50
+ }
51
+
28
52
  /** A run of stack items that renders the same way: see {@link splitStack}. */
29
53
  interface PreprStackBlock<T> {
30
54
  key: string;
@@ -73,6 +97,39 @@ interface PreprVariantProps {
73
97
  */
74
98
  declare function preprVariantProps(item: unknown): PreprVariantProps;
75
99
 
100
+ /**
101
+ * The schema facts the query rewrites need, from `loadPreprSchema`. Pass it
102
+ * along; its shape is not part of the public API.
103
+ */
104
+ type PreprSchema = PreprSchemaInfo;
105
+ /**
106
+ * Your query, asking for every personalization and A/B variant: what
107
+ * `query(..., { variants: true })` sends, as a string for your own GraphQL
108
+ * client. The result is the same for every visitor, so cache it like any
109
+ * other content query, and render it with `resolveVariants` or `PreprStack`.
110
+ *
111
+ * A query without personalizable fields comes back unchanged (minified).
112
+ */
113
+ declare function toVariantsQuery(document: PreprDocument<unknown, unknown> | string, schema: PreprSchema): string;
114
+ /**
115
+ * The per-visitor decision query for the same query: send it with the
116
+ * visitor's Prepr headers, never cached, and pass the response's `data` to
117
+ * `decisionsFrom`.
118
+ *
119
+ * Pass the variants result as `from` whenever you have it: the query then
120
+ * asks only about the lists that hold segment groups on this page, which is
121
+ * a few hundred bytes instead of the whole page and markedly faster for a
122
+ * visitor Prepr has not seen before. Without `from` it asks about every
123
+ * personalizable list. `topLevelOnly` stops at the first personalizable list
124
+ * on each path, for middleware that decides only the top of a stack.
125
+ *
126
+ * Null when there is nothing to decide: send no request then.
127
+ */
128
+ declare function toDecisionQuery(document: PreprDocument<unknown, unknown> | string, schema: PreprSchema, options?: {
129
+ from?: unknown;
130
+ topLevelOnly?: boolean;
131
+ }): string | null;
132
+
76
133
  /**
77
134
  * A GraphQL document accepted by `query`: a plain string, graphql-codegen's
78
135
  * `TypedDocumentString` (`documentMode: 'string'`), or any `DocumentNode`,
@@ -181,6 +238,23 @@ interface PreprQueryResult<TResult> {
181
238
  personalized: boolean;
182
239
  }
183
240
 
241
+ /**
242
+ * Loads what `toVariantsQuery` and `toDecisionQuery` need to know about your
243
+ * Prepr schema (which fields take `personalize`, which types can hold
244
+ * variants) with one introspection request, kept in memory per URL. For a
245
+ * site that uses its own GraphQL client; `createPreprClient` does this
246
+ * itself.
247
+ *
248
+ * Load it once at startup or lazily before the first rewrite. Schema changes
249
+ * in Prepr take effect after a restart or redeploy.
250
+ *
251
+ * @throws PreprError when the URL is invalid or the request fails; the URL,
252
+ * which holds your access token, is never part of the message.
253
+ */
254
+ declare function loadPreprSchema(url: string, options?: {
255
+ fetch?: typeof fetch;
256
+ }): Promise<PreprSchemaInfo>;
257
+
184
258
  /** The cookie `resolveDecisions` writes and the `PreprStack` switch reads. */
185
259
  declare const PREPR_DECISIONS_COOKIE = "prepr_decisions";
186
260
 
@@ -358,4 +432,4 @@ interface PreprNextClient {
358
432
  */
359
433
  declare function createPreprClient(options: PreprNextClientOptions): PreprNextClient;
360
434
 
361
- export { PREPR_DECISIONS_COOKIE, PREPR_DEFAULT_VARIANT, type PreprDecideOptions, type PreprDecisions, type PreprDocument, type PreprNextClient, type PreprNextClientOptions, type PreprNextQueryOptions, type PreprQueryResult, PreprStack, type PreprStackBlock, type PreprStackProps, type PreprStegaMode, type PreprVariantProps, type ResolveVariantsOptions, createPreprClient, preprVariantProps, resolveVariants, splitStack };
435
+ export { PREPR_DECISIONS_COOKIE, PREPR_DEFAULT_VARIANT, type PreprDecideOptions, type PreprDecisions, type PreprDocument, type PreprNextClient, type PreprNextClientOptions, type PreprNextQueryOptions, type PreprQueryResult, type PreprSchema, PreprStack, type PreprStackBlock, type PreprStackProps, type PreprStegaMode, type PreprVariantProps, type ResolveVariantsOptions, createPreprClient, decisionsFrom, loadPreprSchema, preprVariantProps, resolveVariants, splitStack, toDecisionQuery, toVariantsQuery };
@@ -9,6 +9,12 @@ declare const PREPR_DEFAULT_VARIANT = "ALL_OTHER_USERS";
9
9
 
10
10
  /** The variant ids Prepr chose for one visitor, per personalization group. */
11
11
  type PreprDecisions = ReadonlyMap<string, readonly string[]>;
12
+ /**
13
+ * Variant ids per group from a decision response, de-duplicated and in
14
+ * Prepr's order. A visitor in several segments can get more than one variant
15
+ * of the same group, so each entry is a list.
16
+ */
17
+ declare function decisionsFrom(data: unknown): PreprDecisions;
12
18
  interface ResolveVariantsOptions {
13
19
  /**
14
20
  * The visitor's per-group variants (from a decision query). Without it,
@@ -25,6 +31,24 @@ interface ResolveVariantsOptions {
25
31
  */
26
32
  declare function resolveVariants<T>(data: T, options?: ResolveVariantsOptions): T;
27
33
 
34
+ interface FieldInfo {
35
+ /** Named type of the field, without list/non-null wrappers. */
36
+ type: string;
37
+ /** The field accepts Prepr's `personalize` argument (a stack). */
38
+ personalizable: boolean;
39
+ }
40
+ interface TypeInfo {
41
+ fields: Record<string, FieldInfo>;
42
+ /** Members of a union or implementations of an interface. */
43
+ possibleTypes: string[];
44
+ hasContext: boolean;
45
+ }
46
+ /** The slice of the schema the variant transforms need. */
47
+ interface PreprSchemaInfo {
48
+ queryType: string;
49
+ types: Record<string, TypeInfo>;
50
+ }
51
+
28
52
  /** A run of stack items that renders the same way: see {@link splitStack}. */
29
53
  interface PreprStackBlock<T> {
30
54
  key: string;
@@ -73,6 +97,39 @@ interface PreprVariantProps {
73
97
  */
74
98
  declare function preprVariantProps(item: unknown): PreprVariantProps;
75
99
 
100
+ /**
101
+ * The schema facts the query rewrites need, from `loadPreprSchema`. Pass it
102
+ * along; its shape is not part of the public API.
103
+ */
104
+ type PreprSchema = PreprSchemaInfo;
105
+ /**
106
+ * Your query, asking for every personalization and A/B variant: what
107
+ * `query(..., { variants: true })` sends, as a string for your own GraphQL
108
+ * client. The result is the same for every visitor, so cache it like any
109
+ * other content query, and render it with `resolveVariants` or `PreprStack`.
110
+ *
111
+ * A query without personalizable fields comes back unchanged (minified).
112
+ */
113
+ declare function toVariantsQuery(document: PreprDocument<unknown, unknown> | string, schema: PreprSchema): string;
114
+ /**
115
+ * The per-visitor decision query for the same query: send it with the
116
+ * visitor's Prepr headers, never cached, and pass the response's `data` to
117
+ * `decisionsFrom`.
118
+ *
119
+ * Pass the variants result as `from` whenever you have it: the query then
120
+ * asks only about the lists that hold segment groups on this page, which is
121
+ * a few hundred bytes instead of the whole page and markedly faster for a
122
+ * visitor Prepr has not seen before. Without `from` it asks about every
123
+ * personalizable list. `topLevelOnly` stops at the first personalizable list
124
+ * on each path, for middleware that decides only the top of a stack.
125
+ *
126
+ * Null when there is nothing to decide: send no request then.
127
+ */
128
+ declare function toDecisionQuery(document: PreprDocument<unknown, unknown> | string, schema: PreprSchema, options?: {
129
+ from?: unknown;
130
+ topLevelOnly?: boolean;
131
+ }): string | null;
132
+
76
133
  /**
77
134
  * A GraphQL document accepted by `query`: a plain string, graphql-codegen's
78
135
  * `TypedDocumentString` (`documentMode: 'string'`), or any `DocumentNode`,
@@ -181,6 +238,23 @@ interface PreprQueryResult<TResult> {
181
238
  personalized: boolean;
182
239
  }
183
240
 
241
+ /**
242
+ * Loads what `toVariantsQuery` and `toDecisionQuery` need to know about your
243
+ * Prepr schema (which fields take `personalize`, which types can hold
244
+ * variants) with one introspection request, kept in memory per URL. For a
245
+ * site that uses its own GraphQL client; `createPreprClient` does this
246
+ * itself.
247
+ *
248
+ * Load it once at startup or lazily before the first rewrite. Schema changes
249
+ * in Prepr take effect after a restart or redeploy.
250
+ *
251
+ * @throws PreprError when the URL is invalid or the request fails; the URL,
252
+ * which holds your access token, is never part of the message.
253
+ */
254
+ declare function loadPreprSchema(url: string, options?: {
255
+ fetch?: typeof fetch;
256
+ }): Promise<PreprSchemaInfo>;
257
+
184
258
  /** The cookie `resolveDecisions` writes and the `PreprStack` switch reads. */
185
259
  declare const PREPR_DECISIONS_COOKIE = "prepr_decisions";
186
260
 
@@ -358,4 +432,4 @@ interface PreprNextClient {
358
432
  */
359
433
  declare function createPreprClient(options: PreprNextClientOptions): PreprNextClient;
360
434
 
361
- export { PREPR_DECISIONS_COOKIE, PREPR_DEFAULT_VARIANT, type PreprDecideOptions, type PreprDecisions, type PreprDocument, type PreprNextClient, type PreprNextClientOptions, type PreprNextQueryOptions, type PreprQueryResult, PreprStack, type PreprStackBlock, type PreprStackProps, type PreprStegaMode, type PreprVariantProps, type ResolveVariantsOptions, createPreprClient, preprVariantProps, resolveVariants, splitStack };
435
+ export { PREPR_DECISIONS_COOKIE, PREPR_DEFAULT_VARIANT, type PreprDecideOptions, type PreprDecisions, type PreprDocument, type PreprNextClient, type PreprNextClientOptions, type PreprNextQueryOptions, type PreprQueryResult, type PreprSchema, PreprStack, type PreprStackBlock, type PreprStackProps, type PreprStegaMode, type PreprVariantProps, type ResolveVariantsOptions, createPreprClient, decisionsFrom, loadPreprSchema, preprVariantProps, resolveVariants, splitStack, toDecisionQuery, toVariantsQuery };
@@ -4,7 +4,7 @@ import {
4
4
  getPreprHeadersFromHeaders,
5
5
  isPersonalizedResponse,
6
6
  validatePreprToken
7
- } from "./chunk-U4HXENF7.js";
7
+ } from "./chunk-BQ6IGSH6.js";
8
8
 
9
9
  // src/core/variants/constants.ts
10
10
  var PREPR_CONTEXT_ALIAS = "_preprContext";
@@ -483,6 +483,63 @@ function toVariantsDocument(document2, schema) {
483
483
  };
484
484
  }
485
485
 
486
+ // src/core/graphql/document.ts
487
+ import { print } from "graphql/language/printer.js";
488
+ import { stripIgnoredCharacters } from "graphql/utilities/stripIgnoredCharacters.js";
489
+ var printed = /* @__PURE__ */ new WeakMap();
490
+ function isDocumentNode(value) {
491
+ return typeof value === "object" && value !== null && value.kind === "Document" && Array.isArray(value.definitions);
492
+ }
493
+ function invalidDocument(originalError) {
494
+ return new PreprError(
495
+ "Expected a GraphQL query string, TypedDocumentString or DocumentNode",
496
+ "INVALID_DOCUMENT",
497
+ "createPreprClient",
498
+ originalError
499
+ );
500
+ }
501
+ var minified = /* @__PURE__ */ new Map();
502
+ var MINIFIED_CACHE_LIMIT = 500;
503
+ function minify(query) {
504
+ const cached = minified.get(query);
505
+ if (cached !== void 0) return cached;
506
+ let result = query;
507
+ try {
508
+ result = stripIgnoredCharacters(query);
509
+ } catch {
510
+ }
511
+ if (minified.size < MINIFIED_CACHE_LIMIT) minified.set(query, result);
512
+ return result;
513
+ }
514
+ function resolveQuery(document2) {
515
+ if (typeof document2 === "string") return minify(document2);
516
+ if (document2 instanceof String) return minify(document2.toString());
517
+ if (!isDocumentNode(document2)) throw invalidDocument();
518
+ let query = printed.get(document2);
519
+ if (query === void 0) {
520
+ try {
521
+ query = minify(print(document2));
522
+ } catch (error) {
523
+ throw invalidDocument(error instanceof Error ? error : void 0);
524
+ }
525
+ printed.set(document2, query);
526
+ }
527
+ return query;
528
+ }
529
+
530
+ // src/core/variants/queries.ts
531
+ function toVariantsQuery(document2, schema) {
532
+ return resolveQuery(toVariantsDocument(document2, schema));
533
+ }
534
+ function toDecisionQuery(document2, schema, options = {}) {
535
+ const paths = options.from === void 0 ? void 0 : personalizationPaths(options.from);
536
+ if (paths && paths.size === 0) return null;
537
+ const decision = toDecisionDocument(document2, schema, paths, {
538
+ topLevelOnly: !paths && options.topLevelOnly
539
+ });
540
+ return decision ? resolveQuery(decision) : null;
541
+ }
542
+
486
543
  // src/core/graphql/transport.ts
487
544
  import { VERCEL_STEGA_REGEX } from "@vercel/stega";
488
545
 
@@ -535,50 +592,6 @@ function stegaClean(text) {
535
592
  return vercelStegaClean(text);
536
593
  }
537
594
 
538
- // src/core/graphql/document.ts
539
- import { print } from "graphql/language/printer.js";
540
- import { stripIgnoredCharacters } from "graphql/utilities/stripIgnoredCharacters.js";
541
- var printed = /* @__PURE__ */ new WeakMap();
542
- function isDocumentNode(value) {
543
- return typeof value === "object" && value !== null && value.kind === "Document" && Array.isArray(value.definitions);
544
- }
545
- function invalidDocument(originalError) {
546
- return new PreprError(
547
- "Expected a GraphQL query string, TypedDocumentString or DocumentNode",
548
- "INVALID_DOCUMENT",
549
- "createPreprClient",
550
- originalError
551
- );
552
- }
553
- var minified = /* @__PURE__ */ new Map();
554
- var MINIFIED_CACHE_LIMIT = 500;
555
- function minify(query) {
556
- const cached = minified.get(query);
557
- if (cached !== void 0) return cached;
558
- let result = query;
559
- try {
560
- result = stripIgnoredCharacters(query);
561
- } catch {
562
- }
563
- if (minified.size < MINIFIED_CACHE_LIMIT) minified.set(query, result);
564
- return result;
565
- }
566
- function resolveQuery(document2) {
567
- if (typeof document2 === "string") return minify(document2);
568
- if (document2 instanceof String) return minify(document2.toString());
569
- if (!isDocumentNode(document2)) throw invalidDocument();
570
- let query = printed.get(document2);
571
- if (query === void 0) {
572
- try {
573
- query = minify(print(document2));
574
- } catch (error) {
575
- throw invalidDocument(error instanceof Error ? error : void 0);
576
- }
577
- printed.set(document2, query);
578
- }
579
- return query;
580
- }
581
-
582
595
  // src/core/graphql/transport.ts
583
596
  var OPERATION_NAME = /\b(?:query|mutation|subscription)\s+([_A-Za-z][_0-9A-Za-z]*)/;
584
597
  var STEGA_RAW = new RegExp(
@@ -765,16 +778,18 @@ function isParseableUrl(url) {
765
778
  return false;
766
779
  }
767
780
  }
768
- function createPreprClient(options) {
769
- const { url } = options;
781
+ function assertPreprUrl(url, source) {
770
782
  validatePreprToken(url);
771
783
  if (!isParseableUrl(url)) {
772
784
  throw new PreprError(
773
785
  "Prepr GraphQL URL is not a valid URL",
774
786
  "INVALID_TOKEN",
775
- "createPreprClient"
787
+ source
776
788
  );
777
789
  }
790
+ }
791
+ function createPreprClient(options) {
792
+ assertPreprUrl(options.url, "createPreprClient");
778
793
  const run = createTransport(options);
779
794
  const probeVary = createVaryProbe(run, options);
780
795
  let schema;
@@ -832,6 +847,30 @@ function createPreprClient(options) {
832
847
  };
833
848
  }
834
849
 
850
+ // src/core/graphql/schema-loader.ts
851
+ var schemas = /* @__PURE__ */ new Map();
852
+ async function loadPreprSchema(url, options = {}) {
853
+ assertPreprUrl(url, "loadPreprSchema");
854
+ let schema = schemas.get(url);
855
+ if (!schema) {
856
+ const run = createTransport({ url, fetch: options.fetch, stega: "none" });
857
+ schema = run(
858
+ PREPR_SCHEMA_QUERY
859
+ ).then((result) => toSchemaInfo(result.data)).catch((error) => {
860
+ schemas.delete(url);
861
+ if (error instanceof PreprError) throw error;
862
+ throw new PreprError(
863
+ "Prepr schema response is not an introspection result",
864
+ "INVALID_RESPONSE",
865
+ "loadPreprSchema",
866
+ error instanceof Error ? error : void 0
867
+ );
868
+ });
869
+ schemas.set(url, schema);
870
+ }
871
+ return schema;
872
+ }
873
+
835
874
  // src/nextjs/decisions.ts
836
875
  var PREPR_DECISIONS_COOKIE = "prepr_decisions";
837
876
  var DECISIONS_MAX_GROUPS = 40;
@@ -1211,8 +1250,12 @@ export {
1211
1250
  PreprError,
1212
1251
  PreprStack,
1213
1252
  createPreprClient2 as createPreprClient,
1253
+ decisionsFrom,
1214
1254
  isPersonalizedResponse,
1255
+ loadPreprSchema,
1215
1256
  preprVariantProps,
1216
1257
  resolveVariants,
1217
- splitStack
1258
+ splitStack,
1259
+ toDecisionQuery,
1260
+ toVariantsQuery
1218
1261
  };
@@ -43,7 +43,7 @@ module.exports = __toCommonJS(nextjs_exports);
43
43
  var import_server = require("next/server");
44
44
 
45
45
  // src/version.ts
46
- var VERSION = "0.6.0-alpha.0";
46
+ var VERSION = "0.6.0-alpha.1";
47
47
 
48
48
  // src/core/constants.ts
49
49
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -10,7 +10,7 @@ import {
10
10
  isPersonalizedResponse,
11
11
  resolveFeatures,
12
12
  validatePreprToken
13
- } from "./chunk-U4HXENF7.js";
13
+ } from "./chunk-BQ6IGSH6.js";
14
14
 
15
15
  // src/nextjs/middleware.ts
16
16
  import { NextResponse } from "next/server";
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "0.6.0-alpha.0";
2
+ var VERSION = "0.6.0-alpha.1";
3
3
 
4
4
  // src/core/constants.ts
5
5
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";