@goast/kotlin 0.0.1 → 0.0.2

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.
Files changed (22) hide show
  1. package/cjs/lib/generators/index.js +1 -0
  2. package/cjs/lib/generators/models/model-generator.js +77 -25
  3. package/cjs/lib/generators/services/okhttp3-clients/index.js +6 -0
  4. package/cjs/lib/generators/services/okhttp3-clients/models.js +5 -0
  5. package/cjs/lib/generators/services/okhttp3-clients/okhttp3-client-generator.js +404 -0
  6. package/cjs/lib/generators/services/okhttp3-clients/okhttp3-clients-generator.js +48 -0
  7. package/cjs/lib/generators/services/spring-controllers/spring-controller-generator.js +15 -42
  8. package/esm/lib/generators/index.js +1 -0
  9. package/esm/lib/generators/models/model-generator.js +77 -25
  10. package/esm/lib/generators/services/okhttp3-clients/index.js +3 -0
  11. package/esm/lib/generators/services/okhttp3-clients/models.js +2 -0
  12. package/esm/lib/generators/services/okhttp3-clients/okhttp3-client-generator.js +400 -0
  13. package/esm/lib/generators/services/okhttp3-clients/okhttp3-clients-generator.js +44 -0
  14. package/esm/lib/generators/services/spring-controllers/spring-controller-generator.js +15 -42
  15. package/package.json +2 -2
  16. package/types/lib/file-builder.d.ts +1 -1
  17. package/types/lib/generators/index.d.ts +1 -0
  18. package/types/lib/generators/models/model-generator.d.ts +9 -3
  19. package/types/lib/generators/services/okhttp3-clients/index.d.ts +3 -0
  20. package/types/lib/generators/services/okhttp3-clients/models.d.ts +21 -0
  21. package/types/lib/generators/services/okhttp3-clients/okhttp3-client-generator.d.ts +59 -0
  22. package/types/lib/generators/services/okhttp3-clients/okhttp3-clients-generator.d.ts +20 -0
@@ -3,4 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./file-generator"), exports);
5
5
  tslib_1.__exportStar(require("./models"), exports);
6
+ tslib_1.__exportStar(require("./services/okhttp3-clients"), exports);
6
7
  tslib_1.__exportStar(require("./services/spring-controllers"), exports);
@@ -77,26 +77,77 @@ class DefaultKotlinModelGenerator extends file_generator_1.KotlinFileGenerator {
77
77
  }
78
78
  }
79
79
  else {
80
- this.generateDataClass(ctx, builder, schema);
80
+ this.generateObjectPackageMember(ctx, builder, schema);
81
81
  }
82
82
  }
83
- generateDataClass(ctx, builder, schema) {
83
+ generateObjectPackageMember(ctx, builder, schema) {
84
+ if (schema.discriminator) {
85
+ this.generateObjectInterface(ctx, builder, schema);
86
+ }
87
+ else {
88
+ this.generateObjectDataClass(ctx, builder, schema);
89
+ }
90
+ }
91
+ generateObjectInterface(ctx, builder, schema) {
92
+ builder
93
+ .apply((builder) => this.generateDocumentation(ctx, builder, schema))
94
+ .ensureCurrentLineEmpty()
95
+ .apply((builder) => this.generateObjectInterfaceAnnotations(ctx, builder, schema))
96
+ .ensureCurrentLineEmpty()
97
+ .apply((builder) => this.generateObjectInterfaceSignature(ctx, builder, schema))
98
+ .append(' ')
99
+ .parenthesizeMultiline('{}', (builder) => this.generateObjectInterfaceMembers(ctx, builder, schema));
100
+ }
101
+ generateObjectInterfaceAnnotations(ctx, builder, schema) {
102
+ if (schema.discriminator) {
103
+ builder.appendAnnotation('JsonTypeInfo', 'com.fasterxml.jackson.annotation', [
104
+ ['use', 'JsonTypeInfo.Id.NAME'],
105
+ ['include', 'JsonTypeInfo.As.PROPERTY'],
106
+ ['property', this.toStringLiteral(ctx, schema.discriminator.propertyName)],
107
+ ['visible', 'true'],
108
+ ]);
109
+ const entries = Object.entries(schema.discriminator.mapping);
110
+ if (entries.length > 0) {
111
+ builder.appendAnnotation('JsonSubTypes', 'com.fasterxml.jackson.annotation', entries.map(([value, schema]) => (builder) => {
112
+ const schemaResult = ctx.getSchemaResult(schema);
113
+ builder
114
+ .append(`JsonSubTypes.Type(value = ${schemaResult.typeName}::class, name = ${this.toStringLiteral(ctx, value)})`)
115
+ .addImport(schemaResult.typeName, schemaResult.packageName);
116
+ }));
117
+ }
118
+ }
119
+ }
120
+ generateObjectInterfaceSignature(ctx, builder, schema) {
121
+ builder.append('interface ').append(this.getDeclarationTypeName(ctx));
122
+ }
123
+ generateObjectInterfaceMembers(ctx, builder, schema) {
124
+ builder.forEach(this.sortProperties(ctx, schema, schema.properties.values()), (builder, property) => builder
125
+ .ensurePreviousLineEmpty()
126
+ .apply((builder) => this.generateJsonPropertyAnnotation(ctx, builder, schema, property, 'get'))
127
+ .ensureCurrentLineEmpty()
128
+ .append(`val ${(0, core_1.toCasing)(property.name, 'camel')}: `)
129
+ .apply((builder) => this.generateType(ctx, builder, property.schema))
130
+ .applyIf(!schema.required.has(property.name), (builder) => builder.appendIf(!property.schema.nullable, '?').append(' = null')));
131
+ }
132
+ generateObjectDataClass(ctx, builder, schema) {
133
+ const inheritedSchemas = schema.inheritedSchemas.filter((x) => this.shouldGenerateTypeDeclaration(ctx, x) && !x.isNameGenerated);
84
134
  builder
85
135
  .apply((builder) => this.generateDocumentation(ctx, builder, schema))
86
136
  .append('data class ')
87
137
  .append(this.getDeclarationTypeName(ctx))
88
- .parenthesizeIf(schema.properties.size > 0, '()', (builder) => builder
89
- .appendLine()
90
- .forEachSeparated(this.sortProperties(ctx, schema, schema.properties.values()), ',\n', (builder, property) => builder
138
+ .parenthesizeMultilineIf(schema.properties.size > 0, '()', (builder) => builder.forEachSeparated(this.sortProperties(ctx, schema, schema.properties.values()), ',\n', (builder, property) => builder
91
139
  .ensurePreviousLineEmpty()
92
- .apply((builder) => this.generatePropertyAnnotations(ctx, builder, schema, property))
140
+ .apply((builder) => this.generateObjectDataClassParameterAnnotations(ctx, builder, schema, property))
141
+ .appendIf(inheritedSchemas.some((x) => this.hasProperty(ctx, x, property.name)), 'override ')
93
142
  .append(`val ${(0, core_1.toCasing)(property.name, 'camel')}: `)
94
143
  .apply((builder) => this.generateType(ctx, builder, property.schema))
95
- .applyIf(!schema.required.has(property.name), (builder) => builder.appendIf(!property.schema.nullable, '?').append(' = null')))
96
- .appendLineIf(schema.properties.size > 0))
97
- .parenthesizeIf(schema.additionalProperties !== undefined && schema.additionalProperties !== false, '{}', (builder) => builder
98
- .appendLine()
99
- .applyIf(schema.additionalProperties !== undefined && schema.additionalProperties !== false, (builder) => builder
144
+ .applyIf(!schema.required.has(property.name), (builder) => builder.appendIf(!property.schema.nullable, '?').append(' = null'))))
145
+ .applyIf(inheritedSchemas.length > 0, (builder) => builder
146
+ .append(' : ')
147
+ .forEachSeparated(inheritedSchemas, ', ', (builder, schema) => builder.append((0, core_1.toCasing)(schema.name, 'pascal'))) // TODO: Calling generateType here will lead to endless loop
148
+ )
149
+ .append(' ')
150
+ .parenthesizeMultilineIf(schema.additionalProperties !== undefined && schema.additionalProperties !== false, '{}', (builder) => builder.applyIf(schema.additionalProperties !== undefined && schema.additionalProperties !== false, (builder) => builder
100
151
  .appendLine('@JsonIgnore')
101
152
  .addImport('JsonIgnore', 'com.fasterxml.jackson.annotation')
102
153
  .append('val additionalProperties: Mutable')
@@ -108,7 +159,7 @@ class DefaultKotlinModelGenerator extends file_generator_1.KotlinFileGenerator {
108
159
  .append('fun set')
109
160
  .parenthesize('()', (builder) => builder.append('name: String, value: ').applyIfElse(schema.additionalProperties === true, (builder) => builder.append('Any?'), (builder) => this.generateType(ctx, builder, schema.additionalProperties)))
110
161
  .append(' ')
111
- .parenthesize('{}', (builder) => builder.appendLine().appendLine('this.additionalProperties[name] = value'))
162
+ .parenthesizeMultiline('{}', 'this.additionalProperties[name] = value')
112
163
  .appendLine()
113
164
  .appendLine()
114
165
  .appendLine('@JsonAnyGetter')
@@ -116,10 +167,9 @@ class DefaultKotlinModelGenerator extends file_generator_1.KotlinFileGenerator {
116
167
  .append('fun getMap(): ')
117
168
  .apply((builder) => this.generateMapType(ctx, builder, schema))
118
169
  .append(' ')
119
- .parenthesize('{}', (builder) => builder.appendLine().appendLine('return this.additionalProperties'))
120
- .appendLine()));
170
+ .parenthesizeMultiline('{}', 'return this.additionalProperties')));
121
171
  }
122
- generatePropertyAnnotations(ctx, builder, schema, property) {
172
+ generateObjectDataClassParameterAnnotations(ctx, builder, schema, property) {
123
173
  this.generatePropertyValidationAnnotations(ctx, builder, schema, property);
124
174
  this.generatePropertySchemaAnnotation(ctx, builder, schema, property);
125
175
  this.generateJsonPropertyAnnotation(ctx, builder, schema, property);
@@ -154,9 +204,9 @@ class DefaultKotlinModelGenerator extends file_generator_1.KotlinFileGenerator {
154
204
  .parenthesizeIf(parts.size > 0, '()', (builder) => builder.forEachSeparated(parts.entries(), ', ', (builder, [key, value]) => builder.append(`${key} = ${value}`)))
155
205
  .appendLine();
156
206
  }
157
- generateJsonPropertyAnnotation(ctx, builder, schema, property) {
207
+ generateJsonPropertyAnnotation(ctx, builder, schema, property, scope) {
158
208
  builder
159
- .append('@JsonProperty')
209
+ .append(`@${scope ? scope + ':' : ''}JsonProperty`)
160
210
  .addImport('JsonProperty', 'com.fasterxml.jackson.annotation')
161
211
  .parenthesize('()', (builder) => builder
162
212
  .append(this.toStringLiteral(ctx, property.name))
@@ -165,7 +215,7 @@ class DefaultKotlinModelGenerator extends file_generator_1.KotlinFileGenerator {
165
215
  .applyIf(property.schema.custom['exclude-when-null'] === true, (builder) => builder
166
216
  .append('@get:JsonInclude')
167
217
  .addImport('JsonInclude', 'com.fasterxml.jackson.annotation')
168
- .parenthesize('()', (builder) => builder.append('JsonInclude.Include.NON_NULL'))
218
+ .parenthesize('()', 'JsonInclude.Include.NON_NULL')
169
219
  .appendLine());
170
220
  }
171
221
  generateMapType(ctx, builder, schema) {
@@ -272,18 +322,15 @@ class DefaultKotlinModelGenerator extends file_generator_1.KotlinFileGenerator {
272
322
  .append('enum class ')
273
323
  .append(this.getDeclarationTypeName(ctx))
274
324
  .append('(val value: String) ')
275
- .parenthesize('{}', (builder) => {
325
+ .parenthesizeMultiline('{}', (builder) => {
276
326
  var _a;
277
- return builder
278
- .appendLine()
279
- .forEachSeparated((_a = schema.enum) !== null && _a !== void 0 ? _a : [], (builder) => builder.appendLine(',').appendLine(), (builder, value) => builder
327
+ return builder.forEachSeparated((_a = schema.enum) !== null && _a !== void 0 ? _a : [], (builder) => builder.appendLine(',').appendLine(), (builder, value) => builder
280
328
  .append('@JsonProperty')
281
329
  .addImport('JsonProperty', 'com.fasterxml.jackson.annotation')
282
- .parenthesize('()', (builder) => builder.append(this.toStringLiteral(ctx, String(value))))
330
+ .parenthesize('()', this.toStringLiteral(ctx, String(value)))
283
331
  .appendLine()
284
332
  .append((0, core_1.toCasing)(String(value), 'snake'))
285
- .parenthesize('()', (builder) => builder.append(this.toStringLiteral(ctx, String(value)))))
286
- .appendLine();
333
+ .parenthesize('()', this.toStringLiteral(ctx, String(value))));
287
334
  });
288
335
  }
289
336
  generateArrayType(ctx, builder, schema) {
@@ -333,5 +380,10 @@ class DefaultKotlinModelGenerator extends file_generator_1.KotlinFileGenerator {
333
380
  return bRequired - aRequired;
334
381
  });
335
382
  }
383
+ hasProperty(ctx, schema, name) {
384
+ return (('properties' in schema && schema.properties.has(name)) ||
385
+ ('anyOf' in schema && schema.anyOf.some((x) => this.hasProperty(ctx, x, name))) ||
386
+ ('allOf' in schema && schema.allOf.some((x) => this.hasProperty(ctx, x, name))));
387
+ }
336
388
  }
337
389
  exports.DefaultKotlinModelGenerator = DefaultKotlinModelGenerator;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./models"), exports);
5
+ tslib_1.__exportStar(require("./okhttp3-client-generator"), exports);
6
+ tslib_1.__exportStar(require("./okhttp3-clients-generator"), exports);
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultKotlinOkHttp3ClientsGeneratorConfig = void 0;
4
+ const config_1 = require("../../../config");
5
+ exports.defaultKotlinOkHttp3ClientsGeneratorConfig = Object.assign(Object.assign({}, config_1.defaultKotlinGeneratorConfig), { packageName: 'com.openapi.generated', packageSuffix: '.client', infrastructurePackageName: 'com.openapi.client.infrastructure' });
@@ -0,0 +1,404 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultKotlinOkHttp3Generator = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const fs_extra_1 = require("fs-extra");
7
+ const core_1 = require("@goast/core");
8
+ const file_builder_1 = require("../../../file-builder");
9
+ const utils_1 = require("../../../utils");
10
+ const file_generator_1 = require("../../file-generator");
11
+ class DefaultKotlinOkHttp3Generator extends file_generator_1.KotlinFileGenerator {
12
+ generate(ctx) {
13
+ const packageName = this.getPackageName(ctx);
14
+ const typeName = this.getApiClientName(ctx);
15
+ const filePath = this.getFilePath(ctx, packageName);
16
+ (0, fs_extra_1.ensureDirSync)((0, path_1.dirname)(filePath));
17
+ console.log(`Generating client for service ${ctx.service.name} to ${filePath}...`);
18
+ const builder = new file_builder_1.KotlinFileBuilder(packageName, ctx.config);
19
+ this.generateApiClientFileContent(ctx, builder);
20
+ (0, fs_1.writeFileSync)(filePath, builder.toString());
21
+ return { typeName, packageName };
22
+ }
23
+ generateApiClientFileContent(ctx, builder) {
24
+ builder
25
+ .apply((builder) => this.generateApiClientClassAnnotations(ctx, builder))
26
+ .ensureCurrentLineEmpty()
27
+ .apply((builder) => this.generateApiClientClassSignature(ctx, builder))
28
+ .append(' ')
29
+ .parenthesizeMultiline('{}', (builder) => this.generateApiClientClassContent(ctx, builder));
30
+ }
31
+ generateApiClientClassAnnotations(ctx, builder) {
32
+ // None for now
33
+ }
34
+ generateApiClientClassSignature(ctx, builder) {
35
+ builder
36
+ .append('class ')
37
+ .append(this.getApiClientName(ctx))
38
+ .parenthesizeMultiline('()', (builder) => builder
39
+ .appendLine('basePath: String = defaultBasePath,')
40
+ .appendLine('client: OkHttpClient = ApiClient.defaultClient')
41
+ .addImport('OkHttpClient', 'okhttp3')
42
+ .addImport('ApiClient', ctx.config.infrastructurePackageName))
43
+ .append(' : ')
44
+ .append('ApiClient(basePath, client)');
45
+ }
46
+ generateApiClientClassContent(ctx, builder) {
47
+ builder
48
+ .apply((builder) => this.generateApiClientCompanionObject(ctx, builder))
49
+ .forEach(ctx.service.endpoints, (builder, endpoint) => builder
50
+ .ensurePreviousLineEmpty()
51
+ .apply((builder) => this.generateApiClientMethod(ctx, builder, endpoint))
52
+ .ensurePreviousLineEmpty()
53
+ .apply((builder) => this.generateApiClientHttpInfoMethod(ctx, builder, endpoint))
54
+ .ensurePreviousLineEmpty()
55
+ .apply((builder) => this.generateApiClientRequestConfigMethod(ctx, builder, endpoint)))
56
+ .ensurePreviousLineEmpty()
57
+ .apply((builder) => this.generateAdditionalMethods(ctx, builder));
58
+ }
59
+ generateApiClientCompanionObject(ctx, builder) {
60
+ builder
61
+ .append('companion object ')
62
+ .parenthesizeMultiline('{}', (builder) => this.generateApiClientCompanionObjectContent(ctx, builder));
63
+ }
64
+ generateApiClientCompanionObjectContent(ctx, builder) {
65
+ this.generateApiClientCompanionObjectDefaultBasePathProperty(ctx, builder);
66
+ }
67
+ generateApiClientCompanionObjectDefaultBasePathProperty(ctx, builder) {
68
+ builder
69
+ .appendAnnotation('JvmStatic')
70
+ .append('val defaultBasePath: String by lazy ')
71
+ .parenthesizeMultiline('{}', (builder) => builder
72
+ .appendLine(`System.getProperties().getProperty(ApiClient.baseUrlKey, ${this.toStringLiteral(ctx, this.getBasePath(ctx))})`)
73
+ .addImport('ApiClient', ctx.config.infrastructurePackageName));
74
+ }
75
+ generateApiClientMethod(ctx, builder, endpoint) {
76
+ builder
77
+ .apply((builder) => this.generateApiClientMethodDocumentation(ctx, builder, endpoint))
78
+ .ensureCurrentLineEmpty()
79
+ .apply((builder) => this.generateApiClientMethodAnnotations(ctx, builder, endpoint))
80
+ .ensureCurrentLineEmpty()
81
+ .apply((builder) => this.generateApiClientMethodSignature(ctx, builder, endpoint))
82
+ .append(' ')
83
+ .parenthesizeMultiline('{}', (builder) => this.generateApiClientMethodContent(ctx, builder, endpoint));
84
+ }
85
+ generateApiClientMethodDocumentation(ctx, builder, endpoint) {
86
+ builder
87
+ .appendLine('/**')
88
+ .applyWithLinePrefix(' * ', (builder) => {
89
+ var _a;
90
+ return builder
91
+ .appendLine(`${(_a = endpoint.summary) !== null && _a !== void 0 ? _a : 'TODO: Provide summary'}`)
92
+ .apply((builder) => this.generateParamDocEntries(ctx, builder, endpoint))
93
+ .append('@return ')
94
+ .apply((builder) => this.generateApiClientMethodReturnType(ctx, builder, endpoint))
95
+ .appendLine()
96
+ .appendLine('@throws IllegalStateException If the request is not correctly configured')
97
+ .appendLine('@throws IOException Rethrows the OkHttp execute method exception')
98
+ .appendLine('@throws UnsupportedOperationException If the API returns an informational or redirection response')
99
+ .appendLine('@throws ClientException If the API returns a client error response')
100
+ .appendLine('@throws ServerException If the API returns a server error response');
101
+ })
102
+ .appendLine(' */');
103
+ }
104
+ generateApiClientMethodAnnotations(ctx, builder, endpoint) {
105
+ const responseSchema = this.getResponseSchema(ctx, endpoint);
106
+ builder
107
+ .applyIf(responseSchema !== undefined, (builder) => builder.appendAnnotation('Supress', undefined, ['"UNCHECKED_CAST"']))
108
+ .appendAnnotation('Throws', undefined, [
109
+ 'IllegalStateException::class',
110
+ 'IOException::class',
111
+ 'UnsupportedOperationException::class',
112
+ 'ClientException::class',
113
+ 'ServerException::class',
114
+ ])
115
+ .addImport('IOException', 'java.io')
116
+ .addImport('ClientException', ctx.config.infrastructurePackageName)
117
+ .addImport('ServerException', ctx.config.infrastructurePackageName);
118
+ }
119
+ generateApiClientMethodSignature(ctx, builder, endpoint) {
120
+ builder
121
+ .append('fun ')
122
+ .append((0, core_1.toCasing)(endpoint.name, 'camel'))
123
+ .parenthesize('()', (builder) => this.generateApiClientMethodParameters(ctx, builder, endpoint))
124
+ .append(': ')
125
+ .apply((builder) => this.generateApiClientMethodReturnType(ctx, builder, endpoint));
126
+ }
127
+ generateApiClientMethodParameters(ctx, builder, endpoint) {
128
+ this.generateParams(ctx, builder, endpoint, true);
129
+ }
130
+ generateApiClientMethodReturnType(ctx, builder, endpoint) {
131
+ this.generateTypeUsage(ctx, builder, this.getResponseSchema(ctx, endpoint), 'Unit');
132
+ }
133
+ generateApiClientMethodContent(ctx, builder, endpoint) {
134
+ const responseSchema = this.getResponseSchema(ctx, endpoint);
135
+ builder
136
+ .append(`val localVarResponse = ${(0, core_1.toCasing)(endpoint.name, 'camel')}HttpInfo`)
137
+ .parenthesize('()', (builder) => this.generateParams(ctx, builder, endpoint, false))
138
+ .appendLine()
139
+ .appendLine()
140
+ .append('return when (localVarResponse.responseType) ')
141
+ .parenthesizeMultiline('{}', (builder) => builder
142
+ .append('ResponseType.Success -> ')
143
+ .applyIfElse(responseSchema === undefined, (builder) => builder.append('Unit'), (builder) => builder
144
+ .append('(localVarResponse as Success<*>).data as ')
145
+ .addImport('Success', ctx.config.infrastructurePackageName)
146
+ .apply((builder) => this.generateTypeUsage(ctx, builder, responseSchema)))
147
+ .ensureCurrentLineEmpty()
148
+ .appendLine(responseErrorHandlingCode)
149
+ .addImport('ClientError', ctx.config.infrastructurePackageName)
150
+ .addImport('ServerError', ctx.config.infrastructurePackageName)
151
+ .addImport('ResponseType', ctx.config.infrastructurePackageName));
152
+ }
153
+ generateApiClientHttpInfoMethod(ctx, builder, endpoint) {
154
+ builder
155
+ .apply((builder) => this.generateApiClientHttpInfoMethodDocumentation(ctx, builder, endpoint))
156
+ .ensureCurrentLineEmpty()
157
+ .apply((builder) => this.generateApiClientHttpInfoMethodAnnotations(ctx, builder, endpoint))
158
+ .ensureCurrentLineEmpty()
159
+ .apply((builder) => this.generateApiClientHttpInfoMethodSignature(ctx, builder, endpoint))
160
+ .append(' ')
161
+ .parenthesizeMultiline('{}', (builder) => this.generateApiClientHttpInfoMethodContent(ctx, builder, endpoint));
162
+ }
163
+ generateApiClientHttpInfoMethodDocumentation(ctx, builder, endpoint) {
164
+ builder
165
+ .appendLine('/**')
166
+ .applyWithLinePrefix(' * ', (builder) => {
167
+ var _a;
168
+ return builder
169
+ .appendLine(`${(_a = endpoint.summary) !== null && _a !== void 0 ? _a : 'TODO: Provide summary'}`)
170
+ .apply((builder) => this.generateParamDocEntries(ctx, builder, endpoint))
171
+ .append('@return ')
172
+ .apply((builder) => this.generateApiClientHttpInfoMethodReturnType(ctx, builder, endpoint))
173
+ .appendLine()
174
+ .appendLine('@throws IllegalStateException If the request is not correctly configured')
175
+ .appendLine('@throws IOException Rethrows the OkHttp execute method exception')
176
+ .appendLine('@throws UnsupportedOperationException If the API returns an informational or redirection response')
177
+ .appendLine('@throws ClientException If the API returns a client error response')
178
+ .appendLine('@throws ServerException If the API returns a server error response');
179
+ })
180
+ .appendLine(' */');
181
+ }
182
+ generateApiClientHttpInfoMethodAnnotations(ctx, builder, endpoint) {
183
+ builder
184
+ .appendAnnotation('Throws', undefined, ['IllegalStateException::class', 'IOException::class'])
185
+ .addImport('IOException', 'java.io');
186
+ }
187
+ generateApiClientHttpInfoMethodSignature(ctx, builder, endpoint) {
188
+ builder
189
+ .append('fun ')
190
+ .append((0, core_1.toCasing)(endpoint.name, 'camel'), 'HttpInfo')
191
+ .parenthesize('()', (builder) => this.generateApiClientHttpInfoMethodSignatureParameters(ctx, builder, endpoint))
192
+ .append(': ')
193
+ .apply((builder) => this.generateApiClientHttpInfoMethodReturnType(ctx, builder, endpoint));
194
+ }
195
+ generateApiClientHttpInfoMethodSignatureParameters(ctx, builder, endpoint) {
196
+ this.generateParams(ctx, builder, endpoint, true);
197
+ }
198
+ generateApiClientHttpInfoMethodReturnType(ctx, builder, endpoint) {
199
+ builder
200
+ .append('ApiResponse')
201
+ .addImport('ApiResponse', ctx.config.infrastructurePackageName)
202
+ .parenthesize('<>', (builder) => this.generateTypeUsage(ctx, builder, this.getResponseSchema(ctx, endpoint), 'Unit'));
203
+ }
204
+ generateApiClientHttpInfoMethodContent(ctx, builder, endpoint) {
205
+ builder
206
+ .append(`val localVariableConfig = ${(0, core_1.toCasing)(endpoint.name, 'camel')}RequestConfig`)
207
+ .parenthesize('()', (builder) => this.generateParams(ctx, builder, endpoint, false))
208
+ .appendLine()
209
+ .appendLine()
210
+ .append('return request')
211
+ .parenthesize('<>', (builder) => builder
212
+ .apply((builder) => { var _a; return this.generateTypeUsage(ctx, builder, (_a = endpoint.requestBody) === null || _a === void 0 ? void 0 : _a.content[0].schema, 'Unit'); })
213
+ .append(', ')
214
+ .apply((builder) => this.generateTypeUsage(ctx, builder, this.getResponseSchema(ctx, endpoint), 'Unit')))
215
+ .parenthesizeMultiline('()', (builder) => builder.append('localVariableConfig'));
216
+ }
217
+ generateApiClientRequestConfigMethod(ctx, builder, endpoint) {
218
+ builder
219
+ .apply((builder) => this.generateApiClientRequestConfigMethodDocumentation(ctx, builder, endpoint))
220
+ .ensureCurrentLineEmpty()
221
+ .apply((builder) => this.generateApiClientRequestConfigMethodAnnotations(ctx, builder, endpoint))
222
+ .ensureCurrentLineEmpty()
223
+ .apply((builder) => this.generateApiClientRequestConfigMethodSignature(ctx, builder, endpoint))
224
+ .append(' ')
225
+ .parenthesizeMultiline('{}', (builder) => this.generateApiClientRequestConfigMethodContent(ctx, builder, endpoint));
226
+ }
227
+ generateApiClientRequestConfigMethodDocumentation(ctx, builder, endpoint) {
228
+ builder
229
+ .appendLine('/**')
230
+ .applyWithLinePrefix(' * ', (builder) => builder
231
+ .appendLine(`To obtain the request config of the operation ${(0, core_1.toCasing)(endpoint.name, 'camel')}`)
232
+ .apply((builder) => this.generateParamDocEntries(ctx, builder, endpoint))
233
+ .append('@return RequestConfig'))
234
+ .appendLine(' */');
235
+ }
236
+ generateApiClientRequestConfigMethodAnnotations(ctx, builder, endpoint) {
237
+ // No annotations needed
238
+ }
239
+ generateApiClientRequestConfigMethodSignature(ctx, builder, endpoint) {
240
+ builder
241
+ .append('private fun ')
242
+ .append((0, core_1.toCasing)(endpoint.name, 'camel'), 'RequestConfig')
243
+ .parenthesize('()', (builder) => this.generateApiClientRequestConfigMethodSignatureParameters(ctx, builder, endpoint))
244
+ .append(': ')
245
+ .apply((builder) => this.generateApiClientRequestConfigMethodReturnType(ctx, builder, endpoint));
246
+ }
247
+ generateApiClientRequestConfigMethodSignatureParameters(ctx, builder, endpoint) {
248
+ this.generateParams(ctx, builder, endpoint, true);
249
+ }
250
+ generateApiClientRequestConfigMethodReturnType(ctx, builder, endpoint) {
251
+ builder
252
+ .append('RequestConfig')
253
+ .addImport('RequestConfig', ctx.config.infrastructurePackageName)
254
+ .parenthesize('<>', (builder) => { var _a; return this.generateTypeUsage(ctx, builder, (_a = endpoint.requestBody) === null || _a === void 0 ? void 0 : _a.content[0].schema, 'Unit'); });
255
+ }
256
+ generateApiClientRequestConfigMethodContent(ctx, builder, endpoint) {
257
+ var _a, _b;
258
+ builder
259
+ .appendLine(`val localVariableBody = ${this.getRequestBodyParamName(ctx, endpoint)}`)
260
+ .appendLine('val localVariableQuery: MultiValueMap = mutableMapOf()')
261
+ .addImport('MultiValueMap', ctx.config.infrastructurePackageName)
262
+ .forEach(endpoint.parameters.filter((x) => x.target === 'query'), (builder, param) => builder.appendLine(`localVariableQuery["${param.name}"] = ${(0, core_1.toCasing)(param.name, 'camel')}`))
263
+ .appendLine('val localVariableHeaders: MutableMap<String, String> = mutableMapOf()')
264
+ .appendLineIf(((_a = endpoint.requestBody) === null || _a === void 0 ? void 0 : _a.content[0]) !== undefined, `localVariableHeaders["Content-Type"] = "${(_b = endpoint.requestBody) === null || _b === void 0 ? void 0 : _b.content[0].type}"`)
265
+ .appendLine()
266
+ .append('return RequestConfig')
267
+ .addImport('RequestConfig', ctx.config.infrastructurePackageName)
268
+ .parenthesizeMultiline('()', (builder) => builder
269
+ .appendLine(`method = RequestMethod.${endpoint.method.toUpperCase()},`)
270
+ .addImport('RequestMethod', ctx.config.infrastructurePackageName)
271
+ .appendLine(`path = "${this.getPathWithInterpolation(ctx, endpoint)}",`)
272
+ .appendLine('query = localVariableQuery,')
273
+ .appendLine('headers = localVariableHeaders,')
274
+ .appendLine('requiresAuthentication = false,')
275
+ .appendLine('body = localVariableBody'));
276
+ }
277
+ generateAdditionalMethods(ctx, builder) {
278
+ this.generateEncodeUriComponentMethod(ctx, builder);
279
+ }
280
+ generateEncodeUriComponentMethod(ctx, builder) {
281
+ builder
282
+ .appendLine('private fun encodeURIComponent(uriComponent: String): String =')
283
+ .indent('HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0]')
284
+ .addImport('HttpUrl', 'okhttp3');
285
+ }
286
+ generateParamDocEntries(ctx, builder, endpoint) {
287
+ const parameters = this.getAllParameters(ctx, endpoint);
288
+ builder.forEach(parameters, (builder, parameter) => { var _a; return builder.appendLine(`@param ${parameter.name} ${(_a = parameter.description) !== null && _a !== void 0 ? _a : 'TODO: Provide description'}`); });
289
+ }
290
+ generateParams(ctx, builder, endpoint, includeTypeDefinition) {
291
+ const parameters = this.getAllParameters(ctx, endpoint);
292
+ builder.forEachSeparated(parameters, ', ', (builder, parameter) => builder.append((0, core_1.toCasing)(parameter.name, 'camel')).applyIf(includeTypeDefinition, (builder) => builder
293
+ .append(': ')
294
+ .apply((builder) => this.generateTypeUsage(ctx, builder, parameter.schema))
295
+ .appendIf(!parameter.required, '? = ', this.getDefaultValue(ctx, parameter.schema))));
296
+ }
297
+ generateTypeUsage(ctx, builder, schema, fallback) {
298
+ if (schema && schema.kind === 'array') {
299
+ const schemaInfo = this.getSchemaInfo(ctx, schema.items);
300
+ builder.append(`List<${schemaInfo.typeName}>`);
301
+ builder.imports.addImports([schemaInfo, ...schemaInfo.additionalImports]);
302
+ }
303
+ else if (schema || !fallback) {
304
+ const schemaInfo = this.getSchemaInfo(ctx, schema);
305
+ builder.append(schemaInfo.typeName);
306
+ builder.imports.addImports([schemaInfo, ...schemaInfo.additionalImports]);
307
+ }
308
+ else {
309
+ builder.append(fallback);
310
+ }
311
+ }
312
+ getDefaultValue(ctx, schema) {
313
+ if (!(schema === null || schema === void 0 ? void 0 : schema.default)) {
314
+ return 'null';
315
+ }
316
+ if (typeof schema.default === 'string') {
317
+ return (0, utils_1.toKotlinStringLiteral)(schema.default);
318
+ }
319
+ else if (typeof schema.default === 'number' || typeof schema.default === 'boolean') {
320
+ return schema.default.toString();
321
+ }
322
+ else {
323
+ return 'null';
324
+ }
325
+ }
326
+ getPathWithInterpolation(ctx, endpoint) {
327
+ let path = endpoint.path;
328
+ endpoint.parameters
329
+ .filter((x) => x.target === 'path')
330
+ .forEach((parameter) => {
331
+ path = path.replace(`{${parameter.name}}`, `\${encodeURIComponent(${(0, core_1.toCasing)(parameter.name, 'camel')}.toString())}`);
332
+ });
333
+ return path;
334
+ }
335
+ getResponseSchema(ctx, endpoint) {
336
+ var _a, _b;
337
+ return (_b = (_a = endpoint.responses.find((x) => !x.statusCode || (x.statusCode >= 200 && x.statusCode < 300))) === null || _a === void 0 ? void 0 : _a.contentOptions[0]) === null || _b === void 0 ? void 0 : _b.schema;
338
+ }
339
+ getSchemaInfo(ctx, schema) {
340
+ var _a;
341
+ return ((_a = (schema && ctx.input.models[schema.id])) !== null && _a !== void 0 ? _a : { typeName: 'Any?', packageName: undefined, additionalImports: [] });
342
+ }
343
+ getAllParameters(ctx, endpoint) {
344
+ const parameters = endpoint.parameters.filter((parameter) => parameter.target === 'query' || parameter.target === 'path');
345
+ if (endpoint.requestBody) {
346
+ const schema = endpoint.requestBody.content[0].schema;
347
+ parameters.push({
348
+ $src: undefined,
349
+ $ref: undefined,
350
+ id: 'body',
351
+ name: this.getRequestBodyParamName(ctx, endpoint),
352
+ target: 'body',
353
+ schema,
354
+ required: endpoint.requestBody.required,
355
+ description: endpoint.requestBody.description,
356
+ allowEmptyValue: undefined,
357
+ allowReserved: undefined,
358
+ deprecated: false,
359
+ explode: undefined,
360
+ style: undefined,
361
+ });
362
+ }
363
+ return parameters.sort((a, b) => (a.required === b.required ? 0 : a.required ? -1 : 1));
364
+ }
365
+ getRequestBodyParamName(ctx, endpoint) {
366
+ var _a;
367
+ const schema = (_a = endpoint.requestBody) === null || _a === void 0 ? void 0 : _a.content[0].schema;
368
+ const schemaInfo = this.getSchemaInfo(ctx, schema);
369
+ return /^Any\??$/.test(schemaInfo.typeName) ? 'body' : schemaInfo.typeName;
370
+ }
371
+ getBasePath(ctx) {
372
+ var _a, _b, _c, _d, _e, _f;
373
+ return (_f = (_e = (_d = (_c = ((_a = ctx.service.$src) !== null && _a !== void 0 ? _a : (_b = ctx.service.endpoints[0]) === null || _b === void 0 ? void 0 : _b.$src)) === null || _c === void 0 ? void 0 : _c.document.servers) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.url) !== null && _f !== void 0 ? _f : '/';
374
+ }
375
+ getFilePath(ctx, packageName) {
376
+ return `${ctx.config.outputDir}/${packageName.replace(/\./g, '/')}/${this.getApiClientName(ctx)}.kt`;
377
+ }
378
+ getPackageName(ctx) {
379
+ return ctx.config.packageName + ctx.config.packageSuffix;
380
+ }
381
+ getApiClientName(ctx) {
382
+ return (0, core_1.toCasing)(ctx.service.name, 'pascal') + 'ApiClient';
383
+ }
384
+ }
385
+ exports.DefaultKotlinOkHttp3Generator = DefaultKotlinOkHttp3Generator;
386
+ const responseErrorHandlingCode = `ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
387
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
388
+ ResponseType.ClientError -> {
389
+ val localVarError = localVarResponse as ClientError<*>
390
+ throw ClientException(
391
+ "Client error : \${localVarError.statusCode} \${localVarError.message.orEmpty()}",
392
+ localVarError.statusCode,
393
+ localVarResponse
394
+ )
395
+ }
396
+
397
+ ResponseType.ServerError -> {
398
+ val localVarError = localVarResponse as ServerError<*>
399
+ throw ServerException(
400
+ "Server error : \${localVarError.statusCode} \${localVarError.message.orEmpty()}",
401
+ localVarError.statusCode,
402
+ localVarResponse
403
+ )
404
+ }`;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KotlinOkHttp3ClientsGenerator = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const fs_extra_1 = require("fs-extra");
7
+ const core_1 = require("@goast/core");
8
+ const models_1 = require("./models");
9
+ const okhttp3_client_generator_1 = require("./okhttp3-client-generator");
10
+ class KotlinOkHttp3ClientsGenerator extends core_1.OpenApiServicesGenerationProviderBase {
11
+ constructor(serviceGeneratorFactory) {
12
+ super();
13
+ this._serviceGeneratorFactory = serviceGeneratorFactory !== null && serviceGeneratorFactory !== void 0 ? serviceGeneratorFactory : core_1.Factory.fromValue(new okhttp3_client_generator_1.DefaultKotlinOkHttp3Generator());
14
+ }
15
+ onGenerate(ctx) {
16
+ this.copyInfrastructureFiles(ctx);
17
+ return super.onGenerate(ctx);
18
+ }
19
+ initResult() {
20
+ return {
21
+ clients: {},
22
+ };
23
+ }
24
+ generateService(ctx, service) {
25
+ const serviceGenerator = this._serviceGeneratorFactory.create();
26
+ return serviceGenerator.generate(Object.assign(Object.assign({}, ctx), { service }));
27
+ }
28
+ addServiceResult(ctx, service, result) {
29
+ ctx.output.clients[service.id] = result;
30
+ }
31
+ buildContext(context, config) {
32
+ context.data.services = context.data.services.filter((x) => x.name !== 'exclude-from-generation');
33
+ return this.getProviderContext(context, config, models_1.defaultKotlinOkHttp3ClientsGeneratorConfig);
34
+ }
35
+ copyInfrastructureFiles(ctx) {
36
+ const sourceDir = (0, path_1.resolve)((0, path_1.dirname)(require.resolve('@goast/kotlin')), '../assets/client/okhttp3');
37
+ const targetDir = (0, path_1.resolve)(ctx.config.outputDir, ctx.config.infrastructurePackageName.replace(/\./g, '/'));
38
+ (0, fs_extra_1.ensureDirSync)(targetDir);
39
+ const files = (0, fs_extra_1.readdirSync)(sourceDir);
40
+ for (const file of files) {
41
+ const fileContent = (0, fs_extra_1.readFileSync)((0, path_1.resolve)(sourceDir, file))
42
+ .toString()
43
+ .replace(/@PACKAGE_NAME@/g, ctx.config.infrastructurePackageName);
44
+ (0, fs_1.writeFileSync)((0, path_1.resolve)(targetDir, file), fileContent);
45
+ }
46
+ }
47
+ }
48
+ exports.KotlinOkHttp3ClientsGenerator = KotlinOkHttp3ClientsGenerator;