@goast/typescript 0.5.3 → 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 (97) hide show
  1. package/LICENSE +21 -21
  2. package/esm/src/file-builder.d.ts.map +1 -1
  3. package/esm/src/file-builder.js +2 -5
  4. package/esm/src/generators/models/model-generator.d.ts.map +1 -1
  5. package/esm/src/generators/models/model-generator.js +6 -2
  6. package/esm/src/generators/services/k6-clients/k6-client-generator.d.ts.map +1 -1
  7. package/esm/src/generators/services/k6-clients/k6-client-generator.js +2 -1
  8. package/package.json +3 -3
  9. package/script/src/file-builder.d.ts.map +1 -1
  10. package/script/src/file-builder.js +1 -5
  11. package/script/src/generators/models/model-generator.d.ts.map +1 -1
  12. package/script/src/generators/models/model-generator.js +5 -1
  13. package/script/src/generators/services/k6-clients/k6-client-generator.d.ts.map +1 -1
  14. package/script/src/generators/services/k6-clients/k6-client-generator.js +2 -1
  15. package/src/mod.ts +0 -7
  16. package/src/src/assets.ts +0 -9
  17. package/src/src/ast/_index.ts +0 -54
  18. package/src/src/ast/common.ts +0 -1
  19. package/src/src/ast/index.ts +0 -1
  20. package/src/src/ast/node.ts +0 -10
  21. package/src/src/ast/nodes/argument.ts +0 -40
  22. package/src/src/ast/nodes/array-type.ts +0 -49
  23. package/src/src/ast/nodes/arrow-function.ts +0 -91
  24. package/src/src/ast/nodes/call.ts +0 -55
  25. package/src/src/ast/nodes/class.ts +0 -133
  26. package/src/src/ast/nodes/constructor-parameter.ts +0 -70
  27. package/src/src/ast/nodes/constructor.ts +0 -77
  28. package/src/src/ast/nodes/decorator.ts +0 -76
  29. package/src/src/ast/nodes/doc-tag.ts +0 -291
  30. package/src/src/ast/nodes/doc.ts +0 -102
  31. package/src/src/ast/nodes/enum-value.ts +0 -72
  32. package/src/src/ast/nodes/enum.ts +0 -77
  33. package/src/src/ast/nodes/export.ts +0 -54
  34. package/src/src/ast/nodes/function-type.ts +0 -60
  35. package/src/src/ast/nodes/function.ts +0 -107
  36. package/src/src/ast/nodes/generic-parameter.ts +0 -71
  37. package/src/src/ast/nodes/indexer.ts +0 -60
  38. package/src/src/ast/nodes/interface.ts +0 -117
  39. package/src/src/ast/nodes/intersection-type.ts +0 -67
  40. package/src/src/ast/nodes/lookup-type.ts +0 -53
  41. package/src/src/ast/nodes/method.ts +0 -138
  42. package/src/src/ast/nodes/object-type.ts +0 -52
  43. package/src/src/ast/nodes/object.ts +0 -48
  44. package/src/src/ast/nodes/parameter.ts +0 -85
  45. package/src/src/ast/nodes/property-accessor.ts +0 -173
  46. package/src/src/ast/nodes/property.ts +0 -192
  47. package/src/src/ast/nodes/reference.ts +0 -194
  48. package/src/src/ast/nodes/string.ts +0 -49
  49. package/src/src/ast/nodes/tuple.ts +0 -53
  50. package/src/src/ast/nodes/type-alias.ts +0 -75
  51. package/src/src/ast/nodes/typeof.ts +0 -42
  52. package/src/src/ast/nodes/types.ts +0 -40
  53. package/src/src/ast/nodes/union-type.ts +0 -62
  54. package/src/src/ast/nodes/variable.ts +0 -73
  55. package/src/src/ast/references/angular.ts +0 -24
  56. package/src/src/ast/references/easy-network-stub.ts +0 -21
  57. package/src/src/ast/references/index.ts +0 -5
  58. package/src/src/ast/references/k6.ts +0 -8
  59. package/src/src/ast/references/rxjs.ts +0 -7
  60. package/src/src/ast/references/typescript.ts +0 -35
  61. package/src/src/ast/utils/get-type-script-builder-options.ts +0 -19
  62. package/src/src/ast/utils/to-ts-node.ts +0 -27
  63. package/src/src/ast/utils/write-ts-generic-parameters.ts +0 -25
  64. package/src/src/ast/utils/write-ts-members.ts +0 -28
  65. package/src/src/ast/utils/write-ts-nodes.ts +0 -35
  66. package/src/src/ast/utils/write-ts-parameters.ts +0 -25
  67. package/src/src/common-results.ts +0 -26
  68. package/src/src/config.ts +0 -89
  69. package/src/src/file-builder.ts +0 -136
  70. package/src/src/generators/file-generator.ts +0 -15
  71. package/src/src/generators/index.ts +0 -6
  72. package/src/src/generators/models/index.ts +0 -3
  73. package/src/src/generators/models/model-generator.ts +0 -469
  74. package/src/src/generators/models/models-generator.ts +0 -108
  75. package/src/src/generators/models/models.ts +0 -121
  76. package/src/src/generators/services/angular-services/angular-service-generator.ts +0 -406
  77. package/src/src/generators/services/angular-services/angular-services-generator.ts +0 -295
  78. package/src/src/generators/services/angular-services/index.ts +0 -3
  79. package/src/src/generators/services/angular-services/models.ts +0 -277
  80. package/src/src/generators/services/angular-services/refs.ts +0 -54
  81. package/src/src/generators/services/easy-network-stub/easy-network-stub-generator.ts +0 -242
  82. package/src/src/generators/services/easy-network-stub/easy-network-stubs-generator.ts +0 -211
  83. package/src/src/generators/services/easy-network-stub/index.ts +0 -3
  84. package/src/src/generators/services/easy-network-stub/models.ts +0 -124
  85. package/src/src/generators/services/easy-network-stub/refs.ts +0 -45
  86. package/src/src/generators/services/fetch-clients/fetch-client-generator.ts +0 -275
  87. package/src/src/generators/services/fetch-clients/fetch-clients-generator.ts +0 -163
  88. package/src/src/generators/services/fetch-clients/index.ts +0 -3
  89. package/src/src/generators/services/fetch-clients/models.ts +0 -130
  90. package/src/src/generators/services/fetch-clients/refs.ts +0 -21
  91. package/src/src/generators/services/k6-clients/index.ts +0 -3
  92. package/src/src/generators/services/k6-clients/k6-client-generator.ts +0 -465
  93. package/src/src/generators/services/k6-clients/k6-clients-generator.ts +0 -171
  94. package/src/src/generators/services/k6-clients/models.ts +0 -247
  95. package/src/src/generators/services/k6-clients/refs.ts +0 -16
  96. package/src/src/import-collection.ts +0 -236
  97. package/src/src/utils.ts +0 -72
@@ -1,465 +0,0 @@
1
- import { resolve } from 'node:path';
2
-
3
- import {
4
- type ApiEndpoint,
5
- type ApiResponse,
6
- type ApiSchema,
7
- type AppendValueGroup,
8
- appendValueGroup,
9
- builderTemplate as s,
10
- type MaybePromise,
11
- toCasing,
12
- } from '@goast/core';
13
-
14
- import { ts } from '../../../ast/index.js';
15
- import type { TypeScriptExportOutput } from '../../../common-results.js';
16
- import { TypeScriptFileBuilder } from '../../../file-builder.js';
17
- import type { TypeScriptImportOptions } from '../../../import-collection.js';
18
- import { TypeScriptFileGenerator } from '../../file-generator.js';
19
- import type { TypeScriptK6ClientGeneratorContext, TypeScriptK6ClientGeneratorOutput } from './models.js';
20
-
21
- type Context = TypeScriptK6ClientGeneratorContext;
22
- type Output = TypeScriptK6ClientGeneratorOutput;
23
- type Builder = TypeScriptFileBuilder;
24
-
25
- export interface TypeScriptK6ClientGenerator<TOutput extends Output = Output> {
26
- generate(context: Context): MaybePromise<TOutput>;
27
- }
28
-
29
- export class DefaultTypeScriptK6ClientGenerator extends TypeScriptFileGenerator<Context, Output>
30
- implements TypeScriptK6ClientGenerator {
31
- public override generate(ctx: TypeScriptK6ClientGeneratorContext): MaybePromise<TypeScriptK6ClientGeneratorOutput> {
32
- const responseModels = this.generateResponseModels(ctx);
33
-
34
- const filePath = this.getFilePath(ctx);
35
- const name = this.getClassName(ctx);
36
-
37
- TypeScriptFileBuilder.generate({
38
- logName: `k6 client ${name}`,
39
- filePath,
40
- options: ctx.config,
41
- generator: (b) => b.append(this.getClientFileContent(ctx)),
42
- });
43
-
44
- return {
45
- filePath,
46
- component: name,
47
- responseModels,
48
- };
49
- }
50
-
51
- // #region Response Model
52
- protected generateResponseModels(ctx: Context): Record<string, TypeScriptExportOutput> {
53
- const result: Record<string, TypeScriptExportOutput> = {};
54
- const filePath = this.getResponseModelFilePath(ctx);
55
- const builder = new TypeScriptFileBuilder(filePath, ctx.config);
56
-
57
- for (const endpoint of ctx.service.endpoints) {
58
- const name = this.getResponseModelName(ctx, endpoint);
59
- builder.appendLine(this.getResponseModelFileContent(ctx, endpoint));
60
- result[endpoint.id] = { component: name, filePath };
61
- }
62
-
63
- builder.writeToFile();
64
- return result;
65
- }
66
-
67
- protected getResponseModelFileContent(ctx: Context, endpoint: ApiEndpoint): AppendValueGroup<Builder> {
68
- const result = appendValueGroup<Builder>([]);
69
- const statusCodes = this.getEndpointStatusCodes(ctx, endpoint);
70
- let statusCodeType: ts.Reference<Builder>;
71
-
72
- const statusCodesTypeName = toCasing(`${endpoint.name}_StatusCodes`, ctx.config.typeNameCasing);
73
- result.values.push(ts.typeAlias(statusCodesTypeName, ts.unionType(Object.keys(statusCodes))));
74
- if (ctx.config.strictResponseTypes) {
75
- statusCodeType = ts.reference(statusCodesTypeName);
76
- } else {
77
- statusCodeType = ctx.refs.httpStatusCode();
78
- }
79
-
80
- result.values.push(
81
- ts.typeAlias(
82
- this.getResponseModelName(ctx, endpoint),
83
- ts.intersectionType([
84
- ts.unionType([
85
- ...Object.entries(statusCodes).map(([key, value]) => {
86
- return ts.intersectionType<Builder>([
87
- ts.refs.omit([ts.refs.k6.response(), ts.string('json')]),
88
- ts.objectType({
89
- members: [
90
- ts.property('status', { type: key }),
91
- ts.method('json', {
92
- returnType: value.type,
93
- }),
94
- ts.method('json', {
95
- parameters: [ts.parameter('selector', { type: ts.refs.string() })],
96
- returnType: ts.refs.k6.jsonValue(),
97
- }),
98
- ],
99
- }),
100
- ]);
101
- }),
102
- !ctx.config.strictResponseTypes
103
- ? ts.intersectionType([
104
- ts.refs.k6.response(),
105
- ts.objectType({
106
- members: [
107
- ts.property('status', {
108
- type: ts.refs.exclude([ctx.refs.httpStatusCode(), ts.reference(statusCodesTypeName)]),
109
- }),
110
- ],
111
- }),
112
- ])
113
- : null,
114
- ]),
115
- ts.objectType({ members: [ts.property('status', { type: 'TStatus' })] }),
116
- ]),
117
- {
118
- doc: ts.doc({
119
- description: `Response model for operation ${this.getEndpointMethodName(ctx, endpoint)}`,
120
- tags: [endpoint.deprecated ? ts.docTag('deprecated') : null],
121
- }),
122
- export: true,
123
- generics: [
124
- ts.genericParameter('TStatus', {
125
- constraint: statusCodeType,
126
- default: statusCodeType,
127
- }),
128
- ],
129
- },
130
- ),
131
- );
132
-
133
- return result;
134
- }
135
-
136
- protected getEndpointStatusCodes(ctx: Context, endpoint: ApiEndpoint): Record<number, { type: ts.Type<Builder> }> {
137
- return Object.fromEntries([
138
- ...Object.entries(ctx.config.defaultStatusCodeResponseTypes).map(([key, value]) => [
139
- key,
140
- {
141
- parser: value?.parser ?? 'text',
142
- type: typeof value?.type === 'function'
143
- ? this.getSchemaType(ctx, value.type(ctx.data.schemas))
144
- : value ?? ts.refs.never(),
145
- },
146
- ]),
147
- ...endpoint.responses
148
- .filter((x) => x.statusCode)
149
- .map((x) => [
150
- x.statusCode,
151
- {
152
- type: this.getSchemaType(ctx, x.contentOptions[0]?.schema, { fallback: ts.refs.never() }),
153
- },
154
- ]),
155
- ]);
156
- }
157
- // #endregion
158
-
159
- protected getClientFileContent(ctx: Context): AppendValueGroup<Builder> {
160
- const code = appendValueGroup<Builder>([], '\n');
161
- for (const endpoint of ctx.service.endpoints) {
162
- if (endpoint.parameters.length > 0 || endpoint.requestBody !== undefined) {
163
- code.values.push(this.getEndpointParamsType(ctx, endpoint));
164
- }
165
- }
166
- code.values.push(
167
- appendValueGroup<Builder>(
168
- ctx.service.endpoints.map((e) =>
169
- ts.variable(this.getEndpointPathPropertyName(ctx, e), {
170
- readonly: true,
171
- value: ts.string(e.path),
172
- })
173
- ),
174
- ),
175
- );
176
- code.values.push(this.getClass(ctx));
177
- return code;
178
- }
179
-
180
- protected getEndpointParamsType(ctx: Context, endpoint: ApiEndpoint): ts.Doc<Builder> | ts.TypeAlias<Builder> {
181
- const importOptions: TypeScriptImportOptions = ctx.config.language === 'javascript' ? { type: 'js-doc' } : {};
182
- const description = `Parameters for operation ${this.getEndpointMethodName(ctx, endpoint)}`;
183
- const typeName = this.getEndpointParamsTypeName(ctx, endpoint);
184
- const properties: { name: string; type: ts.Type<Builder>; description: string | undefined; required: boolean }[] =
185
- endpoint.parameters.map((parameter) => {
186
- const schema = parameter.schema;
187
- return {
188
- name: toCasing(parameter.name, ctx.config.propertyNameCasing),
189
- type: schema
190
- ? (b) => b.appendModelUsage(ctx.input.typescript.models[schema.id], importOptions)
191
- : this.getAnyType(ctx),
192
- description: (parameter.deprecated ? 'Deprecated: ' : '') + parameter.description,
193
- required: parameter.required,
194
- };
195
- });
196
-
197
- if (endpoint.requestBody !== undefined) {
198
- const body = endpoint.requestBody;
199
- const schema = body.content[0].schema;
200
- properties.push({
201
- name: 'body',
202
- type: schema
203
- ? (b) => b.appendModelUsage(ctx.input.typescript.models[schema.id], importOptions)
204
- : this.getAnyType(ctx),
205
- description: body.description,
206
- required: body.required,
207
- });
208
- }
209
-
210
- if (ctx.config.language === 'javascript') {
211
- return ts.doc<Builder>({
212
- description,
213
- tags: [
214
- ts.docTag('typedef', typeName),
215
- ...properties.map((p) =>
216
- ts.docTag<'property', Builder>('property', p.required ? p.name : `[${p.name}]`, {
217
- type: p.type,
218
- text: p.description,
219
- })
220
- ),
221
- ],
222
- });
223
- } else {
224
- return ts.typeAlias<Builder>(
225
- typeName,
226
- ts.objectType({
227
- members: properties.map((p) =>
228
- ts.property(p.name, {
229
- type: p.type,
230
- optional: !p.required,
231
- doc: p.description ? ts.doc({ description: p.description }) : undefined,
232
- })
233
- ),
234
- }),
235
- );
236
- }
237
- }
238
-
239
- protected getClass(ctx: Context): ts.Class<Builder> {
240
- const isJs = ctx.config.language === 'javascript';
241
- const rootUrlType = ts.refs.string();
242
- const paramType = ts.functionType({
243
- returnType: ts.refs.k6.params({ importType: isJs ? 'js-doc' : 'type-import' }),
244
- });
245
- return ts.class<Builder>(this.getClassName(ctx), {
246
- doc: ts.doc({
247
- description: ctx.service.description,
248
- tags: [
249
- isJs ? ts.docTag('property', 'rootUrl', 'The root URL for this client.', { type: ts.refs.string() }) : null,
250
- ctx.service.endpoints.length === 0 || ctx.service.endpoints.some((x) => !x.deprecated)
251
- ? null
252
- : ts.docTag('deprecated'),
253
- ],
254
- }),
255
- export: true,
256
- members: [
257
- ...(isJs ? [] : [
258
- ts.property('rootUrl', {
259
- type: rootUrlType,
260
- readonly: true,
261
- accessModifier: 'public',
262
- doc: ts.doc({ description: 'The root URL for this client.' }),
263
- }),
264
- ts.property('_defaultK6ParamsFactory', {
265
- type: paramType,
266
- optional: true,
267
- readonly: true,
268
- accessModifier: 'private',
269
- doc: ts.doc({ description: 'A factory function that returns the default K6 parameters.' }),
270
- }),
271
- ]),
272
- ts.constructor({
273
- doc: ts.doc({
274
- description: 'Creates a new instance of the client.',
275
- tags: [
276
- ts.docTag('param', 'rootUrl', 'The root URL for this client.', { type: isJs ? rootUrlType : undefined }),
277
- ts.docTag(
278
- 'param',
279
- '[defaultK6ParamsFactory]',
280
- 'A factory function that returns the default K6 parameters.',
281
- { type: isJs ? paramType : undefined },
282
- ),
283
- ],
284
- }),
285
- parameters: [
286
- ts.constructorParameter('rootUrl', { type: isJs ? undefined : rootUrlType }),
287
- ts.constructorParameter('defaultK6ParamsFactory', { type: isJs ? undefined : paramType, optional: true }),
288
- ],
289
- body: s`this.rootUrl = rootUrl;
290
- this._defaultK6ParamsFactory = defaultK6ParamsFactory;`,
291
- }),
292
- ...ctx.service.endpoints.map((e) => this.getEndpointMethod(ctx, e)),
293
- this.getGetK6ParamsMethod(ctx),
294
- ],
295
- });
296
- }
297
-
298
- protected getEndpointMethod(ctx: Context, endpoint: ApiEndpoint): ts.Method<Builder> {
299
- const isJs = ctx.config.language === 'javascript';
300
- const hasParams = this.hasEndpointParams(ctx, endpoint);
301
- const paramsOptional = !endpoint.parameters.some((p) => p.required) && !endpoint.requestBody?.required;
302
- const responseModelType = ts.reference(
303
- this.getResponseModelName(ctx, endpoint),
304
- this.getResponseModelFilePath(ctx),
305
- { importType: ctx.config.language === 'javascript' ? 'js-doc' : 'type-import' },
306
- );
307
- const returnType = responseModelType;
308
- const accept = this.getEndpointSuccessResponse(ctx, endpoint)?.contentOptions[0]?.type ?? '*/*';
309
- const paramsType = hasParams ? ts.reference(this.getEndpointParamsTypeName(ctx, endpoint)) : null;
310
- const returnTypeWithPromise = ctx.config.async ? ts.refs.promise([returnType]) : returnType;
311
-
312
- return ts.method<Builder>(this.getEndpointMethodName(ctx, endpoint), {
313
- async: ctx.config.async,
314
- parameters: [
315
- hasParams ? ts.parameter('params', { type: isJs ? null : paramsType }) : null,
316
- ts.parameter('k6Params', { type: isJs ? null : ts.refs.k6.params({ importType: 'type-import' }) }),
317
- ],
318
- returnType: isJs ? null : returnTypeWithPromise,
319
- doc: ts.doc({
320
- description: endpoint.description,
321
- tags: isJs
322
- ? [
323
- hasParams ? ts.docTag('param', paramsOptional ? '[params]' : 'params', { type: paramsType }) : null,
324
- ts.docTag('param', '[k6Params]', { type: ts.refs.k6.params({ importType: 'js-doc' }) }),
325
- ts.docTag('returns', { type: returnTypeWithPromise }),
326
- endpoint.deprecated ? ts.docTag('deprecated') : null,
327
- ]
328
- : [],
329
- }),
330
- accessModifier: isJs ? null : 'public',
331
- body: appendValueGroup(
332
- [
333
- s`const rb = new ${ctx.refs.requestBuilder()}(this.rootUrl, ${
334
- this.getEndpointPathPropertyName(ctx, endpoint)
335
- }, '${endpoint.method}');`,
336
- hasParams
337
- ? (b) =>
338
- b.appendIf(paramsOptional, 'if (params) ').parenthesizeIf(
339
- paramsOptional,
340
- '{}',
341
- appendValueGroup(
342
- [
343
- ...endpoint.parameters
344
- .filter((p) => p.target === 'path' || p.target === 'query' || p.target === 'header')
345
- .map((p) => {
346
- const options = ts.object({
347
- members: [
348
- p.style !== undefined ? ts.property('style', { value: ts.string(p.style) }) : null,
349
- p.explode !== undefined ? ts.property('explode', { value: ts.toNode(p.explode) }) : null,
350
- ],
351
- });
352
- return s<Builder>`rb.${p.target}(${ts.string(p.name)}, params.${
353
- toCasing(
354
- p.name,
355
- ctx.config.propertyNameCasing,
356
- )
357
- }, ${options});`;
358
- }),
359
- endpoint.requestBody
360
- ? s`rb.body(params.body, ${
361
- ts.string(endpoint.requestBody.content[0].type ?? 'application/json')
362
- });`
363
- : null,
364
- ],
365
- '\n',
366
- ),
367
- { multiline: true },
368
- )
369
- : null,
370
- '',
371
- ctx.config.language === 'javascript'
372
- ? s`return /** @type {${returnType}} */ (${s.indent`
373
- ${ctx.config.async ? 'await rb.buildAsync' : 'rb.build'}({${s.indent`
374
- accept: ${ts.string(accept)},
375
- params: this.getK6Params(k6Params),`}
376
- })`}
377
- );`
378
- : s`return (${s.indent`
379
- ${ctx.config.async ? 'await rb.buildAsync' : 'rb.build'}({${s.indent`
380
- accept: ${ts.string(accept)},
381
- params: this.getK6Params(k6Params),`}
382
- })`}
383
- ) as unknown as ${returnType};`,
384
- ],
385
- '\n',
386
- ),
387
- });
388
- }
389
-
390
- protected getGetK6ParamsMethod(ctx: Context): ts.Method<Builder> {
391
- const isJs = ctx.config.language === 'javascript';
392
- return ts.method('getK6Params', {
393
- accessModifier: isJs ? null : 'private',
394
- doc: isJs
395
- ? ts.doc({
396
- tags: [
397
- ts.docTag('private'),
398
- ts.docTag('param', '[k6Params]', { type: ts.refs.k6.params({ importType: 'js-doc' }) }),
399
- ],
400
- })
401
- : null,
402
- parameters: [ts.parameter('k6Params', { type: isJs ? null : ts.refs.k6.params({ importType: 'type-import' }) })],
403
- body: s`return Object.assign({}, this._defaultK6ParamsFactory ? this._defaultK6ParamsFactory() : {}, k6Params);`,
404
- });
405
- }
406
-
407
- protected getEndpointSuccessResponse(_ctx: Context, endpoint: ApiEndpoint): ApiResponse | undefined {
408
- return (
409
- endpoint.responses.find((x) => x.statusCode && x.statusCode >= 200 && x.statusCode < 300) ??
410
- endpoint.responses.find((x) => x.statusCode === undefined)
411
- );
412
- }
413
-
414
- protected getSchemaType(
415
- ctx: Context,
416
- schema: ApiSchema | undefined,
417
- options?: TypeScriptImportOptions & { fallback?: ts.Type<Builder> },
418
- ): ts.Type<Builder> {
419
- const output = schema && ctx.input.typescript.models[schema.id];
420
- if (!output) return options?.fallback ?? this.getAnyType(ctx);
421
- return (b) => b.appendModelUsage(output, options);
422
- }
423
-
424
- protected getClassName(ctx: Context): string {
425
- return toCasing(ctx.service.name, ctx.config.clientNameCasing ?? ctx.config.typeNameCasing);
426
- }
427
-
428
- protected getResponseModelName(ctx: Context, endpoint: ApiEndpoint): string {
429
- return toCasing(`${this.getEndpointMethodName(ctx, endpoint)}ApiResponse`, ctx.config.typeNameCasing);
430
- }
431
-
432
- protected getEndpointParamsTypeName(ctx: Context, endpoint: ApiEndpoint): string {
433
- return toCasing(this.getEndpointMethodName(ctx, endpoint) + '_Params', ctx.config.typeNameCasing);
434
- }
435
-
436
- protected getEndpointPathPropertyName(ctx: Context, endpoint: ApiEndpoint): string {
437
- return toCasing(this.getEndpointMethodName(ctx, endpoint) + '_Path', ctx.config.constantNameCasing);
438
- }
439
-
440
- protected getEndpointMethodName(ctx: Context, endpoint: ApiEndpoint): string {
441
- return toCasing(endpoint.name, ctx.config.functionNameCasing);
442
- }
443
-
444
- protected getFilePath(ctx: Context): string {
445
- return resolve(
446
- ctx.config.outputDir,
447
- ctx.config.clientDir,
448
- `${toCasing(ctx.service.name, ctx.config.clientFileNameCasing ?? ctx.config.fileNameCasing)}.${
449
- ctx.config.language === 'typescript' ? 'ts' : 'js'
450
- }`,
451
- );
452
- }
453
-
454
- protected getResponseModelFilePath(ctx: Context): string {
455
- return resolve(
456
- ctx.config.outputDir,
457
- ctx.config.responseModelsDir,
458
- `${toCasing(ctx.service.name, ctx.config.responseModelFileNameCasing ?? ctx.config.fileNameCasing)}.ts`,
459
- );
460
- }
461
-
462
- protected hasEndpointParams(_ctx: Context, endpoint: ApiEndpoint): boolean {
463
- return endpoint.parameters.length > 0 || endpoint.requestBody !== undefined;
464
- }
465
- }
@@ -1,171 +0,0 @@
1
- import { resolve } from 'node:path';
2
-
3
-
4
- import fs from 'fs-extra';
5
-
6
- import {
7
- type ApiService,
8
- type AppendValueGroup,
9
- appendValueGroup,
10
- Factory,
11
- type MaybePromise,
12
- type OpenApiGeneratorContext,
13
- OpenApiServicesGenerationProviderBase,
14
- } from '@goast/core';
15
-
16
- import { copyAssetFile } from '../../../assets.js';
17
- import { ts } from '../../../ast/index.js';
18
- import { TypeScriptFileBuilder } from '../../../file-builder.js';
19
- import { DefaultTypeScriptK6ClientGenerator, type TypeScriptK6ClientGenerator } from './k6-client-generator.js';
20
- import {
21
- defaultTypeScriptK6ClientsGeneratorConfig,
22
- type TypeScriptK6ClientGeneratorOutput,
23
- type TypeScriptK6ClientsGeneratorConfig,
24
- type TypeScriptK6ClientsGeneratorContext,
25
- type TypeScriptK6ClientsGeneratorInput,
26
- type TypeScriptK6ClientsGeneratorOutput,
27
- } from './models.js';
28
- import { getReferenceFactories } from './refs.js';
29
-
30
- type Input = TypeScriptK6ClientsGeneratorInput;
31
- type Output = TypeScriptK6ClientsGeneratorOutput;
32
- type Config = TypeScriptK6ClientsGeneratorConfig;
33
- type ServiceOutput = TypeScriptK6ClientGeneratorOutput;
34
- type Context = TypeScriptK6ClientsGeneratorContext;
35
-
36
- export class TypeScriptK6ClientsGenerator extends OpenApiServicesGenerationProviderBase<
37
- Input,
38
- Output,
39
- Config,
40
- ServiceOutput,
41
- Context
42
- > {
43
- private readonly _clientGeneratorFactory: Factory<TypeScriptK6ClientGenerator, []>;
44
-
45
- constructor(clientGeneratorFactory?: Factory<TypeScriptK6ClientGenerator, []>) {
46
- super();
47
- this._clientGeneratorFactory = clientGeneratorFactory ??
48
- Factory.fromValue(new DefaultTypeScriptK6ClientGenerator());
49
- }
50
-
51
- protected override initResult(): Output {
52
- return {
53
- typescript: {
54
- k6Clients: {},
55
- indexFiles: {
56
- k6Clients: undefined,
57
- k6ResponseModels: undefined,
58
- },
59
- },
60
- };
61
- }
62
-
63
- protected override buildContext(
64
- context: OpenApiGeneratorContext<Input>,
65
- config?: Partial<Config> | undefined,
66
- ): Context {
67
- const providerContext = this.getProviderContext(context, config, defaultTypeScriptK6ClientsGeneratorConfig);
68
- return Object.assign(providerContext, {
69
- refs: getReferenceFactories(providerContext.config),
70
- });
71
- }
72
-
73
- protected override async generateAdditionalFiles(ctx: TypeScriptK6ClientsGeneratorContext): Promise<void> {
74
- await this.generateUtilsFiles(ctx);
75
- ctx.output.typescript.indexFiles = this.generateIndexFiles(ctx);
76
- }
77
-
78
- protected override generateService(ctx: Context, service: ApiService): MaybePromise<ServiceOutput> {
79
- const clientGenerator = this._clientGeneratorFactory.create();
80
- return clientGenerator.generate({
81
- ...ctx,
82
- service,
83
- });
84
- }
85
-
86
- protected override addServiceResult(ctx: Context, service: ApiService, result: ServiceOutput): void {
87
- ctx.output.typescript.k6Clients[service.id] = result;
88
- }
89
-
90
- protected async generateUtilsFiles(ctx: Context): Promise<void> {
91
- const targetDir = resolve(ctx.config.outputDir, ctx.config.utilsDir);
92
- await fs.ensureDir(targetDir);
93
-
94
- const ext = ctx.config.language === 'javascript' ? '.js' : '.ts';
95
- await copyAssetFile(`client/k6/request-builder${ext}`, targetDir, 'Request Builder');
96
-
97
- if (!ctx.config.strictResponseTypes) {
98
- TypeScriptFileBuilder.generate({
99
- logName: 'http status codes',
100
- filePath: resolve(targetDir, 'http-status-code.ts'),
101
- options: ctx.config,
102
- generator: (b) => b.append(this.getHttpStatusCodeFileContent(ctx)),
103
- });
104
- }
105
- }
106
-
107
- protected getHttpStatusCodeFileContent(ctx: Context): AppendValueGroup<TypeScriptFileBuilder> {
108
- return appendValueGroup(
109
- [
110
- ts.typeAlias('HttpStatusCode', ts.unionType(ctx.config.possibleStatusCodes), {
111
- doc: ts.doc({ description: 'The possible status codes that any API endpoint can return.' }),
112
- export: true,
113
- }),
114
- ],
115
- '\n',
116
- );
117
- }
118
-
119
- protected generateIndexFiles(ctx: Context): Output['typescript']['indexFiles'] {
120
- const clientsIndexFilePath = this.getIndexFilePath(ctx);
121
- const responseModelsIndexFilePath = this.getResponseModelsIndexFilePath(ctx);
122
-
123
- TypeScriptFileBuilder.tryGenerate({
124
- logName: 'clients index file',
125
- filePath: clientsIndexFilePath,
126
- options: ctx.config,
127
- generator: (b) => b.append(this.getIndexFileContent(ctx)),
128
- });
129
-
130
- TypeScriptFileBuilder.tryGenerate({
131
- logName: 'response models index file',
132
- filePath: responseModelsIndexFilePath,
133
- options: ctx.config,
134
- generator: (b) => b.append(this.getResponseModelsIndexFileContent(ctx)),
135
- });
136
-
137
- return {
138
- k6Clients: clientsIndexFilePath,
139
- k6ResponseModels: responseModelsIndexFilePath,
140
- };
141
- }
142
-
143
- protected getIndexFilePath(ctx: Context): string | null {
144
- return ctx.config.clientsIndexFile
145
- ? resolve(
146
- ctx.config.outputDir,
147
- ctx.config.clientsIndexFile.replace(/\.[jt]s$/, ctx.config.language === 'javascript' ? '.js' : '.ts'),
148
- )
149
- : null;
150
- }
151
-
152
- protected getResponseModelsIndexFilePath(ctx: Context): string | null {
153
- return ctx.config.responseModelsIndexFile
154
- ? resolve(ctx.config.outputDir, ctx.config.responseModelsIndexFile)
155
- : null;
156
- }
157
-
158
- protected getIndexFileContent(ctx: Context): AppendValueGroup<TypeScriptFileBuilder> {
159
- return appendValueGroup(
160
- Object.values(ctx.output.typescript.k6Clients).map((x) => ts.export(x.component, x.filePath)),
161
- );
162
- }
163
-
164
- protected getResponseModelsIndexFileContent(ctx: Context): AppendValueGroup<TypeScriptFileBuilder> {
165
- return appendValueGroup(
166
- Object.values(ctx.output.typescript.k6Clients)
167
- .flatMap((x) => Object.values(x.responseModels))
168
- .map((x) => ts.export(x.component, x.filePath)),
169
- );
170
- }
171
- }