@lenne.tech/nest-server 11.29.0 → 11.30.0
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/package-management.md +57 -2
- package/FRAMEWORK-API.md +157 -157
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/migration-guides/11.29.0-to-11.29.1.md +311 -0
- package/migration-guides/11.29.x-to-11.30.x.md +98 -0
- package/package.json +14 -14
- package/src/core/modules/ai/README.md +1 -3
- package/src/core/modules/better-auth/README.md +8 -7
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# Migration Guide: 11.29.0 → 11.29.1
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
| Category | Details |
|
|
6
|
+
|----------|---------|
|
|
7
|
+
| **Breaking Changes** | None |
|
|
8
|
+
| **Bugfixes** | None — no runtime code changed. `src/core/` is byte-identical to 11.29.0. |
|
|
9
|
+
| **New Features** | None |
|
|
10
|
+
| **Maintenance** | **Toolchain only.** `package.json#packageManager` is restored as the *single* place the pnpm version is pinned. `corepack` is gone from the `Dockerfile` (Node >= 25 no longer ships it); every pnpm-running build stage now provisions the pinned pnpm itself. `pnpm/action-setup` reads the pin instead of carrying its own `version` input. A contract test (`tests/unit/pnpm-pin-contract.spec.ts`) guards the whole chain. |
|
|
11
|
+
| **Migration Effort** | **0 minutes for npm-mode and vendor-mode consumers** — nothing in your project changes. **~10 minutes if you adopt the pattern**, which you should do *before* moving any build to Node >= 25. |
|
|
12
|
+
|
|
13
|
+
This release changes **how the framework repo builds itself**. It ships no API change, no
|
|
14
|
+
configuration change, and no behavioral change. Update with `pnpm add @lenne.tech/nest-server@11.29.1`
|
|
15
|
+
and you are done.
|
|
16
|
+
|
|
17
|
+
The reason to read further: **the `Dockerfile` is not part of the npm package** (it is not in
|
|
18
|
+
`package.json#files`). Your project's own `Dockerfile` and CI came from the starter template, so you
|
|
19
|
+
do **not** inherit this fix automatically. If they still run `corepack enable`, they will break the
|
|
20
|
+
day you move to Node >= 25 — see [Adopting the pattern](#adopting-the-pattern-in-your-project-recommended).
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quick Migration (npm mode)
|
|
25
|
+
|
|
26
|
+
No code changes required.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Update the package
|
|
30
|
+
pnpm add @lenne.tech/nest-server@11.29.1
|
|
31
|
+
|
|
32
|
+
# Verify
|
|
33
|
+
pnpm run build
|
|
34
|
+
pnpm test
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Why this release exists: corepack is going away
|
|
40
|
+
|
|
41
|
+
`corepack` was the mechanism that read `package.json#packageManager` and materialized the right
|
|
42
|
+
package-manager binary. It shipped with Node for years, which is why the framework's `Dockerfile`
|
|
43
|
+
could simply say `corepack enable` and trust that pnpm appeared.
|
|
44
|
+
|
|
45
|
+
**Node >= 25 no longer ships corepack.** A build stage that runs `corepack enable` on such an image
|
|
46
|
+
fails outright:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
/bin/sh: corepack: not found
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
So the framework needed a way to provision an exact pnpm version that does not depend on corepack
|
|
53
|
+
existing — without giving up the single-source-of-truth pin.
|
|
54
|
+
|
|
55
|
+
### What 11.29.0 did, and why it is reverted here
|
|
56
|
+
|
|
57
|
+
11.29.0 removed the `packageManager` field and introduced `engines.pnpm: "^11.0.0"`. That left the
|
|
58
|
+
repo with **no exact pin at all**, so the version had to be restated wherever pnpm was needed — the
|
|
59
|
+
workflows grew a hardcoded `with: version: 11`, and Docker's `corepack enable` (with no
|
|
60
|
+
`packageManager` field to follow) would resolve to whatever it considered current.
|
|
61
|
+
|
|
62
|
+
Two sources of truth, neither exact. 11.29.1 collapses them back into one:
|
|
63
|
+
|
|
64
|
+
| | 11.29.0 | 11.29.1 |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `package.json#packageManager` | *(removed)* | `pnpm@11.13.1+sha512.…` — **the** pin |
|
|
67
|
+
| `package.json#engines.pnpm` | `^11.0.0` | `^11.0.0` — unchanged, a soft major gate |
|
|
68
|
+
| `.github/workflows/*` | `with: version: 11` | *(no `version` input — reads the pin)* |
|
|
69
|
+
| `Dockerfile` | `corepack enable` | derive-line (below) |
|
|
70
|
+
|
|
71
|
+
`engines.pnpm` stays, but understand what it is: a **soft major-range guard**, not a pin. It warns a
|
|
72
|
+
pnpm 10 user; it does not tell CI which version to install. Only `packageManager` does that.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## What Changed
|
|
77
|
+
|
|
78
|
+
### 1. `packageManager` is back — exact, with an integrity hash
|
|
79
|
+
|
|
80
|
+
```jsonc
|
|
81
|
+
// package.json
|
|
82
|
+
{
|
|
83
|
+
"packageManager": "pnpm@11.13.1+sha512.b2fc7683b8a6525414e7d13e1ba28caaddde96bf66ec540bfaeb7e702b81f3e0be4d1f295edf7f9fe0396740a8dce4509c582ddf79891f4543fea32d37645f25",
|
|
84
|
+
"engines": {
|
|
85
|
+
"node": ">= 22",
|
|
86
|
+
"pnpm": "^11.0.0"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**This field has no effect on your project.** `packageManager` is only ever read from the *root*
|
|
92
|
+
`package.json` of the project being built — never from a dependency's. You inherit nothing from the
|
|
93
|
+
framework's pin.
|
|
94
|
+
|
|
95
|
+
Note that pnpm itself honours the field, with no corepack involved: run any `pnpm` command in a
|
|
96
|
+
directory whose `package.json` pins a different pnpm, and pnpm switches to it
|
|
97
|
+
(`managePackageManagerVersions`, on by default since pnpm 10). Corepack was never the only thing
|
|
98
|
+
reading this field — which is exactly why dropping it costs nothing.
|
|
99
|
+
|
|
100
|
+
### 2. The Dockerfile provisions pnpm without corepack
|
|
101
|
+
|
|
102
|
+
Every stage that runs `pnpm` now provisions the pinned version itself, from the pin:
|
|
103
|
+
|
|
104
|
+
```dockerfile
|
|
105
|
+
# Provision the exact pnpm declared in package.json (single source of truth).
|
|
106
|
+
# No corepack: Node >= 25 no longer ships it. The +sha512 suffix is stripped;
|
|
107
|
+
# npm enforces registry integrity for the tarball itself.
|
|
108
|
+
RUN npm install -g "$(node -p "require('./package.json').packageManager.split('+')[0]")"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The `.split('+')[0]` turns `pnpm@11.13.1+sha512.b2fc…` into `pnpm@11.13.1`, because `npm install -g`
|
|
112
|
+
takes a plain spec. The dropped hash is not a loss of integrity: npm verifies the tarball against the
|
|
113
|
+
registry's own integrity metadata on install.
|
|
114
|
+
|
|
115
|
+
The line appears **once per pnpm-running stage** (`deps` and `builder`) — Docker stages do not inherit
|
|
116
|
+
each other's globally installed binaries, only what is explicitly `COPY --from=`'d.
|
|
117
|
+
|
|
118
|
+
### 3. `pnpm/action-setup` no longer carries a `version` input
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
- name: Install pnpm
|
|
122
|
+
# No version input: the exact version is read from package.json's packageManager field.
|
|
123
|
+
uses: pnpm/action-setup@v6
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The action reads `packageManager` on its own. Specifying **both** is not redundant-but-harmless — the
|
|
127
|
+
action treats a mismatch as a hard error, so the two sources cannot silently drift.
|
|
128
|
+
|
|
129
|
+
### 4. A contract test guards the chain
|
|
130
|
+
|
|
131
|
+
`tests/unit/pnpm-pin-contract.spec.ts` (11 assertions, unit suite, no MongoDB) fails the build if
|
|
132
|
+
anyone re-introduces the drift this release removes:
|
|
133
|
+
|
|
134
|
+
- the pin is exact (`x.y.z` + `sha512` hash — never a range),
|
|
135
|
+
- `engines.pnpm` tracks the pin's major,
|
|
136
|
+
- `devEngines.packageManager` never (re)appears — npm/npx abort with `EBADDEVENGINES` on it,
|
|
137
|
+
- the `Dockerfile` contains no `corepack` in any `RUN`,
|
|
138
|
+
- **every** pnpm-running stage runs the derive-line *before* its first `pnpm` command, and only after
|
|
139
|
+
a `COPY` has put `package.json` in place,
|
|
140
|
+
- no workflow passes a `version:` to `pnpm/action-setup` or hardcodes `npm install -g pnpm@…`.
|
|
141
|
+
|
|
142
|
+
A twelfth test proves the chain end-to-end — it derives the spec exactly as the Dockerfile does,
|
|
143
|
+
installs it into a throwaway prefix, and asserts the provisioned binary reports the pinned version.
|
|
144
|
+
It needs network and ~10 MB, so it is gated to `CI` / `PIN_PROVISION_TEST=1` and stays out of your way
|
|
145
|
+
locally.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Breaking Changes
|
|
150
|
+
|
|
151
|
+
**None.** No public API, config key, decorator, or exported symbol changed.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Adopting the pattern in your project (recommended)
|
|
156
|
+
|
|
157
|
+
Do this **before** you move any build to Node >= 25 — not after it breaks. If your project was
|
|
158
|
+
generated from a recent `nest-server-starter` / `lt fullstack init`, check whether it is already done.
|
|
159
|
+
|
|
160
|
+
### Step 1: Pin pnpm in your root `package.json`
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Writes packageManager with the integrity hash for the version you actually use
|
|
164
|
+
pnpm self-update
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Or set it by hand — the exact form matters (`pnpm@x.y.z+sha512.<hash>`):
|
|
168
|
+
|
|
169
|
+
```jsonc
|
|
170
|
+
{
|
|
171
|
+
"packageManager": "pnpm@11.13.1+sha512.b2fc7683…",
|
|
172
|
+
"engines": { "node": ">= 22", "pnpm": "^11.0.0" }
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
> **Monorepo:** this belongs in the **workspace root** `package.json`, not only in `projects/api/`.
|
|
177
|
+
> The Dockerfile's derive-line reads `/app/package.json`, which in monorepo mode
|
|
178
|
+
> (`--build-arg API_DIR=projects/api`) is the root manifest. See
|
|
179
|
+
> [Troubleshooting](#docker-build-fails-with-typeerror-cannot-read-properties-of-undefined-reading-split).
|
|
180
|
+
|
|
181
|
+
### Step 2: Replace corepack in your Dockerfile
|
|
182
|
+
|
|
183
|
+
**Before:**
|
|
184
|
+
```dockerfile
|
|
185
|
+
RUN apk add --no-cache python3 make g++ && corepack enable
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**After:**
|
|
189
|
+
```dockerfile
|
|
190
|
+
RUN apk add --no-cache python3 make g++
|
|
191
|
+
|
|
192
|
+
# … COPY the manifests first — the derive-line reads package.json …
|
|
193
|
+
|
|
194
|
+
# Provision the exact pnpm declared in package.json (single source of truth).
|
|
195
|
+
# No corepack: Node >= 25 no longer ships it. The +sha512 suffix is stripped;
|
|
196
|
+
# npm enforces registry integrity for the tarball itself.
|
|
197
|
+
RUN npm install -g "$(node -p "require('./package.json').packageManager.split('+')[0]")"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Two ordering rules, both easy to get wrong:
|
|
201
|
+
|
|
202
|
+
1. The derive-line must come **after** the `COPY` that puts `package.json` into the WORKDIR — it
|
|
203
|
+
reads that file.
|
|
204
|
+
2. It must be repeated in **each** stage that runs `pnpm`. A global install in `deps` does not reach
|
|
205
|
+
`builder`.
|
|
206
|
+
|
|
207
|
+
### Step 3: Drop the hardcoded version in CI
|
|
208
|
+
|
|
209
|
+
**GitHub Actions** — remove the `version` input:
|
|
210
|
+
|
|
211
|
+
```yaml
|
|
212
|
+
- name: Install pnpm
|
|
213
|
+
uses: pnpm/action-setup@v6 # reads packageManager; no `with: version:`
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**GitLab CI** (or any runner without the action) — use the same derive-line:
|
|
217
|
+
|
|
218
|
+
```yaml
|
|
219
|
+
before_script:
|
|
220
|
+
# Provision the exact pnpm pinned in package.json (single source of truth).
|
|
221
|
+
- npm install -g "$(node -p "require('./package.json').packageManager.split('+')[0]")"
|
|
222
|
+
- pnpm install --frozen-lockfile
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Step 4 (optional): Guard it with a test
|
|
226
|
+
|
|
227
|
+
Copy `tests/unit/pnpm-pin-contract.spec.ts` from this repo and trim it to the files your project has.
|
|
228
|
+
The value is not the assertions — it is that the next person who "helpfully" re-adds
|
|
229
|
+
`with: version: 11` or a second `npm install -g pnpm@…` gets a red build instead of a silent drift
|
|
230
|
+
that surfaces months later as an unreproducible container.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Compatibility Notes
|
|
235
|
+
|
|
236
|
+
| Pattern | Status |
|
|
237
|
+
|---------|--------|
|
|
238
|
+
| Any application code, decorator, service, or config using the framework | ✅ Unaffected — no runtime code changed |
|
|
239
|
+
| **npm-mode** consumers (`@lenne.tech/nest-server` as a dependency) | ✅ Unaffected — `pnpm add …@11.29.1` and done |
|
|
240
|
+
| **Vendor-mode** consumers (`src/core/` copied in) | ✅ Unaffected — `src/core/` is byte-identical to 11.29.0; a sync produces no delta |
|
|
241
|
+
| The framework's `packageManager` pin leaking into your project | ✅ Impossible — the field is read only from the root manifest, never from a dependency |
|
|
242
|
+
| Your project's `Dockerfile` still using `corepack enable` | ⚠️ Works on Node <= 24, **breaks on Node >= 25** — apply Step 2 |
|
|
243
|
+
| Your CI passing both `with: version:` **and** having a `packageManager` field | ⚠️ Hard error on version mismatch — apply Step 3 |
|
|
244
|
+
| Node version | ✅ Unchanged (`engines.node: ">= 22"`); the framework's own images stay on Node 24 LTS |
|
|
245
|
+
| pnpm 10 or older as your project's package manager | ⚠️ `engines.pnpm: "^11.0.0"` warns (`EBADENGINE`); a hard failure only with `engine-strict=true` |
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Troubleshooting
|
|
250
|
+
|
|
251
|
+
### `corepack: not found` in a Docker build or CI job
|
|
252
|
+
|
|
253
|
+
You moved to a Node >= 25 image while your build still calls `corepack enable`. This is exactly the
|
|
254
|
+
failure this release prevents — apply [Step 2](#step-2-replace-corepack-in-your-dockerfile). Do not
|
|
255
|
+
"fix" it with `npm install -g corepack`: that reintroduces the indirection the derive-line removes.
|
|
256
|
+
|
|
257
|
+
### Docker build fails with `TypeError: Cannot read properties of undefined (reading 'split')`
|
|
258
|
+
|
|
259
|
+
The derive-line found a `package.json` **without** a `packageManager` field. Almost always a
|
|
260
|
+
monorepo: in monorepo mode the build context is the workspace root, so `/app/package.json` is the
|
|
261
|
+
**root** manifest — and the pin was only added to `projects/api/package.json`.
|
|
262
|
+
|
|
263
|
+
Fix: add `packageManager` to the workspace **root** manifest (Step 1). Keeping the root and the API
|
|
264
|
+
package on the same pin is the point — one pnpm builds the whole workspace.
|
|
265
|
+
|
|
266
|
+
### `ERR_PNPM_BAD_PM_VERSION`, or the action reports multiple pnpm versions
|
|
267
|
+
|
|
268
|
+
Two sources disagree about the version. Either your workflow still passes `with: version:` alongside
|
|
269
|
+
a `packageManager` field (remove the input — [Step 3](#step-3-drop-the-hardcoded-version-in-ci)), or a
|
|
270
|
+
stray `npm install -g pnpm@<other>` runs before the derive-line.
|
|
271
|
+
|
|
272
|
+
### `EBADENGINE` / `ERR_PNPM_UNSUPPORTED_ENGINE` warning mentioning pnpm
|
|
273
|
+
|
|
274
|
+
Unchanged from 11.29.0 — `engines.pnpm: "^11.0.0"` warns when installing with pnpm 10 or older.
|
|
275
|
+
Upgrade with `npm i -g pnpm@11`, or pin your project via `packageManager` and let pnpm switch itself.
|
|
276
|
+
The framework's *runtime* does not depend on pnpm; this concerns the install step only.
|
|
277
|
+
|
|
278
|
+
### `EBADDEVENGINES` from npm or npx
|
|
279
|
+
|
|
280
|
+
Something added a `devEngines.packageManager` block. npm and npx abort on it, and corepack rejects
|
|
281
|
+
ranges inside it. Use `packageManager` (exact pin) plus `engines.pnpm` (soft range) instead — the
|
|
282
|
+
contract test asserts `devEngines.packageManager` stays absent.
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Affected Files
|
|
287
|
+
|
|
288
|
+
No core module changed in this release, so there is no module documentation to revisit. For
|
|
289
|
+
completeness, the full change surface:
|
|
290
|
+
|
|
291
|
+
| File | Change |
|
|
292
|
+
|------|--------|
|
|
293
|
+
| `package.json` | `packageManager` restored (exact pin + `sha512`); version → 11.29.1 |
|
|
294
|
+
| `Dockerfile` | `corepack enable` removed; derive-line added to the `deps` and `builder` stages |
|
|
295
|
+
| `.github/workflows/build.yml`, `publish.yml` | `with: version: 11` removed from `pnpm/action-setup` |
|
|
296
|
+
| `tests/unit/pnpm-pin-contract.spec.ts` | **New** — 11 structural assertions + 1 CI-gated provisioning proof |
|
|
297
|
+
| `spectaql.yml`, `FRAMEWORK-API.md` | Version bump only (kept in sync per the release process) |
|
|
298
|
+
| `.claude/rules/package-management.md` | Documents the corepack-free pin contract |
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## References
|
|
303
|
+
|
|
304
|
+
- [Package Management Rules — fixed versions, overrides, the pnpm pin contract](../.claude/rules/package-management.md)
|
|
305
|
+
- [Versioning Strategy — release process, `package.json` / `spectaql.yml` version sync](../.claude/rules/versioning.md)
|
|
306
|
+
- Contract test: `tests/unit/pnpm-pin-contract.spec.ts`
|
|
307
|
+
- [Migration Guide 11.28.1 → 11.29.0](./11.28.1-to-11.29.0.md) — previous release (introduced the `engines.pnpm` gate this guide keeps)
|
|
308
|
+
- [Migration Guide 11.27.6 → 11.27.7](./11.27.6-to-11.27.7.md) — the pnpm 11 move, when corepack was still the mechanism
|
|
309
|
+
- [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation)
|
|
310
|
+
</content>
|
|
311
|
+
</invoke>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Migration Guide: 11.29.x → 11.30.x
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
| Category | Details |
|
|
6
|
+
|----------|---------|
|
|
7
|
+
| **Breaking Changes** | None in nest-server's own API. Two transitive changes may affect projects: `@nestjs/websockets` removed from dependencies; `@nestjs/swagger` 11.4.6 blocks deep imports |
|
|
8
|
+
| **New Features** | None (dependency maintenance release) |
|
|
9
|
+
| **Bugfixes** | Dependency updates incl. security-relevant `ws` 8.21.1 override; 6 obsolete pnpm overrides removed |
|
|
10
|
+
| **Migration Effort** | Very Low (~5 minutes) — most projects need no changes |
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Quick Migration
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Update package
|
|
18
|
+
npm install @lenne.tech/nest-server@11.30.x
|
|
19
|
+
|
|
20
|
+
# Verify build
|
|
21
|
+
npm run build
|
|
22
|
+
|
|
23
|
+
# Run tests
|
|
24
|
+
npm test
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Most projects need no code changes. Read the two notes below only if your
|
|
28
|
+
project uses `@WebSocketGateway` or deep-imports from `@nestjs/swagger`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## What Changed in 11.30.x
|
|
33
|
+
|
|
34
|
+
Dependency maintenance across the board (all checks green, 2157 tests, 0 audit
|
|
35
|
+
findings):
|
|
36
|
+
|
|
37
|
+
- **dependencies:** `@getbrevo/brevo` 3.0.4, `@nestjs/swagger` 11.4.6,
|
|
38
|
+
`jose` 6.2.3, `ws` 8.21.1, `graphql-ws` 6.1.0, `ejs` 6.0.1,
|
|
39
|
+
`ts-morph` 28.0.0
|
|
40
|
+
- **removed:** `@nestjs/websockets` (unused by the framework itself — see below)
|
|
41
|
+
- **devDependencies:** `@nestjs/cli` 11.0.24, `vite` 8.1.5, `oxfmt` 0.59.0,
|
|
42
|
+
`@compodoc/compodoc` 2.0.0, `@types/node` 26.1.1
|
|
43
|
+
- **pnpm overrides:** 6 obsolete entries removed (`ajv`, `picomatch`,
|
|
44
|
+
`js-yaml`, `uuid`, `@babel/core`, `websocket-driver` — all resolved
|
|
45
|
+
upstream); the `ws` override stays (load-bearing against
|
|
46
|
+
GHSA-96hv-2xvq-fx4p)
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Notes for Consuming Projects
|
|
51
|
+
|
|
52
|
+
### 1. `@nestjs/websockets` is no longer a nest-server dependency
|
|
53
|
+
|
|
54
|
+
The framework itself never used it. If your project uses `@WebSocketGateway`
|
|
55
|
+
(or anything else from `@nestjs/websockets`) it previously worked only as a
|
|
56
|
+
phantom dependency — add it explicitly now:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install @nestjs/websockets@^11.1.28
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
GraphQL subscriptions are NOT affected (`@nestjs/graphql` uses
|
|
63
|
+
`graphql-ws`/`ws` directly).
|
|
64
|
+
|
|
65
|
+
### 2. `@nestjs/swagger` 11.4.6 ships an `exports` map — deep imports fail at runtime
|
|
66
|
+
|
|
67
|
+
**Before:**
|
|
68
|
+
```typescript
|
|
69
|
+
import { DECORATORS } from '@nestjs/swagger/dist/constants';
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**After:**
|
|
73
|
+
```typescript
|
|
74
|
+
import { DECORATORS } from '@nestjs/swagger';
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Deep imports like `@nestjs/swagger/dist/*` now throw
|
|
78
|
+
`ERR_PACKAGE_PATH_NOT_EXPORTED` at runtime (type-only imports still compile).
|
|
79
|
+
Everything you need is available from the root export.
|
|
80
|
+
|
|
81
|
+
### 3. `ejs` 5 → 6 (framework-internal)
|
|
82
|
+
|
|
83
|
+
The framework's own template rendering (`ejs.compile`) is unchanged and fully
|
|
84
|
+
tested. Only if your project passes removed legacy ejs options to its own
|
|
85
|
+
templates would you be affected — unlikely; check the ejs 6 changelog if you
|
|
86
|
+
use custom ejs options.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Detailed Migration Steps
|
|
91
|
+
|
|
92
|
+
1. Update the package (`npm install @lenne.tech/nest-server@11.30.x` or
|
|
93
|
+
`pnpm run update` in starter-based projects).
|
|
94
|
+
2. Search your project for `@nestjs/swagger/dist` deep imports and replace
|
|
95
|
+
them with root imports.
|
|
96
|
+
3. If you use `@WebSocketGateway`: add `@nestjs/websockets` to your own
|
|
97
|
+
dependencies.
|
|
98
|
+
4. `npm run build` + `npm test` — both should pass without further changes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.30.0",
|
|
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",
|
|
@@ -79,11 +79,12 @@
|
|
|
79
79
|
"node": ">= 22",
|
|
80
80
|
"pnpm": "^11.0.0"
|
|
81
81
|
},
|
|
82
|
+
"packageManager": "pnpm@11.13.1+sha512.b2fc7683b8a6525414e7d13e1ba28caaddde96bf66ec540bfaeb7e702b81f3e0be4d1f295edf7f9fe0396740a8dce4509c582ddf79891f4543fea32d37645f25",
|
|
82
83
|
"dependencies": {
|
|
83
84
|
"@apollo/server": "5.5.1",
|
|
84
85
|
"@as-integrations/express5": "1.1.2",
|
|
85
86
|
"@better-auth/passkey": "1.6.23",
|
|
86
|
-
"@getbrevo/brevo": "3.0.
|
|
87
|
+
"@getbrevo/brevo": "3.0.4",
|
|
87
88
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
88
89
|
"@nestjs/apollo": "13.4.2",
|
|
89
90
|
"@nestjs/common": "11.1.28",
|
|
@@ -94,9 +95,8 @@
|
|
|
94
95
|
"@nestjs/passport": "11.0.5",
|
|
95
96
|
"@nestjs/platform-express": "11.1.28",
|
|
96
97
|
"@nestjs/schedule": "6.1.3",
|
|
97
|
-
"@nestjs/swagger": "11.4.
|
|
98
|
+
"@nestjs/swagger": "11.4.6",
|
|
98
99
|
"@nestjs/terminus": "11.1.1",
|
|
99
|
-
"@nestjs/websockets": "11.1.28",
|
|
100
100
|
"@tus/file-store": "2.1.0",
|
|
101
101
|
"@tus/server": "2.4.1",
|
|
102
102
|
"@types/supertest": "7.2.1",
|
|
@@ -108,14 +108,14 @@
|
|
|
108
108
|
"cookie-parser": "1.4.7",
|
|
109
109
|
"cron": "4.4.0",
|
|
110
110
|
"dotenv": "17.4.2",
|
|
111
|
-
"ejs": "
|
|
111
|
+
"ejs": "6.0.1",
|
|
112
112
|
"express": "5.2.1",
|
|
113
113
|
"graphql": "16.14.0",
|
|
114
114
|
"graphql-query-complexity": "1.1.1",
|
|
115
115
|
"graphql-subscriptions": "3.0.0",
|
|
116
116
|
"graphql-upload": "15.0.2",
|
|
117
|
-
"graphql-ws": "6.0
|
|
118
|
-
"jose": "6.2.
|
|
117
|
+
"graphql-ws": "6.1.0",
|
|
118
|
+
"jose": "6.2.3",
|
|
119
119
|
"js-sha256": "0.11.1",
|
|
120
120
|
"json-to-graphql-query": "2.3.0",
|
|
121
121
|
"lodash": "4.18.1",
|
|
@@ -130,13 +130,13 @@
|
|
|
130
130
|
"rfdc": "1.4.1",
|
|
131
131
|
"rxjs": "7.8.2",
|
|
132
132
|
"supertest": "7.2.2",
|
|
133
|
-
"ts-morph": "
|
|
134
|
-
"ws": "8.21.
|
|
133
|
+
"ts-morph": "28.0.0",
|
|
134
|
+
"ws": "8.21.1",
|
|
135
135
|
"yuml-diagram": "1.2.0"
|
|
136
136
|
},
|
|
137
137
|
"devDependencies": {
|
|
138
|
-
"@compodoc/compodoc": "
|
|
139
|
-
"@nestjs/cli": "11.0.
|
|
138
|
+
"@compodoc/compodoc": "2.0.0",
|
|
139
|
+
"@nestjs/cli": "11.0.24",
|
|
140
140
|
"@nestjs/schematics": "11.1.0",
|
|
141
141
|
"@nestjs/testing": "11.1.28",
|
|
142
142
|
"@swc/cli": "0.8.1",
|
|
@@ -147,7 +147,7 @@
|
|
|
147
147
|
"@types/express": "5.0.6",
|
|
148
148
|
"@types/lodash": "4.17.24",
|
|
149
149
|
"@types/multer": "2.2.0",
|
|
150
|
-
"@types/node": "
|
|
150
|
+
"@types/node": "26.1.1",
|
|
151
151
|
"@types/nodemailer": "8.0.1",
|
|
152
152
|
"@types/passport": "1.0.17",
|
|
153
153
|
"@vitest/coverage-v8": "4.1.10",
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
"nodemon": "3.1.14",
|
|
159
159
|
"npm-watch": "0.13.0",
|
|
160
160
|
"otpauth": "9.5.1",
|
|
161
|
-
"oxfmt": "0.
|
|
161
|
+
"oxfmt": "0.59.0",
|
|
162
162
|
"oxlint": "1.74.0",
|
|
163
163
|
"rimraf": "6.1.3",
|
|
164
164
|
"ts-node": "10.9.2",
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
"tus-js-client": "4.3.1",
|
|
168
168
|
"typescript": "5.9.3",
|
|
169
169
|
"unplugin-swc": "1.5.9",
|
|
170
|
-
"vite": "8.1.
|
|
170
|
+
"vite": "8.1.5",
|
|
171
171
|
"vite-plugin-node": "8.0.0",
|
|
172
172
|
"vitest": "4.1.10"
|
|
173
173
|
},
|
|
@@ -273,9 +273,7 @@ export class FindUsersAiTool extends AiTool {
|
|
|
273
273
|
// Routes through CrudService with the caller's serviceOptions → permissions apply.
|
|
274
274
|
const users = await this.userService.find(
|
|
275
275
|
{
|
|
276
|
-
filterQuery: {
|
|
277
|
-
/* … */
|
|
278
|
-
},
|
|
276
|
+
filterQuery: {/* … */},
|
|
279
277
|
},
|
|
280
278
|
context.serviceOptions,
|
|
281
279
|
);
|
|
@@ -297,13 +297,14 @@ const localConfig = {
|
|
|
297
297
|
- **Graceful Degradation**: If auto-detection fails (no baseUrl), Passkey is disabled with a warning - other auth methods (Email/Password, 2FA) continue to work
|
|
298
298
|
|
|
299
299
|
**Auto-Detection Resolution:**
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
|
303
|
-
| `
|
|
304
|
-
| `
|
|
305
|
-
| `
|
|
306
|
-
| `
|
|
300
|
+
|
|
301
|
+
| Value | Priority | Source |
|
|
302
|
+
| ---------------- | ------------------------------------------------------------------------------------------------- | ------ |
|
|
303
|
+
| `baseUrl` | 1. Explicit `betterAuth.baseUrl` → 2. Root-level `baseUrl` → 3. Localhost default (env: 'local') |
|
|
304
|
+
| `appUrl` | 1. Root-level `appUrl` → 2. Derived from `baseUrl` (removes `api.` prefix) → 3. Localhost default |
|
|
305
|
+
| `rpId` | 1. Explicit `passkey.rpId` → 2. Auto-detect from appUrl hostname |
|
|
306
|
+
| `origin` | 1. Explicit `passkey.origin` → 2. Auto-detect from appUrl |
|
|
307
|
+
| `trustedOrigins` | 1. Explicit `trustedOrigins` → 2. Auto-detect from appUrl |
|
|
307
308
|
|
|
308
309
|
### Explicit Passkey Configuration (Advanced)
|
|
309
310
|
|