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