graphql-jerky 1.0.5 → 1.0.7
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/bin/jerky.cjs +16 -8
- package/build/bin/jerky.mjs +17 -9
- package/build/lib.cjs +555 -221
- package/build/lib.d.ts +1 -0
- package/build/lib.mjs +555 -221
- package/package.json +2 -1
package/build/lib.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import path, { resolve, basename, extname, join } from 'path';
|
|
2
|
+
import { pathToFileURL, fileURLToPath } from 'url';
|
|
1
3
|
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
4
|
import jen$1, { jen } from 'jennifer-js';
|
|
3
5
|
import format from 'jennifer-js/format';
|
|
4
6
|
import partition from 'just-partition';
|
|
5
7
|
import pascalCase from 'just-pascal-case';
|
|
6
|
-
import path, { resolve, basename, extname, join } from 'path';
|
|
7
|
-
import { pathToFileURL, fileURLToPath } from 'url';
|
|
8
8
|
import fs from 'fs/promises';
|
|
9
9
|
import ts, { getLineAndCharacterOfPosition } from 'typescript';
|
|
10
10
|
import { globIterate } from 'glob';
|
|
@@ -26,29 +26,44 @@ function resolveModule(specifier, referrer) {
|
|
|
26
26
|
if (url.protocol === "file:") {
|
|
27
27
|
return parseSource(url);
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
throw new Error(`Unsupported protocol: ${url.protocol}`);
|
|
30
|
+
}
|
|
31
|
+
function pushExports(e, name, ...decls) {
|
|
32
|
+
if (!e[name]) {
|
|
33
|
+
e[name] = [];
|
|
31
34
|
}
|
|
35
|
+
e[name].push(...decls);
|
|
32
36
|
}
|
|
33
37
|
async function findExports(source, resolveModuleFn = resolveModule) {
|
|
34
38
|
const exports = {};
|
|
35
39
|
const namedExports = [];
|
|
36
40
|
for (const node of source.statements) {
|
|
37
|
-
if (ts.isFunctionDeclaration(node) ||
|
|
41
|
+
if (ts.isFunctionDeclaration(node) ||
|
|
42
|
+
ts.isClassDeclaration(node) ||
|
|
43
|
+
ts.isInterfaceDeclaration(node)) {
|
|
38
44
|
if (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
const name = node.modifiers.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword)
|
|
46
|
+
? "default"
|
|
47
|
+
: node.name?.getText(source);
|
|
48
|
+
if (name) {
|
|
49
|
+
pushExports(exports, name, {
|
|
50
|
+
declaration: node,
|
|
51
|
+
source,
|
|
52
|
+
name: name,
|
|
53
|
+
});
|
|
45
54
|
}
|
|
46
55
|
}
|
|
47
56
|
}
|
|
48
|
-
else if (ts.isTypeAliasDeclaration(node) ||
|
|
57
|
+
else if (ts.isTypeAliasDeclaration(node) ||
|
|
58
|
+
ts.isEnumDeclaration(node) ||
|
|
59
|
+
ts.isModuleDeclaration(node)) {
|
|
49
60
|
if (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {
|
|
50
61
|
const name = node.name.getText(source);
|
|
51
|
-
(exports
|
|
62
|
+
pushExports(exports, name, {
|
|
63
|
+
declaration: node,
|
|
64
|
+
source,
|
|
65
|
+
name: name,
|
|
66
|
+
});
|
|
52
67
|
}
|
|
53
68
|
}
|
|
54
69
|
else if (ts.isVariableStatement(node)) {
|
|
@@ -56,7 +71,11 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
56
71
|
for (const decl of node.declarationList.declarations) {
|
|
57
72
|
if (decl.name) {
|
|
58
73
|
const name = decl.name.getText(source);
|
|
59
|
-
(exports
|
|
74
|
+
pushExports(exports, name, {
|
|
75
|
+
declaration: decl,
|
|
76
|
+
source,
|
|
77
|
+
name: name,
|
|
78
|
+
});
|
|
60
79
|
}
|
|
61
80
|
}
|
|
62
81
|
}
|
|
@@ -74,7 +93,7 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
74
93
|
if (!(name in moduleExports)) {
|
|
75
94
|
throw new Error(`Exported name ${name} not found in ${JSON.stringify(specifier)}`);
|
|
76
95
|
}
|
|
77
|
-
(exports
|
|
96
|
+
pushExports(exports, name, ...moduleExports[name]);
|
|
78
97
|
}
|
|
79
98
|
}
|
|
80
99
|
else {
|
|
@@ -86,7 +105,9 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
86
105
|
}
|
|
87
106
|
}
|
|
88
107
|
}
|
|
89
|
-
else if (!node.exportClause &&
|
|
108
|
+
else if (!node.exportClause &&
|
|
109
|
+
node.moduleSpecifier &&
|
|
110
|
+
ts.isStringLiteral(node.moduleSpecifier)) {
|
|
90
111
|
// export * from 'whatever';
|
|
91
112
|
Object.assign(exports, await findExports(await resolveModuleFn(node.moduleSpecifier.text, new URL(source.fileName)), resolveModuleFn));
|
|
92
113
|
}
|
|
@@ -97,9 +118,10 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
97
118
|
for (const statement of source.statements) {
|
|
98
119
|
if (ts.isVariableStatement(statement)) {
|
|
99
120
|
for (const decl of statement.declarationList.declarations) {
|
|
100
|
-
if (ts.isIdentifier(decl.name) &&
|
|
121
|
+
if (ts.isIdentifier(decl.name) &&
|
|
122
|
+
decl.name.getText(source) in names) {
|
|
101
123
|
const name = names[decl.name.getText(source)];
|
|
102
|
-
(exports
|
|
124
|
+
pushExports(exports, name, {
|
|
103
125
|
declaration: decl,
|
|
104
126
|
source,
|
|
105
127
|
name: names[decl.name.getText(source)],
|
|
@@ -108,9 +130,11 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
108
130
|
}
|
|
109
131
|
}
|
|
110
132
|
if (ts.isFunctionDeclaration(statement)) {
|
|
111
|
-
if (statement.name &&
|
|
133
|
+
if (statement.name &&
|
|
134
|
+
ts.isIdentifier(statement.name) &&
|
|
135
|
+
statement.name.getText(source) in names) {
|
|
112
136
|
const name = names[statement.name.getText(source)];
|
|
113
|
-
(exports
|
|
137
|
+
pushExports(exports, name, {
|
|
114
138
|
declaration: statement,
|
|
115
139
|
source,
|
|
116
140
|
name: names[statement.name.getText(source)],
|
|
@@ -118,9 +142,11 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
118
142
|
}
|
|
119
143
|
}
|
|
120
144
|
if (ts.isClassDeclaration(statement)) {
|
|
121
|
-
if (statement.name &&
|
|
145
|
+
if (statement.name &&
|
|
146
|
+
ts.isIdentifier(statement.name) &&
|
|
147
|
+
statement.name.getText(source) in names) {
|
|
122
148
|
const name = names[statement.name.getText(source)];
|
|
123
|
-
(exports
|
|
149
|
+
pushExports(exports, name, {
|
|
124
150
|
declaration: statement,
|
|
125
151
|
source,
|
|
126
152
|
name: names[statement.name.getText(source)],
|
|
@@ -128,9 +154,11 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
128
154
|
}
|
|
129
155
|
}
|
|
130
156
|
if (ts.isTypeAliasDeclaration(statement)) {
|
|
131
|
-
if (statement.name &&
|
|
157
|
+
if (statement.name &&
|
|
158
|
+
ts.isIdentifier(statement.name) &&
|
|
159
|
+
statement.name.getText(source) in names) {
|
|
132
160
|
const name = names[statement.name.getText(source)];
|
|
133
|
-
(exports
|
|
161
|
+
pushExports(exports, name, {
|
|
134
162
|
declaration: statement,
|
|
135
163
|
source,
|
|
136
164
|
name: names[statement.name.getText(source)],
|
|
@@ -138,9 +166,11 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
138
166
|
}
|
|
139
167
|
}
|
|
140
168
|
if (ts.isInterfaceDeclaration(statement)) {
|
|
141
|
-
if (statement.name &&
|
|
169
|
+
if (statement.name &&
|
|
170
|
+
ts.isIdentifier(statement.name) &&
|
|
171
|
+
statement.name.getText(source) in names) {
|
|
142
172
|
const name = names[statement.name.getText(source)];
|
|
143
|
-
(exports
|
|
173
|
+
pushExports(exports, name, {
|
|
144
174
|
declaration: statement,
|
|
145
175
|
source,
|
|
146
176
|
name: names[statement.name.getText(source)],
|
|
@@ -148,9 +178,11 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
148
178
|
}
|
|
149
179
|
}
|
|
150
180
|
if (ts.isEnumDeclaration(statement)) {
|
|
151
|
-
if (statement.name &&
|
|
181
|
+
if (statement.name &&
|
|
182
|
+
ts.isIdentifier(statement.name) &&
|
|
183
|
+
statement.name.getText(source) in names) {
|
|
152
184
|
const name = names[statement.name.getText(source)];
|
|
153
|
-
(exports
|
|
185
|
+
pushExports(exports, name, {
|
|
154
186
|
declaration: statement,
|
|
155
187
|
source,
|
|
156
188
|
name: names[statement.name.getText(source)],
|
|
@@ -158,13 +190,15 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
158
190
|
}
|
|
159
191
|
}
|
|
160
192
|
if (ts.isImportDeclaration(statement)) {
|
|
161
|
-
if (statement.importClause
|
|
193
|
+
if (statement.importClause?.namedBindings &&
|
|
162
194
|
ts.isNamedImports(statement.importClause.namedBindings)) {
|
|
163
195
|
let importExports;
|
|
164
196
|
for (const element of statement.importClause.namedBindings.elements) {
|
|
165
|
-
if (element.propertyName &&
|
|
197
|
+
if (element.propertyName &&
|
|
198
|
+
ts.isIdentifier(element.propertyName) &&
|
|
166
199
|
element.propertyName.getText(source) in names) {
|
|
167
|
-
if (!importExports &&
|
|
200
|
+
if (!importExports &&
|
|
201
|
+
ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
168
202
|
const specifier = statement.moduleSpecifier.getText(source);
|
|
169
203
|
importExports = await findExports(await resolveModuleFn(specifier, new URL(source.fileName)), resolveModuleFn);
|
|
170
204
|
}
|
|
@@ -175,7 +209,7 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
175
209
|
throw new Error(`Exported name ${element.name.getText(source)} not found in ${JSON.stringify(statement.moduleSpecifier.getText(source))}`);
|
|
176
210
|
}
|
|
177
211
|
const name = names[element.propertyName.getText(source)];
|
|
178
|
-
(exports
|
|
212
|
+
pushExports(exports, name, {
|
|
179
213
|
declaration: element,
|
|
180
214
|
source,
|
|
181
215
|
name: names[element.propertyName.getText(source)],
|
|
@@ -188,9 +222,11 @@ async function findExports(source, resolveModuleFn = resolveModule) {
|
|
|
188
222
|
}
|
|
189
223
|
return exports;
|
|
190
224
|
}
|
|
191
|
-
async function parseModule(
|
|
192
|
-
const url = typeof
|
|
193
|
-
|
|
225
|
+
async function parseModule(sourceOrPath) {
|
|
226
|
+
const url = typeof sourceOrPath === "string"
|
|
227
|
+
? pathToFileURL(resolve(sourceOrPath))
|
|
228
|
+
: new URL(sourceOrPath.fileName);
|
|
229
|
+
const source = typeof sourceOrPath === "string" ? await parseSource(url) : sourceOrPath;
|
|
194
230
|
return {
|
|
195
231
|
path: url,
|
|
196
232
|
exports: await findExports(source),
|
|
@@ -202,7 +238,8 @@ async function parseModule(source) {
|
|
|
202
238
|
*
|
|
203
239
|
* @see https://github.com/microsoft/TypeScript/blob/0d0a79371471d627ae298a145f8009b05cbccb72/src/compiler/scanner.ts#L81
|
|
204
240
|
*/
|
|
205
|
-
const keywords = new Set(Object.keys(ts
|
|
241
|
+
const keywords = new Set(Object.keys(ts
|
|
242
|
+
.textToKeywordObj));
|
|
206
243
|
|
|
207
244
|
class RequiredPackages {
|
|
208
245
|
requires;
|
|
@@ -222,8 +259,11 @@ class RequiredPackages {
|
|
|
222
259
|
this.requires[pkg] = new Set();
|
|
223
260
|
}
|
|
224
261
|
let symbol = alias || name;
|
|
225
|
-
if ((symbol in this.symbols || keywords.has(symbol)) &&
|
|
226
|
-
|
|
262
|
+
if ((symbol in this.symbols || keywords.has(symbol)) &&
|
|
263
|
+
this.symbols[symbol] !== pkg) {
|
|
264
|
+
for (let i = 1;
|
|
265
|
+
// biome-ignore lint/suspicious/noAssignInExpressions: it works don't fix it
|
|
266
|
+
this.symbols[(symbol = `${name}$${i}`)] && this.symbols[symbol] !== pkg; i++)
|
|
227
267
|
;
|
|
228
268
|
}
|
|
229
269
|
this.requires[pkg].add(symbol);
|
|
@@ -236,7 +276,9 @@ class RequiredPackages {
|
|
|
236
276
|
}
|
|
237
277
|
|
|
238
278
|
function renderSymbolReference(pkgs, ref, alias) {
|
|
239
|
-
const ns =
|
|
279
|
+
const ns = ref.module
|
|
280
|
+
? jen.id(pkgs.addRequires(ref.module, ref.symbol, alias ?? ref.alias))
|
|
281
|
+
: jen.id(ref.symbol);
|
|
240
282
|
return ref.property ? ns.dot(ref.property) : ns;
|
|
241
283
|
}
|
|
242
284
|
|
|
@@ -263,7 +305,7 @@ function renderImports(base, imports, aliases, extMode = "omit") {
|
|
|
263
305
|
if (mod.startsWith("file:///")) {
|
|
264
306
|
mod = fileURLToPath(mod);
|
|
265
307
|
}
|
|
266
|
-
if (mod.startsWith(
|
|
308
|
+
if (mod.startsWith("/")) {
|
|
267
309
|
mod = path.relative(base, mod);
|
|
268
310
|
if (!mod.startsWith(".")) {
|
|
269
311
|
mod = `./${mod}`;
|
|
@@ -278,13 +320,21 @@ function renderImports(base, imports, aliases, extMode = "omit") {
|
|
|
278
320
|
else if (extMode === "replace") {
|
|
279
321
|
mod = mod.replace(/\.ts$/, ".js");
|
|
280
322
|
}
|
|
281
|
-
return jen$1.import
|
|
282
|
-
.
|
|
283
|
-
.
|
|
323
|
+
return jen$1.import
|
|
324
|
+
.obj(...Array.from(symbols)
|
|
325
|
+
.sort((a, b) => a.localeCompare(b) ||
|
|
326
|
+
importAlias(a).localeCompare(importAlias(b)))
|
|
327
|
+
.map((symbol) => symbol in aliases
|
|
328
|
+
? jen$1.id(aliases[symbol]).as.id(symbol)
|
|
329
|
+
: jen$1.id(symbol)))
|
|
330
|
+
.from.lit(mod);
|
|
284
331
|
}));
|
|
285
332
|
}
|
|
286
333
|
function renderAstNode(astNode) {
|
|
287
|
-
return jen$1
|
|
334
|
+
return jen$1
|
|
335
|
+
.id("JSON")
|
|
336
|
+
.dot("parse")
|
|
337
|
+
.call(jen$1.literal(JSON.stringify(astNode, (key, value) => key === "loc" ? undefined : value)));
|
|
288
338
|
}
|
|
289
339
|
function isBuiltInDirective(name) {
|
|
290
340
|
// https://spec.graphql.org/draft/#sec-Type-System.Directives.Built-in-Directives
|
|
@@ -309,6 +359,7 @@ class GeneratorContext {
|
|
|
309
359
|
_resolversInfo;
|
|
310
360
|
_subscribersInfo;
|
|
311
361
|
_graphqlModuleSpecifier;
|
|
362
|
+
_includeSubscriptionFieldResolvers;
|
|
312
363
|
constructor(options = {}) {
|
|
313
364
|
this._scalarsInfo = options.scalarsInfo ?? {};
|
|
314
365
|
this._fieldDirectivesInfo = options.fieldDirectivesInfo ?? {};
|
|
@@ -318,32 +369,46 @@ class GeneratorContext {
|
|
|
318
369
|
this._graphqlModuleSpecifier = options.graphqlModuleSpecifier ?? "graphql";
|
|
319
370
|
this._pkgs = new RequiredPackages();
|
|
320
371
|
this._extMode = options.extMode ?? "omit";
|
|
372
|
+
this._includeSubscriptionFieldResolvers = options.includeSubscriptionFieldResolvers ?? false;
|
|
321
373
|
}
|
|
322
374
|
_gql(name) {
|
|
323
375
|
return jen$1.id(this._pkgs.addRequires(this._graphqlModuleSpecifier, name));
|
|
324
376
|
}
|
|
325
377
|
_renderGraphQLTypeIdentifier(type) {
|
|
326
378
|
if (type instanceof GraphQLNonNull) {
|
|
327
|
-
return jen$1.new
|
|
379
|
+
return jen$1.new
|
|
380
|
+
.add(this._gql("GraphQLNonNull"))
|
|
381
|
+
.params(this._renderGraphQLTypeIdentifier(type.ofType));
|
|
328
382
|
}
|
|
329
383
|
if (type instanceof GraphQLList) {
|
|
330
|
-
return jen$1.new
|
|
384
|
+
return jen$1.new
|
|
385
|
+
.add(this._gql("GraphQLList"))
|
|
386
|
+
.params(this._renderGraphQLTypeIdentifier(type.ofType));
|
|
331
387
|
}
|
|
332
388
|
if (type instanceof GraphQLScalarType) {
|
|
333
389
|
if (isPrimitiveType(type)) {
|
|
334
|
-
return this._gql(
|
|
390
|
+
return this._gql(`GraphQL${type.name}`);
|
|
335
391
|
}
|
|
336
|
-
return jen$1.id(type.name
|
|
392
|
+
return jen$1.id(`${type.name}Scalar`);
|
|
337
393
|
}
|
|
338
|
-
return jen$1.id(type.name +
|
|
394
|
+
return jen$1.id(type.name +
|
|
395
|
+
(type instanceof GraphQLEnumType
|
|
396
|
+
? "Enum"
|
|
397
|
+
: type instanceof GraphQLDirective
|
|
398
|
+
? "Directive"
|
|
399
|
+
: "Type"));
|
|
339
400
|
}
|
|
340
401
|
_renderArgumentsObject(args) {
|
|
341
402
|
return jen$1.obj(...Array.from(args)
|
|
342
403
|
.sort(compareName)
|
|
404
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
343
405
|
.map((arg) => jen$1.prop(arg.name, jen$1.obj(jen$1.prop("type", this._renderGraphQLTypeIdentifier(arg.type)), ...truthify([
|
|
344
|
-
arg.description &&
|
|
345
|
-
|
|
346
|
-
arg.
|
|
406
|
+
arg.description &&
|
|
407
|
+
jen$1.prop("description", jen$1.lit(arg.description)),
|
|
408
|
+
arg.defaultValue &&
|
|
409
|
+
jen$1.prop("defaultValue", jen$1.lit(arg.defaultValue)),
|
|
410
|
+
arg.deprecationReason &&
|
|
411
|
+
jen$1.prop("deprecationReason", jen$1.lit(arg.deprecationReason)),
|
|
347
412
|
])))));
|
|
348
413
|
}
|
|
349
414
|
_renderValueNode(node) {
|
|
@@ -374,7 +439,8 @@ class GeneratorContext {
|
|
|
374
439
|
if (type instanceof GraphQLObjectType && !resolver) {
|
|
375
440
|
// try to find resolver in interface in the declaration order
|
|
376
441
|
for (const iface of type.getInterfaces()) {
|
|
377
|
-
|
|
442
|
+
resolver = this._resolversInfo[iface.name]?.[f.name];
|
|
443
|
+
if (resolver) {
|
|
378
444
|
break;
|
|
379
445
|
}
|
|
380
446
|
}
|
|
@@ -388,24 +454,36 @@ class GeneratorContext {
|
|
|
388
454
|
continue;
|
|
389
455
|
}
|
|
390
456
|
if (!resolveFn) {
|
|
391
|
-
resolveFn = jen$1
|
|
457
|
+
resolveFn = jen$1
|
|
458
|
+
.arrow(jen$1.id("source").op(":").any)
|
|
459
|
+
.id("source")
|
|
460
|
+
.dot(f.name);
|
|
392
461
|
}
|
|
393
|
-
resolveFn = renderSymbolReference(this._pkgs, ref, `apply${pascalCase(directive.name.value)}FieldDirective`).call(resolveFn, ...(directive.arguments?.length
|
|
462
|
+
resolveFn = renderSymbolReference(this._pkgs, ref, `apply${pascalCase(directive.name.value)}FieldDirective`).call(resolveFn, ...(directive.arguments?.length
|
|
463
|
+
? [this._renderArgumentNodes(directive.arguments)]
|
|
464
|
+
: []));
|
|
394
465
|
}
|
|
395
466
|
}
|
|
396
467
|
if (resolveFn) {
|
|
397
468
|
// args probably don't need to be transformed if there's no resolver
|
|
398
469
|
const argsWithDirectives = truthify(f.args?.map((arg) => this._findInputDirectiveInfoFromArgOrField(arg, inputFieldDirectives)) ?? []);
|
|
399
470
|
if (argsWithDirectives.length) {
|
|
400
|
-
resolveFn = jen$1
|
|
471
|
+
resolveFn = jen$1
|
|
472
|
+
.parens(jen$1
|
|
473
|
+
.params(jen$1.prop("next", this._gql("GraphQLFieldResolver").types(jen$1.any, jen$1.any)))
|
|
474
|
+
.op(":")
|
|
401
475
|
.add(this._gql("GraphQLFieldResolver"))
|
|
402
|
-
.types(jen$1.any, jen$1.any, jen$1.id(type.name).dot(pascalCase(f.name
|
|
403
|
-
.op("=>")
|
|
476
|
+
.types(jen$1.any, jen$1.any, jen$1.id(type.name).dot(pascalCase(`${f.name}_args`)))
|
|
477
|
+
.op("=>")
|
|
478
|
+
.arrow(jen$1.id("source"), jen$1.id("args"), jen$1.id("context"), jen$1.id("info"))
|
|
479
|
+
.id("next")
|
|
480
|
+
.call(jen$1.id("source"), this._renderInputFieldsWithDirectives(jen$1.id("args"), argsWithDirectives, argsWithDirectives.length < (f.args?.length ?? 0)), jen$1.id("context"), jen$1.id("info")))
|
|
481
|
+
.call(resolveFn);
|
|
404
482
|
}
|
|
405
483
|
}
|
|
406
484
|
}
|
|
407
485
|
// NOTE: The way subscribers work in the graphql-js is by calling `subscribe` on the top level fields, and then
|
|
408
|
-
// calling `resolve` on the nested fields. This means that subscribers only need to be defined on
|
|
486
|
+
// calling `resolve` on the nested fields. This means that subscribers only need to be defined on
|
|
409
487
|
// `Subscription`.
|
|
410
488
|
//
|
|
411
489
|
// In theory, an alternate implementation could be created to call `subscribe` at every level, but considering
|
|
@@ -419,18 +497,25 @@ class GeneratorContext {
|
|
|
419
497
|
f.args?.length && jen$1.prop("args", this._renderArgumentsObject(f.args)),
|
|
420
498
|
f.defaultValue && jen$1.prop("defaultValue", jen$1.lit(f.defaultValue)),
|
|
421
499
|
f.description && jen$1.prop("description", jen$1.lit(f.description)),
|
|
422
|
-
f.deprecationReason &&
|
|
500
|
+
f.deprecationReason &&
|
|
501
|
+
jen$1.prop("deprecationReason", jen$1.lit(f.deprecationReason)),
|
|
423
502
|
// NOTE: Resolver functions on interface definitions are not used by the default graphql-js
|
|
424
503
|
// executor implementation, but nonetheless accessible by a potential alternate implementation.
|
|
425
504
|
resolveFn && jen$1.prop("resolve", jen$1.parens(resolveFn).as.any),
|
|
426
|
-
subscriber &&
|
|
505
|
+
subscriber &&
|
|
506
|
+
jen$1.prop("subscribe", jen$1.parens(renderSymbolReference(this._pkgs, subscriber)).as.any),
|
|
427
507
|
astNodeExpr && jen$1.prop("astNode", astNodeExpr),
|
|
428
508
|
]));
|
|
429
509
|
}
|
|
430
510
|
_renderFieldsThunk(type, inputFieldDirectives, includeAstNodes, noresolver) {
|
|
431
511
|
let astNodeExpr;
|
|
432
512
|
if (includeAstNodes) {
|
|
433
|
-
astNodeExpr = jen$1
|
|
513
|
+
astNodeExpr = jen$1
|
|
514
|
+
.id(`${type.name}Type`)
|
|
515
|
+
.dot("astNode")
|
|
516
|
+
.op("?")
|
|
517
|
+
.dot("fields")
|
|
518
|
+
.op("?.");
|
|
434
519
|
}
|
|
435
520
|
return jen$1.arrow().parens(jen$1.obj(...Object.values(type.getFields())
|
|
436
521
|
.map((field, i) => [field, i])
|
|
@@ -452,7 +537,7 @@ class GeneratorContext {
|
|
|
452
537
|
return "unknown";
|
|
453
538
|
}
|
|
454
539
|
if (type instanceof GraphQLEnumType) {
|
|
455
|
-
return
|
|
540
|
+
return `E${type.name}`;
|
|
456
541
|
}
|
|
457
542
|
return type.name;
|
|
458
543
|
}
|
|
@@ -488,19 +573,22 @@ class GeneratorContext {
|
|
|
488
573
|
}
|
|
489
574
|
}
|
|
490
575
|
if (!returnType) {
|
|
491
|
-
console.log(
|
|
576
|
+
console.log(`WARNING: Could not determine scalar ${type.name} type from parseValue or parseLiteral`);
|
|
492
577
|
}
|
|
493
|
-
|
|
578
|
+
this._scalarTypeTypeCache[type.name] = returnType;
|
|
579
|
+
return returnType;
|
|
494
580
|
}
|
|
495
581
|
_renderGraphQLTypeType(type) {
|
|
496
582
|
if (type instanceof GraphQLNonNull) {
|
|
497
583
|
return this._renderGraphQLTypeType(type.ofType);
|
|
498
584
|
}
|
|
499
585
|
if (type instanceof GraphQLList) {
|
|
500
|
-
return jen$1
|
|
586
|
+
return jen$1
|
|
587
|
+
.id("Array")
|
|
588
|
+
.types(this._renderOptionalGraphQLTypeType(type.ofType));
|
|
501
589
|
}
|
|
502
590
|
if (type instanceof GraphQLDirective) {
|
|
503
|
-
throw new Error(
|
|
591
|
+
throw new Error(`unexpected directive type ${type.name}`);
|
|
504
592
|
}
|
|
505
593
|
return jen$1.id(this._deriveGraphQLTypeName(type));
|
|
506
594
|
}
|
|
@@ -511,13 +599,20 @@ class GeneratorContext {
|
|
|
511
599
|
}
|
|
512
600
|
_renderGraphQLObjectTypeDefinition(type, { inputFieldDirectives, includeAstNodes }) {
|
|
513
601
|
const typeInterfaces = type.getInterfaces();
|
|
514
|
-
return jen$1.new
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
602
|
+
return jen$1.new
|
|
603
|
+
.add(this._gql("GraphQLObjectType"))
|
|
604
|
+
.call(jen$1.obj(jen$1.prop("name", jen$1.lit(type.name)), jen$1.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives, includeAstNodes, !this._includeSubscriptionFieldResolvers && type.name === "Subscription")), ...truthify([
|
|
605
|
+
type.description &&
|
|
606
|
+
jen$1.prop("description", jen$1.lit(type.description)),
|
|
607
|
+
typeInterfaces.length &&
|
|
608
|
+
jen$1.prop("interfaces", jen$1.arrow().arr(
|
|
609
|
+
// do not sort interfaces, the declaration order may be important
|
|
610
|
+
...typeInterfaces.map(this._renderGraphQLTypeIdentifier, this))),
|
|
611
|
+
includeAstNodes &&
|
|
612
|
+
type.astNode &&
|
|
613
|
+
jen$1.prop("astNode", renderAstNode(type.astNode)),
|
|
614
|
+
])))
|
|
615
|
+
.as.add(this._gql("GraphQLObjectType"));
|
|
521
616
|
}
|
|
522
617
|
_renderGraphQLObjectTypeTypes(type) {
|
|
523
618
|
const fieldsWithArgs = Object.values(type.getFields())
|
|
@@ -527,7 +622,7 @@ class GeneratorContext {
|
|
|
527
622
|
jen$1.export.add(this._renderTypeInterface(type)),
|
|
528
623
|
...(fieldsWithArgs.length
|
|
529
624
|
? [
|
|
530
|
-
jen$1.export.namespace.add(this._renderGraphQLTypeType(type)).block(...fieldsWithArgs.map((field) => jen$1.export.interface.id(pascalCase(field.name
|
|
625
|
+
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)
|
|
531
626
|
.sort(compareName)
|
|
532
627
|
.map((arg) => jen$1.prop(arg.name, this._renderOptionalGraphQLTypeType(arg.type)))))),
|
|
533
628
|
]
|
|
@@ -536,30 +631,64 @@ class GeneratorContext {
|
|
|
536
631
|
}
|
|
537
632
|
_renderGraphQLScalarTypeDefinition(type) {
|
|
538
633
|
const s = this._scalarsInfo[type.name];
|
|
539
|
-
return jen$1.new
|
|
540
|
-
|
|
541
|
-
jen$1.
|
|
542
|
-
|
|
543
|
-
|
|
634
|
+
return jen$1.new
|
|
635
|
+
.add(this._gql("GraphQLScalarType"))
|
|
636
|
+
.call(jen$1.obj(jen$1.prop("name", jen$1.lit(type.name)), ...truthify([
|
|
637
|
+
type.description &&
|
|
638
|
+
jen$1.prop("description", jen$1.lit(type.description)),
|
|
639
|
+
jen$1.prop("serialize", s?.serializeFunc
|
|
640
|
+
? renderSymbolReference(this._pkgs, s.serializeFunc)
|
|
641
|
+
: jen$1.trivia("stub").arrow(jen$1.id("v")).id("v")),
|
|
642
|
+
s?.parseValueFunc &&
|
|
643
|
+
jen$1.prop("parseValue", renderSymbolReference(this._pkgs, s.parseValueFunc)),
|
|
644
|
+
s?.parseLiteralFunc &&
|
|
645
|
+
jen$1.prop("parseLiteral", renderSymbolReference(this._pkgs, s.parseLiteralFunc)),
|
|
544
646
|
])));
|
|
545
647
|
}
|
|
546
648
|
_renderTypeResolverAndCastFunctions(type, subTypes, prefix) {
|
|
547
649
|
const sortedSubTypes = Array.from(subTypes).sort(compareName);
|
|
548
650
|
return [
|
|
549
|
-
jen$1
|
|
651
|
+
jen$1
|
|
652
|
+
.arrow(jen$1.prop("v", jen$1.any))
|
|
653
|
+
.block(jen$1
|
|
654
|
+
.switch(jen$1.id("v").computed(jen$1.id(`${prefix}Symbol_${type.name}`)))
|
|
655
|
+
.block(...sortedSubTypes.map((subType) => jen$1
|
|
656
|
+
.case(jen$1.id(`${prefix}TypeSymbol_${subType.name}_${type.name}`))
|
|
657
|
+
.return(jen$1.lit(subType.name)))), jen$1.return(jen$1.id("v").dot("__typename"))),
|
|
550
658
|
[
|
|
551
|
-
jen$1.const
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
.
|
|
659
|
+
jen$1.const
|
|
660
|
+
.id(`${prefix}Symbol_${type.name}`)
|
|
661
|
+
.op("=")
|
|
662
|
+
.id("Symbol")
|
|
663
|
+
.call(jen$1.lit(`${type.name} type`)),
|
|
664
|
+
...sortedSubTypes.map((subType) => jen$1.const
|
|
665
|
+
.id(`${prefix}TypeSymbol_${subType.name}_${type.name}`)
|
|
666
|
+
.op("=")
|
|
667
|
+
.id("Symbol")
|
|
668
|
+
.call(jen$1.lit(`${subType.name} ${type.name}`))),
|
|
669
|
+
...sortedSubTypes.map((subType) => jen$1.export.const
|
|
670
|
+
.id(`as${subType.name}${type.name}`)
|
|
671
|
+
.op("=")
|
|
672
|
+
.types(jen$1.id("T"))
|
|
673
|
+
.params(jen$1.prop("v", jen$1.any))
|
|
674
|
+
.op(":")
|
|
675
|
+
.intersect(jen$1.id("T"), jen$1.obj(jen$1.prop(jen$1.computed(jen$1.id(`${prefix}Symbol_${type.name}`)), jen$1.symbol)))
|
|
676
|
+
.op("=>")
|
|
677
|
+
.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}`))))),
|
|
555
678
|
],
|
|
556
679
|
];
|
|
557
680
|
}
|
|
558
681
|
_renderGraphQLInterfaceTypeDefinition(type, { inputFieldDirectives, includeAstNodes }) {
|
|
559
|
-
return jen$1.new
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
682
|
+
return jen$1.new
|
|
683
|
+
.add(this._gql("GraphQLInterfaceType"))
|
|
684
|
+
.call(jen$1.obj(jen$1.prop("name", jen$1.lit(type.name)), jen$1.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives, includeAstNodes)), ...truthify([
|
|
685
|
+
type.description &&
|
|
686
|
+
jen$1.prop("description", jen$1.lit(type.description)),
|
|
687
|
+
includeAstNodes &&
|
|
688
|
+
type.astNode &&
|
|
689
|
+
jen$1.prop("astNode", renderAstNode(type.astNode)),
|
|
690
|
+
])))
|
|
691
|
+
.as.add(this._gql("GraphQLInterfaceType"));
|
|
563
692
|
}
|
|
564
693
|
_renderGraphQLInterfaceTypeTypes(type, { implementors: { implementors } }) {
|
|
565
694
|
const fieldsWithArgs = Object.values(type.getFields())
|
|
@@ -567,30 +696,55 @@ class GeneratorContext {
|
|
|
567
696
|
.sort(compareName);
|
|
568
697
|
return [
|
|
569
698
|
jen$1.export.add(this._renderTypeInterface(type)),
|
|
570
|
-
jen$1.export.namespace.id(type.name).block(...implementors.map((implementor) => jen$1.export.const
|
|
571
|
-
.
|
|
699
|
+
jen$1.export.namespace.id(type.name).block(...implementors.map((implementor) => jen$1.export.const
|
|
700
|
+
.id(`as${pascalCase(implementor.name)}`)
|
|
701
|
+
.op("=")
|
|
702
|
+
.types(jen$1.id("T"))
|
|
703
|
+
.params(jen$1.prop("v", jen$1.id("T")))
|
|
704
|
+
.op("=>")
|
|
705
|
+
.id("setTypename")
|
|
706
|
+
.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)
|
|
572
707
|
.sort(compareName)
|
|
573
708
|
.map((arg) => jen$1.prop(arg.name, this._renderOptionalGraphQLTypeType(arg.type)))))),
|
|
574
709
|
];
|
|
575
710
|
}
|
|
576
711
|
_renderGraphQLUnionTypeDefinition(type) {
|
|
577
|
-
return jen$1.new
|
|
578
|
-
|
|
712
|
+
return jen$1.new
|
|
713
|
+
.add(this._gql("GraphQLUnionType"))
|
|
714
|
+
.call(jen$1.obj(jen$1.prop("name", jen$1.lit(type.name)), jen$1.prop("types", jen$1
|
|
715
|
+
.arrow()
|
|
716
|
+
.array(...type
|
|
717
|
+
.getTypes()
|
|
718
|
+
.map((type) => this._renderGraphQLTypeIdentifier(type)))), ...truthify([
|
|
719
|
+
type.description &&
|
|
720
|
+
jen$1.prop("description", jen$1.lit(type.description)),
|
|
579
721
|
])));
|
|
580
722
|
}
|
|
581
723
|
_renderGraphQLUnionTypeTypes(type) {
|
|
582
724
|
return [
|
|
583
|
-
jen$1.export.type
|
|
584
|
-
|
|
585
|
-
.
|
|
725
|
+
jen$1.export.type
|
|
726
|
+
.add(this._renderGraphQLTypeType(type))
|
|
727
|
+
.op("=")
|
|
728
|
+
.union(...Array.from(type.getTypes())
|
|
729
|
+
.sort(compareName)
|
|
730
|
+
.map(this._renderGraphQLTypeType, this)),
|
|
731
|
+
jen$1.export.namespace.id(type.name).block(...type.getTypes().map((type) => jen$1.export.const
|
|
732
|
+
.id(`as${pascalCase(type.name)}`)
|
|
733
|
+
.op("=")
|
|
734
|
+
.types(jen$1.id("T"))
|
|
735
|
+
.params(jen$1.prop("v", jen$1.id("T")))
|
|
736
|
+
.op("=>")
|
|
737
|
+
.id("setTypename")
|
|
738
|
+
.call(jen$1.id("v"), jen$1.lit(type.name)))),
|
|
586
739
|
];
|
|
587
740
|
}
|
|
588
741
|
_findInputDirectiveInfoFromArgOrField(field, inputFieldDirectives) {
|
|
589
742
|
const fieldTypeName = getNamedType(field.type).name;
|
|
590
743
|
let transform;
|
|
591
|
-
if (inputFieldDirectives[fieldTypeName] &&
|
|
744
|
+
if (inputFieldDirectives[fieldTypeName] &&
|
|
745
|
+
Object.keys(inputFieldDirectives[fieldTypeName]).length) {
|
|
592
746
|
transform = {
|
|
593
|
-
symbol:
|
|
747
|
+
symbol: `transform${fieldTypeName}`,
|
|
594
748
|
};
|
|
595
749
|
}
|
|
596
750
|
if (field.astNode?.directives?.length) {
|
|
@@ -610,9 +764,7 @@ class GeneratorContext {
|
|
|
610
764
|
}
|
|
611
765
|
}
|
|
612
766
|
_renderInputFieldsWithDirectives(valueExpr, fieldsWithDirectives, spread) {
|
|
613
|
-
return jen$1.obj(...truthify([
|
|
614
|
-
spread && jen$1.spread(valueExpr),
|
|
615
|
-
]), ...fieldsWithDirectives.map(({ field, directives, transform }) => {
|
|
767
|
+
return jen$1.obj(...truthify([spread && jen$1.spread(valueExpr)]), ...fieldsWithDirectives.map(({ field, directives, transform }) => {
|
|
616
768
|
const fieldExpr = valueExpr.dot(field.name);
|
|
617
769
|
const nullableType = getNullableType(field.type);
|
|
618
770
|
let transformedExpr;
|
|
@@ -629,50 +781,107 @@ class GeneratorContext {
|
|
|
629
781
|
transformedExpr = renderSymbolReference(this._pkgs, ref).call(transformedExpr, this._renderArgumentNodes(args));
|
|
630
782
|
}
|
|
631
783
|
if (nullableType instanceof GraphQLList) {
|
|
632
|
-
transformedExpr = jen$1
|
|
784
|
+
transformedExpr = jen$1
|
|
785
|
+
.id("Array")
|
|
786
|
+
.dot("from")
|
|
787
|
+
.call(valueExpr.dot(field.name), jen$1.arrow(jen$1.id("elem")).add(transformedExpr));
|
|
633
788
|
if (!(field.type instanceof GraphQLNonNull)) {
|
|
634
|
-
transformedExpr = jen$1.cond(valueExpr
|
|
789
|
+
transformedExpr = jen$1.cond(valueExpr
|
|
790
|
+
.dot(field.name)
|
|
791
|
+
.op("===")
|
|
792
|
+
.null.op("||")
|
|
793
|
+
.add(valueExpr)
|
|
794
|
+
.dot(field.name)
|
|
795
|
+
.op("===").undefined, jen$1.undefined, transformedExpr);
|
|
635
796
|
}
|
|
636
797
|
}
|
|
637
798
|
return jen$1.prop(field.name, transformedExpr);
|
|
638
799
|
}));
|
|
639
800
|
}
|
|
640
801
|
_renderGraphQLInputObjectTypeDefinition(type, { inputFieldDirectives, includeAstNodes }) {
|
|
641
|
-
return jen$1.new
|
|
642
|
-
|
|
643
|
-
|
|
802
|
+
return jen$1.new
|
|
803
|
+
.add(this._gql("GraphQLInputObjectType"))
|
|
804
|
+
.call(jen$1.obj(jen$1.prop("name", jen$1.lit(type.name)), jen$1.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives, includeAstNodes, true)), ...truthify([
|
|
805
|
+
type.description &&
|
|
806
|
+
jen$1.prop("description", jen$1.lit(type.description)),
|
|
807
|
+
includeAstNodes &&
|
|
808
|
+
type.astNode &&
|
|
809
|
+
jen$1.prop("astNode", renderAstNode(type.astNode)),
|
|
644
810
|
])));
|
|
645
811
|
}
|
|
646
812
|
_renderGraphQLInputObjectTypeTypes(type, { inputFieldDirectives }) {
|
|
647
|
-
const fieldsWithDirectives = truthify(Object.values(type.getFields())
|
|
648
|
-
.map((f) => this._findInputDirectiveInfoFromArgOrField(f, inputFieldDirectives)));
|
|
813
|
+
const fieldsWithDirectives = truthify(Object.values(type.getFields()).map((f) => this._findInputDirectiveInfoFromArgOrField(f, inputFieldDirectives)));
|
|
649
814
|
return [
|
|
650
815
|
jen$1.export.interface.add(this._renderGraphQLTypeType(type)).block(...Object.values(type.getFields())
|
|
651
816
|
.sort(compareName)
|
|
652
817
|
.map((field) => jen$1.prop(field.name, this._renderOptionalGraphQLTypeType(field.type)))),
|
|
653
818
|
...truthify([
|
|
654
819
|
fieldsWithDirectives.length &&
|
|
655
|
-
jen$1.const
|
|
656
|
-
.
|
|
820
|
+
jen$1.const
|
|
821
|
+
.id(`transform${this._deriveGraphQLTypeName(type)}`)
|
|
822
|
+
.op("=")
|
|
823
|
+
.types(jen$1.id("T").extends.union(jen$1.id(type.name), jen$1.undefined))
|
|
824
|
+
.params(jen$1.prop("v", jen$1.id("T")))
|
|
825
|
+
.op(":")
|
|
826
|
+
.id("T")
|
|
827
|
+
.op("=>")
|
|
828
|
+
.parens(jen$1
|
|
829
|
+
.id("v")
|
|
830
|
+
.op("&&")
|
|
831
|
+
.add(this._renderInputFieldsWithDirectives(jen$1.id("v"), fieldsWithDirectives, fieldsWithDirectives.length <
|
|
832
|
+
Object.keys(type.getFields()).length))),
|
|
657
833
|
]),
|
|
658
834
|
];
|
|
659
835
|
}
|
|
660
836
|
_renderGraphQLEnumTypeDefinition(type) {
|
|
661
837
|
const sortedValues = Array.from(type.getValues()).sort(compareName);
|
|
662
|
-
return jen$1.new
|
|
663
|
-
|
|
664
|
-
|
|
838
|
+
return jen$1.new
|
|
839
|
+
.add(this._gql("GraphQLEnumType"))
|
|
840
|
+
.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([
|
|
841
|
+
e.description &&
|
|
842
|
+
jen$1.prop("description", jen$1.lit(e.description)),
|
|
843
|
+
e.deprecationReason &&
|
|
844
|
+
jen$1.prop("deprecationReason", jen$1.lit(e.deprecationReason)),
|
|
665
845
|
])))))), ...truthify([
|
|
666
|
-
type.description &&
|
|
846
|
+
type.description &&
|
|
847
|
+
jen$1.prop("description", jen$1.lit(type.description)),
|
|
667
848
|
])));
|
|
668
849
|
}
|
|
669
850
|
_renderGraphQLEnumTypeTypes(type) {
|
|
670
851
|
const sortedValues = Array.from(type.getValues()).sort(compareName);
|
|
671
852
|
return [
|
|
672
|
-
jen$1.export.enum
|
|
673
|
-
|
|
853
|
+
jen$1.export.enum
|
|
854
|
+
.add(this._renderGraphQLTypeType(type))
|
|
855
|
+
.obj(...sortedValues.map(({ name }) => jen$1.id(name).op("=").lit(name))),
|
|
856
|
+
jen$1.export
|
|
857
|
+
.function(jen$1.id(`is${this._deriveGraphQLTypeName(type)}`), jen$1.prop("v", jen$1.id("any")))
|
|
858
|
+
.op(":")
|
|
859
|
+
.id("v")
|
|
860
|
+
.is.add(this._renderGraphQLTypeType(type))
|
|
861
|
+
.block(jen$1.return(jen$1.id("v").in.add(this._renderGraphQLTypeType(type)))),
|
|
674
862
|
];
|
|
675
863
|
}
|
|
864
|
+
_getGraphQLTypeClass(type) {
|
|
865
|
+
if (type instanceof GraphQLObjectType) {
|
|
866
|
+
return 'GraphQLObjectType';
|
|
867
|
+
}
|
|
868
|
+
if (type instanceof GraphQLScalarType) {
|
|
869
|
+
return 'GraphQLScalarType';
|
|
870
|
+
}
|
|
871
|
+
if (type instanceof GraphQLInterfaceType) {
|
|
872
|
+
return 'GraphQLInterfaceType';
|
|
873
|
+
}
|
|
874
|
+
if (type instanceof GraphQLUnionType) {
|
|
875
|
+
return 'GraphQLUnionType';
|
|
876
|
+
}
|
|
877
|
+
if (type instanceof GraphQLInputObjectType) {
|
|
878
|
+
return 'GraphQLInputObjectType';
|
|
879
|
+
}
|
|
880
|
+
if (type instanceof GraphQLEnumType) {
|
|
881
|
+
return 'GraphQLEnumType';
|
|
882
|
+
}
|
|
883
|
+
throw new Error(`unhandled type: ${type.toString()}`);
|
|
884
|
+
}
|
|
676
885
|
_getRenderDefintionFnForType(type) {
|
|
677
886
|
if (type instanceof GraphQLObjectType) {
|
|
678
887
|
return this._renderGraphQLObjectTypeDefinition.bind(this, type);
|
|
@@ -692,7 +901,7 @@ class GeneratorContext {
|
|
|
692
901
|
if (type instanceof GraphQLEnumType) {
|
|
693
902
|
return this._renderGraphQLEnumTypeDefinition.bind(this, type);
|
|
694
903
|
}
|
|
695
|
-
throw new Error(
|
|
904
|
+
throw new Error(`unhandled type: ${type.toString()}`);
|
|
696
905
|
}
|
|
697
906
|
_getRenderTypesFnForType(type) {
|
|
698
907
|
if (type instanceof GraphQLObjectType) {
|
|
@@ -713,10 +922,15 @@ class GeneratorContext {
|
|
|
713
922
|
if (type instanceof GraphQLEnumType) {
|
|
714
923
|
return this._renderGraphQLEnumTypeTypes.bind(this, type);
|
|
715
924
|
}
|
|
716
|
-
throw new Error(
|
|
925
|
+
throw new Error(`unhandled type: ${type.toString()}`);
|
|
717
926
|
}
|
|
718
927
|
_renderGraphQLTypeDefinitions(type, interfaces, inputFieldDirectives, includeAstNodes) {
|
|
719
|
-
return jen$1.const
|
|
928
|
+
return jen$1.const
|
|
929
|
+
.add(this._renderGraphQLTypeIdentifier(type))
|
|
930
|
+
.op(":")
|
|
931
|
+
.id(this._getGraphQLTypeClass(type))
|
|
932
|
+
.op("=")
|
|
933
|
+
.add(this._getRenderDefintionFnForType(type)({
|
|
720
934
|
implementors: interfaces[type.name],
|
|
721
935
|
inputFieldDirectives,
|
|
722
936
|
includeAstNodes,
|
|
@@ -729,54 +943,101 @@ class GeneratorContext {
|
|
|
729
943
|
});
|
|
730
944
|
}
|
|
731
945
|
_renderGraphQLDirectiveDefinition(directive, includeAstNodes) {
|
|
732
|
-
return jen$1.const
|
|
733
|
-
.
|
|
734
|
-
|
|
946
|
+
return jen$1.const
|
|
947
|
+
.add(this._renderGraphQLTypeIdentifier(directive))
|
|
948
|
+
.op("=")
|
|
949
|
+
.new.add(this._gql("GraphQLDirective"))
|
|
950
|
+
.call(jen$1.obj(jen$1.prop("name", jen$1.lit(directive.name)), jen$1.prop("locations", jen$1.array(...Array.from(directive.locations)
|
|
951
|
+
.sort()
|
|
952
|
+
.map((location) => jen$1.add(this._gql("DirectiveLocation")).dot(location)))), jen$1.prop("args", this._renderArgumentsObject(directive.args)), ...truthify([
|
|
953
|
+
directive.description &&
|
|
954
|
+
jen$1.prop("description", jen$1.lit(directive.description)),
|
|
735
955
|
directive.isRepeatable && jen$1.prop("isRepeatable", jen$1.true),
|
|
736
|
-
includeAstNodes &&
|
|
956
|
+
includeAstNodes &&
|
|
957
|
+
directive.astNode &&
|
|
958
|
+
jen$1.prop("astNode", renderAstNode(directive.astNode)),
|
|
737
959
|
])));
|
|
738
960
|
}
|
|
739
961
|
_renderGraphQLDirectiveTypes(directive) {
|
|
740
962
|
return truthify([
|
|
741
|
-
directive.args.length &&
|
|
742
|
-
|
|
743
|
-
|
|
963
|
+
directive.args.length &&
|
|
964
|
+
jen$1.export.interface
|
|
965
|
+
.id(pascalCase(`${directive.name}_directive_args`))
|
|
966
|
+
.block(...directive.args.map((arg) => jen$1.prop(jen$1
|
|
967
|
+
.id(arg.name)
|
|
968
|
+
.add(...truthify([
|
|
969
|
+
!(arg.type instanceof GraphQLNonNull) && jen$1.op("?"),
|
|
970
|
+
])), this._renderGraphQLTypeType(arg.type)))),
|
|
744
971
|
]);
|
|
745
972
|
}
|
|
746
973
|
schemaExprs(schema, [types, interfaces, inputFieldDirectives, includeAstNodes]) {
|
|
974
|
+
const queryType = schema.getQueryType();
|
|
975
|
+
const mutationType = schema.getMutationType();
|
|
976
|
+
const subscriptionType = schema.getSubscriptionType();
|
|
747
977
|
return [
|
|
748
978
|
...[
|
|
749
979
|
// render type definitions
|
|
750
980
|
...types
|
|
751
|
-
.map((type) => [
|
|
981
|
+
.map((type) => [
|
|
982
|
+
type.name,
|
|
983
|
+
this._renderGraphQLTypeDefinitions(type, interfaces, inputFieldDirectives, includeAstNodes),
|
|
984
|
+
])
|
|
752
985
|
.sort(compareEntryKey),
|
|
753
986
|
// render directive definitions
|
|
754
|
-
...schema
|
|
987
|
+
...schema
|
|
988
|
+
.getDirectives()
|
|
755
989
|
.filter((d) => !isBuiltInDirective(d.name))
|
|
756
|
-
.map((directive) => [
|
|
990
|
+
.map((directive) => [
|
|
991
|
+
directive.name,
|
|
992
|
+
this._renderGraphQLDirectiveDefinition(directive),
|
|
993
|
+
])
|
|
757
994
|
.sort(compareEntryKey),
|
|
758
995
|
].map(([, expr]) => expr),
|
|
759
|
-
...Array.from(PRIMITIVE_TYPES)
|
|
760
|
-
.flatMap((type) => {
|
|
996
|
+
...Array.from(PRIMITIVE_TYPES).flatMap((type) => {
|
|
761
997
|
const info = this._scalarsInfo[type];
|
|
762
998
|
if (!info) {
|
|
763
999
|
return [];
|
|
764
1000
|
}
|
|
765
1001
|
return [
|
|
766
1002
|
jen$1.statements(...[
|
|
767
|
-
info.serializeFunc &&
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
1003
|
+
info.serializeFunc &&
|
|
1004
|
+
this._gql(`GraphQL${type}`)
|
|
1005
|
+
.dot("serialize")
|
|
1006
|
+
.op("=")
|
|
1007
|
+
.parens(renderSymbolReference(this._pkgs, info.serializeFunc).as
|
|
1008
|
+
.any),
|
|
1009
|
+
info.parseValueFunc &&
|
|
1010
|
+
this._gql(`GraphQL${type}`)
|
|
1011
|
+
.dot("parseValue")
|
|
1012
|
+
.op("=")
|
|
1013
|
+
.parens(renderSymbolReference(this._pkgs, info.parseValueFunc).as
|
|
1014
|
+
.any),
|
|
1015
|
+
info.parseLiteralFunc &&
|
|
1016
|
+
this._gql(`GraphQL${type}`)
|
|
1017
|
+
.dot("parseLiteral")
|
|
1018
|
+
.op("=")
|
|
1019
|
+
.parens(renderSymbolReference(this._pkgs, info.parseLiteralFunc).as
|
|
1020
|
+
.any),
|
|
1021
|
+
].filter(Boolean)),
|
|
771
1022
|
];
|
|
772
1023
|
}),
|
|
773
1024
|
// render schema
|
|
774
|
-
jen$1.const
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
? [
|
|
1025
|
+
jen$1.const
|
|
1026
|
+
.id("schema")
|
|
1027
|
+
.op("=")
|
|
1028
|
+
.new.add(this._gql("GraphQLSchema"))
|
|
1029
|
+
.call(jen$1.obj(...(queryType
|
|
1030
|
+
? [
|
|
1031
|
+
jen$1.prop("query", this._renderGraphQLTypeIdentifier(queryType)),
|
|
1032
|
+
]
|
|
1033
|
+
: []), ...(mutationType
|
|
1034
|
+
? [
|
|
1035
|
+
jen$1.prop("mutation", this._renderGraphQLTypeIdentifier(mutationType)),
|
|
1036
|
+
]
|
|
1037
|
+
: []), ...(subscriptionType
|
|
1038
|
+
? [
|
|
1039
|
+
jen$1.prop("subscription", this._renderGraphQLTypeIdentifier(subscriptionType)),
|
|
1040
|
+
]
|
|
780
1041
|
: []), jen$1.prop("types", jen$1.array(...types.map((type) => this._renderGraphQLTypeIdentifier(type)))), jen$1.prop("directives", jen$1.array(...Array.from(schema.getDirectives())
|
|
781
1042
|
.filter((d) => !isBuiltInDirective(d.name))
|
|
782
1043
|
.map((d) => this._renderGraphQLTypeIdentifier(d)))))),
|
|
@@ -785,15 +1046,44 @@ class GeneratorContext {
|
|
|
785
1046
|
}
|
|
786
1047
|
typesExprs(schema, [types, interfaces, inputFieldDirectives]) {
|
|
787
1048
|
return [
|
|
788
|
-
[
|
|
1049
|
+
[
|
|
1050
|
+
"",
|
|
1051
|
+
jen$1.const
|
|
1052
|
+
.id("setTypename")
|
|
1053
|
+
.op("=")
|
|
1054
|
+
.types(jen$1.id("T"))
|
|
1055
|
+
.params(jen$1.id("v").op(":").id("T"), jen$1.id("t").op(":").string)
|
|
1056
|
+
.op(":")
|
|
1057
|
+
.id("T")
|
|
1058
|
+
.op("=>")
|
|
1059
|
+
.block(jen$1
|
|
1060
|
+
.if(jen$1
|
|
1061
|
+
.op("!")
|
|
1062
|
+
.id("v")
|
|
1063
|
+
.op("||")
|
|
1064
|
+
.typeof(jen$1.id("v"))
|
|
1065
|
+
.op("!==")
|
|
1066
|
+
.lit("object"))
|
|
1067
|
+
.block(jen$1.throw.new.id("Error").call(jen$1.lit("expected object"))), jen$1.return(jen$1
|
|
1068
|
+
.id("Object")
|
|
1069
|
+
.dot("assign")
|
|
1070
|
+
.call(jen$1.id("v"), jen$1.obj(jen$1.prop(jen$1.id("__typename"), jen$1.id("t")))))),
|
|
1071
|
+
],
|
|
789
1072
|
// render type definitions
|
|
790
1073
|
...types
|
|
791
|
-
.map((type) => [
|
|
1074
|
+
.map((type) => [
|
|
1075
|
+
type.name,
|
|
1076
|
+
jen$1.statements(...this._renderGraphQLTypeTypes(type, interfaces, inputFieldDirectives)),
|
|
1077
|
+
])
|
|
792
1078
|
.sort(compareEntryKey),
|
|
793
1079
|
// render directive definitions
|
|
794
|
-
...schema
|
|
1080
|
+
...schema
|
|
1081
|
+
.getDirectives()
|
|
795
1082
|
.filter((d) => !isBuiltInDirective(d.name))
|
|
796
|
-
.map((directive) => [
|
|
1083
|
+
.map((directive) => [
|
|
1084
|
+
directive.name,
|
|
1085
|
+
jen$1.statements(...this._renderGraphQLDirectiveTypes(directive)),
|
|
1086
|
+
])
|
|
797
1087
|
.sort(compareEntryKey),
|
|
798
1088
|
].map(([, expr]) => expr);
|
|
799
1089
|
}
|
|
@@ -807,7 +1097,9 @@ class GeneratorContext {
|
|
|
807
1097
|
const base = outfile.startsWith("/") ? outfile : path.resolve(outfile);
|
|
808
1098
|
const statements = renderStatements.call(this);
|
|
809
1099
|
const [localImports, externalImports] = partition(Object.entries(this._pkgs.requires), ([pkg]) => pkg.startsWith("/"));
|
|
810
|
-
return format(jen$1
|
|
1100
|
+
return format(jen$1
|
|
1101
|
+
.statements(renderImports(path.dirname(base), externalImports, this._pkgs.aliases, this._extMode), renderImports(path.dirname(base), localImports, this._pkgs.aliases, this._extMode), ...statements)
|
|
1102
|
+
.toString());
|
|
811
1103
|
}
|
|
812
1104
|
static prepareInterfacesAndInputFieldDirectives(schema, options = {}) {
|
|
813
1105
|
if (options.fieldDirectivesInfo) {
|
|
@@ -835,7 +1127,11 @@ class GeneratorContext {
|
|
|
835
1127
|
}
|
|
836
1128
|
for (const field of Object.values(type.getFields())) {
|
|
837
1129
|
if (getNamedType(field.type) instanceof GraphQLInputObjectType) {
|
|
838
|
-
typesWithObjectFields.push([
|
|
1130
|
+
typesWithObjectFields.push([
|
|
1131
|
+
type.name,
|
|
1132
|
+
field.name,
|
|
1133
|
+
getNamedType(field.type).name,
|
|
1134
|
+
]);
|
|
839
1135
|
}
|
|
840
1136
|
const directives = field.astNode?.directives;
|
|
841
1137
|
if (!directives) {
|
|
@@ -846,22 +1142,34 @@ class GeneratorContext {
|
|
|
846
1142
|
if (!options.inputDirectivesInfo[name]) {
|
|
847
1143
|
continue;
|
|
848
1144
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
1145
|
+
if (!inputFieldDirectives[type.name]) {
|
|
1146
|
+
inputFieldDirectives[type.name] = {};
|
|
1147
|
+
}
|
|
1148
|
+
const fieldDirectives = inputFieldDirectives[type.name];
|
|
1149
|
+
if (!fieldDirectives[field.name]) {
|
|
1150
|
+
fieldDirectives[field.name] = [];
|
|
1151
|
+
}
|
|
1152
|
+
fieldDirectives[field.name].push(name);
|
|
852
1153
|
}
|
|
853
1154
|
}
|
|
854
1155
|
}
|
|
855
1156
|
for (let changes = 1; changes; changes = 0) {
|
|
856
1157
|
const newTypesWithObjectFields = new Array();
|
|
857
|
-
for (const [typeName, fieldName, objectTypeName] of typesWithObjectFields) {
|
|
1158
|
+
for (const [typeName, fieldName, objectTypeName,] of typesWithObjectFields) {
|
|
858
1159
|
console.log(`checking ${typeName}.${fieldName} for ${objectTypeName}`);
|
|
859
1160
|
if (inputFieldDirectives[objectTypeName]) {
|
|
860
|
-
inputFieldDirectives[typeName] = {
|
|
1161
|
+
inputFieldDirectives[typeName] = {
|
|
1162
|
+
...inputFieldDirectives[typeName],
|
|
1163
|
+
[fieldName]: [],
|
|
1164
|
+
};
|
|
861
1165
|
changes += 1;
|
|
862
1166
|
}
|
|
863
1167
|
else {
|
|
864
|
-
newTypesWithObjectFields.push([
|
|
1168
|
+
newTypesWithObjectFields.push([
|
|
1169
|
+
typeName,
|
|
1170
|
+
fieldName,
|
|
1171
|
+
objectTypeName,
|
|
1172
|
+
]);
|
|
865
1173
|
}
|
|
866
1174
|
}
|
|
867
1175
|
typesWithObjectFields = newTypesWithObjectFields;
|
|
@@ -882,7 +1190,12 @@ class GeneratorContext {
|
|
|
882
1190
|
interfaces[iface.name].implementors.push(type);
|
|
883
1191
|
}
|
|
884
1192
|
}
|
|
885
|
-
return [
|
|
1193
|
+
return [
|
|
1194
|
+
types,
|
|
1195
|
+
interfaces,
|
|
1196
|
+
inputFieldDirectives,
|
|
1197
|
+
options.includeAstNodes,
|
|
1198
|
+
];
|
|
886
1199
|
}
|
|
887
1200
|
}
|
|
888
1201
|
function createGenerator(schema, options) {
|
|
@@ -922,8 +1235,8 @@ function createMatcher(pattern) {
|
|
|
922
1235
|
if (typeof pattern === "string") {
|
|
923
1236
|
return pm(pattern);
|
|
924
1237
|
}
|
|
925
|
-
|
|
926
|
-
|
|
1238
|
+
const matchers = [];
|
|
1239
|
+
const globs = [];
|
|
927
1240
|
for (const p of Array.isArray(pattern) ? pattern : [pattern]) {
|
|
928
1241
|
if (typeof p === "string") {
|
|
929
1242
|
globs.push(p);
|
|
@@ -945,9 +1258,9 @@ function createMatcher(pattern) {
|
|
|
945
1258
|
}
|
|
946
1259
|
|
|
947
1260
|
async function parseResolverFile(path) {
|
|
948
|
-
return Object.fromEntries(Object.entries((await parseModule(path)).exports)
|
|
949
|
-
|
|
950
|
-
|
|
1261
|
+
return Object.fromEntries(Object.entries((await parseModule(path)).exports).flatMap(([name, decls]) => decls.flatMap(({ declaration }) => {
|
|
1262
|
+
if (ts.isVariableDeclaration(declaration) &&
|
|
1263
|
+
declaration.initializer) {
|
|
951
1264
|
if (ts.isFunctionExpression(declaration.initializer)) {
|
|
952
1265
|
return [[name, { module: path, symbol: name }]];
|
|
953
1266
|
}
|
|
@@ -966,14 +1279,18 @@ async function parseTypeResolvers(typeName, glob, ignore) {
|
|
|
966
1279
|
const result = {};
|
|
967
1280
|
for await (const entry of globIterate(glob, { withFileTypes: true })) {
|
|
968
1281
|
const fullpath = entry.fullpath();
|
|
969
|
-
if (!shouldIgnore(fullpath) &&
|
|
1282
|
+
if (!shouldIgnore(fullpath) &&
|
|
1283
|
+
entry.isFile() &&
|
|
1284
|
+
entry.name.endsWith(".ts")) {
|
|
970
1285
|
for (const [name, reference] of Object.entries(await parseResolverFile(fullpath))) {
|
|
971
1286
|
let realName = name;
|
|
972
|
-
if (realName === "default" &&
|
|
1287
|
+
if (realName === "default" &&
|
|
1288
|
+
typeof glob === "string" &&
|
|
1289
|
+
glob.endsWith("/*.ts")) {
|
|
973
1290
|
realName = basename(fullpath, extname(fullpath));
|
|
974
1291
|
}
|
|
975
1292
|
if (realName in result) {
|
|
976
|
-
console.warn(`WARNING: Duplicate resolver name: ${typeName ? typeName
|
|
1293
|
+
console.warn(`WARNING: Duplicate resolver name: ${typeName ? `${typeName}.` : ""}${name} in ${fullpath} and ${result[name].module}`);
|
|
977
1294
|
}
|
|
978
1295
|
result[realName] = reference;
|
|
979
1296
|
}
|
|
@@ -986,16 +1303,13 @@ async function parse$2(dirpath, ignore) {
|
|
|
986
1303
|
if (!dir.isDirectory()) {
|
|
987
1304
|
throw new Error(`Expected ${dirpath} to be a directory`);
|
|
988
1305
|
}
|
|
989
|
-
if (!dirpath.endsWith("/")) {
|
|
990
|
-
dirpath += "/";
|
|
991
|
-
}
|
|
992
1306
|
const out = {};
|
|
993
1307
|
const shouldIgnore = createMatcher(ignore);
|
|
994
1308
|
for await (const name of await fs.readdir(dirpath)) {
|
|
995
1309
|
const file = join(dirpath, name);
|
|
996
1310
|
const entry = await fs.stat(file);
|
|
997
1311
|
if (entry.isDirectory()) {
|
|
998
|
-
out[name] = await parseTypeResolvers(name, file
|
|
1312
|
+
out[name] = await parseTypeResolvers(name, `${file}/*.ts`, shouldIgnore);
|
|
999
1313
|
}
|
|
1000
1314
|
else if (entry.isFile() && name.endsWith(".ts")) {
|
|
1001
1315
|
out[name.slice(0, -3)] = await parseTypeResolvers(name.slice(0, -3), file, shouldIgnore);
|
|
@@ -1020,7 +1334,8 @@ function refFromImportTypeNode(node, source) {
|
|
|
1020
1334
|
console.log("WARNING: namespace import for scalar type is not supported");
|
|
1021
1335
|
return;
|
|
1022
1336
|
}
|
|
1023
|
-
if (!ts.isLiteralTypeNode(node.argument) ||
|
|
1337
|
+
if (!ts.isLiteralTypeNode(node.argument) ||
|
|
1338
|
+
!ts.isStringLiteral(node.argument.literal)) {
|
|
1024
1339
|
// this is a grammar error, handling it is out of scope
|
|
1025
1340
|
const { line, character } = getLineAndCharacterOfPosition(source, node.pos);
|
|
1026
1341
|
console.log(`WARNING: grammar error at ${source.fileName}:${line + 1}:${character + 1}`);
|
|
@@ -1035,8 +1350,8 @@ function refFromTypeReferenceNode(typeNode, source) {
|
|
|
1035
1350
|
}
|
|
1036
1351
|
const typeName = typeNode.typeName.text;
|
|
1037
1352
|
if (typeNode.typeArguments?.length) {
|
|
1038
|
-
if (typeName !==
|
|
1039
|
-
throw new Error(
|
|
1353
|
+
if (typeName !== "Promise") {
|
|
1354
|
+
throw new Error("TODO: handle type arguments");
|
|
1040
1355
|
}
|
|
1041
1356
|
return refFromTypeNode(typeNode.typeArguments[0], source);
|
|
1042
1357
|
}
|
|
@@ -1054,7 +1369,11 @@ function refFromTypeReferenceNode(typeNode, source) {
|
|
|
1054
1369
|
if (statement.importClause.name) {
|
|
1055
1370
|
// default import
|
|
1056
1371
|
if (statement.importClause.name.text === typeName) {
|
|
1057
|
-
return {
|
|
1372
|
+
return {
|
|
1373
|
+
module: statement.importClause.name.text,
|
|
1374
|
+
symbol: "default",
|
|
1375
|
+
alias: typeName,
|
|
1376
|
+
};
|
|
1058
1377
|
}
|
|
1059
1378
|
}
|
|
1060
1379
|
if (!statement.importClause.namedBindings) {
|
|
@@ -1065,17 +1384,24 @@ function refFromTypeReferenceNode(typeNode, source) {
|
|
|
1065
1384
|
// TODO: handle namespace imports (will need to check if `typeName` has a dot in it)
|
|
1066
1385
|
continue;
|
|
1067
1386
|
}
|
|
1068
|
-
for (const specifier of statement.importClause.namedBindings.elements ??
|
|
1387
|
+
for (const specifier of statement.importClause.namedBindings.elements ??
|
|
1388
|
+
[]) {
|
|
1069
1389
|
if (specifier.name.text === typeName) {
|
|
1070
|
-
return {
|
|
1390
|
+
return {
|
|
1391
|
+
module: statement.moduleSpecifier.text,
|
|
1392
|
+
symbol: specifier.propertyName?.text ?? typeName,
|
|
1393
|
+
alias: typeName,
|
|
1394
|
+
};
|
|
1071
1395
|
}
|
|
1072
1396
|
}
|
|
1073
1397
|
}
|
|
1074
|
-
else if (ts.isTypeAliasDeclaration(statement) ||
|
|
1398
|
+
else if (ts.isTypeAliasDeclaration(statement) ||
|
|
1399
|
+
ts.isInterfaceDeclaration(statement) ||
|
|
1400
|
+
ts.isEnumDeclaration(statement)) {
|
|
1075
1401
|
if (statement.name.text === typeName) {
|
|
1076
1402
|
if (!statement.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)) {
|
|
1077
1403
|
console.log(statement);
|
|
1078
|
-
console.log(`WARNING: found type ${typeName} in ${source.fileName}:${locLineColumn$1(statement, source).join(
|
|
1404
|
+
console.log(`WARNING: found type ${typeName} in ${source.fileName}:${locLineColumn$1(statement, source).join(":")} but it is not exported`);
|
|
1079
1405
|
continue;
|
|
1080
1406
|
}
|
|
1081
1407
|
return { module: source.fileName, symbol: typeName };
|
|
@@ -1089,16 +1415,14 @@ function refFromTypeNode(typeNode, source) {
|
|
|
1089
1415
|
if (ts.isImportTypeNode(typeNode)) {
|
|
1090
1416
|
return refFromImportTypeNode(typeNode, source);
|
|
1091
1417
|
}
|
|
1092
|
-
|
|
1418
|
+
if (ts.isTokenKind(typeNode.kind)) {
|
|
1093
1419
|
// primitive type string, number, etc...
|
|
1094
1420
|
return { symbol: typeNode.getText(source) };
|
|
1095
1421
|
}
|
|
1096
|
-
|
|
1422
|
+
if (ts.isTypeReferenceNode(typeNode)) {
|
|
1097
1423
|
return refFromTypeReferenceNode(typeNode, source);
|
|
1098
1424
|
}
|
|
1099
|
-
|
|
1100
|
-
console.warn("WARNING: unexpected type node: " + ts.SyntaxKind[typeNode.kind]);
|
|
1101
|
-
}
|
|
1425
|
+
console.warn(`WARNING: unexpected type node: ${ts.SyntaxKind[typeNode.kind]}`);
|
|
1102
1426
|
}
|
|
1103
1427
|
function reconcileScalarType(scalarName, typeDecls, source) {
|
|
1104
1428
|
let type;
|
|
@@ -1106,7 +1430,7 @@ function reconcileScalarType(scalarName, typeDecls, source) {
|
|
|
1106
1430
|
if (!typeNode) {
|
|
1107
1431
|
continue;
|
|
1108
1432
|
}
|
|
1109
|
-
|
|
1433
|
+
const newType = refFromTypeNode(typeNode, source);
|
|
1110
1434
|
if (type && newType) {
|
|
1111
1435
|
if (type.symbol !== newType.symbol ||
|
|
1112
1436
|
type.alias !== newType.alias ||
|
|
@@ -1131,11 +1455,13 @@ function scalarInfoFromObjectLiteralExpression(scalarName, module, properties) {
|
|
|
1131
1455
|
case "serialize":
|
|
1132
1456
|
case "parseValue":
|
|
1133
1457
|
case "parseLiteral":
|
|
1134
|
-
if (!ts.isFunctionExpression(prop.initializer) &&
|
|
1458
|
+
if (!ts.isFunctionExpression(prop.initializer) &&
|
|
1459
|
+
!ts.isArrowFunction(prop.initializer)) {
|
|
1135
1460
|
console.log(`WARNING: expected scalar property ${scalarName}.${prop.name.text} to be a function, but got ${ts.SyntaxKind[prop.initializer.kind]}`);
|
|
1136
1461
|
return [];
|
|
1137
1462
|
}
|
|
1138
|
-
return [
|
|
1463
|
+
return [
|
|
1464
|
+
[
|
|
1139
1465
|
`${prop.name.text}Func`,
|
|
1140
1466
|
{
|
|
1141
1467
|
module: module,
|
|
@@ -1143,7 +1469,8 @@ function scalarInfoFromObjectLiteralExpression(scalarName, module, properties) {
|
|
|
1143
1469
|
property: prop.name.text,
|
|
1144
1470
|
declaration: prop.initializer,
|
|
1145
1471
|
},
|
|
1146
|
-
]
|
|
1472
|
+
],
|
|
1473
|
+
];
|
|
1147
1474
|
default:
|
|
1148
1475
|
console.log(`WARNING: found extraneous scalar property ${scalarName}.${prop.name.text}`);
|
|
1149
1476
|
}
|
|
@@ -1156,7 +1483,8 @@ function scalarInfoFromObjectLiteralExpression(scalarName, module, properties) {
|
|
|
1156
1483
|
case "serialize":
|
|
1157
1484
|
case "parseValue":
|
|
1158
1485
|
case "parseLiteral":
|
|
1159
|
-
return [
|
|
1486
|
+
return [
|
|
1487
|
+
[
|
|
1160
1488
|
`${prop.name.text}Func`,
|
|
1161
1489
|
{
|
|
1162
1490
|
module,
|
|
@@ -1164,7 +1492,8 @@ function scalarInfoFromObjectLiteralExpression(scalarName, module, properties) {
|
|
|
1164
1492
|
property: prop.name.text,
|
|
1165
1493
|
declaration: prop,
|
|
1166
1494
|
},
|
|
1167
|
-
]
|
|
1495
|
+
],
|
|
1496
|
+
];
|
|
1168
1497
|
default:
|
|
1169
1498
|
console.log(`WARNING: found extraneous scalar property ${scalarName}.${prop.name.text}`);
|
|
1170
1499
|
}
|
|
@@ -1183,7 +1512,8 @@ async function parse$1(path) {
|
|
|
1183
1512
|
for (const { declaration, source } of decls) {
|
|
1184
1513
|
sources[name] = source;
|
|
1185
1514
|
if (ts.isVariableDeclaration(declaration)) {
|
|
1186
|
-
if (declaration.initializer &&
|
|
1515
|
+
if (declaration.initializer &&
|
|
1516
|
+
ts.isObjectLiteralExpression(declaration.initializer)) {
|
|
1187
1517
|
scalarFnsInfos[name] = scalarInfoFromObjectLiteralExpression(name, new URL(source.fileName).toString(), declaration.initializer.properties);
|
|
1188
1518
|
}
|
|
1189
1519
|
}
|
|
@@ -1200,18 +1530,23 @@ async function parse$1(path) {
|
|
|
1200
1530
|
}
|
|
1201
1531
|
}
|
|
1202
1532
|
const infos = {};
|
|
1203
|
-
for (const name of new Set([
|
|
1533
|
+
for (const name of new Set([
|
|
1534
|
+
...Object.keys(scalarFnsInfos),
|
|
1535
|
+
...Object.keys(scalarTypeNodes),
|
|
1536
|
+
])) {
|
|
1204
1537
|
const fnsInfo = scalarFnsInfos[name];
|
|
1205
1538
|
const typeNode = scalarTypeNodes[name];
|
|
1206
1539
|
const source = sources[name];
|
|
1207
|
-
const type = typeNode
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1540
|
+
const type = typeNode
|
|
1541
|
+
? {
|
|
1542
|
+
module: source.fileName,
|
|
1543
|
+
symbol: name,
|
|
1544
|
+
}
|
|
1545
|
+
: reconcileScalarType(name, [
|
|
1546
|
+
// NOTE: omit serialize input type because it is supposed to be `unknown`
|
|
1547
|
+
fnsInfo?.parseValueFunc?.declaration?.type,
|
|
1548
|
+
fnsInfo?.parseLiteralFunc?.declaration?.type,
|
|
1549
|
+
], source);
|
|
1215
1550
|
if (type) {
|
|
1216
1551
|
if (type.module) {
|
|
1217
1552
|
type.module = new URL(type.module, source.fileName).toString();
|
|
@@ -1239,8 +1574,10 @@ function traceLine(loc, prefix = "") {
|
|
|
1239
1574
|
return `\n ${prefix}at file://${loc.source.name}:${locLineColumn(loc).join(":")}`;
|
|
1240
1575
|
}
|
|
1241
1576
|
function setTraceToSchema(err, name, loc) {
|
|
1577
|
+
// biome-ignore lint/suspicious/noExplicitAny: hacks
|
|
1242
1578
|
if (globalThis.Deno) {
|
|
1243
1579
|
if (loc) {
|
|
1580
|
+
// biome-ignore lint/suspicious/noExplicitAny: hacks
|
|
1244
1581
|
const trace = err.__callSiteEvals;
|
|
1245
1582
|
const [lineNumber, columnNumber] = locLineColumn(loc);
|
|
1246
1583
|
// NOTE: this is deno magic
|
|
@@ -1253,7 +1590,7 @@ function setTraceToSchema(err, name, loc) {
|
|
|
1253
1590
|
function: undefined,
|
|
1254
1591
|
functionName: name,
|
|
1255
1592
|
methodName: null,
|
|
1256
|
-
fileName:
|
|
1593
|
+
fileName: `file://${loc.source.name}`,
|
|
1257
1594
|
lineNumber,
|
|
1258
1595
|
columnNumber,
|
|
1259
1596
|
evalOrigin: undefined,
|
|
@@ -1297,8 +1634,7 @@ function isListValueNodeEqual(a, b) {
|
|
|
1297
1634
|
return zip(a.values, b.values).every(([a, b]) => isValueNodeEqual(a, b));
|
|
1298
1635
|
}
|
|
1299
1636
|
function isObjectValueNodeEqual(a, b) {
|
|
1300
|
-
return zip(sortNamedNodes(a.fields), sortNamedNodes(b.fields))
|
|
1301
|
-
.every(([a, b]) => a.name.value === b.name.value && isValueNodeEqual(a.value, b.value));
|
|
1637
|
+
return zip(sortNamedNodes(a.fields), sortNamedNodes(b.fields)).every(([a, b]) => a.name.value === b.name.value && isValueNodeEqual(a.value, b.value));
|
|
1302
1638
|
}
|
|
1303
1639
|
function isValueNodeEqual(a, b) {
|
|
1304
1640
|
if (a === b || (!a && !b)) {
|
|
@@ -1366,7 +1702,8 @@ function isInputValueDefinitionNodesEqual(a, b) {
|
|
|
1366
1702
|
if (!a || !b || a.length !== b.length) {
|
|
1367
1703
|
return false;
|
|
1368
1704
|
}
|
|
1369
|
-
return zip(sortNamedNodes(a), sortNamedNodes(b)).every(([a, b]) => a.name.value === b.name.value &&
|
|
1705
|
+
return zip(sortNamedNodes(a), sortNamedNodes(b)).every(([a, b]) => a.name.value === b.name.value &&
|
|
1706
|
+
isTypeNodeEqual(a.type, b.type) &&
|
|
1370
1707
|
isValueNodeEqual(a.defaultValue, b.defaultValue) &&
|
|
1371
1708
|
isDirectiveNodesEqual(a.directives, b.directives));
|
|
1372
1709
|
}
|
|
@@ -1377,17 +1714,15 @@ function mergeFieldDefinitionNodes(name, a, b) {
|
|
|
1377
1714
|
const prev = fields[f.name.value];
|
|
1378
1715
|
if (prev) {
|
|
1379
1716
|
if (!isInputValueDefinitionNodesEqual(prev.arguments, f.arguments)) {
|
|
1380
|
-
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate field with different arguments: ${name}.${f.name.value}`), name
|
|
1717
|
+
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate field with different arguments: ${name}.${f.name.value}`), `${name}.${f.name.value}`, f.loc);
|
|
1381
1718
|
}
|
|
1382
1719
|
if (!isTypeNodeEqual(prev.type, f.type)) {
|
|
1383
|
-
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate field with different type: ${name}.${f.name.value}`), name
|
|
1720
|
+
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate field with different type: ${name}.${f.name.value}`), `${name}.${f.name.value}`, f.type.loc);
|
|
1384
1721
|
}
|
|
1385
|
-
console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}`
|
|
1386
|
-
traceLine(f.loc) +
|
|
1387
|
-
traceLine(prev.loc, "previously ") + "\n");
|
|
1722
|
+
console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}${traceLine(f.loc)}${traceLine(prev.loc, "previously ")}\n`);
|
|
1388
1723
|
fields[f.name.value] = {
|
|
1389
1724
|
...prev,
|
|
1390
|
-
directives: mergeDirectiveNodes(name
|
|
1725
|
+
directives: mergeDirectiveNodes(`${name}.${f.name.value}`, prev.directives, f.directives),
|
|
1391
1726
|
};
|
|
1392
1727
|
}
|
|
1393
1728
|
else {
|
|
@@ -1404,17 +1739,15 @@ function mergeInputValueDefinitionNodes(name, a, b) {
|
|
|
1404
1739
|
const prev = fields[f.name.value];
|
|
1405
1740
|
if (prev) {
|
|
1406
1741
|
if (!isValueNodeEqual(prev.defaultValue, f.defaultValue)) {
|
|
1407
|
-
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate field with different arguments: ${name}.${f.name.value}`), name
|
|
1742
|
+
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate field with different arguments: ${name}.${f.name.value}`), `${name}.${f.name.value}`, f.loc);
|
|
1408
1743
|
}
|
|
1409
1744
|
if (!isTypeNodeEqual(prev.type, f.type)) {
|
|
1410
|
-
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate field with different type: ${name}.${f.name.value}`), name
|
|
1745
|
+
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate field with different type: ${name}.${f.name.value}`), `${name}.${f.name.value}`, f.type.loc);
|
|
1411
1746
|
}
|
|
1412
|
-
console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}`
|
|
1413
|
-
traceLine(f.loc) +
|
|
1414
|
-
traceLine(prev.loc, "previously ") + "\n");
|
|
1747
|
+
console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}${traceLine(f.loc)}${traceLine(prev.loc, "previously ")}\n`);
|
|
1415
1748
|
fields[f.name.value] = {
|
|
1416
1749
|
...prev,
|
|
1417
|
-
directives: mergeDirectiveNodes(name
|
|
1750
|
+
directives: mergeDirectiveNodes(`${name}.${f.name.value}`, prev.directives, f.directives),
|
|
1418
1751
|
};
|
|
1419
1752
|
}
|
|
1420
1753
|
else {
|
|
@@ -1439,7 +1772,7 @@ function mergeDirectiveNodes(name, a, b) {
|
|
|
1439
1772
|
for (const d of b) {
|
|
1440
1773
|
if (d.name.value in directives &&
|
|
1441
1774
|
!isArgumentNodesEqual(directives[d.name.value].arguments, d.arguments)) {
|
|
1442
|
-
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate directive with different arguments: ${name} @${d.name.value}`), name
|
|
1775
|
+
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate directive with different arguments: ${name} @${d.name.value}`), `${name} @${d.name.value}`, d.loc);
|
|
1443
1776
|
}
|
|
1444
1777
|
directives[d.name.value] = d;
|
|
1445
1778
|
}
|
|
@@ -1491,9 +1824,9 @@ function mergeUnionTypeDefinitionNodes(a, b) {
|
|
|
1491
1824
|
function mergeEnumTypeDefinitionNodes(a, b) {
|
|
1492
1825
|
const values = namedNodesDict(a.values);
|
|
1493
1826
|
if (b) {
|
|
1494
|
-
for (const v of
|
|
1827
|
+
for (const v of b.values || []) {
|
|
1495
1828
|
if (v.name.value in values) {
|
|
1496
|
-
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate enum value: ${v.name.value}.${v.name.value}`), v.name.value
|
|
1829
|
+
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate enum value: ${v.name.value}.${v.name.value}`), `${v.name.value}.${v.name.value}`, v.loc);
|
|
1497
1830
|
}
|
|
1498
1831
|
values[v.name.value] = v;
|
|
1499
1832
|
}
|
|
@@ -1532,7 +1865,7 @@ function mergeDocumentNodes(documentNodes) {
|
|
|
1532
1865
|
case Kind.UNION_TYPE_EXTENSION:
|
|
1533
1866
|
case Kind.ENUM_TYPE_EXTENSION:
|
|
1534
1867
|
case Kind.INPUT_OBJECT_TYPE_EXTENSION:
|
|
1535
|
-
throw new Error(
|
|
1868
|
+
throw new Error(`unexpected definition kind: ${definition.kind}`);
|
|
1536
1869
|
}
|
|
1537
1870
|
const prevDefinition = definitions[definition.name.value];
|
|
1538
1871
|
if (!prevDefinition) {
|
|
@@ -1545,11 +1878,10 @@ function mergeDocumentNodes(documentNodes) {
|
|
|
1545
1878
|
if (prevDefinition.kind === Kind.DIRECTIVE_DEFINITION) {
|
|
1546
1879
|
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate directive definitions: ${definition.name.value}`), definition.name.value, definition.loc);
|
|
1547
1880
|
}
|
|
1548
|
-
if (prevDefinition.description &&
|
|
1881
|
+
if (prevDefinition.description &&
|
|
1882
|
+
definition.description &&
|
|
1549
1883
|
prevDefinition.description.value !== definition.description.value) {
|
|
1550
|
-
console.warn(`WARNING: different descriptions for type ${prevDefinition.name.value}: ${JSON.stringify(prevDefinition.description.value)} and ${JSON.stringify(definition.description.value)}`
|
|
1551
|
-
traceLine(definition.description.loc) +
|
|
1552
|
-
traceLine(prevDefinition.description.loc, "previously ") + "\n");
|
|
1884
|
+
console.warn(`WARNING: different descriptions for type ${prevDefinition.name.value}: ${JSON.stringify(prevDefinition.description.value)} and ${JSON.stringify(definition.description.value)}${traceLine(definition.description.loc)}${traceLine(prevDefinition.description.loc, "previously ")}\n`);
|
|
1553
1885
|
}
|
|
1554
1886
|
switch (definition.kind) {
|
|
1555
1887
|
case Kind.SCALAR_TYPE_DEFINITION:
|
|
@@ -1559,7 +1891,8 @@ function mergeDocumentNodes(documentNodes) {
|
|
|
1559
1891
|
definitions[definition.name.value] = mergeObjectTypeDefinitionNodes(prevDefinition, definition);
|
|
1560
1892
|
break;
|
|
1561
1893
|
case Kind.INTERFACE_TYPE_DEFINITION:
|
|
1562
|
-
definitions[definition.name.value] =
|
|
1894
|
+
definitions[definition.name.value] =
|
|
1895
|
+
mergeInterfaceTypeDefinitionNodes(prevDefinition, definition);
|
|
1563
1896
|
break;
|
|
1564
1897
|
case Kind.UNION_TYPE_DEFINITION:
|
|
1565
1898
|
definitions[definition.name.value] = mergeUnionTypeDefinitionNodes(prevDefinition, definition);
|
|
@@ -1568,7 +1901,8 @@ function mergeDocumentNodes(documentNodes) {
|
|
|
1568
1901
|
definitions[definition.name.value] = mergeEnumTypeDefinitionNodes(prevDefinition, definition);
|
|
1569
1902
|
break;
|
|
1570
1903
|
case Kind.INPUT_OBJECT_TYPE_DEFINITION:
|
|
1571
|
-
definitions[definition.name.value] =
|
|
1904
|
+
definitions[definition.name.value] =
|
|
1905
|
+
mergeInputObjectTypeDefinitionNodes(prevDefinition, definition);
|
|
1572
1906
|
break;
|
|
1573
1907
|
}
|
|
1574
1908
|
}
|