@lenne.tech/nest-server 11.42.6 → 11.42.8

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.
@@ -14,11 +14,26 @@
14
14
 
15
15
  ```bash
16
16
  pnpm update @lenne.tech/nest-server
17
+ pnpm run update # starter-based projects: raises every exact pin you share with the framework
17
18
  ```
18
19
 
19
20
  Then check `main.ts` as described in §1. Vendor-mode projects pick up the core update and need the
20
21
  same check.
21
22
 
23
+ **Exact pins below the framework's own split packages in two.** A project that pins `@nestjs/core`,
24
+ `@nestjs/common`, `mongoose` or another package the framework also declares, at a LOWER exact version,
25
+ gets two copies of it. The install only prints a peer warning. The failure appears in the tests, as a
26
+ dependency-injection error that does not look like a version problem (see Troubleshooting).
27
+ `pnpm run update` (`extras/sync-packages.mjs` in starter-based projects) raises those pins. Without
28
+ that script, list the deviations and raise each one:
29
+
30
+ ```bash
31
+ node -e "const f=require('@lenne.tech/nest-server/package.json'),p=require('./package.json');const want={...f.dependencies,...f.peerDependencies};for(const s of ['dependencies','devDependencies'])for(const[k,v]of Object.entries(p[s]||{}))if(want[k]&&/^\d/.test(want[k])&&want[k]!==v)console.log(s,k,v,'->',want[k])"
32
+ ```
33
+
34
+ An `overrides:` entry in `pnpm-workspace.yaml` must not pin such a package below the framework's
35
+ version either: it forces the framework onto the older version without anybody having tested it.
36
+
22
37
  ## 1. Keep `useBodyParser()` next to a path-scoped parser
23
38
 
24
39
  §1 of the [11.42.3 → 11.42.4 guide](./11.42.3-to-11.42.4.md) recommended moving the body limit from
@@ -86,6 +101,7 @@ receive these fixes with their template update.
86
101
  | ------- | ----- | --- |
87
102
  | Boot warning "No global json body parser is registered" | `main.ts` registers a path-scoped `json()` and no global parser | Add `server.useBodyParser('json')` to `main.ts` (§1) |
88
103
  | Requests arrive with an empty body outside one path; sign-in reports "Missing input" | Same cause, on a version before 11.42.6 | Same fix (§1) |
104
+ | Tests fail with `Nest can't resolve dependencies of the MongooseCoreModule (MongooseConnectionName, ?)` (often hidden behind `Cannot read properties of undefined` from a `beforeAll` that swallows it) | Two copies of `@nestjs/core`: the project pins it below the framework's version | Raise the exact pins (Quick Migration), then check that `pnpm-lock.yaml` holds one copy of each |
89
105
  | `check:overrides` prints `could not obtain an audit report (fetch failed)` | The npm registry was not reachable during the audit | Re-run with network access, or pass a captured report with `--audit-file` |
90
106
  | `check:overrides` fails with `records a failed audit, not a result` | The report passed with `--audit-file` is a pnpm error, not an audit | Capture the report again once the registry answers |
91
107
 
@@ -0,0 +1,115 @@
1
+ # Migration Guide: 11.42.6 → 11.42.7
2
+
3
+ ## Overview
4
+
5
+ | Category | Details |
6
+ | -------------------- | --------------------------------------------------------------------------------------------------------------- |
7
+ | **New Feature** | `setupSwagger()` — a Swagger document that says how each route is reached: security, API-token scopes, tenant header (§1) |
8
+ | **New Feature** | Optional second document with only the routes an API token may call (§2) |
9
+ | **Dependencies** | `nodemailer` 10.0.15, `@modelcontextprotocol/sdk` 1.32.1, dev: `oxlint` 1.87.0 (§3) |
10
+ | **Breaking Changes** | None |
11
+ | **Migration Effort** | Optional. Switching `main.ts` to the helper replaces the hand-built `DocumentBuilder` block with one call |
12
+
13
+ ## Quick Migration
14
+
15
+ ```bash
16
+ pnpm update @lenne.tech/nest-server
17
+ ```
18
+
19
+ Nothing changes until `main.ts` calls the new helper. Vendor-mode projects pick it up with the core
20
+ update.
21
+
22
+ ## 1. `setupSwagger()` instead of a hand-built `DocumentBuilder`
23
+
24
+ The starters built the document like this:
25
+
26
+ ```typescript
27
+ const config = new DocumentBuilder().setTitle('…').addBearerAuth().build();
28
+ SwaggerModule.setup('swagger', server, () => SwaggerModule.createDocument(server, config, { … }), {
29
+ jsonDocumentUrl: '/api-docs-json',
30
+ });
31
+ ```
32
+
33
+ `addBearerAuth()` registers a scheme but attaches it to no route. A token entered under "Authorize" is
34
+ therefore sent with almost no request: in one project 10 of 158 operations carried a security entry.
35
+ And what a caller needs to know — is the route public, which API-token scope does it release, does it
36
+ read the tenant header — lived only in decorators.
37
+
38
+ ```typescript
39
+ import { setupSwagger } from '@lenne.tech/nest-server';
40
+
41
+ setupSwagger(server, {
42
+ description: 'API of my project',
43
+ documentOptions: {
44
+ extraModels: [CoreUserModel, CoreAuthModel, User, PersistenceModel, CorePersistenceModel, FilterArgs],
45
+ },
46
+ title: 'My Project API',
47
+ version: packageJson.version,
48
+ });
49
+ ```
50
+
51
+ Paths stay as before (`/swagger`, `/api-docs-json`) unless `path` / `jsonDocumentUrl` say otherwise.
52
+ What the document now contains, read from the same metadata the guards read:
53
+
54
+ | Feature in the config | In the document |
55
+ | --- | --- |
56
+ | always | `bearer` as a global security requirement — "Authorize" applies to every route. Public routes (no `@Roles`, or `S_EVERYONE`) carry `security: []` |
57
+ | `betterAuth` + `cookies` on | the session cookie (`iam.session_token`, or the name `COOKIE_PREFIX` / `basePath` produce) as a second, alternative requirement |
58
+ | `apiTokens` on | per operation `x-api-token-scopes` and a description line: "allowed with scope `read`" or "not allowed on this route". `@ApiTokenScopes()` on the method replaces the class declaration, exactly as in `assertApiTokenScopes()` |
59
+ | `multiTenancy` on | a reusable `TenantHeader` parameter (`X-Tenant-Id`, or `multiTenancy.headerName`) on every operation except public ones and `@SkipTenantCheck()`; its description says which callers need it (sessions and personal tokens) and which may omit it (company tokens) |
60
+
61
+ Optional:
62
+
63
+ - `operationTags: (operation) => string[] | undefined` regroups operations by use case instead of by
64
+ controller; `tags: [{ name, description }]` orders and describes them.
65
+ - `configureBuilder: (builder) => builder` adds servers, contact or further schemes.
66
+ - `customOptions` is passed to `SwaggerModule.setup()` for both documents.
67
+
68
+ Each operation is mapped to its handler through the default operation id (`<Controller>_<method>`, with
69
+ `[<n>]` for a handler serving several paths). An own `operationIdFactory` is therefore refused. Two different controller classes with the same name
70
+ cannot be told apart; their operations are left as Swagger built them, with a warning.
71
+
72
+ ## 2. A document for API-token callers
73
+
74
+ ```typescript
75
+ setupSwagger(server, { …, apiTokenView: true });
76
+ // or: apiTokenView: { path: 'swagger-partner', title: 'Partner API' }
77
+ ```
78
+
79
+ Serves a second document (default: UI `swagger-api-tokens`, JSON `/api-docs-api-tokens-json`) with only
80
+ the operations that release a scope, the bearer scheme as the only requirement and without the schemas
81
+ nothing refers to any more. Keep its path outside the path of the full UI, which serves its assets below
82
+ its own path.
83
+
84
+ The tenant header stays in this view while personal (user) tokens are enabled (`apiTokens.userTokens`,
85
+ the default): such a token without a company restriction chooses the company like a session does, and
86
+ without the header it is checked against its global roles and refused on company routes. With company
87
+ tokens only (`userTokens: false`) the header is dropped — a company token carries its company.
88
+
89
+ ## 3. Dependency updates
90
+
91
+ Patch-level maintenance, no code changes required:
92
+
93
+ | Package | Old | New | Section |
94
+ | --- | --- | --- | --- |
95
+ | `nodemailer` | 10.0.14 | 10.0.15 | dependencies |
96
+ | `@modelcontextprotocol/sdk` | 1.32.0 | 1.32.1 | dependencies |
97
+ | `oxlint` | 1.86.0 | 1.87.0 | devDependencies |
98
+
99
+ A project that pins `oxlint` itself should raise it to 1.87.0 alongside the framework —
100
+ `pnpm run update` in starter-based projects does this. A project that carries a `nodemailer`
101
+ override matching the framework's version (the starter does) should raise it to `10.0.15`.
102
+
103
+ ## Compatibility Notes
104
+
105
+ - The helper is additive. `DocumentBuilder` + `SwaggerModule.setup()` keep working unchanged.
106
+ - The document is built on the first request, as before.
107
+ - `buildSwaggerDocument()` and `buildApiTokenSwaggerDocument()` are exported for tests: a project can
108
+ assert in its e2e suite that a route documents the scope it enforces.
109
+
110
+ ## References
111
+
112
+ - Helper: `src/core/common/helpers/swagger.helper.ts`
113
+ - Options: `src/core/common/interfaces/swagger-setup-options.interface.ts`
114
+ - Tests: `tests/unit/swagger-helper.spec.ts`
115
+ - [nest-server-starter](https://github.com/lenneTech/nest-server-starter) `src/main.ts`
@@ -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`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "11.42.6",
3
+ "version": "11.42.8",
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",
@@ -92,7 +92,7 @@
92
92
  "@apollo/server": "5.5.1",
93
93
  "@as-integrations/express5": "1.1.2",
94
94
  "@getbrevo/brevo": "6.0.3",
95
- "@modelcontextprotocol/sdk": "1.32.0",
95
+ "@modelcontextprotocol/sdk": "1.32.1",
96
96
  "@nestjs/apollo": "13.4.5",
97
97
  "@nestjs/common": "11.2.7",
98
98
  "@nestjs/core": "11.2.7",
@@ -129,7 +129,7 @@
129
129
  "mongoose": "9.10.4",
130
130
  "multer": "2.4.0",
131
131
  "node-mailjet": "6.0.11",
132
- "nodemailer": "10.0.14",
132
+ "nodemailer": "10.0.15",
133
133
  "passport": "0.7.0",
134
134
  "passport-jwt": "4.0.1",
135
135
  "reflect-metadata": "0.2.2",
@@ -212,7 +212,7 @@
212
212
  "npm-watch": "0.13.0",
213
213
  "otpauth": "9.5.2",
214
214
  "oxfmt": "0.71.0",
215
- "oxlint": "1.86.0",
215
+ "oxlint": "1.87.0",
216
216
  "rimraf": "6.1.3",
217
217
  "smtp-server": "3.19.17",
218
218
  "ts-node": "10.9.2",
@@ -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.2",
224
+ "vite": "8.3.3",
225
225
  "vite-plugin-node": "8.0.0",
226
226
  "vitest": "4.1.11"
227
227
  },