graphql-data-generator 0.1.0

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/esm/codegen.js ADDED
@@ -0,0 +1,474 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { Kind, parse } from "graphql";
3
+ import fg from "fast-glob";
4
+ import { join } from "node:path";
5
+ import { raise } from "./util.js";
6
+ const getType = ({ type, ...props }) => {
7
+ if (type.kind === "NamedType") {
8
+ if (props.selections) {
9
+ const def = props.definitions[type.name.value];
10
+ const implementations = def?.[0].kind === "InterfaceTypeDefinition"
11
+ ? Object.values(props.definitions)
12
+ .filter((v) => v?.[0].kind === "ObjectTypeDefinition" &&
13
+ v[0].interfaces?.some((i) => i.name.value === def[0].name.value) ||
14
+ false)
15
+ : def?.[0].kind === "UnionTypeDefinition"
16
+ ? Object.values(props.definitions)
17
+ .filter((v) => "types" in def[0] &&
18
+ def[0].types?.some((t) => v && t.name.value === v[0].name.value) ||
19
+ false)
20
+ : [];
21
+ const groupedValues = getSelectionsType(type.name.value, props.selections, props.definitions, props.fragments, props.references, props.includeTypenames).reduce((union, [name, value, group]) => {
22
+ group ??= type.name.value;
23
+ if (!union[group]) {
24
+ union[group] = {};
25
+ Object.defineProperty(union[group], "__typename", {
26
+ enumerable: props.includeTypenames &&
27
+ props.definitions[group]?.[0].kind === "ObjectTypeDefinition",
28
+ value: { kind: "StringLiteral", value: group, optional: false },
29
+ });
30
+ }
31
+ union[group][name] = value;
32
+ const def = props.definitions[group];
33
+ if (def) {
34
+ if (implementations.length) {
35
+ for (const implementation of implementations) {
36
+ implementation[1].add(name);
37
+ }
38
+ }
39
+ else
40
+ def[1].add(name);
41
+ }
42
+ return union;
43
+ }, {});
44
+ const value = groupedValues[type.name.value] ?? {};
45
+ delete groupedValues[type.name.value];
46
+ const nonExhaustive = implementations
47
+ .filter((o) => !(o[0].name.value in groupedValues)).map((o) => o[0].name.value);
48
+ return {
49
+ kind: "Object",
50
+ value,
51
+ conditionals: Object.values(groupedValues).map((value) => ({
52
+ kind: "Object",
53
+ value,
54
+ optional: false,
55
+ })),
56
+ nonExhaustive,
57
+ optional: props.optional ?? true,
58
+ };
59
+ }
60
+ const reference = props.references[type.name.value];
61
+ if (reference)
62
+ reference[1] = true;
63
+ return {
64
+ kind: "Name",
65
+ value: type.name.value,
66
+ optional: props.optional ?? true,
67
+ };
68
+ }
69
+ else if (type.kind === "NonNullType") {
70
+ return getType({ ...props, type: type.type, optional: false });
71
+ }
72
+ else if (type.kind === "ListType") {
73
+ return {
74
+ kind: "List",
75
+ value: getType({ ...props, type: type.type, optional: true }),
76
+ optional: props.optional ?? true,
77
+ };
78
+ }
79
+ else
80
+ throw new Error(`Unhandled type '${type}'`);
81
+ };
82
+ const getSelectionsType = (name, selections, definitions, fragments, references, includeTypenames) => {
83
+ const selectionTypes = [];
84
+ for (const selection of selections) {
85
+ switch (selection.kind) {
86
+ case "Field": {
87
+ const selectionType = definitions[name];
88
+ if (!selectionType) {
89
+ throw new Error(`Could not find type '${selection.name.value}'`);
90
+ }
91
+ switch (selectionType[0].kind) {
92
+ case "ObjectTypeDefinition":
93
+ case "InterfaceTypeDefinition": {
94
+ const fieldType = selectionType[0].fields?.find((f) => f.name.value === selection.name.value);
95
+ if (!fieldType) {
96
+ throw new Error(`Could not find field '${selection.name.value}' on type '${name}'`);
97
+ }
98
+ selectionTypes.push([
99
+ selection.alias?.value ?? selection.name.value,
100
+ getType({
101
+ type: fieldType.type,
102
+ selections: selection.selectionSet?.selections,
103
+ definitions,
104
+ fragments,
105
+ references,
106
+ includeTypenames,
107
+ }),
108
+ ]);
109
+ break;
110
+ }
111
+ case "UnionTypeDefinition": {
112
+ const types = selectionType[0].types;
113
+ if (!types) {
114
+ throw new Error(`Expected types to be present on union '${selectionType[0].name.value}'`);
115
+ }
116
+ selectionTypes.push(...getSelectionsType(types[0].name.value, // Assuming the selection is in all types
117
+ [selection], definitions, fragments, references, includeTypenames));
118
+ break;
119
+ }
120
+ default:
121
+ throw new Error(`Unhandled selection type '${selectionType[0].kind}'`);
122
+ }
123
+ break;
124
+ }
125
+ case "InlineFragment": {
126
+ const subSelection = getSelectionsType(selection.typeCondition?.name.value ?? name, selection.selectionSet.selections, definitions, fragments, references, includeTypenames);
127
+ const group = selection.typeCondition?.name.value ??
128
+ selection.directives?.map((d) => d.name).join(",");
129
+ selectionTypes.push(...(group
130
+ ? subSelection.map(([n, t, g]) => [n, t, g ? `${group}:${g}` : group])
131
+ : subSelection));
132
+ break;
133
+ }
134
+ case "FragmentSpread": {
135
+ const fragment = fragments[selection.name.value];
136
+ if (!fragment) {
137
+ throw new Error(`Could not find fragment '${selection.name.value}' in '${name}'`);
138
+ }
139
+ selectionTypes.push(...getSelectionsType(fragment.typeCondition.name.value, fragment.selectionSet.selections, definitions, fragments, references, includeTypenames));
140
+ break;
141
+ }
142
+ default:
143
+ throw new Error(`Unhandled selection kind '${selection.kind}'`);
144
+ }
145
+ }
146
+ return selectionTypes;
147
+ };
148
+ const getOperationType = (operation, definitions, fragments, root, references, includeTypenames) => ({
149
+ kind: "Object",
150
+ value: Object.fromEntries(operation.selectionSet.selections.map((selection) => {
151
+ if (selection.kind !== "Field") {
152
+ throw new Error(`Expected top-level selection on operation to be field, got '${selection.kind}'`);
153
+ }
154
+ const definition = root[selection.name.value];
155
+ if (!definition) {
156
+ throw new Error(`Could not find definition '${selection.name.value}'`);
157
+ }
158
+ return [
159
+ selection.alias?.value ?? selection.name.value,
160
+ getType({
161
+ type: definition.type,
162
+ selections: selection.selectionSet?.selections,
163
+ definitions,
164
+ fragments,
165
+ references,
166
+ includeTypenames,
167
+ }),
168
+ ];
169
+ })),
170
+ optional: false,
171
+ });
172
+ const getOperationVariables = (operation, references) => ({
173
+ kind: "Object",
174
+ value: Object.fromEntries(operation.variableDefinitions?.map((v) => [
175
+ v.variable.name.value,
176
+ getType({
177
+ type: v.type,
178
+ references,
179
+ definitions: {},
180
+ fragments: {},
181
+ includeTypenames: false,
182
+ }),
183
+ ]) ?? []),
184
+ optional: false,
185
+ });
186
+ const serializeType = (type, variables = false, depth = 0) => {
187
+ switch (type.kind) {
188
+ case "Name":
189
+ return `${type.value}${type.optional ? " | null" : ""}`;
190
+ case "List":
191
+ if (type.value.optional ||
192
+ (type.value.kind === "Object" &&
193
+ ((type.value.conditionals?.length ?? 0) -
194
+ (Object.keys(type.value.value).length ? 0 : 1)))) {
195
+ return `(${serializeType(type.value, variables, depth)})[]${type.optional ? " | null" : ""}`;
196
+ }
197
+ return `${serializeType(type.value, variables, depth)}[]${type.optional ? " | null" : ""}`;
198
+ case "Object": {
199
+ const content = Object.entries(type.value).map(([key, value]) => `${" ".repeat(depth + 1)}${key}${value.optional && variables ? "?" : ""}: ${serializeType(value, variables, depth + 1)};`).join("\n");
200
+ const ands = [
201
+ `{${content ? `\n${content}\n${" ".repeat(depth)}` : ""}}`,
202
+ ...(type.conditionals?.filter((c) => c.kind !== "Object" || !c.value.__typename)?.map((c) => `(${serializeType(c, variables, depth + 1)} | {})`) ??
203
+ []),
204
+ ];
205
+ const ors = type.conditionals
206
+ ?.filter((c) => c.kind === "Object" && c.value.__typename)
207
+ .map((c) => serializeType(c, variables, depth)) ?? [];
208
+ if (type.nonExhaustive?.length && ors.length) {
209
+ ors.push(`{ __typename: ${type.nonExhaustive.map((v) => `"${v}"`).join(" | ")} }`);
210
+ }
211
+ // TODO: Ideally this would be better formatted, but then I need to track
212
+ // depth
213
+ return `${[
214
+ ands[0] === "{}" ? undefined : ands[0],
215
+ ors.length > 1 && (ands.length !== 1 || ands[0] !== "{}")
216
+ ? `(${ors.join(" | ")})`
217
+ : ors.join(" | "),
218
+ ...ands.slice(1),
219
+ ].filter(Boolean).join(" & ")}${type.optional ? " | null" : ""}`;
220
+ }
221
+ case "StringLiteral":
222
+ return `"${type.value}"`;
223
+ }
224
+ };
225
+ const serializeInput = (fields, optional, inputs, references) => ({
226
+ kind: "Object",
227
+ value: Object.fromEntries(fields.map((f) => [
228
+ f.name.value,
229
+ fillOutInput(getType({
230
+ type: f.type,
231
+ references,
232
+ definitions: {},
233
+ fragments: {},
234
+ includeTypenames: false,
235
+ }), inputs, references),
236
+ ])),
237
+ optional,
238
+ });
239
+ const fillOutInput = (input, inputs, references) => {
240
+ switch (input.kind) {
241
+ case "List":
242
+ return { ...input, value: fillOutInput(input.value, inputs, references) };
243
+ case "Object":
244
+ return {
245
+ ...input,
246
+ value: Object.fromEntries(Object.entries(input.value).map(([k, v]) => [k, fillOutInput(v, inputs, references)])),
247
+ };
248
+ case "Name": {
249
+ const def = inputs[input.value];
250
+ if (!def)
251
+ return input;
252
+ return serializeInput(def[0].fields ?? [], input.optional, inputs, references);
253
+ }
254
+ case "StringLiteral":
255
+ return input;
256
+ }
257
+ };
258
+ const operationNames = {
259
+ query: { types: "Query", list: "queries" },
260
+ mutation: { types: "Mutation", list: "mutations" },
261
+ subscription: { types: "Subscription", list: "subscriptions" },
262
+ };
263
+ const simpleType = (type, types, optional = true) => {
264
+ switch (type.kind) {
265
+ case Kind.NON_NULL_TYPE:
266
+ return simpleType(type.type, types, false);
267
+ case Kind.LIST_TYPE:
268
+ return {
269
+ kind: "List",
270
+ value: simpleType(type.type, types),
271
+ optional,
272
+ };
273
+ case Kind.NAMED_TYPE:
274
+ return {
275
+ kind: "Name",
276
+ value: type.name.value,
277
+ optional,
278
+ };
279
+ }
280
+ };
281
+ export const codegen = (schema, files, { useEnums = true, scalars = {}, includeTypenames = true } = {}) => {
282
+ const schemaDoc = parse(schema);
283
+ const types = {};
284
+ const inputs = {};
285
+ const fragments = {};
286
+ const references = Object.fromEntries(["Int", "Float", "String", "Boolean", "ID"].map((name) => [name, [{
287
+ kind: Kind.SCALAR_TYPE_DEFINITION,
288
+ name: { kind: Kind.NAME, value: name },
289
+ }, false]]));
290
+ let query = {};
291
+ let mutation = {};
292
+ let subscription = {};
293
+ for (const definition of schemaDoc.definitions) {
294
+ switch (definition.kind) {
295
+ case "ObjectTypeDefinition":
296
+ if (definition.name.value === "Query") {
297
+ query = Object.fromEntries(definition.fields?.map((f) => [f.name.value, f]) ?? []);
298
+ }
299
+ else if (definition.name.value === "Mutation") {
300
+ mutation = Object.fromEntries(definition.fields?.map((f) => [f.name.value, f]) ?? []);
301
+ }
302
+ else if (definition.name.value === "Subscription") {
303
+ subscription = Object.fromEntries(definition.fields?.map((f) => [f.name.value, f]) ?? []);
304
+ }
305
+ else
306
+ types[definition.name.value] = [definition, new Set()];
307
+ break;
308
+ case "InputObjectTypeDefinition":
309
+ inputs[definition.name.value] = [definition, new Set()];
310
+ break;
311
+ case "InterfaceTypeDefinition":
312
+ types[definition.name.value] = [definition, new Set()];
313
+ break;
314
+ case "UnionTypeDefinition": {
315
+ const prev = types[definition.name.value];
316
+ if (prev?.[0].kind === "UnionTypeDefinition") {
317
+ types[definition.name.value] = [{
318
+ ...prev[0],
319
+ types: [...(prev[0].types ?? []), ...(definition.types ?? [])],
320
+ }, prev[1]];
321
+ }
322
+ else
323
+ types[definition.name.value] = [definition, new Set()];
324
+ break;
325
+ }
326
+ case "EnumTypeDefinition":
327
+ if (!references[definition.name.value]) {
328
+ references[definition.name.value] = [definition, false];
329
+ }
330
+ else {
331
+ const prev = references[definition.name.value][0];
332
+ references[definition.name.value][0] = {
333
+ ...prev,
334
+ values: [
335
+ ...(prev.values ?? []),
336
+ ...(definition.values ?? []),
337
+ ],
338
+ };
339
+ }
340
+ break;
341
+ case "ScalarTypeDefinition":
342
+ references[definition.name.value] = [definition, false];
343
+ break;
344
+ default:
345
+ throw new Error(`Unhandled definition type '${definition.kind}'`);
346
+ }
347
+ }
348
+ const roots = { query, mutation, subscription };
349
+ const operations = {
350
+ query: [],
351
+ mutation: [],
352
+ subscription: [],
353
+ };
354
+ for (const { path, content } of files) {
355
+ const dom = parse(content);
356
+ for (const definition of dom.definitions) {
357
+ switch (definition.kind) {
358
+ case "OperationDefinition": {
359
+ const name = definition.name?.value;
360
+ if (!name) {
361
+ console.warn(`Skipping unnamed operation in '${path}'`);
362
+ continue;
363
+ }
364
+ operations[definition.operation].push({
365
+ name,
366
+ path,
367
+ definition: definition,
368
+ });
369
+ break;
370
+ }
371
+ case "FragmentDefinition":
372
+ fragments[definition.name.value] = definition;
373
+ break;
374
+ default:
375
+ throw new Error(`Unhandled definition kind '${definition.kind}' in operation file '${path}'`);
376
+ }
377
+ }
378
+ }
379
+ const handledInputs = new Set();
380
+ const serializedTypes = Object.entries(operations).filter(([, v]) => v.length)
381
+ .flatMap(([name, collection]) => [
382
+ ...collection.flatMap((c) => c.definition.variableDefinitions?.map((v) => {
383
+ let type = getType({
384
+ type: v.type,
385
+ definitions: inputs,
386
+ references,
387
+ fragments: {},
388
+ includeTypenames: false,
389
+ });
390
+ let inputType = fillOutInput(type, inputs, references);
391
+ if (JSON.stringify(type) === JSON.stringify(inputType))
392
+ return;
393
+ if (type.kind === "List")
394
+ type = type.value;
395
+ if (inputType.kind === "List")
396
+ inputType = inputType.value;
397
+ if (type.kind !== "Name") {
398
+ throw new Error(`Could not find type for variable '${v.variable.name.value}'`);
399
+ }
400
+ if (handledInputs.has(type.value))
401
+ return;
402
+ handledInputs.add(type.value);
403
+ // return `type ${type.value} = ${serializeType(inputType)};`;
404
+ }).filter(Boolean)),
405
+ `export type ${operationNames[name].types} = {
406
+ ${collection.map((o) => {
407
+ const data = serializeType(getOperationType(o.definition, types, fragments, roots[o.definition.operation], references, includeTypenames), false, 2);
408
+ const variables = getOperationVariables(o.definition, references);
409
+ return ` ${o.name}: {
410
+ data: ${data};${variables.kind === "Object" && Object.keys(variables.value).length
411
+ ? `
412
+ variables: ${serializeType(variables, true, 2)};`
413
+ : ""}
414
+ };`;
415
+ }).join("\n")}
416
+ };
417
+
418
+ export const ${operationNames[name].list} = {
419
+ ${collection.map((o) => ` ${o.name}: "${o.path}",`).join("\n")}
420
+ };`,
421
+ ]);
422
+ if (handledInputs.size) {
423
+ serializedTypes.unshift(...Array.from(handledInputs).map((i) => {
424
+ const def = inputs[i]?.[0];
425
+ if (!def)
426
+ throw new Error(`Could not find input '${i}'`);
427
+ return `type ${i} = ${serializeType(serializeInput(def.fields ?? [], false, {}, references))};`;
428
+ }), `export type Inputs = {
429
+ ${Array.from(handledInputs).map((i) => ` ${i}: ${i};`).join("\n")}
430
+ };`, `export const inputs = [${Array.from(handledInputs).map((i) => `"${i}"`).join(", ")}] as const;`);
431
+ }
432
+ const usedTypes = Object.entries(types)
433
+ .map(([name, info]) => [name, ...info])
434
+ .filter((data) => data[1].kind === "ObjectTypeDefinition" && data[2].size > 0);
435
+ if (usedTypes.length) {
436
+ serializedTypes.unshift(...usedTypes.map(([name, type, usage]) => `type ${name} = {
437
+ ${includeTypenames ? ` __typename: "${name}";\n` : ""}${type.fields?.filter((f) => usage.has(f.name.value)).map((v) => ` ${v.name.value}: ${serializeType(simpleType(v.type, types))};`).join("\n")}
438
+ };`), `export type Types = {
439
+ ${usedTypes.map(([name]) => ` ${name}: ${name};`).join("\n")}
440
+ };`, `export const types = [${usedTypes.map(([name]) => `"${name}"`).join(", ")}] as const;`);
441
+ }
442
+ const usedReferences = Object.values(references).filter((r) => r[1]).map((r) => r[0]);
443
+ serializedTypes.unshift(...usedReferences.map((r) => {
444
+ // TODO: warn if missing and use unknown instead
445
+ if (r.kind === "ScalarTypeDefinition") {
446
+ return `type ${r.name.value} = ${scalars[r.name.value] ??
447
+ raise(`Could not find scalar '${r.name.value}'`)};`;
448
+ }
449
+ if (useEnums) {
450
+ return `enum ${r.name.value} {
451
+ ${r.values?.map((r) => r.name.value).join(",\n ")}
452
+ }`;
453
+ }
454
+ else {
455
+ return `type ${r.name.value} = ${r.values?.map((r) => `"${r.name.value}"`).join(" | ")};`;
456
+ }
457
+ }));
458
+ return serializedTypes.join("\n\n") + "\n";
459
+ };
460
+ export const loadFiles = async (schemaPath, operationDirs) => {
461
+ const operationPromises = [];
462
+ for (const dir of operationDirs) {
463
+ for await (const path of fg.stream(join(dir, "**/*.gql"))) {
464
+ operationPromises.push(readFile(path.toString(), "utf-8").then((content) => ({
465
+ path: path.toString(),
466
+ content,
467
+ })));
468
+ }
469
+ }
470
+ return [
471
+ await readFile(schemaPath, "utf-8"),
472
+ await Promise.all(operationPromises),
473
+ ];
474
+ };
@@ -0,0 +1,65 @@
1
+ import type { ContravariantEmpty, OperationMock, Patch, SimpleOperationMock } from "./types.js";
2
+ type DefaultObjectTransformSwitch<T, U> = T extends (infer G)[] ? DefaultObjectTransformSwitch<G, U>[] : DefaultObjectTransform<T, U>;
3
+ type DefaultObjectTransform<T, U = T> = {
4
+ [K in keyof T]?: T[K] extends object ? DefaultObjectTransformSwitch<T[K], U> | ((host: U) => DefaultObjectTransformSwitch<T[K], U>) : T[K] | ((host: U) => T[K]);
5
+ };
6
+ export type Shift<T extends unknown[]> = T extends [infer _First, ...infer Rest] ? Rest : [];
7
+ type OperationBuilder<Data extends Record<string, unknown> = Record<string, unknown>, Variables = unknown, Transforms = unknown, Extra = ContravariantEmpty> = ((...patches: ((Patch<SimpleOperationMock<Data, Variables>> & Partial<Extra>) | ((prev: SimpleOperationMock<Data, Variables>) => Patch<SimpleOperationMock<Data, Variables>>))[]) => OperationBuilderWithMock<Data, Variables, Transforms, Extra>) & {
8
+ variables: (variables: Patch<Variables> | ((data: Data, variables: Variables) => Patch<Variables>)) => OperationBuilderWithMock<Data, Variables, Transforms, Extra>;
9
+ data: (data: Patch<Data> | ((variables: Variables, data: Data) => Patch<Data>)) => OperationBuilderWithMock<Data, Variables, Transforms, Extra>;
10
+ patch: (patch: Patch<{
11
+ data: Data;
12
+ variables: Variables;
13
+ }>) => OperationBuilderWithMock<Data, Variables, Transforms, Extra>;
14
+ } & {
15
+ [Transform in keyof Transforms]: Transforms[Transform] extends (...args: any[]) => unknown ? (...params: Shift<Parameters<Transforms[Transform]>>) => OperationBuilderWithMock<Data, Variables, Transforms, Extra> : () => OperationBuilderWithMock<Data, Variables, Transforms, Extra>;
16
+ };
17
+ type OperationBuilderWithMock<Data extends Record<string, unknown>, Variables, Transforms, Extra> = OperationBuilder<Data, Variables, Transforms> & OperationMock<Data, Variables> & Partial<Extra>;
18
+ type ObjectTransforms<T, Transforms> = {
19
+ [Transform in keyof Transforms]: Transforms[Transform] extends (...args: any[]) => any ? (...args: Shift<Parameters<Transforms[Transform]>>) => T & ObjectTransforms<T, Transforms> : () => T & ObjectTransforms<T, Transforms>;
20
+ } & {
21
+ patch: (patch: Patch<T> | ((prev: T) => Patch<T>)) => T & ObjectTransforms<T, Transforms>;
22
+ };
23
+ type ObjectBuilder<T, Transforms> = ((...patches: (Patch<T> | ((previous: T) => Patch<T>))[]) => T & ObjectTransforms<T, Transforms>) & ObjectTransforms<T, Transforms>;
24
+ type CapitalizeFirst<S extends string> = S extends `${infer F}${infer R}` ? `${Uppercase<F>}${R}` : S;
25
+ type PrefixKeys<T, Prefix extends string> = {
26
+ [K in keyof T as `${Prefix}${CapitalizeFirst<string & K>}`]: T[K];
27
+ };
28
+ type MapObjectsToBuilders<T, Transforms> = {
29
+ [K in keyof T]: ObjectBuilder<T[K], K extends keyof Transforms ? Transforms[K] : ContravariantEmpty>;
30
+ };
31
+ export type MapObjectsToTransforms<Objects extends Record<string, Record<string, unknown>>> = {
32
+ [Object in keyof Objects]?: Record<string, DefaultObjectTransform<Objects[Object], Objects[Object]> | ((prev: Objects[Object], ...args: any[]) => Patch<Objects[Object]>)>;
33
+ };
34
+ type InnerMapOperationsToTransforms<Operations> = {
35
+ [Operation in keyof Operations]?: Record<string, InferOperationTransforms<Operations[Operation]>>;
36
+ };
37
+ export type MapOperationsToTransforms<Queries, Mutations, Subscriptions, Types, Inputs> = InnerMapOperationsToTransforms<ResolveConflicts<Queries, Mutations, Subscriptions, Types, Inputs>>;
38
+ type MapOperationsToBuilders<T, Transforms, Extra> = {
39
+ [K in keyof T]: OperationBuilder<T[K] extends {
40
+ data: infer U;
41
+ } ? U extends Record<string, unknown> ? U : Record<string, unknown> : Record<string, unknown>, T[K] extends {
42
+ variables: infer U;
43
+ } ? U : unknown, K extends keyof Transforms ? Transforms[K] : ContravariantEmpty, Extra>;
44
+ };
45
+ type ResolveOperationConflicts<T, Name extends string, A, B, C, D> = Omit<T, keyof A | keyof B | keyof C | keyof D> & PrefixKeys<Pick<T, keyof T & (keyof A | keyof B | keyof C | keyof D)>, Name>;
46
+ type ResolveConflicts<Queries, Mutations, Subscriptions, Types, Inputs> = ResolveOperationConflicts<Queries, "queries", Mutations, Subscriptions, Types, Inputs> & ResolveOperationConflicts<Mutations, "mutations", Queries, Subscriptions, Types, Inputs> & ResolveOperationConflicts<Subscriptions, "subscriptions", Queries, Mutations, Types, Inputs>;
47
+ type DefaultOperationTransform<T> = {
48
+ data?: T extends {
49
+ data: infer D;
50
+ } ? Patch<D> : never;
51
+ variables?: T extends {
52
+ variables: infer V;
53
+ } ? Patch<V> : never;
54
+ };
55
+ type OperationTransform<T> = (b: {
56
+ data: T extends {
57
+ data: infer U;
58
+ } ? U : never;
59
+ variables: T extends {
60
+ variables: infer U;
61
+ } ? U : never;
62
+ }, ...args: any[]) => Patch<T>;
63
+ type InferOperationTransforms<T> = DefaultOperationTransform<T> | OperationTransform<T>;
64
+ export type Build<Queries, Mutations, Subscriptions, Types, Inputs, Transforms, Extra> = MapObjectsToBuilders<Types & Inputs, Transforms> & MapOperationsToBuilders<ResolveConflicts<Queries, Mutations, Subscriptions, Types, Inputs>, Transforms, Extra>;
65
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/esm/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export { init } from "./init.js";
2
+ export type { DeepPartial, Patch } from "./types.js";
3
+ export { codegen } from "./codegen.js";
4
+ export { proxy } from "./proxy.js";
5
+ export { formatCode, toObject } from "./util.js";
package/esm/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { init } from "./init.js";
2
+ export { codegen } from "./codegen.js";
3
+ export { proxy } from "./proxy.js";
4
+ export { formatCode, toObject } from "./util.js";
package/esm/init.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import type { Build, MapObjectsToTransforms, MapOperationsToTransforms } from "./extendedTypes.js";
2
+ import type { ContravariantEmpty, OperationMock } from "./types.js";
3
+ export declare const init: <Query extends Record<string, {
4
+ data: Record<string, unknown>;
5
+ variables?: Record<string, unknown>;
6
+ }>, Mutation extends Record<string, {
7
+ data: Record<string, unknown>;
8
+ variables?: Record<string, unknown>;
9
+ }>, Subscription extends Record<string, {
10
+ data: Record<string, unknown>;
11
+ variables?: Record<string, unknown>;
12
+ }>, Types extends Record<string, Record<string, unknown>>, Inputs extends Record<string, Record<string, unknown>>, Extra = object>(schema: string, queries: { [operation in keyof Query]: string; }, mutations: { [operation in keyof Mutation]: string; }, subscriptions: { [operation in keyof Subscription]: string; }, types: readonly (keyof Types & string)[], inputs: readonly (keyof Inputs & string)[], scalars: {
13
+ [name: string]: ((typeName: string, fieldName: string) => unknown) | string | number | boolean | null;
14
+ }, options?: {
15
+ finalizeOperation: <T extends OperationMock & Partial<Extra>>(operation: T) => T;
16
+ }) => <Transforms extends MapObjectsToTransforms<Types & Inputs> & MapOperationsToTransforms<Query, Mutation, Subscription, Types, Inputs>>(fn: (b: Build<Query, Mutation, Subscription, Types, Inputs, ContravariantEmpty, Extra>) => Transforms) => Build<Query, Mutation, Subscription, Types, Inputs, Transforms, Extra>;