@goast/kotlin 0.0.1

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 (51) hide show
  1. package/README.md +7 -0
  2. package/cjs/index.js +9 -0
  3. package/cjs/lib/common-results.js +2 -0
  4. package/cjs/lib/config.js +9 -0
  5. package/cjs/lib/file-builder.js +63 -0
  6. package/cjs/lib/generators/file-generator.js +17 -0
  7. package/cjs/lib/generators/index.js +6 -0
  8. package/cjs/lib/generators/models/index.js +6 -0
  9. package/cjs/lib/generators/models/model-generator.js +337 -0
  10. package/cjs/lib/generators/models/models-generator.js +28 -0
  11. package/cjs/lib/generators/models/models.js +5 -0
  12. package/cjs/lib/generators/services/spring-controllers/index.js +6 -0
  13. package/cjs/lib/generators/services/spring-controllers/models.js +5 -0
  14. package/cjs/lib/generators/services/spring-controllers/spring-controller-generator.js +416 -0
  15. package/cjs/lib/generators/services/spring-controllers/spring-controllers-generator.js +30 -0
  16. package/cjs/lib/import-collection.js +70 -0
  17. package/cjs/lib/utils.js +22 -0
  18. package/cjs/package.json +1 -0
  19. package/esm/index.js +6 -0
  20. package/esm/lib/common-results.js +1 -0
  21. package/esm/lib/config.js +6 -0
  22. package/esm/lib/file-builder.js +59 -0
  23. package/esm/lib/generators/file-generator.js +13 -0
  24. package/esm/lib/generators/index.js +3 -0
  25. package/esm/lib/generators/models/index.js +3 -0
  26. package/esm/lib/generators/models/model-generator.js +333 -0
  27. package/esm/lib/generators/models/models-generator.js +24 -0
  28. package/esm/lib/generators/models/models.js +2 -0
  29. package/esm/lib/generators/services/spring-controllers/index.js +3 -0
  30. package/esm/lib/generators/services/spring-controllers/models.js +2 -0
  31. package/esm/lib/generators/services/spring-controllers/spring-controller-generator.js +412 -0
  32. package/esm/lib/generators/services/spring-controllers/spring-controllers-generator.js +26 -0
  33. package/esm/lib/import-collection.js +66 -0
  34. package/esm/lib/utils.js +17 -0
  35. package/package.json +29 -0
  36. package/types/index.d.ts +6 -0
  37. package/types/lib/common-results.d.ts +4 -0
  38. package/types/lib/config.d.ts +6 -0
  39. package/types/lib/file-builder.d.ts +14 -0
  40. package/types/lib/generators/file-generator.d.ts +8 -0
  41. package/types/lib/generators/index.d.ts +3 -0
  42. package/types/lib/generators/models/index.d.ts +3 -0
  43. package/types/lib/generators/models/model-generator.d.ts +31 -0
  44. package/types/lib/generators/models/models-generator.d.ts +17 -0
  45. package/types/lib/generators/models/models.d.ts +22 -0
  46. package/types/lib/generators/services/spring-controllers/index.d.ts +3 -0
  47. package/types/lib/generators/services/spring-controllers/models.d.ts +24 -0
  48. package/types/lib/generators/services/spring-controllers/spring-controller-generator.d.ts +63 -0
  49. package/types/lib/generators/services/spring-controllers/spring-controllers-generator.d.ts +17 -0
  50. package/types/lib/import-collection.d.ts +13 -0
  51. package/types/lib/utils.d.ts +3 -0
@@ -0,0 +1,416 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultKotlinSpringControllerGenerator = void 0;
4
+ const fs_extra_1 = require("fs-extra");
5
+ const core_1 = require("@goast/core");
6
+ const file_builder_1 = require("../../../file-builder");
7
+ const file_generator_1 = require("../../file-generator");
8
+ class DefaultKotlinSpringControllerGenerator extends file_generator_1.KotlinFileGenerator {
9
+ generate(ctx) {
10
+ const packageName = this.getPackageName(ctx);
11
+ const dirPath = this.getDirectoryPath(ctx, packageName);
12
+ (0, fs_extra_1.ensureDirSync)(dirPath);
13
+ console.log(`Generating service ${ctx.service.id} to ${dirPath}...`);
14
+ return {
15
+ apiInterface: this.generateApiInterfaceFile(ctx, dirPath, packageName),
16
+ apiController: this.generateApiControllerFile(ctx, dirPath, packageName),
17
+ apiDelegate: this.generateApiDelegateInterfaceFile(ctx, dirPath, packageName),
18
+ };
19
+ }
20
+ generateApiInterfaceFile(ctx, dirPath, packageName) {
21
+ const typeName = this.getApiInterfaceName(ctx);
22
+ const fileName = `${typeName}.kt`;
23
+ const filePath = `${dirPath}/${fileName}`;
24
+ console.log(` Generating API interface ${typeName} to ${fileName}...`);
25
+ const builder = new file_builder_1.KotlinFileBuilder(packageName, ctx.config);
26
+ this.generateApiInterfaceFileContent(ctx, builder);
27
+ (0, fs_extra_1.writeFileSync)(filePath, builder.toString());
28
+ return { typeName: builder.toString(), packageName };
29
+ }
30
+ generateApiInterfaceFileContent(ctx, builder) {
31
+ builder
32
+ .apply((builder) => this.generateApiInterfaceAnnotations(ctx, builder))
33
+ .ensureCurrentLineEmpty()
34
+ .apply((builder) => this.generateApiInterfaceSignature(ctx, builder))
35
+ .append(' ')
36
+ .parenthesize('{}', (builder) => builder
37
+ .appendLine()
38
+ .apply((builder) => this.generateApiInterfaceContent(ctx, builder))
39
+ .ensureCurrentLineEmpty());
40
+ }
41
+ generateApiInterfaceAnnotations(ctx, builder) {
42
+ builder
43
+ .appendAnnotation('Validated', 'org.springframework.validation.annotation')
44
+ .appendAnnotation('RequestMapping', 'org.springframework.web.bind.annotation', [
45
+ this.getControllerRequestMapping(ctx, 'api'),
46
+ ]);
47
+ }
48
+ generateApiInterfaceSignature(ctx, builder) {
49
+ builder.append('interface ').append(this.getApiInterfaceName(ctx));
50
+ }
51
+ generateApiInterfaceContent(ctx, builder) {
52
+ builder
53
+ .apply((builder) => this.generateApiInterfaceDelegateAccessor(ctx, builder))
54
+ .ensurePreviousLineEmpty()
55
+ .apply((builder) => this.generateApiInterfaceMethods(ctx, builder));
56
+ }
57
+ generateApiInterfaceDelegateAccessor(ctx, builder) {
58
+ builder.appendLine(`fun getDelegate(): ${this.getApiDelegateInterfaceName(ctx)} = object : ${this.getApiDelegateInterfaceName(ctx)} {}`);
59
+ }
60
+ generateApiInterfaceMethods(ctx, builder) {
61
+ builder.forEach(ctx.service.endpoints, (builder, endpoint) => builder.ensurePreviousLineEmpty().apply((builder) => this.generateApiInterfaceMethod(ctx, builder, endpoint)));
62
+ }
63
+ generateApiInterfaceMethod(ctx, builder, endpoint) {
64
+ builder
65
+ .apply((builder) => this.generateApiInterfaceMethodAnnnotations(ctx, builder, endpoint))
66
+ .ensureCurrentLineEmpty()
67
+ .apply((builder) => this.generateApiInterfaceMethodSignature(ctx, builder, endpoint))
68
+ .append(' ')
69
+ .parenthesize('{}', (builder) => builder
70
+ .appendLine()
71
+ .apply((builder) => this.generateApiInterfaceMethodContent(ctx, builder, endpoint))
72
+ .appendLine());
73
+ }
74
+ generateApiInterfaceMethodAnnnotations(ctx, builder, endpoint) {
75
+ var _a, _b, _c;
76
+ builder
77
+ .appendAnnotation('Operation', 'io.swagger.v3.oas.annotations', [
78
+ ['summary', this.toStringLiteral(ctx, (_a = endpoint.summary) === null || _a === void 0 ? void 0 : _a.trim())],
79
+ ['operationId', this.toStringLiteral(ctx, endpoint.name)],
80
+ ['description', this.toStringLiteral(ctx, (_b = endpoint.description) === null || _b === void 0 ? void 0 : _b.trim())],
81
+ [
82
+ 'responses',
83
+ (builder) => builder.parenthesize('[]', (builder) => builder
84
+ .appendLine()
85
+ .forEachSeparated(endpoint.responses, ',\n', (builder, response) => builder
86
+ .append('ApiResponse')
87
+ .addImport('ApiResponse', 'io.swagger.v3.oas.annotations.responses')
88
+ .parenthesize('()', (builder) => {
89
+ var _a, _b;
90
+ return builder
91
+ .append(`responseCode = ${this.toStringLiteral(ctx, (_a = response.statusCode) === null || _a === void 0 ? void 0 : _a.toString())}, `)
92
+ .append(`description = ${this.toStringLiteral(ctx, (_b = response.description) === null || _b === void 0 ? void 0 : _b.trim())}`);
93
+ }))
94
+ .appendLine()),
95
+ endpoint.responses.length > 0,
96
+ ],
97
+ ])
98
+ .appendAnnotation('RequestMapping', 'org.springframework.web.bind.annotation', [
99
+ ['method', '[RequestMethod.' + endpoint.method.toUpperCase() + ']'],
100
+ ['value', '[' + this.toStringLiteral(ctx, endpoint.path) + ']'],
101
+ [
102
+ 'consumes',
103
+ '[' + ((_c = endpoint.requestBody) === null || _c === void 0 ? void 0 : _c.content.map((x) => this.toStringLiteral(ctx, x.type)).join(', ')) + ']',
104
+ !!endpoint.requestBody && endpoint.requestBody.content.length > 0,
105
+ ],
106
+ ])
107
+ .addImport('RequestMethod', 'org.springframework.web.bind.annotation');
108
+ }
109
+ generateApiInterfaceMethodSignature(ctx, builder, endpoint) {
110
+ builder
111
+ .append(`suspend fun ${(0, core_1.toCasing)(endpoint.name, 'camel')}`)
112
+ .parenthesize('()', (builder) => builder
113
+ .appendLine()
114
+ .apply((builder) => this.generateApiInterfaceMethodParameters(ctx, builder, endpoint))
115
+ .appendLine())
116
+ .append(': ')
117
+ .apply((builder) => this.generateApiInterfaceMethodReturnType(ctx, builder, endpoint));
118
+ }
119
+ generateApiInterfaceMethodParameters(ctx, builder, endpoint) {
120
+ const parameters = this.getAllParameters(ctx, endpoint);
121
+ builder.forEachSeparated(parameters, ',\n', (builder, parameter) => this.generateApiInterfaceMethodParameter(ctx, builder, endpoint, parameter));
122
+ }
123
+ generateApiInterfaceMethodReturnType(ctx, builder, endpoint) {
124
+ var _a, _b;
125
+ this.generateResponseEntityType(ctx, builder, (_b = (_a = endpoint.responses[0]) === null || _a === void 0 ? void 0 : _a.contentOptions[0]) === null || _b === void 0 ? void 0 : _b.schema);
126
+ }
127
+ generateApiInterfaceMethodParameter(ctx, builder, endpoint, parameter) {
128
+ builder
129
+ .apply((builder) => this.generateApiInterfaceMethodParameterAnnotations(ctx, builder, endpoint, parameter))
130
+ .ensureCurrentLineEmpty()
131
+ .apply((builder) => this.generateApiInterfaceMethodParameterSignature(ctx, builder, endpoint, parameter));
132
+ }
133
+ generateApiInterfaceMethodParameterAnnotations(ctx, builder, endpoint, parameter) {
134
+ var _a, _b, _c, _d, _e, _f, _g, _h;
135
+ const parameterSchemaInfo = this.getSchemaInfo(ctx, parameter.schema);
136
+ if (((_a = parameter.schema) === null || _a === void 0 ? void 0 : _a.default) !== undefined) {
137
+ builder.addImport('Schema', 'io.swagger.v3.oas.annotations.media');
138
+ }
139
+ builder.appendAnnotation('Parameter', 'io.swagger.v3.oas.annotations', [
140
+ ['description', this.toStringLiteral(ctx, (_b = parameter.description) === null || _b === void 0 ? void 0 : _b.trim())],
141
+ ['required', (_c = parameter.required) === null || _c === void 0 ? void 0 : _c.toString()],
142
+ [
143
+ 'schema',
144
+ `Schema(defaultValue = ${this.toStringLiteral(ctx, String((_d = parameter.schema) === null || _d === void 0 ? void 0 : _d.default))})`,
145
+ ((_e = parameter.schema) === null || _e === void 0 ? void 0 : _e.default) !== undefined,
146
+ ],
147
+ ]);
148
+ if (parameterSchemaInfo.packageName) {
149
+ builder.appendAnnotation('Valid', 'jakarta.validation');
150
+ }
151
+ if (parameter.target === 'body') {
152
+ builder.appendAnnotation('RequestBody', 'org.springframework.web.bind.annotation');
153
+ }
154
+ if (parameter.target === 'query') {
155
+ builder.appendAnnotation('RequestParam', 'org.springframework.web.bind.annotation', [
156
+ ['value', this.toStringLiteral(ctx, parameter.name)],
157
+ ['required', (_f = parameter.required) === null || _f === void 0 ? void 0 : _f.toString()],
158
+ [
159
+ 'defaultValue',
160
+ this.toStringLiteral(ctx, String((_g = parameter.schema) === null || _g === void 0 ? void 0 : _g.default)),
161
+ ((_h = parameter.schema) === null || _h === void 0 ? void 0 : _h.default) !== undefined,
162
+ ],
163
+ ]);
164
+ }
165
+ if (parameter.target === 'path') {
166
+ builder.appendAnnotation('PathVariable', 'org.springframework.web.bind.annotation', [
167
+ this.toStringLiteral(ctx, parameter.name),
168
+ ]);
169
+ }
170
+ }
171
+ generateApiInterfaceMethodParameterSignature(ctx, builder, endpoint, parameter) {
172
+ builder
173
+ .append((0, core_1.toCasing)(parameter.name, 'camel'))
174
+ .append(': ')
175
+ .apply((builder) => this.generateTypeUsage(ctx, builder, parameter.schema));
176
+ }
177
+ generateApiInterfaceMethodContent(ctx, builder, endpoint) {
178
+ const parameters = this.getAllParameters(ctx, endpoint);
179
+ builder
180
+ .append(`return getDelegate().${(0, core_1.toCasing)(endpoint.name, 'camel')}(`)
181
+ .forEachSeparated(parameters, ', ', (builder, parameter) => builder.append((0, core_1.toCasing)(parameter.name, 'camel')))
182
+ .append(')');
183
+ }
184
+ generateApiControllerFile(ctx, dirPath, packageName) {
185
+ const typeName = this.getApiControllerName(ctx);
186
+ const fileName = `${typeName}.kt`;
187
+ const filePath = `${dirPath}/${fileName}`;
188
+ console.log(` Generating API controller ${typeName} to ${fileName}...`);
189
+ const builder = new file_builder_1.KotlinFileBuilder(packageName, ctx.config);
190
+ this.generateApiControllerFileContent(ctx, builder);
191
+ (0, fs_extra_1.writeFileSync)(filePath, builder.toString());
192
+ return { typeName: builder.toString(), packageName };
193
+ }
194
+ generateApiControllerFileContent(ctx, builder) {
195
+ builder
196
+ .apply((builder) => this.generateApiControllerAnnotations(ctx, builder))
197
+ .ensureCurrentLineEmpty()
198
+ .apply((builder) => this.generateApiControllerSignature(ctx, builder))
199
+ .append(' ')
200
+ .parenthesize('{}', (builder) => builder
201
+ .appendLine()
202
+ .apply((builder) => this.generateApiControllerContent(ctx, builder))
203
+ .ensureCurrentLineEmpty());
204
+ }
205
+ generateApiControllerAnnotations(ctx, builder) {
206
+ builder
207
+ .appendAnnotation('Generated', 'jakarta.annotation', [
208
+ ['value', '[' + this.toStringLiteral(ctx, 'com.goast.kotlin.spring-service-generator') + ']'],
209
+ ])
210
+ .appendAnnotation('Controller', 'org.springframework.stereotype')
211
+ .appendAnnotation('RequestMapping', 'org.springframework.web.bind.annotation', [
212
+ this.getControllerRequestMapping(ctx),
213
+ ]);
214
+ }
215
+ generateApiControllerSignature(ctx, builder) {
216
+ builder
217
+ .append('class ')
218
+ .append(this.getApiControllerName(ctx))
219
+ .parenthesize('()', (builder) => builder
220
+ .appendLine()
221
+ .apply((builder) => this.generateApiControllerParameters(ctx, builder))
222
+ .ensureCurrentLineEmpty())
223
+ .append(' : ')
224
+ .append(this.getApiInterfaceName(ctx));
225
+ }
226
+ generateApiControllerParameters(ctx, builder) {
227
+ builder
228
+ .appendAnnotation('Autowired', 'org.springframework.beans.factory.annotation', [['required', 'false']])
229
+ .append('delegate: ')
230
+ .append(this.getApiDelegateInterfaceName(ctx))
231
+ .append('?');
232
+ }
233
+ generateApiControllerContent(ctx, builder) {
234
+ builder
235
+ .append('private val delegate: ')
236
+ .appendLine(this.getApiDelegateInterfaceName(ctx))
237
+ .appendLine()
238
+ .append('init ')
239
+ .parenthesize('{}', (builder) => builder
240
+ .appendLine()
241
+ .append('this.delegate = Optional.ofNullable(delegate).orElse')
242
+ .addImport('Optional', 'java.util')
243
+ .parenthesize('()', (builder) => builder.append('object : ').append(this.getApiDelegateInterfaceName(ctx)).append(' {}'))
244
+ .appendLine())
245
+ .appendLine()
246
+ .appendLine()
247
+ .appendLine(`override fun getDelegate(): ${this.getApiDelegateInterfaceName(ctx)} = delegate`);
248
+ }
249
+ generateApiDelegateInterfaceFile(ctx, dirPath, packageName) {
250
+ const typeName = this.getApiDelegateInterfaceName(ctx);
251
+ const fileName = `${typeName}.kt`;
252
+ const filePath = `${dirPath}/${fileName}`;
253
+ console.log(` Generating API delegate ${typeName} to ${fileName}...`);
254
+ const builder = new file_builder_1.KotlinFileBuilder(packageName, ctx.config);
255
+ this.generateApiDelegateInterfaceFileContent(ctx, builder);
256
+ (0, fs_extra_1.writeFileSync)(filePath, builder.toString());
257
+ return { typeName: builder.toString(), packageName };
258
+ }
259
+ generateApiDelegateInterfaceFileContent(ctx, builder) {
260
+ builder
261
+ .apply((builder) => this.generateApiDelegateInterfaceAnnotations(ctx, builder))
262
+ .ensureCurrentLineEmpty()
263
+ .apply((builder) => this.generateApiDelegateInterfaceSignature(ctx, builder))
264
+ .append(' ')
265
+ .parenthesize('{}', (builder) => builder
266
+ .appendLine()
267
+ .apply((builder) => this.generateApiDelegateInterfaceContent(ctx, builder))
268
+ .ensureCurrentLineEmpty());
269
+ }
270
+ generateApiDelegateInterfaceAnnotations(ctx, builder) {
271
+ builder.appendAnnotation('Generated', 'jakarta.annotation', [
272
+ ['value', '[' + this.toStringLiteral(ctx, 'com.goast.kotlin.spring-service-generator') + ']'],
273
+ ]);
274
+ }
275
+ generateApiDelegateInterfaceSignature(ctx, builder) {
276
+ builder.append('interface ').append(this.getApiDelegateInterfaceName(ctx));
277
+ }
278
+ generateApiDelegateInterfaceContent(ctx, builder) {
279
+ builder
280
+ .appendLine(`fun getRequest(): Optional<NativeWebRequest> = Optional.empty()`)
281
+ .addImport('Optional', 'java.util')
282
+ .addImport('NativeWebRequest', 'org.springframework.web.context.request')
283
+ .forEach(ctx.service.endpoints, (builder, endpoint) => builder
284
+ .ensurePreviousLineEmpty()
285
+ .apply((builder) => this.generateApiDelegateInterfaceMethod(ctx, builder, endpoint)));
286
+ }
287
+ generateApiDelegateInterfaceMethod(ctx, builder, endpoint) {
288
+ builder
289
+ .apply((builder) => this.generateApiDelegateInterfaceMethodAnnnotations(ctx, builder, endpoint))
290
+ .ensureCurrentLineEmpty()
291
+ .apply((builder) => this.generateApiDelegateInterfaceMethodSignature(ctx, builder, endpoint))
292
+ .append(' ')
293
+ .parenthesize('{}', (builder) => builder
294
+ .appendLine()
295
+ .apply((builder) => this.generateApiDelegateInterfaceMethodContent(ctx, builder, endpoint))
296
+ .ensureCurrentLineEmpty());
297
+ }
298
+ generateApiDelegateInterfaceMethodAnnnotations(ctx, builder, endpoint) {
299
+ // None for now.
300
+ }
301
+ generateApiDelegateInterfaceMethodSignature(ctx, builder, endpoint) {
302
+ builder
303
+ .append(`suspend fun ${(0, core_1.toCasing)(endpoint.name, 'camel')}`)
304
+ .parenthesize('()', (builder) => builder
305
+ .appendLine()
306
+ .apply((builder) => this.generateApiDelegateInterfaceMethodParameters(ctx, builder, endpoint))
307
+ .appendLine())
308
+ .append(': ')
309
+ .apply((builder) => this.generateApiDelegateInterfaceMethodReturnType(ctx, builder, endpoint));
310
+ }
311
+ generateApiDelegateInterfaceMethodParameters(ctx, builder, endpoint) {
312
+ const parameters = this.getAllParameters(ctx, endpoint);
313
+ builder.forEachSeparated(parameters, ',\n', (builder, parameter) => this.generateApiDelegateInterfaceMethodParameter(ctx, builder, endpoint, parameter));
314
+ }
315
+ generateApiDelegateInterfaceMethodReturnType(ctx, builder, endpoint) {
316
+ var _a, _b;
317
+ this.generateResponseEntityType(ctx, builder, (_b = (_a = endpoint.responses[0]) === null || _a === void 0 ? void 0 : _a.contentOptions[0]) === null || _b === void 0 ? void 0 : _b.schema);
318
+ }
319
+ generateApiDelegateInterfaceMethodParameter(ctx, builder, endpoint, parameter) {
320
+ builder
321
+ .apply((builder) => this.generateApiDelegateInterfaceMethodParameterAnnotations(ctx, builder, endpoint, parameter))
322
+ .ensureCurrentLineEmpty()
323
+ .apply((builder) => this.generateApiDelegateInterfaceMethodParameterSignature(ctx, builder, endpoint, parameter));
324
+ }
325
+ generateApiDelegateInterfaceMethodParameterAnnotations(ctx, builder, endpoint, parameter) {
326
+ // None for now.
327
+ }
328
+ generateApiDelegateInterfaceMethodParameterSignature(ctx, builder, endpoint, parameter) {
329
+ builder
330
+ .append((0, core_1.toCasing)(parameter.name, 'camel'))
331
+ .append(': ')
332
+ .apply((builder) => this.generateTypeUsage(ctx, builder, parameter.schema));
333
+ }
334
+ generateApiDelegateInterfaceMethodContent(ctx, builder, endpoint) {
335
+ builder
336
+ .appendLine('return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)')
337
+ .addImport('ResponseEntity', 'org.springframework.http')
338
+ .addImport('HttpStatus', 'org.springframework.http');
339
+ }
340
+ generateResponseEntityType(ctx, builder, schema) {
341
+ builder
342
+ .append('ResponseEntity')
343
+ .addImport('ResponseEntity', 'org.springframework.http')
344
+ .parenthesize('<>', (builder) => this.generateTypeUsage(ctx, builder, schema, 'Unit'));
345
+ }
346
+ generateTypeUsage(ctx, builder, schema, fallback) {
347
+ if (schema && schema.kind === 'array') {
348
+ const schemaInfo = this.getSchemaInfo(ctx, schema.items);
349
+ builder.append(`Flux<${schemaInfo.typeName}>`).addImport('Flux', 'reactor.core.publisher');
350
+ builder.imports.addImports([schemaInfo, ...schemaInfo.additionalImports]);
351
+ }
352
+ else if (schema || !fallback) {
353
+ const schemaInfo = this.getSchemaInfo(ctx, schema);
354
+ builder.append(schemaInfo.typeName);
355
+ builder.imports.addImports([schemaInfo, ...schemaInfo.additionalImports]);
356
+ }
357
+ else {
358
+ builder.append(fallback);
359
+ }
360
+ }
361
+ getControllerRequestMapping(ctx, prefix) {
362
+ var _a, _b, _c, _d, _e, _f;
363
+ const basePath = (_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 : '/';
364
+ prefix !== null && prefix !== void 0 ? prefix : (prefix = `openapi.${(0, core_1.toCasing)(ctx.service.name, 'camel')}`);
365
+ return this.toStringLiteral(ctx, `\${${prefix}.base-path:${basePath}}`);
366
+ }
367
+ getDirectoryPath(ctx, packageName) {
368
+ return `${ctx.config.outputDir}/${packageName.replace(/\./g, '/')}`;
369
+ }
370
+ getPackageName(ctx) {
371
+ return ctx.config.packageName + ctx.config.packageSuffix;
372
+ }
373
+ getApiInterfaceName(ctx) {
374
+ return (0, core_1.toCasing)(ctx.service.name, 'pascal') + 'Api';
375
+ }
376
+ getApiControllerName(ctx) {
377
+ return (0, core_1.toCasing)(ctx.service.name, 'pascal') + 'ApiController';
378
+ }
379
+ getApiDelegateInterfaceName(ctx) {
380
+ return (0, core_1.toCasing)(ctx.service.name, 'pascal') + 'ApiDelegate';
381
+ }
382
+ getSchemaInfo(ctx, schema) {
383
+ var _a;
384
+ return ((_a = (schema && ctx.input.models[schema.id])) !== null && _a !== void 0 ? _a : { typeName: 'Any?', packageName: undefined, additionalImports: [] });
385
+ }
386
+ getAllParameters(ctx, endpoint) {
387
+ const parameters = endpoint.parameters.filter((parameter) => parameter.target === 'query' || parameter.target === 'path');
388
+ if (endpoint.requestBody) {
389
+ const schema = endpoint.requestBody.content[0].schema;
390
+ parameters.push({
391
+ $src: undefined,
392
+ $ref: undefined,
393
+ id: 'body',
394
+ name: schema ? this.getSchemaInfo(ctx, schema).typeName : 'body',
395
+ target: 'body',
396
+ schema,
397
+ required: endpoint.requestBody.required,
398
+ description: endpoint.requestBody.description,
399
+ allowEmptyValue: undefined,
400
+ allowReserved: undefined,
401
+ deprecated: false,
402
+ explode: undefined,
403
+ style: undefined,
404
+ });
405
+ }
406
+ return parameters;
407
+ }
408
+ sortParameters(ctx, parameters) {
409
+ return [...parameters].sort((a, b) => {
410
+ const aRequired = a.required ? 1 : 0;
411
+ const bRequired = b.required ? 1 : 0;
412
+ return aRequired - bRequired;
413
+ });
414
+ }
415
+ }
416
+ exports.DefaultKotlinSpringControllerGenerator = DefaultKotlinSpringControllerGenerator;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KotlinSpringControllersGenerator = void 0;
4
+ const core_1 = require("@goast/core");
5
+ const models_1 = require("./models");
6
+ const spring_controller_generator_1 = require("./spring-controller-generator");
7
+ class KotlinSpringControllersGenerator extends core_1.OpenApiServicesGenerationProviderBase {
8
+ constructor(serviceGeneratorFactory) {
9
+ super();
10
+ this._serviceGeneratorFactory =
11
+ serviceGeneratorFactory !== null && serviceGeneratorFactory !== void 0 ? serviceGeneratorFactory : core_1.Factory.fromValue(new spring_controller_generator_1.DefaultKotlinSpringControllerGenerator());
12
+ }
13
+ initResult() {
14
+ return {
15
+ services: {},
16
+ };
17
+ }
18
+ generateService(ctx, service) {
19
+ const serviceGenerator = this._serviceGeneratorFactory.create();
20
+ return serviceGenerator.generate(Object.assign(Object.assign({}, ctx), { service }));
21
+ }
22
+ addServiceResult(ctx, service, result) {
23
+ ctx.output.services[service.id] = result;
24
+ }
25
+ buildContext(context, config) {
26
+ context.data.services = context.data.services.filter((x) => x.name !== 'exclude-from-generation');
27
+ return this.getProviderContext(context, config, models_1.defaultKotlinServicesGeneratorConfig);
28
+ }
29
+ }
30
+ exports.KotlinSpringControllersGenerator = KotlinSpringControllersGenerator;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImportCollection = void 0;
4
+ const core_1 = require("@goast/core");
5
+ class ImportCollection {
6
+ constructor() {
7
+ this._imports = new Map();
8
+ }
9
+ get hasImports() {
10
+ return this._imports.size > 0;
11
+ }
12
+ get imports() {
13
+ return Array.from(this._imports.entries())
14
+ .map(([fromPackage, importNames]) => Array.from(importNames).map((importName) => ({
15
+ packageName: fromPackage,
16
+ typeName: importName,
17
+ })))
18
+ .flat();
19
+ }
20
+ addImport(importOrImportName, fromModule) {
21
+ const importName = typeof importOrImportName === 'string' ? importOrImportName : importOrImportName.typeName;
22
+ fromModule = typeof importOrImportName === 'string' ? fromModule : importOrImportName.packageName;
23
+ if (!fromModule) {
24
+ return;
25
+ }
26
+ const existingImport = this._imports.get(fromModule);
27
+ if (existingImport) {
28
+ existingImport.add(importName);
29
+ }
30
+ else {
31
+ this._imports.set(fromModule, new Set([importName]));
32
+ }
33
+ }
34
+ addImports(imports) {
35
+ for (const importObj of imports) {
36
+ this.addImport(importObj);
37
+ }
38
+ }
39
+ clear() {
40
+ this._imports.clear();
41
+ }
42
+ toString(options) {
43
+ const builder = new core_1.StringBuilder(options);
44
+ this.writeTo(builder);
45
+ return builder.toString();
46
+ }
47
+ writeTo(builder) {
48
+ if (this._imports.size > 0) {
49
+ const sortedImports = Array.from(this._imports.entries()).sort(([fromModuleA], [fromModuleB]) => {
50
+ if (isCoreImport(fromModuleA) && !isCoreImport(fromModuleB)) {
51
+ return 1;
52
+ }
53
+ else if (!isCoreImport(fromModuleA) && isCoreImport(fromModuleB)) {
54
+ return -1;
55
+ }
56
+ return fromModuleA.localeCompare(fromModuleB);
57
+ });
58
+ for (const [fromPackage, importNames] of sortedImports) {
59
+ const sortedImportNames = Array.from(importNames).sort();
60
+ for (const importName of sortedImportNames) {
61
+ builder.appendLine(`import ${fromPackage}.${importName}`);
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ exports.ImportCollection = ImportCollection;
68
+ function isCoreImport(packageName) {
69
+ return packageName.startsWith('kotlin.') || packageName.startsWith('java.') || packageName.startsWith('javax.');
70
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toKotlinPropertyName = exports.toKotlinStringLiteral = void 0;
4
+ function toKotlinStringLiteral(value) {
5
+ if (!value) {
6
+ return '""';
7
+ }
8
+ const escaped = value
9
+ .replace(/(["\\$])/g, '\\$1')
10
+ .replace(/\n/g, '\\n')
11
+ .replace(/\r/g, '\\r')
12
+ .replace(/\t/g, '\\t');
13
+ return `"${escaped}"`;
14
+ }
15
+ exports.toKotlinStringLiteral = toKotlinStringLiteral;
16
+ function toKotlinPropertyName(value) {
17
+ if (value.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/)) {
18
+ return value;
19
+ }
20
+ return `\`${value}\``;
21
+ }
22
+ exports.toKotlinPropertyName = toKotlinPropertyName;
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
package/esm/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export * from './lib/common-results';
2
+ export * from './lib/config';
3
+ export * from './lib/generators';
4
+ export * from './lib/file-builder';
5
+ export * from './lib/import-collection';
6
+ export * from './lib/utils';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ export const defaultKotlinGeneratorConfig = {
2
+ charsTreatedAsEmptyLine: ['{'],
3
+ indent: { type: 'spaces', count: 4 },
4
+ propertyNameCasing: 'camel',
5
+ enumValueNameCasing: 'snake',
6
+ };
@@ -0,0 +1,59 @@
1
+ import { SourceBuilder } from '@goast/core';
2
+ import { ImportCollection } from './import-collection';
3
+ export class KotlinFileBuilder extends SourceBuilder {
4
+ constructor(packageName, options) {
5
+ super(options);
6
+ this.imports = new ImportCollection();
7
+ this.packageName = packageName;
8
+ }
9
+ addImport(name, packageName) {
10
+ if (packageName !== undefined && packageName !== this.packageName) {
11
+ this.imports.addImport(name, packageName);
12
+ }
13
+ return this;
14
+ }
15
+ appendAnnotation(name, packageName, args) {
16
+ const allArgs = [];
17
+ if (args) {
18
+ for (const a of args) {
19
+ if (!Array.isArray(a)) {
20
+ allArgs.push([undefined, a]);
21
+ }
22
+ else if (a.length === 2 && a[1] === true) {
23
+ allArgs.push([undefined, a[0]]);
24
+ }
25
+ }
26
+ for (const a of args) {
27
+ if (Array.isArray(a) && typeof a[1] !== 'boolean' && a[2] !== false) {
28
+ allArgs.push(a.length === 2 ? a : [a[0], a[1]]);
29
+ }
30
+ }
31
+ }
32
+ this.append(`@${name}`).addImport(name, packageName);
33
+ if (allArgs.length > 0) {
34
+ const multiline = allArgs.some((x) => typeof x[1] !== 'string') ||
35
+ allArgs.reduce((c, [key, value]) => { var _a; return c + (key ? key.length + 3 : 0) + ((_a = value === null || value === void 0 ? void 0 : value.length) !== null && _a !== void 0 ? _a : 0); }, 0) > 80;
36
+ this.parenthesize('()', (builder) => builder
37
+ .appendLineIf(multiline)
38
+ .forEachSeparated(allArgs, multiline ? ',\n' : ', ', (builder, [name, value]) => builder
39
+ .append(name ? `${name} = ` : '')
40
+ .apply((builder) => (typeof value === 'string' ? builder.append(value) : value(builder))))
41
+ .appendLineIf(multiline));
42
+ }
43
+ this.appendLine();
44
+ return this;
45
+ }
46
+ clear() {
47
+ super.clear();
48
+ this.imports.clear();
49
+ }
50
+ toString(addPadding = true) {
51
+ return new SourceBuilder(this.options)
52
+ .applyIf(this.packageName !== undefined, (builder) => builder.appendLine(`package ${this.packageName}`).appendLine())
53
+ .apply((builder) => this.imports.writeTo(builder))
54
+ .applyIf(addPadding, (builder) => builder.ensurePreviousLineEmpty())
55
+ .append(super.toString())
56
+ .applyIf(addPadding, (builder) => builder.ensureCurrentLineEmpty())
57
+ .toString();
58
+ }
59
+ }
@@ -0,0 +1,13 @@
1
+ import { toCasing } from '@goast/core';
2
+ import { toKotlinPropertyName, toKotlinStringLiteral } from '../utils';
3
+ export class KotlinFileGenerator {
4
+ toPropertyName(context, name) {
5
+ return toKotlinPropertyName(toCasing(name, context.config.propertyNameCasing));
6
+ }
7
+ toEnumValueName(context, name) {
8
+ return toKotlinPropertyName(toCasing(name, context.config.enumValueNameCasing));
9
+ }
10
+ toStringLiteral(context, text) {
11
+ return toKotlinStringLiteral(text);
12
+ }
13
+ }
@@ -0,0 +1,3 @@
1
+ export * from './file-generator';
2
+ export * from './models';
3
+ export * from './services/spring-controllers';
@@ -0,0 +1,3 @@
1
+ export * from './model-generator';
2
+ export * from './models';
3
+ export * from './models-generator';