graphql-jerky 1.0.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/build/lib.cjs ADDED
@@ -0,0 +1,1540 @@
1
+ 'use strict';
2
+
3
+ var graphql = require('graphql');
4
+ var jen = require('jennifer-js');
5
+ var format = require('jennifer-js/format');
6
+ var partition = require('just-partition');
7
+ var pascalCase = require('just-pascal-case');
8
+ var path = require('path');
9
+ var url = require('url');
10
+ var fs = require('fs/promises');
11
+ var ts = require('typescript');
12
+ var glob = require('glob');
13
+ var zip = require('just-zip-it');
14
+
15
+ async function parseSource(filepath) {
16
+ return ts.createSourceFile(filepath.href, await fs.readFile(filepath, "utf-8"), ts.ScriptTarget.ESNext);
17
+ }
18
+ function resolveModule(specifier, referrer) {
19
+ let url;
20
+ if (specifier.startsWith(".")) {
21
+ url = new URL(specifier.replace(/(?<!\.[jt]sx?)$/, ".ts"), referrer);
22
+ }
23
+ else {
24
+ // TODO use import_map.json
25
+ url = new URL(specifier);
26
+ }
27
+ if (url.protocol === "file:") {
28
+ return parseSource(url);
29
+ }
30
+ else {
31
+ throw new Error(`Unsupported protocol: ${url.protocol}`);
32
+ }
33
+ }
34
+ async function findExports(source, resolveModuleFn = resolveModule) {
35
+ const exports = {};
36
+ const namedExports = [];
37
+ for (const node of source.statements) {
38
+ if (ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) {
39
+ if (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {
40
+ if (node.modifiers.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword)) {
41
+ exports.default = { declaration: node, source, name: "default" };
42
+ }
43
+ else if (node.name) {
44
+ exports[node.name.getText(source)] = { declaration: node, source, name: node.name.getText(source) };
45
+ }
46
+ }
47
+ }
48
+ else if (ts.isTypeAliasDeclaration(node) || ts.isEnumDeclaration(node) || ts.isModuleDeclaration(node)) {
49
+ if (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {
50
+ exports[node.name.getText(source)] = { declaration: node, source, name: node.name.getText(source) };
51
+ }
52
+ }
53
+ else if (ts.isVariableStatement(node)) {
54
+ if (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {
55
+ for (const decl of node.declarationList.declarations) {
56
+ if (decl.name) {
57
+ exports[decl.name.getText(source)] = { declaration: decl, source, name: decl.name.getText(source) };
58
+ }
59
+ }
60
+ }
61
+ }
62
+ else if (ts.isExportDeclaration(node)) {
63
+ if (node.exportClause && ts.isNamedExports(node.exportClause)) {
64
+ if (node.moduleSpecifier) {
65
+ if (!ts.isStringLiteral(node.moduleSpecifier)) {
66
+ continue;
67
+ }
68
+ // export { whatever } from 'whatever';
69
+ const specifier = node.moduleSpecifier.text;
70
+ const moduleExports = await findExports(await resolveModuleFn(specifier, new URL(source.fileName)), resolveModuleFn);
71
+ for (const name of Array.from(node.exportClause.elements, (e) => e.name.getText(source))) {
72
+ if (!(name in moduleExports)) {
73
+ throw new Error(`Exported name ${name} not found in ${JSON.stringify(specifier)}`);
74
+ }
75
+ exports[name] = moduleExports[name];
76
+ }
77
+ }
78
+ else {
79
+ for (const element of node.exportClause.elements) {
80
+ namedExports.push({
81
+ name: element.name.text,
82
+ property: element.propertyName?.text,
83
+ });
84
+ // exports[element.name.getText(source)] = { declaration: element, source };
85
+ }
86
+ }
87
+ }
88
+ else if (!node.exportClause && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
89
+ // export * from 'whatever';
90
+ Object.assign(exports, await findExports(await resolveModuleFn(node.moduleSpecifier.text, new URL(source.fileName)), resolveModuleFn));
91
+ }
92
+ }
93
+ }
94
+ if (namedExports.length) {
95
+ const names = Object.fromEntries(namedExports.map((e) => [e.property ?? e.name, e.name]));
96
+ for (const statement of source.statements) {
97
+ if (ts.isVariableStatement(statement)) {
98
+ for (const decl of statement.declarationList.declarations) {
99
+ if (ts.isIdentifier(decl.name) && decl.name.getText(source) in names) {
100
+ exports[names[decl.name.getText(source)]] = {
101
+ declaration: decl,
102
+ source,
103
+ name: names[decl.name.getText(source)],
104
+ };
105
+ }
106
+ }
107
+ }
108
+ if (ts.isFunctionDeclaration(statement)) {
109
+ if (statement.name && ts.isIdentifier(statement.name) && statement.name.getText(source) in names) {
110
+ exports[names[statement.name.getText(source)]] = {
111
+ declaration: statement,
112
+ source,
113
+ name: names[statement.name.getText(source)],
114
+ };
115
+ }
116
+ }
117
+ if (ts.isClassDeclaration(statement)) {
118
+ if (statement.name && ts.isIdentifier(statement.name) && statement.name.getText(source) in names) {
119
+ exports[names[statement.name.getText(source)]] = {
120
+ declaration: statement,
121
+ source,
122
+ name: names[statement.name.getText(source)],
123
+ };
124
+ }
125
+ }
126
+ if (ts.isTypeAliasDeclaration(statement)) {
127
+ if (statement.name && ts.isIdentifier(statement.name) && statement.name.getText(source) in names) {
128
+ exports[names[statement.name.getText(source)]] = {
129
+ declaration: statement,
130
+ source,
131
+ name: names[statement.name.getText(source)],
132
+ };
133
+ }
134
+ }
135
+ if (ts.isInterfaceDeclaration(statement)) {
136
+ if (statement.name && ts.isIdentifier(statement.name) && statement.name.getText(source) in names) {
137
+ exports[names[statement.name.getText(source)]] = {
138
+ declaration: statement,
139
+ source,
140
+ name: names[statement.name.getText(source)],
141
+ };
142
+ }
143
+ }
144
+ if (ts.isEnumDeclaration(statement)) {
145
+ if (statement.name && ts.isIdentifier(statement.name) && statement.name.getText(source) in names) {
146
+ exports[names[statement.name.getText(source)]] = {
147
+ declaration: statement,
148
+ source,
149
+ name: names[statement.name.getText(source)],
150
+ };
151
+ }
152
+ }
153
+ if (ts.isImportDeclaration(statement)) {
154
+ if (statement.importClause && statement.importClause.namedBindings &&
155
+ ts.isNamedImports(statement.importClause.namedBindings)) {
156
+ let importExports;
157
+ for (const element of statement.importClause.namedBindings.elements) {
158
+ if (element.propertyName && ts.isIdentifier(element.propertyName) &&
159
+ element.propertyName.getText(source) in names) {
160
+ if (!importExports && ts.isStringLiteral(statement.moduleSpecifier)) {
161
+ const specifier = statement.moduleSpecifier.getText(source);
162
+ importExports = await findExports(await resolveModuleFn(specifier, new URL(source.fileName)), resolveModuleFn);
163
+ }
164
+ if (!importExports) {
165
+ throw new Error(`Unable to find exports for ${statement.moduleSpecifier.getText(source)}`);
166
+ }
167
+ if (!importExports[element.name.getText(source)]) {
168
+ throw new Error(`Exported name ${element.name.getText(source)} not found in ${JSON.stringify(statement.moduleSpecifier.getText(source))}`);
169
+ }
170
+ exports[names[element.propertyName.getText(source)]] = {
171
+ declaration: element,
172
+ source,
173
+ name: names[element.propertyName.getText(source)],
174
+ };
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+ }
181
+ return exports;
182
+ }
183
+ async function parseModule(source) {
184
+ const url$1 = typeof source === 'string' ? url.pathToFileURL(path.resolve(source)) : new URL(source.fileName);
185
+ source = typeof source === 'string' ? await parseSource(url$1) : source;
186
+ return {
187
+ path: url$1,
188
+ exports: await findExports(source),
189
+ source,
190
+ };
191
+ }
192
+ /**
193
+ * NOTE: this is an internal value in the TypeScript compiler
194
+ *
195
+ * @see https://github.com/microsoft/TypeScript/blob/0d0a79371471d627ae298a145f8009b05cbccb72/src/compiler/scanner.ts#L81
196
+ */
197
+ const keywords = new Set(Object.keys(ts.textToKeywordObj));
198
+
199
+ class RequiredPackages {
200
+ requires;
201
+ // map from symbol to module path
202
+ symbols = {};
203
+ aliases = {};
204
+ constructor(requires = {}) {
205
+ this.requires = requires;
206
+ for (const [pkg, symbols] of Object.entries(requires)) {
207
+ for (const symbol of symbols) {
208
+ this.symbols[symbol] = pkg;
209
+ }
210
+ }
211
+ }
212
+ addRequires(pkg, name, alias) {
213
+ if (!(pkg in this.requires)) {
214
+ this.requires[pkg] = new Set();
215
+ }
216
+ let symbol = alias || name;
217
+ if ((symbol in this.symbols || keywords.has(symbol)) && this.symbols[symbol] !== pkg) {
218
+ for (let i = 1; this.symbols[symbol = name + "$" + i] && this.symbols[symbol] !== pkg; i++)
219
+ ;
220
+ }
221
+ this.requires[pkg].add(symbol);
222
+ this.symbols[symbol] = pkg;
223
+ if (symbol !== name) {
224
+ this.aliases[symbol] = name;
225
+ }
226
+ return symbol;
227
+ }
228
+ }
229
+
230
+ function renderSymbolReference(pkgs, ref, alias) {
231
+ const ns = (ref.module ? jen.jen.id(pkgs.addRequires(ref.module, ref.symbol, alias ?? ref.alias)) : jen.jen.id(ref.symbol));
232
+ return ref.property ? ns.dot(ref.property) : ns;
233
+ }
234
+
235
+ function compareEntryKey([a], [b]) {
236
+ return a.localeCompare(b);
237
+ }
238
+ function compareName({ name: a }, { name: b }) {
239
+ return a.localeCompare(b);
240
+ }
241
+ function isPrimitiveType(type) {
242
+ switch (type.name) {
243
+ case "ID":
244
+ case "Int":
245
+ case "Float":
246
+ case "String":
247
+ case "Boolean":
248
+ return true;
249
+ }
250
+ return false;
251
+ }
252
+ function importAlias(line) {
253
+ const pos = line.indexOf(" as ");
254
+ if (pos === -1) {
255
+ return "";
256
+ }
257
+ return line.slice(pos + 4);
258
+ }
259
+ function renderImports(base, imports, aliases, extMode = "omit") {
260
+ return jen.statements(...imports.map(([pkg, symbols]) => {
261
+ let mod = pkg;
262
+ if (mod.startsWith("file:///")) {
263
+ mod = url.fileURLToPath(mod);
264
+ }
265
+ if (mod.startsWith('/')) {
266
+ mod = path.relative(base, mod);
267
+ if (!mod.startsWith(".")) {
268
+ mod = `./${mod}`;
269
+ }
270
+ }
271
+ if (extMode === "omit") {
272
+ const ext = path.extname(mod);
273
+ if (ext) {
274
+ mod = mod.slice(0, -ext.length);
275
+ }
276
+ }
277
+ else if (extMode === "replace") {
278
+ mod = mod.replace(/\.ts$/, ".js");
279
+ }
280
+ return jen.import.obj(...Array.from(symbols)
281
+ .sort((a, b) => a.localeCompare(b) || importAlias(a).localeCompare(importAlias(b)))
282
+ .map((symbol) => symbol in aliases ? jen.id(aliases[symbol]).as.id(symbol) : jen.id(symbol))).from.lit(mod);
283
+ }));
284
+ }
285
+ function isBuiltInDirective(name) {
286
+ // https://spec.graphql.org/draft/#sec-Type-System.Directives.Built-in-Directives
287
+ switch (name) {
288
+ case "deprecated":
289
+ case "skip":
290
+ case "include":
291
+ case "specifiedBy":
292
+ return true;
293
+ }
294
+ return false;
295
+ }
296
+ function truthify(arr) {
297
+ return arr.filter(Boolean);
298
+ }
299
+ class GeneratorContext {
300
+ _pkgs;
301
+ _extMode;
302
+ _scalarsInfo;
303
+ _fieldDirectivesInfo;
304
+ _inputDirectivesInfo;
305
+ _resolversInfo;
306
+ _subscribersInfo;
307
+ _graphqlModuleSpecifier;
308
+ constructor(options = {}) {
309
+ this._scalarsInfo = options.scalarsInfo ?? {};
310
+ this._fieldDirectivesInfo = options.fieldDirectivesInfo ?? {};
311
+ this._inputDirectivesInfo = options.inputDirectivesInfo ?? {};
312
+ this._resolversInfo = options.resolversInfo ?? {};
313
+ this._subscribersInfo = options.subscribersInfo ?? {};
314
+ this._graphqlModuleSpecifier = options.graphqlModuleSpecifier ?? "graphql";
315
+ this._pkgs = new RequiredPackages();
316
+ this._extMode = options.extMode ?? "omit";
317
+ }
318
+ _gql(name) {
319
+ return jen.id(this._pkgs.addRequires(this._graphqlModuleSpecifier, name));
320
+ }
321
+ _renderGraphQLTypeIdentifier(type) {
322
+ if (type instanceof graphql.GraphQLNonNull) {
323
+ return jen.new.add(this._gql("GraphQLNonNull")).params(this._renderGraphQLTypeIdentifier(type.ofType));
324
+ }
325
+ if (type instanceof graphql.GraphQLList) {
326
+ return jen.new.add(this._gql("GraphQLList")).params(this._renderGraphQLTypeIdentifier(type.ofType));
327
+ }
328
+ if (type instanceof graphql.GraphQLScalarType) {
329
+ if (isPrimitiveType(type)) {
330
+ return this._gql("GraphQL" + type.name);
331
+ }
332
+ return jen.id(type.name + "Scalar");
333
+ }
334
+ return jen.id(type.name + (type instanceof graphql.GraphQLEnumType ? "Enum" : type instanceof graphql.GraphQLDirective ? "Directive" : "Type"));
335
+ }
336
+ _renderArgumentsObject(args) {
337
+ return jen.obj(...Array.from(args)
338
+ .sort(compareName)
339
+ .map((arg) => jen.prop(arg.name, jen.obj(jen.prop("type", this._renderGraphQLTypeIdentifier(arg.type)), ...truthify([
340
+ arg.description && jen.prop("description", jen.lit(arg.description)),
341
+ arg.defaultValue && jen.prop("defaultValue", jen.lit(arg.defaultValue)),
342
+ arg.deprecationReason && jen.prop("deprecationReason", jen.lit(arg.deprecationReason)),
343
+ ])))));
344
+ }
345
+ _renderValueNode(node) {
346
+ switch (node.kind) {
347
+ case graphql.Kind.ENUM:
348
+ case graphql.Kind.STRING:
349
+ case graphql.Kind.BOOLEAN:
350
+ return jen.lit(node.value);
351
+ case graphql.Kind.INT:
352
+ case graphql.Kind.FLOAT:
353
+ return jen.id(node.value);
354
+ case graphql.Kind.NULL:
355
+ return jen.null;
356
+ case graphql.Kind.LIST:
357
+ return jen.array(...node.values.map((v) => this._renderValueNode(v)));
358
+ case graphql.Kind.OBJECT:
359
+ return jen.obj(...node.fields.map((f) => jen.prop(f.name.value, this._renderValueNode(f.value))));
360
+ }
361
+ throw new Error(`unexpected value kind: ${node.kind}`);
362
+ }
363
+ _renderArgumentNodes(nodes) {
364
+ return jen.obj(...Array.from(nodes ?? [], (arg) => jen.prop(arg.name.value, this._renderValueNode(arg.value))));
365
+ }
366
+ _renderFieldObject(type, f, inputFieldDirectives) {
367
+ let resolver = this._resolversInfo[type.name]?.[f.name];
368
+ if (type instanceof graphql.GraphQLObjectType && !resolver) {
369
+ // try to find resolver in interface in the declaration order
370
+ for (const iface of type.getInterfaces()) {
371
+ if ((resolver = this._resolversInfo[iface.name]?.[f.name])) {
372
+ break;
373
+ }
374
+ }
375
+ }
376
+ let resolveFn = resolver && renderSymbolReference(this._pkgs, resolver);
377
+ if (f.astNode?.directives?.length) {
378
+ // apply directives in reverse order
379
+ for (const directive of Array.from(f.astNode.directives).reverse()) {
380
+ const ref = this._fieldDirectivesInfo[directive.name.value];
381
+ if (!ref) {
382
+ continue;
383
+ }
384
+ if (!resolveFn) {
385
+ resolveFn = jen.arrow(jen.id("source").op(":").any).id("source").dot(f.name);
386
+ }
387
+ resolveFn = renderSymbolReference(this._pkgs, ref, `apply${pascalCase(directive.name.value)}FieldDirective`).call(resolveFn, ...(directive.arguments?.length ? [this._renderArgumentNodes(directive.arguments)] : []));
388
+ }
389
+ }
390
+ if (resolveFn) {
391
+ // args probably don't need to be transformed if there's no resolver
392
+ const argsWithDirectives = truthify(f.args?.map((arg) => this._findInputDirectiveInfoFromArgOrField(arg, inputFieldDirectives)) ?? []);
393
+ if (argsWithDirectives.length) {
394
+ resolveFn = jen.parens(jen.params(jen.prop("next", this._gql("GraphQLFieldResolver").types(jen.any, jen.any))).op(":")
395
+ .add(this._gql("GraphQLFieldResolver"))
396
+ .types(jen.any, jen.any, jen.id(type.name).dot(pascalCase(f.name + "_args")))
397
+ .op("=>").arrow(jen.id("source"), jen.id("args"), jen.id("context"), jen.id("info")).id("next").call(jen.id("source"), this._renderInputFieldsWithDirectives(jen.id("args"), argsWithDirectives, argsWithDirectives.length < f.args.length), jen.id("context"), jen.id("info"))).call(resolveFn);
398
+ }
399
+ }
400
+ // NOTE: The way subscribers work in the graphql-js is by calling `subscribe` on the top level fields, and then
401
+ // calling `resolve` on the nested fields. This means that subscribers only need to be defined on
402
+ // `Subscription`.
403
+ //
404
+ // In theory, an alternate implementation could be created to call `subscribe` at every level, but considering
405
+ // how subscribe functions work, it would be unclear how it would make sense.
406
+ //
407
+ // If you ever need such functionality, please open an issue and it can be discussed.
408
+ //
409
+ // @see https://github.com/graphql/graphql-js/blob/e9a81f2ba9020ec5fd0f67f5553ccabe392e95e8/src/execution/execute.ts#L1645
410
+ const subscriber = type.name === "Subscription" ? this._subscribersInfo[f.name] : undefined;
411
+ return jen.obj(jen.prop("type", this._renderGraphQLTypeIdentifier(f.type)), ...truthify([
412
+ f.args?.length && jen.prop("args", this._renderArgumentsObject(f.args)),
413
+ f.defaultValue && jen.prop("defaultValue", jen.lit(f.defaultValue)),
414
+ f.description && jen.prop("description", jen.lit(f.description)),
415
+ f.deprecationReason && jen.prop("deprecationReason", jen.lit(f.deprecationReason)),
416
+ // NOTE: Resolver functions on interface definitions are not used by the default graphql-js
417
+ // executor implementation, but nonetheless accessible by a potential alternate implementation.
418
+ resolveFn && jen.prop("resolve", jen.parens(resolveFn).as.any),
419
+ subscriber && jen.prop("subscribe", renderSymbolReference(this._pkgs, subscriber)),
420
+ ]));
421
+ }
422
+ _renderFieldsThunk(type, inputFieldDirectives) {
423
+ return jen.arrow().parens(jen.obj(...Object.values(type.getFields())
424
+ .sort(compareName)
425
+ .map((field) => jen.prop(field.name, this._renderFieldObject(type, field, inputFieldDirectives)))));
426
+ }
427
+ _renderOptionalGraphQLTypeType(type) {
428
+ if (type instanceof graphql.GraphQLNonNull) {
429
+ return this._renderGraphQLTypeType(type);
430
+ }
431
+ return jen.union(this._renderGraphQLTypeType(type), jen.undefined);
432
+ }
433
+ _deriveGraphQLTypeName(type) {
434
+ if (type instanceof graphql.GraphQLScalarType) {
435
+ const scalarType = this._findScalarType(type);
436
+ if (scalarType) {
437
+ return scalarType;
438
+ }
439
+ return "unknown";
440
+ }
441
+ if (type instanceof graphql.GraphQLEnumType) {
442
+ return "E" + type.name;
443
+ }
444
+ return type.name;
445
+ }
446
+ _scalarTypeTypeCache = {};
447
+ _findScalarType(type) {
448
+ if (type.name in this._scalarTypeTypeCache) {
449
+ return this._scalarTypeTypeCache[type.name];
450
+ }
451
+ let returnType;
452
+ const info = this._scalarsInfo[type.name];
453
+ if (info?.type) {
454
+ if (info.type.module) {
455
+ returnType = this._pkgs.addRequires(info.type.module, info.type.symbol);
456
+ }
457
+ returnType = info.type.symbol;
458
+ }
459
+ if (!returnType) {
460
+ // these are the built-in scalars
461
+ switch (type.name) {
462
+ case "ID":
463
+ returnType = "string | number";
464
+ break;
465
+ case "Int":
466
+ case "Float":
467
+ returnType = "number";
468
+ break;
469
+ case "String":
470
+ returnType = "string";
471
+ break;
472
+ case "Boolean":
473
+ returnType = "boolean";
474
+ break;
475
+ }
476
+ }
477
+ if (!returnType) {
478
+ console.log("WARNING: Could not determine scalar " + type.name + " type from parseValue or parseLiteral");
479
+ }
480
+ return (this._scalarTypeTypeCache[type.name] = returnType);
481
+ }
482
+ _renderGraphQLTypeType(type) {
483
+ if (type instanceof graphql.GraphQLNonNull) {
484
+ return this._renderGraphQLTypeType(type.ofType);
485
+ }
486
+ if (type instanceof graphql.GraphQLList) {
487
+ return jen.id("Array").types(this._renderOptionalGraphQLTypeType(type.ofType));
488
+ }
489
+ if (type instanceof graphql.GraphQLDirective) {
490
+ throw new Error("unexpected directive type " + type.name);
491
+ }
492
+ return jen.id(this._deriveGraphQLTypeName(type));
493
+ }
494
+ _renderTypeInterface(type) {
495
+ return jen.interface.add(this._renderGraphQLTypeType(type)).block(...Object.values(type.getFields())
496
+ .sort(compareName)
497
+ .map((field) => jen.prop(jen.id(field.name).op("?"), this._renderGraphQLTypeType(field.type))));
498
+ }
499
+ _renderGraphQLObjectTypeDefinition(type, { inputFieldDirectives }) {
500
+ const typeInterfaces = type.getInterfaces();
501
+ return jen.new.add(this._gql("GraphQLObjectType")).call(jen.obj(jen.prop("name", jen.lit(type.name)), jen.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives)), ...truthify([
502
+ type.description && jen.prop("description", jen.lit(type.description)),
503
+ typeInterfaces.length && jen.prop("interfaces", jen.arrow().arr(
504
+ // do not sort interfaces, the declaration order may be important
505
+ ...typeInterfaces.map(this._renderGraphQLTypeIdentifier, this))),
506
+ ]))).as.add(this._gql("GraphQLObjectType"));
507
+ }
508
+ _renderGraphQLObjectTypeTypes(type) {
509
+ const fieldsWithArgs = Object.values(type.getFields())
510
+ .filter((field) => field.args.length)
511
+ .sort(compareName);
512
+ return [
513
+ jen.export.add(this._renderTypeInterface(type)),
514
+ ...(fieldsWithArgs.length
515
+ ? [
516
+ jen.export.namespace.add(this._renderGraphQLTypeType(type)).block(...fieldsWithArgs.map((field) => jen.export.interface.id(pascalCase(field.name + "_args")).block(...Array.from(field.args)
517
+ .sort(compareName)
518
+ .map((arg) => jen.prop(arg.name, this._renderOptionalGraphQLTypeType(arg.type)))))),
519
+ ]
520
+ : []),
521
+ ];
522
+ }
523
+ _renderGraphQLScalarTypeDefinition(type) {
524
+ const s = this._scalarsInfo[type.name];
525
+ return jen.new.add(this._gql("GraphQLScalarType")).call(jen.obj(jen.prop("name", jen.lit(type.name)), ...truthify([
526
+ type.description && jen.prop("description", jen.lit(type.description)),
527
+ jen.prop("serialize", s?.serializeFunc ? renderSymbolReference(this._pkgs, s.serializeFunc) : jen.trivia("stub").arrow(jen.id("v")).id("v")),
528
+ s?.parseValueFunc && jen.prop("parseValue", renderSymbolReference(this._pkgs, s.parseValueFunc)),
529
+ s?.parseLiteralFunc && jen.prop("parseLiteral", renderSymbolReference(this._pkgs, s.parseLiteralFunc)),
530
+ ])));
531
+ }
532
+ _renderTypeResolverAndCastFunctions(type, subTypes, prefix) {
533
+ const sortedSubTypes = Array.from(subTypes).sort(compareName);
534
+ return [
535
+ jen.arrow(jen.prop("v", jen.any)).block(jen.switch(jen.id("v").computed(jen.id(prefix + "Symbol_" + type.name))).block(...sortedSubTypes.map((subType) => jen.case(jen.id(prefix + "TypeSymbol_" + subType.name + "_" + type.name)).return(jen.lit(subType.name)))), jen.return(jen.id("v").dot("__typename"))),
536
+ [
537
+ jen.const.id(prefix + "Symbol_" + type.name).op("=").id("Symbol").call(jen.lit(type.name + " type")),
538
+ ...sortedSubTypes.map((subType) => jen.const.id(prefix + "TypeSymbol_" + subType.name + "_" + type.name).op("=").id("Symbol").call(jen.lit(subType.name + " " + type.name))),
539
+ ...sortedSubTypes.map((subType) => jen.export.const.id("as" + subType.name + type.name).op("=").types(jen.id("T")).params(jen.prop("v", jen.any)).op(":").intersect(jen.id("T"), jen.obj(jen.prop(jen.computed(jen.id(prefix + "Symbol_" + type.name)), jen.symbol))).op("=>")
540
+ .parens(jen.obj(jen.spread(jen.id("v")), jen.prop(jen.computed(jen.id(prefix + "Symbol_" + type.name)), jen.id(prefix + "TypeSymbol_" + subType.name + "_" + type.name))))),
541
+ ],
542
+ ];
543
+ }
544
+ _renderGraphQLInterfaceTypeDefinition(type, { implementors: { implementors }, inputFieldDirectives }) {
545
+ return jen.new.add(this._gql("GraphQLInterfaceType")).call(jen.obj(jen.prop("name", jen.lit(type.name)), jen.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives)), ...truthify([
546
+ type.description && jen.prop("description", jen.lit(type.description)),
547
+ ]))).as.add(this._gql("GraphQLInterfaceType"));
548
+ }
549
+ _renderGraphQLInterfaceTypeTypes(type, { implementors: { implementors } }) {
550
+ const fieldsWithArgs = Object.values(type.getFields())
551
+ .filter((field) => field.args.length)
552
+ .sort(compareName);
553
+ return [
554
+ jen.export.add(this._renderTypeInterface(type)),
555
+ jen.export.namespace.id(type.name).block(...implementors.map((implementor) => jen.export.const.id("as" + pascalCase(implementor.name)).op("=")
556
+ .types(jen.id("T")).params(jen.prop("v", jen.id("T"))).op("=>").id("setTypename").call(jen.id("v"), jen.lit(implementor.name))), ...fieldsWithArgs.map((field) => jen.export.interface.id(pascalCase(field.name + "_args")).block(...Array.from(field.args)
557
+ .sort(compareName)
558
+ .map((arg) => jen.prop(arg.name, this._renderOptionalGraphQLTypeType(arg.type)))))),
559
+ ];
560
+ }
561
+ _renderGraphQLUnionTypeDefinition(type) {
562
+ return jen.new.add(this._gql("GraphQLUnionType")).call(jen.obj(jen.prop("name", jen.lit(type.name)), jen.prop("types", jen.arrow().array(...type.getTypes().map((type) => this._renderGraphQLTypeIdentifier(type)))), ...truthify([
563
+ type.description && jen.prop("description", jen.lit(type.description)),
564
+ ])));
565
+ }
566
+ _renderGraphQLUnionTypeTypes(type) {
567
+ return [
568
+ jen.export.type.add(this._renderGraphQLTypeType(type)).op("=").union(...Array.from(type.getTypes()).sort(compareName).map(this._renderGraphQLTypeType, this)),
569
+ jen.export.namespace.id(type.name).block(...type.getTypes().map((type) => jen.export.const.id("as" + pascalCase(type.name)).op("=")
570
+ .types(jen.id("T")).params(jen.prop("v", jen.id("T"))).op("=>").id("setTypename").call(jen.id("v"), jen.lit(type.name)))),
571
+ ];
572
+ }
573
+ _findInputDirectiveInfoFromArgOrField(field, inputFieldDirectives) {
574
+ const fieldTypeName = graphql.getNamedType(field.type).name;
575
+ let transform;
576
+ if (inputFieldDirectives[fieldTypeName] && Object.keys(inputFieldDirectives[fieldTypeName]).length) {
577
+ transform = {
578
+ symbol: "transform" + fieldTypeName,
579
+ };
580
+ }
581
+ if (field.astNode?.directives?.length) {
582
+ const directives = field.astNode.directives.flatMap((directive) => {
583
+ const ref = this._inputDirectivesInfo[directive.name.value];
584
+ if (!ref) {
585
+ return [];
586
+ }
587
+ return [{ ref, args: directive.arguments }];
588
+ });
589
+ if (directives.length) {
590
+ return { field, directives, transform };
591
+ }
592
+ }
593
+ if (transform) {
594
+ return { field, directives: [], transform };
595
+ }
596
+ }
597
+ _renderInputFieldsWithDirectives(valueExpr, fieldsWithDirectives, spread) {
598
+ return jen.obj(...truthify([
599
+ spread && jen.spread(valueExpr),
600
+ ]), ...fieldsWithDirectives.map(({ field, directives, transform }) => {
601
+ const fieldExpr = valueExpr.dot(field.name);
602
+ const nullableType = graphql.getNullableType(field.type);
603
+ let transformedExpr;
604
+ if (nullableType instanceof graphql.GraphQLList) {
605
+ transformedExpr = jen.id("elem");
606
+ }
607
+ else {
608
+ transformedExpr = fieldExpr;
609
+ }
610
+ if (transform) {
611
+ transformedExpr = renderSymbolReference(this._pkgs, transform).call(transformedExpr);
612
+ }
613
+ for (const { ref, args } of directives) {
614
+ transformedExpr = renderSymbolReference(this._pkgs, ref).call(transformedExpr, this._renderArgumentNodes(args));
615
+ }
616
+ if (nullableType instanceof graphql.GraphQLList) {
617
+ transformedExpr = jen.id("Array").dot("from").call(valueExpr.dot(field.name), jen.arrow(jen.id("elem")).add(transformedExpr));
618
+ if (!(field.type instanceof graphql.GraphQLNonNull)) {
619
+ transformedExpr = jen.cond(valueExpr.dot(field.name).op("===").null.op("||").add(valueExpr).dot(field.name).op("===").undefined, jen.undefined, transformedExpr);
620
+ }
621
+ }
622
+ return jen.prop(field.name, transformedExpr);
623
+ }));
624
+ }
625
+ _renderGraphQLInputObjectTypeDefinition(type, { inputFieldDirectives }) {
626
+ return jen.new.add(this._gql("GraphQLInputObjectType")).call(jen.obj(jen.prop("name", jen.lit(type.name)), jen.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives)), ...truthify([
627
+ type.description && jen.prop("description", jen.lit(type.description)),
628
+ ])));
629
+ }
630
+ _renderGraphQLInputObjectTypeTypes(type, { inputFieldDirectives }) {
631
+ const fieldsWithDirectives = truthify(Object.values(type.getFields())
632
+ .map((f) => this._findInputDirectiveInfoFromArgOrField(f, inputFieldDirectives)));
633
+ return [
634
+ jen.export.interface.add(this._renderGraphQLTypeType(type)).block(...Object.values(type.getFields())
635
+ .sort(compareName)
636
+ .map((field) => jen.prop(field.name, this._renderOptionalGraphQLTypeType(field.type)))),
637
+ ...truthify([
638
+ fieldsWithDirectives.length &&
639
+ jen.const.id("transform" + this._deriveGraphQLTypeName(type)).op("=").types(jen.id("T").extends.union(jen.id(type.name), jen.undefined)).params(jen.prop("v", jen.id("T")))
640
+ .op(":").id("T").op("=>").parens(jen.id("v").op("&&").add(this._renderInputFieldsWithDirectives(jen.id("v"), fieldsWithDirectives, fieldsWithDirectives.length < Object.keys(type.getFields()).length))),
641
+ ]),
642
+ ];
643
+ }
644
+ _renderGraphQLEnumTypeDefinition(type) {
645
+ const sortedValues = Array.from(type.getValues()).sort(compareName);
646
+ return jen.new.add(this._gql("GraphQLEnumType")).call(jen.obj(jen.prop("name", jen.lit(type.name)), jen.prop("values", jen.obj(...sortedValues.map((e) => jen.prop(e.name, jen.obj(jen.prop("value", jen.lit(e.value)), ...truthify([
647
+ e.description && jen.prop("description", jen.lit(e.description)),
648
+ e.deprecationReason && jen.prop("deprecationReason", jen.lit(e.deprecationReason)),
649
+ ])))))), ...truthify([
650
+ type.description && jen.prop("description", jen.lit(type.description)),
651
+ ])));
652
+ }
653
+ _renderGraphQLEnumTypeTypes(type) {
654
+ const sortedValues = Array.from(type.getValues()).sort(compareName);
655
+ return [
656
+ jen.export.enum.add(this._renderGraphQLTypeType(type)).obj(...sortedValues.map(({ name }) => jen.id(name).op("=").lit(name))),
657
+ jen.export.function(jen.id("is" + this._deriveGraphQLTypeName(type)), jen.prop("v", jen.id("any"))).op(":").id("v").is.add(this._renderGraphQLTypeType(type)).block(jen.return(jen.id("v").in.add(this._renderGraphQLTypeType(type)))),
658
+ ];
659
+ }
660
+ _getRenderDefintionFnForType(type) {
661
+ if (type instanceof graphql.GraphQLObjectType) {
662
+ return this._renderGraphQLObjectTypeDefinition.bind(this, type);
663
+ }
664
+ if (type instanceof graphql.GraphQLScalarType) {
665
+ return this._renderGraphQLScalarTypeDefinition.bind(this, type);
666
+ }
667
+ if (type instanceof graphql.GraphQLInterfaceType) {
668
+ return this._renderGraphQLInterfaceTypeDefinition.bind(this, type);
669
+ }
670
+ if (type instanceof graphql.GraphQLUnionType) {
671
+ return this._renderGraphQLUnionTypeDefinition.bind(this, type);
672
+ }
673
+ if (type instanceof graphql.GraphQLInputObjectType) {
674
+ return this._renderGraphQLInputObjectTypeDefinition.bind(this, type);
675
+ }
676
+ if (type instanceof graphql.GraphQLEnumType) {
677
+ return this._renderGraphQLEnumTypeDefinition.bind(this, type);
678
+ }
679
+ throw new Error("unhandled type: " + type.toString());
680
+ }
681
+ _getRenderTypesFnForType(type) {
682
+ if (type instanceof graphql.GraphQLObjectType) {
683
+ return this._renderGraphQLObjectTypeTypes.bind(this, type);
684
+ }
685
+ if (type instanceof graphql.GraphQLScalarType) {
686
+ return () => [];
687
+ }
688
+ if (type instanceof graphql.GraphQLInterfaceType) {
689
+ return this._renderGraphQLInterfaceTypeTypes.bind(this, type);
690
+ }
691
+ if (type instanceof graphql.GraphQLUnionType) {
692
+ return this._renderGraphQLUnionTypeTypes.bind(this, type);
693
+ }
694
+ if (type instanceof graphql.GraphQLInputObjectType) {
695
+ return this._renderGraphQLInputObjectTypeTypes.bind(this, type);
696
+ }
697
+ if (type instanceof graphql.GraphQLEnumType) {
698
+ return this._renderGraphQLEnumTypeTypes.bind(this, type);
699
+ }
700
+ throw new Error("unhandled type: " + type.toString());
701
+ }
702
+ _renderGraphQLTypeDefinitions(type, interfaces, inputFieldDirectives) {
703
+ return jen.const.add(this._renderGraphQLTypeIdentifier(type)).op("=").add(this._getRenderDefintionFnForType(type)({
704
+ implementors: interfaces[type.name],
705
+ inputFieldDirectives,
706
+ }));
707
+ }
708
+ _renderGraphQLTypeTypes(type, interfaces, inputFieldDirectives) {
709
+ return this._getRenderTypesFnForType(type)({
710
+ implementors: interfaces[type.name],
711
+ inputFieldDirectives,
712
+ });
713
+ }
714
+ _renderGraphQLDirectiveDefinition(directive) {
715
+ return jen.const.add(this._renderGraphQLTypeIdentifier(directive)).op("=").new.add(this._gql("GraphQLDirective"))
716
+ .call(jen.obj(jen.prop("name", jen.lit(directive.name)), jen.prop("locations", jen.array(...Array.from(directive.locations).sort().map((location) => jen.add(this._gql("DirectiveLocation")).dot(location)))), jen.prop("args", this._renderArgumentsObject(directive.args)), ...truthify([
717
+ directive.description && jen.prop("description", jen.lit(directive.description)),
718
+ directive.isRepeatable && jen.prop("isRepeatable", jen.true),
719
+ ])));
720
+ }
721
+ _renderGraphQLDirectiveTypes(directive) {
722
+ return truthify([
723
+ directive.args.length && jen.export.interface.id(pascalCase(directive.name + "_directive_args")).block(...directive.args.map((arg) => jen.prop(jen.id(arg.name).add(...truthify([
724
+ !(arg.type instanceof graphql.GraphQLNonNull) && jen.op("?"),
725
+ ])), this._renderGraphQLTypeType(arg.type)))),
726
+ ]);
727
+ }
728
+ schemaExprs(schema, [types, interfaces, inputFieldDirectives]) {
729
+ return [
730
+ ...[
731
+ // render type definitions
732
+ ...types
733
+ .map((type) => [type.name, this._renderGraphQLTypeDefinitions(type, interfaces, inputFieldDirectives)])
734
+ .sort(compareEntryKey),
735
+ // render directive definitions
736
+ ...schema.getDirectives()
737
+ .filter((d) => !isBuiltInDirective(d.name))
738
+ .map((directive) => [directive.name, this._renderGraphQLDirectiveDefinition(directive)])
739
+ .sort(compareEntryKey),
740
+ ].map(([, expr]) => expr),
741
+ // render schema
742
+ jen.const.id("schema").op("=").new.add(this._gql("GraphQLSchema")).call(jen.obj(...(schema.getQueryType()
743
+ ? [jen.prop("query", this._renderGraphQLTypeIdentifier(schema.getQueryType()))]
744
+ : []), ...(schema.getMutationType()
745
+ ? [jen.prop("mutation", this._renderGraphQLTypeIdentifier(schema.getMutationType()))]
746
+ : []), ...(schema.getSubscriptionType()
747
+ ? [jen.prop("subscription", this._renderGraphQLTypeIdentifier(schema.getSubscriptionType()))]
748
+ : []), jen.prop("types", jen.array(...types.map((type) => this._renderGraphQLTypeIdentifier(type)))), jen.prop("directives", jen.array(...Array.from(schema.getDirectives())
749
+ .filter((d) => !isBuiltInDirective(d.name))
750
+ .map((d) => this._renderGraphQLTypeIdentifier(d)))))),
751
+ jen.export.default.id("schema"),
752
+ ];
753
+ }
754
+ typesExprs(schema, [types, interfaces, inputFieldDirectives]) {
755
+ return [
756
+ ["", jen.const.id("setTypename").op("=").types(jen.id("T")).params(jen.id("v").op(":").id("T"), jen.id("t").op(":").string).op(":").id("T").op("=>").block(jen.if(jen.op("!").id("v").op("||").typeof(jen.id("v")).op("!==").lit("object")).block(jen.throw.new.id("Error").call(jen.lit("expected object"))), jen.return(jen.id("Object").dot("assign").call(jen.id("v"), jen.obj(jen.prop(jen.id("__typename"), jen.id("t"))))))],
757
+ // render type definitions
758
+ ...types
759
+ .map((type) => [type.name, jen.statements(...this._renderGraphQLTypeTypes(type, interfaces, inputFieldDirectives))])
760
+ .sort(compareEntryKey),
761
+ // render directive definitions
762
+ ...schema.getDirectives()
763
+ .filter((d) => !isBuiltInDirective(d.name))
764
+ .map((directive) => [directive.name, jen.statements(...this._renderGraphQLDirectiveTypes(directive))])
765
+ .sort(compareEntryKey),
766
+ ].map(([, expr]) => expr);
767
+ }
768
+ schemaAndTypesExprs(schema, [types, interfaces, inputFieldDirectives]) {
769
+ return [
770
+ ...this.schemaExprs(schema, [types, interfaces, inputFieldDirectives]),
771
+ ...this.typesExprs(schema, [types, interfaces, inputFieldDirectives]),
772
+ ];
773
+ }
774
+ renderFile(outfile, renderStatements) {
775
+ const base = outfile.startsWith("/") ? outfile : path.resolve(outfile);
776
+ const statements = renderStatements.call(this);
777
+ const [localImports, externalImports] = partition(Object.entries(this._pkgs.requires), ([pkg]) => pkg.startsWith("/"));
778
+ return format(jen.statements(renderImports(path.dirname(base), externalImports, this._pkgs.aliases, this._extMode), renderImports(path.dirname(base), localImports, this._pkgs.aliases, this._extMode), ...statements).toString());
779
+ }
780
+ static prepareInterfacesAndInputFieldDirectives(schema, options = {}) {
781
+ if (options.fieldDirectivesInfo) {
782
+ const names = new Set(Object.keys(options.fieldDirectivesInfo));
783
+ for (const directive of schema.getDirectives()) {
784
+ if (isBuiltInDirective(directive.name) ||
785
+ directive.locations.every((loc) => loc !== graphql.DirectiveLocation.FIELD_DEFINITION) ||
786
+ names.has(directive.name)) {
787
+ continue;
788
+ }
789
+ console.log(`WARNING: missing directive function for ${JSON.stringify(directive.name)}`);
790
+ }
791
+ }
792
+ const types = Object.entries(schema.getTypeMap())
793
+ .sort(compareEntryKey)
794
+ .filter(([, type]) => !type.name.startsWith("__") && !isPrimitiveType(type))
795
+ .map(([, type]) => type);
796
+ const inputFieldDirectives = {};
797
+ if (options.inputDirectivesInfo) {
798
+ // input field directives not needed if the module was not specified
799
+ let typesWithObjectFields = new Array();
800
+ for (const type of types) {
801
+ if (!(type instanceof graphql.GraphQLInputObjectType)) {
802
+ continue;
803
+ }
804
+ for (const field of Object.values(type.getFields())) {
805
+ if (graphql.getNamedType(field.type) instanceof graphql.GraphQLInputObjectType) {
806
+ typesWithObjectFields.push([type.name, field.name, graphql.getNamedType(field.type).name]);
807
+ }
808
+ const directives = field.astNode?.directives;
809
+ if (!directives) {
810
+ continue;
811
+ }
812
+ for (const directive of directives) {
813
+ const name = directive.name.value;
814
+ if (!options.inputDirectivesInfo[name]) {
815
+ continue;
816
+ }
817
+ const fieldDirectives = inputFieldDirectives[type.name] ?? (inputFieldDirectives[type.name] = {});
818
+ const fieldDirective = fieldDirectives[field.name] ?? (fieldDirectives[field.name] = []);
819
+ fieldDirective.push(name);
820
+ }
821
+ }
822
+ }
823
+ for (let changes = 1; changes; changes = 0) {
824
+ const newTypesWithObjectFields = new Array();
825
+ for (const [typeName, fieldName, objectTypeName] of typesWithObjectFields) {
826
+ console.log(`checking ${typeName}.${fieldName} for ${objectTypeName}`);
827
+ if (inputFieldDirectives[objectTypeName]) {
828
+ inputFieldDirectives[typeName] = { ...inputFieldDirectives[typeName], [fieldName]: [] };
829
+ changes += 1;
830
+ }
831
+ else {
832
+ newTypesWithObjectFields.push([typeName, fieldName, objectTypeName]);
833
+ }
834
+ }
835
+ typesWithObjectFields = newTypesWithObjectFields;
836
+ }
837
+ }
838
+ const interfaces = {};
839
+ for (const type of types) {
840
+ if (!(type instanceof graphql.GraphQLObjectType)) {
841
+ continue;
842
+ }
843
+ for (const iface of type.getInterfaces()) {
844
+ if (!(iface.name in interfaces)) {
845
+ interfaces[iface.name] = {
846
+ interface: iface,
847
+ implementors: [],
848
+ };
849
+ }
850
+ interfaces[iface.name].implementors.push(type);
851
+ }
852
+ }
853
+ return [types, interfaces, inputFieldDirectives];
854
+ }
855
+ }
856
+ function createGenerator(schema, options) {
857
+ const args = GeneratorContext.prepareInterfacesAndInputFieldDirectives(schema, options);
858
+ return {
859
+ generateSchema: (outfile) => new GeneratorContext(options).renderFile(outfile, function () {
860
+ return this.schemaExprs(schema, args);
861
+ }),
862
+ generateTypes: (outfile) => new GeneratorContext(options).renderFile(outfile, function () {
863
+ return this.typesExprs(schema, args);
864
+ }),
865
+ generate: (outfile) => new GeneratorContext(options).renderFile(outfile, function () {
866
+ return this.schemaAndTypesExprs(schema, args);
867
+ }),
868
+ };
869
+ }
870
+ function generateSchema(schema, outfile, options = {}) {
871
+ return createGenerator(schema, options).generateSchema(outfile);
872
+ }
873
+ function generateTypes(schema, outfile, options = {}) {
874
+ return createGenerator(schema, options).generateTypes(outfile);
875
+ }
876
+ function generate(schema, outfile, options = {}) {
877
+ return createGenerator(schema, options).generate(outfile);
878
+ }
879
+
880
+ async function parseResolverFile(path) {
881
+ return Object.fromEntries(Object.entries((await parseModule(path)).exports)
882
+ .flatMap(([name, { declaration }]) => {
883
+ if (ts.isVariableDeclaration(declaration) && declaration.initializer) {
884
+ if (ts.isFunctionExpression(declaration.initializer)) {
885
+ return [[name, { module: path, symbol: name }]];
886
+ }
887
+ if (ts.isArrowFunction(declaration.initializer)) {
888
+ return [[name, { module: path, symbol: name }]];
889
+ }
890
+ }
891
+ if (ts.isFunctionDeclaration(declaration)) {
892
+ return [[name, { module: path, symbol: name }]];
893
+ }
894
+ return [];
895
+ }));
896
+ }
897
+ async function parseTypeResolvers(typeName, glob$1) {
898
+ const result = {};
899
+ for await (const entry of glob.globIterate(glob$1, { withFileTypes: true })) {
900
+ const fullpath = entry.fullpath();
901
+ if (entry.isFile() && entry.name.endsWith(".ts")) {
902
+ for (const [name, reference] of Object.entries(await parseResolverFile(fullpath))) {
903
+ let realName = name;
904
+ if (realName === "default") {
905
+ realName = path.basename(fullpath, path.extname(fullpath));
906
+ }
907
+ if (realName in result) {
908
+ console.warn(`WARNING: Duplicate resolver name: ${typeName ? typeName + "." : ""}${name} in ${fullpath} and ${result[name].module}`);
909
+ }
910
+ result[realName] = reference;
911
+ }
912
+ }
913
+ }
914
+ return result;
915
+ }
916
+ async function parse$2(dirpath) {
917
+ const dir = await fs.stat(dirpath);
918
+ if (!dir.isDirectory()) {
919
+ throw new Error(`Expected ${dirpath} to be a directory`);
920
+ }
921
+ if (!dirpath.endsWith("/")) {
922
+ dirpath += "/";
923
+ }
924
+ const out = {};
925
+ for await (const name of await fs.readdir(dirpath)) {
926
+ const file = path.join(dirpath, name);
927
+ const entry = await fs.stat(file);
928
+ if (entry.isDirectory()) {
929
+ out[name] = await parseTypeResolvers(name, file + "/*.ts");
930
+ }
931
+ else if (entry.isFile() && name.endsWith(".ts")) {
932
+ out[name.slice(0, -3)] = await parseTypeResolvers(name.slice(0, -3), file);
933
+ }
934
+ }
935
+ return out;
936
+ }
937
+
938
+ function locLineColumn$1(decl, source) {
939
+ const head = source.text.slice(0, decl.pos);
940
+ return [
941
+ head.split("\n").length,
942
+ head.slice(head.lastIndexOf("\n") + 1).length + 1,
943
+ ];
944
+ }
945
+ function refFromImportTypeNode(node, source) {
946
+ if (node.isTypeOf) {
947
+ console.log("WARNING: typeof namespace import for scalar type is not supported");
948
+ return;
949
+ }
950
+ if (!node.qualifier || !ts.isIdentifier(node.qualifier)) {
951
+ console.log("WARNING: namespace import for scalar type is not supported");
952
+ return;
953
+ }
954
+ if (!ts.isLiteralTypeNode(node.argument) || !ts.isStringLiteral(node.argument.literal)) {
955
+ // this is a grammar error, handling it is out of scope
956
+ const { line, character } = ts.getLineAndCharacterOfPosition(source, node.pos);
957
+ console.log(`WARNING: grammar error at ${source.fileName}:${line + 1}:${character + 1}`);
958
+ return;
959
+ }
960
+ return { module: node.argument.literal.text, symbol: node.qualifier.text };
961
+ }
962
+ function refFromTypeReferenceNode(typeNode, source) {
963
+ if (typeNode.typeName.kind === ts.SyntaxKind.QualifiedName) {
964
+ // TODO: handle qualified names
965
+ return;
966
+ }
967
+ const typeName = typeNode.typeName.text;
968
+ for (const statement of source.statements) {
969
+ if (ts.isImportDeclaration(statement)) {
970
+ // search imports
971
+ if (!ts.isStringLiteral(statement.moduleSpecifier)) {
972
+ // this is a grammar error, handling it is out of scope
973
+ continue;
974
+ }
975
+ if (!statement.importClause) {
976
+ // side-effect import
977
+ continue;
978
+ }
979
+ if (statement.importClause.name) {
980
+ // default import
981
+ if (statement.importClause.name.text === typeName) {
982
+ return { module: statement.importClause.name.text, symbol: 'default', alias: typeName };
983
+ }
984
+ }
985
+ if (!statement.importClause.namedBindings) {
986
+ // this is a grammar error, handling it is out of scope
987
+ continue;
988
+ }
989
+ if (!ts.isNamedImports(statement.importClause.namedBindings)) {
990
+ // TODO: handle namespace imports (will need to check if `typeName` has a dot in it)
991
+ continue;
992
+ }
993
+ for (const specifier of statement.importClause.namedBindings.elements ?? []) {
994
+ if (specifier.name.text === typeName) {
995
+ return { module: statement.moduleSpecifier.text, symbol: specifier.propertyName?.text ?? typeName, alias: typeName };
996
+ }
997
+ }
998
+ }
999
+ else if (ts.isTypeAliasDeclaration(statement) || ts.isInterfaceDeclaration(statement) || ts.isEnumDeclaration(statement)) {
1000
+ if (statement.name.text === typeName) {
1001
+ if (!statement.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)) {
1002
+ console.log(statement);
1003
+ console.log(`WARNING: found type ${typeName} in ${source.fileName}:${locLineColumn$1(statement, source).join(':')} but it is not exported`);
1004
+ continue;
1005
+ }
1006
+ return { module: source.fileName, symbol: typeName };
1007
+ }
1008
+ }
1009
+ }
1010
+ // assume intrinsic or global type
1011
+ return { symbol: typeName };
1012
+ }
1013
+ function refFromTypeNode(typeNode, source) {
1014
+ if (ts.isImportTypeNode(typeNode)) {
1015
+ return refFromImportTypeNode(typeNode, source);
1016
+ }
1017
+ else if (ts.isTokenKind(typeNode.kind)) {
1018
+ // primitive type string, number, etc...
1019
+ return { symbol: typeNode.getText(source) };
1020
+ }
1021
+ else if (ts.isTypeReferenceNode(typeNode)) {
1022
+ return refFromTypeReferenceNode(typeNode, source);
1023
+ }
1024
+ else {
1025
+ console.warn("WARNING: unexpected type node: " + ts.SyntaxKind[typeNode.kind]);
1026
+ }
1027
+ }
1028
+ function reconcileScalarType(scalarName, typeDecls, source) {
1029
+ let type;
1030
+ for (const typeNode of typeDecls) {
1031
+ if (!typeNode) {
1032
+ continue;
1033
+ }
1034
+ let newType = refFromTypeNode(typeNode, source);
1035
+ if (type && newType) {
1036
+ if (type.symbol !== newType.symbol ||
1037
+ type.alias !== newType.alias ||
1038
+ type.module !== newType.module ||
1039
+ type.property !== newType.property) {
1040
+ throw new Error(`mismatched types do not match for scalar ${scalarName}: ${type.symbol} !== ${newType.symbol}`);
1041
+ }
1042
+ }
1043
+ else if (!type && newType) {
1044
+ type = newType;
1045
+ }
1046
+ }
1047
+ return type;
1048
+ }
1049
+ function scalarInfoFromObjectLiteralExpression(scalarName, module, properties) {
1050
+ return Object.fromEntries(Array.from(properties).flatMap((prop) => {
1051
+ if (ts.isPropertyAssignment(prop)) {
1052
+ if (!ts.isIdentifier(prop.name)) {
1053
+ return [];
1054
+ }
1055
+ switch (prop.name.text) {
1056
+ case "serialize":
1057
+ case "parseValue":
1058
+ case "parseLiteral":
1059
+ if (!ts.isFunctionExpression(prop.initializer) && !ts.isArrowFunction(prop.initializer)) {
1060
+ console.log(`WARNING: expected scalar property ${scalarName}.${prop.name.text} to be a function, but got ${ts.SyntaxKind[prop.initializer.kind]}`);
1061
+ return [];
1062
+ }
1063
+ return [[
1064
+ `${prop.name.text}Func`,
1065
+ {
1066
+ module: module,
1067
+ symbol: scalarName,
1068
+ property: prop.name.text,
1069
+ declaration: prop.initializer,
1070
+ },
1071
+ ]];
1072
+ default:
1073
+ console.log(`WARNING: found extraneous scalar property ${scalarName}.${prop.name.text}`);
1074
+ }
1075
+ }
1076
+ else if (ts.isMethodDeclaration(prop)) {
1077
+ if (!ts.isIdentifier(prop.name)) {
1078
+ return [];
1079
+ }
1080
+ switch (prop.name.text) {
1081
+ case "serialize":
1082
+ case "parseValue":
1083
+ case "parseLiteral":
1084
+ return [[
1085
+ `${prop.name.text}Func`,
1086
+ {
1087
+ module,
1088
+ symbol: scalarName,
1089
+ property: prop.name.text,
1090
+ declaration: prop,
1091
+ },
1092
+ ]];
1093
+ default:
1094
+ console.log(`WARNING: found extraneous scalar property ${scalarName}.${prop.name.text}`);
1095
+ }
1096
+ }
1097
+ else {
1098
+ console.log(`WARNING: unsupported object literal element in scalar object ${scalarName}: ${ts.SyntaxKind[prop.kind]}`);
1099
+ }
1100
+ return [];
1101
+ }));
1102
+ }
1103
+ async function parse$1(path) {
1104
+ const scalarFnsInfos = {};
1105
+ const scalarTypeNodes = {};
1106
+ const sources = {};
1107
+ for (const [name, { declaration, source }] of Object.entries((await parseModule(path)).exports)) {
1108
+ sources[name] = source;
1109
+ if (ts.isVariableDeclaration(declaration)) {
1110
+ if (declaration.initializer && ts.isObjectLiteralExpression(declaration.initializer)) {
1111
+ scalarFnsInfos[name] = scalarInfoFromObjectLiteralExpression(name, new URL(source.fileName).toString(), declaration.initializer.properties);
1112
+ }
1113
+ }
1114
+ else if (ts.isTypeAliasDeclaration(declaration)) {
1115
+ if (declaration.typeParameters?.length) {
1116
+ console.log(`WARNING: skipping scalar type ${name}: type parameters are not supported`);
1117
+ continue;
1118
+ }
1119
+ const ref = refFromTypeNode(declaration.type, source);
1120
+ if (ref) {
1121
+ scalarTypeNodes[name] = declaration.type;
1122
+ }
1123
+ }
1124
+ }
1125
+ const infos = {};
1126
+ for (const name of new Set([...Object.keys(scalarFnsInfos), ...Object.keys(scalarTypeNodes)])) {
1127
+ const fnsInfo = scalarFnsInfos[name];
1128
+ const typeNode = scalarTypeNodes[name];
1129
+ const source = sources[name];
1130
+ const type = typeNode ? {
1131
+ module: source.fileName,
1132
+ symbol: name,
1133
+ } : reconcileScalarType(name, [
1134
+ fnsInfo?.serializeFunc?.declaration?.parameters?.[0]?.type,
1135
+ fnsInfo?.parseValueFunc?.declaration?.type,
1136
+ fnsInfo?.parseLiteralFunc?.declaration?.type,
1137
+ ], source);
1138
+ if (type) {
1139
+ if (type.module) {
1140
+ type.module = new URL(type.module, source.fileName).toString();
1141
+ }
1142
+ }
1143
+ infos[name] = {
1144
+ ...fnsInfo,
1145
+ type,
1146
+ };
1147
+ }
1148
+ return infos;
1149
+ }
1150
+
1151
+ function locLineColumn(loc) {
1152
+ const head = loc.source.body.slice(0, loc.start);
1153
+ return [
1154
+ head.split("\n").length,
1155
+ head.slice(head.lastIndexOf("\n") + 1).length + 1,
1156
+ ];
1157
+ }
1158
+ function traceLine(loc, prefix = "") {
1159
+ if (!loc) {
1160
+ return "";
1161
+ }
1162
+ return `\n ${prefix}at file://${loc.source.name}:${locLineColumn(loc).join(":")}`;
1163
+ }
1164
+ function setTraceToSchema(err, name, loc) {
1165
+ if (globalThis.Deno) {
1166
+ if (loc) {
1167
+ const trace = err.__callSiteEvals;
1168
+ const [lineNumber, columnNumber] = locLineColumn(loc);
1169
+ // NOTE: this is deno magic
1170
+ // @see https://github.com/denoland/deno/blob/b1b418b81a13ede548273665e83c1bc5a97dffcd/core/error.rs#L275
1171
+ Object.defineProperty(err, "__callSiteEvals", {
1172
+ get: () => [
1173
+ {
1174
+ this: undefined,
1175
+ typeName: null,
1176
+ function: undefined,
1177
+ functionName: name,
1178
+ methodName: null,
1179
+ fileName: "file://" + loc.source.name,
1180
+ lineNumber,
1181
+ columnNumber,
1182
+ evalOrigin: undefined,
1183
+ isToplevel: true,
1184
+ isEval: false,
1185
+ isNative: false,
1186
+ isConstructor: false,
1187
+ isAsync: false,
1188
+ isPromiseAll: false,
1189
+ promiseIndex: null,
1190
+ },
1191
+ ...trace,
1192
+ ],
1193
+ });
1194
+ }
1195
+ }
1196
+ return err;
1197
+ }
1198
+ function namedNodesDict(nodes = []) {
1199
+ return Object.fromEntries(nodes.map((node) => [node.name.value, node]));
1200
+ }
1201
+ function sortNamedNodes(nodes) {
1202
+ return Array.from(nodes).sort(({ name: { value: a } }, { name: { value: b } }) => a.localeCompare(b));
1203
+ }
1204
+ function isIntValueNodeEqual(a, b) {
1205
+ return a.value === b.value;
1206
+ }
1207
+ function isFloatValueNodeEqual(a, b) {
1208
+ return a.value === b.value;
1209
+ }
1210
+ function isStringValueNodeEqual(a, b) {
1211
+ return a.value === b.value;
1212
+ }
1213
+ function isBooleanValueNodeEqual(a, b) {
1214
+ return a.value === b.value;
1215
+ }
1216
+ function isEnumValueNodeEqual(a, b) {
1217
+ return a.value === b.value;
1218
+ }
1219
+ function isListValueNodeEqual(a, b) {
1220
+ return zip(a.values, b.values).every(([a, b]) => isValueNodeEqual(a, b));
1221
+ }
1222
+ function isObjectValueNodeEqual(a, b) {
1223
+ return zip(sortNamedNodes(a.fields), sortNamedNodes(b.fields))
1224
+ .every(([a, b]) => a.name.value === b.name.value && isValueNodeEqual(a.value, b.value));
1225
+ }
1226
+ function isValueNodeEqual(a, b) {
1227
+ if (a === b || (!a && !b)) {
1228
+ return true;
1229
+ }
1230
+ if (!a || !b || a.kind !== b.kind) {
1231
+ return false;
1232
+ }
1233
+ switch (a.kind) {
1234
+ case graphql.Kind.INT:
1235
+ return isIntValueNodeEqual(a, b);
1236
+ case graphql.Kind.FLOAT:
1237
+ return isFloatValueNodeEqual(a, b);
1238
+ case graphql.Kind.STRING:
1239
+ return isStringValueNodeEqual(a, b);
1240
+ case graphql.Kind.BOOLEAN:
1241
+ return isBooleanValueNodeEqual(a, b);
1242
+ case graphql.Kind.ENUM:
1243
+ return isEnumValueNodeEqual(a, b);
1244
+ case graphql.Kind.LIST:
1245
+ return isListValueNodeEqual(a, b);
1246
+ case graphql.Kind.OBJECT:
1247
+ return isObjectValueNodeEqual(a, b);
1248
+ case graphql.Kind.NULL:
1249
+ case graphql.Kind.VARIABLE:
1250
+ return true;
1251
+ }
1252
+ }
1253
+ function isArgumentNodesEqual(a, b) {
1254
+ if (a === b || (!a && !b)) {
1255
+ return true;
1256
+ }
1257
+ if (!a || !b || a.length !== b.length) {
1258
+ return false;
1259
+ }
1260
+ return zip(sortNamedNodes(a), sortNamedNodes(b)).every(([a, b]) => a.name.value === b.name.value && isValueNodeEqual(a.value, b.value));
1261
+ }
1262
+ function isTypeNodeEqual(a, b) {
1263
+ if (a.kind !== b.kind) {
1264
+ return false;
1265
+ }
1266
+ switch (a.kind) {
1267
+ case graphql.Kind.NAMED_TYPE:
1268
+ return a.name.value === b.name.value;
1269
+ case graphql.Kind.LIST_TYPE:
1270
+ return isTypeNodeEqual(a.type, b.type);
1271
+ case graphql.Kind.NON_NULL_TYPE:
1272
+ return isTypeNodeEqual(a.type, b.type);
1273
+ }
1274
+ }
1275
+ function isDirectiveNodesEqual(a, b) {
1276
+ if (a === b || (!a && !b)) {
1277
+ return true;
1278
+ }
1279
+ if (!a || !b || a.length !== b.length) {
1280
+ return false;
1281
+ }
1282
+ return zip(sortNamedNodes(a), sortNamedNodes(b)).every(([a, b]) => a.name.value === b.name.value &&
1283
+ isArgumentNodesEqual(a.arguments, b.arguments));
1284
+ }
1285
+ function isInputValueDefinitionNodesEqual(a, b) {
1286
+ if (a === b || (!a && !b)) {
1287
+ return true;
1288
+ }
1289
+ if (!a || !b || a.length !== b.length) {
1290
+ return false;
1291
+ }
1292
+ return zip(sortNamedNodes(a), sortNamedNodes(b)).every(([a, b]) => a.name.value === b.name.value && isTypeNodeEqual(a.type, b.type) &&
1293
+ isValueNodeEqual(a.defaultValue, b.defaultValue) &&
1294
+ isDirectiveNodesEqual(a.directives, b.directives));
1295
+ }
1296
+ function mergeFieldDefinitionNodes(name, a, b) {
1297
+ const fields = namedNodesDict(a);
1298
+ if (b) {
1299
+ for (const f of b) {
1300
+ const prev = fields[f.name.value];
1301
+ if (prev) {
1302
+ if (!isInputValueDefinitionNodesEqual(prev.arguments, f.arguments)) {
1303
+ throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different arguments: ${name}.${f.name.value}`), name + "." + f.name.value, f.loc);
1304
+ }
1305
+ if (!isTypeNodeEqual(prev.type, f.type)) {
1306
+ throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different type: ${name}.${f.name.value}`), name + "." + f.name.value, f.type.loc);
1307
+ }
1308
+ console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}` +
1309
+ traceLine(f.loc) +
1310
+ traceLine(prev.loc, "previously ") + "\n");
1311
+ fields[f.name.value] = {
1312
+ ...prev,
1313
+ directives: mergeDirectiveNodes(name + "." + f.name.value, prev.directives, f.directives),
1314
+ };
1315
+ }
1316
+ else {
1317
+ fields[f.name.value] = f;
1318
+ }
1319
+ }
1320
+ }
1321
+ return Object.values(fields);
1322
+ }
1323
+ function mergeInputValueDefinitionNodes(name, a, b) {
1324
+ const fields = namedNodesDict(a);
1325
+ if (b) {
1326
+ for (const f of b) {
1327
+ const prev = fields[f.name.value];
1328
+ if (prev) {
1329
+ if (!isValueNodeEqual(prev.defaultValue, f.defaultValue)) {
1330
+ throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different arguments: ${name}.${f.name.value}`), name + "." + f.name.value, f.loc);
1331
+ }
1332
+ if (!isTypeNodeEqual(prev.type, f.type)) {
1333
+ throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different type: ${name}.${f.name.value}`), name + "." + f.name.value, f.type.loc);
1334
+ }
1335
+ console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}` +
1336
+ traceLine(f.loc) +
1337
+ traceLine(prev.loc, "previously ") + "\n");
1338
+ fields[f.name.value] = {
1339
+ ...prev,
1340
+ directives: mergeDirectiveNodes(name + "." + f.name.value, prev.directives, f.directives),
1341
+ };
1342
+ }
1343
+ else {
1344
+ fields[f.name.value] = f;
1345
+ }
1346
+ }
1347
+ }
1348
+ return Object.values(fields);
1349
+ }
1350
+ function mergeNamedNodes(a, b) {
1351
+ const nodes = namedNodesDict(a);
1352
+ if (b) {
1353
+ for (const n of b) {
1354
+ nodes[n.name.value] = n;
1355
+ }
1356
+ }
1357
+ return Object.values(nodes);
1358
+ }
1359
+ function mergeDirectiveNodes(name, a, b) {
1360
+ const directives = namedNodesDict(a);
1361
+ if (b) {
1362
+ for (const d of b) {
1363
+ if (d.name.value in directives &&
1364
+ !isArgumentNodesEqual(directives[d.name.value].arguments, d.arguments)) {
1365
+ throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate directive with different arguments: ${name} @${d.name.value}`), name + " @" + d.name.value, d.loc);
1366
+ }
1367
+ directives[d.name.value] = d;
1368
+ }
1369
+ }
1370
+ return Object.values(directives);
1371
+ }
1372
+ function mergeScalarTypeDefinitionNodes(a, b) {
1373
+ if (a.name.value !== b.name.value) {
1374
+ throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge scalar types with different names: ${a.name.value} and ${b.name.value}`), a.name.value, a.loc);
1375
+ }
1376
+ return {
1377
+ kind: graphql.Kind.SCALAR_TYPE_DEFINITION,
1378
+ name: a.name,
1379
+ directives: mergeDirectiveNodes(a.name.value, a.directives, b.directives),
1380
+ };
1381
+ }
1382
+ function mergeObjectTypeDefinitionNodes(a, b) {
1383
+ return {
1384
+ kind: graphql.Kind.OBJECT_TYPE_DEFINITION,
1385
+ loc: a.loc,
1386
+ name: a.name,
1387
+ description: a.description || b.description,
1388
+ interfaces: mergeNamedNodes(a.interfaces, b.interfaces),
1389
+ directives: mergeDirectiveNodes(a.name.value, a.directives, b.directives),
1390
+ fields: mergeFieldDefinitionNodes(a.name.value, a.fields, b.fields),
1391
+ };
1392
+ }
1393
+ function mergeInterfaceTypeDefinitionNodes(a, b) {
1394
+ return {
1395
+ kind: graphql.Kind.INTERFACE_TYPE_DEFINITION,
1396
+ loc: a.loc,
1397
+ name: a.name,
1398
+ description: a.description || b.description,
1399
+ interfaces: mergeNamedNodes(a.interfaces, b.interfaces),
1400
+ directives: mergeDirectiveNodes(a.name.value, a.directives, b.directives),
1401
+ fields: mergeFieldDefinitionNodes(a.name.value, a.fields, b.fields),
1402
+ };
1403
+ }
1404
+ function mergeUnionTypeDefinitionNodes(a, b) {
1405
+ return {
1406
+ kind: graphql.Kind.UNION_TYPE_DEFINITION,
1407
+ loc: a.loc,
1408
+ name: a.name,
1409
+ description: a.description || b.description,
1410
+ directives: mergeDirectiveNodes(a.name.value, a.directives, b.directives),
1411
+ types: mergeNamedNodes(a.types, b.types),
1412
+ };
1413
+ }
1414
+ function mergeEnumTypeDefinitionNodes(a, b) {
1415
+ const values = namedNodesDict(a.values);
1416
+ if (b) {
1417
+ for (const v of (b.values || [])) {
1418
+ if (v.name.value in values) {
1419
+ throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate enum value: ${v.name.value}.${v.name.value}`), v.name.value + "." + v.name.value, v.loc);
1420
+ }
1421
+ values[v.name.value] = v;
1422
+ }
1423
+ }
1424
+ return {
1425
+ kind: graphql.Kind.ENUM_TYPE_DEFINITION,
1426
+ loc: a.loc,
1427
+ name: a.name,
1428
+ description: a.description || b.description,
1429
+ directives: mergeDirectiveNodes(a.name.value, a.directives, b.directives),
1430
+ values: Object.values(values),
1431
+ };
1432
+ }
1433
+ function mergeInputObjectTypeDefinitionNodes(a, b) {
1434
+ return {
1435
+ kind: graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION,
1436
+ loc: a.loc,
1437
+ name: a.name,
1438
+ description: a.description || b.description,
1439
+ directives: mergeDirectiveNodes(a.name.value, a.directives, b.directives),
1440
+ fields: mergeInputValueDefinitionNodes(a.name.value, a.fields, b.fields),
1441
+ };
1442
+ }
1443
+ function mergeDocumentNodes(documentNodes) {
1444
+ const definitions = {};
1445
+ for (const documentNode of documentNodes) {
1446
+ for (const definition of documentNode.definitions) {
1447
+ switch (definition.kind) {
1448
+ case graphql.Kind.SCHEMA_DEFINITION:
1449
+ case graphql.Kind.SCHEMA_EXTENSION:
1450
+ case graphql.Kind.OPERATION_DEFINITION:
1451
+ case graphql.Kind.FRAGMENT_DEFINITION:
1452
+ case graphql.Kind.SCALAR_TYPE_EXTENSION:
1453
+ case graphql.Kind.OBJECT_TYPE_EXTENSION:
1454
+ case graphql.Kind.INTERFACE_TYPE_EXTENSION:
1455
+ case graphql.Kind.UNION_TYPE_EXTENSION:
1456
+ case graphql.Kind.ENUM_TYPE_EXTENSION:
1457
+ case graphql.Kind.INPUT_OBJECT_TYPE_EXTENSION:
1458
+ throw new Error("unexpected definition kind: " + definition.kind);
1459
+ }
1460
+ const prevDefinition = definitions[definition.name.value];
1461
+ if (!prevDefinition) {
1462
+ definitions[definition.name.value] = definition;
1463
+ continue;
1464
+ }
1465
+ if (prevDefinition.kind !== definition.kind) {
1466
+ throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge different definition kinds: ${prevDefinition.kind} and ${definition.kind}`), definition.name.value, definition.loc);
1467
+ }
1468
+ if (prevDefinition.kind === graphql.Kind.DIRECTIVE_DEFINITION) {
1469
+ throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate directive definitions: ${definition.name.value}`), definition.name.value, definition.loc);
1470
+ }
1471
+ if (prevDefinition.description && definition.description &&
1472
+ prevDefinition.description.value !== definition.description.value) {
1473
+ console.warn(`WARNING: different descriptions for type ${prevDefinition.name.value}: ${JSON.stringify(prevDefinition.description.value)} and ${JSON.stringify(definition.description.value)}` +
1474
+ traceLine(definition.description.loc) +
1475
+ traceLine(prevDefinition.description.loc, "previously ") + "\n");
1476
+ }
1477
+ switch (definition.kind) {
1478
+ case graphql.Kind.SCALAR_TYPE_DEFINITION:
1479
+ definitions[definition.name.value] = mergeScalarTypeDefinitionNodes(prevDefinition, definition);
1480
+ break;
1481
+ case graphql.Kind.OBJECT_TYPE_DEFINITION:
1482
+ definitions[definition.name.value] = mergeObjectTypeDefinitionNodes(prevDefinition, definition);
1483
+ break;
1484
+ case graphql.Kind.INTERFACE_TYPE_DEFINITION:
1485
+ definitions[definition.name.value] = mergeInterfaceTypeDefinitionNodes(prevDefinition, definition);
1486
+ break;
1487
+ case graphql.Kind.UNION_TYPE_DEFINITION:
1488
+ definitions[definition.name.value] = mergeUnionTypeDefinitionNodes(prevDefinition, definition);
1489
+ break;
1490
+ case graphql.Kind.ENUM_TYPE_DEFINITION:
1491
+ definitions[definition.name.value] = mergeEnumTypeDefinitionNodes(prevDefinition, definition);
1492
+ break;
1493
+ case graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION:
1494
+ definitions[definition.name.value] = mergeInputObjectTypeDefinitionNodes(prevDefinition, definition);
1495
+ break;
1496
+ }
1497
+ }
1498
+ }
1499
+ return {
1500
+ kind: graphql.Kind.DOCUMENT,
1501
+ loc: documentNodes[0].loc,
1502
+ definitions: Object.values(definitions),
1503
+ };
1504
+ }
1505
+
1506
+ async function* findSchemaFiles(glob$1) {
1507
+ for await (const path$1 of glob.globIterate(glob$1)) {
1508
+ const entry = await fs.stat(path$1);
1509
+ if (entry.isFile()) {
1510
+ yield path$1;
1511
+ }
1512
+ else if (entry.isDirectory()) {
1513
+ yield* findSchemaFiles(path.join(path$1, "**/*.graphql"));
1514
+ }
1515
+ }
1516
+ }
1517
+ async function parse(glob) {
1518
+ const documentNodes = [];
1519
+ for await (const entry of findSchemaFiles(glob)) {
1520
+ documentNodes.push(graphql.parse(new graphql.Source(await fs.readFile(entry, "utf-8"), entry)));
1521
+ }
1522
+ if (!documentNodes.length) {
1523
+ throw new Error("No graphql files found");
1524
+ }
1525
+ const schema = graphql.buildASTSchema(mergeDocumentNodes(documentNodes));
1526
+ const validationErrors = graphql.validateSchema(schema);
1527
+ if (validationErrors.length > 0) {
1528
+ throw validationErrors;
1529
+ }
1530
+ return schema;
1531
+ }
1532
+
1533
+ exports.createGenerator = createGenerator;
1534
+ exports.generate = generate;
1535
+ exports.generateSchema = generateSchema;
1536
+ exports.generateTypes = generateTypes;
1537
+ exports.parseResolvers = parse$2;
1538
+ exports.parseScalars = parse$1;
1539
+ exports.parseSchema = parse;
1540
+ exports.parseTypeResolvers = parseTypeResolvers;