UNPKG

8.56 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5const graphql = require('graphql');
6const visitorPluginCommon = require('@graphql-codegen/visitor-plugin-common');
7const javaCommon = require('@graphql-codegen/java-common');
8const path = require('path');
9
10const KOTLIN_SCALARS = {
11 ID: 'Any',
12 String: 'String',
13 Boolean: 'Boolean',
14 Int: 'Int',
15 Float: 'Float',
16};
17class 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 // language=kotlin
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 // language=kotlin
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 // Variable
159 // ObjectValue
160 // ObjectField
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
200const 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
212exports.plugin = plugin;
213//# sourceMappingURL=index.cjs.js.map