@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
@@ -0,0 +1,557 @@
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 name2 in all)
8
+ __defProp(target, name2, { get: all[name2], 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/codegen/index.ts
21
+ var codegen_exports = {};
22
+ __export(codegen_exports, {
23
+ plugin: () => plugin
24
+ });
25
+ module.exports = __toCommonJS(codegen_exports);
26
+
27
+ // src/core/graphql/document.ts
28
+ var import_printer = require("graphql/language/printer.js");
29
+ var import_stripIgnoredCharacters = require("graphql/utilities/stripIgnoredCharacters.js");
30
+
31
+ // src/core/server.ts
32
+ var PreprError = class extends Error {
33
+ constructor(message, code, context, originalError) {
34
+ super(message);
35
+ this.code = code;
36
+ this.context = context;
37
+ this.originalError = originalError;
38
+ this.name = "PreprError";
39
+ }
40
+ };
41
+
42
+ // src/core/graphql/document.ts
43
+ var printed = /* @__PURE__ */ new WeakMap();
44
+ function isDocumentNode(value) {
45
+ return typeof value === "object" && value !== null && value.kind === "Document" && Array.isArray(value.definitions);
46
+ }
47
+ function invalidDocument(originalError) {
48
+ return new PreprError(
49
+ "Expected a GraphQL query string, TypedDocumentString or DocumentNode",
50
+ "INVALID_DOCUMENT",
51
+ "createPreprClient",
52
+ originalError
53
+ );
54
+ }
55
+ var minified = /* @__PURE__ */ new Map();
56
+ var MINIFIED_CACHE_LIMIT = 500;
57
+ function minify(query) {
58
+ const cached = minified.get(query);
59
+ if (cached !== void 0) return cached;
60
+ let result = query;
61
+ try {
62
+ result = (0, import_stripIgnoredCharacters.stripIgnoredCharacters)(query);
63
+ } catch {
64
+ }
65
+ if (minified.size < MINIFIED_CACHE_LIMIT) minified.set(query, result);
66
+ return result;
67
+ }
68
+ function resolveQuery(document) {
69
+ if (typeof document === "string") return minify(document);
70
+ if (document instanceof String) return minify(document.toString());
71
+ if (!isDocumentNode(document)) throw invalidDocument();
72
+ let query = printed.get(document);
73
+ if (query === void 0) {
74
+ try {
75
+ query = minify((0, import_printer.print)(document));
76
+ } catch (error) {
77
+ throw invalidDocument(error instanceof Error ? error : void 0);
78
+ }
79
+ printed.set(document, query);
80
+ }
81
+ return query;
82
+ }
83
+
84
+ // src/core/variants/ast.ts
85
+ var import_parser = require("graphql/language/parser.js");
86
+
87
+ // src/core/variants/constants.ts
88
+ var PREPR_CONTEXT_ALIAS = "_preprContext";
89
+ var PREPR_TYPE_ALIAS = "_preprType";
90
+
91
+ // src/core/variants/ast.ts
92
+ var name = (value) => ({ kind: "Name", value });
93
+ function selectionSet(selections) {
94
+ return { kind: "SelectionSet", selections };
95
+ }
96
+ function contextField(withKey) {
97
+ const fields = ["kind", "group_id", "variant_id"];
98
+ if (withKey) fields.push("variant_key");
99
+ return {
100
+ kind: "Field",
101
+ alias: name(PREPR_CONTEXT_ALIAS),
102
+ name: name("_context"),
103
+ selectionSet: selectionSet(
104
+ fields.map(
105
+ (field) => ({ kind: "Field", name: name(field) })
106
+ )
107
+ )
108
+ };
109
+ }
110
+ function typenameField() {
111
+ return {
112
+ kind: "Field",
113
+ alias: name(PREPR_TYPE_ALIAS),
114
+ name: name("__typename")
115
+ };
116
+ }
117
+ function inlineFragment(typeName, selections) {
118
+ return {
119
+ kind: "InlineFragment",
120
+ typeCondition: { kind: "NamedType", name: name(typeName) },
121
+ selectionSet: selectionSet(selections)
122
+ };
123
+ }
124
+ function contextSelections(typeName, schema, onlyTypes, withType = true) {
125
+ const fields = () => withType ? [contextField(true), typenameField()] : [contextField(false)];
126
+ const type = schema.types[typeName];
127
+ if (!type) return [];
128
+ if (type.possibleTypes.length > 0) {
129
+ return type.possibleTypes.filter(
130
+ (member) => schema.types[member]?.hasContext && (!onlyTypes || onlyTypes.has(member))
131
+ ).map((member) => inlineFragment(member, fields()));
132
+ }
133
+ return type.hasContext ? fields() : [];
134
+ }
135
+ function withoutPersonalizeArg(args = []) {
136
+ return args.filter((arg) => arg.name.value !== "personalize");
137
+ }
138
+ function documentOf(document) {
139
+ if (typeof document === "string") return (0, import_parser.parse)(document);
140
+ if (document instanceof String) return (0, import_parser.parse)(document.toString());
141
+ return document;
142
+ }
143
+ function collectVariables(node, used) {
144
+ if (!node || typeof node !== "object") return;
145
+ if (Array.isArray(node)) {
146
+ for (const item of node) collectVariables(item, used);
147
+ return;
148
+ }
149
+ const value = node;
150
+ if (value.kind === "Variable") {
151
+ used.add(value.name.value);
152
+ return;
153
+ }
154
+ for (const key of Object.keys(value)) {
155
+ if (key !== "loc") collectVariables(value[key], used);
156
+ }
157
+ }
158
+
159
+ // src/core/variants/decision-document.ts
160
+ function decisionSelectionSet(set, typeName, path, ctx) {
161
+ const selections = [];
162
+ for (const selection of set.selections) {
163
+ if (selection.kind === "FragmentSpread") {
164
+ const fragment = ctx.fragments[selection.name.value];
165
+ if (!fragment) continue;
166
+ const pruned = decisionSelectionSet(
167
+ fragment.selectionSet,
168
+ fragment.typeCondition.name.value,
169
+ path,
170
+ ctx
171
+ );
172
+ if (!pruned) continue;
173
+ if (fragment.typeCondition.name.value === typeName) {
174
+ selections.push(...pruned.selections);
175
+ } else {
176
+ selections.push(
177
+ inlineFragment(fragment.typeCondition.name.value, [
178
+ ...pruned.selections
179
+ ])
180
+ );
181
+ }
182
+ continue;
183
+ }
184
+ if (selection.kind === "InlineFragment") {
185
+ const condition = selection.typeCondition?.name.value ?? typeName;
186
+ const pruned = decisionSelectionSet(
187
+ selection.selectionSet,
188
+ condition,
189
+ path,
190
+ ctx
191
+ );
192
+ if (!pruned) continue;
193
+ if (condition === typeName && !selection.directives?.length) {
194
+ selections.push(...pruned.selections);
195
+ } else {
196
+ selections.push({ ...selection, selectionSet: pruned });
197
+ }
198
+ continue;
199
+ }
200
+ if (!selection.selectionSet) continue;
201
+ const field = ctx.schema.types[typeName]?.fields[selection.name.value];
202
+ if (!field) continue;
203
+ const key = selection.alias?.value ?? selection.name.value;
204
+ const fieldPath = path ? `${path}.${key}` : key;
205
+ if (ctx.paths && !ctx.paths.prefixes.has(fieldPath)) continue;
206
+ const child = decisionSelectionSet(
207
+ selection.selectionSet,
208
+ field.type,
209
+ fieldPath,
210
+ ctx
211
+ );
212
+ const groupTypes = ctx.paths?.groups.get(fieldPath);
213
+ const holdsGroups = field.personalizable && (!ctx.paths || groupTypes !== void 0);
214
+ if (holdsGroups) {
215
+ selections.push({
216
+ ...selection,
217
+ arguments: withoutPersonalizeArg(selection.arguments),
218
+ selectionSet: selectionSet([
219
+ ...ctx.topLevelOnly ? [] : child?.selections ?? [],
220
+ ...contextSelections(
221
+ field.type,
222
+ ctx.schema,
223
+ groupTypes && !groupTypes.has("*") ? groupTypes : void 0,
224
+ false
225
+ )
226
+ ])
227
+ });
228
+ } else if (child) {
229
+ selections.push({
230
+ ...selection,
231
+ arguments: field.personalizable ? withoutPersonalizeArg(selection.arguments) : selection.arguments,
232
+ selectionSet: child
233
+ });
234
+ }
235
+ }
236
+ return selections.length > 0 ? selectionSet(selections) : null;
237
+ }
238
+ function toDecisionDocument(document, schema, groupPaths, options) {
239
+ const doc = documentOf(document);
240
+ const fragments = {};
241
+ for (const definition of doc.definitions) {
242
+ if (definition.kind === "FragmentDefinition") {
243
+ fragments[definition.name.value] = definition;
244
+ }
245
+ }
246
+ const operation = doc.definitions.find(
247
+ (definition) => definition.kind === "OperationDefinition"
248
+ );
249
+ if (!operation) return null;
250
+ let paths;
251
+ if (groupPaths) {
252
+ const prefixes = /* @__PURE__ */ new Set();
253
+ for (const groupPath of groupPaths.keys()) {
254
+ const parts = groupPath.split(".");
255
+ for (let i = 1; i <= parts.length; i++) {
256
+ prefixes.add(parts.slice(0, i).join("."));
257
+ }
258
+ }
259
+ paths = { groups: groupPaths, prefixes };
260
+ }
261
+ const pruned = decisionSelectionSet(
262
+ operation.selectionSet,
263
+ schema.queryType,
264
+ "",
265
+ { schema, fragments, paths, topLevelOnly: options?.topLevelOnly }
266
+ );
267
+ if (!pruned) return null;
268
+ const used = /* @__PURE__ */ new Set();
269
+ collectVariables(pruned, used);
270
+ collectVariables(operation.directives, used);
271
+ const shared = sharedContextFragment(schema);
272
+ return {
273
+ kind: "Document",
274
+ definitions: [
275
+ ...shared ? [shared.definition] : [],
276
+ {
277
+ ...operation,
278
+ name: operation.name && name(`${operation.name.value}Decision`),
279
+ variableDefinitions: (operation.variableDefinitions ?? []).filter(
280
+ (definition) => used.has(definition.variable.name.value)
281
+ ),
282
+ selectionSet: shared ? shared.apply(pruned) : pruned
283
+ }
284
+ ]
285
+ };
286
+ }
287
+ function sharedContextFragment(schema) {
288
+ const contextTypes = new Set(
289
+ Object.values(schema.types).flatMap(
290
+ (type) => type.hasContext ? [type.fields._context.type] : []
291
+ )
292
+ );
293
+ if (contextTypes.size !== 1) return null;
294
+ const [contextType] = contextTypes;
295
+ const fragmentName = "c";
296
+ const definition = {
297
+ kind: "FragmentDefinition",
298
+ name: name(fragmentName),
299
+ typeCondition: { kind: "NamedType", name: name(contextType) },
300
+ selectionSet: selectionSet(
301
+ ["kind", "group_id", "variant_id"].map(
302
+ (field) => ({ kind: "Field", name: name(field) })
303
+ )
304
+ )
305
+ };
306
+ const spread = {
307
+ kind: "FragmentSpread",
308
+ name: name(fragmentName)
309
+ };
310
+ const apply = (set) => selectionSet(
311
+ set.selections.map((selection) => {
312
+ if (selection.kind === "Field" && selection.alias?.value === PREPR_CONTEXT_ALIAS) {
313
+ return { ...selection, selectionSet: selectionSet([spread]) };
314
+ }
315
+ return "selectionSet" in selection && selection.selectionSet ? {
316
+ ...selection,
317
+ selectionSet: apply(selection.selectionSet)
318
+ } : selection;
319
+ })
320
+ );
321
+ return { definition, apply };
322
+ }
323
+
324
+ // src/core/variants/resolve.ts
325
+ function personalizationPaths(data) {
326
+ const paths = /* @__PURE__ */ new Map();
327
+ const walk = (value, path) => {
328
+ if (Array.isArray(value)) {
329
+ for (const item of value) {
330
+ if (contextOf(item)?.kind === "PERSONALIZATION") {
331
+ const record = item;
332
+ const type = record[PREPR_TYPE_ALIAS] ?? record.__typename;
333
+ const types = paths.get(path) ?? /* @__PURE__ */ new Set();
334
+ types.add(typeof type === "string" ? type : "*");
335
+ paths.set(path, types);
336
+ }
337
+ walk(item, path);
338
+ }
339
+ return;
340
+ }
341
+ if (!value || typeof value !== "object") return;
342
+ for (const [key, child] of Object.entries(value)) {
343
+ if (key !== PREPR_CONTEXT_ALIAS && key !== PREPR_TYPE_ALIAS)
344
+ walk(child, path ? `${path}.${key}` : key);
345
+ }
346
+ };
347
+ walk(data, "");
348
+ return paths;
349
+ }
350
+ function contextOf(item) {
351
+ if (!item || typeof item !== "object") return null;
352
+ const context = item[PREPR_CONTEXT_ALIAS];
353
+ const ctx = context;
354
+ return ctx?.kind && ctx.group_id ? ctx : null;
355
+ }
356
+
357
+ // src/core/variants/variants-document.ts
358
+ function variantsSelectionSet(set, typeName, schema) {
359
+ const selections = set.selections.map((selection) => {
360
+ if (selection.kind === "InlineFragment") {
361
+ return {
362
+ ...selection,
363
+ selectionSet: variantsSelectionSet(
364
+ selection.selectionSet,
365
+ selection.typeCondition?.name.value ?? typeName,
366
+ schema
367
+ )
368
+ };
369
+ }
370
+ if (selection.kind !== "Field" || !selection.selectionSet) return selection;
371
+ const field = schema.types[typeName]?.fields[selection.name.value];
372
+ if (!field) return selection;
373
+ const child = variantsSelectionSet(
374
+ selection.selectionSet,
375
+ field.type,
376
+ schema
377
+ );
378
+ if (!field.personalizable) return { ...selection, selectionSet: child };
379
+ return {
380
+ ...selection,
381
+ arguments: [
382
+ ...withoutPersonalizeArg(selection.arguments),
383
+ {
384
+ kind: "Argument",
385
+ name: name("personalize"),
386
+ value: { kind: "BooleanValue", value: false }
387
+ }
388
+ ],
389
+ selectionSet: selectionSet([
390
+ ...child.selections,
391
+ ...contextSelections(field.type, schema)
392
+ ])
393
+ };
394
+ });
395
+ return { ...set, selections };
396
+ }
397
+ function toVariantsDocument(document, schema) {
398
+ const doc = documentOf(document);
399
+ return {
400
+ ...doc,
401
+ definitions: doc.definitions.map((definition) => {
402
+ if (definition.kind === "OperationDefinition") {
403
+ return {
404
+ ...definition,
405
+ selectionSet: variantsSelectionSet(
406
+ definition.selectionSet,
407
+ schema.queryType,
408
+ schema
409
+ )
410
+ };
411
+ }
412
+ if (definition.kind === "FragmentDefinition") {
413
+ return {
414
+ ...definition,
415
+ selectionSet: variantsSelectionSet(
416
+ definition.selectionSet,
417
+ definition.typeCondition.name.value,
418
+ schema
419
+ )
420
+ };
421
+ }
422
+ return definition;
423
+ })
424
+ };
425
+ }
426
+
427
+ // src/core/variants/queries.ts
428
+ function toVariantsQuery(document, schema) {
429
+ return resolveQuery(toVariantsDocument(document, schema));
430
+ }
431
+ function toDecisionQuery(document, schema, options = {}) {
432
+ const paths = options.from === void 0 ? void 0 : personalizationPaths(options.from);
433
+ if (paths && paths.size === 0) return null;
434
+ const decision = toDecisionDocument(document, schema, paths, {
435
+ topLevelOnly: !paths && options.topLevelOnly
436
+ });
437
+ return decision ? resolveQuery(decision) : null;
438
+ }
439
+
440
+ // src/core/variants/schema.ts
441
+ function namedType(ref) {
442
+ let current = ref;
443
+ while (current && !current.name) current = current.ofType;
444
+ return current?.name ?? "";
445
+ }
446
+ function toSchemaInfo(introspection) {
447
+ const types = {};
448
+ for (const type of introspection.__schema.types) {
449
+ if (type.name.startsWith("__")) continue;
450
+ const fields = {};
451
+ for (const field of type.fields ?? []) {
452
+ fields[field.name] = {
453
+ type: namedType(field.type),
454
+ personalizable: field.args.some((arg) => arg.name === "personalize")
455
+ };
456
+ }
457
+ types[type.name] = {
458
+ fields,
459
+ possibleTypes: (type.possibleTypes ?? []).map((t) => t.name),
460
+ hasContext: "_context" in fields
461
+ };
462
+ }
463
+ return { queryType: introspection.__schema.queryType.name, types };
464
+ }
465
+
466
+ // src/codegen/index.ts
467
+ function typeRef(type) {
468
+ const value = type;
469
+ return value.ofType ? { name: null, ofType: typeRef(value.ofType) } : { name: value.name ?? null };
470
+ }
471
+ function introspect(schema) {
472
+ const types = Object.values(
473
+ schema.getTypeMap()
474
+ ).map((type) => {
475
+ const possible = "getTypes" in type || "getInterfaces" in type ? schema.getPossibleTypes(type) : [];
476
+ return {
477
+ name: type.name,
478
+ possibleTypes: possible.length ? possible.map((member) => ({ name: member.name })) : null,
479
+ fields: type.getFields ? Object.values(type.getFields()).map((field) => ({
480
+ name: field.name,
481
+ args: (field.args ?? []).map((arg) => ({ name: arg.name })),
482
+ type: typeRef(field.type)
483
+ })) : null
484
+ };
485
+ });
486
+ return {
487
+ __schema: {
488
+ queryType: { name: schema.getQueryType()?.name ?? "Query" },
489
+ types
490
+ }
491
+ };
492
+ }
493
+ function spreadNames(node, into) {
494
+ if (Array.isArray(node)) {
495
+ for (const child of node) spreadNames(child, into);
496
+ } else if (node && typeof node === "object") {
497
+ const value = node;
498
+ if (value.kind === "FragmentSpread" && value.name) {
499
+ into.add(value.name.value);
500
+ }
501
+ for (const [key, child] of Object.entries(node)) {
502
+ if (key !== "loc") spreadNames(child, into);
503
+ }
504
+ }
505
+ return into;
506
+ }
507
+ function plugin(schema, documents, _config) {
508
+ const info = toSchemaInfo(introspect(schema));
509
+ const definitions = documents.flatMap((source) => [
510
+ ...source.document?.definitions ?? []
511
+ ]);
512
+ const fragments = /* @__PURE__ */ new Map();
513
+ for (const definition of definitions) {
514
+ if (definition.kind === "FragmentDefinition") {
515
+ fragments.set(definition.name.value, definition);
516
+ }
517
+ }
518
+ const lines = [
519
+ "// Generated by @preprio/toolkit/graphql/codegen. Do not edit."
520
+ ];
521
+ const seen = /* @__PURE__ */ new Set();
522
+ for (const definition of definitions) {
523
+ if (definition.kind !== "OperationDefinition") continue;
524
+ const operation = definition;
525
+ if (operation.operation !== "query" || !operation.name) continue;
526
+ const name2 = operation.name.value;
527
+ if (seen.has(name2)) {
528
+ throw new Error(
529
+ `@preprio/toolkit codegen: two queries are named "${name2}"; rename one so their exports do not collide.`
530
+ );
531
+ }
532
+ seen.add(name2);
533
+ const used = /* @__PURE__ */ new Set();
534
+ const queue = [...spreadNames(operation, /* @__PURE__ */ new Set())];
535
+ while (queue.length) {
536
+ const next = queue.pop();
537
+ if (used.has(next) || !fragments.has(next)) continue;
538
+ used.add(next);
539
+ queue.push(...spreadNames(fragments.get(next), /* @__PURE__ */ new Set()));
540
+ }
541
+ const document = {
542
+ kind: "Document",
543
+ definitions: [operation, ...[...used].map((n) => fragments.get(n))]
544
+ };
545
+ const decision = toDecisionQuery(document, info);
546
+ if (!decision) continue;
547
+ lines.push(
548
+ `export const ${name2}VariantsQuery = ${JSON.stringify(toVariantsQuery(document, info))};`,
549
+ `export const ${name2}DecisionQuery = ${JSON.stringify(decision)};`
550
+ );
551
+ }
552
+ return lines.join("\n") + "\n";
553
+ }
554
+ // Annotate the CommonJS export names for ESM import in node:
555
+ 0 && (module.exports = {
556
+ plugin
557
+ });
@@ -0,0 +1,23 @@
1
+ import { GraphQLSchema, DocumentNode } from 'graphql';
2
+
3
+ /**
4
+ * graphql-codegen plugin: for every named query that touches personalizable
5
+ * fields, writes the variants query and the decision query as string
6
+ * constants, `<Name>VariantsQuery` and `<Name>DecisionQuery`. For sites that
7
+ * send queries with their own client and want the rewrites done at build
8
+ * time instead of loading the schema at runtime.
9
+ *
10
+ * The decision query asks about every personalizable list of the query. When
11
+ * the variants result is at hand at runtime, `toDecisionQuery(query, schema,
12
+ * { from })` is smaller and faster for visitors Prepr has not seen before.
13
+ *
14
+ * Register it in codegen.ts: `plugins: ['@preprio/toolkit/graphql/codegen']`.
15
+ *
16
+ * @throws Error when two queries share a name, since their exports would
17
+ * collide.
18
+ */
19
+ declare function plugin(schema: GraphQLSchema, documents: {
20
+ document?: DocumentNode;
21
+ }[], _config?: Record<string, never>): string;
22
+
23
+ export { plugin };
@@ -0,0 +1,23 @@
1
+ import { GraphQLSchema, DocumentNode } from 'graphql';
2
+
3
+ /**
4
+ * graphql-codegen plugin: for every named query that touches personalizable
5
+ * fields, writes the variants query and the decision query as string
6
+ * constants, `<Name>VariantsQuery` and `<Name>DecisionQuery`. For sites that
7
+ * send queries with their own client and want the rewrites done at build
8
+ * time instead of loading the schema at runtime.
9
+ *
10
+ * The decision query asks about every personalizable list of the query. When
11
+ * the variants result is at hand at runtime, `toDecisionQuery(query, schema,
12
+ * { from })` is smaller and faster for visitors Prepr has not seen before.
13
+ *
14
+ * Register it in codegen.ts: `plugins: ['@preprio/toolkit/graphql/codegen']`.
15
+ *
16
+ * @throws Error when two queries share a name, since their exports would
17
+ * collide.
18
+ */
19
+ declare function plugin(schema: GraphQLSchema, documents: {
20
+ document?: DocumentNode;
21
+ }[], _config?: Record<string, never>): string;
22
+
23
+ export { plugin };
@@ -0,0 +1,99 @@
1
+ import {
2
+ toDecisionQuery,
3
+ toSchemaInfo,
4
+ toVariantsQuery
5
+ } from "../chunk-M3RBYJ5J.js";
6
+ import "../chunk-SF6TN4JR.js";
7
+ import "../chunk-TN6SNAR2.js";
8
+
9
+ // src/codegen/index.ts
10
+ function typeRef(type) {
11
+ const value = type;
12
+ return value.ofType ? { name: null, ofType: typeRef(value.ofType) } : { name: value.name ?? null };
13
+ }
14
+ function introspect(schema) {
15
+ const types = Object.values(
16
+ schema.getTypeMap()
17
+ ).map((type) => {
18
+ const possible = "getTypes" in type || "getInterfaces" in type ? schema.getPossibleTypes(type) : [];
19
+ return {
20
+ name: type.name,
21
+ possibleTypes: possible.length ? possible.map((member) => ({ name: member.name })) : null,
22
+ fields: type.getFields ? Object.values(type.getFields()).map((field) => ({
23
+ name: field.name,
24
+ args: (field.args ?? []).map((arg) => ({ name: arg.name })),
25
+ type: typeRef(field.type)
26
+ })) : null
27
+ };
28
+ });
29
+ return {
30
+ __schema: {
31
+ queryType: { name: schema.getQueryType()?.name ?? "Query" },
32
+ types
33
+ }
34
+ };
35
+ }
36
+ function spreadNames(node, into) {
37
+ if (Array.isArray(node)) {
38
+ for (const child of node) spreadNames(child, into);
39
+ } else if (node && typeof node === "object") {
40
+ const value = node;
41
+ if (value.kind === "FragmentSpread" && value.name) {
42
+ into.add(value.name.value);
43
+ }
44
+ for (const [key, child] of Object.entries(node)) {
45
+ if (key !== "loc") spreadNames(child, into);
46
+ }
47
+ }
48
+ return into;
49
+ }
50
+ function plugin(schema, documents, _config) {
51
+ const info = toSchemaInfo(introspect(schema));
52
+ const definitions = documents.flatMap((source) => [
53
+ ...source.document?.definitions ?? []
54
+ ]);
55
+ const fragments = /* @__PURE__ */ new Map();
56
+ for (const definition of definitions) {
57
+ if (definition.kind === "FragmentDefinition") {
58
+ fragments.set(definition.name.value, definition);
59
+ }
60
+ }
61
+ const lines = [
62
+ "// Generated by @preprio/toolkit/graphql/codegen. Do not edit."
63
+ ];
64
+ const seen = /* @__PURE__ */ new Set();
65
+ for (const definition of definitions) {
66
+ if (definition.kind !== "OperationDefinition") continue;
67
+ const operation = definition;
68
+ if (operation.operation !== "query" || !operation.name) continue;
69
+ const name = operation.name.value;
70
+ if (seen.has(name)) {
71
+ throw new Error(
72
+ `@preprio/toolkit codegen: two queries are named "${name}"; rename one so their exports do not collide.`
73
+ );
74
+ }
75
+ seen.add(name);
76
+ const used = /* @__PURE__ */ new Set();
77
+ const queue = [...spreadNames(operation, /* @__PURE__ */ new Set())];
78
+ while (queue.length) {
79
+ const next = queue.pop();
80
+ if (used.has(next) || !fragments.has(next)) continue;
81
+ used.add(next);
82
+ queue.push(...spreadNames(fragments.get(next), /* @__PURE__ */ new Set()));
83
+ }
84
+ const document = {
85
+ kind: "Document",
86
+ definitions: [operation, ...[...used].map((n) => fragments.get(n))]
87
+ };
88
+ const decision = toDecisionQuery(document, info);
89
+ if (!decision) continue;
90
+ lines.push(
91
+ `export const ${name}VariantsQuery = ${JSON.stringify(toVariantsQuery(document, info))};`,
92
+ `export const ${name}DecisionQuery = ${JSON.stringify(decision)};`
93
+ );
94
+ }
95
+ return lines.join("\n") + "\n";
96
+ }
97
+ export {
98
+ plugin
99
+ };