@goast/kotlin 0.5.14 → 0.6.0-beta.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 (115) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +45 -45
  3. package/assets/client/okhttp3/ApiAbstractions.kt +30 -30
  4. package/assets/client/okhttp3/ApiClient.kt +252 -252
  5. package/assets/client/okhttp3/ApiResponse.kt +43 -43
  6. package/assets/client/okhttp3/Errors.kt +21 -21
  7. package/assets/client/okhttp3/PartConfig.kt +11 -11
  8. package/assets/client/okhttp3/RequestConfig.kt +18 -18
  9. package/assets/client/okhttp3/RequestMethod.kt +8 -8
  10. package/assets/client/okhttp3/ResponseExtensions.kt +24 -24
  11. package/assets/client/spring-reactive-web-clients/ApiRequestFile.kt +33 -33
  12. package/esm/src/generators/models/model-generator.d.ts.map +1 -1
  13. package/esm/src/generators/models/model-generator.js +5 -14
  14. package/esm/src/generators/services/okhttp3-clients/okhttp3-client-generator.d.ts.map +1 -1
  15. package/esm/src/generators/services/okhttp3-clients/okhttp3-client-generator.js +40 -47
  16. package/esm/src/generators/services/okhttp3-clients/okhttp3-clients-generator.js +9 -9
  17. package/esm/src/generators/services/spring-controllers/spring-controller-generator.d.ts.map +1 -1
  18. package/esm/src/generators/services/spring-controllers/spring-controller-generator.js +32 -42
  19. package/esm/src/generators/services/spring-reactive-web-clients/spring-reactive-web-client-generator.d.ts.map +1 -1
  20. package/esm/src/generators/services/spring-reactive-web-clients/spring-reactive-web-client-generator.js +16 -25
  21. package/esm/src/utils.d.ts +1 -3
  22. package/esm/src/utils.d.ts.map +1 -1
  23. package/esm/src/utils.js +0 -7
  24. package/package.json +2 -2
  25. package/script/src/generators/models/model-generator.d.ts.map +1 -1
  26. package/script/src/generators/models/model-generator.js +4 -13
  27. package/script/src/generators/services/okhttp3-clients/okhttp3-client-generator.d.ts.map +1 -1
  28. package/script/src/generators/services/okhttp3-clients/okhttp3-client-generator.js +39 -46
  29. package/script/src/generators/services/okhttp3-clients/okhttp3-clients-generator.js +9 -9
  30. package/script/src/generators/services/spring-controllers/spring-controller-generator.d.ts.map +1 -1
  31. package/script/src/generators/services/spring-controllers/spring-controller-generator.js +31 -41
  32. package/script/src/generators/services/spring-reactive-web-clients/spring-reactive-web-client-generator.d.ts.map +1 -1
  33. package/script/src/generators/services/spring-reactive-web-clients/spring-reactive-web-client-generator.js +15 -24
  34. package/script/src/utils.d.ts +1 -3
  35. package/script/src/utils.d.ts.map +1 -1
  36. package/script/src/utils.js +0 -9
  37. package/src/mod.ts +0 -8
  38. package/src/src/assets.ts +0 -9
  39. package/src/src/ast/_index.ts +0 -66
  40. package/src/src/ast/common.ts +0 -1
  41. package/src/src/ast/index.ts +0 -1
  42. package/src/src/ast/node.ts +0 -10
  43. package/src/src/ast/nodes/annotation.ts +0 -79
  44. package/src/src/ast/nodes/argument.ts +0 -62
  45. package/src/src/ast/nodes/call.ts +0 -75
  46. package/src/src/ast/nodes/class.ts +0 -178
  47. package/src/src/ast/nodes/collection-literal.ts +0 -49
  48. package/src/src/ast/nodes/constructor.ts +0 -126
  49. package/src/src/ast/nodes/doc-tag.ts +0 -138
  50. package/src/src/ast/nodes/doc.ts +0 -111
  51. package/src/src/ast/nodes/enum-value.ts +0 -100
  52. package/src/src/ast/nodes/enum.ts +0 -163
  53. package/src/src/ast/nodes/function.ts +0 -178
  54. package/src/src/ast/nodes/generic-parameter.ts +0 -54
  55. package/src/src/ast/nodes/init-block.ts +0 -38
  56. package/src/src/ast/nodes/interface.ts +0 -133
  57. package/src/src/ast/nodes/lambda-type.ts +0 -73
  58. package/src/src/ast/nodes/lambda.ts +0 -74
  59. package/src/src/ast/nodes/object.ts +0 -102
  60. package/src/src/ast/nodes/parameter.ts +0 -118
  61. package/src/src/ast/nodes/property.ts +0 -225
  62. package/src/src/ast/nodes/reference.ts +0 -178
  63. package/src/src/ast/nodes/string.ts +0 -114
  64. package/src/src/ast/nodes/types.ts +0 -23
  65. package/src/src/ast/references/index.ts +0 -10
  66. package/src/src/ast/references/jackson.ts +0 -59
  67. package/src/src/ast/references/jakarta.ts +0 -14
  68. package/src/src/ast/references/java.ts +0 -27
  69. package/src/src/ast/references/kotlin.ts +0 -41
  70. package/src/src/ast/references/kotlinx.ts +0 -14
  71. package/src/src/ast/references/okhttp3.ts +0 -5
  72. package/src/src/ast/references/reactor.ts +0 -5
  73. package/src/src/ast/references/spring-reactive.ts +0 -37
  74. package/src/src/ast/references/spring.ts +0 -86
  75. package/src/src/ast/references/swagger.ts +0 -23
  76. package/src/src/ast/utils/get-kotlin-builder-options.ts +0 -19
  77. package/src/src/ast/utils/to-kt-node.ts +0 -31
  78. package/src/src/ast/utils/write-kt-annotations.ts +0 -15
  79. package/src/src/ast/utils/write-kt-arguments.ts +0 -45
  80. package/src/src/ast/utils/write-kt-enum-values.ts +0 -27
  81. package/src/src/ast/utils/write-kt-generic-parameters.ts +0 -12
  82. package/src/src/ast/utils/write-kt-members.ts +0 -25
  83. package/src/src/ast/utils/write-kt-node.ts +0 -37
  84. package/src/src/ast/utils/write-kt-parameters.ts +0 -25
  85. package/src/src/common-results.ts +0 -4
  86. package/src/src/config.ts +0 -61
  87. package/src/src/file-builder.ts +0 -112
  88. package/src/src/generators/file-generator.ts +0 -29
  89. package/src/src/generators/index.ts +0 -5
  90. package/src/src/generators/models/args.ts +0 -136
  91. package/src/src/generators/models/index.ts +0 -4
  92. package/src/src/generators/models/model-generator.ts +0 -736
  93. package/src/src/generators/models/models-generator.ts +0 -65
  94. package/src/src/generators/models/models.ts +0 -95
  95. package/src/src/generators/services/okhttp3-clients/args.ts +0 -90
  96. package/src/src/generators/services/okhttp3-clients/index.ts +0 -4
  97. package/src/src/generators/services/okhttp3-clients/models.ts +0 -73
  98. package/src/src/generators/services/okhttp3-clients/okhttp3-client-generator.ts +0 -627
  99. package/src/src/generators/services/okhttp3-clients/okhttp3-clients-generator.ts +0 -188
  100. package/src/src/generators/services/okhttp3-clients/refs.ts +0 -59
  101. package/src/src/generators/services/spring-controllers/args.ts +0 -95
  102. package/src/src/generators/services/spring-controllers/index.ts +0 -4
  103. package/src/src/generators/services/spring-controllers/models.ts +0 -76
  104. package/src/src/generators/services/spring-controllers/refs.ts +0 -17
  105. package/src/src/generators/services/spring-controllers/spring-controller-generator.ts +0 -1122
  106. package/src/src/generators/services/spring-controllers/spring-controllers-generator.ts +0 -140
  107. package/src/src/generators/services/spring-reactive-web-clients/args.ts +0 -112
  108. package/src/src/generators/services/spring-reactive-web-clients/index.ts +0 -4
  109. package/src/src/generators/services/spring-reactive-web-clients/models.ts +0 -78
  110. package/src/src/generators/services/spring-reactive-web-clients/refs.ts +0 -11
  111. package/src/src/generators/services/spring-reactive-web-clients/spring-reactive-web-client-generator.ts +0 -641
  112. package/src/src/generators/services/spring-reactive-web-clients/spring-reactive-web-clients-generator.ts +0 -125
  113. package/src/src/import-collection.ts +0 -98
  114. package/src/src/types.ts +0 -3
  115. package/src/src/utils.ts +0 -55
@@ -1,736 +0,0 @@
1
- import {
2
- type ApiSchema,
3
- type ApiSchemaKind,
4
- type ApiSchemaProperty,
5
- type AppendValue,
6
- type AppendValueGroup,
7
- appendValueGroup,
8
- type BasicAppendValue,
9
- builderTemplate as s,
10
- createOverwriteProxy,
11
- DEFAULT_IGNORED_SCHEMA_PROPERTIES,
12
- getSchemaReference,
13
- getSourceDisplayName,
14
- type MaybePromise,
15
- modify,
16
- modifyEach,
17
- notNullish,
18
- resolveAnyOfAndAllOf,
19
- type SourceBuilder,
20
- toCasing,
21
- } from '@goast/core';
22
-
23
- import { kt } from '../../ast/index.js';
24
- import { KotlinFileBuilder } from '../../file-builder.js';
25
- import { getSourceDocLine, getStringEnumSchema } from '../../utils.js';
26
- import { KotlinFileGenerator } from '../file-generator.js';
27
- import type { DefaultKotlinModelGeneratorArgs as Args } from './index.js';
28
- import type { KotlinModelGeneratorContext, KotlinModelGeneratorOutput } from './models.js';
29
-
30
- type Context = KotlinModelGeneratorContext;
31
- type Output = KotlinModelGeneratorOutput;
32
- type Builder = KotlinFileBuilder;
33
-
34
- export interface KotlinModelGenerator<TOutput extends Output = Output> {
35
- generate(ctx: Context): MaybePromise<TOutput>;
36
- }
37
-
38
- export class DefaultKotlinModelGenerator extends KotlinFileGenerator<Context, Output> implements KotlinModelGenerator {
39
- public generate(ctx: Context): MaybePromise<KotlinModelGeneratorOutput> {
40
- if (/\/(anyOf|allOf)(\/[0-9]+)?$/.test(ctx.schema.$src.path)) {
41
- // Do not generate types that are only used for anyOf and/or allOf
42
- return { type: kt.refs.any({ nullable: true }) };
43
- }
44
-
45
- const schemaReference = getSchemaReference(ctx.schema, DEFAULT_IGNORED_SCHEMA_PROPERTIES);
46
- if (schemaReference !== ctx.schema) {
47
- const typeName = this.getDeclarationTypeName(ctx, { schema: schemaReference });
48
- const packageName = this.getPackageName(ctx, { schema: schemaReference });
49
- return { type: kt.reference(typeName, packageName) };
50
- }
51
-
52
- if (this.shouldGenerateTypeDeclaration(ctx, { schema: ctx.schema })) {
53
- const typeName = this.getDeclarationTypeName(ctx, { schema: ctx.schema });
54
- const packageName = this.getPackageName(ctx, { schema: ctx.schema });
55
- const filePath = `${ctx.config.outputDir}/${packageName.replace(/\./g, '/')}/${typeName}.kt`;
56
-
57
- console.log(
58
- `Generating model ${getSourceDisplayName(ctx.data, ctx.schema)} [${packageName}.${typeName}] to ${filePath}...`,
59
- );
60
- const builder = new KotlinFileBuilder(packageName, ctx.config);
61
- builder.append(this.getFileContent(ctx, {}));
62
- builder.writeToFile(filePath);
63
-
64
- return { type: kt.reference(typeName, packageName) };
65
- } else {
66
- return { type: this.getType(ctx, { schema: ctx.schema }) };
67
- }
68
- }
69
-
70
- protected getFileContent(ctx: Context, _args: Args.GetFileContent): AppendValueGroup<Builder> {
71
- return appendValueGroup<Builder>(
72
- [this.getSchemaDeclaration(ctx, { schema: this.normalizeSchema(ctx, { schema: ctx.schema }) })],
73
- '\n\n',
74
- );
75
- }
76
-
77
- protected getSchemaDeclaration(ctx: Context, args: Args.GetSchemaDeclaration): AppendValue<Builder> {
78
- const { schema } = args;
79
-
80
- if (schema.kind === 'object') {
81
- return schema.discriminator ? this.getInterface(ctx, { schema }) : this.getClass(ctx, { schema });
82
- } else if (schema.enum !== undefined && schema.enum.length > 0) {
83
- return this.getEnum(ctx, { schema });
84
- }
85
-
86
- return '// The generator was not able to generate this schema.\n// This should not happend. If you see this comment, please open an Issue on Github.';
87
- }
88
-
89
- protected getClass(ctx: Context, args: Args.GetClass): kt.Class<Builder> {
90
- const { schema } = args;
91
- const inheritedSchemas = this.getInheritedSchemas(ctx, { schema });
92
- const parameters = this.getClassProperties(ctx, { schema });
93
-
94
- return kt.class(this.getDeclarationTypeName(ctx, { schema }), {
95
- doc: kt.doc(this.getSchemaDocDescription(ctx, { schema })),
96
- annotations: [
97
- this.getJacksonJsonClassDescriptionAnnotation(ctx, { schema }),
98
- schema.deprecated ? kt.annotation(kt.refs.deprecated(), [kt.argument(kt.string(''))]) : null,
99
- ],
100
- classKind: parameters.length === 0 ? null : 'data',
101
- implements: inheritedSchemas.map((schema) => this.getType(ctx, { schema, nullable: false })),
102
- primaryConstructor: kt.constructor(
103
- parameters.map((property) => this.getClassParameter(ctx, { ...args, inheritedSchemas, parameters, property })),
104
- ),
105
- members: [
106
- ...(schema.additionalProperties !== undefined && schema.additionalProperties !== false
107
- ? [
108
- this.getAdditionalPropertiesProperty(ctx, { schema }),
109
- this.getAdditionalPropertiesSetter(ctx, { schema }),
110
- this.getAdditionalPropertiesGetter(ctx, { schema }),
111
- ]
112
- : []),
113
- ],
114
- });
115
- }
116
-
117
- protected getInterface(ctx: Context, args: Args.GetInterface): kt.Interface<Builder> {
118
- const { schema } = args;
119
-
120
- return kt.interface(this.getDeclarationTypeName(ctx, { schema }), {
121
- doc: kt.doc(this.getSchemaDocDescription(ctx, { schema })),
122
- annotations: [
123
- this.getJacksonJsonTypeInfoAnnotation(ctx, { schema }),
124
- this.getJacksonJsonSubTypesAnnotation(ctx, { schema }),
125
- this.getJacksonJsonClassDescriptionAnnotation(ctx, { schema }),
126
- schema.deprecated ? kt.annotation(kt.refs.deprecated(), [kt.argument(kt.string(''))]) : null,
127
- ].filter(notNullish),
128
- members: this.sortProperties(ctx, { schema, properties: schema.properties.values() }).map((property) =>
129
- this.getInterfaceProperty(ctx, { schema, property })
130
- ),
131
- });
132
- }
133
-
134
- protected getEnum(ctx: Context, args: Args.GetEnum): kt.Enum<Builder> {
135
- const { schema } = args;
136
-
137
- const name = this.getDeclarationTypeName(ctx, { schema });
138
- return kt.enum(
139
- name,
140
- schema.enum?.map((x) =>
141
- kt.enumValue(toCasing(String(x), ctx.config.enumValueNameCasing), {
142
- annotations: [kt.annotation(kt.refs.jackson.jsonProperty(), [kt.argument(kt.string(String(x)))])],
143
- arguments: [kt.argument(kt.string(String(x)))],
144
- })
145
- ) ?? [],
146
- {
147
- doc: kt.doc(this.getSchemaDocDescription(ctx, { schema })),
148
- annotations: [schema.deprecated ? kt.annotation(kt.refs.deprecated(), [kt.argument(kt.string(''))]) : null],
149
- primaryConstructor: kt.constructor([
150
- kt.parameter.class(toCasing('value', ctx.config.propertyNameCasing), kt.refs.string(), {
151
- property: 'readonly',
152
- }),
153
- ]),
154
- companionObject: kt.object({
155
- members: [
156
- kt.function('fromValue', {
157
- parameters: [kt.parameter('value', kt.refs.string())],
158
- returnType: kt.reference(name, null, { nullable: true }),
159
- singleExpression: true,
160
- body: !schema.enum?.length ? 'null' : s`\nwhen(value) {${s.indent`${
161
- appendValueGroup([
162
- schema.enum.map((x) =>
163
- s`\n${kt.string(String(x))} -> ${toCasing(String(x), ctx.config.enumValueNameCasing)}`
164
- ),
165
- ])
166
- }
167
- else -> null`}
168
- }`,
169
- }),
170
- ],
171
- }),
172
- },
173
- );
174
- }
175
-
176
- protected getSchemaDocDescription(ctx: Context, args: Args.GetSchemaDocDescription): BasicAppendValue<Builder> {
177
- const docSegments = [args.schema.description?.trim()];
178
-
179
- if (ctx.config.includeSourceInDocs) {
180
- docSegments.push(getSourceDocLine(args.schema));
181
- }
182
-
183
- return docSegments.filter(notNullish).join('\n\n');
184
- }
185
-
186
- protected getType(ctx: Context, args: Args.GetType): kt.Reference<SourceBuilder> {
187
- let { schema, nullable } = args;
188
-
189
- if (schema.kind === 'oneOf' && schema.oneOf.length === 2 && schema.oneOf.some((x) => x.kind === 'null')) {
190
- const nonNullSchema = schema.oneOf.find((x) => x.kind !== 'null')!;
191
- if (nonNullSchema) {
192
- schema = nonNullSchema;
193
- nullable ??= true;
194
- }
195
- }
196
-
197
- const generatedType = this.getGeneratedType(ctx, { schema, nullable });
198
- if (generatedType) {
199
- return generatedType;
200
- }
201
-
202
- nullable ??= schema.nullable;
203
- switch (schema.kind) {
204
- case 'boolean':
205
- return kt.refs.boolean({ nullable });
206
- case 'integer':
207
- case 'number':
208
- switch (schema.format) {
209
- case 'int32':
210
- return kt.refs.int({ nullable });
211
- case 'int64':
212
- return kt.refs.long({ nullable });
213
- case 'float':
214
- return kt.refs.float({ nullable });
215
- case 'double':
216
- return kt.refs.double({ nullable });
217
- default:
218
- return schema.kind === 'integer' ? kt.refs.int({ nullable }) : kt.refs.double({ nullable });
219
- }
220
- case 'string':
221
- switch (schema.format) {
222
- case 'date-time':
223
- return kt.refs.java.offsetDateTime({ nullable });
224
- case 'time':
225
- return kt.refs.java.offsetTime({ nullable });
226
- case 'date':
227
- return kt.refs.java.localDate({ nullable });
228
- case 'local-date-time':
229
- return kt.refs.java.localDateTime({ nullable });
230
- case 'local-time':
231
- return kt.refs.java.localTime({ nullable });
232
- case 'uri':
233
- return kt.refs.java.uri({ nullable });
234
- default:
235
- return kt.refs.string({ nullable });
236
- }
237
- case 'null':
238
- return kt.refs.nothing({ nullable });
239
- case 'unknown':
240
- return kt.refs.any({ nullable });
241
- case 'array':
242
- return kt.refs.list(
243
- [schema.items ? this.getType(ctx, { schema: schema.items }) : kt.refs.any({ nullable: true })],
244
- { nullable },
245
- );
246
- case 'object':
247
- return schema.properties.size === 0 && schema.additionalProperties
248
- ? kt.refs.map([kt.refs.string(), this.getAdditionalPropertiesType(ctx, { schema })], { nullable })
249
- : kt.refs.any({ nullable });
250
- default:
251
- return kt.refs.any({ nullable });
252
- }
253
- }
254
-
255
- protected getGeneratedType(ctx: Context, args: Args.GetGeneratedType): kt.Reference<SourceBuilder> | null {
256
- const schema = getSchemaReference(args.schema, DEFAULT_IGNORED_SCHEMA_PROPERTIES);
257
- if (this.shouldGenerateTypeDeclaration(ctx, { schema })) {
258
- return kt.reference(this.getDeclarationTypeName(ctx, { schema }), this.getPackageName(ctx, { schema }), {
259
- nullable: args.nullable ?? schema.nullable,
260
- });
261
- }
262
- return null;
263
- }
264
-
265
- protected getAdditionalPropertiesType(
266
- ctx: Context,
267
- args: Args.GetAdditionalPropertiesType,
268
- ): kt.Reference<SourceBuilder> {
269
- const { schema } = args;
270
-
271
- return typeof schema.additionalProperties === 'object'
272
- ? this.getType(ctx, { schema: schema.additionalProperties })
273
- : kt.refs.any({ nullable: true });
274
- }
275
-
276
- protected getDefaultValue(ctx: Context, args: Args.GetDefaultValue): kt.Value<Builder> {
277
- const { schema } = args;
278
-
279
- if (schema.default === null || schema.default === undefined) {
280
- return 'null';
281
- } else {
282
- switch (schema.kind) {
283
- case 'boolean':
284
- return Boolean(schema.default) || String(schema.default).toLowerCase() === 'true' ? 'true' : 'false';
285
- case 'integer':
286
- case 'number':
287
- return String(schema.default);
288
- case 'string':
289
- return schema.enum && schema.enum.length > 0
290
- ? kt.call([this.getType(ctx, { schema }), toCasing(String(schema.default), ctx.config.enumValueNameCasing)])
291
- : kt.string(String(schema.default));
292
- case 'array': {
293
- const itemEnumSchema = getStringEnumSchema(schema.items);
294
- return kt.call(
295
- kt.refs.listOf.infer(),
296
- Array.isArray(schema.default)
297
- ? schema.default.map((x) =>
298
- itemEnumSchema
299
- ? kt.call([
300
- this.getType(ctx, { schema: itemEnumSchema }),
301
- toCasing(String(x), ctx.config.enumValueNameCasing),
302
- ])
303
- : kt.toNode(x)
304
- )
305
- : [],
306
- );
307
- }
308
- default:
309
- return 'null';
310
- }
311
- }
312
- }
313
-
314
- // #region Members
315
- protected getClassParameter(ctx: Context, args: Args.GetClassParameter): kt.Parameter<Builder> {
316
- const { schema, inheritedSchemas, property } = args;
317
-
318
- return kt.parameter.class(
319
- toCasing(property.name, ctx.config.propertyNameCasing),
320
- this.getType(ctx, { schema: property.schema, nullable: schema.required.has(property.name) ? undefined : true }),
321
- {
322
- description: property.schema.description?.trim(),
323
- annotations: [
324
- ...this.getJakartaValidationAnnotations(ctx, { schema, property }),
325
- this.getSwaggerSchemaAnnotation(ctx, { schema, property }),
326
- modify(this.getJacksonJsonPropertyAnnotation(ctx, { schema, property }), (x) => (x.target = 'param')),
327
- ...modifyEach(
328
- [
329
- this.getJacksonJsonPropertyAnnotation(ctx, { schema, property }),
330
- this.getJacksonJsonPropertyDescriptionAnnotation(ctx, { schema, property }),
331
- this.getJacksonJsonIncludeAnnotation(ctx, { schema, property }),
332
- ].filter(notNullish),
333
- (x) => (x.target = 'get'),
334
- ),
335
- property.schema.deprecated ? kt.annotation(kt.refs.deprecated(), [kt.argument(kt.string(''))]) : null,
336
- ].filter(notNullish),
337
- override: inheritedSchemas.some((schema) => this.hasProperty(ctx, { schema, propertyName: property.name })),
338
- property: 'readonly',
339
- default: property.schema.default !== undefined || !schema.required.has(property.name)
340
- ? this.getDefaultValue(ctx, { schema: property.schema })
341
- : null,
342
- },
343
- );
344
- }
345
-
346
- protected getInterfaceProperty(ctx: Context, args: Args.GetInterfaceProperty): kt.Property<Builder> {
347
- const { schema, property } = args;
348
-
349
- return kt.property(toCasing(property.name, ctx.config.propertyNameCasing), {
350
- doc: kt.doc(this.getSchemaDocDescription(ctx, { schema: property.schema })),
351
- annotations: modifyEach(
352
- [
353
- this.getJacksonJsonPropertyAnnotation(ctx, { schema, property }),
354
- this.getJacksonJsonPropertyDescriptionAnnotation(ctx, { schema, property }),
355
- this.getJacksonJsonIncludeAnnotation(ctx, { schema, property }),
356
- property.schema.deprecated ? kt.annotation(kt.refs.deprecated(), [kt.argument(kt.string(''))]) : null,
357
- ].filter(notNullish),
358
- (x) => (x.target = 'get'),
359
- ),
360
- type: this.getType(ctx, {
361
- schema: property.schema,
362
- nullable: schema.required.has(property.name) ? undefined : true,
363
- }),
364
- });
365
- }
366
-
367
- protected getAdditionalPropertiesProperty(
368
- ctx: Context,
369
- args: Args.GetAdditionalPropertiesProperty,
370
- ): kt.Property<Builder> {
371
- const { schema } = args;
372
-
373
- return kt.property(toCasing('additionalProperties', ctx.config.propertyNameCasing), {
374
- annotations: [kt.annotation(kt.refs.jackson.jsonIgnore())],
375
- type: kt.reference('MutableMap', null, {
376
- generics: ['String', this.getAdditionalPropertiesType(ctx, { schema })],
377
- }),
378
- default: 'mutableMapOf()',
379
- });
380
- }
381
-
382
- protected getAdditionalPropertiesSetter(
383
- ctx: Context,
384
- args: Args.GetAdditionalPropertiesSetter,
385
- ): kt.Function<Builder> {
386
- const { schema } = args;
387
-
388
- return kt.function(toCasing('set', ctx.config.functionNameCasing), {
389
- annotations: [kt.annotation(kt.refs.jackson.jsonAnySetter())],
390
- parameters: [
391
- kt.parameter(toCasing('name', ctx.config.parameterNameCasing), 'String'),
392
- kt.parameter(
393
- toCasing('value', ctx.config.parameterNameCasing),
394
- this.getAdditionalPropertiesType(ctx, { schema }),
395
- ),
396
- ],
397
- body: `this.${toCasing('additionalProperties', ctx.config.propertyNameCasing)}[name] = value`,
398
- });
399
- }
400
-
401
- protected getAdditionalPropertiesGetter(
402
- ctx: Context,
403
- args: Args.GetAdditionalPropertiesGetter,
404
- ): kt.Function<Builder> {
405
- const { schema } = args;
406
-
407
- return kt.function(toCasing('getMap', ctx.config.functionNameCasing), {
408
- annotations: [kt.annotation(kt.refs.jackson.jsonAnyGetter())],
409
- returnType: kt.refs.map([kt.refs.string(), this.getAdditionalPropertiesType(ctx, { schema })]),
410
- body: `return this.${toCasing('additionalProperties', ctx.config.propertyNameCasing)}`,
411
- });
412
- }
413
- // #endregion
414
-
415
- // #region Annotations
416
- protected getJacksonJsonTypeInfoAnnotation(
417
- ctx: Context,
418
- args: Args.GetJacksonJsonTypeInfoAnnotation,
419
- ): kt.Annotation<Builder> | null {
420
- const { schema } = args;
421
-
422
- return ctx.config.addJacksonAnnotations && schema.discriminator
423
- ? kt.annotation(kt.refs.jackson.jsonTypeInfo(), [
424
- kt.argument.named('use', 'JsonTypeInfo.Id.NAME'),
425
- kt.argument.named(
426
- 'include',
427
- 'properties' in schema && schema.properties.has(schema.discriminator.propertyName)
428
- ? 'JsonTypeInfo.As.EXISTING_PROPERTY'
429
- : 'JsonTypeInfo.As.PROPERTY',
430
- ),
431
- kt.argument.named('property', kt.string(schema.discriminator.propertyName)),
432
- kt.argument.named('visible', 'true'),
433
- ])
434
- : null;
435
- }
436
-
437
- protected getJacksonJsonSubTypesAnnotation(
438
- ctx: Context,
439
- args: Args.GetJacksonJsonSubTypesAnnotation,
440
- ): kt.Annotation<Builder> | null {
441
- const { schema } = args;
442
-
443
- if (!ctx.config.addJacksonAnnotations || !schema.discriminator) return null;
444
- const entries = Object.entries(schema.discriminator.mapping);
445
- return entries.length > 0
446
- ? kt.annotation(
447
- kt.refs.jackson.jsonSubTypes(),
448
- entries.map(([value, schema]) =>
449
- kt.argument(
450
- kt.call(
451
- [kt.refs.jackson.jsonSubTypes(), 'Type'],
452
- [
453
- kt.argument.named(
454
- 'value',
455
- modify(this.getType(ctx, { schema }), (x) => (x.classReference = true)),
456
- ),
457
- kt.argument.named('name', kt.string(value)),
458
- ],
459
- ),
460
- )
461
- ),
462
- )
463
- : null;
464
- }
465
-
466
- protected getJacksonJsonClassDescriptionAnnotation(
467
- ctx: Context,
468
- args: Args.GetJacksonJsonClassDescriptionAnnotation,
469
- ): kt.Annotation<Builder> | null {
470
- const { schema } = args;
471
-
472
- return ctx.config.addJacksonAnnotations && schema.description
473
- ? kt.annotation(kt.refs.jackson.jsonClassDescription(), [
474
- kt.argument(kt.string(schema.description)),
475
- ])
476
- : null;
477
- }
478
-
479
- protected getJacksonJsonPropertyAnnotation(
480
- ctx: Context,
481
- args: Args.GetJacksonJsonPropertyAnnotation,
482
- ): kt.Annotation<Builder> | null {
483
- const { schema, property } = args;
484
-
485
- return ctx.config.addJacksonAnnotations
486
- ? kt.annotation(kt.refs.jackson.jsonProperty(), [
487
- kt.argument(kt.string(property.name)),
488
- schema.required.has(property.name) ? kt.argument.named('required', 'true') : null,
489
- ])
490
- : null;
491
- }
492
-
493
- protected getJacksonJsonPropertyDescriptionAnnotation(
494
- ctx: Context,
495
- args: Args.GetJacksonJsonPropertyDescriptionAnnotation,
496
- ): kt.Annotation<Builder> | null {
497
- const { property } = args;
498
-
499
- return ctx.config.addJacksonAnnotations && property.schema.description
500
- ? kt.annotation(kt.refs.jackson.jsonPropertyDescription(), [
501
- kt.argument(kt.string(property.schema.description)),
502
- ])
503
- : null;
504
- }
505
-
506
- protected getJacksonJsonIncludeAnnotation(
507
- ctx: Context,
508
- args: Args.GetJacksonJsonIncludeAnnotation,
509
- ): kt.Annotation<Builder> | null {
510
- const { property } = args;
511
-
512
- return ctx.config.addJacksonAnnotations && property.schema.custom['exclude-when-null'] === true
513
- ? kt.annotation(kt.refs.jackson.jsonInclude(), [
514
- kt.argument(kt.call([kt.refs.jackson.jsonInclude(), 'Include', 'NON_NULL'])),
515
- ])
516
- : null;
517
- }
518
-
519
- protected getJakartaValidationAnnotations(
520
- ctx: Context,
521
- args: Args.GetJakartaValidationAnnotations,
522
- ): kt.Annotation<Builder>[] {
523
- const { property } = args;
524
- const annotations: kt.Annotation<Builder>[] = [];
525
- if (!ctx.config.addJakartaValidationAnnotations) {
526
- return annotations;
527
- }
528
-
529
- if (property.schema.kind === 'string') {
530
- if (property.schema.pattern) {
531
- annotations.push(
532
- kt.annotation(kt.refs.jakarta.pattern(), [kt.argument.named('regexp', kt.string(property.schema.pattern))], {
533
- target: 'get',
534
- }),
535
- );
536
- }
537
- if (property.schema.minLength === 1 && property.schema.maxLength === undefined) {
538
- annotations.push(kt.annotation(kt.refs.jakarta.notEmpty(), [], { target: 'get' }));
539
- } else if (property.schema.minLength !== undefined || property.schema.maxLength !== undefined) {
540
- annotations.push(kt.annotation(kt.refs.jakarta.size(), [
541
- property.schema.minLength !== undefined ? kt.argument.named('min', property.schema.minLength) : null,
542
- property.schema.maxLength !== undefined ? kt.argument.named('max', property.schema.maxLength) : null,
543
- ], { target: 'get' }));
544
- }
545
- } else if (property.schema.kind === 'number' || property.schema.kind === 'integer') {
546
- if (property.schema.minimum !== undefined) {
547
- annotations.push(
548
- kt.annotation(kt.refs.jakarta.min(), [kt.argument.named('value', property.schema.minimum)], {
549
- target: 'get',
550
- }),
551
- );
552
- }
553
- if (property.schema.maximum !== undefined) {
554
- annotations.push(
555
- kt.annotation(kt.refs.jakarta.max(), [kt.argument.named('value', property.schema.maximum)], {
556
- target: 'get',
557
- }),
558
- );
559
- }
560
- } else if (property.schema.kind === 'array') {
561
- if (property.schema.minItems !== undefined || property.schema.maxItems !== undefined) {
562
- annotations.push(kt.annotation(kt.refs.jakarta.size(), [
563
- property.schema.minItems !== undefined ? kt.argument.named('min', property.schema.minItems) : null,
564
- property.schema.maxItems !== undefined ? kt.argument.named('max', property.schema.maxItems) : null,
565
- ], { target: 'get' }));
566
- }
567
- }
568
-
569
- if (this.shouldGenerateTypeDeclaration(ctx, { schema: property.schema })) {
570
- annotations.push(kt.annotation(kt.refs.jakarta.valid(), [], { target: 'field' }));
571
- }
572
-
573
- return annotations;
574
- }
575
-
576
- protected getSwaggerSchemaAnnotation(
577
- ctx: Context,
578
- args: Args.GetSwaggerSchemaAnnotation,
579
- ): kt.Annotation<Builder> | null {
580
- const { schema, property } = args;
581
-
582
- return ctx.config.addSwaggerAnnotations
583
- ? kt.annotation(kt.refs.swagger.schema(), [
584
- property.schema.example !== undefined
585
- ? kt.argument.named('example', kt.string(String(property.schema.example)))
586
- : null,
587
- schema.required.has(property.name) ? kt.argument.named('required', 'true') : null,
588
- property.schema.description !== undefined
589
- ? kt.argument.named('description', kt.string(property.schema.description))
590
- : null,
591
- property.schema.deprecated ? kt.argument.named('deprecated', kt.toNode(property.schema.deprecated)) : null,
592
- ])
593
- : null;
594
- }
595
- // #endregion
596
-
597
- protected getPackageName(ctx: Context, args: Args.GetPackageName): string {
598
- const { schema } = args;
599
-
600
- const packageSuffix = typeof ctx.config.packageSuffix === 'string'
601
- ? ctx.config.packageSuffix
602
- : ctx.config.packageSuffix(schema);
603
- return ctx.config.packageName + packageSuffix;
604
- }
605
-
606
- protected shouldGenerateTypeDeclaration(ctx: Context, args: Args.ShouldGenerateTypeDeclaration): boolean {
607
- let { schema } = args;
608
-
609
- // All enum types should have its own type declaration
610
- if (schema.enum !== undefined && schema.enum.length > 0) {
611
- return true;
612
- }
613
-
614
- // All primitive types already exist and do not need its own type declaration
615
- if (
616
- schema.kind !== 'combined' &&
617
- schema.kind !== 'multi-type' &&
618
- schema.kind !== 'object' &&
619
- schema.kind !== 'oneOf'
620
- ) {
621
- return false;
622
- }
623
-
624
- // Too complex types cannot be represented in Kotlin, so they fallback to Any
625
- if (schema.kind === 'multi-type') {
626
- return false;
627
- }
628
- schema = this.normalizeSchema(ctx, { schema });
629
- if (schema.kind === 'combined' || schema.kind === 'oneOf') {
630
- return false;
631
- }
632
-
633
- // Schemas representable by a simple Map type do not need its own type declaration
634
- if (schema.kind === 'object' && schema.properties.size === 0 && schema.additionalProperties) {
635
- return false;
636
- }
637
-
638
- if (schema.kind === 'object' && ctx.config.emptyObjectTypeBehavior === 'use-any' && schema.properties.size === 0) {
639
- return false;
640
- }
641
-
642
- // Dynamically generated schemas do not have its own type declaration
643
- if (!ctx.data.schemas.some((x) => x.id === schema.id)) {
644
- return false;
645
- }
646
-
647
- // multipart schemas should not have its own type declaration
648
- if (schema.$src.path.endsWith('/requestBody/content/multipart/form-data/schema')) {
649
- return false;
650
- }
651
-
652
- return true;
653
- }
654
-
655
- protected getDeclarationTypeName(ctx: Context, args: Args.GetDeclarationTypeName): string {
656
- return toCasing(args.schema.name, ctx.config.typeNameCasing);
657
- }
658
-
659
- protected getInheritedSchemas(
660
- ctx: Context,
661
- args: Args.GetInheritedSchemas,
662
- ): (ApiSchema<ApiSchemaKind> & { discriminator: NonNullable<ApiSchema['discriminator']> })[] {
663
- return args.schema.inheritedSchemas
664
- .filter((schema) => this.shouldGenerateTypeDeclaration(ctx, { schema }) && !schema.isNameGenerated)
665
- .filter((item, index, self) => self.indexOf(item) === index);
666
- }
667
-
668
- protected getClassProperties(ctx: Context, args: Args.GetClassProperties): ApiSchemaProperty[] {
669
- const { schema } = args;
670
-
671
- const inheritedSchemas = this.getInheritedSchemas(ctx, { schema });
672
- const properties: ApiSchemaProperty[] = [];
673
- const appendedProperties: ApiSchemaProperty[] = [];
674
- for (const property of schema.properties.values()) {
675
- const discriminator = inheritedSchemas.find(
676
- (x) => x.discriminator?.propertyName === property.name,
677
- )?.discriminator;
678
- if (discriminator) {
679
- const schemaMappings = Object.entries(discriminator.mapping).filter(([_, v]) => v.id === schema.id);
680
- if (schemaMappings.length === 1) {
681
- const p = createOverwriteProxy(property);
682
- const s = createOverwriteProxy(p.schema);
683
- p.schema = s;
684
- s.default = schemaMappings[0][0];
685
- appendedProperties.push(p);
686
- continue;
687
- }
688
- }
689
-
690
- properties.push(property);
691
- }
692
-
693
- return [...this.sortProperties(ctx, { schema, properties }), ...appendedProperties];
694
- }
695
-
696
- protected sortProperties(_ctx: Context, args: Args.SortProperties): ApiSchemaProperty[] {
697
- return [...args.properties].sort((a, b) => classify(a) - classify(b));
698
-
699
- function classify(p: ApiSchemaProperty) {
700
- if (p.schema.default !== undefined) return 1;
701
- if (args.schema.required.has(p.name)) return 0;
702
- return 2;
703
- }
704
- }
705
-
706
- protected normalizeSchema(ctx: Context, args: Args.NormalizeSchema): ApiSchema {
707
- let { schema } = args;
708
-
709
- if (schema.kind === 'oneOf') {
710
- schema = ctx.config.oneOfBehavior === 'treat-as-any-of'
711
- // deno-lint-ignore no-explicit-any
712
- ? { ...(schema as any), kind: 'combined', anyOf: schema.oneOf, allOf: [], oneOf: undefined }
713
- // deno-lint-ignore no-explicit-any
714
- : { ...(schema as any), kind: 'combined', allOf: schema.oneOf, anyOf: [], oneOf: undefined };
715
- ctx.schema = schema;
716
- }
717
- if (schema.kind === 'object' || schema.kind === 'combined') {
718
- const mergedSchema = resolveAnyOfAndAllOf(schema, true);
719
- if (mergedSchema) {
720
- schema = mergedSchema;
721
- }
722
- }
723
-
724
- return schema;
725
- }
726
-
727
- protected hasProperty(ctx: Context, args: Args.HasProperty): boolean {
728
- const { schema, propertyName } = args;
729
-
730
- return (
731
- ('properties' in schema && schema.properties.has(propertyName)) ||
732
- ('anyOf' in schema && schema.anyOf.some((schema) => this.hasProperty(ctx, { schema, propertyName }))) ||
733
- ('allOf' in schema && schema.allOf.some((schema) => this.hasProperty(ctx, { schema, propertyName })))
734
- );
735
- }
736
- }