@lenne.tech/nest-server 11.28.0 → 11.28.1

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.
@@ -0,0 +1,155 @@
1
+ # Migration Guide: 11.28.0 → 11.28.1
2
+
3
+ ## Overview
4
+
5
+ | Category | Details |
6
+ |----------|---------|
7
+ | **Breaking Changes** | None |
8
+ | **Bugfixes** | Internal only — the `ejs` import in the BetterAuth email-verification service was normalized to the CommonJS style (`import ejs = require('ejs')`), silencing a static-analysis warning. No runtime behavior change. |
9
+ | **New Features** | None |
10
+ | **Maintenance** | Dependency housekeeping: 17 within-major package updates, 4 previously-undeclared runtime dependencies now declared explicitly, security overrides pruned 9 → 6. `pnpm audit` remains at **0 vulnerabilities**. |
11
+ | **Migration Effort** | **0 minutes for npm-mode consumers** (`pnpm update`). **~2 minutes for vendor-mode consumers** — ensure 4 runtime dependencies are present (see below). |
12
+
13
+ This is a **pure maintenance patch**. There is no API change, no configuration change, and no
14
+ behavioral change. Every one of the framework's 1381 tests passes unchanged.
15
+
16
+ ---
17
+
18
+ ## Quick Migration (npm mode)
19
+
20
+ No code changes required.
21
+
22
+ ```bash
23
+ # Update the package
24
+ pnpm add @lenne.tech/nest-server@11.28.1
25
+
26
+ # Verify
27
+ pnpm run build
28
+ pnpm test
29
+ ```
30
+
31
+ All transitive dependency changes resolve automatically. Nothing in your project needs to change.
32
+
33
+ ---
34
+
35
+ ## What Changed
36
+
37
+ ### 1. Framework dependency updates (all within NestJS 11)
38
+
39
+ The MAJOR version still mirrors NestJS 11 — no NestJS major boundary was crossed. Notable updates:
40
+
41
+ | Package | 11.28.0 | 11.28.1 | Note |
42
+ |---------|---------|---------|------|
43
+ | `@nestjs/common` / `core` / `platform-express` / `websockets` | 11.1.23 | 11.1.28 | NestJS 11 patch |
44
+ | `mongoose` | 9.6.2 | 9.7.4 | Minor (mongodb stays 7.2.0 — coupled) |
45
+ | `nodemailer` | 8.0.8 | 9.0.3 | **Major bump** — internal email transport (see Compatibility Notes) |
46
+ | `multer` | 2.1.1 | 2.2.0 | Security (unhandled multipart DoS) |
47
+ | `graphql-query-complexity` | 1.1.0 | 1.1.1 | Patch |
48
+
49
+ Dev-only tooling was also refreshed (`vitest`/`@vitest/*` 4.1.7 → 4.1.10, `vite` 8.0.14 → 8.1.4,
50
+ `oxlint` 1.66.0 → 1.74.0, `@swc/core` 1.15.40 → 1.15.43, `tsx` 4.22.3 → 4.23.1, plus `@types/*`).
51
+ Dev-tooling changes have **zero** effect on consuming projects.
52
+
53
+ ### 2. Newly declared runtime dependencies (relevant for vendor mode)
54
+
55
+ Four packages that the framework's shipped code **imports directly** were previously only resolved
56
+ **transitively** (phantom dependencies), relying on pnpm hoisting. They are now declared explicitly
57
+ and pinned to the exact versions that were already resolving — **this is a declaration change, not a
58
+ version bump, so nothing new is installed for npm-mode consumers.**
59
+
60
+ | Package | Version | Imported by | Reached transitively before via |
61
+ |---------|---------|-------------|----------------------------------|
62
+ | `cron` | 4.4.0 | `src/core/common/services/core-cron-jobs.service.ts` (`new CronJob`) | `@nestjs/schedule` |
63
+ | `jose` | 6.2.1 | `src/core/modules/better-auth/core-better-auth.service.ts` (`importJWK`/`jwtVerify`) | `better-auth`, `@modelcontextprotocol/sdk` |
64
+ | `ws` | 8.21.0 | `src/test/test.helper.ts` (`require('ws')`) | `@nestjs/graphql`, `@nestjs/apollo` |
65
+ | `graphql-ws` | 6.0.8 | `src/test/test.helper.ts` (`createClient`) | `@nestjs/graphql`, `@nestjs/apollo` |
66
+
67
+ Why this matters: relying on a transitive package means its presence and **version** are controlled
68
+ by someone else's dependency tree. `ws` already resolved to two versions in the tree (`8.21.0` and
69
+ a nested `7.5.11`); an explicit declaration removes the hoisting lottery.
70
+
71
+ ### 3. Security override cleanup (9 → 6)
72
+
73
+ Three overrides in `pnpm-workspace.yaml` became genuine no-ops after the direct-dependency updates
74
+ above and were removed (verified with `pnpm audit`, which stays at 0 vulnerabilities):
75
+
76
+ | Removed override | Now resolved by |
77
+ |------------------|-----------------|
78
+ | `nodemailer@<9.0.1` | direct dependency is now `nodemailer@9.0.3` (the old override was silently patching a vulnerable `8.0.8` direct pin) |
79
+ | `multer@<2.2.0` | `@nestjs/platform-express@11.1.28` now pins `multer@2.2.0` exactly |
80
+ | `vite@>=8.0.0 <8.0.16` | all `vite` now resolves to `8.1.4` |
81
+
82
+ Six overrides remain, each proven still load-bearing (removing them reintroduces a vulnerability):
83
+ `ajv`, `picomatch`, `ws`, `uuid`, `@babel/core`, `js-yaml`. Each carries its CVE/GHSA rationale as
84
+ an inline comment.
85
+
86
+ ---
87
+
88
+ ## Compatibility Notes
89
+
90
+ - **npm-mode consumers:** Nothing to do. `pnpm update @lenne.tech/nest-server` is sufficient.
91
+ - **`nodemailer` 8 → 9 (internal):** `nodemailer` is used internally by the framework's
92
+ `EmailService`/SMTP transport. Projects configure it declaratively through
93
+ `email.smtp` in `config.env.ts`, and those options are unchanged across the 8 → 9 boundary — all
94
+ email tests pass unmodified. If (and only if) your project constructs a **custom `nodemailer`
95
+ transport object directly** and passes it in, review the
96
+ [nodemailer 9 release notes](https://github.com/nodemailer/nodemailer/releases) for the transport
97
+ API. The declarative `email.smtp` path needs no changes.
98
+ - **Projects without BetterAuth / cron / GraphQL subscriptions:** Unaffected — the newly declared
99
+ packages were already in your tree transitively.
100
+
101
+ ### Vendor-mode consumers (`src/core/` copied into your project)
102
+
103
+ Vendor-mode projects do **not** install `@lenne.tech/nest-server` as an npm dependency, so they do
104
+ not inherit its `dependencies`. After syncing this release into your vendored `src/core/`, make sure
105
+ these four runtime packages exist in **your** `package.json` (pinned, per the fixed-version rule):
106
+
107
+ ```jsonc
108
+ {
109
+ "dependencies": {
110
+ "cron": "4.4.0", // required — imported by core-cron-jobs.service.ts
111
+ "jose": "6.2.1" // required — imported by core-better-auth.service.ts
112
+ // ws / graphql-ws: required only if you use the exported TestHelper (src/test/test.helper.ts)
113
+ // in your own tests — most projects do:
114
+ // "graphql-ws": "6.0.8",
115
+ // "ws": "8.21.0"
116
+ }
117
+ }
118
+ ```
119
+
120
+ In practice these are almost always already present transitively (via `@nestjs/schedule`,
121
+ `better-auth`, `@nestjs/graphql`). Declaring them explicitly protects you from a future transitive
122
+ change silently removing them. The `lt-dev:nest-server-core-updater` agent surfaces this during a
123
+ core sync.
124
+
125
+ ---
126
+
127
+ ## Troubleshooting
128
+
129
+ ### `Cannot find module 'jose'` / `'cron'` after a vendor-mode sync
130
+
131
+ You copied the updated `src/core/` but did not add the runtime dependency. Add the package to your
132
+ project's `package.json` (see the vendor-mode block above) and run `pnpm install`.
133
+
134
+ ### `pnpm audit` reports a vulnerability I thought an override covered
135
+
136
+ The `nodemailer`, `multer`, and `vite` overrides were removed because the direct/transitive
137
+ resolutions now land on fixed versions on their own. If your project maintains its **own**
138
+ `pnpm-workspace.yaml` overrides (vendor mode or a monorepo root), re-verify with a with/without
139
+ lockfile diff — do not blindly copy this repo's removals; your tree may still resolve a vulnerable
140
+ version back into range.
141
+
142
+ ### Build tool (`nest build`) fails with a permission error after `pnpm install`
143
+
144
+ Unrelated to your code — a known pnpm 11 hoisted-linker store-dedup artifact can drop the executable
145
+ bit on `node_modules/.bin/nest`. This release deliberately keeps `@nestjs/cli` at `11.0.21` to avoid
146
+ re-linking it. If you still hit it, `chmod +x node_modules/@nestjs/cli/bin/nest.js` restores it and
147
+ survives subsequent installs.
148
+
149
+ ---
150
+
151
+ ## References
152
+
153
+ - [Package Management Rules](../.claude/rules/package-management.md) — fixed-version policy, override target rules
154
+ - [Migration Guide 11.27.7 → 11.28.0](./11.27.7-to-11.28.0.md) — previous release (the 401/403 policy + S_SELF/S_CREATOR ownership fixes)
155
+ - [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "11.28.0",
3
+ "version": "11.28.1",
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",
@@ -84,41 +84,44 @@
84
84
  "@getbrevo/brevo": "3.0.1",
85
85
  "@modelcontextprotocol/sdk": "1.29.0",
86
86
  "@nestjs/apollo": "13.4.2",
87
- "@nestjs/common": "11.1.23",
88
- "@nestjs/core": "11.1.23",
87
+ "@nestjs/common": "11.1.28",
88
+ "@nestjs/core": "11.1.28",
89
89
  "@nestjs/graphql": "13.4.2",
90
90
  "@nestjs/jwt": "11.0.2",
91
91
  "@nestjs/mongoose": "11.0.4",
92
92
  "@nestjs/passport": "11.0.5",
93
- "@nestjs/platform-express": "11.1.23",
93
+ "@nestjs/platform-express": "11.1.28",
94
94
  "@nestjs/schedule": "6.1.3",
95
95
  "@nestjs/swagger": "11.4.2",
96
96
  "@nestjs/terminus": "11.1.1",
97
- "@nestjs/websockets": "11.1.23",
97
+ "@nestjs/websockets": "11.1.28",
98
98
  "@tus/file-store": "2.1.0",
99
99
  "@tus/server": "2.4.1",
100
- "@types/supertest": "7.2.0",
100
+ "@types/supertest": "7.2.1",
101
101
  "bcrypt": "6.0.0",
102
102
  "better-auth": "1.6.23",
103
103
  "class-transformer": "0.5.1",
104
104
  "class-validator": "0.15.1",
105
105
  "compression": "1.8.1",
106
106
  "cookie-parser": "1.4.7",
107
+ "cron": "4.4.0",
107
108
  "dotenv": "17.4.2",
108
109
  "ejs": "5.0.2",
109
110
  "express": "5.2.1",
110
111
  "graphql": "16.14.0",
111
- "graphql-query-complexity": "1.1.0",
112
+ "graphql-query-complexity": "1.1.1",
112
113
  "graphql-subscriptions": "3.0.0",
113
114
  "graphql-upload": "15.0.2",
115
+ "graphql-ws": "6.0.8",
116
+ "jose": "6.2.1",
114
117
  "js-sha256": "0.11.1",
115
118
  "json-to-graphql-query": "2.3.0",
116
119
  "lodash": "4.18.1",
117
120
  "mongodb": "7.2.0",
118
- "mongoose": "9.6.2",
119
- "multer": "2.1.1",
121
+ "mongoose": "9.7.4",
122
+ "multer": "2.2.0",
120
123
  "node-mailjet": "6.0.11",
121
- "nodemailer": "8.0.8",
124
+ "nodemailer": "9.0.3",
122
125
  "passport": "0.7.0",
123
126
  "passport-jwt": "4.0.1",
124
127
  "reflect-metadata": "0.2.2",
@@ -126,26 +129,27 @@
126
129
  "rxjs": "7.8.2",
127
130
  "supertest": "7.2.2",
128
131
  "ts-morph": "27.0.2",
132
+ "ws": "8.21.0",
129
133
  "yuml-diagram": "1.2.0"
130
134
  },
131
135
  "devDependencies": {
132
136
  "@compodoc/compodoc": "1.2.1",
133
137
  "@nestjs/cli": "11.0.21",
134
138
  "@nestjs/schematics": "11.1.0",
135
- "@nestjs/testing": "11.1.23",
139
+ "@nestjs/testing": "11.1.28",
136
140
  "@swc/cli": "0.8.1",
137
- "@swc/core": "1.15.40",
141
+ "@swc/core": "1.15.43",
138
142
  "@types/compression": "1.8.1",
139
143
  "@types/cookie-parser": "1.4.10",
140
144
  "@types/ejs": "3.1.5",
141
145
  "@types/express": "5.0.6",
142
146
  "@types/lodash": "4.17.24",
143
- "@types/multer": "2.1.0",
147
+ "@types/multer": "2.2.0",
144
148
  "@types/node": "25.9.1",
145
- "@types/nodemailer": "8.0.0",
149
+ "@types/nodemailer": "8.0.1",
146
150
  "@types/passport": "1.0.17",
147
- "@vitest/coverage-v8": "4.1.7",
148
- "@vitest/ui": "4.1.7",
151
+ "@vitest/coverage-v8": "4.1.10",
152
+ "@vitest/ui": "4.1.10",
149
153
  "ansi-colors": "4.1.3",
150
154
  "find-file-up": "2.0.1",
151
155
  "husky": "9.1.7",
@@ -153,17 +157,17 @@
153
157
  "npm-watch": "0.13.0",
154
158
  "otpauth": "9.5.1",
155
159
  "oxfmt": "0.51.0",
156
- "oxlint": "1.66.0",
160
+ "oxlint": "1.74.0",
157
161
  "rimraf": "6.1.3",
158
162
  "ts-node": "10.9.2",
159
163
  "tsconfig-paths": "4.2.0",
160
- "tsx": "4.22.3",
164
+ "tsx": "4.23.1",
161
165
  "tus-js-client": "4.3.1",
162
166
  "typescript": "5.9.3",
163
167
  "unplugin-swc": "1.5.9",
164
- "vite": "8.0.14",
168
+ "vite": "8.1.4",
165
169
  "vite-plugin-node": "8.0.0",
166
- "vitest": "4.1.7"
170
+ "vitest": "4.1.10"
167
171
  },
168
172
  "main": "dist/index.js",
169
173
  "types": "dist/index.d.ts",
@@ -1,5 +1,5 @@
1
1
  import { Inject, Injectable, Logger, Optional } from '@nestjs/common';
2
- import * as ejs from 'ejs';
2
+ import ejs = require('ejs');
3
3
  import * as fs from 'fs';
4
4
  import * as path from 'path';
5
5