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