@lenne.tech/nest-server 11.42.7 → 11.42.9
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/.claude/rules/better-auth.md +24 -0
- package/.claude/rules/configurable-features.md +5 -3
- package/.claude/rules/testing.md +4 -4
- package/FRAMEWORK-API.md +3 -2
- package/dist/core/common/decorators/api-methods.decorator.d.ts +2 -0
- package/dist/core/common/decorators/api-methods.decorator.js +8 -0
- package/dist/core/common/decorators/api-methods.decorator.js.map +1 -0
- package/dist/core/common/helpers/swagger.helper.js +324 -15
- package/dist/core/common/helpers/swagger.helper.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +1 -0
- package/dist/core/modules/ai/core-ai-mcp.controller.js +15 -1
- package/dist/core/modules/ai/core-ai-mcp.controller.js.map +1 -1
- package/dist/core/modules/ai/helpers/ai-mcp-oauth.helper.js +8 -1
- package/dist/core/modules/ai/helpers/ai-mcp-oauth.helper.js.map +1 -1
- package/dist/core/modules/ai/helpers/ai-mcp-oauth.registry.d.ts +7 -0
- package/dist/core/modules/ai/helpers/ai-mcp-oauth.registry.js +12 -0
- package/dist/core/modules/ai/helpers/ai-mcp-oauth.registry.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth.config.js +12 -0
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.js +2 -2
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-openapi.helper.d.ts +62 -0
- package/dist/core/modules/better-auth/core-better-auth-openapi.helper.js +95 -0
- package/dist/core/modules/better-auth/core-better-auth-openapi.helper.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.js +1 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.service.d.ts +10 -2
- package/dist/core/modules/better-auth/core-better-auth.service.js +89 -0
- package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
- package/dist/core/modules/tus/core-tus.controller.js +3 -0
- package/dist/core/modules/tus/core-tus.controller.js.map +1 -1
- package/dist/core/modules/tus/core-tus.service.d.ts +3 -0
- package/dist/core/modules/tus/core-tus.service.js +58 -25
- package/dist/core/modules/tus/core-tus.service.js.map +1 -1
- package/dist/core/modules/tus/interfaces/tus-config.interface.js +1 -0
- package/dist/core/modules/tus/interfaces/tus-config.interface.js.map +1 -1
- package/dist/core/modules/tus/tus.module.d.ts +2 -0
- package/dist/core/modules/tus/tus.module.js +23 -1
- package/dist/core/modules/tus/tus.module.js.map +1 -1
- package/dist/core.module.js +1 -1
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/REQUEST-LIFECYCLE.md +9 -1
- package/migration-guides/11.42.7-to-11.42.8.md +74 -0
- package/migration-guides/11.42.8-to-11.42.9.md +186 -0
- package/package.json +2 -2
- package/src/core/common/decorators/api-methods.decorator.ts +25 -0
- package/src/core/common/helpers/swagger.helper.ts +479 -19
- package/src/core/common/interfaces/server-options.interface.ts +46 -8
- package/src/core/common/interfaces/swagger-setup-options.interface.ts +5 -2
- package/src/core/modules/ai/README.md +7 -0
- package/src/core/modules/ai/core-ai-mcp.controller.ts +19 -2
- package/src/core/modules/ai/helpers/ai-mcp-oauth.helper.ts +12 -2
- package/src/core/modules/ai/helpers/ai-mcp-oauth.registry.ts +29 -0
- package/src/core/modules/better-auth/README.md +34 -0
- package/src/core/modules/better-auth/better-auth.config.ts +27 -1
- package/src/core/modules/better-auth/core-better-auth-api.middleware.ts +4 -17
- package/src/core/modules/better-auth/core-better-auth-openapi.helper.ts +219 -0
- package/src/core/modules/better-auth/core-better-auth.controller.ts +1 -0
- package/src/core/modules/better-auth/core-better-auth.service.ts +166 -2
- package/src/core/modules/tus/README.md +50 -14
- package/src/core/modules/tus/core-tus.controller.ts +6 -0
- package/src/core/modules/tus/core-tus.service.ts +97 -26
- package/src/core/modules/tus/interfaces/tus-config.interface.ts +1 -0
- package/src/core/modules/tus/tus.module.ts +43 -1
- package/src/core.module.ts +2 -1
- package/src/index.ts +1 -0
|
@@ -157,6 +157,7 @@ JWT-based authentication for existing projects:
|
|
|
157
157
|
| `@CommonError(code)` | Error code registration |
|
|
158
158
|
| `@SkipTenantCheck()` | Opt out of CoreTenantGuard validation on a method (not for tenant-restricted API tokens — they stay bound) |
|
|
159
159
|
| `@ApiTokenScopes(...scopes)` | Open a route/class to API tokens holding one of the scopes; tokens are denied everywhere else |
|
|
160
|
+
| `@ApiMethods(...methods)` | Swagger only (11.42.9): the HTTP methods an `@All()` handler actually serves — `setupSwagger()` documents those instead of all eight. No runtime effect |
|
|
160
161
|
|
|
161
162
|
### File Handling
|
|
162
163
|
|
|
@@ -166,7 +167,7 @@ JWT-based authentication for existing projects:
|
|
|
166
167
|
| **REST Endpoints** | `GET /files/id/:id`, `GET /files/:filename` (core, gated by `file.downloadRoles`, default ADMIN); `POST /files/upload`, `DELETE /files/:id` (project-specific) |
|
|
167
168
|
| **GraphQL Endpoints** | `getFileInfo` (`file.downloadRoles`), `uploadFile` / `uploadFiles` (`file.uploadRoles`), `deleteFile` (`file.deleteRoles`) — all default ADMIN |
|
|
168
169
|
| **File access control** | Roles are the coarse filter; per-file rules go in `CoreFileService.checkRights()` using metadata written at upload time. Cover BOTH the `id` and the `filename` branch — the filename route authorizes on the by-name lookup alone when presigned S3 downloads are on, and `deleteFileByName()` always does. Working reference: `src/server/modules/file/file.service.ts` (with `file.downloadRoles: [S_USER]` in `src/config.env.ts`, so the rule is actually reached). Both file classes carry `@SkipTenantCheck()` — GridFS is not tenant-scoped |
|
|
169
|
-
| **TUS Module** | Resumable uploads via tus.io protocol (creation, termination, expiration), gated by `tus.roles` (default `S_USER`); `OPTIONS` stays public for the CORS preflight. Records owner and, with `multiTenancy` only, the validated tenant at upload creation; a custom service plugs in via `TusModule.forRoot({ service })` |
|
|
170
|
+
| **TUS Module** | Resumable uploads via tus.io protocol (creation, termination, expiration), gated by `tus.roles` (default `S_USER`); `OPTIONS` stays public for the CORS preflight. Records owner and, with `multiTenancy` only, the validated tenant at upload creation; a custom service plugs in via `TusModule.forRoot({ service })`. Configured by `TusModule.forRoot({ config })`, else the server config's `tus` key (11.42.9+). Switched-off `creation` / `termination` answer 501 (enforced by `CoreTusService`, not `@tus/server`); upload URLs follow the path the upload was created at |
|
|
170
171
|
| **GridFS Migration** | Completed TUS uploads auto-migrate to GridFS |
|
|
171
172
|
| **CORS Support** | Automatic CORS headers for browser uploads |
|
|
172
173
|
|
|
@@ -636,6 +637,13 @@ If authentication succeeds, `req.user` is set with the authenticated user (inclu
|
|
|
636
637
|
> raw-forwarded routes. A forged `POST /iam/update-user {"roles":["admin"]}` is rejected with
|
|
637
638
|
> `FIELD_NOT_ALLOWED` (HTTP 400) at the input-parse stage, before any persistence.
|
|
638
639
|
|
|
640
|
+
> **Never routed: `/iam/open-api/*` (11.42.9).** nest-server registers Better-Auth's `openAPI()` plugin
|
|
641
|
+
> only so `setupSwagger()` can document Better-Auth's own routes, and marks its endpoints `SERVER_ONLY`:
|
|
642
|
+
> better-call leaves them out of the router, so a forwarded request answers 404 however its path is
|
|
643
|
+
> spelled, while the generator still runs in-process. Deliberately not a path check in the middleware —
|
|
644
|
+
> it would see the path as sent, Better-Auth the one `new URL()` produced (`/iam/./open-api/…`). Only a
|
|
645
|
+
> project that registered `openAPI()` itself in `betterAuth.plugins` gets the routes.
|
|
646
|
+
|
|
639
647
|
> **"Raw" has one exception since 11.38.0: the password-setting reset routes.**
|
|
640
648
|
> `CoreBetterAuthApiMiddleware.normalizeResetPassword()` rewrites the password field of
|
|
641
649
|
> `/reset-password`, `/email-otp/reset-password` and `/phone-number/reset-password` to its
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Migration Guide: 11.42.7 → 11.42.8
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
| Category | Details |
|
|
6
|
+
| -------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
7
|
+
| **Bugfix** | `setupSwagger()` enriches every operation an `@All()` route produces, including `SEARCH` (§1) |
|
|
8
|
+
| **Bugfix** | The Better-Auth pass-through route no longer appears as `/iam/{path}` in the Swagger document (§2) |
|
|
9
|
+
| **Dependencies** | dev: `vite` 8.3.3; override `js-yaml` 5.4.3 (§3) |
|
|
10
|
+
| **Breaking Changes** | None |
|
|
11
|
+
| **Migration Effort** | None for most projects. Regenerate a client built from `/api-docs-json` if you keep one (§2) |
|
|
12
|
+
|
|
13
|
+
## Quick Migration
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm update @lenne.tech/nest-server
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Vendor-mode projects pick it up with the core update.
|
|
20
|
+
|
|
21
|
+
## 1. `SEARCH` operations of `@All()` routes are enriched
|
|
22
|
+
|
|
23
|
+
For an `@All()` route, `@nestjs/swagger` documents one operation per HTTP method — including
|
|
24
|
+
`SEARCH`, which no OpenAPI version lists as a path-item method. 11.42.7 walked a fixed list of
|
|
25
|
+
methods and skipped it, so that one operation stayed as Swagger built it: no API-token scope line,
|
|
26
|
+
no `security: []` on a public route, no tenant header, and `operationTags` did not reach it — it
|
|
27
|
+
landed in its own tag group next to the regrouped siblings.
|
|
28
|
+
|
|
29
|
+
The helper now reads the operations from the path item itself, so `SEARCH` (and any other method
|
|
30
|
+
`@nestjs/swagger` emits) is treated like every other operation — in the full document and in the
|
|
31
|
+
API-token view.
|
|
32
|
+
|
|
33
|
+
Nothing to change in your code. If you assert on the document in tests, a `search` operation of an
|
|
34
|
+
`@All()` route now carries the same `x-api-token-scopes`, description line and tags as its siblings.
|
|
35
|
+
|
|
36
|
+
## 2. `/iam/{path}` is gone from the document
|
|
37
|
+
|
|
38
|
+
`CoreBetterAuthController.handlePluginRoutes` (`@All('*path')`) forwards every other `/iam/*` request
|
|
39
|
+
to Better-Auth's own handler. It appeared in Swagger as eight `/iam/{path}` operations without
|
|
40
|
+
parameters or description. It is now `@ApiExcludeEndpoint()`; the route itself is unchanged.
|
|
41
|
+
|
|
42
|
+
- **Generated clients:** a client generated from `/api-docs-json` (hey-api, openapi-generator, …)
|
|
43
|
+
loses its `coreBetterAuthControllerHandlePluginRoutes*` functions on the next generation. They
|
|
44
|
+
could not express any real Better-Auth call, so nothing should depend on them — but regenerate and
|
|
45
|
+
let the compiler confirm it.
|
|
46
|
+
- **Own controller:** a project controller that **overrides** `handlePluginRoutes` (re-declaring
|
|
47
|
+
`@All('*path')`) must also re-declare `@ApiExcludeEndpoint()` to keep it out of the document.
|
|
48
|
+
Decorator metadata belongs to the method, so an override starts without it. A controller that
|
|
49
|
+
only inherits the method is covered automatically.
|
|
50
|
+
|
|
51
|
+
## 3. Dependency updates
|
|
52
|
+
|
|
53
|
+
Maintenance only, nothing to change in your project:
|
|
54
|
+
|
|
55
|
+
| Package | Old | New | Where |
|
|
56
|
+
| --- | --- | --- | --- |
|
|
57
|
+
| `vite` | 8.3.2 | 8.3.3 | devDependencies (test tooling) |
|
|
58
|
+
| `js-yaml` 5.x | 5.4.2 | 5.4.3 | override target in `pnpm-workspace.yaml` (parser bug fix) |
|
|
59
|
+
|
|
60
|
+
`mongoose` 9.11.0 / `mongodb` 7.7.0 are deliberately not part of this release: the framework and the
|
|
61
|
+
starter have to raise `mongodb` together, because two driver copies make Better-Auth's Mongo adapter
|
|
62
|
+
reject each other's ids.
|
|
63
|
+
|
|
64
|
+
## Compatibility Notes
|
|
65
|
+
|
|
66
|
+
- Both changes only affect the generated Swagger/OpenAPI document. Routing, guards and API-token
|
|
67
|
+
enforcement are unchanged.
|
|
68
|
+
- The document gets smaller: the framework's own test server goes from 142 to 134 operations.
|
|
69
|
+
|
|
70
|
+
## References
|
|
71
|
+
|
|
72
|
+
- Helper: `src/core/common/helpers/swagger.helper.ts` (`operationsOf()`)
|
|
73
|
+
- Controller: `src/core/modules/better-auth/core-better-auth.controller.ts` (`handlePluginRoutes`)
|
|
74
|
+
- Tests: `tests/unit/swagger-helper.spec.ts`
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Migration Guide: 11.42.8 → 11.42.9
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
| Category | Details |
|
|
6
|
+
| -------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
7
|
+
| **New Feature** | `setupSwagger()` documents every HTTP interface the server makes usable — Better-Auth's own routes, `/ai/mcp`, the MCP OAuth endpoints (§1) |
|
|
8
|
+
| **Bugfix** | …and only those: routes the running configuration makes fail for every caller leave the document (§2) |
|
|
9
|
+
| **New Feature** | `@ApiMethods()` — the HTTP methods an `@All()` handler actually serves (§3) |
|
|
10
|
+
| **Bugfix** | The `tus` key in the server configuration takes effect — it was never read (§5). **Check your `tus` block** |
|
|
11
|
+
| **Bugfix** | TUS: upload URLs work below a global prefix and a project route, a `path` naming a new route moves the endpoint, `termination: false` / `creation: false` are enforced, new `relativeLocation` (§5) |
|
|
12
|
+
| **Bugfix** | `healthCheck.enabled: false` leaves the health check endpoints out (§6) |
|
|
13
|
+
| **Breaking Changes** | None in the API. A `tus` block in `config.env.ts` that did nothing before now applies (§5) |
|
|
14
|
+
| **Migration Effort** | Review a `tus` block in `config.env.ts` if you have one (§5.1); a proxy that renames the tus route or relative upload URLs need a look (§5.2). Regenerate a client built from `/api-docs-json` if you keep one (§4) |
|
|
15
|
+
|
|
16
|
+
## Quick Migration
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm update @lenne.tech/nest-server
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Vendor-mode projects pick it up with the core update.
|
|
23
|
+
|
|
24
|
+
## 1. Everything usable is documented
|
|
25
|
+
|
|
26
|
+
The document is built from the running application, so it follows the server configuration and every
|
|
27
|
+
project module automatically: a module that is registered appears, one that is not stays out. Three
|
|
28
|
+
kinds of interface used to be invisible to `@nestjs/swagger` because they have no Nest handler:
|
|
29
|
+
|
|
30
|
+
| Interface | Documented since 11.42.9 |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| Routes Better-Auth serves itself under `/iam` — whatever the configured plugins add (two-factor, passkey, sessions, password change, …), including plugins a project adds via `betterAuth.plugins` | from Better-Auth's own OpenAPI generator, under your Better-Auth controller (§1.1) |
|
|
33
|
+
| `/ai/mcp` (MCP server, `ai.mcp`) | POST/GET/DELETE, with the bearer requirement the endpoint enforces itself |
|
|
34
|
+
| MCP OAuth endpoints (`mountAiMcpOAuth()` in `main.ts`) | exactly the endpoints the call mounted (`/.well-known/…`, `/authorize`, `/token`, `/register`) |
|
|
35
|
+
|
|
36
|
+
### 1.1 Better-Auth routes
|
|
37
|
+
|
|
38
|
+
- Documented under your Better-Auth controller: same tags, and `operationTags` receives them with
|
|
39
|
+
`controller` set to that controller's class name (`handler` is Better-Auth's operation id).
|
|
40
|
+
- Operation ids: `<Controller>_betterAuth_<betterAuthOperationId>`, e.g.
|
|
41
|
+
`BetterAuthController_betterAuth_changePassword`. Unique and stable across builds.
|
|
42
|
+
- Schemas Better-Auth refers to are added as `BetterAuthUser`, `BetterAuthSession`, … so they cannot
|
|
43
|
+
collide with your own `User` model; Better-Auth's OpenAPI 3.1 constructs are converted to 3.0.
|
|
44
|
+
- Security: what Better-Auth enforces. A route behind one of its session middlewares (or one of the
|
|
45
|
+
social-account routes that check the session in their handler) carries the global requirement —
|
|
46
|
+
bearer or the session cookie; every other route is public (`security: []`): sign-in, password reset,
|
|
47
|
+
get-session, the two-factor verification steps of a sign-in. Better-Auth's own generator marks every
|
|
48
|
+
route bearer-only, so this is read from the live instance, not from the generator. Routes of plugins
|
|
49
|
+
you add yourself (`admin()`, `organization()`, …) always carry the global requirement.
|
|
50
|
+
- With API tokens configured they carry "API tokens: not allowed on this route" and never appear in the
|
|
51
|
+
API-token view.
|
|
52
|
+
- Under a global prefix or URI versioning Better-Auth's own routes are not reachable (the API
|
|
53
|
+
middleware does not forward them); they are then not documented, and a warning says why.
|
|
54
|
+
|
|
55
|
+
**Behind it:** Better-Auth exposes its generator only through its `openAPI()` plugin, so nest-server
|
|
56
|
+
registers that plugin itself (`disableDefaultReference: true`). Its own route,
|
|
57
|
+
`/iam/open-api/generate-schema`, is not part of your API: its endpoints are marked server-only, so
|
|
58
|
+
Better-Auth never routes them and they answer 404, as before this release. If you registered `openAPI()`
|
|
59
|
+
in `betterAuth.plugins` yourself, nothing changes — your registration replaces the internal one.
|
|
60
|
+
|
|
61
|
+
## 2. Only what can succeed is documented
|
|
62
|
+
|
|
63
|
+
A route that answers an error to every caller under the running configuration is left out. Each rule
|
|
64
|
+
reads the switch the handler itself reads:
|
|
65
|
+
|
|
66
|
+
| Configuration | Left out |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| `auth.legacyEndpoints` keeps REST closed (the default since 11.38.0) | legacy `/auth/signin`, `/auth/signup`, `/auth/logout`, `/auth/refresh-token` (they answer 410) |
|
|
69
|
+
| `betterAuth.emailAndPassword.enabled: false` | `/iam/sign-in/email`, `/iam/sign-up/email` |
|
|
70
|
+
| `betterAuth.emailAndPassword.disableSignUp: true` | `/iam/sign-up/email` |
|
|
71
|
+
| `betterAuth.emailAndPassword.passwordReset: false` | `/iam/request-password-reset`, `/iam/reset-password`, `/iam/reset-password/{token}` |
|
|
72
|
+
| Better-Auth's own options, read from the live instance — so `betterAuth.options` counts too | e.g. POST `/iam/get-session` without `session.deferSessionRefresh`, social routes without a provider, two-factor OTP routes without `otpOptions.sendOTP`, `/iam/delete-user` without `user.deleteUser.enabled`, `/iam/change-email` without `user.changeEmail.enabled`, `/iam/update-session` without session fields that accept input |
|
|
73
|
+
| A Hub panel switched off (`hub.collectors.*`, `hub.mailbox`, `hub.emailPreview`, `hub.db`, `hub.migrations`) | its `*.json` endpoint and actions, which would only answer `{ available: false }` or 400 |
|
|
74
|
+
|
|
75
|
+
A project controller extending a core controller is covered too — the rules go by the handler, not by
|
|
76
|
+
the class name.
|
|
77
|
+
|
|
78
|
+
## 3. `@ApiMethods()` for `@All()` handlers
|
|
79
|
+
|
|
80
|
+
`@nestjs/swagger` documents an `@All()` handler as eight operations (GET … SEARCH), whatever it serves.
|
|
81
|
+
The TUS handlers now declare theirs, so `/tus` shows POST and `/tus/{id}` HEAD/PATCH/DELETE. Use the
|
|
82
|
+
decorator on your own catch-all handlers:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { ApiMethods } from '@lenne.tech/nest-server';
|
|
86
|
+
|
|
87
|
+
@All(':id')
|
|
88
|
+
@ApiMethods('get', 'delete')
|
|
89
|
+
async handle(@Req() req: Request, @Res() res: Response) { … }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
It affects the document only, never routing.
|
|
93
|
+
|
|
94
|
+
## 4. Generated clients
|
|
95
|
+
|
|
96
|
+
A client generated from `/api-docs-json` (hey-api, openapi-generator, …) gains functions for the newly
|
|
97
|
+
documented routes and loses those for routes your configuration switches off (and the eight
|
|
98
|
+
`/iam/{path}` catch-all functions since 11.42.8). Regenerate and let the compiler point at anything that
|
|
99
|
+
used a removed function.
|
|
100
|
+
|
|
101
|
+
## 5. TUS: the configuration takes effect
|
|
102
|
+
|
|
103
|
+
### 5.1 The server configuration's `tus` key is read
|
|
104
|
+
|
|
105
|
+
`TusModule.forRoot()` without a `config` of its own now reads the `tus` key of the server configuration
|
|
106
|
+
(`config.env.ts`, `NSC__TUS__*`) — the zero-config rule `BetterAuthModule.forRoot()` already follows. An
|
|
107
|
+
explicit `TusModule.forRoot({ config })` still wins. **Before this release that key was never read**:
|
|
108
|
+
TUS ran with the defaults whatever it said.
|
|
109
|
+
|
|
110
|
+
What that means for you, if `config.env.ts` has a `tus` block:
|
|
111
|
+
|
|
112
|
+
| You set | Before | Now |
|
|
113
|
+
| --- | --- | --- |
|
|
114
|
+
| `tus: false` | TUS enabled anyway | `/tus` is not registered |
|
|
115
|
+
| `allowedTypes` | every type accepted | other types answer 415 at creation |
|
|
116
|
+
| `maxSize` | 50 GB | your limit (413 above it) |
|
|
117
|
+
| `roles` | `[S_USER]` | your roles |
|
|
118
|
+
| `termination`, `creation`, `path`, `expiration`, … | defaults | your values (see 5.2 / 5.3) |
|
|
119
|
+
|
|
120
|
+
These are the values the block was written to enforce, so this is the behaviour you asked for — but it
|
|
121
|
+
starts on this upgrade. Check that the allowed types cover what your clients upload before you deploy.
|
|
122
|
+
|
|
123
|
+
### 5.2 `path` and upload URLs
|
|
124
|
+
|
|
125
|
+
Before this release `path` only changed the URL handed to a client for a new upload (`Location`); the
|
|
126
|
+
endpoint itself always stayed where the controller declared it. Every setup that works today keeps
|
|
127
|
+
working:
|
|
128
|
+
|
|
129
|
+
| `path` | Since 11.42.9 |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| unset | The upload URL is built from the path the upload was created at — so resuming now also works below a global prefix, a URI version or a project controller's own route, where it answered 404 before |
|
|
132
|
+
| ends with the controller's route — `'/api/tus'` (global prefix) or `'/files/tus'` (a proxy that strips `/files`) | Unchanged: the controller stays, upload URLs use this path. This was the workaround for the old behaviour and needs no change |
|
|
133
|
+
| a new route — `'/uploads'` | The controller is now mounted there (a project controller too, as `roles` already did). Before, the endpoint stayed at `/tus` while clients were sent to `/uploads/…`, so no upload could ever be resumed |
|
|
134
|
+
|
|
135
|
+
Like any controller route, a new route sits below the global prefix and the URI version.
|
|
136
|
+
|
|
137
|
+
Two cases need a look:
|
|
138
|
+
|
|
139
|
+
- **A proxy that renames the route** (public `/files/upload` forwarded as `/tus`): `path: '/files/upload'`
|
|
140
|
+
now moves the endpoint. Remove `path` and override `uploadCollectionPath(req)` in your
|
|
141
|
+
`CoreTusService` subclass to return the public path.
|
|
142
|
+
- **Relative upload URLs.** The framework now builds the upload URL itself, which takes precedence over
|
|
143
|
+
`@tus/server`'s `relativeLocation`. Use `tus.relativeLocation: true` (new); a `relativeLocation` you
|
|
144
|
+
pass to the tus server yourself — in a vendored core, for example — is honoured as well.
|
|
145
|
+
|
|
146
|
+
### 5.3 Switched-off extensions are enforced
|
|
147
|
+
|
|
148
|
+
`@tus/server` itself ignores the extension flags. Since this release:
|
|
149
|
+
|
|
150
|
+
| Setting | Effect |
|
|
151
|
+
| --- | --- |
|
|
152
|
+
| `termination: false` | DELETE answers 501, OPTIONS no longer advertises `termination` |
|
|
153
|
+
| `creation: false` | POST answers 501, OPTIONS no longer advertises the creation extensions |
|
|
154
|
+
| `creationWithUpload: false` | a POST carrying data answers 501 |
|
|
155
|
+
|
|
156
|
+
`checksum` and `concatenation` have no effect: neither built-in store supports them. The boot log now
|
|
157
|
+
lists the extensions the server actually offers.
|
|
158
|
+
|
|
159
|
+
## 6. `healthCheck.enabled: false`
|
|
160
|
+
|
|
161
|
+
The flag was declared and ignored: any `healthCheck` object registered `GET /health-check` and the
|
|
162
|
+
`healthCheck` query. `enabled: false` now leaves both out (and out of the Swagger document).
|
|
163
|
+
|
|
164
|
+
## Compatibility Notes
|
|
165
|
+
|
|
166
|
+
- The Swagger work changes nothing at runtime. Better-Auth's `openAPI()` plugin is now registered, but
|
|
167
|
+
kept off the router, so `/iam/open-api/*` answers 404 exactly as before. The runtime changes of this
|
|
168
|
+
release are the ones in §5 and §6.
|
|
169
|
+
- A `CoreTusService` subclass that overrides `onUploadCreate()` keeps the extension checks of §5.3: they
|
|
170
|
+
run before the hook, whether or not the override calls `super`.
|
|
171
|
+
- The description of Better-Auth's routes is prepared once at application bootstrap
|
|
172
|
+
(`CoreBetterAuthService.onApplicationBootstrap()`). A project service extending
|
|
173
|
+
`CoreBetterAuthService` that overrides `onApplicationBootstrap()` must call `super` to keep it.
|
|
174
|
+
- An explicit `@ApiBearerAuth()` / `@ApiSecurity()` on a route the guards admit to everybody now keeps
|
|
175
|
+
its security requirement instead of being documented as public.
|
|
176
|
+
|
|
177
|
+
## References
|
|
178
|
+
|
|
179
|
+
- Swagger helper: `src/core/common/helpers/swagger.helper.ts`
|
|
180
|
+
- Better-Auth rules: `src/core/modules/better-auth/core-better-auth-openapi.helper.ts`
|
|
181
|
+
- Decorator: `src/core/common/decorators/api-methods.decorator.ts`
|
|
182
|
+
- TUS: `src/core/modules/tus/tus.module.ts`, `src/core/modules/tus/core-tus.service.ts`, `src/core/modules/tus/README.md`
|
|
183
|
+
- Tests: `tests/unit/swagger-helper.spec.ts`, `tests/unit/swagger-availability.spec.ts`,
|
|
184
|
+
`tests/unit/better-auth-openapi-availability.spec.ts`, `tests/better-auth-openapi.e2e-spec.ts`,
|
|
185
|
+
`tests/unit/tus-module-config.spec.ts`, `tests/tus-protocol-config.e2e-spec.ts`,
|
|
186
|
+
`tests/unit/core-module-signatures.spec.ts`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.42.
|
|
3
|
+
"version": "11.42.9",
|
|
4
4
|
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -221,7 +221,7 @@
|
|
|
221
221
|
"tus-js-client": "4.3.1",
|
|
222
222
|
"typescript": "5.9.3",
|
|
223
223
|
"unplugin-swc": "2.0.0",
|
|
224
|
-
"vite": "8.3.
|
|
224
|
+
"vite": "8.3.3",
|
|
225
225
|
"vite-plugin-node": "8.0.0",
|
|
226
226
|
"vitest": "4.1.11"
|
|
227
227
|
},
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SetMetadata } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
/** Metadata key of {@link ApiMethods} */
|
|
4
|
+
export const API_METHODS_KEY = 'lt:apiMethods';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lists the HTTP methods an `@All()` handler actually serves.
|
|
8
|
+
*
|
|
9
|
+
* `@nestjs/swagger` documents an `@All()` handler as eight operations (GET, POST, PUT, DELETE, PATCH,
|
|
10
|
+
* OPTIONS, HEAD, SEARCH), whatever the handler does with them. `setupSwagger()` keeps only the methods
|
|
11
|
+
* named here, so a catch-all that serves three of them is documented with three.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* @All(':id')
|
|
16
|
+
* @ApiMethods('head', 'patch', 'delete')
|
|
17
|
+
* async handleUpload(@Req() req: Request, @Res() res: Response) { … }
|
|
18
|
+
* ```
|
|
19
|
+
* @since 11.42.9
|
|
20
|
+
*/
|
|
21
|
+
export const ApiMethods = (...methods: string[]) =>
|
|
22
|
+
SetMetadata(
|
|
23
|
+
API_METHODS_KEY,
|
|
24
|
+
methods.map((method) => method.toLowerCase()),
|
|
25
|
+
);
|