@goast/kotlin 0.5.7 → 0.5.9-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 (118) hide show
  1. package/LICENSE +21 -21
  2. package/assets/client/okhttp3/ApiAbstractions.kt +30 -30
  3. package/assets/client/okhttp3/ApiClient.kt +253 -253
  4. package/assets/client/okhttp3/ApiResponse.kt +43 -43
  5. package/assets/client/okhttp3/Errors.kt +21 -21
  6. package/assets/client/okhttp3/PartConfig.kt +11 -11
  7. package/assets/client/okhttp3/RequestConfig.kt +18 -18
  8. package/assets/client/okhttp3/RequestMethod.kt +8 -8
  9. package/assets/client/okhttp3/ResponseExtensions.kt +24 -24
  10. package/assets/client/spring-reactive-web-clients/ApiRequestFile.kt +33 -33
  11. package/esm/src/ast/references/jackson.d.ts +8 -5
  12. package/esm/src/ast/references/jackson.d.ts.map +1 -1
  13. package/esm/src/ast/references/jackson.js +14 -6
  14. package/esm/src/config.d.ts +10 -0
  15. package/esm/src/config.d.ts.map +1 -1
  16. package/esm/src/config.js +1 -0
  17. package/esm/src/generators/services/okhttp3-clients/okhttp3-client-generator.d.ts.map +1 -1
  18. package/esm/src/generators/services/okhttp3-clients/okhttp3-client-generator.js +36 -32
  19. package/esm/src/generators/services/okhttp3-clients/okhttp3-clients-generator.d.ts.map +1 -1
  20. package/esm/src/generators/services/okhttp3-clients/okhttp3-clients-generator.js +22 -6
  21. package/esm/src/generators/services/spring-controllers/spring-controller-generator.d.ts.map +1 -1
  22. package/esm/src/generators/services/spring-controllers/spring-controller-generator.js +23 -13
  23. package/esm/src/generators/services/spring-reactive-web-clients/spring-reactive-web-client-generator.d.ts.map +1 -1
  24. package/esm/src/generators/services/spring-reactive-web-clients/spring-reactive-web-client-generator.js +4 -1
  25. package/package.json +3 -3
  26. package/script/src/ast/references/jackson.d.ts +8 -5
  27. package/script/src/ast/references/jackson.d.ts.map +1 -1
  28. package/script/src/ast/references/jackson.js +20 -7
  29. package/script/src/config.d.ts +10 -0
  30. package/script/src/config.d.ts.map +1 -1
  31. package/script/src/config.js +1 -0
  32. package/script/src/generators/services/okhttp3-clients/okhttp3-client-generator.d.ts.map +1 -1
  33. package/script/src/generators/services/okhttp3-clients/okhttp3-client-generator.js +36 -32
  34. package/script/src/generators/services/okhttp3-clients/okhttp3-clients-generator.d.ts.map +1 -1
  35. package/script/src/generators/services/okhttp3-clients/okhttp3-clients-generator.js +22 -6
  36. package/script/src/generators/services/spring-controllers/spring-controller-generator.d.ts.map +1 -1
  37. package/script/src/generators/services/spring-controllers/spring-controller-generator.js +23 -13
  38. package/script/src/generators/services/spring-reactive-web-clients/spring-reactive-web-client-generator.d.ts.map +1 -1
  39. package/script/src/generators/services/spring-reactive-web-clients/spring-reactive-web-client-generator.js +4 -1
  40. package/src/mod.ts +0 -8
  41. package/src/src/assets.ts +0 -9
  42. package/src/src/ast/_index.ts +0 -66
  43. package/src/src/ast/common.ts +0 -1
  44. package/src/src/ast/index.ts +0 -1
  45. package/src/src/ast/node.ts +0 -10
  46. package/src/src/ast/nodes/annotation.ts +0 -79
  47. package/src/src/ast/nodes/argument.ts +0 -62
  48. package/src/src/ast/nodes/call.ts +0 -75
  49. package/src/src/ast/nodes/class.ts +0 -178
  50. package/src/src/ast/nodes/collection-literal.ts +0 -49
  51. package/src/src/ast/nodes/constructor.ts +0 -126
  52. package/src/src/ast/nodes/doc-tag.ts +0 -138
  53. package/src/src/ast/nodes/doc.ts +0 -111
  54. package/src/src/ast/nodes/enum-value.ts +0 -100
  55. package/src/src/ast/nodes/enum.ts +0 -163
  56. package/src/src/ast/nodes/function.ts +0 -178
  57. package/src/src/ast/nodes/generic-parameter.ts +0 -54
  58. package/src/src/ast/nodes/init-block.ts +0 -38
  59. package/src/src/ast/nodes/interface.ts +0 -133
  60. package/src/src/ast/nodes/lambda-type.ts +0 -73
  61. package/src/src/ast/nodes/lambda.ts +0 -74
  62. package/src/src/ast/nodes/object.ts +0 -102
  63. package/src/src/ast/nodes/parameter.ts +0 -118
  64. package/src/src/ast/nodes/property.ts +0 -225
  65. package/src/src/ast/nodes/reference.ts +0 -178
  66. package/src/src/ast/nodes/string.ts +0 -114
  67. package/src/src/ast/nodes/types.ts +0 -23
  68. package/src/src/ast/references/index.ts +0 -10
  69. package/src/src/ast/references/jackson.ts +0 -44
  70. package/src/src/ast/references/jakarta.ts +0 -14
  71. package/src/src/ast/references/java.ts +0 -27
  72. package/src/src/ast/references/kotlin.ts +0 -41
  73. package/src/src/ast/references/kotlinx.ts +0 -14
  74. package/src/src/ast/references/okhttp3.ts +0 -5
  75. package/src/src/ast/references/reactor.ts +0 -5
  76. package/src/src/ast/references/spring-reactive.ts +0 -33
  77. package/src/src/ast/references/spring.ts +0 -86
  78. package/src/src/ast/references/swagger.ts +0 -23
  79. package/src/src/ast/utils/get-kotlin-builder-options.ts +0 -19
  80. package/src/src/ast/utils/to-kt-node.ts +0 -31
  81. package/src/src/ast/utils/write-kt-annotations.ts +0 -15
  82. package/src/src/ast/utils/write-kt-arguments.ts +0 -45
  83. package/src/src/ast/utils/write-kt-enum-values.ts +0 -27
  84. package/src/src/ast/utils/write-kt-generic-parameters.ts +0 -12
  85. package/src/src/ast/utils/write-kt-members.ts +0 -25
  86. package/src/src/ast/utils/write-kt-node.ts +0 -37
  87. package/src/src/ast/utils/write-kt-parameters.ts +0 -25
  88. package/src/src/common-results.ts +0 -4
  89. package/src/src/config.ts +0 -48
  90. package/src/src/file-builder.ts +0 -112
  91. package/src/src/generators/file-generator.ts +0 -29
  92. package/src/src/generators/index.ts +0 -5
  93. package/src/src/generators/models/args.ts +0 -136
  94. package/src/src/generators/models/index.ts +0 -4
  95. package/src/src/generators/models/model-generator.ts +0 -725
  96. package/src/src/generators/models/models-generator.ts +0 -65
  97. package/src/src/generators/models/models.ts +0 -95
  98. package/src/src/generators/services/okhttp3-clients/args.ts +0 -90
  99. package/src/src/generators/services/okhttp3-clients/index.ts +0 -4
  100. package/src/src/generators/services/okhttp3-clients/models.ts +0 -73
  101. package/src/src/generators/services/okhttp3-clients/okhttp3-client-generator.ts +0 -609
  102. package/src/src/generators/services/okhttp3-clients/okhttp3-clients-generator.ts +0 -169
  103. package/src/src/generators/services/okhttp3-clients/refs.ts +0 -59
  104. package/src/src/generators/services/spring-controllers/args.ts +0 -95
  105. package/src/src/generators/services/spring-controllers/index.ts +0 -4
  106. package/src/src/generators/services/spring-controllers/models.ts +0 -76
  107. package/src/src/generators/services/spring-controllers/refs.ts +0 -17
  108. package/src/src/generators/services/spring-controllers/spring-controller-generator.ts +0 -1097
  109. package/src/src/generators/services/spring-controllers/spring-controllers-generator.ts +0 -140
  110. package/src/src/generators/services/spring-reactive-web-clients/args.ts +0 -103
  111. package/src/src/generators/services/spring-reactive-web-clients/index.ts +0 -4
  112. package/src/src/generators/services/spring-reactive-web-clients/models.ts +0 -62
  113. package/src/src/generators/services/spring-reactive-web-clients/refs.ts +0 -11
  114. package/src/src/generators/services/spring-reactive-web-clients/spring-reactive-web-client-generator.ts +0 -583
  115. package/src/src/generators/services/spring-reactive-web-clients/spring-reactive-web-clients-generator.ts +0 -125
  116. package/src/src/import-collection.ts +0 -98
  117. package/src/src/types.ts +0 -3
  118. package/src/src/utils.ts +0 -47
@@ -1,609 +0,0 @@
1
- import {
2
- type ApiParameter,
3
- type ApiSchema,
4
- type AppendValueGroup,
5
- appendValueGroup,
6
- type BasicAppendValue,
7
- builderTemplate as s,
8
- createOverwriteProxy,
9
- getSourceDisplayName,
10
- type MaybePromise,
11
- notNullish,
12
- resolveAnyOfAndAllOf,
13
- SourceBuilder,
14
- toCasing,
15
- } from '@goast/core';
16
-
17
- import { kt } from '../../../ast/index.js';
18
- import type { KtValue } from '../../../ast/nodes/types.js';
19
- import { KotlinFileBuilder } from '../../../file-builder.js';
20
- import type { ApiParameterWithMultipartInfo } from '../../../types.js';
21
- import { getSourceDocLine, modifyString } from '../../../utils.js';
22
- import { KotlinFileGenerator } from '../../file-generator.js';
23
- import type { DefaultKotlinOkHttp3GeneratorArgs as Args } from './index.js';
24
- import type { KotlinOkHttp3ClientGeneratorContext, KotlinOkHttp3ClientGeneratorOutput } from './models.js';
25
-
26
- type Context = KotlinOkHttp3ClientGeneratorContext;
27
- type Output = KotlinOkHttp3ClientGeneratorOutput;
28
- type Builder = KotlinFileBuilder;
29
-
30
- export interface KotlinOkHttp3Generator<TOutput extends Output = Output> {
31
- generate(ctx: Context): MaybePromise<TOutput>;
32
- }
33
-
34
- export class DefaultKotlinOkHttp3Generator extends KotlinFileGenerator<Context, Output>
35
- implements KotlinOkHttp3Generator {
36
- public generate(ctx: KotlinOkHttp3ClientGeneratorContext): MaybePromise<Output> {
37
- const typeName = this.getApiClientName(ctx, {});
38
- const packageName = this.getPackageName(ctx, {});
39
- const filePath = this.getFilePath(ctx, { packageName });
40
-
41
- console.log(`Generating client for service ${ctx.service.name} to ${filePath}...`);
42
- ctx.service.endpoints.forEach((endpoint) => {
43
- console.log(
44
- ` ${getSourceDisplayName(ctx.data, endpoint)} [${toCasing(endpoint.name, ctx.config.functionNameCasing)}]`,
45
- );
46
- });
47
- const builder = new KotlinFileBuilder(packageName, ctx.config);
48
- builder.append(this.getClientFileContent(ctx, {}));
49
- builder.writeToFile(filePath);
50
-
51
- return { typeName, packageName };
52
- }
53
-
54
- protected getClientFileContent(ctx: Context, _args: Args.GetClientFileContent): AppendValueGroup<Builder> {
55
- return appendValueGroup([this.getClientClass(ctx, {})]);
56
- }
57
-
58
- protected getClientClass(ctx: Context, _args: Args.GetClientClass): kt.Class<Builder> {
59
- const serializerAsParameter = ctx.config.serializer === 'parameter';
60
- return kt.class(this.getApiClientName(ctx, {}), {
61
- annotations: [
62
- ctx.service.endpoints.length === 0 || ctx.service.endpoints.some((x) => !x.deprecated)
63
- ? null
64
- : kt.annotation(kt.refs.deprecated(), [kt.argument(kt.string(''))]),
65
- ],
66
- extends: ctx.refs.apiClient(),
67
- primaryConstructor: kt.constructor(
68
- [
69
- serializerAsParameter ? kt.parameter('objectMapper', kt.refs.jackson.objectMapper()) : null,
70
- kt.parameter('basePath', kt.refs.string(), { default: 'defaultBasePath' }),
71
- kt.parameter('client', kt.refs.okhttp3.okHttpClient(), {
72
- default: 'defaultClient',
73
- }),
74
- serializerAsParameter ? null : kt.parameter('objectMapper', kt.refs.jackson.objectMapper(), {
75
- default: kt.call([ctx.refs.serializer(), 'jacksonObjectMapper']),
76
- }),
77
- ],
78
- null,
79
- {
80
- delegateTarget: 'super',
81
- delegateArguments: ['basePath', 'objectMapper', 'client'],
82
- },
83
- ),
84
- companionObject: this.getClientCompanionObject(ctx, {}),
85
- members: [
86
- ...ctx.service.endpoints.flatMap((endpoint) =>
87
- this.getEndpointClientMembers(ctx, { endpoint, parameters: this.getAllParameters(ctx, { endpoint }) })
88
- ),
89
- ...this.getAdditionalClientMembers(ctx, {}),
90
- ],
91
- });
92
- }
93
-
94
- protected getClientCompanionObject(ctx: Context, _args: Args.GetClientCompanionObject): kt.Object<Builder> {
95
- const result = kt.object<Builder>();
96
-
97
- result.members.push(
98
- kt.property('defaultBasePath', {
99
- annotations: [kt.annotation(kt.refs.jvmStatic())],
100
- type: kt.refs.string(),
101
- delegate: kt.refs.lazyFun.infer(),
102
- delegateArguments: [
103
- kt.lambda(
104
- [],
105
- kt.call(
106
- [kt.call([kt.refs.java.system(), 'getProperties'], []), 'getProperty'],
107
- [kt.call([ctx.refs.apiClient(), 'baseUrlKey']), kt.string(this.getBasePath(ctx, {}))],
108
- ),
109
- ),
110
- ],
111
- }),
112
- );
113
-
114
- return result;
115
- }
116
-
117
- protected getEndpointClientMembers(ctx: Context, args: Args.GetEndpointClientMembers): kt.ClassMember<Builder>[] {
118
- const { endpoint, parameters } = args;
119
- const responseSchema = this.getResponseSchema(ctx, { endpoint });
120
- return [
121
- this.getEndpointClientMethod(ctx, { endpoint, parameters, responseSchema }),
122
- this.getEndpointClientHttpInfoMethod(ctx, { endpoint, parameters, responseSchema }),
123
- this.getEndpointClientRequestConfigMethod(ctx, { endpoint, parameters }),
124
- ];
125
- }
126
-
127
- protected getEndpointClientMethod(ctx: Context, args: Args.GetEndpointClientMethod): kt.Function<Builder> {
128
- const { endpoint, parameters, responseSchema } = args;
129
-
130
- return kt.function(toCasing(endpoint.name, ctx.config.functionNameCasing), {
131
- doc: kt.doc(this.getEndpointDocDescription(ctx, { endpoint }), [
132
- kt.docTag('throws', 'IllegalStateException', 'If the request is not correctly configured'),
133
- kt.docTag('throws', 'IOException', 'Rethrows the OkHttp execute method exception'),
134
- kt.docTag(
135
- 'throws',
136
- 'UnsupportedOperationException',
137
- 'If the API returns an informational or redirection response',
138
- ),
139
- kt.docTag('throws', 'ClientException', 'If the API returns a client error response'),
140
- kt.docTag('throws', 'ServerException', 'If the API returns a server error response'),
141
- ]),
142
- annotations: [
143
- kt.annotation(kt.refs.throws(), [
144
- kt.refs.java.illegalStateException({ classReference: true }),
145
- kt.refs.java.ioException({ classReference: true }),
146
- kt.refs.java.unsupportedOperationException({ classReference: true }),
147
- ctx.refs.clientException({ classReference: true }),
148
- ctx.refs.serverException({ classReference: true }),
149
- ]),
150
- endpoint.deprecated ? kt.annotation(kt.refs.deprecated(), [kt.argument(kt.string(''))]) : null,
151
- ],
152
- parameters: parameters.map((p) => {
153
- return kt.parameter(
154
- toCasing(p.name, ctx.config.parameterNameCasing),
155
- this.getParameterType(ctx, { endpoint, parameter: p }),
156
- {
157
- description: p.description,
158
- default: this.getParameterDefaultValue(ctx, { endpoint, parameter: p }),
159
- },
160
- );
161
- }),
162
- returnType: this.getTypeUsage(ctx, { schema: responseSchema, fallback: kt.refs.unit() }),
163
- body: this.getEndpointClientMethodBody(ctx, { endpoint, parameters, responseSchema }),
164
- });
165
- }
166
-
167
- protected getEndpointClientMethodBody(
168
- ctx: Context,
169
- args: Args.GetEndpointClientMethodBody,
170
- ): AppendValueGroup<Builder> {
171
- const { endpoint, parameters, responseSchema } = args;
172
-
173
- return appendValueGroup(
174
- [
175
- s`val localVarResponse = ${
176
- kt.call(
177
- [toCasing(endpoint.name + '_WithHttpInfo', ctx.config.functionNameCasing)],
178
- parameters.map((x) => toCasing(x.name, ctx.config.parameterNameCasing)),
179
- )
180
- }`,
181
- '',
182
- s`return when (localVarResponse.responseType) {${s.indent`
183
- ${ctx.refs.responseType()}.Success -> ${
184
- responseSchema === undefined
185
- ? kt.refs.unit()
186
- : s`(localVarResponse as ${ctx.refs.success(['*'])}).data as ${
187
- this.getTypeUsage(ctx, {
188
- schema: responseSchema,
189
- })
190
- }`
191
- }
192
- ${ctx.refs.responseType()}.Informational -> throw ${kt.refs.java.unsupportedOperationException()}("Client does not support Informational responses.")
193
- ${ctx.refs.responseType()}.Redirection -> throw ${kt.refs.java.unsupportedOperationException()}("Client does not support Redirection responses.")
194
- ${ctx.refs.responseType()}.ClientError -> {${s.indent`
195
- val localVarError = localVarResponse as ${ctx.refs.clientError(['*'])}
196
- throw ${ctx.refs.clientException()}(${s.indent`
197
- "Client error : \${localVarError.statusCode} \${localVarError.message.orEmpty()}",
198
- localVarError.statusCode,
199
- localVarResponse`}
200
- )`}
201
- }
202
-
203
- ${ctx.refs.responseType()}.ServerError -> {${s.indent`
204
- val localVarError = localVarResponse as ${ctx.refs.serverError(['*'])}
205
- throw ${ctx.refs.serverException()}(${s.indent`
206
- "Server error : \${localVarError.statusCode} \${localVarError.message.orEmpty()}",
207
- localVarError.statusCode,
208
- localVarResponse`}
209
- )`}
210
- }`}
211
- }`,
212
- ],
213
- '\n',
214
- );
215
- }
216
-
217
- protected getEndpointClientHttpInfoMethod(
218
- ctx: Context,
219
- args: Args.GetEndpointClientHttpInfoMethod,
220
- ): kt.Function<Builder> {
221
- const { endpoint, parameters, responseSchema } = args;
222
-
223
- return kt.function(toCasing(args.endpoint.name, ctx.config.functionNameCasing) + 'WithHttpInfo', {
224
- doc: kt.doc(this.getEndpointDocDescription(ctx, { endpoint }), [
225
- kt.docTag('throws', 'IllegalStateException', 'If the request is not correctly configured'),
226
- kt.docTag('throws', 'IOException', 'Rethrows the OkHttp execute method exception'),
227
- ]),
228
- annotations: [
229
- kt.annotation(kt.refs.throws(), [
230
- kt.refs.java.illegalStateException({ classReference: true }),
231
- kt.refs.java.ioException({ classReference: true }),
232
- ]),
233
- endpoint.deprecated ? kt.annotation(kt.refs.deprecated(), [kt.argument(kt.string(''))]) : null,
234
- ],
235
- parameters: parameters.map((p) =>
236
- kt.parameter(
237
- toCasing(p.name, ctx.config.parameterNameCasing),
238
- this.getParameterType(ctx, { endpoint, parameter: p }),
239
- {
240
- description: p.description,
241
- default: this.getParameterDefaultValue(ctx, { endpoint, parameter: p }),
242
- },
243
- )
244
- ),
245
- returnType: ctx.refs.apiResponse([
246
- this.getTypeUsage(ctx, { schema: responseSchema, fallback: kt.refs.unit({ nullable: true }), nullable: true }),
247
- ]),
248
- body: this.getEndpointClientHttpInfoMethodBody(ctx, { endpoint, parameters, responseSchema }),
249
- });
250
- }
251
-
252
- protected getEndpointClientHttpInfoMethodBody(
253
- ctx: Context,
254
- args: Args.GetEndpointClientHttpInfoMethodBody,
255
- ): AppendValueGroup<Builder> {
256
- const { endpoint, parameters, responseSchema } = args;
257
-
258
- return appendValueGroup(
259
- [
260
- s`val localVariableConfig = ${
261
- kt.call(
262
- [toCasing(endpoint.name, 'camel') + 'RequestConfig'],
263
- parameters.map((x) => toCasing(x.name, ctx.config.parameterNameCasing)),
264
- )
265
- }`,
266
- s`return ${
267
- kt.call(
268
- [
269
- kt.reference('request', null, {
270
- generics: [
271
- this.getRequestBodyType(ctx, { endpoint }),
272
- this.getTypeUsage(ctx, { schema: responseSchema, fallback: kt.refs.unit() }),
273
- ],
274
- }),
275
- ],
276
- ['localVariableConfig'],
277
- )
278
- }`,
279
- ],
280
- '\n',
281
- );
282
- }
283
-
284
- protected getEndpointClientRequestConfigMethod(
285
- ctx: Context,
286
- args: Args.GetEndpointClientRequestConfigMethod,
287
- ): kt.Function<Builder> {
288
- const { endpoint, parameters } = args;
289
- const operationName = toCasing(endpoint.name, ctx.config.functionNameCasing);
290
-
291
- return kt.function(toCasing(args.endpoint.name, ctx.config.functionNameCasing) + 'RequestConfig', {
292
- accessModifier: 'private',
293
- doc: kt.doc(`To obtain the request config of the operation ${operationName}`),
294
- annotations: [endpoint.deprecated ? kt.annotation(kt.refs.deprecated(), [kt.argument(kt.string(''))]) : null],
295
- parameters: parameters.map((p) =>
296
- kt.parameter(
297
- toCasing(p.name, ctx.config.parameterNameCasing),
298
- this.getParameterType(ctx, { endpoint, parameter: p }),
299
- {
300
- description: p.description,
301
- default: this.getParameterDefaultValue(ctx, { endpoint, parameter: p }),
302
- },
303
- )
304
- ),
305
- returnType: ctx.refs.requestConfig([this.getRequestBodyType(ctx, { endpoint })]),
306
- body: this.getEndpointClientRequestConfigMethodBody(ctx, { endpoint, parameters }),
307
- });
308
- }
309
-
310
- protected getEndpointClientRequestConfigMethodBody(
311
- ctx: Context,
312
- args: Args.GetEndpointClientRequestConfigMethodBody,
313
- ): AppendValueGroup<Builder> {
314
- const { endpoint, parameters } = args;
315
- const queryParameters = parameters.filter((x) => x.target === 'query');
316
- const headerParameters = parameters.filter((x) => x.target === 'header');
317
- const result = appendValueGroup<Builder>([], '\n');
318
-
319
- if (endpoint.requestBody) {
320
- if (endpoint.requestBody.content[0]?.type === 'multipart/form-data') {
321
- const partConfigs = parameters
322
- .filter((x) => x.multipart)
323
- .map<KtValue<Builder>>((param) => {
324
- const paramName = toCasing(param.name, ctx.config.parameterNameCasing);
325
- return s`"${param.multipart?.name ?? ''}" to ${ctx.refs.partConfig.infer()}(body = ${paramName})`;
326
- });
327
- result.values.push(
328
- s`val localVariableBody = ${
329
- kt.call(kt.refs.mapOf([kt.refs.string(), ctx.refs.partConfig(['*'])]), partConfigs)
330
- }`,
331
- );
332
- } else {
333
- const bodyParamName = toCasing(this.getRequestBodyParamName(ctx, { endpoint }), ctx.config.parameterNameCasing);
334
- result.values.push(`val localVariableBody = ${bodyParamName}`);
335
- }
336
- }
337
-
338
- result.values.push(
339
- s`val localVariableQuery: ${ctx.refs.multiValueMap()} = ${
340
- kt.call(
341
- [kt.refs.mutableMapOf([kt.refs.string(), kt.refs.list([kt.refs.string()])])],
342
- [],
343
- )
344
- }${
345
- queryParameters.length === 0 ? '' : s.indent`
346
- .apply {${s.indent`
347
- ${
348
- appendValueGroup(
349
- queryParameters.map((param) => {
350
- const paramName = toCasing(param.name, ctx.config.parameterNameCasing);
351
- const toString = this.getParameterToString(ctx, { endpoint, parameter: param });
352
- const put = s<Builder>`put(${kt.string(param.name)}, listOf(${paramName}${toString}))`;
353
- return param.required ? put : s<Builder>`if (${paramName} != null) {${s.indent`
354
- ${put}`}
355
- }`;
356
- }),
357
- '\n',
358
- )
359
- }`}
360
- }`
361
- }`,
362
- );
363
-
364
- result.values.push('val localVariableHeaders: MutableMap<String, String> = mutableMapOf()');
365
- if (endpoint.requestBody?.content[0] !== undefined) {
366
- result.values.push(`localVariableHeaders["Content-Type"] = "${endpoint.requestBody?.content[0].type}"`);
367
- }
368
- for (const header of headerParameters) {
369
- const paramName = toCasing(header.name, ctx.config.parameterNameCasing);
370
- const toString = this.getParameterToString(ctx, { endpoint, parameter: header });
371
- result.values.push(
372
- s`if (${paramName} != null) {${s.indent`
373
- localVariableHeaders["${header.name}"] = ${paramName}${toString}`}
374
- }`,
375
- );
376
- }
377
-
378
- result.values.push(
379
- s`return ${
380
- kt.call(
381
- [ctx.refs.requestConfig.infer()],
382
- [
383
- kt.argument.named('method', kt.call([ctx.refs.requestMethod(), endpoint.method.toUpperCase()])),
384
- kt.argument.named('path', kt.string(this.getPathWithInterpolation(ctx, { endpoint }), { template: true })),
385
- kt.argument.named('query', 'localVariableQuery'),
386
- kt.argument.named('headers', 'localVariableHeaders'),
387
- kt.argument.named('requiresAuthentication', 'false'),
388
- endpoint.requestBody ? kt.argument.named('body', 'localVariableBody') : null,
389
- ],
390
- )
391
- }`,
392
- );
393
-
394
- return result;
395
- }
396
-
397
- protected getParameterToString(ctx: Context, args: Args.GetParameterToString): kt.Value<Builder> {
398
- const { parameter } = args;
399
- if (parameter.schema?.kind === 'array') {
400
- return '.joinToString()';
401
- } else if (
402
- parameter.schema?.kind === 'string' && parameter.schema.enum?.length &&
403
- this.getSchemaType(ctx, { schema: parameter.schema })
404
- ) {
405
- return '.value';
406
- } else {
407
- return '.toString()';
408
- }
409
- }
410
-
411
- protected getAdditionalClientMembers(
412
- _ctx: Context,
413
- _args: Args.GetAdditionalClientMembers,
414
- ): kt.ClassMember<Builder>[] {
415
- return [
416
- kt.function('encodeURIComponent', {
417
- accessModifier: 'private',
418
- parameters: [kt.parameter('uriComponent', kt.refs.string())],
419
- returnType: kt.refs.string(),
420
- singleExpression: true,
421
- body:
422
- s`${kt.refs.okhttp3.httpUrl()}.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0]`,
423
- }),
424
- ];
425
- }
426
-
427
- protected getParameterType(ctx: Context, args: Args.GetParameterType): kt.Type<Builder> {
428
- const { parameter } = args;
429
- if (parameter.multipart?.isFile) {
430
- return kt.refs.java.file();
431
- }
432
- return this.getTypeUsage(ctx, {
433
- schema: parameter.schema,
434
- nullable: !parameter.required,
435
- });
436
- }
437
-
438
- protected getRequestBodyType(ctx: Context, args: Args.GetRequestBodyType): kt.Type<Builder> {
439
- const { endpoint } = args;
440
- const content = endpoint.requestBody?.content[0];
441
- return content?.type === 'multipart/form-data'
442
- ? kt.refs.map([kt.refs.string(), ctx.refs.partConfig(['*'])])
443
- : this.getTypeUsage(ctx, { schema: content?.schema, fallback: kt.refs.unit() });
444
- }
445
-
446
- protected getParameterDefaultValue(ctx: Context, args: Args.GetParameterDefaultValue): kt.Value<Builder> | null {
447
- const { parameter } = args;
448
-
449
- return !parameter.required
450
- ? parameter.schema?.kind === 'string' && parameter.schema.enum && parameter.schema.default
451
- ? s`${this.getTypeUsage(ctx, { schema: parameter.schema, nullable: false })}.${
452
- toCasing(String(parameter.schema.default), ctx.config.enumValueNameCasing)
453
- }`
454
- : kt.toNode(parameter.schema?.default)
455
- : null;
456
- }
457
-
458
- protected getTypeUsage(ctx: Context, args: Args.GetTypeUsage<Builder>): kt.Type<Builder> {
459
- const { schema, nullable, fallback } = args;
460
- const type = this.getSchemaType(ctx, { schema });
461
- return type
462
- ? createOverwriteProxy(type, { nullable: nullable ?? type.nullable })
463
- : (fallback ?? kt.refs.any({ nullable }));
464
- }
465
-
466
- protected getPackageName(ctx: Context, _args: Args.GetPackageName): string {
467
- const packageSuffix = typeof ctx.config.packageSuffix === 'string'
468
- ? ctx.config.packageSuffix
469
- : ctx.config.packageSuffix(ctx.service);
470
- return ctx.config.packageName + packageSuffix;
471
- }
472
-
473
- protected getPathWithInterpolation(ctx: Context, args: Args.GetPathWithInterpolation): string {
474
- const { endpoint } = args;
475
- let path = this.getEndpointPath(ctx, { endpoint });
476
- endpoint.parameters
477
- .filter((x) => x.target === 'path')
478
- .forEach((parameter) => {
479
- path = path.replace(
480
- `{${parameter.name}}`,
481
- `\${encodeURIComponent(${toCasing(parameter.name, 'camel')}${
482
- this.getParameterToString(ctx, { endpoint, parameter })
483
- })}`,
484
- );
485
- });
486
- return path;
487
- }
488
-
489
- protected getResponseSchema(_ctx: Context, args: Args.GetResponseSchema): ApiSchema | undefined {
490
- const { endpoint } = args;
491
- return endpoint.responses.find((x) => !x.statusCode || (x.statusCode >= 200 && x.statusCode < 300))
492
- ?.contentOptions[0]?.schema;
493
- }
494
-
495
- protected getSchemaType(ctx: Context, args: Args.GetSchemaType): kt.Reference<SourceBuilder> | undefined {
496
- const { schema } = args;
497
- return schema && ctx.input.kotlin.models[schema.id].type;
498
- }
499
-
500
- protected getAllParameters(ctx: Context, args: Args.GetAllParameters): ApiParameterWithMultipartInfo[] {
501
- const { endpoint } = args;
502
- const parameters = endpoint.parameters.filter(
503
- (parameter) => parameter.target === 'query' || parameter.target === 'path' || parameter.target === 'header',
504
- );
505
- if (endpoint.requestBody) {
506
- const content = endpoint.requestBody.content[0];
507
- let schema = content.schema;
508
-
509
- if (content.type === 'multipart/form-data') {
510
- if (schema && schema.kind === 'object') {
511
- schema = resolveAnyOfAndAllOf(schema, true) ?? schema;
512
- const properties = schema.properties ?? {};
513
- for (const [name, property] of properties.entries()) {
514
- parameters.push(
515
- Object.assign(
516
- this.createApiParameter({
517
- id: `multipart-${name}`,
518
- name,
519
- target: 'body',
520
- schema: property.schema,
521
- required: schema.required.has(name),
522
- description: property.schema.description,
523
- }),
524
- {
525
- multipart: {
526
- name,
527
- isFile: property.schema.kind === 'string' && property.schema.format === 'binary',
528
- },
529
- },
530
- ),
531
- );
532
- }
533
- }
534
- } else {
535
- parameters.push(
536
- this.createApiParameter({
537
- id: 'body',
538
- name: this.getRequestBodyParamName(ctx, { endpoint }),
539
- target: 'body',
540
- schema,
541
- required: endpoint.requestBody.required,
542
- description: endpoint.requestBody.description,
543
- }),
544
- );
545
- }
546
- }
547
-
548
- return parameters.sort((a, b) => (a.required === b.required ? 0 : a.required ? -1 : 1));
549
- }
550
-
551
- protected getRequestBodyParamName(ctx: Context, args: Args.GetRequestBodyParamName): string {
552
- const { endpoint } = args;
553
- const schema = endpoint.requestBody?.content[0].schema;
554
- const schemaInfo = this.getSchemaType(ctx, { schema });
555
- return toCasing(
556
- schemaInfo && schemaInfo.name !== 'Any' ? SourceBuilder.build((b) => kt.reference.write(b, schemaInfo)) : 'body',
557
- ctx.config.parameterNameCasing,
558
- );
559
- }
560
-
561
- protected getEndpointDocDescription(ctx: Context, args: Args.GetEndpointDocDescription): BasicAppendValue<Builder> {
562
- const docSegments = [args.endpoint.description?.trim()];
563
-
564
- if (ctx.config.includeSourceInDocs) {
565
- docSegments.push(getSourceDocLine(args.endpoint));
566
- }
567
-
568
- return docSegments.filter(notNullish).join('\n\n');
569
- }
570
-
571
- protected getBasePath(ctx: Context, _args: Args.GetBasePath): string {
572
- return modifyString(
573
- (ctx.service.$src ?? ctx.service.endpoints[0]?.$src)?.document.servers?.[0]?.url ?? '/',
574
- ctx.config.basePath,
575
- ctx.service,
576
- );
577
- }
578
-
579
- protected getEndpointPath(ctx: Context, args: Args.GetEndpointPath): string {
580
- const { endpoint } = args;
581
- return modifyString(endpoint.path, ctx.config.pathModifier, endpoint);
582
- }
583
-
584
- protected getFilePath(ctx: Context, args: Args.GetFilePath): string {
585
- const { packageName } = args;
586
- return `${ctx.config.outputDir}/${packageName.replace(/\./g, '/')}/${this.getApiClientName(ctx, {})}.kt`;
587
- }
588
-
589
- protected getApiClientName(ctx: Context, _args: Args.GetApiClientName): string {
590
- return toCasing(ctx.service.name, ctx.config.typeNameCasing) + 'ApiClient';
591
- }
592
-
593
- private createApiParameter(data: Partial<ApiParameter> & Pick<ApiParameter, 'id' | 'name' | 'target'>): ApiParameter {
594
- return {
595
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
596
- $src: undefined!,
597
- $ref: undefined,
598
- schema: undefined,
599
- required: false,
600
- description: undefined,
601
- allowEmptyValue: undefined,
602
- allowReserved: undefined,
603
- deprecated: false,
604
- explode: undefined,
605
- style: undefined,
606
- ...data,
607
- };
608
- }
609
- }