graphql-jerky 1.0.4 → 1.0.6
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 +532 -221
- package/build/lib.d.ts +1 -0
- package/build/lib.mjs +532 -221
- package/package.json +3 -2
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,48 +783,84 @@ 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
|
}
|
|
678
866
|
_getRenderDefintionFnForType(type) {
|
|
@@ -694,7 +882,7 @@ class GeneratorContext {
|
|
|
694
882
|
if (type instanceof graphql.GraphQLEnumType) {
|
|
695
883
|
return this._renderGraphQLEnumTypeDefinition.bind(this, type);
|
|
696
884
|
}
|
|
697
|
-
throw new Error(
|
|
885
|
+
throw new Error(`unhandled type: ${type.toString()}`);
|
|
698
886
|
}
|
|
699
887
|
_getRenderTypesFnForType(type) {
|
|
700
888
|
if (type instanceof graphql.GraphQLObjectType) {
|
|
@@ -715,10 +903,13 @@ class GeneratorContext {
|
|
|
715
903
|
if (type instanceof graphql.GraphQLEnumType) {
|
|
716
904
|
return this._renderGraphQLEnumTypeTypes.bind(this, type);
|
|
717
905
|
}
|
|
718
|
-
throw new Error(
|
|
906
|
+
throw new Error(`unhandled type: ${type.toString()}`);
|
|
719
907
|
}
|
|
720
908
|
_renderGraphQLTypeDefinitions(type, interfaces, inputFieldDirectives, includeAstNodes) {
|
|
721
|
-
return jen.const
|
|
909
|
+
return jen.const
|
|
910
|
+
.add(this._renderGraphQLTypeIdentifier(type))
|
|
911
|
+
.op("=")
|
|
912
|
+
.add(this._getRenderDefintionFnForType(type)({
|
|
722
913
|
implementors: interfaces[type.name],
|
|
723
914
|
inputFieldDirectives,
|
|
724
915
|
includeAstNodes,
|
|
@@ -731,54 +922,101 @@ class GeneratorContext {
|
|
|
731
922
|
});
|
|
732
923
|
}
|
|
733
924
|
_renderGraphQLDirectiveDefinition(directive, includeAstNodes) {
|
|
734
|
-
return jen.const
|
|
735
|
-
.
|
|
736
|
-
|
|
925
|
+
return jen.const
|
|
926
|
+
.add(this._renderGraphQLTypeIdentifier(directive))
|
|
927
|
+
.op("=")
|
|
928
|
+
.new.add(this._gql("GraphQLDirective"))
|
|
929
|
+
.call(jen.obj(jen.prop("name", jen.lit(directive.name)), jen.prop("locations", jen.array(...Array.from(directive.locations)
|
|
930
|
+
.sort()
|
|
931
|
+
.map((location) => jen.add(this._gql("DirectiveLocation")).dot(location)))), jen.prop("args", this._renderArgumentsObject(directive.args)), ...truthify([
|
|
932
|
+
directive.description &&
|
|
933
|
+
jen.prop("description", jen.lit(directive.description)),
|
|
737
934
|
directive.isRepeatable && jen.prop("isRepeatable", jen.true),
|
|
738
|
-
includeAstNodes &&
|
|
935
|
+
includeAstNodes &&
|
|
936
|
+
directive.astNode &&
|
|
937
|
+
jen.prop("astNode", renderAstNode(directive.astNode)),
|
|
739
938
|
])));
|
|
740
939
|
}
|
|
741
940
|
_renderGraphQLDirectiveTypes(directive) {
|
|
742
941
|
return truthify([
|
|
743
|
-
directive.args.length &&
|
|
744
|
-
|
|
745
|
-
|
|
942
|
+
directive.args.length &&
|
|
943
|
+
jen.export.interface
|
|
944
|
+
.id(pascalCase(`${directive.name}_directive_args`))
|
|
945
|
+
.block(...directive.args.map((arg) => jen.prop(jen
|
|
946
|
+
.id(arg.name)
|
|
947
|
+
.add(...truthify([
|
|
948
|
+
!(arg.type instanceof graphql.GraphQLNonNull) && jen.op("?"),
|
|
949
|
+
])), this._renderGraphQLTypeType(arg.type)))),
|
|
746
950
|
]);
|
|
747
951
|
}
|
|
748
952
|
schemaExprs(schema, [types, interfaces, inputFieldDirectives, includeAstNodes]) {
|
|
953
|
+
const queryType = schema.getQueryType();
|
|
954
|
+
const mutationType = schema.getMutationType();
|
|
955
|
+
const subscriptionType = schema.getSubscriptionType();
|
|
749
956
|
return [
|
|
750
957
|
...[
|
|
751
958
|
// render type definitions
|
|
752
959
|
...types
|
|
753
|
-
.map((type) => [
|
|
960
|
+
.map((type) => [
|
|
961
|
+
type.name,
|
|
962
|
+
this._renderGraphQLTypeDefinitions(type, interfaces, inputFieldDirectives, includeAstNodes),
|
|
963
|
+
])
|
|
754
964
|
.sort(compareEntryKey),
|
|
755
965
|
// render directive definitions
|
|
756
|
-
...schema
|
|
966
|
+
...schema
|
|
967
|
+
.getDirectives()
|
|
757
968
|
.filter((d) => !isBuiltInDirective(d.name))
|
|
758
|
-
.map((directive) => [
|
|
969
|
+
.map((directive) => [
|
|
970
|
+
directive.name,
|
|
971
|
+
this._renderGraphQLDirectiveDefinition(directive),
|
|
972
|
+
])
|
|
759
973
|
.sort(compareEntryKey),
|
|
760
974
|
].map(([, expr]) => expr),
|
|
761
|
-
...Array.from(PRIMITIVE_TYPES)
|
|
762
|
-
.flatMap((type) => {
|
|
975
|
+
...Array.from(PRIMITIVE_TYPES).flatMap((type) => {
|
|
763
976
|
const info = this._scalarsInfo[type];
|
|
764
977
|
if (!info) {
|
|
765
978
|
return [];
|
|
766
979
|
}
|
|
767
980
|
return [
|
|
768
981
|
jen.statements(...[
|
|
769
|
-
info.serializeFunc &&
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
982
|
+
info.serializeFunc &&
|
|
983
|
+
this._gql(`GraphQL${type}`)
|
|
984
|
+
.dot("serialize")
|
|
985
|
+
.op("=")
|
|
986
|
+
.parens(renderSymbolReference(this._pkgs, info.serializeFunc).as
|
|
987
|
+
.any),
|
|
988
|
+
info.parseValueFunc &&
|
|
989
|
+
this._gql(`GraphQL${type}`)
|
|
990
|
+
.dot("parseValue")
|
|
991
|
+
.op("=")
|
|
992
|
+
.parens(renderSymbolReference(this._pkgs, info.parseValueFunc).as
|
|
993
|
+
.any),
|
|
994
|
+
info.parseLiteralFunc &&
|
|
995
|
+
this._gql(`GraphQL${type}`)
|
|
996
|
+
.dot("parseLiteral")
|
|
997
|
+
.op("=")
|
|
998
|
+
.parens(renderSymbolReference(this._pkgs, info.parseLiteralFunc).as
|
|
999
|
+
.any),
|
|
1000
|
+
].filter(Boolean)),
|
|
773
1001
|
];
|
|
774
1002
|
}),
|
|
775
1003
|
// render schema
|
|
776
|
-
jen.const
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
? [
|
|
1004
|
+
jen.const
|
|
1005
|
+
.id("schema")
|
|
1006
|
+
.op("=")
|
|
1007
|
+
.new.add(this._gql("GraphQLSchema"))
|
|
1008
|
+
.call(jen.obj(...(queryType
|
|
1009
|
+
? [
|
|
1010
|
+
jen.prop("query", this._renderGraphQLTypeIdentifier(queryType)),
|
|
1011
|
+
]
|
|
1012
|
+
: []), ...(mutationType
|
|
1013
|
+
? [
|
|
1014
|
+
jen.prop("mutation", this._renderGraphQLTypeIdentifier(mutationType)),
|
|
1015
|
+
]
|
|
1016
|
+
: []), ...(subscriptionType
|
|
1017
|
+
? [
|
|
1018
|
+
jen.prop("subscription", this._renderGraphQLTypeIdentifier(subscriptionType)),
|
|
1019
|
+
]
|
|
782
1020
|
: []), jen.prop("types", jen.array(...types.map((type) => this._renderGraphQLTypeIdentifier(type)))), jen.prop("directives", jen.array(...Array.from(schema.getDirectives())
|
|
783
1021
|
.filter((d) => !isBuiltInDirective(d.name))
|
|
784
1022
|
.map((d) => this._renderGraphQLTypeIdentifier(d)))))),
|
|
@@ -787,15 +1025,44 @@ class GeneratorContext {
|
|
|
787
1025
|
}
|
|
788
1026
|
typesExprs(schema, [types, interfaces, inputFieldDirectives]) {
|
|
789
1027
|
return [
|
|
790
|
-
[
|
|
1028
|
+
[
|
|
1029
|
+
"",
|
|
1030
|
+
jen.const
|
|
1031
|
+
.id("setTypename")
|
|
1032
|
+
.op("=")
|
|
1033
|
+
.types(jen.id("T"))
|
|
1034
|
+
.params(jen.id("v").op(":").id("T"), jen.id("t").op(":").string)
|
|
1035
|
+
.op(":")
|
|
1036
|
+
.id("T")
|
|
1037
|
+
.op("=>")
|
|
1038
|
+
.block(jen
|
|
1039
|
+
.if(jen
|
|
1040
|
+
.op("!")
|
|
1041
|
+
.id("v")
|
|
1042
|
+
.op("||")
|
|
1043
|
+
.typeof(jen.id("v"))
|
|
1044
|
+
.op("!==")
|
|
1045
|
+
.lit("object"))
|
|
1046
|
+
.block(jen.throw.new.id("Error").call(jen.lit("expected object"))), jen.return(jen
|
|
1047
|
+
.id("Object")
|
|
1048
|
+
.dot("assign")
|
|
1049
|
+
.call(jen.id("v"), jen.obj(jen.prop(jen.id("__typename"), jen.id("t")))))),
|
|
1050
|
+
],
|
|
791
1051
|
// render type definitions
|
|
792
1052
|
...types
|
|
793
|
-
.map((type) => [
|
|
1053
|
+
.map((type) => [
|
|
1054
|
+
type.name,
|
|
1055
|
+
jen.statements(...this._renderGraphQLTypeTypes(type, interfaces, inputFieldDirectives)),
|
|
1056
|
+
])
|
|
794
1057
|
.sort(compareEntryKey),
|
|
795
1058
|
// render directive definitions
|
|
796
|
-
...schema
|
|
1059
|
+
...schema
|
|
1060
|
+
.getDirectives()
|
|
797
1061
|
.filter((d) => !isBuiltInDirective(d.name))
|
|
798
|
-
.map((directive) => [
|
|
1062
|
+
.map((directive) => [
|
|
1063
|
+
directive.name,
|
|
1064
|
+
jen.statements(...this._renderGraphQLDirectiveTypes(directive)),
|
|
1065
|
+
])
|
|
799
1066
|
.sort(compareEntryKey),
|
|
800
1067
|
].map(([, expr]) => expr);
|
|
801
1068
|
}
|
|
@@ -809,7 +1076,9 @@ class GeneratorContext {
|
|
|
809
1076
|
const base = outfile.startsWith("/") ? outfile : path.resolve(outfile);
|
|
810
1077
|
const statements = renderStatements.call(this);
|
|
811
1078
|
const [localImports, externalImports] = partition(Object.entries(this._pkgs.requires), ([pkg]) => pkg.startsWith("/"));
|
|
812
|
-
return format(jen
|
|
1079
|
+
return format(jen
|
|
1080
|
+
.statements(renderImports(path.dirname(base), externalImports, this._pkgs.aliases, this._extMode), renderImports(path.dirname(base), localImports, this._pkgs.aliases, this._extMode), ...statements)
|
|
1081
|
+
.toString());
|
|
813
1082
|
}
|
|
814
1083
|
static prepareInterfacesAndInputFieldDirectives(schema, options = {}) {
|
|
815
1084
|
if (options.fieldDirectivesInfo) {
|
|
@@ -837,7 +1106,11 @@ class GeneratorContext {
|
|
|
837
1106
|
}
|
|
838
1107
|
for (const field of Object.values(type.getFields())) {
|
|
839
1108
|
if (graphql.getNamedType(field.type) instanceof graphql.GraphQLInputObjectType) {
|
|
840
|
-
typesWithObjectFields.push([
|
|
1109
|
+
typesWithObjectFields.push([
|
|
1110
|
+
type.name,
|
|
1111
|
+
field.name,
|
|
1112
|
+
graphql.getNamedType(field.type).name,
|
|
1113
|
+
]);
|
|
841
1114
|
}
|
|
842
1115
|
const directives = field.astNode?.directives;
|
|
843
1116
|
if (!directives) {
|
|
@@ -848,22 +1121,34 @@ class GeneratorContext {
|
|
|
848
1121
|
if (!options.inputDirectivesInfo[name]) {
|
|
849
1122
|
continue;
|
|
850
1123
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
1124
|
+
if (!inputFieldDirectives[type.name]) {
|
|
1125
|
+
inputFieldDirectives[type.name] = {};
|
|
1126
|
+
}
|
|
1127
|
+
const fieldDirectives = inputFieldDirectives[type.name];
|
|
1128
|
+
if (!fieldDirectives[field.name]) {
|
|
1129
|
+
fieldDirectives[field.name] = [];
|
|
1130
|
+
}
|
|
1131
|
+
fieldDirectives[field.name].push(name);
|
|
854
1132
|
}
|
|
855
1133
|
}
|
|
856
1134
|
}
|
|
857
1135
|
for (let changes = 1; changes; changes = 0) {
|
|
858
1136
|
const newTypesWithObjectFields = new Array();
|
|
859
|
-
for (const [typeName, fieldName, objectTypeName] of typesWithObjectFields) {
|
|
1137
|
+
for (const [typeName, fieldName, objectTypeName,] of typesWithObjectFields) {
|
|
860
1138
|
console.log(`checking ${typeName}.${fieldName} for ${objectTypeName}`);
|
|
861
1139
|
if (inputFieldDirectives[objectTypeName]) {
|
|
862
|
-
inputFieldDirectives[typeName] = {
|
|
1140
|
+
inputFieldDirectives[typeName] = {
|
|
1141
|
+
...inputFieldDirectives[typeName],
|
|
1142
|
+
[fieldName]: [],
|
|
1143
|
+
};
|
|
863
1144
|
changes += 1;
|
|
864
1145
|
}
|
|
865
1146
|
else {
|
|
866
|
-
newTypesWithObjectFields.push([
|
|
1147
|
+
newTypesWithObjectFields.push([
|
|
1148
|
+
typeName,
|
|
1149
|
+
fieldName,
|
|
1150
|
+
objectTypeName,
|
|
1151
|
+
]);
|
|
867
1152
|
}
|
|
868
1153
|
}
|
|
869
1154
|
typesWithObjectFields = newTypesWithObjectFields;
|
|
@@ -884,7 +1169,12 @@ class GeneratorContext {
|
|
|
884
1169
|
interfaces[iface.name].implementors.push(type);
|
|
885
1170
|
}
|
|
886
1171
|
}
|
|
887
|
-
return [
|
|
1172
|
+
return [
|
|
1173
|
+
types,
|
|
1174
|
+
interfaces,
|
|
1175
|
+
inputFieldDirectives,
|
|
1176
|
+
options.includeAstNodes,
|
|
1177
|
+
];
|
|
888
1178
|
}
|
|
889
1179
|
}
|
|
890
1180
|
function createGenerator(schema, options) {
|
|
@@ -924,8 +1214,8 @@ function createMatcher(pattern) {
|
|
|
924
1214
|
if (typeof pattern === "string") {
|
|
925
1215
|
return pm(pattern);
|
|
926
1216
|
}
|
|
927
|
-
|
|
928
|
-
|
|
1217
|
+
const matchers = [];
|
|
1218
|
+
const globs = [];
|
|
929
1219
|
for (const p of Array.isArray(pattern) ? pattern : [pattern]) {
|
|
930
1220
|
if (typeof p === "string") {
|
|
931
1221
|
globs.push(p);
|
|
@@ -947,9 +1237,9 @@ function createMatcher(pattern) {
|
|
|
947
1237
|
}
|
|
948
1238
|
|
|
949
1239
|
async function parseResolverFile(path) {
|
|
950
|
-
return Object.fromEntries(Object.entries((await parseModule(path)).exports)
|
|
951
|
-
|
|
952
|
-
|
|
1240
|
+
return Object.fromEntries(Object.entries((await parseModule(path)).exports).flatMap(([name, decls]) => decls.flatMap(({ declaration }) => {
|
|
1241
|
+
if (ts.isVariableDeclaration(declaration) &&
|
|
1242
|
+
declaration.initializer) {
|
|
953
1243
|
if (ts.isFunctionExpression(declaration.initializer)) {
|
|
954
1244
|
return [[name, { module: path, symbol: name }]];
|
|
955
1245
|
}
|
|
@@ -968,14 +1258,18 @@ async function parseTypeResolvers(typeName, glob$1, ignore) {
|
|
|
968
1258
|
const result = {};
|
|
969
1259
|
for await (const entry of glob.globIterate(glob$1, { withFileTypes: true })) {
|
|
970
1260
|
const fullpath = entry.fullpath();
|
|
971
|
-
if (!shouldIgnore(fullpath) &&
|
|
1261
|
+
if (!shouldIgnore(fullpath) &&
|
|
1262
|
+
entry.isFile() &&
|
|
1263
|
+
entry.name.endsWith(".ts")) {
|
|
972
1264
|
for (const [name, reference] of Object.entries(await parseResolverFile(fullpath))) {
|
|
973
1265
|
let realName = name;
|
|
974
|
-
if (realName === "default"
|
|
1266
|
+
if (realName === "default" &&
|
|
1267
|
+
typeof glob$1 === "string" &&
|
|
1268
|
+
glob$1.endsWith("/*.ts")) {
|
|
975
1269
|
realName = path.basename(fullpath, path.extname(fullpath));
|
|
976
1270
|
}
|
|
977
1271
|
if (realName in result) {
|
|
978
|
-
console.warn(`WARNING: Duplicate resolver name: ${typeName ? typeName
|
|
1272
|
+
console.warn(`WARNING: Duplicate resolver name: ${typeName ? `${typeName}.` : ""}${name} in ${fullpath} and ${result[name].module}`);
|
|
979
1273
|
}
|
|
980
1274
|
result[realName] = reference;
|
|
981
1275
|
}
|
|
@@ -988,16 +1282,13 @@ async function parse$2(dirpath, ignore) {
|
|
|
988
1282
|
if (!dir.isDirectory()) {
|
|
989
1283
|
throw new Error(`Expected ${dirpath} to be a directory`);
|
|
990
1284
|
}
|
|
991
|
-
if (!dirpath.endsWith("/")) {
|
|
992
|
-
dirpath += "/";
|
|
993
|
-
}
|
|
994
1285
|
const out = {};
|
|
995
1286
|
const shouldIgnore = createMatcher(ignore);
|
|
996
1287
|
for await (const name of await fs.readdir(dirpath)) {
|
|
997
1288
|
const file = path.join(dirpath, name);
|
|
998
1289
|
const entry = await fs.stat(file);
|
|
999
1290
|
if (entry.isDirectory()) {
|
|
1000
|
-
out[name] = await parseTypeResolvers(name, file
|
|
1291
|
+
out[name] = await parseTypeResolvers(name, `${file}/*.ts`, shouldIgnore);
|
|
1001
1292
|
}
|
|
1002
1293
|
else if (entry.isFile() && name.endsWith(".ts")) {
|
|
1003
1294
|
out[name.slice(0, -3)] = await parseTypeResolvers(name.slice(0, -3), file, shouldIgnore);
|
|
@@ -1022,7 +1313,8 @@ function refFromImportTypeNode(node, source) {
|
|
|
1022
1313
|
console.log("WARNING: namespace import for scalar type is not supported");
|
|
1023
1314
|
return;
|
|
1024
1315
|
}
|
|
1025
|
-
if (!ts.isLiteralTypeNode(node.argument) ||
|
|
1316
|
+
if (!ts.isLiteralTypeNode(node.argument) ||
|
|
1317
|
+
!ts.isStringLiteral(node.argument.literal)) {
|
|
1026
1318
|
// this is a grammar error, handling it is out of scope
|
|
1027
1319
|
const { line, character } = ts.getLineAndCharacterOfPosition(source, node.pos);
|
|
1028
1320
|
console.log(`WARNING: grammar error at ${source.fileName}:${line + 1}:${character + 1}`);
|
|
@@ -1037,8 +1329,8 @@ function refFromTypeReferenceNode(typeNode, source) {
|
|
|
1037
1329
|
}
|
|
1038
1330
|
const typeName = typeNode.typeName.text;
|
|
1039
1331
|
if (typeNode.typeArguments?.length) {
|
|
1040
|
-
if (typeName !==
|
|
1041
|
-
throw new Error(
|
|
1332
|
+
if (typeName !== "Promise") {
|
|
1333
|
+
throw new Error("TODO: handle type arguments");
|
|
1042
1334
|
}
|
|
1043
1335
|
return refFromTypeNode(typeNode.typeArguments[0], source);
|
|
1044
1336
|
}
|
|
@@ -1056,7 +1348,11 @@ function refFromTypeReferenceNode(typeNode, source) {
|
|
|
1056
1348
|
if (statement.importClause.name) {
|
|
1057
1349
|
// default import
|
|
1058
1350
|
if (statement.importClause.name.text === typeName) {
|
|
1059
|
-
return {
|
|
1351
|
+
return {
|
|
1352
|
+
module: statement.importClause.name.text,
|
|
1353
|
+
symbol: "default",
|
|
1354
|
+
alias: typeName,
|
|
1355
|
+
};
|
|
1060
1356
|
}
|
|
1061
1357
|
}
|
|
1062
1358
|
if (!statement.importClause.namedBindings) {
|
|
@@ -1067,17 +1363,24 @@ function refFromTypeReferenceNode(typeNode, source) {
|
|
|
1067
1363
|
// TODO: handle namespace imports (will need to check if `typeName` has a dot in it)
|
|
1068
1364
|
continue;
|
|
1069
1365
|
}
|
|
1070
|
-
for (const specifier of statement.importClause.namedBindings.elements ??
|
|
1366
|
+
for (const specifier of statement.importClause.namedBindings.elements ??
|
|
1367
|
+
[]) {
|
|
1071
1368
|
if (specifier.name.text === typeName) {
|
|
1072
|
-
return {
|
|
1369
|
+
return {
|
|
1370
|
+
module: statement.moduleSpecifier.text,
|
|
1371
|
+
symbol: specifier.propertyName?.text ?? typeName,
|
|
1372
|
+
alias: typeName,
|
|
1373
|
+
};
|
|
1073
1374
|
}
|
|
1074
1375
|
}
|
|
1075
1376
|
}
|
|
1076
|
-
else if (ts.isTypeAliasDeclaration(statement) ||
|
|
1377
|
+
else if (ts.isTypeAliasDeclaration(statement) ||
|
|
1378
|
+
ts.isInterfaceDeclaration(statement) ||
|
|
1379
|
+
ts.isEnumDeclaration(statement)) {
|
|
1077
1380
|
if (statement.name.text === typeName) {
|
|
1078
1381
|
if (!statement.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)) {
|
|
1079
1382
|
console.log(statement);
|
|
1080
|
-
console.log(`WARNING: found type ${typeName} in ${source.fileName}:${locLineColumn$1(statement, source).join(
|
|
1383
|
+
console.log(`WARNING: found type ${typeName} in ${source.fileName}:${locLineColumn$1(statement, source).join(":")} but it is not exported`);
|
|
1081
1384
|
continue;
|
|
1082
1385
|
}
|
|
1083
1386
|
return { module: source.fileName, symbol: typeName };
|
|
@@ -1091,16 +1394,14 @@ function refFromTypeNode(typeNode, source) {
|
|
|
1091
1394
|
if (ts.isImportTypeNode(typeNode)) {
|
|
1092
1395
|
return refFromImportTypeNode(typeNode, source);
|
|
1093
1396
|
}
|
|
1094
|
-
|
|
1397
|
+
if (ts.isTokenKind(typeNode.kind)) {
|
|
1095
1398
|
// primitive type string, number, etc...
|
|
1096
1399
|
return { symbol: typeNode.getText(source) };
|
|
1097
1400
|
}
|
|
1098
|
-
|
|
1401
|
+
if (ts.isTypeReferenceNode(typeNode)) {
|
|
1099
1402
|
return refFromTypeReferenceNode(typeNode, source);
|
|
1100
1403
|
}
|
|
1101
|
-
|
|
1102
|
-
console.warn("WARNING: unexpected type node: " + ts.SyntaxKind[typeNode.kind]);
|
|
1103
|
-
}
|
|
1404
|
+
console.warn(`WARNING: unexpected type node: ${ts.SyntaxKind[typeNode.kind]}`);
|
|
1104
1405
|
}
|
|
1105
1406
|
function reconcileScalarType(scalarName, typeDecls, source) {
|
|
1106
1407
|
let type;
|
|
@@ -1108,7 +1409,7 @@ function reconcileScalarType(scalarName, typeDecls, source) {
|
|
|
1108
1409
|
if (!typeNode) {
|
|
1109
1410
|
continue;
|
|
1110
1411
|
}
|
|
1111
|
-
|
|
1412
|
+
const newType = refFromTypeNode(typeNode, source);
|
|
1112
1413
|
if (type && newType) {
|
|
1113
1414
|
if (type.symbol !== newType.symbol ||
|
|
1114
1415
|
type.alias !== newType.alias ||
|
|
@@ -1133,11 +1434,13 @@ function scalarInfoFromObjectLiteralExpression(scalarName, module, properties) {
|
|
|
1133
1434
|
case "serialize":
|
|
1134
1435
|
case "parseValue":
|
|
1135
1436
|
case "parseLiteral":
|
|
1136
|
-
if (!ts.isFunctionExpression(prop.initializer) &&
|
|
1437
|
+
if (!ts.isFunctionExpression(prop.initializer) &&
|
|
1438
|
+
!ts.isArrowFunction(prop.initializer)) {
|
|
1137
1439
|
console.log(`WARNING: expected scalar property ${scalarName}.${prop.name.text} to be a function, but got ${ts.SyntaxKind[prop.initializer.kind]}`);
|
|
1138
1440
|
return [];
|
|
1139
1441
|
}
|
|
1140
|
-
return [
|
|
1442
|
+
return [
|
|
1443
|
+
[
|
|
1141
1444
|
`${prop.name.text}Func`,
|
|
1142
1445
|
{
|
|
1143
1446
|
module: module,
|
|
@@ -1145,7 +1448,8 @@ function scalarInfoFromObjectLiteralExpression(scalarName, module, properties) {
|
|
|
1145
1448
|
property: prop.name.text,
|
|
1146
1449
|
declaration: prop.initializer,
|
|
1147
1450
|
},
|
|
1148
|
-
]
|
|
1451
|
+
],
|
|
1452
|
+
];
|
|
1149
1453
|
default:
|
|
1150
1454
|
console.log(`WARNING: found extraneous scalar property ${scalarName}.${prop.name.text}`);
|
|
1151
1455
|
}
|
|
@@ -1158,7 +1462,8 @@ function scalarInfoFromObjectLiteralExpression(scalarName, module, properties) {
|
|
|
1158
1462
|
case "serialize":
|
|
1159
1463
|
case "parseValue":
|
|
1160
1464
|
case "parseLiteral":
|
|
1161
|
-
return [
|
|
1465
|
+
return [
|
|
1466
|
+
[
|
|
1162
1467
|
`${prop.name.text}Func`,
|
|
1163
1468
|
{
|
|
1164
1469
|
module,
|
|
@@ -1166,7 +1471,8 @@ function scalarInfoFromObjectLiteralExpression(scalarName, module, properties) {
|
|
|
1166
1471
|
property: prop.name.text,
|
|
1167
1472
|
declaration: prop,
|
|
1168
1473
|
},
|
|
1169
|
-
]
|
|
1474
|
+
],
|
|
1475
|
+
];
|
|
1170
1476
|
default:
|
|
1171
1477
|
console.log(`WARNING: found extraneous scalar property ${scalarName}.${prop.name.text}`);
|
|
1172
1478
|
}
|
|
@@ -1185,7 +1491,8 @@ async function parse$1(path) {
|
|
|
1185
1491
|
for (const { declaration, source } of decls) {
|
|
1186
1492
|
sources[name] = source;
|
|
1187
1493
|
if (ts.isVariableDeclaration(declaration)) {
|
|
1188
|
-
if (declaration.initializer &&
|
|
1494
|
+
if (declaration.initializer &&
|
|
1495
|
+
ts.isObjectLiteralExpression(declaration.initializer)) {
|
|
1189
1496
|
scalarFnsInfos[name] = scalarInfoFromObjectLiteralExpression(name, new URL(source.fileName).toString(), declaration.initializer.properties);
|
|
1190
1497
|
}
|
|
1191
1498
|
}
|
|
@@ -1202,18 +1509,23 @@ async function parse$1(path) {
|
|
|
1202
1509
|
}
|
|
1203
1510
|
}
|
|
1204
1511
|
const infos = {};
|
|
1205
|
-
for (const name of new Set([
|
|
1512
|
+
for (const name of new Set([
|
|
1513
|
+
...Object.keys(scalarFnsInfos),
|
|
1514
|
+
...Object.keys(scalarTypeNodes),
|
|
1515
|
+
])) {
|
|
1206
1516
|
const fnsInfo = scalarFnsInfos[name];
|
|
1207
1517
|
const typeNode = scalarTypeNodes[name];
|
|
1208
1518
|
const source = sources[name];
|
|
1209
|
-
const type = typeNode
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1519
|
+
const type = typeNode
|
|
1520
|
+
? {
|
|
1521
|
+
module: source.fileName,
|
|
1522
|
+
symbol: name,
|
|
1523
|
+
}
|
|
1524
|
+
: reconcileScalarType(name, [
|
|
1525
|
+
// NOTE: omit serialize input type because it is supposed to be `unknown`
|
|
1526
|
+
fnsInfo?.parseValueFunc?.declaration?.type,
|
|
1527
|
+
fnsInfo?.parseLiteralFunc?.declaration?.type,
|
|
1528
|
+
], source);
|
|
1217
1529
|
if (type) {
|
|
1218
1530
|
if (type.module) {
|
|
1219
1531
|
type.module = new URL(type.module, source.fileName).toString();
|
|
@@ -1241,8 +1553,10 @@ function traceLine(loc, prefix = "") {
|
|
|
1241
1553
|
return `\n ${prefix}at file://${loc.source.name}:${locLineColumn(loc).join(":")}`;
|
|
1242
1554
|
}
|
|
1243
1555
|
function setTraceToSchema(err, name, loc) {
|
|
1556
|
+
// biome-ignore lint/suspicious/noExplicitAny: hacks
|
|
1244
1557
|
if (globalThis.Deno) {
|
|
1245
1558
|
if (loc) {
|
|
1559
|
+
// biome-ignore lint/suspicious/noExplicitAny: hacks
|
|
1246
1560
|
const trace = err.__callSiteEvals;
|
|
1247
1561
|
const [lineNumber, columnNumber] = locLineColumn(loc);
|
|
1248
1562
|
// NOTE: this is deno magic
|
|
@@ -1255,7 +1569,7 @@ function setTraceToSchema(err, name, loc) {
|
|
|
1255
1569
|
function: undefined,
|
|
1256
1570
|
functionName: name,
|
|
1257
1571
|
methodName: null,
|
|
1258
|
-
fileName:
|
|
1572
|
+
fileName: `file://${loc.source.name}`,
|
|
1259
1573
|
lineNumber,
|
|
1260
1574
|
columnNumber,
|
|
1261
1575
|
evalOrigin: undefined,
|
|
@@ -1299,8 +1613,7 @@ function isListValueNodeEqual(a, b) {
|
|
|
1299
1613
|
return zip(a.values, b.values).every(([a, b]) => isValueNodeEqual(a, b));
|
|
1300
1614
|
}
|
|
1301
1615
|
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));
|
|
1616
|
+
return zip(sortNamedNodes(a.fields), sortNamedNodes(b.fields)).every(([a, b]) => a.name.value === b.name.value && isValueNodeEqual(a.value, b.value));
|
|
1304
1617
|
}
|
|
1305
1618
|
function isValueNodeEqual(a, b) {
|
|
1306
1619
|
if (a === b || (!a && !b)) {
|
|
@@ -1368,7 +1681,8 @@ function isInputValueDefinitionNodesEqual(a, b) {
|
|
|
1368
1681
|
if (!a || !b || a.length !== b.length) {
|
|
1369
1682
|
return false;
|
|
1370
1683
|
}
|
|
1371
|
-
return zip(sortNamedNodes(a), sortNamedNodes(b)).every(([a, b]) => a.name.value === b.name.value &&
|
|
1684
|
+
return zip(sortNamedNodes(a), sortNamedNodes(b)).every(([a, b]) => a.name.value === b.name.value &&
|
|
1685
|
+
isTypeNodeEqual(a.type, b.type) &&
|
|
1372
1686
|
isValueNodeEqual(a.defaultValue, b.defaultValue) &&
|
|
1373
1687
|
isDirectiveNodesEqual(a.directives, b.directives));
|
|
1374
1688
|
}
|
|
@@ -1379,17 +1693,15 @@ function mergeFieldDefinitionNodes(name, a, b) {
|
|
|
1379
1693
|
const prev = fields[f.name.value];
|
|
1380
1694
|
if (prev) {
|
|
1381
1695
|
if (!isInputValueDefinitionNodesEqual(prev.arguments, f.arguments)) {
|
|
1382
|
-
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different arguments: ${name}.${f.name.value}`), name
|
|
1696
|
+
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different arguments: ${name}.${f.name.value}`), `${name}.${f.name.value}`, f.loc);
|
|
1383
1697
|
}
|
|
1384
1698
|
if (!isTypeNodeEqual(prev.type, f.type)) {
|
|
1385
|
-
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different type: ${name}.${f.name.value}`), name
|
|
1699
|
+
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different type: ${name}.${f.name.value}`), `${name}.${f.name.value}`, f.type.loc);
|
|
1386
1700
|
}
|
|
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");
|
|
1701
|
+
console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}${traceLine(f.loc)}${traceLine(prev.loc, "previously ")}\n`);
|
|
1390
1702
|
fields[f.name.value] = {
|
|
1391
1703
|
...prev,
|
|
1392
|
-
directives: mergeDirectiveNodes(name
|
|
1704
|
+
directives: mergeDirectiveNodes(`${name}.${f.name.value}`, prev.directives, f.directives),
|
|
1393
1705
|
};
|
|
1394
1706
|
}
|
|
1395
1707
|
else {
|
|
@@ -1406,17 +1718,15 @@ function mergeInputValueDefinitionNodes(name, a, b) {
|
|
|
1406
1718
|
const prev = fields[f.name.value];
|
|
1407
1719
|
if (prev) {
|
|
1408
1720
|
if (!isValueNodeEqual(prev.defaultValue, f.defaultValue)) {
|
|
1409
|
-
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different arguments: ${name}.${f.name.value}`), name
|
|
1721
|
+
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different arguments: ${name}.${f.name.value}`), `${name}.${f.name.value}`, f.loc);
|
|
1410
1722
|
}
|
|
1411
1723
|
if (!isTypeNodeEqual(prev.type, f.type)) {
|
|
1412
|
-
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different type: ${name}.${f.name.value}`), name
|
|
1724
|
+
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate field with different type: ${name}.${f.name.value}`), `${name}.${f.name.value}`, f.type.loc);
|
|
1413
1725
|
}
|
|
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");
|
|
1726
|
+
console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}${traceLine(f.loc)}${traceLine(prev.loc, "previously ")}\n`);
|
|
1417
1727
|
fields[f.name.value] = {
|
|
1418
1728
|
...prev,
|
|
1419
|
-
directives: mergeDirectiveNodes(name
|
|
1729
|
+
directives: mergeDirectiveNodes(`${name}.${f.name.value}`, prev.directives, f.directives),
|
|
1420
1730
|
};
|
|
1421
1731
|
}
|
|
1422
1732
|
else {
|
|
@@ -1441,7 +1751,7 @@ function mergeDirectiveNodes(name, a, b) {
|
|
|
1441
1751
|
for (const d of b) {
|
|
1442
1752
|
if (d.name.value in directives &&
|
|
1443
1753
|
!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
|
|
1754
|
+
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate directive with different arguments: ${name} @${d.name.value}`), `${name} @${d.name.value}`, d.loc);
|
|
1445
1755
|
}
|
|
1446
1756
|
directives[d.name.value] = d;
|
|
1447
1757
|
}
|
|
@@ -1493,9 +1803,9 @@ function mergeUnionTypeDefinitionNodes(a, b) {
|
|
|
1493
1803
|
function mergeEnumTypeDefinitionNodes(a, b) {
|
|
1494
1804
|
const values = namedNodesDict(a.values);
|
|
1495
1805
|
if (b) {
|
|
1496
|
-
for (const v of
|
|
1806
|
+
for (const v of b.values || []) {
|
|
1497
1807
|
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
|
|
1808
|
+
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
1809
|
}
|
|
1500
1810
|
values[v.name.value] = v;
|
|
1501
1811
|
}
|
|
@@ -1534,7 +1844,7 @@ function mergeDocumentNodes(documentNodes) {
|
|
|
1534
1844
|
case graphql.Kind.UNION_TYPE_EXTENSION:
|
|
1535
1845
|
case graphql.Kind.ENUM_TYPE_EXTENSION:
|
|
1536
1846
|
case graphql.Kind.INPUT_OBJECT_TYPE_EXTENSION:
|
|
1537
|
-
throw new Error(
|
|
1847
|
+
throw new Error(`unexpected definition kind: ${definition.kind}`);
|
|
1538
1848
|
}
|
|
1539
1849
|
const prevDefinition = definitions[definition.name.value];
|
|
1540
1850
|
if (!prevDefinition) {
|
|
@@ -1547,11 +1857,10 @@ function mergeDocumentNodes(documentNodes) {
|
|
|
1547
1857
|
if (prevDefinition.kind === graphql.Kind.DIRECTIVE_DEFINITION) {
|
|
1548
1858
|
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate directive definitions: ${definition.name.value}`), definition.name.value, definition.loc);
|
|
1549
1859
|
}
|
|
1550
|
-
if (prevDefinition.description &&
|
|
1860
|
+
if (prevDefinition.description &&
|
|
1861
|
+
definition.description &&
|
|
1551
1862
|
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");
|
|
1863
|
+
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
1864
|
}
|
|
1556
1865
|
switch (definition.kind) {
|
|
1557
1866
|
case graphql.Kind.SCALAR_TYPE_DEFINITION:
|
|
@@ -1561,7 +1870,8 @@ function mergeDocumentNodes(documentNodes) {
|
|
|
1561
1870
|
definitions[definition.name.value] = mergeObjectTypeDefinitionNodes(prevDefinition, definition);
|
|
1562
1871
|
break;
|
|
1563
1872
|
case graphql.Kind.INTERFACE_TYPE_DEFINITION:
|
|
1564
|
-
definitions[definition.name.value] =
|
|
1873
|
+
definitions[definition.name.value] =
|
|
1874
|
+
mergeInterfaceTypeDefinitionNodes(prevDefinition, definition);
|
|
1565
1875
|
break;
|
|
1566
1876
|
case graphql.Kind.UNION_TYPE_DEFINITION:
|
|
1567
1877
|
definitions[definition.name.value] = mergeUnionTypeDefinitionNodes(prevDefinition, definition);
|
|
@@ -1570,7 +1880,8 @@ function mergeDocumentNodes(documentNodes) {
|
|
|
1570
1880
|
definitions[definition.name.value] = mergeEnumTypeDefinitionNodes(prevDefinition, definition);
|
|
1571
1881
|
break;
|
|
1572
1882
|
case graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION:
|
|
1573
|
-
definitions[definition.name.value] =
|
|
1883
|
+
definitions[definition.name.value] =
|
|
1884
|
+
mergeInputObjectTypeDefinitionNodes(prevDefinition, definition);
|
|
1574
1885
|
break;
|
|
1575
1886
|
}
|
|
1576
1887
|
}
|