@graphql-codegen/java-apollo-android 2.3.0-alpha-a52c122aa.0 → 2.3.0-alpha-29eb1293b.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/base-java-visitor.js +114 -0
- package/cjs/custom-type-class.js +69 -0
- package/cjs/field-arguments.js +36 -0
- package/cjs/file-type.js +10 -0
- package/cjs/imports.js +45 -0
- package/cjs/index.js +5 -0
- package/cjs/input-type-visitor.js +187 -0
- package/cjs/operation-visitor.js +780 -0
- package/cjs/package.json +1 -0
- package/cjs/plugin.js +48 -0
- package/cjs/preset.js +95 -0
- package/cjs/types.js +2 -0
- package/cjs/visitor-config.js +2 -0
- package/esm/base-java-visitor.js +110 -0
- package/esm/custom-type-class.js +65 -0
- package/esm/field-arguments.js +32 -0
- package/esm/file-type.js +7 -0
- package/esm/imports.js +42 -0
- package/esm/index.js +2 -0
- package/esm/input-type-visitor.js +183 -0
- package/{index.mjs → esm/operation-visitor.js} +38 -620
- package/esm/plugin.js +44 -0
- package/esm/preset.js +92 -0
- package/esm/types.js +1 -0
- package/esm/visitor-config.js +1 -0
- package/package.json +24 -17
- package/{base-java-visitor.d.ts → typings/base-java-visitor.d.ts} +3 -3
- package/{custom-type-class.d.ts → typings/custom-type-class.d.ts} +3 -3
- package/{field-arguments.d.ts → typings/field-arguments.d.ts} +1 -1
- package/{file-type.d.ts → typings/file-type.d.ts} +0 -0
- package/{imports.d.ts → typings/imports.d.ts} +0 -0
- package/typings/index.d.ts +2 -0
- package/{input-type-visitor.d.ts → typings/input-type-visitor.d.ts} +3 -3
- package/{operation-visitor.d.ts → typings/operation-visitor.d.ts} +3 -3
- package/{plugin.d.ts → typings/plugin.d.ts} +4 -4
- package/{preset.d.ts → typings/preset.d.ts} +0 -0
- package/{types.d.ts → typings/types.d.ts} +0 -0
- package/{visitor-config.d.ts → typings/visitor-config.d.ts} +0 -0
- package/index.d.ts +0 -2
- package/index.js +0 -1364
|
@@ -1,379 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { BaseJavaVisitor, SCALAR_TO_WRITER_METHOD } from './base-java-visitor.js';
|
|
2
|
+
import { indent, indentMultiline, getBaseTypeNode } from '@graphql-codegen/visitor-plugin-common';
|
|
3
|
+
import { buildPackageNameFromPath, JavaDeclarationBlock } from '@graphql-codegen/java-common';
|
|
4
|
+
import { getBaseType } from '@graphql-codegen/plugin-helpers';
|
|
5
|
+
import { print, Kind, isNonNullType, isScalarType, isEnumType, isUnionType, isInterfaceType, isObjectType, isInputObjectType, GraphQLString, isListType, } from 'graphql';
|
|
6
|
+
import { Imports } from './imports.js';
|
|
5
7
|
import { createHash } from 'crypto';
|
|
6
8
|
import pluralize from 'pluralize';
|
|
9
|
+
import { visitFieldArguments } from './field-arguments.js';
|
|
7
10
|
import { camelCase, pascalCase } from 'change-case-all';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const Imports = {
|
|
11
|
-
// Primitives
|
|
12
|
-
String: 'java.lang.String',
|
|
13
|
-
Boolean: 'java.lang.Boolean',
|
|
14
|
-
Integer: 'java.lang.Integer',
|
|
15
|
-
Object: 'java.lang.Object',
|
|
16
|
-
Float: 'java.lang.Float',
|
|
17
|
-
Long: 'java.lang.Long',
|
|
18
|
-
// Java Base
|
|
19
|
-
Class: 'java.lang.Class',
|
|
20
|
-
Arrays: 'java.util.Arrays',
|
|
21
|
-
List: 'java.util.List',
|
|
22
|
-
IOException: 'java.io.IOException',
|
|
23
|
-
Collections: 'java.util.Collections',
|
|
24
|
-
LinkedHashMap: 'java.util.LinkedHashMap',
|
|
25
|
-
Map: 'java.util.Map',
|
|
26
|
-
// Annotations
|
|
27
|
-
Nonnull: 'javax.annotation.Nonnull',
|
|
28
|
-
Nullable: 'javax.annotation.Nullable',
|
|
29
|
-
Override: 'java.lang.Override',
|
|
30
|
-
Generated: 'javax.annotation.Generated',
|
|
31
|
-
// Apollo Android
|
|
32
|
-
ScalarType: 'com.apollographql.apollo.api.ScalarType',
|
|
33
|
-
GraphqlFragment: 'com.apollographql.apollo.api.GraphqlFragment',
|
|
34
|
-
Operation: 'com.apollographql.apollo.api.Operation',
|
|
35
|
-
OperationName: 'com.apollographql.apollo.api.OperationName',
|
|
36
|
-
Mutation: 'com.apollographql.apollo.api.Mutation',
|
|
37
|
-
Query: 'com.apollographql.apollo.api.Query',
|
|
38
|
-
Subscription: 'com.apollographql.apollo.api.Subscription',
|
|
39
|
-
ResponseField: 'com.apollographql.apollo.api.ResponseField',
|
|
40
|
-
ResponseFieldMapper: 'com.apollographql.apollo.api.ResponseFieldMapper',
|
|
41
|
-
ResponseFieldMarshaller: 'com.apollographql.apollo.api.ResponseFieldMarshaller',
|
|
42
|
-
ResponseReader: 'com.apollographql.apollo.api.ResponseReader',
|
|
43
|
-
ResponseWriter: 'com.apollographql.apollo.api.ResponseWriter',
|
|
44
|
-
FragmentResponseFieldMapper: 'com.apollographql.apollo.api.FragmentResponseFieldMapper',
|
|
45
|
-
UnmodifiableMapBuilder: 'com.apollographql.apollo.api.internal.UnmodifiableMapBuilder',
|
|
46
|
-
Utils: 'com.apollographql.apollo.api.internal.Utils',
|
|
47
|
-
InputType: 'com.apollographql.apollo.api.InputType',
|
|
48
|
-
Input: 'com.apollographql.apollo.api.Input',
|
|
49
|
-
InputFieldMarshaller: 'com.apollographql.apollo.api.InputFieldMarshaller',
|
|
50
|
-
InputFieldWriter: 'com.apollographql.apollo.api.InputFieldWriter',
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const SCALAR_TO_WRITER_METHOD = {
|
|
54
|
-
ID: 'writeString',
|
|
55
|
-
String: 'writeString',
|
|
56
|
-
Int: 'writeInt',
|
|
57
|
-
Boolean: 'writeBoolean',
|
|
58
|
-
Float: 'writeDouble',
|
|
59
|
-
};
|
|
60
|
-
function isTypeNode(type) {
|
|
61
|
-
return type && !!type.kind;
|
|
62
|
-
}
|
|
63
|
-
class BaseJavaVisitor extends BaseVisitor {
|
|
64
|
-
constructor(_schema, rawConfig, additionalConfig) {
|
|
65
|
-
super(rawConfig, {
|
|
66
|
-
...additionalConfig,
|
|
67
|
-
scalars: buildScalars(_schema, { ID: 'String' }, JAVA_SCALARS),
|
|
68
|
-
});
|
|
69
|
-
this._schema = _schema;
|
|
70
|
-
this._imports = new Set();
|
|
71
|
-
}
|
|
72
|
-
getPackage() {
|
|
73
|
-
return '';
|
|
74
|
-
}
|
|
75
|
-
additionalContent() {
|
|
76
|
-
return '';
|
|
77
|
-
}
|
|
78
|
-
getImports() {
|
|
79
|
-
return Array.from(this._imports).map(imp => `import ${imp};`);
|
|
80
|
-
}
|
|
81
|
-
getImplementingTypes(node) {
|
|
82
|
-
const allTypesMap = this._schema.getTypeMap();
|
|
83
|
-
const implementingTypes = [];
|
|
84
|
-
for (const graphqlType of Object.values(allTypesMap)) {
|
|
85
|
-
if (graphqlType instanceof GraphQLObjectType) {
|
|
86
|
-
const allInterfaces = graphqlType.getInterfaces();
|
|
87
|
-
if (allInterfaces.find(int => int.name === node.name)) {
|
|
88
|
-
implementingTypes.push(graphqlType.name);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return implementingTypes;
|
|
93
|
-
}
|
|
94
|
-
transformType(type) {
|
|
95
|
-
let schemaType;
|
|
96
|
-
let isNonNull;
|
|
97
|
-
if (isTypeNode(type)) {
|
|
98
|
-
const baseTypeNode = getBaseTypeNode(type);
|
|
99
|
-
schemaType = this._schema.getType(baseTypeNode.name.value);
|
|
100
|
-
isNonNull = type.kind === Kind.NON_NULL_TYPE;
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
schemaType = this._schema.getType(getBaseType(type).name);
|
|
104
|
-
isNonNull = isNonNullType(type);
|
|
105
|
-
}
|
|
106
|
-
const javaType = this.getJavaClass(schemaType);
|
|
107
|
-
const annotation = isNonNull ? 'Nonnull' : 'Nullable';
|
|
108
|
-
const typeToUse = isTypeNode(type)
|
|
109
|
-
? this.getListTypeNodeWrapped(javaType, type)
|
|
110
|
-
: this.getListTypeWrapped(javaType, type);
|
|
111
|
-
return {
|
|
112
|
-
baseType: schemaType.name,
|
|
113
|
-
javaType,
|
|
114
|
-
isNonNull,
|
|
115
|
-
annotation,
|
|
116
|
-
typeToUse,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
// Replaces a GraphQL type with a Java class
|
|
120
|
-
getJavaClass(schemaType) {
|
|
121
|
-
let typeToUse = schemaType.name;
|
|
122
|
-
if (isScalarType(schemaType)) {
|
|
123
|
-
const scalar = this.scalars[schemaType.name] || 'Object';
|
|
124
|
-
if (Imports[scalar]) {
|
|
125
|
-
this._imports.add(Imports[scalar]);
|
|
126
|
-
}
|
|
127
|
-
typeToUse = scalar;
|
|
128
|
-
}
|
|
129
|
-
else if (isInputObjectType(schemaType)) {
|
|
130
|
-
// Make sure to import it if it's in use
|
|
131
|
-
this._imports.add(`${this.config.typePackage}.${schemaType.name}`);
|
|
132
|
-
}
|
|
133
|
-
return typeToUse;
|
|
134
|
-
}
|
|
135
|
-
getListTypeWrapped(toWrap, type) {
|
|
136
|
-
if (isNonNullType(type)) {
|
|
137
|
-
return this.getListTypeWrapped(toWrap, type.ofType);
|
|
138
|
-
}
|
|
139
|
-
if (isListType(type)) {
|
|
140
|
-
const child = this.getListTypeWrapped(toWrap, type.ofType);
|
|
141
|
-
this._imports.add(Imports.List);
|
|
142
|
-
return `List<${child}>`;
|
|
143
|
-
}
|
|
144
|
-
return toWrap;
|
|
145
|
-
}
|
|
146
|
-
getListTypeNodeWrapped(toWrap, type) {
|
|
147
|
-
if (type.kind === Kind.NON_NULL_TYPE) {
|
|
148
|
-
return this.getListTypeNodeWrapped(toWrap, type.type);
|
|
149
|
-
}
|
|
150
|
-
if (type.kind === Kind.LIST_TYPE) {
|
|
151
|
-
const child = this.getListTypeNodeWrapped(toWrap, type.type);
|
|
152
|
-
this._imports.add(Imports.List);
|
|
153
|
-
return `List<${child}>`;
|
|
154
|
-
}
|
|
155
|
-
return toWrap;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
class InputTypeVisitor extends BaseJavaVisitor {
|
|
160
|
-
constructor(_schema, rawConfig) {
|
|
161
|
-
super(_schema, rawConfig, {
|
|
162
|
-
typePackage: rawConfig.typePackage || 'type',
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
getPackage() {
|
|
166
|
-
return this.config.typePackage;
|
|
167
|
-
}
|
|
168
|
-
addInputMembers(cls, fields) {
|
|
169
|
-
fields.forEach(field => {
|
|
170
|
-
const type = this.transformType(field.type);
|
|
171
|
-
const actualType = type.isNonNull ? type.typeToUse : `Input<${type.typeToUse}>`;
|
|
172
|
-
const annotations = type.isNonNull ? [type.annotation] : [];
|
|
173
|
-
this._imports.add(Imports[type.annotation]);
|
|
174
|
-
cls.addClassMember(field.name.value, actualType, null, annotations, 'private', { final: true });
|
|
175
|
-
cls.addClassMethod(field.name.value, actualType, `return this.${field.name.value};`, [], [type.annotation], 'public');
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
addInputCtor(cls, className, fields) {
|
|
179
|
-
const impl = fields.map(field => `this.${field.name.value} = ${field.name.value};`).join('\n');
|
|
180
|
-
cls.addClassMethod(className, null, impl, fields.map(f => {
|
|
181
|
-
const type = this.transformType(f.type);
|
|
182
|
-
const actualType = type.isNonNull ? type.typeToUse : `Input<${type.typeToUse}>`;
|
|
183
|
-
this._imports.add(Imports[type.annotation]);
|
|
184
|
-
return {
|
|
185
|
-
name: f.name.value,
|
|
186
|
-
type: actualType,
|
|
187
|
-
annotations: type.isNonNull ? [type.annotation] : [],
|
|
188
|
-
};
|
|
189
|
-
}), [], 'public');
|
|
190
|
-
}
|
|
191
|
-
getFieldWriterCall(field, listItemCall = false) {
|
|
192
|
-
const baseType = getBaseTypeNode(field.type);
|
|
193
|
-
const schemaType = this._schema.getType(baseType.name.value);
|
|
194
|
-
const isNonNull = field.type.kind === Kind.NON_NULL_TYPE;
|
|
195
|
-
let writerMethod = null;
|
|
196
|
-
if (isScalarType(schemaType)) {
|
|
197
|
-
writerMethod = SCALAR_TO_WRITER_METHOD[schemaType.name] || 'writeCustom';
|
|
198
|
-
}
|
|
199
|
-
else if (isInputObjectType(schemaType)) {
|
|
200
|
-
return listItemCall
|
|
201
|
-
? `writeObject($item.marshaller())`
|
|
202
|
-
: `writeObject("${field.name.value}", ${field.name.value}.value != null ? ${field.name.value}.value.marshaller() : null)`;
|
|
203
|
-
}
|
|
204
|
-
else if (isEnumType(schemaType)) {
|
|
205
|
-
writerMethod = 'writeString';
|
|
206
|
-
}
|
|
207
|
-
return listItemCall
|
|
208
|
-
? `${writerMethod}($item)`
|
|
209
|
-
: `${writerMethod}("${field.name.value}", ${field.name.value}${isNonNull ? '' : '.value'})`;
|
|
210
|
-
}
|
|
211
|
-
getFieldWithTypePrefix(field, wrapWith = null, applyNullable = false) {
|
|
212
|
-
this._imports.add(Imports.Input);
|
|
213
|
-
const typeToUse = this.getJavaClass(this._schema.getType(getBaseTypeNode(field.type).name.value));
|
|
214
|
-
const isNonNull = field.type.kind === Kind.NON_NULL_TYPE;
|
|
215
|
-
const name = field.kind === Kind.INPUT_VALUE_DEFINITION ? field.name.value : field.variable.name.value;
|
|
216
|
-
if (isNonNull) {
|
|
217
|
-
this._imports.add(Imports.Nonnull);
|
|
218
|
-
return `@Nonnull ${typeToUse} ${name}`;
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
if (wrapWith) {
|
|
222
|
-
return typeof wrapWith === 'function' ? `${wrapWith(typeToUse)} ${name}` : `${wrapWith}<${typeToUse}> ${name}`;
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
if (applyNullable) {
|
|
226
|
-
this._imports.add(Imports.Nullable);
|
|
227
|
-
}
|
|
228
|
-
return `${applyNullable ? '@Nullable ' : ''}${typeToUse} ${name}`;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
buildFieldsMarshaller(field) {
|
|
233
|
-
const isNonNull = field.type.kind === Kind.NON_NULL_TYPE;
|
|
234
|
-
const isArray = field.type.kind === Kind.LIST_TYPE ||
|
|
235
|
-
(field.type.kind === Kind.NON_NULL_TYPE && field.type.type.kind === Kind.LIST_TYPE);
|
|
236
|
-
const call = this.getFieldWriterCall(field, isArray);
|
|
237
|
-
const baseTypeNode = getBaseTypeNode(field.type);
|
|
238
|
-
const listItemType = this.getJavaClass(this._schema.getType(baseTypeNode.name.value));
|
|
239
|
-
let result = '';
|
|
240
|
-
// TODO: Refactor
|
|
241
|
-
if (isArray) {
|
|
242
|
-
result = `writer.writeList("${field.name.value}", ${field.name.value}.value != null ? new InputFieldWriter.ListWriter() {
|
|
243
|
-
@Override
|
|
244
|
-
public void write(InputFieldWriter.ListItemWriter listItemWriter) throws IOException {
|
|
245
|
-
for (${listItemType} $item : ${field.name.value}.value) {
|
|
246
|
-
listItemWriter.${call};
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
} : null);`;
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
result = indent(`writer.${call};`);
|
|
253
|
-
}
|
|
254
|
-
if (isNonNull) {
|
|
255
|
-
return result;
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
258
|
-
return indentMultiline(`if(${field.name.value}.defined) {
|
|
259
|
-
${indentMultiline(result)}
|
|
260
|
-
}`);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
buildMarshallerOverride(fields) {
|
|
264
|
-
this._imports.add(Imports.Override);
|
|
265
|
-
this._imports.add(Imports.IOException);
|
|
266
|
-
this._imports.add(Imports.InputFieldWriter);
|
|
267
|
-
this._imports.add(Imports.InputFieldMarshaller);
|
|
268
|
-
const allMarshallers = fields.map(field => indentMultiline(this.buildFieldsMarshaller(field), 2));
|
|
269
|
-
return indentMultiline(`@Override
|
|
270
|
-
public InputFieldMarshaller marshaller() {
|
|
271
|
-
return new InputFieldMarshaller() {
|
|
272
|
-
@Override
|
|
273
|
-
public void marshal(InputFieldWriter writer) throws IOException {
|
|
274
|
-
${allMarshallers.join('\n')}
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
}`);
|
|
278
|
-
}
|
|
279
|
-
buildBuilderNestedClass(className, fields) {
|
|
280
|
-
const builderClassName = 'Builder';
|
|
281
|
-
const privateFields = fields
|
|
282
|
-
.map(field => {
|
|
283
|
-
const isArray = field.type.kind === Kind.LIST_TYPE ||
|
|
284
|
-
(field.type.kind === Kind.NON_NULL_TYPE && field.type.type.kind === Kind.LIST_TYPE);
|
|
285
|
-
const fieldType = this.getFieldWithTypePrefix(field, v => (!isArray ? `Input<${v}>` : `Input<List<${v}>>`));
|
|
286
|
-
const isNonNull = field.type.kind === Kind.NON_NULL_TYPE;
|
|
287
|
-
return `private ${fieldType}${isNonNull ? '' : ' = Input.absent()'};`;
|
|
288
|
-
})
|
|
289
|
-
.map(s => indent(s));
|
|
290
|
-
const setters = fields
|
|
291
|
-
.map(field => {
|
|
292
|
-
const isArray = field.type.kind === Kind.LIST_TYPE ||
|
|
293
|
-
(field.type.kind === Kind.NON_NULL_TYPE && field.type.type.kind === Kind.LIST_TYPE);
|
|
294
|
-
const fieldType = this.getFieldWithTypePrefix(field, isArray ? 'List' : null);
|
|
295
|
-
const isNonNull = field.type.kind === Kind.NON_NULL_TYPE;
|
|
296
|
-
return `\npublic ${builderClassName} ${field.name.value}(${isNonNull ? '' : '@Nullable '}${fieldType}) {
|
|
297
|
-
this.${field.name.value} = ${isNonNull ? field.name.value : `Input.fromNullable(${field.name.value})`};
|
|
298
|
-
return this;
|
|
299
|
-
}`;
|
|
300
|
-
})
|
|
301
|
-
.map(s => indentMultiline(s));
|
|
302
|
-
const nonNullFields = fields
|
|
303
|
-
.filter(f => f.type.kind === Kind.NON_NULL_TYPE)
|
|
304
|
-
.map(nnField => {
|
|
305
|
-
this._imports.add(Imports.Utils);
|
|
306
|
-
return indent(`Utils.checkNotNull(${nnField.name.value}, "${nnField.name.value} == null");`, 1);
|
|
307
|
-
});
|
|
308
|
-
const ctor = '\n' + indent(`${builderClassName}() {}`);
|
|
309
|
-
const buildFn = indentMultiline(`public ${className} build() {
|
|
310
|
-
${nonNullFields.join('\n')}
|
|
311
|
-
return new ${className}(${fields.map(f => f.name.value).join(', ')});
|
|
312
|
-
}`);
|
|
313
|
-
const body = [...privateFields, ctor, ...setters, '', buildFn].join('\n');
|
|
314
|
-
return indentMultiline(new JavaDeclarationBlock()
|
|
315
|
-
.withName(builderClassName)
|
|
316
|
-
.access('public')
|
|
317
|
-
.final()
|
|
318
|
-
.static()
|
|
319
|
-
.withBlock(body)
|
|
320
|
-
.asKind('class').string);
|
|
321
|
-
}
|
|
322
|
-
InputObjectTypeDefinition(node) {
|
|
323
|
-
const className = node.name.value;
|
|
324
|
-
this._imports.add(Imports.InputType);
|
|
325
|
-
this._imports.add(Imports.Generated);
|
|
326
|
-
const cls = new JavaDeclarationBlock()
|
|
327
|
-
.annotate([`Generated("Apollo GraphQL")`])
|
|
328
|
-
.access('public')
|
|
329
|
-
.final()
|
|
330
|
-
.asKind('class')
|
|
331
|
-
.withName(className)
|
|
332
|
-
.implements(['InputType']);
|
|
333
|
-
this.addInputMembers(cls, node.fields);
|
|
334
|
-
this.addInputCtor(cls, className, node.fields);
|
|
335
|
-
cls.addClassMethod('builder', 'Builder', 'return new Builder();', [], [], 'public', { static: true });
|
|
336
|
-
const marshallerOverride = this.buildMarshallerOverride(node.fields);
|
|
337
|
-
const builderClass = this.buildBuilderNestedClass(className, node.fields);
|
|
338
|
-
const classBlock = [marshallerOverride, '', builderClass].join('\n');
|
|
339
|
-
cls.withBlock(classBlock);
|
|
340
|
-
return cls.string;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
function visitFieldArguments(selection, imports) {
|
|
345
|
-
if (!selection.arguments || selection.arguments.length === 0) {
|
|
346
|
-
return 'null';
|
|
347
|
-
}
|
|
348
|
-
imports.add(Imports.UnmodifiableMapBuilder);
|
|
349
|
-
imports.add(Imports.String);
|
|
350
|
-
imports.add(Imports.Object);
|
|
351
|
-
return oldVisit(selection, {
|
|
352
|
-
leave: {
|
|
353
|
-
Field: (node) => {
|
|
354
|
-
return (`new UnmodifiableMapBuilder<String, Object>(${node.arguments.length})` + node.arguments.join('') + '.build()');
|
|
355
|
-
},
|
|
356
|
-
Argument: (node) => {
|
|
357
|
-
return `.put("${node.name.value}", ${node.value})`;
|
|
358
|
-
},
|
|
359
|
-
ObjectValue: (node) => {
|
|
360
|
-
return `new UnmodifiableMapBuilder<String, Object>(${node.fields.length})` + node.fields.join('') + '.build()';
|
|
361
|
-
},
|
|
362
|
-
ObjectField: (node) => {
|
|
363
|
-
return `.put("${node.name.value}", ${node.value})`;
|
|
364
|
-
},
|
|
365
|
-
Variable: (node) => {
|
|
366
|
-
return `new UnmodifiableMapBuilder<String, Object>(2).put("kind", "Variable").put("variableName", "${node.name.value}").build()`;
|
|
367
|
-
},
|
|
368
|
-
StringValue: (node) => `"${node.value}"`,
|
|
369
|
-
IntValue: (node) => `"${node.value}"`,
|
|
370
|
-
FloatValue: (node) => `"${node.value}"`,
|
|
371
|
-
},
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
const { singular, isPlural } = pluralize;
|
|
376
|
-
class OperationVisitor extends BaseJavaVisitor {
|
|
11
|
+
export class OperationVisitor extends BaseJavaVisitor {
|
|
377
12
|
constructor(_schema, rawConfig, _availableFragments) {
|
|
378
13
|
super(_schema, rawConfig, {
|
|
379
14
|
package: rawConfig.package || buildPackageNameFromPath(process.cwd()),
|
|
@@ -424,19 +59,17 @@ class OperationVisitor extends BaseJavaVisitor {
|
|
|
424
59
|
if (operation === 'query') {
|
|
425
60
|
return this._schema.getQueryType();
|
|
426
61
|
}
|
|
427
|
-
|
|
62
|
+
if (operation === 'mutation') {
|
|
428
63
|
return this._schema.getMutationType();
|
|
429
64
|
}
|
|
430
|
-
|
|
65
|
+
if (operation === 'subscription') {
|
|
431
66
|
return this._schema.getSubscriptionType();
|
|
432
67
|
}
|
|
433
|
-
|
|
434
|
-
return null;
|
|
435
|
-
}
|
|
68
|
+
return null;
|
|
436
69
|
}
|
|
437
70
|
createUniqueClassName(inUse, name, count = 0) {
|
|
438
71
|
const possibleNewName = count === 0 ? name : `${name}${count}`;
|
|
439
|
-
|
|
72
|
+
if (inUse.includes(possibleNewName)) {
|
|
440
73
|
return this.createUniqueClassName(inUse, name, count + 1);
|
|
441
74
|
}
|
|
442
75
|
return possibleNewName;
|
|
@@ -476,8 +109,8 @@ class OperationVisitor extends BaseJavaVisitor {
|
|
|
476
109
|
const isList = isListType(field.type) || (isNonNullType(field.type) && isListType(field.type.ofType));
|
|
477
110
|
if (isObject) {
|
|
478
111
|
let childClsName = this.convertName(field.name);
|
|
479
|
-
if (isList && isPlural(childClsName)) {
|
|
480
|
-
childClsName = singular(childClsName);
|
|
112
|
+
if (isList && pluralize.isPlural(childClsName)) {
|
|
113
|
+
childClsName = pluralize.singular(childClsName);
|
|
481
114
|
}
|
|
482
115
|
this.transformSelectionSet({
|
|
483
116
|
className: childClsName,
|
|
@@ -503,7 +136,7 @@ class OperationVisitor extends BaseJavaVisitor {
|
|
|
503
136
|
rawType: field.type,
|
|
504
137
|
isObject: false,
|
|
505
138
|
isFragment: false,
|
|
506
|
-
isList
|
|
139
|
+
isList,
|
|
507
140
|
type: baseType,
|
|
508
141
|
isNonNull,
|
|
509
142
|
annotation: fieldAnnotation,
|
|
@@ -819,25 +452,21 @@ ${childFields
|
|
|
819
452
|
if (baseType.name === 'String') {
|
|
820
453
|
return { fn: `readString` };
|
|
821
454
|
}
|
|
822
|
-
|
|
455
|
+
if (baseType.name === 'Int') {
|
|
823
456
|
return { fn: `readInt` };
|
|
824
457
|
}
|
|
825
|
-
|
|
458
|
+
if (baseType.name === 'Float') {
|
|
826
459
|
return { fn: `readDouble` };
|
|
827
460
|
}
|
|
828
|
-
|
|
461
|
+
if (baseType.name === 'Boolean') {
|
|
829
462
|
return { fn: `readBoolean` };
|
|
830
463
|
}
|
|
831
|
-
|
|
832
|
-
return { fn: `readCustomType`, custom: true };
|
|
833
|
-
}
|
|
464
|
+
return { fn: `readCustomType`, custom: true };
|
|
834
465
|
}
|
|
835
|
-
|
|
466
|
+
if (isEnumType(baseType)) {
|
|
836
467
|
return { fn: `readString` };
|
|
837
468
|
}
|
|
838
|
-
|
|
839
|
-
return { fn: `readObject`, object: baseType.name };
|
|
840
|
-
}
|
|
469
|
+
return { fn: `readObject`, object: baseType.name };
|
|
841
470
|
}
|
|
842
471
|
buildMapperClass(parentClassName, childFields) {
|
|
843
472
|
const wrapList = (childField, rawType, edgeStr) => {
|
|
@@ -869,7 +498,7 @@ ${indentMultiline(inner, 2)}
|
|
|
869
498
|
}
|
|
870
499
|
});`;
|
|
871
500
|
}
|
|
872
|
-
|
|
501
|
+
if (f.isList) {
|
|
873
502
|
const listReader = readerFn.object
|
|
874
503
|
? `return listItemReader.${readerFn.fn}(new ResponseReader.ObjectReader<Item>() {
|
|
875
504
|
@Override
|
|
@@ -881,7 +510,7 @@ ${indentMultiline(inner, 2)}
|
|
|
881
510
|
const wrappedList = wrapList(f, f.rawType, listReader);
|
|
882
511
|
return `${varDec} reader.readList($responseFields[${index}], ${wrappedList});`;
|
|
883
512
|
}
|
|
884
|
-
|
|
513
|
+
if (readerFn.object) {
|
|
885
514
|
return `${varDec} reader.readObject($responseFields[${index}], new ResponseReader.ObjectReader<${f.className}>() {
|
|
886
515
|
@Override
|
|
887
516
|
public ${f.className} read(ResponseReader reader) {
|
|
@@ -889,9 +518,7 @@ ${indentMultiline(inner, 2)}
|
|
|
889
518
|
}
|
|
890
519
|
});`;
|
|
891
520
|
}
|
|
892
|
-
|
|
893
|
-
return `${varDec} reader.${readerFn.fn}(${readerFn.custom ? '(ResponseField.CustomTypeField) ' : ''}$responseFields[${index}]);`;
|
|
894
|
-
}
|
|
521
|
+
return `${varDec} reader.${readerFn.fn}(${readerFn.custom ? '(ResponseField.CustomTypeField) ' : ''}$responseFields[${index}]);`;
|
|
895
522
|
});
|
|
896
523
|
const mapperImpl = [
|
|
897
524
|
...mapperBody,
|
|
@@ -921,33 +548,29 @@ ${indentMultiline(inner, 2)}
|
|
|
921
548
|
if (isListType(baseType)) {
|
|
922
549
|
return { fn: `forList` };
|
|
923
550
|
}
|
|
924
|
-
|
|
551
|
+
if (isNonNullType(baseType)) {
|
|
925
552
|
return this._resolveResponseFieldMethodForBaseType(baseType.ofType);
|
|
926
553
|
}
|
|
927
|
-
|
|
554
|
+
if (isScalarType(baseType)) {
|
|
928
555
|
if (baseType.name === 'String') {
|
|
929
556
|
return { fn: `forString` };
|
|
930
557
|
}
|
|
931
|
-
|
|
558
|
+
if (baseType.name === 'Int') {
|
|
932
559
|
return { fn: `forInt` };
|
|
933
560
|
}
|
|
934
|
-
|
|
561
|
+
if (baseType.name === 'Float') {
|
|
935
562
|
return { fn: `forDouble` };
|
|
936
563
|
}
|
|
937
|
-
|
|
564
|
+
if (baseType.name === 'Boolean') {
|
|
938
565
|
return { fn: `forBoolean` };
|
|
939
566
|
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
return { fn: `forCustomType`, custom: true };
|
|
943
|
-
}
|
|
567
|
+
this._imports.add(`${this.config.typePackage}.CustomType`);
|
|
568
|
+
return { fn: `forCustomType`, custom: true };
|
|
944
569
|
}
|
|
945
|
-
|
|
570
|
+
if (isEnumType(baseType)) {
|
|
946
571
|
return { fn: `forEnum` };
|
|
947
572
|
}
|
|
948
|
-
|
|
949
|
-
return { fn: `forObject` };
|
|
950
|
-
}
|
|
573
|
+
return { fn: `forObject` };
|
|
951
574
|
}
|
|
952
575
|
FragmentDefinition(node) {
|
|
953
576
|
this.visitingFragment = true;
|
|
@@ -962,12 +585,12 @@ ${indentMultiline(inner, 2)}
|
|
|
962
585
|
this._imports.add(Imports.Generated);
|
|
963
586
|
this._imports.add(Imports.ResponseFieldMapper);
|
|
964
587
|
const dataClasses = this.transformSelectionSet({
|
|
965
|
-
className
|
|
588
|
+
className,
|
|
966
589
|
nonStaticClass: true,
|
|
967
590
|
implements: ['GraphqlFragment'],
|
|
968
591
|
selectionSet: node.selectionSet && node.selectionSet.selections ? node.selectionSet.selections : [],
|
|
969
592
|
result: {},
|
|
970
|
-
schemaType
|
|
593
|
+
schemaType,
|
|
971
594
|
}, false);
|
|
972
595
|
const rootCls = dataClasses[className];
|
|
973
596
|
const printed = this.printDocument(node);
|
|
@@ -1106,13 +729,13 @@ ${variables
|
|
|
1106
729
|
}
|
|
1107
730
|
return { name: 'writeCustom', checkNull: false, useMarshaller: false, castTo: 'ResponseField.CustomTypeField' };
|
|
1108
731
|
}
|
|
1109
|
-
|
|
732
|
+
if (isInputObjectType(schemaType)) {
|
|
1110
733
|
return { name: 'writeObject', checkNull: true, useMarshaller: true };
|
|
1111
734
|
}
|
|
1112
|
-
|
|
735
|
+
if (isEnumType(schemaType)) {
|
|
1113
736
|
return { name: 'writeString', checkNull: false, useMarshaller: false };
|
|
1114
737
|
}
|
|
1115
|
-
|
|
738
|
+
if (isObjectType(schemaType) || isInterfaceType(schemaType)) {
|
|
1116
739
|
return { name: 'writeObject', checkNull: true, useMarshaller: true };
|
|
1117
740
|
}
|
|
1118
741
|
return { name: 'writeString', useMarshaller: false, checkNull: false };
|
|
@@ -1150,208 +773,3 @@ ${variables
|
|
|
1150
773
|
return cls;
|
|
1151
774
|
}
|
|
1152
775
|
}
|
|
1153
|
-
|
|
1154
|
-
var FileType;
|
|
1155
|
-
(function (FileType) {
|
|
1156
|
-
FileType[FileType["INPUT_TYPE"] = 0] = "INPUT_TYPE";
|
|
1157
|
-
FileType[FileType["OPERATION"] = 1] = "OPERATION";
|
|
1158
|
-
FileType[FileType["FRAGMENT"] = 2] = "FRAGMENT";
|
|
1159
|
-
FileType[FileType["CUSTOM_TYPES"] = 3] = "CUSTOM_TYPES";
|
|
1160
|
-
})(FileType || (FileType = {}));
|
|
1161
|
-
|
|
1162
|
-
const filteredScalars = ['String', 'Float', 'Int', 'Boolean'];
|
|
1163
|
-
class CustomTypeClassVisitor extends BaseJavaVisitor {
|
|
1164
|
-
constructor(schema, rawConfig) {
|
|
1165
|
-
super(schema, rawConfig, {
|
|
1166
|
-
typePackage: rawConfig.typePackage || 'type',
|
|
1167
|
-
});
|
|
1168
|
-
}
|
|
1169
|
-
extract(name) {
|
|
1170
|
-
const lastIndex = name.lastIndexOf('.');
|
|
1171
|
-
if (lastIndex === -1) {
|
|
1172
|
-
return {
|
|
1173
|
-
className: name,
|
|
1174
|
-
importFrom: Imports[name] || null,
|
|
1175
|
-
};
|
|
1176
|
-
}
|
|
1177
|
-
else {
|
|
1178
|
-
return {
|
|
1179
|
-
className: name.substring(lastIndex + 1),
|
|
1180
|
-
importFrom: name,
|
|
1181
|
-
};
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
additionalContent() {
|
|
1185
|
-
this._imports.add(Imports.ScalarType);
|
|
1186
|
-
this._imports.add(Imports.Class);
|
|
1187
|
-
this._imports.add(Imports.Override);
|
|
1188
|
-
this._imports.add(Imports.Generated);
|
|
1189
|
-
const allTypes = this._schema.getTypeMap();
|
|
1190
|
-
const enumValues = Object.keys(allTypes)
|
|
1191
|
-
.filter(t => isScalarType(allTypes[t]) && !filteredScalars.includes(t))
|
|
1192
|
-
.map(t => allTypes[t])
|
|
1193
|
-
.map(scalarType => {
|
|
1194
|
-
const uppercaseName = scalarType.name.toUpperCase();
|
|
1195
|
-
const javaType = this.extract(this.scalars[scalarType.name] || 'String');
|
|
1196
|
-
if (javaType.importFrom) {
|
|
1197
|
-
this._imports.add(javaType.importFrom);
|
|
1198
|
-
}
|
|
1199
|
-
return indentMultiline(`${uppercaseName} {
|
|
1200
|
-
@Override
|
|
1201
|
-
public String typeName() {
|
|
1202
|
-
return "${scalarType.name}";
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
@Override
|
|
1206
|
-
public Class javaType() {
|
|
1207
|
-
return ${javaType.className}.class;
|
|
1208
|
-
}
|
|
1209
|
-
}`);
|
|
1210
|
-
})
|
|
1211
|
-
.join(',\n\n');
|
|
1212
|
-
return new JavaDeclarationBlock()
|
|
1213
|
-
.annotate([`Generated("Apollo GraphQL")`])
|
|
1214
|
-
.access('public')
|
|
1215
|
-
.asKind('enum')
|
|
1216
|
-
.withName('CustomType')
|
|
1217
|
-
.implements(['ScalarType'])
|
|
1218
|
-
.withBlock(enumValues).string;
|
|
1219
|
-
}
|
|
1220
|
-
getPackage() {
|
|
1221
|
-
return this.config.typePackage;
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
const plugin = (schema, documents, config) => {
|
|
1226
|
-
const allAst = concatAST(documents.map(v => v.document));
|
|
1227
|
-
const allFragments = [
|
|
1228
|
-
...allAst.definitions.filter(d => d.kind === Kind.FRAGMENT_DEFINITION).map(fragmentDef => ({
|
|
1229
|
-
node: fragmentDef,
|
|
1230
|
-
name: fragmentDef.name.value,
|
|
1231
|
-
onType: fragmentDef.typeCondition.name.value,
|
|
1232
|
-
isExternal: false,
|
|
1233
|
-
})),
|
|
1234
|
-
...(config.externalFragments || []),
|
|
1235
|
-
];
|
|
1236
|
-
let visitor;
|
|
1237
|
-
switch (config.fileType) {
|
|
1238
|
-
case FileType.FRAGMENT:
|
|
1239
|
-
case FileType.OPERATION: {
|
|
1240
|
-
visitor = new OperationVisitor(schema, config, allFragments);
|
|
1241
|
-
break;
|
|
1242
|
-
}
|
|
1243
|
-
case FileType.INPUT_TYPE: {
|
|
1244
|
-
visitor = new InputTypeVisitor(schema, config);
|
|
1245
|
-
break;
|
|
1246
|
-
}
|
|
1247
|
-
case FileType.CUSTOM_TYPES: {
|
|
1248
|
-
visitor = new CustomTypeClassVisitor(schema, config);
|
|
1249
|
-
break;
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
|
-
if (!visitor) {
|
|
1253
|
-
return { content: '' };
|
|
1254
|
-
}
|
|
1255
|
-
const visitResult = oldVisit(allAst, visitor);
|
|
1256
|
-
const additionalContent = visitor.additionalContent();
|
|
1257
|
-
const imports = visitor.getImports();
|
|
1258
|
-
return {
|
|
1259
|
-
prepend: [`package ${visitor.getPackage()};\n`, ...imports],
|
|
1260
|
-
content: '\n' + [...visitResult.definitions.filter(a => a && typeof a === 'string'), additionalContent].join('\n'),
|
|
1261
|
-
};
|
|
1262
|
-
};
|
|
1263
|
-
|
|
1264
|
-
const packageNameToDirectory = (packageName) => {
|
|
1265
|
-
return `./${packageName.split('.').join('/')}/`;
|
|
1266
|
-
};
|
|
1267
|
-
const preset = {
|
|
1268
|
-
buildGeneratesSection: options => {
|
|
1269
|
-
const outDir = options.baseOutputDir;
|
|
1270
|
-
const inputTypesAst = [];
|
|
1271
|
-
visit(options.schema, {
|
|
1272
|
-
InputObjectTypeDefinition: {
|
|
1273
|
-
enter(node) {
|
|
1274
|
-
inputTypesAst.push(node);
|
|
1275
|
-
},
|
|
1276
|
-
},
|
|
1277
|
-
});
|
|
1278
|
-
const inputTypesDocumentNode = { kind: Kind.DOCUMENT, definitions: inputTypesAst };
|
|
1279
|
-
const allAst = concatAST(options.documents.map(v => v.document));
|
|
1280
|
-
const operationsAst = allAst.definitions.filter(d => d.kind === Kind.OPERATION_DEFINITION);
|
|
1281
|
-
const fragments = allAst.definitions.filter(d => d.kind === Kind.FRAGMENT_DEFINITION);
|
|
1282
|
-
const externalFragments = fragments.map(frag => ({
|
|
1283
|
-
isExternal: true,
|
|
1284
|
-
importFrom: frag.name.value,
|
|
1285
|
-
name: frag.name.value,
|
|
1286
|
-
onType: frag.typeCondition.name.value,
|
|
1287
|
-
node: frag,
|
|
1288
|
-
}));
|
|
1289
|
-
return [
|
|
1290
|
-
{
|
|
1291
|
-
filename: join(outDir, packageNameToDirectory(options.config.typePackage), 'CustomType.java'),
|
|
1292
|
-
plugins: options.plugins,
|
|
1293
|
-
pluginMap: options.pluginMap,
|
|
1294
|
-
config: {
|
|
1295
|
-
...options.config,
|
|
1296
|
-
fileType: FileType.CUSTOM_TYPES,
|
|
1297
|
-
},
|
|
1298
|
-
schema: options.schema,
|
|
1299
|
-
documents: [],
|
|
1300
|
-
cache: options.cache,
|
|
1301
|
-
},
|
|
1302
|
-
...inputTypesDocumentNode.definitions.map((ast) => {
|
|
1303
|
-
const document = { kind: Kind.DOCUMENT, definitions: [ast] };
|
|
1304
|
-
return {
|
|
1305
|
-
filename: join(outDir, packageNameToDirectory(options.config.typePackage), ast.name.value + '.java'),
|
|
1306
|
-
plugins: options.plugins,
|
|
1307
|
-
pluginMap: options.pluginMap,
|
|
1308
|
-
config: {
|
|
1309
|
-
...options.config,
|
|
1310
|
-
fileType: FileType.INPUT_TYPE,
|
|
1311
|
-
skipDocumentsValidation: true,
|
|
1312
|
-
},
|
|
1313
|
-
schema: options.schema,
|
|
1314
|
-
documents: [{ document, location: '' }],
|
|
1315
|
-
cache: options.cache,
|
|
1316
|
-
};
|
|
1317
|
-
}),
|
|
1318
|
-
...operationsAst.map((ast) => {
|
|
1319
|
-
const fileName = ast.name.value.toLowerCase().endsWith(ast.operation)
|
|
1320
|
-
? ast.name.value
|
|
1321
|
-
: `${ast.name.value}${pascalCase(ast.operation)}`;
|
|
1322
|
-
const document = { kind: Kind.DOCUMENT, definitions: [ast] };
|
|
1323
|
-
return {
|
|
1324
|
-
filename: join(outDir, packageNameToDirectory(options.config.package), fileName + '.java'),
|
|
1325
|
-
plugins: options.plugins,
|
|
1326
|
-
pluginMap: options.pluginMap,
|
|
1327
|
-
config: {
|
|
1328
|
-
...options.config,
|
|
1329
|
-
fileType: FileType.OPERATION,
|
|
1330
|
-
externalFragments,
|
|
1331
|
-
},
|
|
1332
|
-
schema: options.schema,
|
|
1333
|
-
documents: [{ document, location: '' }],
|
|
1334
|
-
cache: options.cache,
|
|
1335
|
-
};
|
|
1336
|
-
}),
|
|
1337
|
-
...fragments.map((ast) => {
|
|
1338
|
-
const document = { kind: Kind.DOCUMENT, definitions: [ast] };
|
|
1339
|
-
return {
|
|
1340
|
-
filename: join(outDir, packageNameToDirectory(options.config.fragmentPackage), ast.name.value + '.java'),
|
|
1341
|
-
plugins: options.plugins,
|
|
1342
|
-
pluginMap: options.pluginMap,
|
|
1343
|
-
config: {
|
|
1344
|
-
...options.config,
|
|
1345
|
-
fileType: FileType.FRAGMENT,
|
|
1346
|
-
externalFragments,
|
|
1347
|
-
},
|
|
1348
|
-
schema: options.schema,
|
|
1349
|
-
documents: [{ document, location: '' }],
|
|
1350
|
-
cache: options.cache,
|
|
1351
|
-
};
|
|
1352
|
-
}),
|
|
1353
|
-
];
|
|
1354
|
-
},
|
|
1355
|
-
};
|
|
1356
|
-
|
|
1357
|
-
export { plugin, preset };
|