tsoa-next 8.0.4 → 8.0.5-dev.57.84bb4a63
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/README.MD +18 -59
- package/dist/cli-bin.d.ts +2 -0
- package/dist/cli-bin.js +16 -0
- package/dist/cli-bin.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/spec.d.ts +2 -0
- package/dist/spec.js +72 -0
- package/dist/spec.js.map +1 -0
- package/package.json +28 -4
package/README.MD
CHANGED
|
@@ -47,65 +47,22 @@ Where historical release notes or migration references still point upstream, the
|
|
|
47
47
|
- Runtime validation of tsoa-next should behave as closely as possible to the specifications that the generated OpenAPI 2/3 schema describes. Any differences in validation logic are clarified by logging warnings during the generation of the OpenAPI Specification (OAS) and/or the routes.
|
|
48
48
|
- Please note that by enabling OpenAPI 3 you minimize the chances of divergent validation logic since OpenAPI 3 has a more expressive schema syntax.
|
|
49
49
|
|
|
50
|
-
##
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
translate: (key, params) => translateMessage(key, params),
|
|
67
|
-
errorFormatter: failure => failure,
|
|
68
|
-
},
|
|
69
|
-
})
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
```ts
|
|
73
|
-
import * as t from 'io-ts'
|
|
74
|
-
import { withMessage } from 'io-ts-types'
|
|
75
|
-
import { Body, Controller, Post, Route, Validate } from 'tsoa-next'
|
|
76
|
-
|
|
77
|
-
interface PositiveFloatBrand {
|
|
78
|
-
readonly PositiveFloat: unique symbol
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const PositiveFloat = withMessage(
|
|
82
|
-
t.brand(t.number, (n): n is t.Branded<number, PositiveFloatBrand> => Number.isFinite(n) && n > 0, 'PositiveFloat'),
|
|
83
|
-
() => 'validation.wager.amount.mustBePositiveFloat',
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
const WagerCodec = t.type({
|
|
87
|
-
amount: PositiveFloat,
|
|
88
|
-
outcome: t.Int,
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
type Wager = t.TypeOf<typeof WagerCodec>
|
|
92
|
-
|
|
93
|
-
@Route('wagers')
|
|
94
|
-
export class WagersController extends Controller {
|
|
95
|
-
@Post()
|
|
96
|
-
public createWager(
|
|
97
|
-
@Body()
|
|
98
|
-
@Validate('io-ts', WagerCodec)
|
|
99
|
-
wager: Wager,
|
|
100
|
-
): Wager {
|
|
101
|
-
return wager
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
## Migration Note
|
|
107
|
-
|
|
108
|
-
This feature is fully opt-in. If you do not use `@Validate(...)`, existing interface/class models, generated routes, validation behavior, and error responses are unchanged.
|
|
50
|
+
## Feature List
|
|
51
|
+
|
|
52
|
+
- Generate OpenAPI 2.0, 3.0, or 3.1 documents directly from your TypeScript controllers, models, and JSDoc comments.
|
|
53
|
+
- Treat TypeScript controllers and models as the source of truth for paths, parameters, schemas, examples, tags, and security metadata.
|
|
54
|
+
- Generate framework-specific route handlers for Express, Koa, and Hapi, or supply your own Handlebars templates for custom runtimes.
|
|
55
|
+
- Validate request input at runtime with configurable coercion and additional-property handling that stays aligned with the generated schema.
|
|
56
|
+
- Expose controller-local spec endpoints with `@SpecPath(...)` without reading a generated spec file from local disk at request time.
|
|
57
|
+
- Serve built-in `json`, `yaml`, `swagger`, `redoc`, and `rapidoc` spec targets, with docs UI packages loaded lazily as optional peers when available.
|
|
58
|
+
- Attach multiple `@SpecPath(...)` decorators to the same controller as long as their resolved paths are unique.
|
|
59
|
+
- Cache built-in or custom spec responses with `'none'`, in-process `'memory'`, or a custom cache handler that can read from strings or streams.
|
|
60
|
+
- Return either `string` or `Readable` responses from custom `@SpecPath(...)` handlers for bespoke documentation or downstream integrations.
|
|
61
|
+
- Use `@Validate(...)` to delegate runtime validation to supported external schema libraries such as `zod`, `joi`, `yup`, `superstruct`, or `io-ts`.
|
|
62
|
+
- Customize validation translation and failure formatting through the optional validation context accepted by generated `RegisterRoutes(...)` functions.
|
|
63
|
+
- Support authentication hooks, dependency injection, typed alternate responders, file uploads, custom middleware, and custom validation workflows.
|
|
64
|
+
- Use the `tsoa` CLI for spec and route generation, or call the programmatic APIs from `tsoa-next/cli`.
|
|
65
|
+
- Target modern Node.js releases with the support policy verified in CI across the previous LTS, current LTS, and Node vNext.
|
|
109
66
|
|
|
110
67
|
## Getting Started
|
|
111
68
|
|
|
@@ -127,6 +84,8 @@ This feature is fully opt-in. If you do not use `@Validate(...)`, existing inter
|
|
|
127
84
|
|
|
128
85
|
Check out the [guides](https://tsoa-next.dev/)
|
|
129
86
|
|
|
87
|
+
Use the companion [playground repository](https://github.com/tsoa-next/playground) for runnable example apps and server-focused scenarios.
|
|
88
|
+
|
|
130
89
|
See example controllers in [the tests](https://github.com/tsoa-next/tsoa-next/tree/main/tests/fixtures/controllers)
|
|
131
90
|
|
|
132
91
|
See example models in [the tests](https://github.com/tsoa-next/tsoa-next/blob/main/tests/fixtures/testModel.ts)
|
package/dist/cli-bin.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const runCLI_1 = require("@tsoa-next/cli/dist/runCLI");
|
|
5
|
+
if (require.main === module) {
|
|
6
|
+
void (async () => {
|
|
7
|
+
try {
|
|
8
|
+
await (0, runCLI_1.runCLI)();
|
|
9
|
+
}
|
|
10
|
+
catch (err) {
|
|
11
|
+
console.error('tsoa cli error:\n', err);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
})();
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=cli-bin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-bin.js","sourceRoot":"","sources":["../src/cli-bin.ts"],"names":[],"mappings":";;;AACA,uDAAmD;AAEnD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,IAAI,CAAC;YACH,MAAM,IAAA,eAAM,GAAE,CAAA;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAA;YACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC,CAAC,EAAE,CAAA;AACN,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("@tsoa-next/runtime"), exports);
|
|
18
|
+
__exportStar(require("./spec"), exports);
|
|
18
19
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAkC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAkC;AAClC,yCAAsB"}
|
package/dist/spec.d.ts
ADDED
package/dist/spec.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createOpenApiSpecGenerator = createOpenApiSpecGenerator;
|
|
37
|
+
function assertSpecConfig(config) {
|
|
38
|
+
if (!config) {
|
|
39
|
+
throw new Error('SpecPath requires spec generation settings. Provide spec configuration when generating routes so built-in spec targets can rebuild the OpenAPI document at runtime.');
|
|
40
|
+
}
|
|
41
|
+
return config;
|
|
42
|
+
}
|
|
43
|
+
function createOpenApiSpecGenerator(config) {
|
|
44
|
+
let specPromise;
|
|
45
|
+
const stringCache = new Map();
|
|
46
|
+
const loadCli = async () => await Promise.resolve().then(() => __importStar(require('@tsoa-next/cli')));
|
|
47
|
+
const getSpecObject = async () => {
|
|
48
|
+
specPromise ??= (async () => {
|
|
49
|
+
const runtimeConfig = assertSpecConfig(config);
|
|
50
|
+
const cli = await loadCli();
|
|
51
|
+
return cli.buildSpec(runtimeConfig.spec, runtimeConfig.compilerOptions, runtimeConfig.ignore, undefined, runtimeConfig.defaultNumberType);
|
|
52
|
+
})();
|
|
53
|
+
return specPromise;
|
|
54
|
+
};
|
|
55
|
+
const getSpecString = async (format) => {
|
|
56
|
+
const cached = stringCache.get(format);
|
|
57
|
+
if (cached) {
|
|
58
|
+
return cached;
|
|
59
|
+
}
|
|
60
|
+
const stringPromise = (async () => {
|
|
61
|
+
const cli = await loadCli();
|
|
62
|
+
return cli.serializeSpec(await getSpecObject(), format === 'yaml');
|
|
63
|
+
})();
|
|
64
|
+
stringCache.set(format, stringPromise);
|
|
65
|
+
return stringPromise;
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
getSpecObject,
|
|
69
|
+
getSpecString,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=spec.js.map
|
package/dist/spec.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../src/spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,gEAkCC;AA1CD,SAAS,gBAAgB,CAAC,MAAkC;IAC1D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,qKAAqK,CAAC,CAAA;IACxL,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAgB,0BAA0B,CAAC,MAAkC;IAC3E,IAAI,WAA2E,CAAA;IAC/E,MAAM,WAAW,GAAG,IAAI,GAAG,EAAoC,CAAA;IAE/D,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE,CAAC,wDAAa,gBAAgB,GAAC,CAAA;IAC1D,MAAM,aAAa,GAAmC,KAAK,IAAI,EAAE;QAC/D,WAAW,KAAK,CAAC,KAAK,IAAI,EAAE;YAC1B,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAA;YAC9C,MAAM,GAAG,GAAG,MAAM,OAAO,EAAE,CAAA;YAC3B,OAAO,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,eAAmE,EAAE,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAA;QAC/L,CAAC,CAAC,EAAE,CAAA;QAEJ,OAAO,WAAW,CAAA;IACpB,CAAC,CAAA;IAED,MAAM,aAAa,GAAmC,KAAK,EAAC,MAAM,EAAC,EAAE;QACnE,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QACtC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAA;QACf,CAAC;QAED,MAAM,aAAa,GAAG,CAAC,KAAK,IAAI,EAAE;YAChC,MAAM,GAAG,GAAG,MAAM,OAAO,EAAE,CAAA;YAC3B,OAAO,GAAG,CAAC,aAAa,CAAC,MAAM,aAAa,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,CAAA;QACpE,CAAC,CAAC,EAAE,CAAA;QAEJ,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;QACtC,OAAO,aAAa,CAAA;IACtB,CAAC,CAAA;IAED,OAAO;QACL,aAAa;QACb,aAAa;KACd,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsoa-next",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.5-dev.57.84bb4a63",
|
|
4
4
|
"description": "Build swagger-compliant REST APIs using TypeScript and Node",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"typings": "./dist/index.d.ts",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"tsoa-next-logo-590.png"
|
|
10
10
|
],
|
|
11
11
|
"bin": {
|
|
12
|
-
"tsoa": "dist/cli.js"
|
|
12
|
+
"tsoa": "dist/cli-bin.js"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"build": "npm run tsc",
|
|
@@ -32,13 +32,37 @@
|
|
|
32
32
|
"author": "Vanna DiCatania <vanna@dicatania.me> (http://www.dicatania.me)",
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@tsoa-next/cli": "8.0.
|
|
36
|
-
"@tsoa-next/runtime": "8.0.
|
|
35
|
+
"@tsoa-next/cli": "8.0.5-dev.57.84bb4a63",
|
|
36
|
+
"@tsoa-next/runtime": "8.0.5-dev.57.84bb4a63"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "24.12.0",
|
|
40
40
|
"typescript": "^5.9.3"
|
|
41
41
|
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"hapi-swagger": "^17.3.2",
|
|
44
|
+
"rapidoc": "^9.3.8",
|
|
45
|
+
"redoc": "^2.5.2",
|
|
46
|
+
"swagger-ui-express": "^5.0.1",
|
|
47
|
+
"swagger-ui-koa": "^0.0.1"
|
|
48
|
+
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"hapi-swagger": {
|
|
51
|
+
"optional": true
|
|
52
|
+
},
|
|
53
|
+
"rapidoc": {
|
|
54
|
+
"optional": true
|
|
55
|
+
},
|
|
56
|
+
"redoc": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"swagger-ui-express": {
|
|
60
|
+
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"swagger-ui-koa": {
|
|
63
|
+
"optional": true
|
|
64
|
+
}
|
|
65
|
+
},
|
|
42
66
|
"repository": {
|
|
43
67
|
"type": "git",
|
|
44
68
|
"url": "https://github.com/tsoa-next/tsoa-next.git",
|