@preprio/toolkit 0.6.0-alpha.0 → 0.6.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +268 -59
  2. package/dist/astro/{chunk-3UVUDDNY.js → chunk-CG2QBHNU.js} +1 -1
  3. package/dist/astro/graphql.cjs +154 -59
  4. package/dist/astro/graphql.d.cts +75 -6
  5. package/dist/astro/graphql.d.ts +75 -6
  6. package/dist/astro/graphql.js +150 -59
  7. package/dist/astro/index.cjs +1 -1
  8. package/dist/astro/index.js +1 -1
  9. package/dist/chunk-3NCEVJJ3.js +10 -0
  10. package/dist/{chunk-BJ2LBLWO.js → chunk-LIDUJWWJ.js} +6 -4
  11. package/dist/chunk-M3RBYJ5J.js +499 -0
  12. package/dist/{chunk-DGZA7KX7.js → chunk-S5RWVMDJ.js} +0 -24
  13. package/dist/{chunk-YR7P4IWE.js → chunk-SF6TN4JR.js} +1 -9
  14. package/dist/chunk-TN6SNAR2.js +26 -0
  15. package/dist/graphql/codegen.cjs +557 -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 +185 -59
  20. package/dist/graphql.d.cts +110 -6
  21. package/dist/graphql.d.ts +110 -6
  22. package/dist/graphql.js +91 -430
  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-B4GVZEOL.js +549 -0
  28. package/dist/nextjs/components.cjs +297 -81
  29. package/dist/nextjs/components.d.cts +26 -11
  30. package/dist/nextjs/components.d.ts +26 -11
  31. package/dist/nextjs/components.js +289 -73
  32. package/dist/nextjs/graphql.cjs +952 -315
  33. package/dist/nextjs/graphql.d.cts +225 -83
  34. package/dist/nextjs/graphql.d.ts +225 -83
  35. package/dist/nextjs/graphql.js +634 -314
  36. package/dist/nextjs/index.cjs +116 -54
  37. package/dist/nextjs/index.d.cts +61 -23
  38. package/dist/nextjs/index.d.ts +61 -23
  39. package/dist/nextjs/index.js +97 -299
  40. package/dist/nextjs/{server-CjpELYvq.d.ts → server-BL-sqZvu.d.cts} +1 -1
  41. package/dist/nextjs/{server-CjpELYvq.d.cts → server-BL-sqZvu.d.ts} +1 -1
  42. package/dist/nuxt/{chunk-P6ENNAEE.js → chunk-FMC3DP7N.js} +1 -1
  43. package/dist/nuxt/graphql.cjs +154 -59
  44. package/dist/nuxt/graphql.d.cts +75 -6
  45. package/dist/nuxt/graphql.d.ts +75 -6
  46. package/dist/nuxt/graphql.js +150 -59
  47. package/dist/nuxt/index.cjs +1 -1
  48. package/dist/nuxt/index.js +1 -1
  49. package/dist/react/components.cjs +1 -1
  50. package/dist/react/components.js +1 -1
  51. package/dist/sveltekit/{chunk-FSARVMG5.js → chunk-AJPKBAHO.js} +1 -1
  52. package/dist/sveltekit/graphql.cjs +154 -59
  53. package/dist/sveltekit/graphql.d.cts +75 -6
  54. package/dist/sveltekit/graphql.d.ts +75 -6
  55. package/dist/sveltekit/graphql.js +150 -59
  56. package/dist/sveltekit/index.cjs +1 -1
  57. package/dist/sveltekit/index.js +1 -1
  58. package/package.json +6 -1
  59. package/dist/nextjs/chunk-U4HXENF7.js +0 -231
@@ -3,7 +3,7 @@ import {
3
3
  getPreprHeadersFromHeaders,
4
4
  isPersonalizedResponse,
5
5
  validatePreprToken
6
- } from "./chunk-3UVUDDNY.js";
6
+ } from "./chunk-CG2QBHNU.js";
7
7
 
8
8
  // src/core/variants/constants.ts
9
9
  var PREPR_CONTEXT_ALIAS = "_preprContext";
@@ -92,7 +92,10 @@ function decisionSelectionSet(set, typeName, path, ctx) {
92
92
  path,
93
93
  ctx
94
94
  );
95
- if (pruned) {
95
+ if (!pruned) continue;
96
+ if (fragment.typeCondition.name.value === typeName) {
97
+ selections.push(...pruned.selections);
98
+ } else {
96
99
  selections.push(
97
100
  inlineFragment(fragment.typeCondition.name.value, [
98
101
  ...pruned.selections
@@ -102,13 +105,19 @@ function decisionSelectionSet(set, typeName, path, ctx) {
102
105
  continue;
103
106
  }
104
107
  if (selection.kind === "InlineFragment") {
108
+ const condition = selection.typeCondition?.name.value ?? typeName;
105
109
  const pruned = decisionSelectionSet(
106
110
  selection.selectionSet,
107
- selection.typeCondition?.name.value ?? typeName,
111
+ condition,
108
112
  path,
109
113
  ctx
110
114
  );
111
- if (pruned) selections.push({ ...selection, selectionSet: pruned });
115
+ if (!pruned) continue;
116
+ if (condition === typeName && !selection.directives?.length) {
117
+ selections.push(...pruned.selections);
118
+ } else {
119
+ selections.push({ ...selection, selectionSet: pruned });
120
+ }
112
121
  continue;
113
122
  }
114
123
  if (!selection.selectionSet) continue;
@@ -182,20 +191,58 @@ function toDecisionDocument(document2, schema, groupPaths, options) {
182
191
  const used = /* @__PURE__ */ new Set();
183
192
  collectVariables(pruned, used);
184
193
  collectVariables(operation.directives, used);
194
+ const shared = sharedContextFragment(schema);
185
195
  return {
186
196
  kind: "Document",
187
197
  definitions: [
198
+ ...shared ? [shared.definition] : [],
188
199
  {
189
200
  ...operation,
190
201
  name: operation.name && name(`${operation.name.value}Decision`),
191
202
  variableDefinitions: (operation.variableDefinitions ?? []).filter(
192
203
  (definition) => used.has(definition.variable.name.value)
193
204
  ),
194
- selectionSet: pruned
205
+ selectionSet: shared ? shared.apply(pruned) : pruned
195
206
  }
196
207
  ]
197
208
  };
198
209
  }
210
+ function sharedContextFragment(schema) {
211
+ const contextTypes = new Set(
212
+ Object.values(schema.types).flatMap(
213
+ (type) => type.hasContext ? [type.fields._context.type] : []
214
+ )
215
+ );
216
+ if (contextTypes.size !== 1) return null;
217
+ const [contextType] = contextTypes;
218
+ const fragmentName = "c";
219
+ const definition = {
220
+ kind: "FragmentDefinition",
221
+ name: name(fragmentName),
222
+ typeCondition: { kind: "NamedType", name: name(contextType) },
223
+ selectionSet: selectionSet(
224
+ ["kind", "group_id", "variant_id"].map(
225
+ (field) => ({ kind: "Field", name: name(field) })
226
+ )
227
+ )
228
+ };
229
+ const spread = {
230
+ kind: "FragmentSpread",
231
+ name: name(fragmentName)
232
+ };
233
+ const apply = (set) => selectionSet(
234
+ set.selections.map((selection) => {
235
+ if (selection.kind === "Field" && selection.alias?.value === PREPR_CONTEXT_ALIAS) {
236
+ return { ...selection, selectionSet: selectionSet([spread]) };
237
+ }
238
+ return "selectionSet" in selection && selection.selectionSet ? {
239
+ ...selection,
240
+ selectionSet: apply(selection.selectionSet)
241
+ } : selection;
242
+ })
243
+ );
244
+ return { definition, apply };
245
+ }
199
246
 
200
247
  // src/core/variants/probe-document.ts
201
248
  function probeSelectionSet(set, fragments) {
@@ -482,6 +529,63 @@ function toVariantsDocument(document2, schema) {
482
529
  };
483
530
  }
484
531
 
532
+ // src/core/graphql/document.ts
533
+ import { print } from "graphql/language/printer.js";
534
+ import { stripIgnoredCharacters } from "graphql/utilities/stripIgnoredCharacters.js";
535
+ var printed = /* @__PURE__ */ new WeakMap();
536
+ function isDocumentNode(value) {
537
+ return typeof value === "object" && value !== null && value.kind === "Document" && Array.isArray(value.definitions);
538
+ }
539
+ function invalidDocument(originalError) {
540
+ return new PreprError(
541
+ "Expected a GraphQL query string, TypedDocumentString or DocumentNode",
542
+ "INVALID_DOCUMENT",
543
+ "createPreprClient",
544
+ originalError
545
+ );
546
+ }
547
+ var minified = /* @__PURE__ */ new Map();
548
+ var MINIFIED_CACHE_LIMIT = 500;
549
+ function minify(query) {
550
+ const cached = minified.get(query);
551
+ if (cached !== void 0) return cached;
552
+ let result = query;
553
+ try {
554
+ result = stripIgnoredCharacters(query);
555
+ } catch {
556
+ }
557
+ if (minified.size < MINIFIED_CACHE_LIMIT) minified.set(query, result);
558
+ return result;
559
+ }
560
+ function resolveQuery(document2) {
561
+ if (typeof document2 === "string") return minify(document2);
562
+ if (document2 instanceof String) return minify(document2.toString());
563
+ if (!isDocumentNode(document2)) throw invalidDocument();
564
+ let query = printed.get(document2);
565
+ if (query === void 0) {
566
+ try {
567
+ query = minify(print(document2));
568
+ } catch (error) {
569
+ throw invalidDocument(error instanceof Error ? error : void 0);
570
+ }
571
+ printed.set(document2, query);
572
+ }
573
+ return query;
574
+ }
575
+
576
+ // src/core/variants/queries.ts
577
+ function toVariantsQuery(document2, schema) {
578
+ return resolveQuery(toVariantsDocument(document2, schema));
579
+ }
580
+ function toDecisionQuery(document2, schema, options = {}) {
581
+ const paths = options.from === void 0 ? void 0 : personalizationPaths(options.from);
582
+ if (paths && paths.size === 0) return null;
583
+ const decision = toDecisionDocument(document2, schema, paths, {
584
+ topLevelOnly: !paths && options.topLevelOnly
585
+ });
586
+ return decision ? resolveQuery(decision) : null;
587
+ }
588
+
485
589
  // src/core/graphql/transport.ts
486
590
  import { VERCEL_STEGA_REGEX } from "@vercel/stega";
487
591
 
@@ -534,50 +638,6 @@ function stegaClean(text) {
534
638
  return vercelStegaClean(text);
535
639
  }
536
640
 
537
- // src/core/graphql/document.ts
538
- import { print } from "graphql/language/printer.js";
539
- import { stripIgnoredCharacters } from "graphql/utilities/stripIgnoredCharacters.js";
540
- var printed = /* @__PURE__ */ new WeakMap();
541
- function isDocumentNode(value) {
542
- return typeof value === "object" && value !== null && value.kind === "Document" && Array.isArray(value.definitions);
543
- }
544
- function invalidDocument(originalError) {
545
- return new PreprError(
546
- "Expected a GraphQL query string, TypedDocumentString or DocumentNode",
547
- "INVALID_DOCUMENT",
548
- "createPreprClient",
549
- originalError
550
- );
551
- }
552
- var minified = /* @__PURE__ */ new Map();
553
- var MINIFIED_CACHE_LIMIT = 500;
554
- function minify(query) {
555
- const cached = minified.get(query);
556
- if (cached !== void 0) return cached;
557
- let result = query;
558
- try {
559
- result = stripIgnoredCharacters(query);
560
- } catch {
561
- }
562
- if (minified.size < MINIFIED_CACHE_LIMIT) minified.set(query, result);
563
- return result;
564
- }
565
- function resolveQuery(document2) {
566
- if (typeof document2 === "string") return minify(document2);
567
- if (document2 instanceof String) return minify(document2.toString());
568
- if (!isDocumentNode(document2)) throw invalidDocument();
569
- let query = printed.get(document2);
570
- if (query === void 0) {
571
- try {
572
- query = minify(print(document2));
573
- } catch (error) {
574
- throw invalidDocument(error instanceof Error ? error : void 0);
575
- }
576
- printed.set(document2, query);
577
- }
578
- return query;
579
- }
580
-
581
641
  // src/core/graphql/transport.ts
582
642
  var OPERATION_NAME = /\b(?:query|mutation|subscription)\s+([_A-Za-z][_0-9A-Za-z]*)/;
583
643
  var STEGA_RAW = new RegExp(
@@ -756,6 +816,7 @@ function createVaryProbe(run, options) {
756
816
  }
757
817
 
758
818
  // src/core/graphql/client.ts
819
+ var clientSchemas = /* @__PURE__ */ new WeakMap();
759
820
  function isParseableUrl(url) {
760
821
  try {
761
822
  new URL(url);
@@ -764,16 +825,18 @@ function isParseableUrl(url) {
764
825
  return false;
765
826
  }
766
827
  }
767
- function createPreprClient(options) {
768
- const { url } = options;
828
+ function assertPreprUrl(url, source) {
769
829
  validatePreprToken(url);
770
830
  if (!isParseableUrl(url)) {
771
831
  throw new PreprError(
772
832
  "Prepr GraphQL URL is not a valid URL",
773
833
  "INVALID_TOKEN",
774
- "createPreprClient"
834
+ source
775
835
  );
776
836
  }
837
+ }
838
+ function createPreprClient(options) {
839
+ assertPreprUrl(options.url, "createPreprClient");
777
840
  const run = createTransport(options);
778
841
  const probeVary = createVaryProbe(run, options);
779
842
  let schema;
@@ -790,7 +853,7 @@ function createPreprClient(options) {
790
853
  ));
791
854
  const variantsDocuments = /* @__PURE__ */ new Map();
792
855
  const decisionDocuments = /* @__PURE__ */ new Map();
793
- return {
856
+ const client = {
794
857
  async query(document2, variables, queryOptions = {}) {
795
858
  const { variants, ...rest } = queryOptions;
796
859
  if (!variants) return run(document2, variables, rest);
@@ -802,10 +865,10 @@ function createPreprClient(options) {
802
865
  return run(derived, variables, rest);
803
866
  },
804
867
  async decide(document2, variables, queryOptions = {}) {
805
- const { from, topLevelOnly, ...rest } = queryOptions;
868
+ const { from, ...rest } = queryOptions;
806
869
  const paths = from === void 0 ? void 0 : personalizationPaths(from);
807
870
  if (paths && paths.size === 0) return /* @__PURE__ */ new Map();
808
- const signature = paths ? [...paths].map(([path, types]) => `${path}:${[...types].sort().join(",")}`).sort().join("|") : topLevelOnly ? "top" : "*";
871
+ const signature = paths ? [...paths].map(([path, types]) => `${path}:${[...types].sort().join(",")}`).sort().join("|") : "*";
809
872
  let byPaths = decisionDocuments.get(document2);
810
873
  if (!byPaths) {
811
874
  byPaths = /* @__PURE__ */ new Map();
@@ -813,9 +876,7 @@ function createPreprClient(options) {
813
876
  }
814
877
  let derived = byPaths.get(signature);
815
878
  if (derived === void 0) {
816
- derived = toDecisionDocument(document2, await loadSchema(), paths, {
817
- topLevelOnly: !paths && topLevelOnly
818
- });
879
+ derived = toDecisionDocument(document2, await loadSchema(), paths);
819
880
  byPaths.set(signature, derived);
820
881
  }
821
882
  if (!derived) return /* @__PURE__ */ new Map();
@@ -829,6 +890,8 @@ function createPreprClient(options) {
829
890
  (vary) => vary === null || SEGMENTS_VARY.test(vary)
830
891
  )
831
892
  };
893
+ clientSchemas.set(client, loadSchema);
894
+ return client;
832
895
  }
833
896
 
834
897
  // src/core/graphql/event-client.ts
@@ -876,6 +939,30 @@ function createEventClient(options, adapter) {
876
939
  };
877
940
  }
878
941
 
942
+ // src/core/graphql/schema-loader.ts
943
+ var schemas = /* @__PURE__ */ new Map();
944
+ async function loadPreprSchema(url, options = {}) {
945
+ assertPreprUrl(url, "loadPreprSchema");
946
+ let schema = schemas.get(url);
947
+ if (!schema) {
948
+ const run = createTransport({ url, fetch: options.fetch, stega: "none" });
949
+ schema = run(
950
+ PREPR_SCHEMA_QUERY
951
+ ).then((result) => toSchemaInfo(result.data)).catch((error) => {
952
+ schemas.delete(url);
953
+ if (error instanceof PreprError) throw error;
954
+ throw new PreprError(
955
+ "Prepr schema response is not an introspection result",
956
+ "INVALID_RESPONSE",
957
+ "loadPreprSchema",
958
+ error instanceof Error ? error : void 0
959
+ );
960
+ });
961
+ schemas.set(url, schema);
962
+ }
963
+ return schema;
964
+ }
965
+
879
966
  // src/astro/graphql.ts
880
967
  function createPreprClient2(options) {
881
968
  return createEventClient(options, {
@@ -886,8 +973,12 @@ export {
886
973
  PREPR_DEFAULT_VARIANT,
887
974
  PreprError,
888
975
  createPreprClient2 as createPreprClient,
976
+ decisionsFrom,
889
977
  isPersonalizedResponse,
978
+ loadPreprSchema,
890
979
  preprVariantProps,
891
980
  resolveVariants,
892
- splitStack
981
+ splitStack,
982
+ toDecisionQuery,
983
+ toVariantsQuery
893
984
  };
@@ -31,7 +31,7 @@ __export(astro_exports, {
31
31
  module.exports = __toCommonJS(astro_exports);
32
32
 
33
33
  // src/version.ts
34
- var VERSION = "0.6.0-alpha.0";
34
+ var VERSION = "0.6.0-alpha.10";
35
35
 
36
36
  // src/core/features.ts
37
37
  function isEnabled(config) {
@@ -7,7 +7,7 @@ import {
7
7
  getToolbarPropsFromHeaders,
8
8
  isPersonalizedResponse,
9
9
  resolveFeatures
10
- } from "./chunk-3UVUDDNY.js";
10
+ } from "./chunk-CG2QBHNU.js";
11
11
 
12
12
  // src/core/constants.ts
13
13
  var COOKIE_PREVIEW_MODE = "Prepr-Preview-Mode";
@@ -0,0 +1,10 @@
1
+ // src/core/personalization.ts
2
+ var PERSONALIZED_VARY = /\bPrepr-(Segments|ABTesting)/i;
3
+ function isPersonalizedResponse(source) {
4
+ const headers = "headers" in source ? source.headers : source;
5
+ return PERSONALIZED_VARY.test(headers.get("vary") ?? "");
6
+ }
7
+
8
+ export {
9
+ isPersonalizedResponse
10
+ };
@@ -1,15 +1,17 @@
1
1
  import {
2
- ALL_FEATURES_ENABLED,
3
- VERSION,
4
2
  createElementCache,
5
3
  createScopedLogger,
6
4
  decodeStega,
7
5
  initDebugLogger,
8
- resolveFeatures,
9
6
  sendPreprEvent,
10
7
  setTrustedParentOrigin,
11
8
  throttle
12
- } from "./chunk-DGZA7KX7.js";
9
+ } from "./chunk-S5RWVMDJ.js";
10
+ import {
11
+ ALL_FEATURES_ENABLED,
12
+ VERSION,
13
+ resolveFeatures
14
+ } from "./chunk-TN6SNAR2.js";
13
15
 
14
16
  // src/core/stega/dom.ts
15
17
  var IGNORED_ANCESTORS = "script, style, noscript";