@tsoa-next/cli 8.0.4 → 8.0.5-dev.58.3748c499
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.
- package/dist/api.d.ts +12 -1
- package/dist/api.js +21 -2
- package/dist/api.js.map +1 -1
- package/dist/discovery.d.ts +13 -0
- package/dist/discovery.js +195 -0
- package/dist/discovery.js.map +1 -0
- package/dist/module/generate-routes.d.ts +4 -0
- package/dist/module/generate-routes.js +4 -0
- package/dist/module/generate-routes.js.map +1 -1
- package/dist/module/generate-spec.d.ts +11 -1
- package/dist/module/generate-spec.js +34 -17
- package/dist/module/generate-spec.js.map +1 -1
- package/dist/routeGeneration/defaultRouteGenerator.d.ts +4 -0
- package/dist/routeGeneration/defaultRouteGenerator.js +4 -0
- package/dist/routeGeneration/defaultRouteGenerator.js.map +1 -1
- package/dist/routeGeneration/routeGenerator.d.ts +8 -1
- package/dist/routeGeneration/routeGenerator.js +9 -0
- package/dist/routeGeneration/routeGenerator.js.map +1 -1
- package/dist/routeGeneration/templates/express.hbs +50 -1
- package/dist/routeGeneration/templates/hapi.hbs +52 -1
- package/dist/routeGeneration/templates/koa.hbs +43 -1
- package/dist/runCLI.js +176 -16
- package/dist/runCLI.js.map +1 -1
- package/package.json +2 -2
|
@@ -41,6 +41,7 @@ const runtime_1 = require("@tsoa-next/runtime");
|
|
|
41
41
|
const fs_1 = require("../utils/fs");
|
|
42
42
|
const pathUtils_1 = require("../utils/pathUtils");
|
|
43
43
|
const routeGenerator_1 = require("./routeGenerator");
|
|
44
|
+
/** Default route generator for the built-in Express, Koa, and Hapi templates. */
|
|
44
45
|
class DefaultRouteGenerator extends routeGenerator_1.AbstractRouteGenerator {
|
|
45
46
|
pathTransformerFn;
|
|
46
47
|
template;
|
|
@@ -63,11 +64,13 @@ class DefaultRouteGenerator extends routeGenerator_1.AbstractRouteGenerator {
|
|
|
63
64
|
this.template = options.middlewareTemplate;
|
|
64
65
|
}
|
|
65
66
|
}
|
|
67
|
+
/** Loads the selected template file and generates the route output. */
|
|
66
68
|
async GenerateCustomRoutes() {
|
|
67
69
|
const data = await (0, fs_1.fsReadFile)(path.join(this.template));
|
|
68
70
|
const file = data.toString();
|
|
69
71
|
return await this.GenerateRoutes(file);
|
|
70
72
|
}
|
|
73
|
+
/** Writes the generated route file to disk. */
|
|
71
74
|
async GenerateRoutes(middlewareTemplate) {
|
|
72
75
|
const allowedExtensions = this.options.esm ? ['.ts', '.mts', '.cts'] : ['.ts'];
|
|
73
76
|
if (!fs.lstatSync(this.options.routesDir).isDirectory()) {
|
|
@@ -88,6 +91,7 @@ class DefaultRouteGenerator extends routeGenerator_1.AbstractRouteGenerator {
|
|
|
88
91
|
pathTransformer(path) {
|
|
89
92
|
return this.pathTransformerFn(path);
|
|
90
93
|
}
|
|
94
|
+
/** Renders the route template with the current metadata context. */
|
|
91
95
|
buildContent(middlewareTemplate) {
|
|
92
96
|
handlebars.registerHelper('json', (context) => {
|
|
93
97
|
return JSON.stringify(context);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultRouteGenerator.js","sourceRoot":"","sources":["../../src/routeGeneration/defaultRouteGenerator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uDAAwC;AACxC,4CAA6B;AAC7B,gDAAiC;AAEjC,gDAAiE;AACjE,oCAAqD;AACrD,kDAA4D;AAC5D,qDAAyD;AAEzD,MAAa,qBAAsB,SAAQ,uCAA4C;IACrF,iBAAiB,CAA0B;IAC3C,QAAQ,CAAQ;IAChB,YAAY,QAAuB,EAAE,OAA6B;QAChE,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QACxB,IAAI,CAAC,iBAAiB,GAAG,mCAAuB,CAAA;QAEhD,QAAQ,OAAO,CAAC,UAAU,EAAE,CAAC;YAC3B,KAAK,MAAM;gBACT,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,oCAAoC,CAAC,CAAA;gBAChF,IAAI,CAAC,iBAAiB,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAA;gBAC/C,MAAK;YACP,KAAK,KAAK;gBACR,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,mCAAmC,CAAC,CAAA;gBAC/E,MAAK;YACP,KAAK,SAAS,CAAC;YACf;gBACE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,uCAAuC,CAAC,CAAA;QACvF,CAAC;QAED,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,kBAAkB,CAAA;QAC5C,CAAC;IACH,CAAC;
|
|
1
|
+
{"version":3,"file":"defaultRouteGenerator.js","sourceRoot":"","sources":["../../src/routeGeneration/defaultRouteGenerator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import type { ExtendedRoutesConfig } from '../api';
|
|
2
2
|
import { Tsoa, TsoaRoute } from '@tsoa-next/runtime';
|
|
3
|
+
/**
|
|
4
|
+
* Base implementation for route generators that transform metadata into framework-specific route files.
|
|
5
|
+
*/
|
|
3
6
|
export declare abstract class AbstractRouteGenerator<Config extends ExtendedRoutesConfig> {
|
|
4
7
|
protected readonly metadata: Tsoa.Metadata;
|
|
5
8
|
protected readonly options: Config;
|
|
6
9
|
constructor(metadata: Tsoa.Metadata, options: Config);
|
|
7
10
|
/**
|
|
8
|
-
*
|
|
11
|
+
* Generates the configured route output for the active framework or custom template.
|
|
9
12
|
*/
|
|
10
13
|
abstract GenerateCustomRoutes(): Promise<void>;
|
|
14
|
+
/** Builds the runtime model metadata consumed by generated route handlers. */
|
|
11
15
|
buildModels(): TsoaRoute.Models;
|
|
12
16
|
protected pathTransformer(path: string): string;
|
|
17
|
+
/** Builds the Handlebars template context used by the default route templates. */
|
|
13
18
|
protected buildContext(): {
|
|
14
19
|
authenticationModule: string | undefined;
|
|
15
20
|
basePath: string;
|
|
@@ -37,12 +42,14 @@ export declare abstract class AbstractRouteGenerator<Config extends ExtendedRout
|
|
|
37
42
|
path: string;
|
|
38
43
|
}[];
|
|
39
44
|
environment: NodeJS.ProcessEnv;
|
|
45
|
+
existingGetPaths: string[];
|
|
40
46
|
iocModule: string | undefined;
|
|
41
47
|
minimalSwaggerConfig: {
|
|
42
48
|
noImplicitAdditionalProperties: "ignore" | "throw-on-extras" | "silently-remove-extras";
|
|
43
49
|
bodyCoercion: boolean;
|
|
44
50
|
};
|
|
45
51
|
models: TsoaRoute.Models;
|
|
52
|
+
runtimeSpecConfig: import("@tsoa-next/runtime").RuntimeSpecConfigSnapshot | undefined;
|
|
46
53
|
useFileUploads: boolean;
|
|
47
54
|
multerOpts: Config["multerOpts"];
|
|
48
55
|
useSecurity: boolean;
|
|
@@ -39,6 +39,9 @@ const runtime_1 = require("@tsoa-next/runtime");
|
|
|
39
39
|
const internalTypeGuards_1 = require("../utils/internalTypeGuards");
|
|
40
40
|
const pathUtils_1 = require("../utils/pathUtils");
|
|
41
41
|
const fs_1 = require("../utils/fs");
|
|
42
|
+
/**
|
|
43
|
+
* Base implementation for route generators that transform metadata into framework-specific route files.
|
|
44
|
+
*/
|
|
42
45
|
class AbstractRouteGenerator {
|
|
43
46
|
metadata;
|
|
44
47
|
options;
|
|
@@ -46,6 +49,7 @@ class AbstractRouteGenerator {
|
|
|
46
49
|
this.metadata = metadata;
|
|
47
50
|
this.options = options;
|
|
48
51
|
}
|
|
52
|
+
/** Builds the runtime model metadata consumed by generated route handlers. */
|
|
49
53
|
buildModels() {
|
|
50
54
|
const models = {};
|
|
51
55
|
Object.keys(this.metadata.referenceTypeMap).forEach(name => {
|
|
@@ -96,6 +100,7 @@ class AbstractRouteGenerator {
|
|
|
96
100
|
pathTransformer(path) {
|
|
97
101
|
return (0, pathUtils_1.convertBracesPathParams)(path);
|
|
98
102
|
}
|
|
103
|
+
/** Builds the Handlebars template context used by the default route templates. */
|
|
99
104
|
buildContext() {
|
|
100
105
|
const authenticationModule = this.options.authenticationModule ? this.getRelativeImportPath(this.options.authenticationModule) : undefined;
|
|
101
106
|
const iocModule = this.options.iocModule ? this.getRelativeImportPath(this.options.iocModule) : undefined;
|
|
@@ -139,9 +144,13 @@ class AbstractRouteGenerator {
|
|
|
139
144
|
};
|
|
140
145
|
}),
|
|
141
146
|
environment: process.env,
|
|
147
|
+
existingGetPaths: this.metadata.controllers.flatMap(controller => controller.methods
|
|
148
|
+
.filter(method => method.method.toLowerCase() === 'get')
|
|
149
|
+
.map(method => (0, pathUtils_1.normalisePath)(`${normalisedBasePath}${this.pathTransformer((0, pathUtils_1.normalisePath)(controller.path, '/'))}${this.pathTransformer((0, pathUtils_1.normalisePath)(method.path, '/'))}`, '/', '', false))),
|
|
142
150
|
iocModule,
|
|
143
151
|
minimalSwaggerConfig: { noImplicitAdditionalProperties: this.options.noImplicitAdditionalProperties, bodyCoercion: this.options.bodyCoercion },
|
|
144
152
|
models: this.buildModels(),
|
|
153
|
+
runtimeSpecConfig: this.options.runtimeSpecConfig,
|
|
145
154
|
useFileUploads: this.metadata.controllers.some(controller => controller.methods.some(method => method.parameters.some(parameter => this.isFileUploadParameter(parameter)))),
|
|
146
155
|
multerOpts: {
|
|
147
156
|
limits: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routeGenerator.js","sourceRoot":"","sources":["../../src/routeGeneration/routeGenerator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAAiC;AAEjC,gDAAiE;AACjE,oEAAuD;AACvD,kDAA2E;AAC3E,oCAAkD;AAElD,MAAsB,sBAAsB;IAErB;IACA;IAFrB,YACqB,QAAuB,EACvB,OAAe;QADf,aAAQ,GAAR,QAAQ,CAAe;QACvB,YAAO,GAAP,OAAO,CAAQ;IACjC,CAAC;
|
|
1
|
+
{"version":3,"file":"routeGenerator.js","sourceRoot":"","sources":["../../src/routeGeneration/routeGenerator.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/tsoa-next/tsoa-next
|
|
4
4
|
import type { AdditionalProps, Tsoa, TsoaRoute } from 'tsoa-next';
|
|
5
|
-
import {
|
|
5
|
+
import { createOpenApiSpecGenerator, fetchMiddlewares, fetchSpecPaths, normalisePath, resolveSpecPathResponse, ExpressTemplateService } from 'tsoa-next';
|
|
6
6
|
{{#each controllers}}
|
|
7
7
|
import { {{name}} } from '{{modulePath}}';
|
|
8
8
|
{{/each}}
|
|
@@ -15,6 +15,7 @@ import { iocContainer } from '{{iocModule}}';
|
|
|
15
15
|
import type { IocContainer, IocContainerFactory } from 'tsoa-next';
|
|
16
16
|
{{/if}}
|
|
17
17
|
import type { Request as ExRequest, Response as ExResponse, RequestHandler, Router } from 'express';
|
|
18
|
+
import { pipeline } from 'node:stream';
|
|
18
19
|
{{#if useFileUploads}}
|
|
19
20
|
{{#if esm}}
|
|
20
21
|
import multer from 'multer';
|
|
@@ -49,6 +50,11 @@ const models: TsoaRoute.Models = {
|
|
|
49
50
|
},
|
|
50
51
|
{{/each}}
|
|
51
52
|
};
|
|
53
|
+
{{#if runtimeSpecConfig}}
|
|
54
|
+
const specGenerator = createOpenApiSpecGenerator({{{json runtimeSpecConfig}}});
|
|
55
|
+
{{else}}
|
|
56
|
+
const specGenerator = createOpenApiSpecGenerator();
|
|
57
|
+
{{/if}}
|
|
52
58
|
|
|
53
59
|
{{#if useFileUploads}}
|
|
54
60
|
export function RegisterRoutes(app: Router,opts?:{multer?:ReturnType<typeof multer>; validation?: Tsoa.ValidationContext}) {
|
|
@@ -67,6 +73,7 @@ export function RegisterRoutes(app: Router,opts?:{validation?: Tsoa.ValidationCo
|
|
|
67
73
|
validation: opts?.validation,
|
|
68
74
|
};
|
|
69
75
|
const templateService = new ExpressTemplateService(models, additionalProps);
|
|
76
|
+
const registeredGetPaths = new Set<string>({{{json existingGetPaths}}});
|
|
70
77
|
{{#each controllers}}
|
|
71
78
|
{{#each actions}}
|
|
72
79
|
|
|
@@ -125,6 +132,48 @@ export function RegisterRoutes(app: Router,opts?:{validation?: Tsoa.ValidationCo
|
|
|
125
132
|
});
|
|
126
133
|
{{/each}}
|
|
127
134
|
{{/each}}
|
|
135
|
+
{{#each controllers}}
|
|
136
|
+
for (const specPath of fetchSpecPaths({{name}})) {
|
|
137
|
+
const specFullPath = normalisePath('{{../basePath}}{{path}}' + specPath.normalizedPath, '/', '', false);
|
|
138
|
+
if (registeredGetPaths.has(specFullPath)) {
|
|
139
|
+
throw new Error(`Duplicate GET route detected while registering @SpecPath for {{name}} at '${specFullPath}'.`);
|
|
140
|
+
}
|
|
141
|
+
registeredGetPaths.add(specFullPath);
|
|
142
|
+
|
|
143
|
+
app.get(specFullPath, async function {{name}}_specPath(request: ExRequest, response: ExResponse, next: any) {
|
|
144
|
+
try {
|
|
145
|
+
const specResponse = await resolveSpecPathResponse({
|
|
146
|
+
controllerClass: {{name}},
|
|
147
|
+
fullPath: specFullPath,
|
|
148
|
+
request,
|
|
149
|
+
response,
|
|
150
|
+
runtime: 'express',
|
|
151
|
+
specGenerator,
|
|
152
|
+
specPath,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
if (specResponse.contentType) {
|
|
156
|
+
response.type(specResponse.contentType);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
response.status(200);
|
|
160
|
+
if (typeof specResponse.body === 'string') {
|
|
161
|
+
response.send(specResponse.body);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
pipeline(specResponse.body, response, error => {
|
|
166
|
+
if (error) {
|
|
167
|
+
next(error);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
return;
|
|
171
|
+
} catch (err) {
|
|
172
|
+
return next(err);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
{{/each}}
|
|
128
177
|
{{#if useSecurity}}
|
|
129
178
|
|
|
130
179
|
function authenticateMiddleware(security: TsoaRoute.Security[] = []) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/tsoa-next/tsoa-next
|
|
4
4
|
import type { AdditionalProps, Tsoa, TsoaRoute } from 'tsoa-next';
|
|
5
|
-
import { fetchMiddlewares, HapiTemplateService } from 'tsoa-next';
|
|
5
|
+
import { createOpenApiSpecGenerator, fetchMiddlewares, fetchSpecPaths, normalisePath, resolveSpecPathResponse, HapiTemplateService } from 'tsoa-next';
|
|
6
6
|
{{#each controllers}}
|
|
7
7
|
|
|
8
8
|
import { {{name}} } from '{{modulePath}}';
|
|
@@ -41,6 +41,11 @@ const models: TsoaRoute.Models = {
|
|
|
41
41
|
},
|
|
42
42
|
{{/each}}
|
|
43
43
|
};
|
|
44
|
+
{{#if runtimeSpecConfig}}
|
|
45
|
+
const specGenerator = createOpenApiSpecGenerator({{{json runtimeSpecConfig}}});
|
|
46
|
+
{{else}}
|
|
47
|
+
const specGenerator = createOpenApiSpecGenerator();
|
|
48
|
+
{{/if}}
|
|
44
49
|
|
|
45
50
|
export function RegisterRoutes(server: any, opts?: { validation?: Tsoa.ValidationContext }) {
|
|
46
51
|
// ###########################################################################################################
|
|
@@ -56,6 +61,7 @@ export function RegisterRoutes(server: any, opts?: { validation?: Tsoa.Validatio
|
|
|
56
61
|
additionalProps,
|
|
57
62
|
{ boomify, isBoom },
|
|
58
63
|
);
|
|
64
|
+
const registeredGetPaths = new Set<string>({{{json existingGetPaths}}});
|
|
59
65
|
{{#each controllers}}
|
|
60
66
|
{{#each actions}}
|
|
61
67
|
const args{{../name}}_{{name}}: Record<string, TsoaRoute.ParameterSchema> = {
|
|
@@ -139,6 +145,51 @@ export function RegisterRoutes(server: any, opts?: { validation?: Tsoa.Validatio
|
|
|
139
145
|
});
|
|
140
146
|
{{/each}}
|
|
141
147
|
{{/each}}
|
|
148
|
+
{{#each controllers}}
|
|
149
|
+
for (const specPath of fetchSpecPaths({{name}})) {
|
|
150
|
+
const specFullPath = normalisePath('{{../basePath}}{{path}}' + specPath.normalizedPath, '/', '', false);
|
|
151
|
+
if (registeredGetPaths.has(specFullPath)) {
|
|
152
|
+
throw new Error(`Duplicate GET route detected while registering @SpecPath for {{name}} at '${specFullPath}'.`);
|
|
153
|
+
}
|
|
154
|
+
registeredGetPaths.add(specFullPath);
|
|
155
|
+
|
|
156
|
+
server.route({
|
|
157
|
+
method: 'get',
|
|
158
|
+
path: specFullPath,
|
|
159
|
+
options: {
|
|
160
|
+
handler: async function {{name}}_specPath(request: Request, h: ResponseToolkit) {
|
|
161
|
+
try {
|
|
162
|
+
const specResponse = await resolveSpecPathResponse({
|
|
163
|
+
controllerClass: {{name}},
|
|
164
|
+
fullPath: specFullPath,
|
|
165
|
+
request,
|
|
166
|
+
response: h,
|
|
167
|
+
runtime: 'hapi',
|
|
168
|
+
specGenerator,
|
|
169
|
+
specPath,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const response = h.response(specResponse.body).code(200);
|
|
173
|
+
if (specResponse.contentType) {
|
|
174
|
+
response.type(specResponse.contentType);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return response;
|
|
178
|
+
} catch (error: any) {
|
|
179
|
+
if (isBoom(error)) {
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const errorMessage = error instanceof Error ? error.message : error?.message;
|
|
184
|
+
const boomErr = boomify(error instanceof Error ? error : new Error(errorMessage), { statusCode: error?.status || 500 });
|
|
185
|
+
boomErr.output.payload = { ...boomErr.output.payload, message: errorMessage };
|
|
186
|
+
throw boomErr;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
{{/each}}
|
|
142
193
|
{{#if useSecurity}}
|
|
143
194
|
|
|
144
195
|
function authenticateMiddleware(security: TsoaRoute.Security[] = []) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/tsoa-next/tsoa-next
|
|
4
4
|
import type { AdditionalProps, Tsoa, TsoaRoute } from 'tsoa-next';
|
|
5
|
-
import { fetchMiddlewares, KoaTemplateService } from 'tsoa-next';
|
|
5
|
+
import { createOpenApiSpecGenerator, fetchMiddlewares, fetchSpecPaths, normalisePath, resolveSpecPathResponse, KoaTemplateService } from 'tsoa-next';
|
|
6
6
|
{{#each controllers}}
|
|
7
7
|
|
|
8
8
|
import { {{name}} } from '{{modulePath}}';
|
|
@@ -51,6 +51,11 @@ const models: TsoaRoute.Models = {
|
|
|
51
51
|
},
|
|
52
52
|
{{/each}}
|
|
53
53
|
};
|
|
54
|
+
{{#if runtimeSpecConfig}}
|
|
55
|
+
const specGenerator = createOpenApiSpecGenerator({{{json runtimeSpecConfig}}});
|
|
56
|
+
{{else}}
|
|
57
|
+
const specGenerator = createOpenApiSpecGenerator();
|
|
58
|
+
{{/if}}
|
|
54
59
|
|
|
55
60
|
{{#if useFileUploads}}
|
|
56
61
|
export function RegisterRoutes(router: KoaRouter,opts?:{multer?:ReturnType<typeof multer>; validation?: Tsoa.ValidationContext}) {
|
|
@@ -69,6 +74,7 @@ export function RegisterRoutes(router: KoaRouter,opts?:{validation?: Tsoa.Valida
|
|
|
69
74
|
validation: opts?.validation,
|
|
70
75
|
};
|
|
71
76
|
const templateService = new KoaTemplateService(models, additionalProps);
|
|
77
|
+
const registeredGetPaths = new Set<string>({{{json existingGetPaths}}});
|
|
72
78
|
|
|
73
79
|
{{#each controllers}}
|
|
74
80
|
{{#each actions}}
|
|
@@ -129,6 +135,42 @@ export function RegisterRoutes(router: KoaRouter,opts?:{validation?: Tsoa.Valida
|
|
|
129
135
|
});
|
|
130
136
|
{{/each}}
|
|
131
137
|
{{/each}}
|
|
138
|
+
{{#each controllers}}
|
|
139
|
+
for (const specPath of fetchSpecPaths({{name}})) {
|
|
140
|
+
const specFullPath = normalisePath('{{../basePath}}{{path}}' + specPath.normalizedPath, '/', '', false);
|
|
141
|
+
if (registeredGetPaths.has(specFullPath)) {
|
|
142
|
+
throw new Error(`Duplicate GET route detected while registering @SpecPath for {{name}} at '${specFullPath}'.`);
|
|
143
|
+
}
|
|
144
|
+
registeredGetPaths.add(specFullPath);
|
|
145
|
+
|
|
146
|
+
router.get(specFullPath,
|
|
147
|
+
async function {{name}}_specPath(context: Context, next: Next) {
|
|
148
|
+
try {
|
|
149
|
+
const specResponse = await resolveSpecPathResponse({
|
|
150
|
+
controllerClass: {{name}},
|
|
151
|
+
fullPath: specFullPath,
|
|
152
|
+
request: context.request,
|
|
153
|
+
response: context.response,
|
|
154
|
+
runtime: 'koa',
|
|
155
|
+
specGenerator,
|
|
156
|
+
specPath,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (specResponse.contentType) {
|
|
160
|
+
context.type = specResponse.contentType;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
context.status = 200;
|
|
164
|
+
context.body = specResponse.body;
|
|
165
|
+
return;
|
|
166
|
+
} catch (err) {
|
|
167
|
+
const error = err as any;
|
|
168
|
+
context.status = error.status || 500;
|
|
169
|
+
context.throw(context.status, error.message, error);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
{{/each}}
|
|
132
174
|
{{#if useSecurity}}
|
|
133
175
|
|
|
134
176
|
function authenticateMiddleware(security: TsoaRoute.Security[] = []) {
|
package/dist/runCLI.js
CHANGED
|
@@ -34,13 +34,23 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.runCLI = runCLI;
|
|
37
|
-
const
|
|
37
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
38
|
+
const node_os_1 = require("node:os");
|
|
39
|
+
const node_util_1 = require("node:util");
|
|
40
|
+
const discovery_1 = require("./discovery");
|
|
41
|
+
const outputPrefixStorage = new node_async_hooks_1.AsyncLocalStorage();
|
|
38
42
|
const configurationArgs = {
|
|
39
43
|
alias: 'c',
|
|
40
44
|
describe: 'tsoa configuration file; default is tsoa.json in the working directory',
|
|
41
45
|
required: false,
|
|
42
46
|
string: true,
|
|
43
47
|
};
|
|
48
|
+
const discoverArgs = {
|
|
49
|
+
describe: 'discover tsoa config files using a path or glob before running the command',
|
|
50
|
+
required: false,
|
|
51
|
+
requiresArg: true,
|
|
52
|
+
string: true,
|
|
53
|
+
};
|
|
44
54
|
const hostArgs = {
|
|
45
55
|
describe: 'API host',
|
|
46
56
|
required: false,
|
|
@@ -64,6 +74,7 @@ const jsonArgs = {
|
|
|
64
74
|
const configCommandArgs = {
|
|
65
75
|
basePath: basePathArgs,
|
|
66
76
|
configuration: configurationArgs,
|
|
77
|
+
discover: discoverArgs,
|
|
67
78
|
};
|
|
68
79
|
const specCommandArgs = {
|
|
69
80
|
...configCommandArgs,
|
|
@@ -94,6 +105,142 @@ const getHideBin = (moduleExports) => {
|
|
|
94
105
|
}
|
|
95
106
|
throw new TypeError('Unable to load yargs/helpers');
|
|
96
107
|
};
|
|
108
|
+
const loadCLIAPI = async () => {
|
|
109
|
+
return await Promise.resolve().then(() => __importStar(require('./api')));
|
|
110
|
+
};
|
|
111
|
+
const renderPrefixedOutput = (prefix, args) => {
|
|
112
|
+
const rendered = (0, node_util_1.format)(...args);
|
|
113
|
+
return rendered
|
|
114
|
+
.split('\n')
|
|
115
|
+
.map(line => `${prefix}${line}`)
|
|
116
|
+
.join('\n');
|
|
117
|
+
};
|
|
118
|
+
const withPatchedConsole = async (action) => {
|
|
119
|
+
const originalConsoleError = console.error;
|
|
120
|
+
const originalConsoleLog = console.log;
|
|
121
|
+
const originalConsoleWarn = console.warn;
|
|
122
|
+
console.log = (...args) => {
|
|
123
|
+
const prefix = outputPrefixStorage.getStore();
|
|
124
|
+
if (!prefix) {
|
|
125
|
+
originalConsoleLog(...args);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
originalConsoleLog(renderPrefixedOutput(prefix, args));
|
|
129
|
+
};
|
|
130
|
+
console.warn = (...args) => {
|
|
131
|
+
const prefix = outputPrefixStorage.getStore();
|
|
132
|
+
if (!prefix) {
|
|
133
|
+
originalConsoleWarn(...args);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
originalConsoleWarn(renderPrefixedOutput(prefix, args));
|
|
137
|
+
};
|
|
138
|
+
console.error = (...args) => {
|
|
139
|
+
const prefix = outputPrefixStorage.getStore();
|
|
140
|
+
if (!prefix) {
|
|
141
|
+
originalConsoleError(...args);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
originalConsoleError(renderPrefixedOutput(prefix, args));
|
|
145
|
+
};
|
|
146
|
+
try {
|
|
147
|
+
return await action();
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
console.error = originalConsoleError;
|
|
151
|
+
console.log = originalConsoleLog;
|
|
152
|
+
console.warn = originalConsoleWarn;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const ensureExclusiveConfigurationModes = (configuration, discover) => {
|
|
156
|
+
if (configuration !== undefined && discover !== undefined) {
|
|
157
|
+
throw new Error('The --configuration and --discover options cannot be used together.');
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
const getDiscoveryInputDisplay = (input) => input ?? (0, discovery_1.getDefaultDiscoverRoot)();
|
|
161
|
+
const ensureDiscoveredConfigs = async (input) => {
|
|
162
|
+
const discoveryResult = await (0, discovery_1.discoverConfigs)(input);
|
|
163
|
+
if (discoveryResult.matches.length === 0) {
|
|
164
|
+
throw new Error(`No tsoa config files found for '${getDiscoveryInputDisplay(input)}'.`);
|
|
165
|
+
}
|
|
166
|
+
return discoveryResult.matches;
|
|
167
|
+
};
|
|
168
|
+
const runTasksWithConcurrency = async (limit, tasks) => {
|
|
169
|
+
const results = new Array(tasks.length);
|
|
170
|
+
let nextTaskIndex = 0;
|
|
171
|
+
const workers = Array.from({ length: Math.min(limit, tasks.length) }, async () => {
|
|
172
|
+
while (nextTaskIndex < tasks.length) {
|
|
173
|
+
const currentTaskIndex = nextTaskIndex;
|
|
174
|
+
nextTaskIndex += 1;
|
|
175
|
+
try {
|
|
176
|
+
const value = await tasks[currentTaskIndex]();
|
|
177
|
+
results[currentTaskIndex] = {
|
|
178
|
+
status: 'fulfilled',
|
|
179
|
+
value,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
results[currentTaskIndex] = {
|
|
184
|
+
status: 'rejected',
|
|
185
|
+
reason: error,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
await Promise.all(workers);
|
|
191
|
+
return results;
|
|
192
|
+
};
|
|
193
|
+
const formatFailureReason = (reason) => {
|
|
194
|
+
if (reason instanceof Error) {
|
|
195
|
+
return reason.message;
|
|
196
|
+
}
|
|
197
|
+
return String(reason);
|
|
198
|
+
};
|
|
199
|
+
const formatDiscoveredCommandPrefix = (displayPath) => `[${displayPath}] `;
|
|
200
|
+
const executeDiscoveredTask = async (commandName, api, args, configurationPath, displayPath, execute) => {
|
|
201
|
+
return await outputPrefixStorage.run(formatDiscoveredCommandPrefix(displayPath), async () => {
|
|
202
|
+
console.log(`Starting ${commandName}`);
|
|
203
|
+
const result = await execute(api, configurationPath, args);
|
|
204
|
+
console.log(`Finished ${commandName}`);
|
|
205
|
+
return result;
|
|
206
|
+
});
|
|
207
|
+
};
|
|
208
|
+
const createDiscoveredCommandTask = (commandName, api, args, discoveredConfig, execute) => {
|
|
209
|
+
return async () => await executeDiscoveredTask(commandName, api, args, discoveredConfig.absolutePath, discoveredConfig.displayPath, execute);
|
|
210
|
+
};
|
|
211
|
+
const runDiscoveredCommand = async (commandName, args, execute) => {
|
|
212
|
+
ensureExclusiveConfigurationModes(args.configuration, args.discover);
|
|
213
|
+
if (!args.discover) {
|
|
214
|
+
const api = await loadCLIAPI();
|
|
215
|
+
return await execute(api, args.configuration, args);
|
|
216
|
+
}
|
|
217
|
+
const discoveredConfigs = await ensureDiscoveredConfigs(args.discover);
|
|
218
|
+
const api = await loadCLIAPI();
|
|
219
|
+
const concurrency = Math.min(discoveredConfigs.length, (0, node_os_1.availableParallelism)());
|
|
220
|
+
const results = await withPatchedConsole(async () => {
|
|
221
|
+
return await runTasksWithConcurrency(concurrency, discoveredConfigs.map(discoveredConfig => createDiscoveredCommandTask(commandName, api, args, discoveredConfig, execute)));
|
|
222
|
+
});
|
|
223
|
+
const failures = results.flatMap((result, index) => {
|
|
224
|
+
if (result?.status !== 'rejected') {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
const discoveredConfig = discoveredConfigs[index];
|
|
228
|
+
if (!discoveredConfig) {
|
|
229
|
+
return [];
|
|
230
|
+
}
|
|
231
|
+
return [`- ${discoveredConfig.displayPath}: ${formatFailureReason(result.reason)}`];
|
|
232
|
+
});
|
|
233
|
+
if (failures.length > 0) {
|
|
234
|
+
throw new Error(`Failed ${commandName} for discovered config files:\n${failures.join('\n')}`);
|
|
235
|
+
}
|
|
236
|
+
return results;
|
|
237
|
+
};
|
|
238
|
+
const runDiscoverCommand = async (pathOrGlob) => {
|
|
239
|
+
const discoveryResult = await ensureDiscoveredConfigs(pathOrGlob);
|
|
240
|
+
for (const discoveredConfig of discoveryResult) {
|
|
241
|
+
process.stdout.write(`${discoveredConfig.displayPath}\n`);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
97
244
|
async function runCLI() {
|
|
98
245
|
const [yargsModule, yargsHelpers] = await Promise.all([Promise.resolve().then(() => __importStar(require('yargs'))), Promise.resolve().then(() => __importStar(require('yargs/helpers')))]);
|
|
99
246
|
const yargsFactory = getYargsFactory(yargsModule);
|
|
@@ -102,28 +249,41 @@ async function runCLI() {
|
|
|
102
249
|
return cli
|
|
103
250
|
.scriptName('tsoa')
|
|
104
251
|
.usage('Usage: $0 <command> [options]')
|
|
252
|
+
.command('discover [pathOrGlob]', 'Discover tsoa config files beneath a path or glob', command => command.positional('pathOrGlob', {
|
|
253
|
+
describe: 'Path or glob to search. Defaults to the current working directory.',
|
|
254
|
+
string: true,
|
|
255
|
+
type: 'string',
|
|
256
|
+
}), async (args) => {
|
|
257
|
+
await runDiscoverCommand(args.pathOrGlob);
|
|
258
|
+
})
|
|
105
259
|
.command('spec', 'Generate OpenAPI spec', specCommandArgs, async (args) => {
|
|
106
|
-
await (
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
260
|
+
await runDiscoveredCommand('spec', args, async (api, configurationPath, resolvedArgs) => {
|
|
261
|
+
await api.generateSpecFromArgs({
|
|
262
|
+
basePath: resolvedArgs.basePath,
|
|
263
|
+
configuration: configurationPath,
|
|
264
|
+
host: resolvedArgs.host,
|
|
265
|
+
json: resolvedArgs.json,
|
|
266
|
+
yaml: resolvedArgs.yaml,
|
|
267
|
+
});
|
|
112
268
|
});
|
|
113
269
|
})
|
|
114
270
|
.command('routes', 'Generate routes', configCommandArgs, async (args) => {
|
|
115
|
-
await (
|
|
116
|
-
|
|
117
|
-
|
|
271
|
+
await runDiscoveredCommand('routes', args, async (api, configurationPath, resolvedArgs) => {
|
|
272
|
+
await api.generateRoutesFromArgs({
|
|
273
|
+
basePath: resolvedArgs.basePath,
|
|
274
|
+
configuration: configurationPath,
|
|
275
|
+
});
|
|
118
276
|
});
|
|
119
277
|
})
|
|
120
278
|
.command('spec-and-routes', 'Generate OpenAPI spec and routes', specCommandArgs, async (args) => {
|
|
121
|
-
await (
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
279
|
+
await runDiscoveredCommand('spec-and-routes', args, async (api, configurationPath, resolvedArgs) => {
|
|
280
|
+
await api.generateSpecAndRoutes({
|
|
281
|
+
basePath: resolvedArgs.basePath,
|
|
282
|
+
configuration: configurationPath,
|
|
283
|
+
host: resolvedArgs.host,
|
|
284
|
+
json: resolvedArgs.json,
|
|
285
|
+
yaml: resolvedArgs.yaml,
|
|
286
|
+
});
|
|
127
287
|
});
|
|
128
288
|
})
|
|
129
289
|
.demandCommand(1, 1, 'Must provide a valid command.')
|