@goast/typescript 0.3.1 → 0.3.3

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 (49) hide show
  1. package/README.md +2 -0
  2. package/assets/client/k6/request-builder.js +411 -0
  3. package/cjs/lib/ast/nodes/method.js +9 -6
  4. package/cjs/lib/ast/nodes/reference.js +9 -4
  5. package/cjs/lib/ast/references/index.js +2 -1
  6. package/cjs/lib/ast/references/k6.js +9 -0
  7. package/cjs/lib/file-builder.js +9 -4
  8. package/cjs/lib/generators/index.js +2 -1
  9. package/cjs/lib/generators/models/model-generator.js +1 -1
  10. package/cjs/lib/generators/services/k6-clients/index.js +6 -0
  11. package/cjs/lib/generators/services/k6-clients/k6-client-generator.js +311 -0
  12. package/cjs/lib/generators/services/k6-clients/k6-clients-generator.js +116 -0
  13. package/cjs/lib/generators/services/k6-clients/models.js +28 -0
  14. package/cjs/lib/generators/services/k6-clients/refs.js +12 -0
  15. package/cjs/lib/import-collection.js +49 -7
  16. package/esm/lib/ast/nodes/method.js +9 -6
  17. package/esm/lib/ast/nodes/reference.js +9 -4
  18. package/esm/lib/ast/references/index.js +2 -0
  19. package/esm/lib/ast/references/k6.js +6 -0
  20. package/esm/lib/file-builder.js +9 -4
  21. package/esm/lib/generators/index.js +2 -1
  22. package/esm/lib/generators/models/model-generator.js +1 -1
  23. package/esm/lib/generators/services/k6-clients/index.js +3 -0
  24. package/esm/lib/generators/services/k6-clients/k6-client-generator.js +307 -0
  25. package/esm/lib/generators/services/k6-clients/k6-clients-generator.js +112 -0
  26. package/esm/lib/generators/services/k6-clients/models.js +25 -0
  27. package/esm/lib/generators/services/k6-clients/refs.js +9 -0
  28. package/esm/lib/import-collection.js +49 -7
  29. package/package.json +3 -3
  30. package/types/lib/ast/nodes/method.d.ts +2 -0
  31. package/types/lib/ast/nodes/reference.d.ts +8 -2
  32. package/types/lib/ast/references/angular.d.ts +21 -7
  33. package/types/lib/ast/references/easy-network-stub.d.ts +12 -4
  34. package/types/lib/ast/references/index.d.ts +1 -0
  35. package/types/lib/ast/references/k6.d.ts +24 -0
  36. package/types/lib/ast/references/rxjs.d.ts +15 -5
  37. package/types/lib/ast/references/typescript.d.ts +87 -29
  38. package/types/lib/common-results.d.ts +2 -0
  39. package/types/lib/file-builder.d.ts +3 -3
  40. package/types/lib/generators/index.d.ts +2 -1
  41. package/types/lib/generators/services/angular-services/refs.d.ts +21 -7
  42. package/types/lib/generators/services/easy-network-stub/refs.d.ts +27 -9
  43. package/types/lib/generators/services/fetch-clients/refs.d.ts +9 -3
  44. package/types/lib/generators/services/k6-clients/index.d.ts +3 -0
  45. package/types/lib/generators/services/k6-clients/k6-client-generator.d.ts +39 -0
  46. package/types/lib/generators/services/k6-clients/k6-clients-generator.d.ts +27 -0
  47. package/types/lib/generators/services/k6-clients/models.d.ts +118 -0
  48. package/types/lib/generators/services/k6-clients/refs.d.ts +20 -0
  49. package/types/lib/import-collection.d.ts +10 -3
@@ -0,0 +1,311 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultTypeScriptK6ClientGenerator = void 0;
4
+ const path_1 = require("path");
5
+ const core_1 = require("@goast/core");
6
+ const ast_1 = require("../../../ast");
7
+ const file_builder_1 = require("../../../file-builder");
8
+ const file_generator_1 = require("../../file-generator");
9
+ class DefaultTypeScriptK6ClientGenerator extends file_generator_1.TypeScriptFileGenerator {
10
+ generate(ctx) {
11
+ const responseModels = this.generateResponseModels(ctx);
12
+ const filePath = this.getFilePath(ctx);
13
+ const name = this.getClassName(ctx);
14
+ file_builder_1.TypeScriptFileBuilder.generate({
15
+ logName: `k6 client ${name}`,
16
+ filePath,
17
+ options: ctx.config,
18
+ generator: (b) => b.append(this.getClientFileContent(ctx)),
19
+ });
20
+ return {
21
+ filePath,
22
+ component: name,
23
+ responseModels,
24
+ };
25
+ }
26
+ // #region Response Model
27
+ generateResponseModels(ctx) {
28
+ const result = {};
29
+ const filePath = this.getResponseModelFilePath(ctx);
30
+ const builder = new file_builder_1.TypeScriptFileBuilder(filePath, ctx.config);
31
+ for (const endpoint of ctx.service.endpoints) {
32
+ const name = this.getResponseModelName(ctx, endpoint);
33
+ builder.appendLine(this.getResponseModelFileContent(ctx, endpoint));
34
+ result[endpoint.id] = { component: name, filePath };
35
+ }
36
+ builder.writeToFile();
37
+ return result;
38
+ }
39
+ getResponseModelFileContent(ctx, endpoint) {
40
+ const result = (0, core_1.appendValueGroup)([]);
41
+ const statusCodes = this.getEndpointStatusCodes(ctx, endpoint);
42
+ let statusCodeType;
43
+ const statusCodesTypeName = (0, core_1.toCasing)(`${endpoint.name}_StatusCodes`, ctx.config.typeNameCasing);
44
+ result.values.push(ast_1.ts.typeAlias(statusCodesTypeName, ast_1.ts.unionType(Object.keys(statusCodes))));
45
+ if (ctx.config.strictResponseTypes) {
46
+ statusCodeType = ast_1.ts.reference(statusCodesTypeName);
47
+ }
48
+ else {
49
+ statusCodeType = ctx.refs.httpStatusCode();
50
+ }
51
+ result.values.push(ast_1.ts.typeAlias(this.getResponseModelName(ctx, endpoint), ast_1.ts.intersectionType([
52
+ ast_1.ts.unionType([
53
+ ...Object.entries(statusCodes).map(([key, value]) => {
54
+ return ast_1.ts.intersectionType([
55
+ ast_1.ts.refs.omit([ast_1.ts.refs.k6.response(), ast_1.ts.string('json')]),
56
+ ast_1.ts.objectType({
57
+ members: [
58
+ ast_1.ts.property('status', { type: key }),
59
+ ast_1.ts.method('json', {
60
+ returnType: value.type,
61
+ }),
62
+ ast_1.ts.method('json', {
63
+ parameters: [ast_1.ts.parameter('selector', { type: ast_1.ts.refs.string() })],
64
+ returnType: ast_1.ts.refs.k6.jsonValue(),
65
+ }),
66
+ ],
67
+ }),
68
+ ]);
69
+ }),
70
+ !ctx.config.strictResponseTypes
71
+ ? ast_1.ts.intersectionType([
72
+ ast_1.ts.refs.k6.response(),
73
+ ast_1.ts.objectType({
74
+ members: [
75
+ ast_1.ts.property('status', {
76
+ type: ast_1.ts.refs.exclude([ctx.refs.httpStatusCode(), ast_1.ts.reference(statusCodesTypeName)]),
77
+ }),
78
+ ],
79
+ }),
80
+ ])
81
+ : null,
82
+ ]),
83
+ ast_1.ts.objectType({ members: [ast_1.ts.property('status', { type: 'TStatus' })] }),
84
+ ]), {
85
+ doc: ast_1.ts.doc({
86
+ description: `Response model for operation ${this.getEndpointMethodName(ctx, endpoint)}`,
87
+ tags: [endpoint.deprecated ? ast_1.ts.docTag('deprecated') : null],
88
+ }),
89
+ export: true,
90
+ generics: [
91
+ ast_1.ts.genericParameter('TStatus', {
92
+ constraint: statusCodeType,
93
+ default: statusCodeType,
94
+ }),
95
+ ],
96
+ }));
97
+ return result;
98
+ }
99
+ getEndpointStatusCodes(ctx, endpoint) {
100
+ return Object.fromEntries([
101
+ ...Object.entries(ctx.config.defaultStatusCodeResponseTypes).map(([key, value]) => {
102
+ var _a;
103
+ return [
104
+ key,
105
+ {
106
+ parser: (_a = value === null || value === void 0 ? void 0 : value.parser) !== null && _a !== void 0 ? _a : 'text',
107
+ type: typeof (value === null || value === void 0 ? void 0 : value.type) === 'function'
108
+ ? this.getSchemaType(ctx, value.type(ctx.data.schemas))
109
+ : (value !== null && value !== void 0 ? value : ast_1.ts.refs.never()),
110
+ },
111
+ ];
112
+ }),
113
+ ...endpoint.responses
114
+ .filter((x) => x.statusCode)
115
+ .map((x) => {
116
+ var _a;
117
+ return [
118
+ x.statusCode,
119
+ {
120
+ type: this.getSchemaType(ctx, (_a = x.contentOptions[0]) === null || _a === void 0 ? void 0 : _a.schema, { fallback: ast_1.ts.refs.never() }),
121
+ },
122
+ ];
123
+ }),
124
+ ]);
125
+ }
126
+ // #endregion
127
+ getClientFileContent(ctx) {
128
+ const code = (0, core_1.appendValueGroup)([], '\n');
129
+ for (const endpoint of ctx.service.endpoints) {
130
+ if (endpoint.parameters.length > 0 || endpoint.requestBody !== undefined) {
131
+ code.values.push(this.getEndpointParamsType(ctx, endpoint));
132
+ }
133
+ }
134
+ code.values.push((0, core_1.appendValueGroup)(ctx.service.endpoints.map((e) => ast_1.ts.variable(this.getEndpointPathPropertyName(ctx, e), {
135
+ readonly: true,
136
+ value: ast_1.ts.string(e.path),
137
+ }))));
138
+ code.values.push(this.getClass(ctx));
139
+ return code;
140
+ }
141
+ getEndpointParamsType(ctx, endpoint) {
142
+ const type = ast_1.ts.doc({
143
+ description: `Parameters for operation ${this.getEndpointMethodName(ctx, endpoint)}`,
144
+ tags: [ast_1.ts.docTag('typedef', this.getEndpointParamsTypeName(ctx, endpoint))],
145
+ });
146
+ for (const parameter of endpoint.parameters) {
147
+ const schema = parameter.schema;
148
+ const name = (0, core_1.toCasing)(parameter.name, ctx.config.propertyNameCasing);
149
+ type.tags.push(ast_1.ts.docTag('property', parameter.required ? name : `[${name}]`, {
150
+ type: schema
151
+ ? (b) => b.appendModelUsage(ctx.input.typescript.models[schema.id], { type: 'js-doc' })
152
+ : this.getAnyType(ctx),
153
+ text: (parameter.deprecated ? 'Deprecated: ' : '') + parameter.description,
154
+ }));
155
+ }
156
+ if (endpoint.requestBody !== undefined) {
157
+ const body = endpoint.requestBody;
158
+ const schema = body.content[0].schema;
159
+ type.tags.push(ast_1.ts.docTag('property', body.required ? 'body' : '[body]', {
160
+ type: schema
161
+ ? (b) => b.appendModelUsage(ctx.input.typescript.models[schema.id], { type: 'js-doc' })
162
+ : this.getAnyType(ctx),
163
+ text: body.description,
164
+ }));
165
+ }
166
+ return type;
167
+ }
168
+ getClass(ctx) {
169
+ return ast_1.ts.class(this.getClassName(ctx), {
170
+ doc: ast_1.ts.doc({
171
+ description: ctx.service.description,
172
+ tags: [
173
+ ast_1.ts.docTag('property', 'rootUrl', 'The root URL for this client.', {
174
+ type: ast_1.ts.refs.string(),
175
+ }),
176
+ ctx.service.endpoints.length === 0 || ctx.service.endpoints.some((x) => !x.deprecated)
177
+ ? null
178
+ : ast_1.ts.docTag('deprecated'),
179
+ ],
180
+ }),
181
+ export: true,
182
+ members: [
183
+ ast_1.ts.constructor({
184
+ doc: ast_1.ts.doc({
185
+ description: 'Creates a new instance of the client.',
186
+ tags: [
187
+ ast_1.ts.docTag('param', 'rootUrl', 'The root URL for this client.', { type: ast_1.ts.refs.string() }),
188
+ ast_1.ts.docTag('param', '[defaultK6ParamsFactory]', 'A factory function that returns the default K6 parameters.', { type: ast_1.ts.functionType({ returnType: ast_1.ts.refs.k6.params({ importType: 'js-doc' }) }) }),
189
+ ],
190
+ }),
191
+ parameters: [ast_1.ts.constructorParameter('rootUrl'), ast_1.ts.constructorParameter('defaultK6ParamsFactory')],
192
+ body: (0, core_1.builderTemplate) `this.rootUrl = rootUrl;
193
+ this._defaultK6ParamsFactory = defaultK6ParamsFactory;`,
194
+ }),
195
+ ...ctx.service.endpoints.map((e) => this.getEndpointMethod(ctx, e)),
196
+ this.getGetK6ParamsMethod(ctx),
197
+ ],
198
+ });
199
+ }
200
+ getEndpointMethod(ctx, endpoint) {
201
+ var _a, _b, _c, _d;
202
+ const hasParams = this.hasEndpointParams(ctx, endpoint);
203
+ const paramsOptional = !endpoint.parameters.some((p) => p.required) && !((_a = endpoint.requestBody) === null || _a === void 0 ? void 0 : _a.required);
204
+ const responseModelType = ast_1.ts.reference(this.getResponseModelName(ctx, endpoint), this.getResponseModelFilePath(ctx), { importType: 'js-doc' });
205
+ const returnType = responseModelType;
206
+ const accept = (_d = (_c = (_b = this.getEndpointSuccessResponse(ctx, endpoint)) === null || _b === void 0 ? void 0 : _b.contentOptions[0]) === null || _c === void 0 ? void 0 : _c.type) !== null && _d !== void 0 ? _d : '*/*';
207
+ return ast_1.ts.method(this.getEndpointMethodName(ctx, endpoint), {
208
+ async: ctx.config.async,
209
+ parameters: [hasParams ? ast_1.ts.parameter('params') : null, ast_1.ts.parameter('k6Params')],
210
+ doc: ast_1.ts.doc({
211
+ description: endpoint.description,
212
+ tags: [
213
+ hasParams
214
+ ? ast_1.ts.docTag('param', paramsOptional ? '[params]' : 'params', {
215
+ type: ast_1.ts.reference(this.getEndpointParamsTypeName(ctx, endpoint)),
216
+ })
217
+ : null,
218
+ ast_1.ts.docTag('param', '[k6Params]', {
219
+ type: ast_1.ts.refs.k6.params({ importType: 'js-doc' }),
220
+ }),
221
+ ast_1.ts.docTag('returns', {
222
+ type: ctx.config.async ? ast_1.ts.refs.promise([returnType]) : returnType,
223
+ }),
224
+ endpoint.deprecated ? ast_1.ts.docTag('deprecated') : null,
225
+ ],
226
+ }),
227
+ body: (0, core_1.appendValueGroup)([
228
+ (0, core_1.builderTemplate) `const rb = new ${ctx.refs.requestBuilder()}(this.rootUrl, ${this.getEndpointPathPropertyName(ctx, endpoint)}, '${endpoint.method}');`,
229
+ hasParams
230
+ ? (b) => {
231
+ var _a;
232
+ return b.appendIf(paramsOptional, 'if (params) ').parenthesizeIf(paramsOptional, '{}', (0, core_1.appendValueGroup)([
233
+ ...endpoint.parameters
234
+ .filter((p) => p.target === 'path' || p.target === 'query' || p.target === 'header')
235
+ .map((p) => {
236
+ const options = ast_1.ts.object({
237
+ members: [
238
+ p.style !== undefined ? ast_1.ts.property('style', { value: ast_1.ts.string(p.style) }) : null,
239
+ p.explode !== undefined ? ast_1.ts.property('explode', { value: ast_1.ts.toNode(p.explode) }) : null,
240
+ ],
241
+ });
242
+ return (0, core_1.builderTemplate) `rb.${p.target}(${ast_1.ts.string(p.name)}, params.${(0, core_1.toCasing)(p.name, ctx.config.propertyNameCasing)}, ${options});`;
243
+ }),
244
+ endpoint.requestBody
245
+ ? (0, core_1.builderTemplate) `rb.body(params.body, ${ast_1.ts.string((_a = endpoint.requestBody.content[0].type) !== null && _a !== void 0 ? _a : 'application/json')});`
246
+ : null,
247
+ ], '\n'), { multiline: true });
248
+ }
249
+ : null,
250
+ '',
251
+ (0, core_1.builderTemplate) `return /** @type {${returnType}} */ (${core_1.builderTemplate.indent `
252
+ ${ctx.config.async ? 'await rb.buildAsync' : 'rb.build'}({${core_1.builderTemplate.indent `
253
+ accept: ${ast_1.ts.string(accept)},
254
+ params: this.getK6Params(k6Params),`}
255
+ })`}
256
+ );`,
257
+ ], '\n'),
258
+ });
259
+ }
260
+ getGetK6ParamsMethod(ctx) {
261
+ return ast_1.ts.method('getK6Params', {
262
+ doc: ast_1.ts.doc({
263
+ tags: [
264
+ ast_1.ts.docTag('private'),
265
+ ast_1.ts.docTag('param', '[k6Params]', { type: ast_1.ts.refs.k6.params({ importType: 'js-doc' }) }),
266
+ ],
267
+ }),
268
+ parameters: [ast_1.ts.parameter('k6Params')],
269
+ body: (0, core_1.builderTemplate) `return Object.assign({}, this._defaultK6ParamsFactory ? this._defaultK6ParamsFactory() : {}, k6Params);`,
270
+ });
271
+ }
272
+ getEndpointSuccessResponse(ctx, endpoint) {
273
+ var _a;
274
+ return ((_a = endpoint.responses.find((x) => x.statusCode && x.statusCode >= 200 && x.statusCode < 300)) !== null && _a !== void 0 ? _a : endpoint.responses.find((x) => x.statusCode === undefined));
275
+ }
276
+ getSchemaType(ctx, schema, options) {
277
+ var _a;
278
+ const output = schema && ctx.input.typescript.models[schema.id];
279
+ if (!output)
280
+ return (_a = options === null || options === void 0 ? void 0 : options.fallback) !== null && _a !== void 0 ? _a : this.getAnyType(ctx);
281
+ return (b) => b.appendModelUsage(output, options);
282
+ }
283
+ getClassName(ctx) {
284
+ var _a;
285
+ return (0, core_1.toCasing)(ctx.service.name, (_a = ctx.config.clientNameCasing) !== null && _a !== void 0 ? _a : ctx.config.typeNameCasing);
286
+ }
287
+ getResponseModelName(ctx, endpoint) {
288
+ return (0, core_1.toCasing)(`${this.getEndpointMethodName(ctx, endpoint)}ApiResponse`, ctx.config.typeNameCasing);
289
+ }
290
+ getEndpointParamsTypeName(ctx, endpoint) {
291
+ return (0, core_1.toCasing)(this.getEndpointMethodName(ctx, endpoint) + '_Params', ctx.config.typeNameCasing);
292
+ }
293
+ getEndpointPathPropertyName(ctx, endpoint) {
294
+ return (0, core_1.toCasing)(this.getEndpointMethodName(ctx, endpoint) + '_Path', ctx.config.constantNameCasing);
295
+ }
296
+ getEndpointMethodName(ctx, endpoint) {
297
+ return (0, core_1.toCasing)(endpoint.name, ctx.config.functionNameCasing);
298
+ }
299
+ getFilePath(ctx) {
300
+ var _a;
301
+ return (0, path_1.resolve)(ctx.config.outputDir, ctx.config.clientDir, `${(0, core_1.toCasing)(ctx.service.name, (_a = ctx.config.clientFileNameCasing) !== null && _a !== void 0 ? _a : ctx.config.fileNameCasing)}.js`);
302
+ }
303
+ getResponseModelFilePath(ctx) {
304
+ var _a;
305
+ return (0, path_1.resolve)(ctx.config.outputDir, ctx.config.responseModelsDir, `${(0, core_1.toCasing)(ctx.service.name, (_a = ctx.config.responseModelFileNameCasing) !== null && _a !== void 0 ? _a : ctx.config.fileNameCasing)}.ts`);
306
+ }
307
+ hasEndpointParams(ctx, endpoint) {
308
+ return endpoint.parameters.length > 0 || endpoint.requestBody !== undefined;
309
+ }
310
+ }
311
+ exports.DefaultTypeScriptK6ClientGenerator = DefaultTypeScriptK6ClientGenerator;
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeScriptK6ClientsGenerator = void 0;
4
+ const path_1 = require("path");
5
+ const fs_extra_1 = require("fs-extra");
6
+ const core_1 = require("@goast/core");
7
+ const k6_client_generator_1 = require("./k6-client-generator");
8
+ const models_1 = require("./models");
9
+ const refs_1 = require("./refs");
10
+ const ast_1 = require("../../../ast");
11
+ const file_builder_1 = require("../../../file-builder");
12
+ class TypeScriptK6ClientsGenerator extends core_1.OpenApiServicesGenerationProviderBase {
13
+ constructor(clientGeneratorFactory) {
14
+ super();
15
+ this._clientGeneratorFactory =
16
+ clientGeneratorFactory !== null && clientGeneratorFactory !== void 0 ? clientGeneratorFactory : core_1.Factory.fromValue(new k6_client_generator_1.DefaultTypeScriptK6ClientGenerator());
17
+ }
18
+ initResult() {
19
+ return {
20
+ typescript: {
21
+ k6Clients: {},
22
+ indexFiles: {
23
+ k6Clients: undefined,
24
+ k6ResponseModels: undefined,
25
+ },
26
+ },
27
+ };
28
+ }
29
+ buildContext(context, config) {
30
+ const providerContext = this.getProviderContext(context, config, models_1.defaultTypeScriptK6ClientsGeneratorConfig);
31
+ return Object.assign(providerContext, {
32
+ refs: (0, refs_1.getReferenceFactories)(providerContext.config),
33
+ });
34
+ }
35
+ onGenerate(ctx) {
36
+ const output = super.onGenerate(ctx);
37
+ this.generateUtilsFiles(ctx);
38
+ output.typescript.indexFiles = this.generateIndexFiles(ctx);
39
+ return output;
40
+ }
41
+ generateService(ctx, service) {
42
+ const clientGenerator = this._clientGeneratorFactory.create();
43
+ return clientGenerator.generate({
44
+ ...ctx,
45
+ service,
46
+ });
47
+ }
48
+ addServiceResult(ctx, service, result) {
49
+ ctx.output.typescript.k6Clients[service.id] = result;
50
+ }
51
+ generateUtilsFiles(ctx) {
52
+ const sourceDir = (0, path_1.resolve)((0, path_1.dirname)(require.resolve('@goast/typescript')), '../assets/client/k6');
53
+ const targetDir = (0, path_1.resolve)(ctx.config.outputDir, ctx.config.utilsDir);
54
+ (0, fs_extra_1.ensureDirSync)(targetDir);
55
+ this.copyFile('Request Builder', sourceDir, targetDir, 'request-builder.js');
56
+ if (!ctx.config.strictResponseTypes) {
57
+ file_builder_1.TypeScriptFileBuilder.generate({
58
+ logName: 'http status codes',
59
+ filePath: (0, path_1.resolve)(targetDir, 'http-status-code.ts'),
60
+ options: ctx.config,
61
+ generator: (b) => b.append(this.getHttpStatusCodeFileContent(ctx)),
62
+ });
63
+ }
64
+ }
65
+ getHttpStatusCodeFileContent(ctx) {
66
+ return (0, core_1.appendValueGroup)([
67
+ ast_1.ts.typeAlias('HttpStatusCode', ast_1.ts.unionType(ctx.config.possibleStatusCodes), {
68
+ doc: ast_1.ts.doc({ description: 'The possible status codes that any API endpoint can return.' }),
69
+ export: true,
70
+ }),
71
+ ], '\n');
72
+ }
73
+ generateIndexFiles(ctx) {
74
+ const clientsIndexFilePath = this.getIndexFilePath(ctx);
75
+ const responseModelsIndexFilePath = this.getResponseModelsIndexFilePath(ctx);
76
+ file_builder_1.TypeScriptFileBuilder.tryGenerate({
77
+ logName: 'clients index file',
78
+ filePath: clientsIndexFilePath,
79
+ options: ctx.config,
80
+ generator: (b) => b.append(this.getIndexFileContent(ctx)),
81
+ });
82
+ file_builder_1.TypeScriptFileBuilder.tryGenerate({
83
+ logName: 'response models index file',
84
+ filePath: responseModelsIndexFilePath,
85
+ options: ctx.config,
86
+ generator: (b) => b.append(this.getResponseModelsIndexFileContent(ctx)),
87
+ });
88
+ return {
89
+ k6Clients: clientsIndexFilePath,
90
+ k6ResponseModels: responseModelsIndexFilePath,
91
+ };
92
+ }
93
+ getIndexFilePath(ctx) {
94
+ return ctx.config.clientsIndexFile ? (0, path_1.resolve)(ctx.config.outputDir, ctx.config.clientsIndexFile) : null;
95
+ }
96
+ getResponseModelsIndexFilePath(ctx) {
97
+ return ctx.config.responseModelsIndexFile
98
+ ? (0, path_1.resolve)(ctx.config.outputDir, ctx.config.responseModelsIndexFile)
99
+ : null;
100
+ }
101
+ getIndexFileContent(ctx) {
102
+ return (0, core_1.appendValueGroup)(Object.values(ctx.output.typescript.k6Clients).map((x) => ast_1.ts.export(x.component, x.filePath)));
103
+ }
104
+ getResponseModelsIndexFileContent(ctx) {
105
+ return (0, core_1.appendValueGroup)(Object.values(ctx.output.typescript.k6Clients)
106
+ .flatMap((x) => Object.values(x.responseModels))
107
+ .map((x) => ast_1.ts.export(x.component, x.filePath)));
108
+ }
109
+ copyFile(logName, sourceDir, targetDir, fileName) {
110
+ const source = (0, path_1.resolve)(sourceDir, fileName);
111
+ const target = (0, path_1.resolve)(targetDir, fileName);
112
+ console.log(`Generating ${logName} to ${target}...`);
113
+ (0, fs_extra_1.copyFileSync)(source, target);
114
+ }
115
+ }
116
+ exports.TypeScriptK6ClientsGenerator = TypeScriptK6ClientsGenerator;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultTypeScriptK6ClientsGeneratorConfig = void 0;
4
+ const config_1 = require("../../../config");
5
+ exports.defaultTypeScriptK6ClientsGeneratorConfig = {
6
+ ...config_1.defaultTypeScriptGeneratorConfig,
7
+ importModuleTransformer: 'js-extension',
8
+ strictResponseTypes: true,
9
+ defaultStatusCodeResponseTypes: {
10
+ 401: null,
11
+ 403: null,
12
+ 500: null,
13
+ },
14
+ possibleStatusCodes: [
15
+ 100, 101, 102, 103, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 306, 307, 308,
16
+ 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 421, 422, 423, 424, 425,
17
+ 426, 428, 429, 431, 451, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511,
18
+ ],
19
+ clientFileNameCasing: { casing: 'kebab', suffix: '-client' },
20
+ responseModelFileNameCasing: { casing: 'kebab', suffix: '-responses' },
21
+ clientNameCasing: { casing: 'pascal', suffix: 'Client' },
22
+ clientDir: 'clients',
23
+ responseModelsDir: 'models/responses',
24
+ clientsIndexFile: 'clients.js',
25
+ responseModelsIndexFile: 'responses.ts',
26
+ utilsDir: 'utils',
27
+ async: true,
28
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getReferenceFactories = getReferenceFactories;
4
+ const path_1 = require("path");
5
+ const ast_1 = require("../../../ast");
6
+ function getReferenceFactories(options) {
7
+ const utilsDirPath = (0, path_1.resolve)(options.outputDir, options.utilsDir);
8
+ return {
9
+ requestBuilder: ast_1.ts.reference.factory('RequestBuilder', (0, path_1.join)(utilsDirPath, 'request-builder.js')),
10
+ httpStatusCode: ast_1.ts.reference.factory('HttpStatusCode', (0, path_1.join)(utilsDirPath, 'http-status-code.ts')),
11
+ };
12
+ }
@@ -12,31 +12,53 @@ exports.defaultImportExportCollectionOptions = {
12
12
  class ImportExportCollection {
13
13
  constructor(options) {
14
14
  this._imports = new Map();
15
+ this._typeImports = new Map();
16
+ this._jsDocImports = new Map();
15
17
  this._exports = new Map();
16
18
  this._options = { ...exports.defaultImportExportCollectionOptions, ...options };
17
19
  }
18
20
  get hasImports() {
19
- return this._imports.size > 0;
21
+ return this._imports.size > 0 || this._typeImports.size > 0 || this._jsDocImports.size > 0;
20
22
  }
21
23
  get hasExports() {
22
24
  return this._exports.size > 0;
23
25
  }
24
26
  get imports() {
25
- return Array.from(this._imports.entries())
27
+ return [
28
+ ...this.toImport('import', this._imports),
29
+ ...this.toImport('type-import', this._typeImports),
30
+ ...this.toImport('js-doc', this._jsDocImports),
31
+ ];
32
+ }
33
+ toImport(type, map) {
34
+ return Array.from(map.entries())
26
35
  .map(([fromModule, importNames]) => Array.from(importNames).map((importName) => ({
27
36
  kind: this.getImportKind(fromModule),
37
+ type,
28
38
  modulePath: fromModule,
29
39
  name: importName,
30
40
  })))
31
41
  .flat();
32
42
  }
33
- addImport(importName, fromModule) {
34
- const existingImport = this._imports.get(fromModule);
43
+ addImport(importName, fromModule, options) {
44
+ var _a;
45
+ const map = this.getImportMap((_a = options === null || options === void 0 ? void 0 : options.type) !== null && _a !== void 0 ? _a : 'import');
46
+ const existingImport = map.get(fromModule);
35
47
  if (existingImport) {
36
48
  existingImport.add(importName);
37
49
  }
38
50
  else {
39
- this._imports.set(fromModule, new Set([importName]));
51
+ map.set(fromModule, new Set([importName]));
52
+ }
53
+ }
54
+ getImportMap(type) {
55
+ switch (type) {
56
+ case 'import':
57
+ return this._imports;
58
+ case 'type-import':
59
+ return this._typeImports;
60
+ case 'js-doc':
61
+ return this._jsDocImports;
40
62
  }
41
63
  }
42
64
  addExport(exportName, fromModule) {
@@ -59,14 +81,34 @@ class ImportExportCollection {
59
81
  }
60
82
  writeTo(builder) {
61
83
  const { filePath, importModuleTransformer, useSingleQuotes } = this._options;
84
+ let hasPrevious = false;
62
85
  if (this._imports.size > 0) {
63
86
  const sortedImports = this.sortAndResolve(this._imports, filePath, importModuleTransformer);
64
87
  this.writeImportsExports(builder, 'import', sortedImports, { useSingleQuotes });
88
+ hasPrevious = true;
65
89
  }
66
- if (this._imports.size > 0 && this._exports.size > 0) {
67
- builder.appendLine();
90
+ if (this._typeImports.size > 0) {
91
+ if (hasPrevious) {
92
+ builder.appendLine();
93
+ }
94
+ const sortedImports = this.sortAndResolve(this._typeImports, filePath, importModuleTransformer);
95
+ this.writeImportsExports(builder, 'import type', sortedImports, { useSingleQuotes });
96
+ hasPrevious = true;
97
+ }
98
+ if (this._jsDocImports.size > 0) {
99
+ if (hasPrevious) {
100
+ builder.appendLine();
101
+ }
102
+ const sortedImports = this.sortAndResolve(this._jsDocImports, filePath, importModuleTransformer);
103
+ builder.appendLine('/**');
104
+ this.writeImportsExports(builder, ' * @import', sortedImports, { useSingleQuotes });
105
+ builder.appendLine(' */');
106
+ hasPrevious = true;
68
107
  }
69
108
  if (this._exports.size > 0) {
109
+ if (hasPrevious) {
110
+ builder.appendLine();
111
+ }
70
112
  const sortedExports = this.sortAndResolve(this._exports, filePath, importModuleTransformer);
71
113
  this.writeImportsExports(builder, 'export', sortedExports, { useSingleQuotes });
72
114
  }
@@ -8,7 +8,7 @@ import { TsNode } from '../node';
8
8
  import { writeTsNode, writeTsNodes } from '../utils/write-ts-nodes';
9
9
  export class TsMethod extends TsNode {
10
10
  constructor(options) {
11
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
11
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
12
12
  super(options);
13
13
  this.doc = (_a = options.doc) !== null && _a !== void 0 ? _a : null;
14
14
  this.decorators = (_c = (_b = options.decorators) === null || _b === void 0 ? void 0 : _b.filter(notNullish)) !== null && _c !== void 0 ? _c : [];
@@ -16,12 +16,13 @@ export class TsMethod extends TsNode {
16
16
  this.static = (_e = options.static) !== null && _e !== void 0 ? _e : false;
17
17
  this.abstract = (_f = options.abstract) !== null && _f !== void 0 ? _f : false;
18
18
  this.override = (_g = options.override) !== null && _g !== void 0 ? _g : false;
19
+ this.async = (_h = options.async) !== null && _h !== void 0 ? _h : false;
19
20
  this.name = options.name;
20
- this.optional = (_h = options.optional) !== null && _h !== void 0 ? _h : false;
21
- this.generics = (_k = (_j = options.generics) === null || _j === void 0 ? void 0 : _j.filter(notNullish)) !== null && _k !== void 0 ? _k : [];
22
- this.parameters = (_m = (_l = options.parameters) === null || _l === void 0 ? void 0 : _l.filter(notNullish)) !== null && _m !== void 0 ? _m : [];
23
- this.returnType = (_o = options.returnType) !== null && _o !== void 0 ? _o : null;
24
- this.body = (_p = options.body) !== null && _p !== void 0 ? _p : null;
21
+ this.optional = (_j = options.optional) !== null && _j !== void 0 ? _j : false;
22
+ this.generics = (_l = (_k = options.generics) === null || _k === void 0 ? void 0 : _k.filter(notNullish)) !== null && _l !== void 0 ? _l : [];
23
+ this.parameters = (_o = (_m = options.parameters) === null || _m === void 0 ? void 0 : _m.filter(notNullish)) !== null && _o !== void 0 ? _o : [];
24
+ this.returnType = (_p = options.returnType) !== null && _p !== void 0 ? _p : null;
25
+ this.body = (_q = options.body) !== null && _q !== void 0 ? _q : null;
25
26
  }
26
27
  onWrite(builder) {
27
28
  const isInObjectDeclaration = this.getParentNode(builder) instanceof TsObject;
@@ -40,6 +41,8 @@ export class TsMethod extends TsNode {
40
41
  builder.append('abstract ');
41
42
  if (this.override)
42
43
  builder.append('override ');
44
+ if (this.async)
45
+ builder.append('async ');
43
46
  builder.append(this.inject.afterModifiers);
44
47
  builder.append(this.inject.beforeName, this.name, this.inject.afterName);
45
48
  if (this.optional)
@@ -5,11 +5,12 @@ import { writeTsGenericParameters } from '../utils/write-ts-generic-parameters';
5
5
  import { writeTsNodes } from '../utils/write-ts-nodes';
6
6
  export class TsReference extends TsNode {
7
7
  constructor(options) {
8
- var _a, _b, _c;
8
+ var _a, _b, _c, _d;
9
9
  super(options);
10
10
  this.name = options.name;
11
11
  this.moduleNameOrfilePath = (_a = options.moduleNameOrfilePath) !== null && _a !== void 0 ? _a : null;
12
12
  this.generics = (_c = (_b = options.generics) === null || _b === void 0 ? void 0 : _b.filter(notNullish)) !== null && _c !== void 0 ? _c : [];
13
+ this.importType = (_d = options.importType) !== null && _d !== void 0 ? _d : 'import';
13
14
  }
14
15
  onWrite(builder) {
15
16
  builder.append(this.name);
@@ -29,12 +30,16 @@ export class TsReference extends TsNode {
29
30
  TsReference.addImportHandlers = [
30
31
  {
31
32
  builderClass: TypeScriptFileBuilder,
32
- handler: (builder, reference) => builder.addImport(reference.name, reference.moduleNameOrfilePath),
33
+ handler: (builder, reference) => {
34
+ if (reference.moduleNameOrfilePath) {
35
+ builder.addImport(reference.name, reference.moduleNameOrfilePath, { type: reference.importType });
36
+ }
37
+ },
33
38
  },
34
39
  ];
35
40
  const createReference = (name, moduleNameOrfilePath, options) => new TsReference({ ...options, name, moduleNameOrfilePath });
36
41
  function _createFactory(name, moduleNameOrfilePath) {
37
- return Object.assign(() => createReference(name, moduleNameOrfilePath), {
42
+ return Object.assign((options) => createReference(name, moduleNameOrfilePath, options), {
38
43
  refName: name,
39
44
  moduleNameOrfilePath,
40
45
  });
@@ -43,7 +48,7 @@ function createFactory(name, moduleNameOrfilePath) {
43
48
  return _createFactory(name, moduleNameOrfilePath);
44
49
  }
45
50
  function _createGenericFactory(name, moduleNameOrfilePath) {
46
- return Object.assign((generics) => createReference(name, moduleNameOrfilePath, { generics }), {
51
+ return Object.assign((generics, options) => createReference(name, moduleNameOrfilePath, { ...options, generics }), {
47
52
  refName: name,
48
53
  moduleNameOrfilePath,
49
54
  infer: () => createReference(name, moduleNameOrfilePath),
@@ -4,4 +4,6 @@ import * as angular_1 from './angular';
4
4
  export { angular_1 as angular };
5
5
  import * as rxjs_1 from './rxjs';
6
6
  export { rxjs_1 as rxjs };
7
+ import * as k6_1 from './k6';
8
+ export { k6_1 as k6 };
7
9
  export * from './typescript';
@@ -0,0 +1,6 @@
1
+ import { tsReference } from '../nodes/reference';
2
+ // k6
3
+ export const jsonValue = tsReference.factory('JSONValue', 'k6');
4
+ // h6/http
5
+ export const response = tsReference.factory('Response', 'k6/http');
6
+ export const params = tsReference.factory('Params', 'k6/http');