1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | const graphql = require('graphql');
|
6 | const visitorPluginCommon = require('@graphql-codegen/visitor-plugin-common');
|
7 | const javaCommon = require('@graphql-codegen/java-common');
|
8 | const path = require('path');
|
9 |
|
10 | const KOTLIN_SCALARS = {
|
11 | ID: 'Any',
|
12 | String: 'String',
|
13 | Boolean: 'Boolean',
|
14 | Int: 'Int',
|
15 | Float: 'Float',
|
16 | };
|
17 | class KotlinResolversVisitor extends visitorPluginCommon.BaseVisitor {
|
18 | constructor(rawConfig, _schema, defaultPackageName) {
|
19 | super(rawConfig, {
|
20 | enumValues: rawConfig.enumValues || {},
|
21 | listType: rawConfig.listType || 'Iterable',
|
22 | withTypes: rawConfig.withTypes || false,
|
23 | package: rawConfig.package || defaultPackageName,
|
24 | scalars: visitorPluginCommon.buildScalars(_schema, rawConfig.scalars, KOTLIN_SCALARS),
|
25 | });
|
26 | this._schema = _schema;
|
27 | }
|
28 | getPackageName() {
|
29 | return `package ${this.config.package}\n`;
|
30 | }
|
31 | getEnumValue(enumName, enumOption) {
|
32 | if (this.config.enumValues[enumName] &&
|
33 | typeof this.config.enumValues[enumName] === 'object' &&
|
34 | this.config.enumValues[enumName][enumOption]) {
|
35 | return this.config.enumValues[enumName][enumOption];
|
36 | }
|
37 | return enumOption;
|
38 | }
|
39 | EnumValueDefinition(node) {
|
40 | return (enumName) => {
|
41 | return visitorPluginCommon.indent(`${this.convertName(node, { useTypesPrefix: false, transformUnderscore: true })}("${this.getEnumValue(enumName, node.name.value)}")`);
|
42 | };
|
43 | }
|
44 | EnumTypeDefinition(node) {
|
45 | const comment = visitorPluginCommon.transformComment(node.description, 0);
|
46 | const enumName = this.convertName(node.name);
|
47 | const enumValues = visitorPluginCommon.indentMultiline(node.values.map(enumValue => enumValue(node.name.value)).join(',\n') + ';', 2);
|
48 | return `${comment}enum class ${enumName}(val label: String) {
|
49 | ${enumValues}
|
50 |
|
51 | companion object {
|
52 | @JvmStatic
|
53 | fun valueOfLabel(label: String): ${enumName}? {
|
54 | return values().find { it.label == label }
|
55 | }
|
56 | }
|
57 | }`;
|
58 | }
|
59 | resolveInputFieldType(typeNode) {
|
60 | const innerType = visitorPluginCommon.getBaseTypeNode(typeNode);
|
61 | const schemaType = this._schema.getType(innerType.name.value);
|
62 | const isArray = typeNode.kind === graphql.Kind.LIST_TYPE ||
|
63 | (typeNode.kind === graphql.Kind.NON_NULL_TYPE && typeNode.type.kind === graphql.Kind.LIST_TYPE);
|
64 | let result = null;
|
65 | const nullable = typeNode.kind !== graphql.Kind.NON_NULL_TYPE;
|
66 | if (graphql.isScalarType(schemaType)) {
|
67 | if (this.config.scalars[schemaType.name]) {
|
68 | result = {
|
69 | baseType: this.scalars[schemaType.name],
|
70 | typeName: this.scalars[schemaType.name],
|
71 | isScalar: true,
|
72 | isArray,
|
73 | nullable: nullable,
|
74 | };
|
75 | }
|
76 | else {
|
77 | result = { isArray, baseType: 'Any', typeName: 'Any', isScalar: true, nullable: nullable };
|
78 | }
|
79 | }
|
80 | else if (graphql.isInputObjectType(schemaType)) {
|
81 | const convertedName = this.convertName(schemaType.name);
|
82 | const typeName = convertedName.endsWith('Input') ? convertedName : `${convertedName}Input`;
|
83 | result = {
|
84 | baseType: typeName,
|
85 | typeName: typeName,
|
86 | isScalar: false,
|
87 | isArray,
|
88 | nullable: nullable,
|
89 | };
|
90 | }
|
91 | else if (graphql.isEnumType(schemaType) || graphql.isObjectType(schemaType)) {
|
92 | result = {
|
93 | isArray,
|
94 | baseType: this.convertName(schemaType.name),
|
95 | typeName: this.convertName(schemaType.name),
|
96 | isScalar: true,
|
97 | nullable: nullable,
|
98 | };
|
99 | }
|
100 | else {
|
101 | result = { isArray, baseType: 'Any', typeName: 'Any', isScalar: true, nullable: nullable };
|
102 | }
|
103 | if (result) {
|
104 | result.typeName = javaCommon.wrapTypeWithModifiers(result.typeName, typeNode, this.config.listType);
|
105 | }
|
106 | return result;
|
107 | }
|
108 | buildInputTransfomer(name, inputValueArray) {
|
109 | const classMembers = inputValueArray
|
110 | .map(arg => {
|
111 | const typeToUse = this.resolveInputFieldType(arg.type);
|
112 | const initialValue = this.initialValue(typeToUse.typeName, arg.defaultValue);
|
113 | const initial = initialValue ? ` = ${initialValue}` : typeToUse.nullable ? ' = null' : '';
|
114 | return visitorPluginCommon.indent(`val ${arg.name.value}: ${typeToUse.typeName}${typeToUse.nullable ? '?' : ''}${initial}`, 2);
|
115 | })
|
116 | .join(',\n');
|
117 |
|
118 | return `data class ${name}(
|
119 | ${classMembers}
|
120 | )`;
|
121 | }
|
122 | buildTypeTransfomer(name, typeValueArray) {
|
123 | const classMembers = typeValueArray
|
124 | .map(arg => {
|
125 | if (!arg.type) {
|
126 | return '';
|
127 | }
|
128 | const typeToUse = this.resolveInputFieldType(arg.type);
|
129 | return visitorPluginCommon.indent(`val ${arg.name.value}: ${typeToUse.typeName}${typeToUse.nullable ? '?' : ''}`, 2);
|
130 | })
|
131 | .join(',\n');
|
132 |
|
133 | return `data class ${name}(
|
134 | ${classMembers}
|
135 | )`;
|
136 | }
|
137 | initialValue(typeName, defaultValue) {
|
138 | if (defaultValue) {
|
139 | if (defaultValue.kind === 'IntValue' ||
|
140 | defaultValue.kind === 'FloatValue' ||
|
141 | defaultValue.kind === 'BooleanValue') {
|
142 | return `${defaultValue.value}`;
|
143 | }
|
144 | else if (defaultValue.kind === 'StringValue') {
|
145 | return `"""${defaultValue.value}""".trimIndent()`;
|
146 | }
|
147 | else if (defaultValue.kind === 'EnumValue') {
|
148 | return `${typeName}.${defaultValue.value}`;
|
149 | }
|
150 | else if (defaultValue.kind === 'ListValue') {
|
151 | const list = defaultValue.values
|
152 | .map(value => {
|
153 | return this.initialValue(typeName, value);
|
154 | })
|
155 | .join(', ');
|
156 | return `listOf(${list})`;
|
157 | }
|
158 |
|
159 |
|
160 |
|
161 | }
|
162 | return undefined;
|
163 | }
|
164 | FieldDefinition(node) {
|
165 | if (node.arguments.length > 0) {
|
166 | const inputTransformer = (typeName) => {
|
167 | const transformerName = `${this.convertName(typeName, { useTypesPrefix: true })}${this.convertName(node.name.value, { useTypesPrefix: false })}Args`;
|
168 | return this.buildInputTransfomer(transformerName, node.arguments);
|
169 | };
|
170 | return { node, inputTransformer };
|
171 | }
|
172 | return { node };
|
173 | }
|
174 | InputObjectTypeDefinition(node) {
|
175 | const convertedName = this.convertName(node);
|
176 | const name = convertedName.endsWith('Input') ? convertedName : `${convertedName}Input`;
|
177 | return this.buildInputTransfomer(name, node.fields);
|
178 | }
|
179 | ObjectTypeDefinition(node) {
|
180 | const name = this.convertName(node);
|
181 | const fields = node.fields;
|
182 | const fieldNodes = [];
|
183 | const argsTypes = [];
|
184 | fields.forEach(({ node, inputTransformer }) => {
|
185 | if (node) {
|
186 | fieldNodes.push(node);
|
187 | }
|
188 | if (inputTransformer) {
|
189 | argsTypes.push(inputTransformer);
|
190 | }
|
191 | });
|
192 | let types = argsTypes.map(f => f(node.name.value)).filter(r => r);
|
193 | if (this.config.withTypes) {
|
194 | types = types.concat([this.buildTypeTransfomer(name, fieldNodes)]);
|
195 | }
|
196 | return types.join('\n');
|
197 | }
|
198 | }
|
199 |
|
200 | const plugin = async (schema, documents, config, { outputFile }) => {
|
201 | const relevantPath = path.dirname(path.normalize(outputFile));
|
202 | const defaultPackageName = javaCommon.buildPackageNameFromPath(relevantPath);
|
203 | const visitor = new KotlinResolversVisitor(config, schema, defaultPackageName);
|
204 | const printedSchema = graphql.printSchema(schema);
|
205 | const astNode = graphql.parse(printedSchema);
|
206 | const visitorResult = graphql.visit(astNode, { leave: visitor });
|
207 | const packageName = visitor.getPackageName();
|
208 | const blockContent = visitorResult.definitions.filter(d => typeof d === 'string').join('\n\n');
|
209 | return [packageName, blockContent].join('\n');
|
210 | };
|
211 |
|
212 | exports.plugin = plugin;
|
213 |
|