@graphql-codegen/c-sharp-operations 2.2.14 → 2.3.0-alpha-bd464a586.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/config.js +2 -0
- package/cjs/index.js +43 -0
- package/cjs/package.json +1 -0
- package/cjs/visitor.js +424 -0
- package/esm/config.js +1 -0
- package/esm/index.js +37 -0
- package/{index.mjs → esm/visitor.js} +5 -333
- package/package.json +23 -15
- package/{config.d.ts → typings/config.d.ts} +0 -0
- package/{index.d.ts → typings/index.d.ts} +2 -2
- package/{visitor.d.ts → typings/visitor.d.ts} +2 -2
- package/index.js +0 -756
package/index.js
DELETED
|
@@ -1,756 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
|
6
|
-
|
|
7
|
-
const pluginHelpers = require('@graphql-codegen/plugin-helpers');
|
|
8
|
-
const graphql = require('graphql');
|
|
9
|
-
const visitorPluginCommon = require('@graphql-codegen/visitor-plugin-common');
|
|
10
|
-
const autoBind = _interopDefault(require('auto-bind'));
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const gql = _interopDefault(require('graphql-tag'));
|
|
13
|
-
|
|
14
|
-
const C_SHARP_SCALARS = {
|
|
15
|
-
ID: 'string',
|
|
16
|
-
String: 'string',
|
|
17
|
-
Boolean: 'bool',
|
|
18
|
-
Int: 'int',
|
|
19
|
-
Float: 'double',
|
|
20
|
-
Date: 'DateTime',
|
|
21
|
-
};
|
|
22
|
-
const csharpValueTypes = [
|
|
23
|
-
'bool',
|
|
24
|
-
'byte',
|
|
25
|
-
'sbyte',
|
|
26
|
-
'char',
|
|
27
|
-
'decimal',
|
|
28
|
-
'double',
|
|
29
|
-
'float',
|
|
30
|
-
'int',
|
|
31
|
-
'uint',
|
|
32
|
-
'long',
|
|
33
|
-
'ulong',
|
|
34
|
-
'short',
|
|
35
|
-
'ushort',
|
|
36
|
-
'DateTime',
|
|
37
|
-
];
|
|
38
|
-
|
|
39
|
-
// This file is bundled and inlined.
|
|
40
|
-
function transformComment(comment, indentLevel = 0) {
|
|
41
|
-
if (!comment) {
|
|
42
|
-
return '';
|
|
43
|
-
}
|
|
44
|
-
if (isStringValueNode(comment)) {
|
|
45
|
-
comment = comment.value;
|
|
46
|
-
}
|
|
47
|
-
comment = comment.trimStart().split('*/').join('*\\/');
|
|
48
|
-
let lines = comment.split('\n');
|
|
49
|
-
lines = ['/// <summary>', ...lines.map(line => `/// ${line}`), '/// </summary>'];
|
|
50
|
-
return lines
|
|
51
|
-
.map(line => visitorPluginCommon.indent(line, indentLevel))
|
|
52
|
-
.concat('')
|
|
53
|
-
.join('\n');
|
|
54
|
-
}
|
|
55
|
-
function isStringValueNode(node) {
|
|
56
|
-
return node && typeof node === 'object' && node.kind === graphql.Kind.STRING;
|
|
57
|
-
}
|
|
58
|
-
function isValueType(type) {
|
|
59
|
-
// Limitation: only checks the list of known built in value types
|
|
60
|
-
// Eg .NET types and struct types won't be detected correctly
|
|
61
|
-
return csharpValueTypes.includes(type);
|
|
62
|
-
}
|
|
63
|
-
function getListTypeField(typeNode) {
|
|
64
|
-
if (typeNode.kind === graphql.Kind.LIST_TYPE) {
|
|
65
|
-
return {
|
|
66
|
-
required: false,
|
|
67
|
-
type: getListTypeField(typeNode.type),
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
if (typeNode.kind === graphql.Kind.NON_NULL_TYPE && typeNode.type.kind === graphql.Kind.LIST_TYPE) {
|
|
71
|
-
return Object.assign(getListTypeField(typeNode.type), {
|
|
72
|
-
required: true,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
if (typeNode.kind === graphql.Kind.NON_NULL_TYPE) {
|
|
76
|
-
return getListTypeField(typeNode.type);
|
|
77
|
-
}
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
function getListTypeDepth(listType) {
|
|
81
|
-
if (listType) {
|
|
82
|
-
return getListTypeDepth(listType.type) + 1;
|
|
83
|
-
}
|
|
84
|
-
return 0;
|
|
85
|
-
}
|
|
86
|
-
function getListInnerTypeNode(typeNode) {
|
|
87
|
-
if (typeNode.kind === graphql.Kind.LIST_TYPE) {
|
|
88
|
-
return getListInnerTypeNode(typeNode.type);
|
|
89
|
-
}
|
|
90
|
-
if (typeNode.kind === graphql.Kind.NON_NULL_TYPE && typeNode.type.kind === graphql.Kind.LIST_TYPE) {
|
|
91
|
-
return getListInnerTypeNode(typeNode.type);
|
|
92
|
-
}
|
|
93
|
-
return typeNode;
|
|
94
|
-
}
|
|
95
|
-
function wrapFieldType(fieldType, listTypeField, listType = 'IEnumerable') {
|
|
96
|
-
if (listTypeField) {
|
|
97
|
-
const innerType = wrapFieldType(fieldType, listTypeField.type, listType);
|
|
98
|
-
return `${listType}<${innerType}>`;
|
|
99
|
-
}
|
|
100
|
-
return fieldType.innerTypeName;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// This file is bundled and inlined.
|
|
104
|
-
class CSharpDeclarationBlock {
|
|
105
|
-
constructor() {
|
|
106
|
-
this._name = null;
|
|
107
|
-
this._extendStr = [];
|
|
108
|
-
this._implementsStr = [];
|
|
109
|
-
this._kind = null;
|
|
110
|
-
this._access = 'public';
|
|
111
|
-
this._final = false;
|
|
112
|
-
this._static = false;
|
|
113
|
-
this._block = null;
|
|
114
|
-
this._comment = null;
|
|
115
|
-
this._nestedClasses = [];
|
|
116
|
-
}
|
|
117
|
-
nestedClass(nstCls) {
|
|
118
|
-
this._nestedClasses.push(nstCls);
|
|
119
|
-
return this;
|
|
120
|
-
}
|
|
121
|
-
access(access) {
|
|
122
|
-
this._access = access;
|
|
123
|
-
return this;
|
|
124
|
-
}
|
|
125
|
-
asKind(kind) {
|
|
126
|
-
this._kind = kind;
|
|
127
|
-
return this;
|
|
128
|
-
}
|
|
129
|
-
final() {
|
|
130
|
-
this._final = true;
|
|
131
|
-
return this;
|
|
132
|
-
}
|
|
133
|
-
static() {
|
|
134
|
-
this._static = true;
|
|
135
|
-
return this;
|
|
136
|
-
}
|
|
137
|
-
withComment(comment) {
|
|
138
|
-
if (comment) {
|
|
139
|
-
this._comment = transformComment(comment, 1);
|
|
140
|
-
}
|
|
141
|
-
return this;
|
|
142
|
-
}
|
|
143
|
-
withBlock(block) {
|
|
144
|
-
this._block = block;
|
|
145
|
-
return this;
|
|
146
|
-
}
|
|
147
|
-
extends(extendStr) {
|
|
148
|
-
this._extendStr = extendStr;
|
|
149
|
-
return this;
|
|
150
|
-
}
|
|
151
|
-
implements(implementsStr) {
|
|
152
|
-
this._implementsStr = implementsStr;
|
|
153
|
-
return this;
|
|
154
|
-
}
|
|
155
|
-
withName(name) {
|
|
156
|
-
this._name = typeof name === 'object' ? name.value : name;
|
|
157
|
-
return this;
|
|
158
|
-
}
|
|
159
|
-
get string() {
|
|
160
|
-
let result = '';
|
|
161
|
-
if (this._kind) {
|
|
162
|
-
let name = '';
|
|
163
|
-
if (this._name) {
|
|
164
|
-
name = this._name;
|
|
165
|
-
}
|
|
166
|
-
if (this._kind === 'namespace') {
|
|
167
|
-
result += `${this._kind} ${name} `;
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
let extendStr = '';
|
|
171
|
-
let implementsStr = '';
|
|
172
|
-
const final = this._final ? ' final' : '';
|
|
173
|
-
const isStatic = this._static ? ' static' : '';
|
|
174
|
-
if (this._extendStr.length > 0) {
|
|
175
|
-
extendStr = ` : ${this._extendStr.join(', ')}`;
|
|
176
|
-
}
|
|
177
|
-
if (this._implementsStr.length > 0) {
|
|
178
|
-
implementsStr = ` : ${this._implementsStr.join(', ')}`;
|
|
179
|
-
}
|
|
180
|
-
result += `${this._access}${isStatic}${final} ${this._kind} ${name}${extendStr}${implementsStr} `;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
const nestedClasses = this._nestedClasses.length
|
|
184
|
-
? this._nestedClasses.map(c => visitorPluginCommon.indentMultiline(c.string)).join('\n\n')
|
|
185
|
-
: null;
|
|
186
|
-
const before = '{';
|
|
187
|
-
const after = '}';
|
|
188
|
-
const block = [before, nestedClasses, this._block, after].filter(f => f).join('\n');
|
|
189
|
-
result += block;
|
|
190
|
-
return (this._comment ? this._comment : '') + result + '\n';
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
class CSharpFieldType {
|
|
195
|
-
constructor(fieldType) {
|
|
196
|
-
Object.assign(this, fieldType);
|
|
197
|
-
}
|
|
198
|
-
get innerTypeName() {
|
|
199
|
-
const nullable = this.baseType.valueType && !this.baseType.required ? '?' : '';
|
|
200
|
-
return `${this.baseType.type}${nullable}`;
|
|
201
|
-
}
|
|
202
|
-
get isOuterTypeRequired() {
|
|
203
|
-
return this.listType ? this.listType.required : this.baseType.required;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* C# keywords
|
|
209
|
-
* https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
|
|
210
|
-
*/
|
|
211
|
-
const csharpKeywords = new Set([
|
|
212
|
-
'abstract',
|
|
213
|
-
'as',
|
|
214
|
-
'base',
|
|
215
|
-
'bool',
|
|
216
|
-
'break',
|
|
217
|
-
'byte',
|
|
218
|
-
'case',
|
|
219
|
-
'catch',
|
|
220
|
-
'char',
|
|
221
|
-
'checked',
|
|
222
|
-
'class',
|
|
223
|
-
'const',
|
|
224
|
-
'continue',
|
|
225
|
-
'decimal',
|
|
226
|
-
'default',
|
|
227
|
-
'delegate',
|
|
228
|
-
'do',
|
|
229
|
-
'double',
|
|
230
|
-
'else',
|
|
231
|
-
'enum',
|
|
232
|
-
'event',
|
|
233
|
-
'explicit',
|
|
234
|
-
'extern',
|
|
235
|
-
'false',
|
|
236
|
-
'finally',
|
|
237
|
-
'fixed',
|
|
238
|
-
'float',
|
|
239
|
-
'for',
|
|
240
|
-
'foreach',
|
|
241
|
-
'goto',
|
|
242
|
-
'if',
|
|
243
|
-
'implicit',
|
|
244
|
-
'in',
|
|
245
|
-
'int',
|
|
246
|
-
'interface',
|
|
247
|
-
'internal',
|
|
248
|
-
'is',
|
|
249
|
-
'lock',
|
|
250
|
-
'long',
|
|
251
|
-
'namespace',
|
|
252
|
-
'new',
|
|
253
|
-
'null',
|
|
254
|
-
'object',
|
|
255
|
-
'operator',
|
|
256
|
-
'out',
|
|
257
|
-
'override',
|
|
258
|
-
'params',
|
|
259
|
-
'private',
|
|
260
|
-
'protected',
|
|
261
|
-
'public',
|
|
262
|
-
'readonly',
|
|
263
|
-
'record',
|
|
264
|
-
'ref',
|
|
265
|
-
'return',
|
|
266
|
-
'sbyte',
|
|
267
|
-
'sealed',
|
|
268
|
-
'short',
|
|
269
|
-
'sizeof',
|
|
270
|
-
'stackalloc',
|
|
271
|
-
'static',
|
|
272
|
-
'string',
|
|
273
|
-
'struct',
|
|
274
|
-
'switch',
|
|
275
|
-
'this',
|
|
276
|
-
'throw',
|
|
277
|
-
'true',
|
|
278
|
-
'try',
|
|
279
|
-
'typeof',
|
|
280
|
-
'uint',
|
|
281
|
-
'ulong',
|
|
282
|
-
'unchecked',
|
|
283
|
-
'unsafe',
|
|
284
|
-
'ushort',
|
|
285
|
-
'using',
|
|
286
|
-
'virtual',
|
|
287
|
-
'void',
|
|
288
|
-
'volatile',
|
|
289
|
-
'while',
|
|
290
|
-
]);
|
|
291
|
-
/**
|
|
292
|
-
* Checks name against list of keywords. If it is, will prefix value with @
|
|
293
|
-
*
|
|
294
|
-
* Note:
|
|
295
|
-
* This class should first invoke the convertName from base-visitor to convert the string or node
|
|
296
|
-
* value according the naming configuration, eg upper or lower case. Then resulting string checked
|
|
297
|
-
* against the list or keywords.
|
|
298
|
-
* However the generated C# code is not yet able to handle fields that are in a different case so
|
|
299
|
-
* the invocation of convertName is omitted purposely.
|
|
300
|
-
*/
|
|
301
|
-
function convertSafeName(node) {
|
|
302
|
-
const name = typeof node === 'string' ? node : node.value;
|
|
303
|
-
return csharpKeywords.has(name) ? `@${name}` : name;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const defaultSuffix = 'GQL';
|
|
307
|
-
const R_NAME = /name:\s*"([^"]+)"/;
|
|
308
|
-
function R_DEF(directive) {
|
|
309
|
-
return new RegExp(`\\s+\\@${directive}\\([^)]+\\)`, 'gm');
|
|
310
|
-
}
|
|
311
|
-
class CSharpOperationsVisitor extends visitorPluginCommon.ClientSideBaseVisitor {
|
|
312
|
-
constructor(schema, fragments, rawConfig, documents) {
|
|
313
|
-
super(schema, fragments, rawConfig, {
|
|
314
|
-
namespaceName: rawConfig.namespaceName || 'GraphQLCodeGen',
|
|
315
|
-
namedClient: rawConfig.namedClient,
|
|
316
|
-
querySuffix: rawConfig.querySuffix || defaultSuffix,
|
|
317
|
-
mutationSuffix: rawConfig.mutationSuffix || defaultSuffix,
|
|
318
|
-
subscriptionSuffix: rawConfig.subscriptionSuffix || defaultSuffix,
|
|
319
|
-
scalars: visitorPluginCommon.buildScalarsFromConfig(schema, rawConfig, C_SHARP_SCALARS),
|
|
320
|
-
typesafeOperation: rawConfig.typesafeOperation || false,
|
|
321
|
-
}, documents);
|
|
322
|
-
this._operationsToInclude = [];
|
|
323
|
-
this.overruleConfigSettings();
|
|
324
|
-
autoBind(this);
|
|
325
|
-
this._schemaAST = pluginHelpers.getCachedDocumentNodeFromSchema(schema);
|
|
326
|
-
}
|
|
327
|
-
// Some settings aren't supported with C#, overruled here
|
|
328
|
-
overruleConfigSettings() {
|
|
329
|
-
if (this.config.documentMode === visitorPluginCommon.DocumentMode.graphQLTag) {
|
|
330
|
-
// C# operations does not (yet) support graphQLTag mode
|
|
331
|
-
this.config.documentMode = visitorPluginCommon.DocumentMode.documentNode;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
_operationHasDirective(operation, directive) {
|
|
335
|
-
if (typeof operation === 'string') {
|
|
336
|
-
return operation.includes(`${directive}`);
|
|
337
|
-
}
|
|
338
|
-
let found = false;
|
|
339
|
-
graphql.visit(operation, {
|
|
340
|
-
Directive(node) {
|
|
341
|
-
if (node.name.value === directive) {
|
|
342
|
-
found = true;
|
|
343
|
-
}
|
|
344
|
-
},
|
|
345
|
-
});
|
|
346
|
-
return found;
|
|
347
|
-
}
|
|
348
|
-
_extractDirective(operation, directive) {
|
|
349
|
-
const directives = graphql.print(operation).match(R_DEF(directive));
|
|
350
|
-
if (directives.length > 1) {
|
|
351
|
-
throw new Error(`The ${directive} directive used multiple times in '${operation.name}' operation`);
|
|
352
|
-
}
|
|
353
|
-
return directives[0];
|
|
354
|
-
}
|
|
355
|
-
_namedClient(operation) {
|
|
356
|
-
let name;
|
|
357
|
-
if (this._operationHasDirective(operation, 'namedClient')) {
|
|
358
|
-
name = this._extractNamedClient(operation);
|
|
359
|
-
}
|
|
360
|
-
else if (this.config.namedClient) {
|
|
361
|
-
name = this.config.namedClient;
|
|
362
|
-
}
|
|
363
|
-
return name ? `client = '${name}';` : '';
|
|
364
|
-
}
|
|
365
|
-
_extractNamedClient(operation) {
|
|
366
|
-
const [, name] = this._extractDirective(operation, 'namedClient').match(R_NAME);
|
|
367
|
-
return name;
|
|
368
|
-
}
|
|
369
|
-
_gql(node) {
|
|
370
|
-
const fragments = this._transformFragments(node);
|
|
371
|
-
const doc = this._prepareDocument([graphql.print(node), this._includeFragments(fragments, node.kind)].join('\n'));
|
|
372
|
-
return doc.replace(/"/g, '""');
|
|
373
|
-
}
|
|
374
|
-
_getDocumentNodeVariable(node, documentVariableName) {
|
|
375
|
-
return this.config.documentMode === visitorPluginCommon.DocumentMode.external ? `Operations.${node.name.value}` : documentVariableName;
|
|
376
|
-
}
|
|
377
|
-
_gqlInputSignature(variable) {
|
|
378
|
-
const typeNode = variable.type;
|
|
379
|
-
const innerType = visitorPluginCommon.getBaseTypeNode(typeNode);
|
|
380
|
-
const schemaType = this._schema.getType(innerType.name.value);
|
|
381
|
-
const name = variable.variable.name.value;
|
|
382
|
-
const baseType = !graphql.isScalarType(schemaType) ? innerType.name.value : this.scalars[schemaType.name] || 'object';
|
|
383
|
-
const listType = getListTypeField(typeNode);
|
|
384
|
-
const required = getListInnerTypeNode(typeNode).kind === graphql.Kind.NON_NULL_TYPE;
|
|
385
|
-
return {
|
|
386
|
-
required: listType ? listType.required : required,
|
|
387
|
-
signature: !listType
|
|
388
|
-
? `${name}=(${baseType})`
|
|
389
|
-
: `${name}=(${baseType}${'[]'.repeat(getListTypeDepth(listType))})`,
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
getCSharpImports() {
|
|
393
|
-
return (['System', 'Newtonsoft.Json', 'GraphQL', 'GraphQL.Client.Abstractions'].map(i => `using ${i};`).join('\n') + '\n');
|
|
394
|
-
}
|
|
395
|
-
_operationSuffix(operationType) {
|
|
396
|
-
switch (operationType) {
|
|
397
|
-
case 'query':
|
|
398
|
-
return this.config.querySuffix;
|
|
399
|
-
case 'mutation':
|
|
400
|
-
return this.config.mutationSuffix;
|
|
401
|
-
case 'subscription':
|
|
402
|
-
return this.config.subscriptionSuffix;
|
|
403
|
-
default:
|
|
404
|
-
return defaultSuffix;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
resolveFieldType(typeNode, hasDefaultValue = false) {
|
|
408
|
-
const innerType = visitorPluginCommon.getBaseTypeNode(typeNode);
|
|
409
|
-
const schemaType = this._schema.getType(innerType.name.value);
|
|
410
|
-
const listType = getListTypeField(typeNode);
|
|
411
|
-
const required = getListInnerTypeNode(typeNode).kind === graphql.Kind.NON_NULL_TYPE;
|
|
412
|
-
let result = null;
|
|
413
|
-
if (graphql.isScalarType(schemaType)) {
|
|
414
|
-
if (this.scalars[schemaType.name]) {
|
|
415
|
-
const baseType = this.scalars[schemaType.name];
|
|
416
|
-
result = new CSharpFieldType({
|
|
417
|
-
baseType: {
|
|
418
|
-
type: baseType,
|
|
419
|
-
required,
|
|
420
|
-
valueType: isValueType(baseType),
|
|
421
|
-
},
|
|
422
|
-
listType,
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
else {
|
|
426
|
-
result = new CSharpFieldType({
|
|
427
|
-
baseType: {
|
|
428
|
-
type: 'object',
|
|
429
|
-
required,
|
|
430
|
-
valueType: false,
|
|
431
|
-
},
|
|
432
|
-
listType,
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
else if (graphql.isInputObjectType(schemaType)) {
|
|
437
|
-
result = new CSharpFieldType({
|
|
438
|
-
baseType: {
|
|
439
|
-
type: `${this.convertName(schemaType.name)}`,
|
|
440
|
-
required,
|
|
441
|
-
valueType: false,
|
|
442
|
-
},
|
|
443
|
-
listType,
|
|
444
|
-
});
|
|
445
|
-
}
|
|
446
|
-
else if (graphql.isEnumType(schemaType)) {
|
|
447
|
-
result = new CSharpFieldType({
|
|
448
|
-
baseType: {
|
|
449
|
-
type: this.convertName(schemaType.name),
|
|
450
|
-
required,
|
|
451
|
-
valueType: true,
|
|
452
|
-
},
|
|
453
|
-
listType,
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
result = new CSharpFieldType({
|
|
458
|
-
baseType: {
|
|
459
|
-
type: `${schemaType.name}`,
|
|
460
|
-
required,
|
|
461
|
-
valueType: false,
|
|
462
|
-
},
|
|
463
|
-
listType,
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
if (hasDefaultValue) {
|
|
467
|
-
// Required field is optional when default value specified, see #4273
|
|
468
|
-
(result.listType || result.baseType).required = false;
|
|
469
|
-
}
|
|
470
|
-
return result;
|
|
471
|
-
}
|
|
472
|
-
_getResponseFieldRecursive(node, parentSchema) {
|
|
473
|
-
switch (node.kind) {
|
|
474
|
-
case graphql.Kind.OPERATION_DEFINITION: {
|
|
475
|
-
return new CSharpDeclarationBlock()
|
|
476
|
-
.access('public')
|
|
477
|
-
.asKind('class')
|
|
478
|
-
.withName('Response')
|
|
479
|
-
.withBlock('\n' +
|
|
480
|
-
node.selectionSet.selections
|
|
481
|
-
.map(opr => {
|
|
482
|
-
if (opr.kind !== graphql.Kind.FIELD) {
|
|
483
|
-
throw new Error(`Unknown kind; ${opr.kind} in OperationDefinitionNode`);
|
|
484
|
-
}
|
|
485
|
-
return this._getResponseFieldRecursive(opr, parentSchema);
|
|
486
|
-
})
|
|
487
|
-
.join('\n')).string;
|
|
488
|
-
}
|
|
489
|
-
case graphql.Kind.FIELD: {
|
|
490
|
-
const fieldSchema = parentSchema.fields.find(f => f.name.value === node.name.value);
|
|
491
|
-
if (!fieldSchema) {
|
|
492
|
-
throw new Error(`Field schema not found; ${node.name.value}`);
|
|
493
|
-
}
|
|
494
|
-
const responseType = this.resolveFieldType(fieldSchema.type);
|
|
495
|
-
if (!node.selectionSet) {
|
|
496
|
-
const responseTypeName = wrapFieldType(responseType, responseType.listType, 'System.Collections.Generic.List');
|
|
497
|
-
return visitorPluginCommon.indentMultiline([
|
|
498
|
-
`[JsonProperty("${node.name.value}")]`,
|
|
499
|
-
`public ${responseTypeName} ${convertSafeName(node.name.value)} { get; set; }`,
|
|
500
|
-
].join('\n') + '\n');
|
|
501
|
-
}
|
|
502
|
-
const selectionBaseTypeName = `${responseType.baseType.type}Selection`;
|
|
503
|
-
const selectionType = Object.assign(new CSharpFieldType(responseType), {
|
|
504
|
-
baseType: { type: selectionBaseTypeName },
|
|
505
|
-
});
|
|
506
|
-
const selectionTypeName = wrapFieldType(selectionType, selectionType.listType, 'System.Collections.Generic.List');
|
|
507
|
-
const innerClassSchema = this._schemaAST.definitions.find(d => d.kind === graphql.Kind.OBJECT_TYPE_DEFINITION && d.name.value === responseType.baseType.type);
|
|
508
|
-
const innerClassDefinition = new CSharpDeclarationBlock()
|
|
509
|
-
.access('public')
|
|
510
|
-
.asKind('class')
|
|
511
|
-
.withName(convertSafeName(selectionBaseTypeName))
|
|
512
|
-
.withBlock('\n' +
|
|
513
|
-
node.selectionSet.selections
|
|
514
|
-
.map(s => {
|
|
515
|
-
if (s.kind === graphql.Kind.INLINE_FRAGMENT) {
|
|
516
|
-
throw new Error(`Unsupported kind; ${node.name} ${s.kind}`);
|
|
517
|
-
}
|
|
518
|
-
return this._getResponseFieldRecursive(s, innerClassSchema);
|
|
519
|
-
})
|
|
520
|
-
.join('\n')).string;
|
|
521
|
-
return visitorPluginCommon.indentMultiline([
|
|
522
|
-
innerClassDefinition,
|
|
523
|
-
`[JsonProperty("${node.name.value}")]`,
|
|
524
|
-
`public ${selectionTypeName} ${convertSafeName(node.name.value)} { get; set; }`,
|
|
525
|
-
].join('\n') + '\n');
|
|
526
|
-
}
|
|
527
|
-
case graphql.Kind.FRAGMENT_SPREAD: {
|
|
528
|
-
const fragmentSchema = this._fragments.find(f => f.name === node.name.value);
|
|
529
|
-
if (!fragmentSchema) {
|
|
530
|
-
throw new Error(`Fragment schema not found; ${node.name.value}`);
|
|
531
|
-
}
|
|
532
|
-
return fragmentSchema.node.selectionSet.selections
|
|
533
|
-
.map(s => {
|
|
534
|
-
if (s.kind === graphql.Kind.INLINE_FRAGMENT) {
|
|
535
|
-
throw new Error(`Unsupported kind; ${node.name} ${s.kind}`);
|
|
536
|
-
}
|
|
537
|
-
return this._getResponseFieldRecursive(s, parentSchema);
|
|
538
|
-
})
|
|
539
|
-
.join('\n');
|
|
540
|
-
}
|
|
541
|
-
default: {
|
|
542
|
-
return '';
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
_getResponseClass(node) {
|
|
547
|
-
const operationSchema = this._schemaAST.definitions.find(s => s.kind === graphql.Kind.OBJECT_TYPE_DEFINITION && s.name.value.toLowerCase() === node.operation);
|
|
548
|
-
return this._getResponseFieldRecursive(node, operationSchema);
|
|
549
|
-
}
|
|
550
|
-
_getVariablesClass(node) {
|
|
551
|
-
var _a, _b;
|
|
552
|
-
if (!((_a = node.variableDefinitions) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
553
|
-
return '';
|
|
554
|
-
}
|
|
555
|
-
return new CSharpDeclarationBlock()
|
|
556
|
-
.access('public')
|
|
557
|
-
.asKind('class')
|
|
558
|
-
.withName('Variables')
|
|
559
|
-
.withBlock('\n' +
|
|
560
|
-
((_b = node.variableDefinitions) === null || _b === void 0 ? void 0 : _b.map(v => {
|
|
561
|
-
const inputType = this.resolveFieldType(v.type);
|
|
562
|
-
const inputTypeName = wrapFieldType(inputType, inputType.listType, 'System.Collections.Generic.List');
|
|
563
|
-
return visitorPluginCommon.indentMultiline([
|
|
564
|
-
`[JsonProperty("${v.variable.name.value}")]`,
|
|
565
|
-
`public ${inputTypeName} ${convertSafeName(v.variable.name.value)} { get; set; }`,
|
|
566
|
-
].join('\n') + '\n');
|
|
567
|
-
}).join('\n'))).string;
|
|
568
|
-
}
|
|
569
|
-
_getOperationMethod(node) {
|
|
570
|
-
var _a, _b, _c, _d;
|
|
571
|
-
const operationSchema = this._schemaAST.definitions.find(s => s.kind === graphql.Kind.OBJECT_TYPE_DEFINITION && s.name.value.toLowerCase() === node.operation);
|
|
572
|
-
if (!operationSchema) {
|
|
573
|
-
throw new Error(`Operation schema not found; ${node.operation}`);
|
|
574
|
-
}
|
|
575
|
-
const variablesArgument = ((_a = node.variableDefinitions) === null || _a === void 0 ? void 0 : _a.length) ? ', Variables variables' : '';
|
|
576
|
-
switch (node.operation) {
|
|
577
|
-
case 'query':
|
|
578
|
-
case 'mutation':
|
|
579
|
-
return [
|
|
580
|
-
`public static System.Threading.Tasks.Task<GraphQLResponse<Response>> Send${operationSchema.name.value}Async(IGraphQLClient client${variablesArgument}, System.Threading.CancellationToken cancellationToken = default) {`,
|
|
581
|
-
visitorPluginCommon.indent(`return client.Send${operationSchema.name.value}Async<Response>(Request(${((_b = node.variableDefinitions) === null || _b === void 0 ? void 0 : _b.length) ? 'variables' : ''}), cancellationToken);`),
|
|
582
|
-
`}`,
|
|
583
|
-
].join('\n');
|
|
584
|
-
case 'subscription': {
|
|
585
|
-
return [
|
|
586
|
-
`public static System.IObservable<GraphQLResponse<Response>> CreateSubscriptionStream(IGraphQLClient client${variablesArgument}) {`,
|
|
587
|
-
visitorPluginCommon.indent(`return client.CreateSubscriptionStream<Response>(Request(${((_c = node.variableDefinitions) === null || _c === void 0 ? void 0 : _c.length) ? 'variables' : ''}));`),
|
|
588
|
-
`}`,
|
|
589
|
-
'',
|
|
590
|
-
`public static System.IObservable<GraphQLResponse<Response>> CreateSubscriptionStream(IGraphQLClient client${variablesArgument}, System.Action<System.Exception> exceptionHandler) {`,
|
|
591
|
-
visitorPluginCommon.indent(`return client.CreateSubscriptionStream<Response>(Request(${((_d = node.variableDefinitions) === null || _d === void 0 ? void 0 : _d.length) ? 'variables' : ''}), exceptionHandler);`),
|
|
592
|
-
`}`,
|
|
593
|
-
].join('\n');
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
throw new Error(`Unexpected operation type: ${node.operation}`);
|
|
597
|
-
}
|
|
598
|
-
OperationDefinition(node) {
|
|
599
|
-
var _a;
|
|
600
|
-
if (!node.name || !node.name.value) {
|
|
601
|
-
return null;
|
|
602
|
-
}
|
|
603
|
-
this._collectedOperations.push(node);
|
|
604
|
-
const documentVariableName = this.convertName(node, {
|
|
605
|
-
suffix: this.config.documentVariableSuffix,
|
|
606
|
-
prefix: this.config.documentVariablePrefix,
|
|
607
|
-
useTypesPrefix: false,
|
|
608
|
-
});
|
|
609
|
-
let documentString = '';
|
|
610
|
-
if (this.config.documentMode !== visitorPluginCommon.DocumentMode.external) {
|
|
611
|
-
const gqlBlock = visitorPluginCommon.indentMultiline(this._gql(node), 4);
|
|
612
|
-
documentString = `${this.config.noExport ? '' : 'public'} static string ${convertSafeName(documentVariableName)} = @"\n${gqlBlock}";`;
|
|
613
|
-
}
|
|
614
|
-
const operationType = node.operation;
|
|
615
|
-
const operationTypeSuffix = this.config.dedupeOperationSuffix && node.name.value.toLowerCase().endsWith(node.operation)
|
|
616
|
-
? ''
|
|
617
|
-
: !operationType
|
|
618
|
-
? ''
|
|
619
|
-
: operationType;
|
|
620
|
-
const operationResultType = this.convertName(node, {
|
|
621
|
-
suffix: operationTypeSuffix + this._parsedConfig.operationResultSuffix,
|
|
622
|
-
});
|
|
623
|
-
const operationVariablesTypes = this.convertName(node, {
|
|
624
|
-
suffix: operationTypeSuffix + 'Variables',
|
|
625
|
-
});
|
|
626
|
-
const serviceName = `${this.convertName(node)}${this._operationSuffix(operationType)}`;
|
|
627
|
-
this._operationsToInclude.push({
|
|
628
|
-
node,
|
|
629
|
-
documentVariableName,
|
|
630
|
-
operationType,
|
|
631
|
-
operationResultType,
|
|
632
|
-
operationVariablesTypes,
|
|
633
|
-
});
|
|
634
|
-
const inputSignatures = (_a = node.variableDefinitions) === null || _a === void 0 ? void 0 : _a.map(v => this._gqlInputSignature(v));
|
|
635
|
-
const hasInputArgs = !!(inputSignatures === null || inputSignatures === void 0 ? void 0 : inputSignatures.length);
|
|
636
|
-
const inputArgsHint = hasInputArgs
|
|
637
|
-
? `
|
|
638
|
-
/// <para>Required variables:<br/> { ${inputSignatures
|
|
639
|
-
.filter(sig => sig.required)
|
|
640
|
-
.map(sig => sig.signature)
|
|
641
|
-
.join(', ')} }</para>
|
|
642
|
-
/// <para>Optional variables:<br/> { ${inputSignatures
|
|
643
|
-
.filter(sig => !sig.required)
|
|
644
|
-
.map(sig => sig.signature)
|
|
645
|
-
.join(', ')} }</para>`
|
|
646
|
-
: '';
|
|
647
|
-
// Should use ObsoleteAttribute but VS treats warnings as errors which would be super annoying so use remarks comment instead
|
|
648
|
-
const obsoleteMessage = '/// <remarks>This method is obsolete. Use Request instead.</remarks>';
|
|
649
|
-
let typesafeOperations = '';
|
|
650
|
-
if (this.config.typesafeOperation) {
|
|
651
|
-
typesafeOperations = `
|
|
652
|
-
${this._getVariablesClass(node)}
|
|
653
|
-
${this._getResponseClass(node)}
|
|
654
|
-
${this._getOperationMethod(node)}
|
|
655
|
-
`;
|
|
656
|
-
typesafeOperations = visitorPluginCommon.indentMultiline(typesafeOperations, 3);
|
|
657
|
-
}
|
|
658
|
-
const content = `
|
|
659
|
-
public class ${serviceName} {
|
|
660
|
-
/// <summary>
|
|
661
|
-
/// ${serviceName}.Request ${inputArgsHint}
|
|
662
|
-
/// </summary>
|
|
663
|
-
public static GraphQLRequest Request(${hasInputArgs ? 'object variables = null' : ''}) {
|
|
664
|
-
return new GraphQLRequest {
|
|
665
|
-
Query = ${this._getDocumentNodeVariable(node, documentVariableName)},
|
|
666
|
-
OperationName = "${node.name.value}"${hasInputArgs
|
|
667
|
-
? `,
|
|
668
|
-
Variables = variables`
|
|
669
|
-
: ''}
|
|
670
|
-
};
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
${obsoleteMessage}
|
|
674
|
-
public static GraphQLRequest get${serviceName}() {
|
|
675
|
-
return Request();
|
|
676
|
-
}
|
|
677
|
-
${this._namedClient(node)}
|
|
678
|
-
${documentString}
|
|
679
|
-
${typesafeOperations}
|
|
680
|
-
}
|
|
681
|
-
`;
|
|
682
|
-
return [content].filter(a => a).join('\n');
|
|
683
|
-
}
|
|
684
|
-
InputObjectTypeDefinition(node) {
|
|
685
|
-
var _a;
|
|
686
|
-
if (!this.config.typesafeOperation) {
|
|
687
|
-
return '';
|
|
688
|
-
}
|
|
689
|
-
const inputClass = new CSharpDeclarationBlock()
|
|
690
|
-
.access('public')
|
|
691
|
-
.asKind('class')
|
|
692
|
-
.withName(convertSafeName(this.convertName(node)))
|
|
693
|
-
.withBlock('\n' +
|
|
694
|
-
((_a = node.fields) === null || _a === void 0 ? void 0 : _a.map(f => {
|
|
695
|
-
if (f.kind !== graphql.Kind.INPUT_VALUE_DEFINITION) {
|
|
696
|
-
return null;
|
|
697
|
-
}
|
|
698
|
-
const inputType = this.resolveFieldType(f.type);
|
|
699
|
-
const inputTypeName = wrapFieldType(inputType, inputType.listType, 'System.Collections.Generic.List');
|
|
700
|
-
return visitorPluginCommon.indentMultiline([
|
|
701
|
-
`[JsonProperty("${f.name.value}")]`,
|
|
702
|
-
`public ${inputTypeName} ${convertSafeName(f.name.value)} { get; set; }`,
|
|
703
|
-
].join('\n') + '\n');
|
|
704
|
-
}).filter(f => !!f).join('\n'))).string;
|
|
705
|
-
return visitorPluginCommon.indentMultiline(inputClass, 2);
|
|
706
|
-
}
|
|
707
|
-
EnumTypeDefinition(node) {
|
|
708
|
-
var _a;
|
|
709
|
-
if (!this.config.typesafeOperation) {
|
|
710
|
-
return '';
|
|
711
|
-
}
|
|
712
|
-
const enumDefinition = new CSharpDeclarationBlock()
|
|
713
|
-
.access('public')
|
|
714
|
-
.asKind('enum')
|
|
715
|
-
.withName(convertSafeName(this.convertName(node.name)))
|
|
716
|
-
.withBlock(visitorPluginCommon.indentMultiline((_a = node.values) === null || _a === void 0 ? void 0 : _a.map(v => v.name.value).join(',\n'))).string;
|
|
717
|
-
return visitorPluginCommon.indentMultiline(enumDefinition, 2);
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
const plugin = (schema, documents, config) => {
|
|
722
|
-
const schemaAST = pluginHelpers.getCachedDocumentNodeFromSchema(schema);
|
|
723
|
-
const allAst = graphql.concatAST(documents.map(v => v.document).concat(schemaAST));
|
|
724
|
-
const allFragments = [
|
|
725
|
-
...allAst.definitions.filter(d => d.kind === graphql.Kind.FRAGMENT_DEFINITION).map(fragmentDef => ({
|
|
726
|
-
node: fragmentDef,
|
|
727
|
-
name: fragmentDef.name.value,
|
|
728
|
-
onType: fragmentDef.typeCondition.name.value,
|
|
729
|
-
isExternal: false,
|
|
730
|
-
})),
|
|
731
|
-
...(config.externalFragments || []),
|
|
732
|
-
];
|
|
733
|
-
const visitor = new CSharpOperationsVisitor(schema, allFragments, config, documents);
|
|
734
|
-
const visitorResult = pluginHelpers.oldVisit(allAst, { leave: visitor });
|
|
735
|
-
const imports = visitor.getCSharpImports();
|
|
736
|
-
const openNameSpace = `namespace ${visitor.config.namespaceName} {`;
|
|
737
|
-
return {
|
|
738
|
-
prepend: [],
|
|
739
|
-
content: [imports, openNameSpace, ...visitorResult.definitions.filter(t => typeof t === 'string'), '}']
|
|
740
|
-
.filter(a => a)
|
|
741
|
-
.join('\n'),
|
|
742
|
-
};
|
|
743
|
-
};
|
|
744
|
-
const addToSchema = gql `
|
|
745
|
-
directive @namedClient(name: String!) on OBJECT | FIELD
|
|
746
|
-
`;
|
|
747
|
-
const validate = async (schema, documents, config, outputFile) => {
|
|
748
|
-
if (path.extname(outputFile) !== '.cs') {
|
|
749
|
-
throw new Error(`Plugin "c-sharp-operations" requires extension to be ".cs"!`);
|
|
750
|
-
}
|
|
751
|
-
};
|
|
752
|
-
|
|
753
|
-
exports.CSharpOperationsVisitor = CSharpOperationsVisitor;
|
|
754
|
-
exports.addToSchema = addToSchema;
|
|
755
|
-
exports.plugin = plugin;
|
|
756
|
-
exports.validate = validate;
|