@lenne.tech/nest-server 11.24.0 → 11.24.2
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 +61 -2
- package/CLAUDE.md +77 -0
- package/FRAMEWORK-API.md +3 -3
- package/dist/core/common/services/crud.service.d.ts +9 -3
- package/dist/core/common/services/crud.service.js +4 -2
- package/dist/core/common/services/crud.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/migration-guides/11.24.0-to-11.24.1.md +67 -0
- package/package.json +30 -12
- package/src/core/common/services/crud.service.ts +13 -6
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Migration Guide: 11.24.0 → 11.24.1
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
| Category | Details |
|
|
6
|
+
|----------|---------|
|
|
7
|
+
| **Breaking Changes** | None |
|
|
8
|
+
| **New Features** | `pushToArray()`/`pullFromArray()` now accept `ObjectId` and objects with `id`/`_id` property |
|
|
9
|
+
| **Migration Effort** | 0 minutes (no code changes required) |
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Quick Migration
|
|
14
|
+
|
|
15
|
+
No code changes required.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Update package
|
|
19
|
+
pnpm add @lenne.tech/nest-server@11.24.1
|
|
20
|
+
|
|
21
|
+
# Verify build
|
|
22
|
+
pnpm run build
|
|
23
|
+
|
|
24
|
+
# Run tests
|
|
25
|
+
pnpm test
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## What's New in 11.24.1
|
|
31
|
+
|
|
32
|
+
### Flexible `id` Parameter on `pushToArray()` / `pullFromArray()`
|
|
33
|
+
|
|
34
|
+
Both methods now accept `string`, `Types.ObjectId`, or any object with an `id`/`_id` property (e.g. a Mongoose Document). IDs are normalized internally via `getStringIds()`, consistent with the rest of the framework.
|
|
35
|
+
|
|
36
|
+
**Before (11.24.0):** Only `string` was accepted.
|
|
37
|
+
```typescript
|
|
38
|
+
await this.entityService.pushToArray(entity.id, 'logs', newLog);
|
|
39
|
+
await this.entityService.pullFromArray(entity.id.toString(), 'tags', 'old');
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**After (11.24.1):** All ID types work directly.
|
|
43
|
+
```typescript
|
|
44
|
+
// String (still works)
|
|
45
|
+
await this.entityService.pushToArray('507f1f77bcf86cd799439011', 'logs', newLog);
|
|
46
|
+
|
|
47
|
+
// ObjectId
|
|
48
|
+
await this.entityService.pushToArray(new Types.ObjectId(id), 'logs', newLog);
|
|
49
|
+
|
|
50
|
+
// Object with id property (e.g. Mongoose Document or entity reference)
|
|
51
|
+
await this.entityService.pushToArray(entity, 'logs', newLog);
|
|
52
|
+
|
|
53
|
+
// Same for pullFromArray
|
|
54
|
+
await this.entityService.pullFromArray(entity, 'tags', 'obsolete');
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Compatibility Notes
|
|
60
|
+
|
|
61
|
+
Existing code using `string` IDs continues to work unchanged. The wider type signature is additive — no existing call sites break.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## References
|
|
66
|
+
|
|
67
|
+
- [Migration Guide 11.23.x → 11.24.0](./11.23.x-to-11.24.0.md) — Full list of changes in 11.24.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.24.
|
|
3
|
+
"version": "11.24.2",
|
|
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",
|
|
@@ -78,16 +78,16 @@
|
|
|
78
78
|
"@as-integrations/express5": "1.1.2",
|
|
79
79
|
"@better-auth/passkey": "1.5.5",
|
|
80
80
|
"@getbrevo/brevo": "3.0.1",
|
|
81
|
-
"@nestjs/apollo": "13.2.
|
|
81
|
+
"@nestjs/apollo": "13.2.5",
|
|
82
82
|
"@nestjs/common": "11.1.18",
|
|
83
83
|
"@nestjs/core": "11.1.18",
|
|
84
|
-
"@nestjs/graphql": "13.2.
|
|
84
|
+
"@nestjs/graphql": "13.2.5",
|
|
85
85
|
"@nestjs/jwt": "11.0.2",
|
|
86
86
|
"@nestjs/mongoose": "11.0.4",
|
|
87
87
|
"@nestjs/passport": "11.0.5",
|
|
88
88
|
"@nestjs/platform-express": "11.1.18",
|
|
89
89
|
"@nestjs/schedule": "6.1.1",
|
|
90
|
-
"@nestjs/swagger": "11.2.
|
|
90
|
+
"@nestjs/swagger": "11.2.7",
|
|
91
91
|
"@nestjs/terminus": "11.1.1",
|
|
92
92
|
"@nestjs/websockets": "11.1.18",
|
|
93
93
|
"@tus/file-store": "2.0.0",
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
},
|
|
126
126
|
"devDependencies": {
|
|
127
127
|
"@compodoc/compodoc": "1.2.1",
|
|
128
|
-
"@nestjs/cli": "11.0.
|
|
128
|
+
"@nestjs/cli": "11.0.19",
|
|
129
129
|
"@nestjs/schematics": "11.0.10",
|
|
130
130
|
"@nestjs/testing": "11.1.18",
|
|
131
131
|
"@swc/cli": "0.8.1",
|
|
@@ -136,11 +136,11 @@
|
|
|
136
136
|
"@types/express": "5.0.6",
|
|
137
137
|
"@types/lodash": "4.17.24",
|
|
138
138
|
"@types/multer": "2.1.0",
|
|
139
|
-
"@types/node": "25.
|
|
139
|
+
"@types/node": "25.6.0",
|
|
140
140
|
"@types/nodemailer": "8.0.0",
|
|
141
141
|
"@types/passport": "1.0.17",
|
|
142
|
-
"@vitest/coverage-v8": "4.1.
|
|
143
|
-
"@vitest/ui": "4.1.
|
|
142
|
+
"@vitest/coverage-v8": "4.1.4",
|
|
143
|
+
"@vitest/ui": "4.1.4",
|
|
144
144
|
"ansi-colors": "4.1.3",
|
|
145
145
|
"find-file-up": "2.0.1",
|
|
146
146
|
"husky": "9.1.7",
|
|
@@ -157,8 +157,7 @@
|
|
|
157
157
|
"unplugin-swc": "1.5.9",
|
|
158
158
|
"vite": "7.3.2",
|
|
159
159
|
"vite-plugin-node": "7.0.0",
|
|
160
|
-
"
|
|
161
|
-
"vitest": "4.1.3"
|
|
160
|
+
"vitest": "4.1.4"
|
|
162
161
|
},
|
|
163
162
|
"main": "dist/index.js",
|
|
164
163
|
"types": "dist/index.d.ts",
|
|
@@ -181,7 +180,27 @@
|
|
|
181
180
|
},
|
|
182
181
|
"packageManager": "pnpm@10.33.0",
|
|
183
182
|
"pnpm": {
|
|
183
|
+
"//overrides": {
|
|
184
|
+
"axios@<1.15.0": "Security: SSRF via NO_PROXY bypass (GHSA-3p68-rc4w-qgx5) and unrestricted cloud metadata exfiltration (GHSA-fvcv-3m26-pcqx) - transitive via @getbrevo/brevo and node-mailjet. Remove when @getbrevo/brevo ships axios>=1.15.0",
|
|
185
|
+
"minimatch@<3.1.5": "Security: RegExp DoS (GHSA-p8p7-x288-28g6) - transitive via @getbrevo/brevo>rewire>eslint",
|
|
186
|
+
"minimatch@>=9.0.0 <9.0.9": "Security: RegExp DoS - transitive via @nestjs/cli>@swc/cli",
|
|
187
|
+
"minimatch@>=10.0.0 <10.2.5": "Security: RegExp DoS - transitive via @nestjs/apollo>ts-morph>@ts-morph/common and nodemon",
|
|
188
|
+
"ajv@<6.14.0": "Security: prototype pollution - transitive via @getbrevo/brevo>rewire>eslint",
|
|
189
|
+
"ajv@>=7.0.0-alpha.0 <8.18.0": "Security: prototype pollution - transitive via @nestjs/cli>@angular-devkit",
|
|
190
|
+
"undici@>=7.0.0 <7.24.7": "Security: various CVEs - transitive via @compodoc/compodoc>cheerio",
|
|
191
|
+
"srvx@<0.11.15": "Compatibility: @tus/server@2.3.0 requires ~0.8.2 but 0.11.15 needed for security - remove when @tus/server ships with >=0.11.15",
|
|
192
|
+
"handlebars@>=4.0.0 <4.7.9": "Security: prototype pollution (GHSA-q42p-pg8m-cqh6) - transitive via @compodoc/compodoc",
|
|
193
|
+
"brace-expansion@<1.1.13": "Security: RegExp DoS - transitive via eslint>minimatch",
|
|
194
|
+
"brace-expansion@>=4.0.0 <5.0.5": "Security: RegExp DoS - transitive via nodemon>minimatch and @ts-morph/common>minimatch",
|
|
195
|
+
"picomatch@<2.3.2": "Security: ReDoS - transitive via @nestjs/graphql>fast-glob>micromatch and @compodoc/compodoc>chokidar",
|
|
196
|
+
"picomatch@>=4.0.0 <4.0.4": "Security: ReDoS - transitive via vitest and vite",
|
|
197
|
+
"path-to-regexp@>=8.0.0 <8.4.2": "Security: ReDoS (GHSA-rhx6-c78j-4q9w) - transitive via express>router",
|
|
198
|
+
"kysely@>=0.26.0 <0.28.15": "Security: SQL injection - transitive via better-auth",
|
|
199
|
+
"lodash@>=4.0.0 <4.18.0": "Security: CVE in lodash@4.17.x - transitive via @nestjs/graphql. 4.18.1 is the latest patched version",
|
|
200
|
+
"defu@<=6.1.6": "Security: prototype pollution via __proto__ key - transitive via better-auth"
|
|
201
|
+
},
|
|
184
202
|
"overrides": {
|
|
203
|
+
"axios@<1.15.0": "1.15.0",
|
|
185
204
|
"minimatch@<3.1.5": "3.1.5",
|
|
186
205
|
"minimatch@>=9.0.0 <9.0.9": "9.0.9",
|
|
187
206
|
"minimatch@>=10.0.0 <10.2.5": "10.2.5",
|
|
@@ -197,8 +216,7 @@
|
|
|
197
216
|
"path-to-regexp@>=8.0.0 <8.4.2": "8.4.2",
|
|
198
217
|
"kysely@>=0.26.0 <0.28.15": "0.28.15",
|
|
199
218
|
"lodash@>=4.0.0 <4.18.0": "4.18.1",
|
|
200
|
-
"defu@<=6.1.6": "6.1.7"
|
|
201
|
-
"vite@>=7.0.0 <7.3.2": "7.3.2"
|
|
219
|
+
"defu@<=6.1.6": "6.1.7"
|
|
202
220
|
},
|
|
203
221
|
"onlyBuiltDependencies": [
|
|
204
222
|
"bcrypt",
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
Query,
|
|
10
10
|
QueryFilter,
|
|
11
11
|
QueryOptions,
|
|
12
|
+
Types,
|
|
12
13
|
} from 'mongoose';
|
|
13
14
|
|
|
14
15
|
import { FilterArgs } from '../args/filter.args';
|
|
@@ -707,13 +708,13 @@ export abstract class CrudService<
|
|
|
707
708
|
* await this.pushToArray(id, 'logs', newLog);
|
|
708
709
|
* await this.pushToArray(id, 'logs', newLog, { $slice: -500 }); // Keep last 500
|
|
709
710
|
*
|
|
710
|
-
* @param id - Document ID
|
|
711
|
+
* @param id - Document ID (string, ObjectId, or object with id/_id property)
|
|
711
712
|
* @param field - Array field name. MUST be a compile-time constant — never pass user-controlled input.
|
|
712
713
|
* @param items - Item(s) to append
|
|
713
714
|
* @param options - MongoDB $push modifiers ($slice, $position, $sort)
|
|
714
715
|
*/
|
|
715
716
|
async pushToArray(
|
|
716
|
-
id: string,
|
|
717
|
+
id: string | Types.ObjectId | { id?: any; _id?: any },
|
|
717
718
|
field: string,
|
|
718
719
|
items: any | any[],
|
|
719
720
|
options?: { $slice?: number; $position?: number; $sort?: Record<string, 1 | -1> },
|
|
@@ -727,6 +728,7 @@ export abstract class CrudService<
|
|
|
727
728
|
return;
|
|
728
729
|
}
|
|
729
730
|
|
|
731
|
+
const stringId = getStringIds(id);
|
|
730
732
|
const pushOp: any = { $each: itemsArray };
|
|
731
733
|
if (options?.$slice !== undefined) {
|
|
732
734
|
pushOp.$slice = options.$slice;
|
|
@@ -739,7 +741,7 @@ export abstract class CrudService<
|
|
|
739
741
|
}
|
|
740
742
|
|
|
741
743
|
await this.mainDbModel
|
|
742
|
-
.findByIdAndUpdate(
|
|
744
|
+
.findByIdAndUpdate(stringId, { $push: { [field]: pushOp } } as any)
|
|
743
745
|
.lean()
|
|
744
746
|
.exec();
|
|
745
747
|
}
|
|
@@ -756,17 +758,22 @@ export abstract class CrudService<
|
|
|
756
758
|
* // Remove by condition
|
|
757
759
|
* await this.pullFromArray(id, 'logs', { level: 'DEBUG' });
|
|
758
760
|
*
|
|
759
|
-
* @param id - Document ID
|
|
761
|
+
* @param id - Document ID (string, ObjectId, or object with id/_id property)
|
|
760
762
|
* @param field - Array field name. MUST be a compile-time constant — never pass user-controlled input.
|
|
761
763
|
* @param condition - Match condition for removal. MUST be application-controlled.
|
|
762
764
|
*/
|
|
763
|
-
async pullFromArray(
|
|
765
|
+
async pullFromArray(
|
|
766
|
+
id: string | Types.ObjectId | { id?: any; _id?: any },
|
|
767
|
+
field: string,
|
|
768
|
+
condition: any,
|
|
769
|
+
): Promise<void> {
|
|
764
770
|
if (typeof field !== 'string' || field.startsWith('$') || field.includes('\0')) {
|
|
765
771
|
throw new Error(`pullFromArray: invalid field name "${field}"`);
|
|
766
772
|
}
|
|
767
773
|
|
|
774
|
+
const stringId = getStringIds(id);
|
|
768
775
|
await this.mainDbModel
|
|
769
|
-
.findByIdAndUpdate(
|
|
776
|
+
.findByIdAndUpdate(stringId, { $pull: { [field]: condition } } as any)
|
|
770
777
|
.lean()
|
|
771
778
|
.exec();
|
|
772
779
|
}
|