Compare commits

...

277 Commits

Author SHA1 Message Date
Kamil Mysliwiec
b28012ebf9 Merge pull request #16372 from nestjs/refactor/minor-tweaks
refactor: minor codebase tweaks
2026-02-15 16:42:44 +01:00
Kamil Mysliwiec
a21fd1d83a Merge pull request #16373 from nestjs/feat/param-decorator-options
feat: standard schema validation pipe, and standard serializer, introduce internal export subpath
2026-02-15 16:42:30 +01:00
Kamil Myśliwiec
90a40d540e sample: turn off running sample tests for now 2026-02-15 16:03:05 +01:00
Kamil Myśliwiec
d2fd2e692e sample: fix file upload ts compilation error 2026-02-15 15:02:10 +01:00
Kamil Myśliwiec
b6cecd81c4 ci: ignore coverage script errors in ci 2026-02-15 14:30:14 +01:00
Kamil Myśliwiec
9d4c8656cd chore: exclude samples that use cli plugins for now 2026-02-15 14:29:12 +01:00
Kamil Myśliwiec
fb3ae67e25 chore: address lint errors, and fix ci test errors 2026-02-15 14:17:05 +01:00
Kamil Myśliwiec
543142d5ce fix: dont export plain literal object interface 2026-02-15 13:31:12 +01:00
Kamil Myśliwiec
09c81568f8 feat: introduce standard schema serializer 2026-02-15 13:07:08 +01:00
Kamil Myśliwiec
473810cc85 chore: introduce the internal export path 2026-02-13 17:40:00 +01:00
Kamil Myśliwiec
50f0f7286c feat(common): introduce param decorator options 2026-02-13 13:59:07 +01:00
Kamil Myśliwiec
6586c0d985 refactor: minor codebase tweaks 2026-02-13 13:58:25 +01:00
Kamil Myśliwiec
df1537f74e chore: add root dir to tsconfig 2026-02-12 21:03:38 +01:00
Kamil Myśliwiec
62908b4a8b sample: add await to bootstrap calls 2026-02-12 20:53:03 +01:00
Kamil Myśliwiec
1c046aeea7 sample: migrate samples to esm 2026-02-12 20:28:07 +01:00
Kamil Myśliwiec
288453fabb test: fix coverage collection, add more tests 2026-02-11 20:44:14 +01:00
Kamil Myśliwiec
6846cd7128 test: migrate to vitest 2026-02-11 15:04:51 +01:00
Kamil Myśliwiec
33f37d6270 refactor: minor tweaks 2026-02-09 16:05:02 +01:00
Kamil Myśliwiec
fa6d45da74 build: migrate from cjs to esm 2026-02-09 14:10:04 +01:00
Kamil Mysliwiec
1c324622de Merge pull request #16318 from nestjs/renovate/dotenv-17.x
fix(deps): update dependency dotenv to v17.2.4
2026-02-06 12:11:02 +01:00
Kamil Mysliwiec
88a2c1c8bf Merge pull request #16319 from nestjs/renovate/fast-json-stringify-6.x
fix(deps): update dependency fast-json-stringify to v6.3.0
2026-02-06 12:10:54 +01:00
Kamil Mysliwiec
829d326727 Merge pull request #16314 from SpencerKaiser/bugfix/cors-types
fix(common): change requestOrigin type
2026-02-06 12:06:34 +01:00
Kamil Mysliwiec
f854f9cbe6 Merge pull request #16316 from nestjs/renovate/node-24.x
chore(deps): update dependency @types/node to v24.10.11
2026-02-06 12:06:13 +01:00
renovate[bot]
af9b46513b fix(deps): update dependency fast-json-stringify to v6.3.0 2026-02-06 05:00:59 +00:00
renovate[bot]
b290fbc85f fix(deps): update dependency dotenv to v17.2.4 2026-02-05 22:14:36 +00:00
renovate[bot]
3c00b44771 chore(deps): update dependency @types/node to v24.10.11 2026-02-05 18:09:10 +00:00
Kamil Mysliwiec
fcaa117e22 Merge pull request #16317 from nestjs/renovate/node-25.x
chore(deps): update dependency @types/node to v25.2.1
2026-02-05 19:04:36 +01:00
renovate[bot]
35a1ec1adb chore(deps): update dependency @types/node to v25.2.1 2026-02-05 16:31:05 +00:00
Kamil Mysliwiec
d35b3a8fe8 Merge pull request #16303 from nestjs/renovate/nest-graphql-monorepo
fix(deps): update nest-graphql monorepo to v13.2.4
2026-02-05 12:48:52 +01:00
renovate[bot]
7b9f885262 fix(deps): update nest-graphql monorepo to v13.2.4 2026-02-05 11:44:04 +00:00
Kamil Mysliwiec
e50e3e79fb Merge pull request #16300 from nestjs/renovate/nestjs-schedule-6.x
fix(deps): update dependency @nestjs/schedule to v6.1.1
2026-02-05 12:40:52 +01:00
Kamil Mysliwiec
7cbebba3d8 Merge pull request #16301 from nestjs/renovate/nestjs-swagger-11.x
fix(deps): update dependency @nestjs/swagger to v11.2.6
2026-02-05 12:40:41 +01:00
Kamil Mysliwiec
770c7ca4af Merge pull request #16304 from nestjs/renovate/apollo-graphql-packages
fix(deps): update dependency @apollo/server to v5.4.0
2026-02-05 12:40:26 +01:00
Kamil Mysliwiec
8b616d2e27 Merge pull request #16310 from nestjs/dependabot/npm_and_yarn/nestjs/graphql-13.2.4
chore(deps-dev): bump @nestjs/graphql from 13.2.3 to 13.2.4
2026-02-05 12:40:18 +01:00
Kamil Mysliwiec
a2db2bc673 Merge pull request #16311 from nestjs/dependabot/npm_and_yarn/apollo/server-5.4.0
chore(deps-dev): bump @apollo/server from 5.3.0 to 5.4.0
2026-02-05 12:40:13 +01:00
Kamil Mysliwiec
e7d186d605 Merge pull request #16307 from Recursyve/fix/console-logger-error-context
fix: logger print invalid context when no stack trace provided
2026-02-05 12:39:56 +01:00
dependabot[bot]
ecd34f65c1 chore(deps-dev): bump @apollo/server from 5.3.0 to 5.4.0
Bumps [@apollo/server](https://github.com/apollographql/apollo-server/tree/HEAD/packages/server) from 5.3.0 to 5.4.0.
- [Release notes](https://github.com/apollographql/apollo-server/releases)
- [Changelog](https://github.com/apollographql/apollo-server/blob/main/packages/server/CHANGELOG.md)
- [Commits](https://github.com/apollographql/apollo-server/commits/@apollo/server@5.4.0/packages/server)

---
updated-dependencies:
- dependency-name: "@apollo/server"
  dependency-version: 5.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-05 11:39:52 +00:00
Kamil Mysliwiec
af11a1cdcf Merge pull request #16308 from nestjs/renovate/mongoose-9.x
fix(deps): update dependency mongoose to v9.1.6
2026-02-05 12:38:34 +01:00
Kamil Mysliwiec
0fe64923ab Merge pull request #16312 from nestjs/dependabot/npm_and_yarn/mongoose-9.1.6
chore(deps-dev): bump mongoose from 9.1.5 to 9.1.6
2026-02-05 12:38:22 +01:00
Spencer Kaiser
5058600ae3 fix(common): change requestOrigin type
fix(common): change requestOrigin type
2026-02-04 20:48:36 -06:00
dependabot[bot]
be35bb7dac chore(deps-dev): bump mongoose from 9.1.5 to 9.1.6
Bumps [mongoose](https://github.com/Automattic/mongoose) from 9.1.5 to 9.1.6.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/9.1.5...9.1.6)

---
updated-dependencies:
- dependency-name: mongoose
  dependency-version: 9.1.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-05 00:54:11 +00:00
dependabot[bot]
ca64b40164 chore(deps-dev): bump @nestjs/graphql from 13.2.3 to 13.2.4
Bumps [@nestjs/graphql](https://github.com/nestjs/graphql) from 13.2.3 to 13.2.4.
- [Release notes](https://github.com/nestjs/graphql/releases)
- [Commits](https://github.com/nestjs/graphql/compare/v13.2.3...v13.2.4)

---
updated-dependencies:
- dependency-name: "@nestjs/graphql"
  dependency-version: 13.2.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-05 00:53:05 +00:00
renovate[bot]
fa9baa8eb0 fix(deps): update dependency @apollo/server to v5.4.0 2026-02-04 22:40:10 +00:00
renovate[bot]
31c34340c6 fix(deps): update dependency mongoose to v9.1.6 2026-02-04 22:39:56 +00:00
JulienDuf
91212b20d3 fix: return type error 2026-02-04 16:01:55 -05:00
JulienDuf
804d27bbe4 fix: invalid context when no stack trace is provided 2026-02-04 14:20:21 -05:00
renovate[bot]
f66414667f fix(deps): update dependency @nestjs/swagger to v11.2.6 2026-02-04 14:17:10 +00:00
renovate[bot]
b813820611 fix(deps): update dependency @nestjs/schedule to v6.1.1 2026-02-04 14:17:05 +00:00
Kamil Mysliwiec
bec4329be4 Merge pull request #16298 from nestjs/dependabot/npm_and_yarn/tools/benchmarks/multi-b4698b0d36
chore(deps): bump fastify and @nestjs/platform-fastify in /tools/benchmarks
2026-02-04 11:42:43 +01:00
Kamil Mysliwiec
5a42e7cf23 Merge pull request #16299 from nestjs/renovate/nest-monorepo
chore(deps): update nest monorepo to v11.1.13
2026-02-04 11:42:33 +01:00
Kamil Mysliwiec
deb4c250a5 Merge pull request #16294 from nestjs/renovate/mysql2-3.x
fix(deps): update dependency mysql2 to v3.16.3
2026-02-04 11:42:22 +01:00
renovate[bot]
379f9f9030 fix(deps): update dependency mysql2 to v3.16.3 2026-02-04 10:27:59 +00:00
renovate[bot]
ce86b45d7d chore(deps): update nest monorepo to v11.1.13 2026-02-04 10:25:45 +00:00
Kamil Mysliwiec
2e75afa512 Merge pull request #16296 from nestjs/renovate/mongodb-7.x
fix(deps): update dependency mongodb to v7.1.0
2026-02-04 11:24:38 +01:00
dependabot[bot]
2bec40a801 chore(deps): bump fastify and @nestjs/platform-fastify
Bumps [fastify](https://github.com/fastify/fastify) to 5.7.4 and updates ancestor dependency [@nestjs/platform-fastify](https://github.com/nestjs/nest/tree/HEAD/packages/platform-fastify). These dependencies need to be updated together.


Updates `fastify` from 5.6.2 to 5.7.4
- [Release notes](https://github.com/fastify/fastify/releases)
- [Commits](https://github.com/fastify/fastify/compare/v5.6.2...v5.7.4)

Updates `@nestjs/platform-fastify` from 11.1.12 to 11.1.13
- [Release notes](https://github.com/nestjs/nest/releases)
- [Commits](https://github.com/nestjs/nest/commits/v11.1.13/packages/platform-fastify)

---
updated-dependencies:
- dependency-name: fastify
  dependency-version: 5.7.4
  dependency-type: indirect
- dependency-name: "@nestjs/platform-fastify"
  dependency-version: 11.1.13
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-04 10:24:10 +00:00
Kamil Mysliwiec
8a8833d678 Merge pull request #16271 from mixator/feat/replace-benchmarks
build: replace benchmarks
2026-02-04 11:23:03 +01:00
renovate[bot]
b0f5509f53 fix(deps): update dependency mongodb to v7.1.0 2026-02-04 04:31:01 +00:00
Mykhailo Skrypskyi
72be027d16 Merge branch 'master' into feat/replace-benchmarks 2026-02-03 21:23:19 +02:00
Kamil Mysliwiec
72283cc7a9 Merge pull request #16293 from nestjs/renovate/webpack-5.x
chore(deps): update dependency webpack to v5.105.0
2026-02-03 19:51:22 +01:00
Kamil Mysliwiec
bb8cf85bc9 Merge pull request #16292 from nestjs/renovate/nest-monorepo
fix(deps): update nest monorepo to v11.1.13
2026-02-03 19:51:15 +01:00
renovate[bot]
d0f4d7545b chore(deps): update dependency webpack to v5.105.0 2026-02-03 16:31:17 +00:00
renovate[bot]
1b60fd317f fix(deps): update nest monorepo to v11.1.13 2026-02-03 16:31:06 +00:00
Kamil Myśliwiec
8d1c16c1ca chore: update readme 2026-02-03 14:07:38 +01:00
Kamil Myśliwiec
e3a958ac3e chore(release): publish v11.1.13 release 2026-02-03 13:47:36 +01:00
Kamil Mysliwiec
db90c3fb67 Merge pull request #16286 from suuuuuuminnnnnn/feat/microservices-mqtt-per-handler-qos
feat(microservices): support per-handler qos in mqtt
2026-02-03 13:42:33 +01:00
Kamil Mysliwiec
9a0ea3360c Merge pull request #16290 from nestjs/renovate/node-24.x
chore(deps): update dependency @types/node to v24.10.10
2026-02-03 13:35:42 +01:00
Kamil Mysliwiec
7bdca191c5 Merge pull request #16283 from nestjs/renovate/mqtt-5.x
chore(deps): update dependency mqtt to v5.15.0
2026-02-03 13:35:32 +01:00
Kamil Mysliwiec
401d81b1c4 Merge pull request #16282 from nestjs/renovate/fastify-5.x
fix(deps): update dependency fastify to v5.7.4
2026-02-03 13:34:57 +01:00
Kamil Mysliwiec
87cb6f92a5 Merge pull request #16288 from nestjs/dependabot/npm_and_yarn/mqtt-5.15.0
chore(deps-dev): bump mqtt from 5.14.1 to 5.15.0
2026-02-03 13:34:43 +01:00
renovate[bot]
a92bb399f9 chore(deps): update dependency @types/node to v24.10.10 2026-02-03 10:47:25 +00:00
Mykhailo Skrypskyi
3de4d8a8ef chore: merge changes from master 2026-02-03 11:31:16 +02:00
dependabot[bot]
e9869ed2fa chore(deps-dev): bump mqtt from 5.14.1 to 5.15.0
Bumps [mqtt](https://github.com/mqttjs/MQTT.js) from 5.14.1 to 5.15.0.
- [Release notes](https://github.com/mqttjs/MQTT.js/releases)
- [Changelog](https://github.com/mqttjs/MQTT.js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mqttjs/MQTT.js/compare/v5.14.1...v5.15.0)

---
updated-dependencies:
- dependency-name: mqtt
  dependency-version: 5.15.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-03 05:12:48 +00:00
suuuuuuminnnnnn
f5148709ff feat(microservices): support per-handler qos in mqtt 2026-02-03 10:41:51 +09:00
Mykhailo Skrypskyi
fad09363aa fix: apply chages from review 2026-02-02 23:02:54 +02:00
renovate[bot]
b885673aa8 chore(deps): update dependency mqtt to v5.15.0 2026-02-02 19:31:16 +00:00
renovate[bot]
fba0de79f2 fix(deps): update dependency fastify to v5.7.4 2026-02-02 19:31:05 +00:00
Kamil Mysliwiec
346c954312 Merge pull request #16262 from jobnow/feat/microservices-configurable-max-buffer-size
Feat/microservices configurable max buffer size
2026-02-02 14:20:43 +01:00
Kamil Mysliwiec
4081c1f5e0 Merge pull request #16281 from nestjs/renovate/commitlint-monorepo
chore(deps): update dependency @commitlint/config-angular to v20.4.1
2026-02-02 14:20:08 +01:00
Kamil Mysliwiec
1b11d01840 Update Readme.md 2026-02-02 14:19:47 +01:00
renovate[bot]
fcb774c8ed chore(deps): update dependency @commitlint/config-angular to v20.4.1 2026-02-02 13:09:27 +00:00
Kamil Mysliwiec
49cf11a063 Merge pull request #16276 from nestjs/dependabot/npm_and_yarn/commitlint/cli-20.4.0
chore(deps-dev): bump @commitlint/cli from 20.3.1 to 20.4.0
2026-02-02 14:06:51 +01:00
dependabot[bot]
bfa0ecb176 chore(deps-dev): bump @commitlint/cli from 20.3.1 to 20.4.0
Bumps [@commitlint/cli](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli) from 20.3.1 to 20.4.0.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v20.4.0/@commitlint/cli)

---
updated-dependencies:
- dependency-name: "@commitlint/cli"
  dependency-version: 20.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-02 12:58:38 +00:00
Kamil Mysliwiec
e5003a1a01 Merge pull request #16265 from nestjs/dependabot/npm_and_yarn/artillery-2.0.29
chore(deps-dev): bump artillery from 2.0.28 to 2.0.29
2026-02-02 13:57:21 +01:00
Kamil Mysliwiec
e4a19bbdeb Merge pull request #16266 from nestjs/renovate/commitlint-monorepo
chore(deps): update commitlint monorepo to v20.4.0
2026-02-02 13:57:07 +01:00
Kamil Mysliwiec
e846bcd0e7 Merge pull request #16269 from nestjs/renovate/babel-monorepo
chore(deps): update babel monorepo to v7.29.0
2026-02-02 13:56:58 +01:00
Kamil Mysliwiec
12e70a4bf4 Merge pull request #16270 from nestjs/renovate/globals-17.x
chore(deps): update dependency globals to v17.3.0
2026-02-02 13:56:44 +01:00
Kamil Mysliwiec
8a0e32c616 Merge pull request #16273 from nestjs/renovate/node-25.x
chore(deps): update dependency @types/node to v25.2.0
2026-02-02 13:56:36 +01:00
Kamil Mysliwiec
007a9bdbe9 Merge pull request #16264 from nestjs/renovate/artillery-2.x
chore(deps): update dependency artillery to v2.0.29
2026-02-02 13:56:26 +01:00
renovate[bot]
c96bb2a849 chore(deps): update dependency @types/node to v25.2.0 2026-02-01 17:14:19 +00:00
Mykhailo Skrypskyi
e49e92102a fix: update dependencies 2026-02-01 11:47:08 +02:00
Mykhailo Skrypskyi
3cb3c2d6ad feat: update benchmarks 2026-02-01 11:42:27 +02:00
renovate[bot]
048da85025 chore(deps): update dependency globals to v17.3.0 2026-02-01 01:04:48 +00:00
renovate[bot]
3c7b75b00c chore(deps): update babel monorepo to v7.29.0 2026-01-31 21:47:25 +00:00
renovate[bot]
2e8c645bc1 chore(deps): update commitlint monorepo to v20.4.0 2026-01-30 14:45:32 +00:00
dependabot[bot]
978256d75d chore(deps-dev): bump artillery from 2.0.28 to 2.0.29
Bumps [artillery](https://github.com/artilleryio/artillery) from 2.0.28 to 2.0.29.
- [Release notes](https://github.com/artilleryio/artillery/releases)
- [Commits](https://github.com/artilleryio/artillery/compare/artillery-2.0.28...artillery-2.0.29)

---
updated-dependencies:
- dependency-name: artillery
  dependency-version: 2.0.29
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-30 00:53:37 +00:00
renovate[bot]
d17dff12d4 chore(deps): update dependency artillery to v2.0.29 2026-01-29 18:05:20 +00:00
Ricardo
a5be2710ee refactor(microservices): Use options object for JsonSocket constructor
- Replace maxBufferSize parameter with JsonSocketOptions object
- Add JsonSocketOptions interface for better extensibility
- Update ClientTCP and ServerTCP to pass options object
- Update all tests to use new options format

Addresses review feedback from @kamilmysliwiec
2026-01-28 17:12:46 -03:00
Kamil Mysliwiec
782e0715f0 Merge pull request #16253 from nestjs/dependabot/npm_and_yarn/fastify-5.7.2
chore(deps): bump fastify from 5.7.1 to 5.7.2
2026-01-28 20:48:43 +01:00
Kamil Mysliwiec
91a9655d23 Merge pull request #16254 from nestjs/dependabot/npm_and_yarn/mysql2-3.16.2
chore(deps-dev): bump mysql2 from 3.16.1 to 3.16.2
2026-01-28 20:48:37 +01:00
Kamil Mysliwiec
3a2b180ddb Merge pull request #16247 from nestjs/renovate/fastify-5.x
fix(deps): update dependency fastify to v5.7.2
2026-01-28 20:48:29 +01:00
Kamil Mysliwiec
0d5b566789 Merge pull request #16249 from nestjs/renovate/mysql2-3.x
fix(deps): update dependency mysql2 to v3.16.2
2026-01-28 20:48:18 +01:00
Kamil Mysliwiec
6e8d083eed Merge pull request #16259 from nestjs/renovate/globals-17.x
chore(deps): update dependency globals to v17.2.0
2026-01-28 20:48:07 +01:00
Kamil Mysliwiec
30ccfd75bd Merge pull request #16261 from nestjs/renovate/node-25.x
chore(deps): update dependency @types/node to v25.1.0
2026-01-28 20:48:01 +01:00
Kamil Mysliwiec
bd83c3f5eb Merge pull request #16255 from devizi0/master
perf(core): use set instead of array for module registry lookup
2026-01-28 20:47:52 +01:00
Kamil Mysliwiec
7d8a4428a8 Merge pull request #16248 from nestjs/renovate/typescript-eslint-monorepo
chore(deps): update typescript-eslint monorepo to v8.54.0
2026-01-28 20:47:21 +01:00
Ricardo
5dd0a9ab8c test(microservices): Fix maxBufferSize tests
- Use valid JSON strings in test data
- Account for packet header length in buffer size calculations
- Fix chunked data test to properly accumulate buffer
2026-01-28 15:22:39 -03:00
Ricardo
2c62817436 feat(microservices): Add configurable maxBufferSize option
- Add maxBufferSize option to TcpOptions and TcpClientOptions interfaces
- Modify JsonSocket to accept maxBufferSize as constructor parameter
- Update ClientTCP and ServerTCP to pass maxBufferSize to JsonSocket
- Add comprehensive tests for maxBufferSize functionality
- Maintain backward compatibility with default value (128MB in characters)

Closes #16256
2026-01-28 15:21:04 -03:00
renovate[bot]
c818015862 chore(deps): update dependency @types/node to v25.1.0 2026-01-28 17:15:39 +00:00
renovate[bot]
321cf7dca2 chore(deps): update dependency globals to v17.2.0 2026-01-27 16:09:48 +00:00
Lee Donghyun
db9494a2ad perf(core): use set instead of array for module registry lookup 2026-01-27 12:08:57 +09:00
dependabot[bot]
c875f6fb18 chore(deps-dev): bump mysql2 from 3.16.1 to 3.16.2
Bumps [mysql2](https://github.com/sidorares/node-mysql2) from 3.16.1 to 3.16.2.
- [Release notes](https://github.com/sidorares/node-mysql2/releases)
- [Changelog](https://github.com/sidorares/node-mysql2/blob/master/Changelog.md)
- [Commits](https://github.com/sidorares/node-mysql2/compare/v3.16.1...v3.16.2)

---
updated-dependencies:
- dependency-name: mysql2
  dependency-version: 3.16.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-27 01:21:50 +00:00
dependabot[bot]
2748f48bfa chore(deps): bump fastify from 5.7.1 to 5.7.2
Bumps [fastify](https://github.com/fastify/fastify) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/fastify/fastify/releases)
- [Commits](https://github.com/fastify/fastify/compare/v5.7.1...v5.7.2)

---
updated-dependencies:
- dependency-name: fastify
  dependency-version: 5.7.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-27 01:21:28 +00:00
renovate[bot]
ae495f7e82 fix(deps): update dependency mysql2 to v3.16.2 2026-01-26 21:49:10 +00:00
renovate[bot]
4029607103 chore(deps): update typescript-eslint monorepo to v8.54.0 2026-01-26 17:45:33 +00:00
renovate[bot]
e2ef54b02b fix(deps): update dependency fastify to v5.7.2 2026-01-26 13:39:29 +00:00
Kamil Mysliwiec
b4324b8968 Merge pull request #16246 from 0xC0FFE2/test/add-unit-tests-discovery-and-serializer
test: add unit tests for DiscoveryService and ClassSerializerInterceptor
2026-01-25 18:48:54 +01:00
Lee Donghyun
d88856c3fa test(common): add unit tests for class serializer interceptor
Add comprehensive unit tests for ClassSerializerInterceptor which
previously had no test coverage despite being a public API.

Test coverage includes:
- constructor with custom transformer package injection
- intercept() with RxJS pipe and context options merging
- serialize() for arrays, objects, and StreamableFile handling
- transformToPlain() with type conversion and instanceOf checks
- getContextOptions() with metadata precedence (handler > class)
- Edge cases: null/undefined, mixed arrays, Date objects, primitives

Total: 25+ test cases covering all public methods and edge cases.
2026-01-26 00:38:25 +09:00
Lee Donghyun
909b504d2d test(core): add unit tests for discovery service
Add comprehensive unit tests for DiscoveryService which previously
had no test coverage despite being a public API.

Test coverage includes:
- createDecorator() static method with unique key generation
- getProviders() with metadataKey and include options filtering
- getControllers() with module-based filtering
- getMetadataByDecorator() with method and class metadata
- getModules() protected method with include filtering
- Edge cases: empty modules, undefined instances, null checks

Total: 30+ test cases covering all public methods and edge cases.
2026-01-26 00:38:14 +09:00
Kamil Mysliwiec
747de7149a Merge pull request #16245 from nestjs/renovate/artillery-2.x
chore(deps): update dependency artillery to v2.0.28
2026-01-25 12:56:14 +01:00
renovate[bot]
84968c4dd8 chore(deps): update dependency artillery to v2.0.28 2026-01-24 10:41:59 +00:00
Kamil Mysliwiec
a1f6162971 Merge pull request #16202 from som14062005/fix/issue-16195
fix(common): exclude built-in primitives from strip proto keys
2026-01-23 09:44:35 +01:00
Kamil Mysliwiec
69892e4f95 Merge pull request #16241 from nestjs/renovate/cors-2.x
fix(deps): update dependency cors to v2.8.6
2026-01-23 09:42:09 +01:00
Kamil Mysliwiec
faba27b355 Merge pull request #16243 from nestjs/renovate/globals-17.x
chore(deps): update dependency globals to v17.1.0
2026-01-23 09:42:03 +01:00
renovate[bot]
ce37a4de1c chore(deps): update dependency globals to v17.1.0 2026-01-23 05:10:53 +00:00
renovate[bot]
58c761a10c fix(deps): update dependency cors to v2.8.6 2026-01-22 17:56:13 +00:00
Kamil Myśliwiec
ed8370697d chore: add type cast in nats emitter 2026-01-22 09:34:45 +01:00
Kamil Mysliwiec
a97228848c Merge pull request #16237 from nestjs/dependabot/npm_and_yarn/types/node-25.0.10
chore(deps-dev): bump @types/node from 24.10.9 to 25.0.10
2026-01-22 09:21:19 +01:00
dependabot[bot]
c5d8988f0e chore(deps-dev): bump @types/node from 24.10.9 to 25.0.10
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.10.9 to 25.0.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.0.10
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-22 08:19:16 +00:00
Kamil Mysliwiec
fd9607fd65 Merge pull request #16232 from nestjs/renovate/apollo-graphql-packages
fix(deps): update dependency @apollo/server to v5.3.0
2026-01-22 09:18:50 +01:00
Kamil Mysliwiec
f6eb7317e2 Merge pull request #16233 from nestjs/renovate/prisma-monorepo
fix(deps): update prisma monorepo to v7.3.0
2026-01-22 09:17:56 +01:00
Kamil Mysliwiec
1c1b017d9c Merge pull request #16234 from nestjs/renovate/prettier-3.x
chore(deps): update dependency prettier to v3.8.1
2026-01-22 09:17:50 +01:00
Kamil Mysliwiec
69138113c5 Merge pull request #16235 from nestjs/dependabot/npm_and_yarn/prettier-3.8.1
chore(deps-dev): bump prettier from 3.8.0 to 3.8.1
2026-01-22 09:17:44 +01:00
Kamil Mysliwiec
7f70c1f992 Merge pull request #16236 from nestjs/dependabot/npm_and_yarn/apollo/server-5.3.0
chore(deps-dev): bump @apollo/server from 5.2.0 to 5.3.0
2026-01-22 09:17:38 +01:00
Kamil Mysliwiec
db4779464a Merge pull request #16238 from nestjs/renovate/mysql-9.x
chore(deps): update mysql docker tag to v9.6.0
2026-01-22 09:17:33 +01:00
renovate[bot]
46a9190770 chore(deps): update mysql docker tag to v9.6.0 2026-01-22 05:47:22 +00:00
dependabot[bot]
7ca537ad6d chore(deps-dev): bump @apollo/server from 5.2.0 to 5.3.0
Bumps [@apollo/server](https://github.com/apollographql/apollo-server/tree/HEAD/packages/server) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/apollographql/apollo-server/releases)
- [Changelog](https://github.com/apollographql/apollo-server/blob/main/packages/server/CHANGELOG.md)
- [Commits](https://github.com/apollographql/apollo-server/commits/@apollo/server@5.3.0/packages/server)

---
updated-dependencies:
- dependency-name: "@apollo/server"
  dependency-version: 5.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-22 00:53:29 +00:00
dependabot[bot]
f507228dc7 chore(deps-dev): bump prettier from 3.8.0 to 3.8.1
Bumps [prettier](https://github.com/prettier/prettier) from 3.8.0 to 3.8.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.8.0...3.8.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.8.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-22 00:53:01 +00:00
renovate[bot]
d4e0c6fb40 chore(deps): update dependency prettier to v3.8.1 2026-01-21 21:48:51 +00:00
renovate[bot]
3f8b278d53 fix(deps): update prisma monorepo to v7.3.0 2026-01-21 17:41:12 +00:00
som14062005
82226347fd refactor: move built-in types to module-level constant 2026-01-21 19:42:22 +05:30
renovate[bot]
57129361dc fix(deps): update dependency @apollo/server to v5.3.0 2026-01-21 12:45:16 +00:00
Kamil Mysliwiec
c2944be1cf Merge pull request #16224 from mixator/remove-unused-deps
build: remove unused dependencies
2026-01-21 11:08:24 +01:00
Mykhailo Skrypskyi
77b4b8a763 fix: update package-lock.json 2026-01-21 11:48:24 +02:00
Mykhailo Skrypskyi
36e52495e0 fix: update package-lock.json 2026-01-21 11:22:44 +02:00
Mykhailo Skrypskyi
9a97cbf0a4 Merge remote-tracking branch 'origin/remove-unused-deps' into remove-unused-deps 2026-01-21 11:01:58 +02:00
Mykhailo Skrypskyi
8d528452ee chore: merge changes from master 2026-01-21 11:00:15 +02:00
Mykhailo Skrypskyi
3551745a48 refactor(common): replace eslint and prettier with oxc toolchain 2026-01-21 10:55:09 +02:00
Kamil Mysliwiec
3d1b44c0ca Merge pull request #16230 from chojs23/fix/console-logger-option
fix(common): Fix skipping maxArrayLength and maxStringLength option
2026-01-21 08:51:41 +01:00
Kamil Mysliwiec
e94951f86b Merge pull request #16227 from nestjs/renovate/apollo-graphql-packages
fix(deps): update apollo graphql packages to v2.13.0
2026-01-21 08:51:23 +01:00
Kamil Mysliwiec
76b4fbed34 Merge pull request #16226 from nestjs/renovate/mongoose-9.x
fix(deps): update dependency mongoose to v9.1.5
2026-01-21 08:51:15 +01:00
neo
979a8e2f04 fix(common): Fix skipping maxArrayLength and maxStringLength option
Fixes #16229
2026-01-21 16:00:28 +09:00
renovate[bot]
5535146f65 fix(deps): update apollo graphql packages to v2.13.0 2026-01-21 00:35:32 +00:00
renovate[bot]
2fa655bbbf fix(deps): update dependency mongoose to v9.1.5 2026-01-20 16:46:06 +00:00
Mykhailo Skrypskyi
46ee1074f1 build: remove unused dependencies 2026-01-20 10:43:51 +02:00
Kamil Mysliwiec
07022aff11 Merge pull request #16220 from nestjs/dependabot/npm_and_yarn/fastify/multipart-9.4.0
chore(deps-dev): bump @fastify/multipart from 9.3.0 to 9.4.0
2026-01-20 09:18:22 +01:00
Kamil Mysliwiec
3459e9b595 Merge pull request #16215 from nestjs/renovate/mercurius-16.x
fix(deps): update dependency mercurius to v16.7.0
2026-01-20 09:06:06 +01:00
Kamil Mysliwiec
e42362edb1 Merge pull request #16217 from nestjs/renovate/typescript-eslint-monorepo
chore(deps): update typescript-eslint monorepo to v8.53.1
2026-01-20 09:00:52 +01:00
dependabot[bot]
c78b7a1d67 chore(deps-dev): bump @fastify/multipart from 9.3.0 to 9.4.0
Bumps [@fastify/multipart](https://github.com/fastify/fastify-multipart) from 9.3.0 to 9.4.0.
- [Release notes](https://github.com/fastify/fastify-multipart/releases)
- [Commits](https://github.com/fastify/fastify-multipart/compare/v9.3.0...v9.4.0)

---
updated-dependencies:
- dependency-name: "@fastify/multipart"
  dependency-version: 9.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-20 00:54:53 +00:00
renovate[bot]
9dd5d650d7 chore(deps): update typescript-eslint monorepo to v8.53.1 2026-01-19 17:49:42 +00:00
renovate[bot]
aca0658100 fix(deps): update dependency mercurius to v16.7.0 2026-01-19 15:55:30 +00:00
Kamil Mysliwiec
c93c247474 Merge pull request #16201 from nestjs/renovate/fastify-5.x
fix(deps): update dependency fastify to v5.7.1
2026-01-18 10:48:13 +01:00
renovate[bot]
4fa9409366 fix(deps): update dependency fastify to v5.7.1 2026-01-16 09:17:26 +00:00
Kamil Mysliwiec
2ab7ba377f Merge pull request #16210 from nestjs/renovate/mongoose-9.x
fix(deps): update dependency mongoose to v9.1.4
2026-01-16 10:15:44 +01:00
renovate[bot]
8ccb55bddc fix(deps): update dependency mongoose to v9.1.4 2026-01-16 09:14:01 +00:00
Kamil Mysliwiec
b94858b4b1 Merge pull request #16211 from nestjs/renovate/mysql2-3.x
fix(deps): update dependency mysql2 to v3.16.1
2026-01-16 10:11:51 +01:00
renovate[bot]
2c95e3a159 fix(deps): update dependency mysql2 to v3.16.1 2026-01-16 08:55:48 +00:00
Kamil Mysliwiec
fc682e4117 Merge pull request #16203 from nestjs/renovate/node-24.x
chore(deps): update dependency @types/node to v24.10.9
2026-01-16 09:53:04 +01:00
renovate[bot]
611bfc46cc chore(deps): update dependency @types/node to v24.10.9 2026-01-16 08:34:33 +00:00
Kamil Mysliwiec
c149138dc0 Merge pull request #16197 from nestjs/dependabot/npm_and_yarn/prettier-3.8.0
chore(deps-dev): bump prettier from 3.7.4 to 3.8.0
2026-01-16 09:32:37 +01:00
Kamil Mysliwiec
184757fbe3 Merge pull request #16200 from nestjs/renovate/nest-monorepo
fix(deps): update nest monorepo
2026-01-16 09:17:06 +01:00
dependabot[bot]
36c064c255 chore(deps-dev): bump prettier from 3.7.4 to 3.8.0
Bumps [prettier](https://github.com/prettier/prettier) from 3.7.4 to 3.8.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.7.4...3.8.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-16 08:14:02 +00:00
Kamil Mysliwiec
9f2a48de3c Merge pull request #16199 from nestjs/renovate/prettier-3.x
chore(deps): update dependency prettier to v3.8.0
2026-01-16 09:12:58 +01:00
Kamil Mysliwiec
b9e56c3978 Merge pull request #16206 from nestjs/dependabot/npm_and_yarn/ioredis-5.9.2
chore(deps-dev): bump ioredis from 5.9.1 to 5.9.2
2026-01-16 09:12:39 +01:00
Kamil Mysliwiec
b73328be85 Merge pull request #16208 from nestjs/dependabot/npm_and_yarn/fastify-5.7.0
chore(deps): bump fastify from 5.6.2 to 5.7.0
2026-01-16 09:12:25 +01:00
Kamil Mysliwiec
b145994021 Merge pull request #16207 from nestjs/dependabot/npm_and_yarn/fast-json-stringify-6.2.0
chore(deps): bump fast-json-stringify from 6.1.1 to 6.2.0
2026-01-16 09:11:47 +01:00
dependabot[bot]
ffddbfe71e chore(deps): bump fastify from 5.6.2 to 5.7.0
Bumps [fastify](https://github.com/fastify/fastify) from 5.6.2 to 5.7.0.
- [Release notes](https://github.com/fastify/fastify/releases)
- [Commits](https://github.com/fastify/fastify/compare/v5.6.2...v5.7.0)

---
updated-dependencies:
- dependency-name: fastify
  dependency-version: 5.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-16 00:53:51 +00:00
dependabot[bot]
60df323ce0 chore(deps): bump fast-json-stringify from 6.1.1 to 6.2.0
Bumps [fast-json-stringify](https://github.com/fastify/fast-json-stringify) from 6.1.1 to 6.2.0.
- [Release notes](https://github.com/fastify/fast-json-stringify/releases)
- [Commits](https://github.com/fastify/fast-json-stringify/compare/v6.1.1...v6.2.0)

---
updated-dependencies:
- dependency-name: fast-json-stringify
  dependency-version: 6.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-16 00:53:26 +00:00
dependabot[bot]
df1f3af2cc chore(deps-dev): bump ioredis from 5.9.1 to 5.9.2
Bumps [ioredis](https://github.com/luin/ioredis) from 5.9.1 to 5.9.2.
- [Release notes](https://github.com/luin/ioredis/releases)
- [Changelog](https://github.com/redis/ioredis/blob/main/CHANGELOG.md)
- [Commits](https://github.com/luin/ioredis/compare/v5.9.1...v5.9.2)

---
updated-dependencies:
- dependency-name: ioredis
  dependency-version: 5.9.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-16 00:53:00 +00:00
som14062005
8fb17f517c fix(common): exclude built-in primitives from strip proto keys
Skip constructor deletion for Date, RegExp, Error, Map, Set, WeakMap, and WeakSet to fix Jest useFakeTimers compatibility. Maintains prototype pollution protection for regular objects.

Fixes #16195
2026-01-16 02:00:15 +05:30
renovate[bot]
939559cd28 fix(deps): update nest monorepo 2026-01-15 20:27:53 +00:00
som14062005
16296b9ce8 fix(common): exclude built-in primitives from strip proto keys
Skip constructor deletion for Date, RegExp, Error, Map, Set, WeakMap, and WeakSet to fix Jest useFakeTimers compatibility. Maintains prototype pollution protection for regular objects.

Fixes #16195
2026-01-15 21:30:09 +05:30
renovate[bot]
64ad1e263e chore(deps): update dependency prettier to v3.8.0 2026-01-15 08:32:56 +00:00
Kamil Myśliwiec
96932ad073 chore(release): publish v11.1.12 release 2026-01-15 09:29:44 +01:00
Kamil Mysliwiec
09e96bdee7 Merge pull request #16187 from iamkanguk97/fix/file-type-under-window-os
fix(common): regression in loading file-type under Windows OS
2026-01-15 09:27:08 +01:00
Kamil Myśliwiec
4fdeb0b504 style: address lint issues 2026-01-15 09:25:17 +01:00
Kamil Mysliwiec
6620c431ea Merge pull request #16192 from nestjs/renovate/node-24.x
chore(deps): update dependency @types/node to v24.10.8
2026-01-14 19:59:32 +01:00
Kamil Mysliwiec
294506171f Merge pull request #16194 from nestjs/renovate/nestjs-swagger-11.x
fix(deps): update dependency @nestjs/swagger to v11.2.5
2026-01-14 19:58:50 +01:00
Kamil Mysliwiec
31fc72a90b Merge pull request #16196 from nestjs/renovate/eslint-plugin-prettier-5.x
chore(deps): update dependency eslint-plugin-prettier to v5.5.5
2026-01-14 19:58:40 +01:00
Kamil Myśliwiec
e5616c2b92 feat: apply instance decorator to all enhancers 2026-01-14 19:58:10 +01:00
renovate[bot]
5237c886d1 chore(deps): update dependency eslint-plugin-prettier to v5.5.5 2026-01-14 14:05:40 +00:00
renovate[bot]
881bc371d6 fix(deps): update dependency @nestjs/swagger to v11.2.5 2026-01-14 09:01:48 +00:00
renovate[bot]
2304a68250 chore(deps): update dependency @types/node to v24.10.8 2026-01-13 16:55:16 +00:00
Kamil Mysliwiec
defe683829 Merge pull request #16186 from nestjs/renovate/mongoose-9.x
fix(deps): update dependency mongoose to v9.1.3
2026-01-12 20:08:21 +01:00
Kamil Mysliwiec
d9f1fea585 Merge pull request #16189 from nestjs/renovate/babel-monorepo
chore(deps): update babel monorepo to v7.28.6
2026-01-12 20:08:14 +01:00
Kamil Mysliwiec
b79d89dd29 Merge pull request #16190 from nestjs/renovate/typescript-eslint-monorepo
chore(deps): update typescript-eslint monorepo to v8.53.0
2026-01-12 20:08:09 +01:00
renovate[bot]
0c9e713f66 chore(deps): update typescript-eslint monorepo to v8.53.0 2026-01-12 18:16:59 +00:00
renovate[bot]
0aeab872c9 chore(deps): update babel monorepo to v7.28.6 2026-01-12 18:16:24 +00:00
renovate[bot]
91ca1f913c fix(deps): update dependency mongoose to v9.1.3 2026-01-12 00:57:03 +00:00
iamkanguk97
52bb09abbf ci: remove custom workflow 2026-01-12 00:31:36 +09:00
iamkanguk97
b41dd24259 ci: disable fail-fast to ensure all platforms are tested 2026-01-12 00:18:38 +09:00
iamkanguk97
a52e60820e fix(common): convert absolute paths to urls for esm loading
Uses pathToFileURL to convert file system paths to proper URLs
before passing to the ESM loader, ensuring cross-platform compatibility.

Fixes #16179
2026-01-12 00:05:45 +09:00
iamkanguk97
c9de047945 ci: add cross-platform testing to prevent platform-specific regressions
This adds GitHub Actions workflow to test on Ubuntu, Windows, and macOS.
This is optional and can be removed if the maintainers prefer.

Related to #16179
2026-01-12 00:02:16 +09:00
Kamil Mysliwiec
caf8487b76 Merge pull request #16183 from nestjs/renovate/node-24.x
chore(deps): update dependency @types/node to v24.10.7
2026-01-11 11:28:47 +01:00
renovate[bot]
8501bb2c0b chore(deps): update dependency @types/node to v24.10.7 2026-01-10 20:35:38 +00:00
Kamil Mysliwiec
a830cedab9 Merge pull request #16182 from nestjs/renovate/node-24.x
chore(deps): update dependency @types/node to v24.10.6
2026-01-10 16:44:03 +01:00
Kamil Mysliwiec
841f150675 Merge pull request #16181 from nestjs/renovate/cache-manager-7.x
fix(deps): update dependency cache-manager to v7.2.8
2026-01-10 16:42:58 +01:00
renovate[bot]
d3761bdb32 chore(deps): update dependency @types/node to v24.10.6 2026-01-10 04:34:24 +00:00
renovate[bot]
6f4da5c41e fix(deps): update dependency cache-manager to v7.2.8 2026-01-09 21:47:47 +00:00
Kamil Mysliwiec
5f431b9f38 Merge pull request #16180 from Tony133/chore/update-license
chore: update license
2026-01-09 19:56:55 +01:00
Tony133
2526ec1f1a chore: update license 2026-01-09 17:16:50 +01:00
Kamil Mysliwiec
55b09b8387 Merge pull request #16174 from nestjs/renovate/commitlint-monorepo
chore(deps): update dependency @commitlint/config-angular to v20.3.1
2026-01-09 13:48:49 +01:00
Kamil Mysliwiec
29228ed9f4 Merge pull request #16176 from nestjs/dependabot/npm_and_yarn/commitlint/config-angular-20.3.1
chore(deps-dev): bump @commitlint/config-angular from 20.3.0 to 20.3.1
2026-01-09 13:48:41 +01:00
renovate[bot]
85030eca5c chore(deps): update dependency @commitlint/config-angular to v20.3.1 2026-01-09 09:49:39 +00:00
dependabot[bot]
15d1e4b103 chore(deps-dev): bump @commitlint/config-angular from 20.3.0 to 20.3.1
Bumps [@commitlint/config-angular](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/config-angular) from 20.3.0 to 20.3.1.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-angular/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v20.3.1/@commitlint/config-angular)

---
updated-dependencies:
- dependency-name: "@commitlint/config-angular"
  dependency-version: 20.3.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-09 09:48:34 +00:00
Kamil Mysliwiec
373b78cfbb Merge pull request #16172 from nestjs/renovate/ioredis-5.x
chore(deps): update dependency ioredis to v5.9.1
2026-01-09 10:47:52 +01:00
Kamil Mysliwiec
eea5c5899c Merge pull request #16175 from nestjs/dependabot/npm_and_yarn/ioredis-5.9.1
chore(deps-dev): bump ioredis from 5.9.0 to 5.9.1
2026-01-09 10:47:34 +01:00
Kamil Mysliwiec
87df305640 Merge pull request #16177 from nestjs/dependabot/npm_and_yarn/commitlint/cli-20.3.1
chore(deps-dev): bump @commitlint/cli from 20.3.0 to 20.3.1
2026-01-09 10:47:18 +01:00
dependabot[bot]
975e6099c2 chore(deps-dev): bump @commitlint/cli from 20.3.0 to 20.3.1
Bumps [@commitlint/cli](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli) from 20.3.0 to 20.3.1.
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v20.3.1/@commitlint/cli)

---
updated-dependencies:
- dependency-name: "@commitlint/cli"
  dependency-version: 20.3.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-09 01:04:38 +00:00
dependabot[bot]
014369029f chore(deps-dev): bump ioredis from 5.9.0 to 5.9.1
Bumps [ioredis](https://github.com/luin/ioredis) from 5.9.0 to 5.9.1.
- [Release notes](https://github.com/luin/ioredis/releases)
- [Changelog](https://github.com/redis/ioredis/blob/main/CHANGELOG.md)
- [Commits](https://github.com/luin/ioredis/compare/v5.9.0...v5.9.1)

---
updated-dependencies:
- dependency-name: ioredis
  dependency-version: 5.9.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-09 01:03:40 +00:00
renovate[bot]
0ae760071d chore(deps): update dependency ioredis to v5.9.1 2026-01-08 13:53:03 +00:00
Kamil Mysliwiec
31de8a1d2d Merge pull request #16170 from nestjs/renovate/body-parser-2.x
chore(deps): update dependency body-parser to v2.2.2
2026-01-07 14:54:42 +01:00
renovate[bot]
4576270535 chore(deps): update dependency body-parser to v2.2.2 2026-01-07 13:51:58 +00:00
Kamil Mysliwiec
16a4d4d6a2 Merge pull request #16162 from nestjs/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-8.52.0
chore(deps-dev): bump @typescript-eslint/eslint-plugin from 8.51.0 to 8.52.0
2026-01-07 09:13:23 +01:00
Kamil Mysliwiec
34d2103468 Merge pull request #16167 from nestjs/renovate/nestjs-swagger-11.x
fix(deps): update dependency @nestjs/swagger to v11.2.4
2026-01-07 09:13:15 +01:00
Kamil Mysliwiec
991d07267e Merge pull request #16168 from nestjs/renovate/graphql-tools-monorepo
fix(deps): update dependency graphql-tools to v9.0.26
2026-01-07 09:13:08 +01:00
Kamil Mysliwiec
a0cd0d543a Merge pull request #16169 from nestjs/renovate/major-graphql-tools-monorepo
fix(deps): update dependency @graphql-tools/utils to v11
2026-01-07 09:13:01 +01:00
Kamil Mysliwiec
a25170d8d6 Merge pull request #16160 from nestjs/renovate/typescript-eslint-monorepo
chore(deps): update typescript-eslint monorepo to v8.52.0
2026-01-07 09:12:50 +01:00
renovate[bot]
af10902bcf fix(deps): update dependency @graphql-tools/utils to v11 2026-01-07 02:04:46 +00:00
renovate[bot]
30670319a8 fix(deps): update dependency graphql-tools to v9.0.26 2026-01-07 02:04:33 +00:00
renovate[bot]
8e6d6b7dfb fix(deps): update dependency @nestjs/swagger to v11.2.4 2026-01-06 20:56:33 +00:00
renovate[bot]
9bcf7049c5 chore(deps): update typescript-eslint monorepo to v8.52.0 2026-01-06 17:35:58 +00:00
dependabot[bot]
92a2ec2402 chore(deps-dev): bump @typescript-eslint/eslint-plugin
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 8.51.0 to 8.52.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.52.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.52.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-06 17:34:32 +00:00
Kamil Mysliwiec
9415f659bd Merge pull request #16165 from nestjs/dependabot/npm_and_yarn/typescript-eslint/parser-8.52.0
chore(deps-dev): bump @typescript-eslint/parser from 8.51.0 to 8.52.0
2026-01-06 18:32:56 +01:00
dependabot[bot]
afefa9050e chore(deps-dev): bump @typescript-eslint/parser from 8.51.0 to 8.52.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.51.0 to 8.52.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.52.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.52.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-06 17:31:53 +00:00
Kamil Mysliwiec
88af6c5428 Merge pull request #16161 from nestjs/dependabot/npm_and_yarn/ws-8.19.0
chore(deps): bump ws from 8.18.3 to 8.19.0
2026-01-06 18:30:57 +01:00
Kamil Mysliwiec
72eec8964e Merge pull request #16164 from nestjs/dependabot/npm_and_yarn/mongoose-9.1.2
chore(deps-dev): bump mongoose from 9.1.1 to 9.1.2
2026-01-06 18:30:43 +01:00
Kamil Mysliwiec
22a5121d9c Merge pull request #16159 from nestjs/renovate/mongoose-9.x
fix(deps): update dependency mongoose to v9.1.2
2026-01-06 18:30:30 +01:00
Kamil Mysliwiec
d2f3a2f7d6 Merge pull request #16166 from nestjs/renovate/supertest-7.x
chore(deps): update dependency supertest to v7.2.2
2026-01-06 18:30:21 +01:00
Kamil Mysliwiec
6de4864790 Merge pull request #16163 from nestjs/dependabot/npm_and_yarn/typescript-eslint-8.52.0
chore(deps-dev): bump typescript-eslint from 8.51.0 to 8.52.0
2026-01-06 18:30:04 +01:00
renovate[bot]
02d2749b04 chore(deps): update dependency supertest to v7.2.2 2026-01-06 09:58:10 +00:00
dependabot[bot]
a9952edff0 chore(deps-dev): bump mongoose from 9.1.1 to 9.1.2
Bumps [mongoose](https://github.com/Automattic/mongoose) from 9.1.1 to 9.1.2.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/9.1.1...9.1.2)

---
updated-dependencies:
- dependency-name: mongoose
  dependency-version: 9.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-06 00:03:27 +00:00
dependabot[bot]
23e13fb7c7 chore(deps-dev): bump typescript-eslint from 8.51.0 to 8.52.0
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.51.0 to 8.52.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.52.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.52.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-06 00:03:05 +00:00
dependabot[bot]
eac120336f chore(deps): bump ws from 8.18.3 to 8.19.0
Bumps [ws](https://github.com/websockets/ws) from 8.18.3 to 8.19.0.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.18.3...8.19.0)

---
updated-dependencies:
- dependency-name: ws
  dependency-version: 8.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-06 00:01:48 +00:00
renovate[bot]
45da564b8b fix(deps): update dependency mongoose to v9.1.2 2026-01-05 17:36:07 +00:00
Kamil Mysliwiec
3df5a1836c Merge pull request #16158 from nestjs/renovate/ioredis-5.x
chore(deps): update dependency ioredis to v5.9.0
2026-01-05 18:33:51 +01:00
renovate[bot]
fb292791cf chore(deps): update dependency ioredis to v5.9.0 2026-01-05 14:43:21 +00:00
Kamil Mysliwiec
33911ead25 Merge pull request #16155 from nestjs/renovate/file-type-21.x
fix(deps): update dependency file-type to v21.3.0
2026-01-04 19:16:54 +01:00
renovate[bot]
8a5be22e94 fix(deps): update dependency file-type to v21.3.0 2026-01-04 01:44:43 +00:00
Kamil Mysliwiec
4500f04525 Merge pull request #16154 from nestjs/renovate/find-my-way-9.x
fix(deps): update dependency find-my-way to v9.4.0
2026-01-03 17:51:30 +01:00
Kamil Mysliwiec
b1edd0872f Merge pull request #16153 from nestjs/renovate/fastify-middie-9.x
chore(deps): update dependency @fastify/middie to v9.1.0
2026-01-03 17:51:25 +01:00
renovate[bot]
73f71c45e8 fix(deps): update dependency find-my-way to v9.4.0 2026-01-03 13:53:40 +00:00
renovate[bot]
936173ddff chore(deps): update dependency @fastify/middie to v9.1.0 2026-01-03 13:53:23 +00:00
Kamil Mysliwiec
295bbe27f0 Merge pull request #16151 from nestjs/renovate/globals-17.x
chore(deps): update dependency globals to v17
2026-01-02 15:19:35 +01:00
renovate[bot]
242e4cef4f chore(deps): update dependency globals to v17 2026-01-01 21:03:51 +00:00
Kamil Mysliwiec
01a14d46d1 Merge pull request #16145 from nestjs/renovate/mongoose-9.x
fix(deps): update dependency mongoose to v9.1.1
2026-01-01 16:32:53 +01:00
Kamil Mysliwiec
fdfa52a2a7 Merge pull request #16149 from nestjs/renovate/commitlint-monorepo
chore(deps): update commitlint monorepo to v20.3.0
2026-01-01 16:31:59 +01:00
Kamil Mysliwiec
f7d8e025d9 Merge pull request #16138 from nestjs/renovate/typescript-eslint-monorepo
chore(deps): update typescript-eslint monorepo to v8.51.0
2026-01-01 16:31:29 +01:00
renovate[bot]
00f6e87586 chore(deps): update commitlint monorepo to v20.3.0 2026-01-01 13:39:30 +00:00
renovate[bot]
112167837e fix(deps): update dependency mongoose to v9.1.1 2025-12-31 14:16:45 +00:00
renovate[bot]
da59d1c39c chore(deps): update typescript-eslint monorepo to v8.51.0 2025-12-31 10:47:44 +00:00
Kamil Mysliwiec
182f97d604 Merge pull request #16146 from miso-kyoungminkim/resolve-dependency
chore: Resolve dependencies
2025-12-31 11:43:37 +01:00
Kamil Mysliwiec
4869827aa0 Merge pull request #16144 from nestjs/dependabot/npm_and_yarn/mongoose-9.1.1
chore(deps-dev): bump mongoose from 9.1.0 to 9.1.1
2025-12-31 11:42:56 +01:00
kyoungminkim
8ead13d4f6 chore: Downgrade sinon-chai version 2025-12-31 13:49:18 +09:00
kyoungminkim
d021321624 chore: Update dependencies 2025-12-31 11:00:00 +09:00
dependabot[bot]
66d5059b80 chore(deps-dev): bump mongoose from 9.1.0 to 9.1.1
Bumps [mongoose](https://github.com/Automattic/mongoose) from 9.1.0 to 9.1.1.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/9.1.0...9.1.1)

---
updated-dependencies:
- dependency-name: mongoose
  dependency-version: 9.1.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-31 00:01:35 +00:00
Kamil Mysliwiec
7a3f5b568f Merge pull request #16141 from nestjs/dependabot/npm_and_yarn/typescript-eslint/parser-8.51.0
chore(deps-dev): bump @typescript-eslint/parser from 8.50.1 to 8.51.0
2025-12-30 10:14:42 +01:00
Kamil Mysliwiec
60355c44e0 Merge pull request #16142 from nestjs/renovate/mongoose-9.x
fix(deps): update dependency mongoose to v9.1.0
2025-12-30 10:14:33 +01:00
renovate[bot]
38e4a826dc fix(deps): update dependency mongoose to v9.1.0 2025-12-30 08:35:04 +00:00
dependabot[bot]
f40895423a chore(deps-dev): bump @typescript-eslint/parser from 8.50.1 to 8.51.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.50.1 to 8.51.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.51.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.51.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 08:34:04 +00:00
Kamil Mysliwiec
ce83c9a6de Merge pull request #16143 from nestjs/dependabot/npm_and_yarn/typescript-eslint-8.51.0
chore(deps-dev): bump typescript-eslint from 8.50.1 to 8.51.0
2025-12-30 09:32:49 +01:00
Kamil Mysliwiec
b0aa22d030 Merge pull request #16140 from nestjs/dependabot/npm_and_yarn/mongoose-9.1.0
chore(deps-dev): bump mongoose from 9.0.2 to 9.1.0
2025-12-30 09:32:40 +01:00
dependabot[bot]
2052855d3f chore(deps-dev): bump typescript-eslint from 8.50.1 to 8.51.0
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.50.1 to 8.51.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.51.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.51.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 00:03:53 +00:00
dependabot[bot]
d858df5dda chore(deps-dev): bump mongoose from 9.0.2 to 9.1.0
Bumps [mongoose](https://github.com/Automattic/mongoose) from 9.0.2 to 9.1.0.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/9.0.2...9.1.0)

---
updated-dependencies:
- dependency-name: mongoose
  dependency-version: 9.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 00:02:36 +00:00
Kamil Mysliwiec
91b97edfda Merge pull request #16137 from nestjs/renovate/nest-monorepo
fix(deps): update nest monorepo to v11.1.11
2025-12-29 18:05:09 +01:00
renovate[bot]
00790a06ff fix(deps): update nest monorepo to v11.1.11 2025-12-29 16:51:16 +00:00
Kamil Mysliwiec
1bbd3ec178 Merge pull request #16136 from nestjs/renovate/nest-monorepo
fix(deps): update dependency @nestjs/platform-ws to v11.1.11
2025-12-29 17:48:48 +01:00
renovate[bot]
1818032838 fix(deps): update dependency @nestjs/platform-ws to v11.1.11 2025-12-29 13:32:37 +00:00
1572 changed files with 28337 additions and 33200 deletions

View File

@@ -1,12 +1,6 @@
version: 2.1
parameters:
check-legacy-node-version:
type: boolean
default: false
legacy-node-version:
type: string
default: '18.20'
maintenance-node-version:
type: string
default: '20.18'
@@ -15,7 +9,7 @@ parameters:
default: '22.11'
current-node-version:
type: string
default: '23.3'
default: '24.1'
aliases:
- &restore-cache
@@ -62,61 +56,36 @@ jobs:
docker:
- image: cimg/node:<< parameters.node-version >>
steps:
- checkout
- *restore-cache
- *install-deps
- *build-packages
- when:
condition:
and:
- equal:
[
'<< parameters.node-version >>',
'<< pipeline.parameters.legacy-node-version >>',
]
- not: << pipeline.parameters.check-legacy-node-version >>
equal:
[
'<< parameters.node-version >>',
'<< pipeline.parameters.maintenance-node-version >>',
]
steps:
- run:
name: Skip
command: |
echo Skipping
name: Test (coverage)
command: npm run test:cov
- run:
name: Collect coverage
command: npm run coverage
- store_artifacts:
path: coverage
- when:
condition:
or:
- not:
equal:
[
'<< parameters.node-version >>',
'<< pipeline.parameters.legacy-node-version >>',
]
- << pipeline.parameters.check-legacy-node-version >>
not:
equal:
[
'<< parameters.node-version >>',
'<< pipeline.parameters.maintenance-node-version >>',
]
steps:
- checkout
- *restore-cache
- *install-deps
- *build-packages
- when:
condition:
equal:
[
'<< parameters.node-version >>',
'<< pipeline.parameters.maintenance-node-version >>',
]
steps:
- run:
name: Test (coverage)
command: npm run test:cov
- run:
name: Collect coverage
command: npm run coverage
- store_artifacts:
path: coverage
- when:
condition:
not:
equal:
[
'<< parameters.node-version >>',
'<< pipeline.parameters.maintenance-node-version >>',
]
steps:
- *run-unit-tests
- *run-unit-tests
lint:
working_directory: ~/nest
@@ -183,7 +152,6 @@ jobs:
name: Build all samples
command: npm run build:samples
workflows:
build-and-test:
jobs:
@@ -195,7 +163,6 @@ workflows:
parameters:
node-version:
[
'<< pipeline.parameters.legacy-node-version >>',
'<< pipeline.parameters.maintenance-node-version >>',
'<< pipeline.parameters.active-node-version >>',
'<< pipeline.parameters.current-node-version >>',
@@ -209,4 +176,3 @@ workflows:
- samples:
requires:
- build

View File

@@ -1,13 +0,0 @@
#!/usr/bin/env bash
set -e
cd "$(dirname "$0")"
# based on https://medium.com/@felipedutratine/intelligent-benchmark-with-wrk-163986c1587f
cd /tmp/
sudo apt-get install build-essential libssl-dev git -y
git clone --depth=1 https://github.com/wg/wrk.git wrk
cd wrk
sudo make
# move the executable to somewhere in your PATH, ex:
sudo cp wrk /usr/local/bin

View File

@@ -116,7 +116,6 @@ We cannot accept code without this.
1. In GitHub, send a pull request to `nestjs:master`.
- If we suggest changes then:
- Make the required updates.
- Re-run the Nest test suites to ensure tests are still passing.
- Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
@@ -159,7 +158,7 @@ from the main (upstream) repository:
## <a name="development"></a> Development Setup
You will need [Node.js](https://nodejs.org) version >= 10.13.0 (except for v13).
You will need [Node.js](https://nodejs.org) version >= 20.
1. After cloning the repo, run:
@@ -322,8 +321,10 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
<!-- [coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md -->
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
<!-- [individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html -->
<!-- [corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html -->
[dev-doc]: https://github.com/nestjs/nest/blob/master/docs/DEVELOPER.md
[github]: https://github.com/nestjs/nest
[stackoverflow]: https://stackoverflow.com/questions/tagged/nestjs

View File

@@ -1,6 +1,6 @@
(The MIT License)
Copyright (c) 2017-2025 Kamil Mysliwiec <https://kamilmysliwiec.com>
Copyright (c) 2017-present Kamil Mysliwiec <https://kamilmysliwiec.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -63,6 +63,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
<td><a href="https://microsoft.com/" target="_blank"><img src="https://nestjs.com/img/logos/microsoft-logo.png" width="180" valign="middle" /></a></td>
<td><a href="https://mojam.co" target="_blank"><img src="https://nestjs.com/img/logos/mojam-logo.png" width="80" valign="middle" /></a></td>
<td><a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td>
<td><a href="https://serpapi.com/" target="_blank"><img src="https://nestjs.com/img/logos/serpapi-logo.png" width="150" valign="middle" /></a></td>
</tr>
</table>

View File

@@ -1,88 +0,0 @@
-----------------------
express
-----------------------
Running 10s test @ http://localhost:3000
1024 connections
┌─────────┬───────┬───────┬───────┬────────┬──────────┬──────────┬────────┐
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
├─────────┼───────┼───────┼───────┼────────┼──────────┼──────────┼────────┤
│ Latency │ 55 ms │ 58 ms │ 91 ms │ 138 ms │ 61.88 ms │ 23.95 ms │ 747 ms │
└─────────┴───────┴───────┴───────┴────────┴──────────┴──────────┴────────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬──────────┬─────────┬─────────┐
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼─────────┼─────────┤
│ Req/Sec │ 8407 │ 8407 │ 17407 │ 17743 │ 16454.41 │ 2716.94 │ 8402 │
├───────────┼─────────┼─────────┼─────────┼─────────┼──────────┼─────────┼─────────┤
│ Bytes/Sec │ 1.81 MB │ 1.81 MB │ 3.74 MB │ 3.81 MB │ 3.54 MB │ 584 kB │ 1.81 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴──────────┴─────────┴─────────┘
Req/Bytes counts sampled once per second.
165k requests in 10.17s, 35.4 MB read
-----------------------
nest (with "@nestjs/platform-express")
-----------------------
Running 10s test @ http://localhost:3000
1024 connections
┌─────────┬───────┬───────┬───────┬───────┬──────────┬──────────┬────────┐
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
├─────────┼───────┼───────┼───────┼───────┼──────────┼──────────┼────────┤
│ Latency │ 61 ms │ 64 ms │ 71 ms │ 94 ms │ 65.44 ms │ 17.35 ms │ 325 ms │
└─────────┴───────┴───────┴───────┴───────┴──────────┴──────────┴────────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬────────┬─────────┐
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼────────┼─────────┤
│ Req/Sec │ 14183 │ 14183 │ 15767 │ 15991 │ 15640 │ 501.13 │ 14182 │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼────────┼─────────┤
│ Bytes/Sec │ 3.06 MB │ 3.06 MB │ 3.41 MB │ 3.45 MB │ 3.38 MB │ 108 kB │ 3.06 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴────────┴─────────┘
Req/Bytes counts sampled once per second.
156k requests in 10.24s, 33.8 MB read
-----------------------
fastify
-----------------------
Running 10s test @ http://localhost:3000
1024 connections
┌─────────┬───────┬───────┬───────┬───────┬──────────┬──────────┬─────────┐
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
├─────────┼───────┼───────┼───────┼───────┼──────────┼──────────┼─────────┤
│ Latency │ 27 ms │ 30 ms │ 39 ms │ 78 ms │ 31.62 ms │ 26.59 ms │ 1232 ms │
└─────────┴───────┴───────┴───────┴───────┴──────────┴──────────┴─────────┘
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Req/Sec │ 19935 │ 19935 │ 33247 │ 34111 │ 32030.4 │ 4103.84 │ 19931 │
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Bytes/Sec │ 3.03 MB │ 3.03 MB │ 5.05 MB │ 5.19 MB │ 4.87 MB │ 624 kB │ 3.03 MB │
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
Req/Bytes counts sampled once per second.
320k requests in 10.18s, 48.7 MB read
-----------------------
nest (with "@nestjs/platform-fastify")
-----------------------
Running 10s test @ http://localhost:3000
1024 connections
┌─────────┬───────┬───────┬───────┬───────┬──────────┬──────────┬────────┐
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
├─────────┼───────┼───────┼───────┼───────┼──────────┼──────────┼────────┤
│ Latency │ 31 ms │ 33 ms │ 38 ms │ 52 ms │ 34.41 ms │ 11.73 ms │ 245 ms │
└─────────┴───────┴───────┴───────┴───────┴──────────┴──────────┴────────┘
┌───────────┬─────────┬─────────┬────────┬─────────┬─────────┬─────────┬─────────┐
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
├───────────┼─────────┼─────────┼────────┼─────────┼─────────┼─────────┼─────────┤
│ Req/Sec │ 24911 │ 24911 │ 30031 │ 30335 │ 29470.4 │ 1564.48 │ 24907 │
├───────────┼─────────┼─────────┼────────┼─────────┼─────────┼─────────┼─────────┤
│ Bytes/Sec │ 3.81 MB │ 3.81 MB │ 4.6 MB │ 4.64 MB │ 4.51 MB │ 239 kB │ 3.81 MB │
└───────────┴─────────┴─────────┴────────┴─────────┴─────────┴─────────┴─────────┘
Req/Bytes counts sampled once per second.
295k requests in 10.17s, 45.1 MB read

View File

@@ -1,7 +0,0 @@
'use strict';
const express = require('express');
const app = express();
app.get('/', async (req, res) => res.send('Hello world'));
app.listen(3000);

View File

@@ -1,7 +0,0 @@
'use strict';
const fastify = require('fastify')();
fastify.get('/', async (req, reply) => reply.send('Hello world'));
fastify.listen({
port: 3000
});

View File

@@ -1,14 +0,0 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const core_1 = require('@nestjs/core');
const fastify_platform_1 = require('@nestjs/platform-fastify');
const app_module_1 = require('./nest/app.module');
core_1.NestFactory.create(
app_module_1.AppModule,
new fastify_platform_1.FastifyAdapter(),
{
logger: false,
bodyParser: false,
},
).then(app => app.listen(3000));
//# sourceMappingURL=main.js.map

View File

@@ -1,9 +0,0 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const core_1 = require('@nestjs/core');
const app_module_1 = require('./nest/app.module');
core_1.NestFactory.create(app_module_1.AppModule, {
logger: false,
bodyParser: false,
}).then(app => app.listen(3000));
//# sourceMappingURL=main.js.map

View File

@@ -1,3 +0,0 @@
export declare class AppController {
root(): string;
}

View File

@@ -1,47 +0,0 @@
'use strict';
var __decorate =
(this && this.__decorate) ||
function(decorators, target, key, desc) {
var c = arguments.length,
r =
c < 3
? target
: desc === null
? (desc = Object.getOwnPropertyDescriptor(target, key))
: desc,
d;
if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function')
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if ((d = decorators[i]))
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata =
(this && this.__metadata) ||
function(k, v) {
if (typeof Reflect === 'object' && typeof Reflect.metadata === 'function')
return Reflect.metadata(k, v);
};
Object.defineProperty(exports, '__esModule', { value: true });
const common_1 = require('@nestjs/common');
let AppController = class AppController {
root() {
return 'Hello world!';
}
};
__decorate(
[
common_1.Get(),
__metadata('design:type', Function),
__metadata('design:paramtypes', []),
__metadata('design:returntype', String),
],
AppController.prototype,
'root',
null,
);
AppController = __decorate([common_1.Controller()], AppController);
exports.AppController = AppController;
//# sourceMappingURL=app.controller.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"app.controller.js","sourceRoot":"","sources":["../src/app.controller.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,2CAAiD;AAGjD,IAAa,aAAa,GAA1B,MAAa,aAAa;IAExB,IAAI;QACF,OAAO,cAAc,CAAA;IACvB,CAAC;CACF,CAAA;AAHC;IADC,YAAG,EAAE;;;;yCAGL;AAJU,aAAa;IADzB,mBAAU,EAAE;GACA,aAAa,CAKzB;AALY,sCAAa"}

View File

@@ -1 +0,0 @@
export declare class AppModule {}

View File

@@ -1,20 +0,0 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
const common_1 = require("@nestjs/common");
const app_controller_1 = require("./app.controller");
let AppModule = class AppModule {
};
AppModule = __decorate([
common_1.Module({
imports: [],
controllers: [app_controller_1.AppController],
})
], AppModule);
exports.AppModule = AppModule;
//# sourceMappingURL=app.module.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;AAAA,2CAAwC;AACxC,qDAAiD;AAMjD,IAAa,SAAS,GAAtB,MAAa,SAAS;CAAG,CAAA;AAAZ,SAAS;IAJrB,eAAM,CAAC;QACN,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,CAAC,8BAAa,CAAC;KAC7B,CAAC;GACW,SAAS,CAAG;AAAZ,8BAAS"}

View File

@@ -1 +0,0 @@
export {};

View File

@@ -1 +0,0 @@
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAC3C,6CAAyC;AAEzC,KAAK,UAAU,SAAS;IACtB,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,sBAAS,CAAC,CAAC;IAChD,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AACD,SAAS,EAAE,CAAC"}

View File

@@ -38,18 +38,18 @@ export default tseslint.config(
'@typescript-eslint/no-require-imports': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'warn',
"@typescript-eslint/no-misused-promises": [
"error",
'@typescript-eslint/no-misused-promises': [
'error',
{
"checksVoidReturn": false,
"checksConditionals": false
}
checksVoidReturn: false,
checksConditionals: false,
},
],
"@typescript-eslint/require-await": "off",
'@typescript-eslint/require-await': 'off',
'@typescript-eslint/prefer-promise-reject-errors': 'off',
'@typescript-eslint/no-base-to-string': 'off',
'@typescript-eslint/unbound-method': 'off',
'@typescript-eslint/only-throw-error': 'off',
},
},
);
);

View File

@@ -1,16 +0,0 @@
'use strict';
/**
* Load the TypeScript compiler, then load the TypeScript gulpfile which simply loads all
* the tasks. The tasks are really inside tools/gulp/tasks.
*/
const path = require('path');
const projectDir = __dirname;
const tsconfigPath = path.join(projectDir, 'tools/gulp/tsconfig.json');
require('ts-node').register({
project: tsconfigPath
});
require('./tools/gulp/gulpfile');

13
gulpfile.mjs Normal file
View File

@@ -0,0 +1,13 @@
/**
* Load the TypeScript compiler, then load the TypeScript gulpfile which simply loads all
* the tasks. The tasks are really inside tools/gulp/tasks.
*/
import { register } from 'node:module';
import { pathToFileURL } from 'node:url';
register('ts-node/esm', pathToFileURL('./'), {
data: { project: './tools/gulp/tsconfig.json' },
});
await import('./tools/gulp/gulpfile.ts');

View File

@@ -1,7 +0,0 @@
export const mochaHooks = (): Mocha.RootHookObject => {
return {
async beforeAll(this: Mocha.Context) {
await import('reflect-metadata');
},
};
};

View File

@@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common';
import { FooService } from './foo.service';
import { FooService } from './foo.service.js';
@Injectable()
export class BarService {

View File

@@ -1,17 +1,11 @@
import { Test } from '@nestjs/testing';
import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
import * as sinon from 'sinon';
import { BarService } from '../src/bar.service';
import { FooService } from '../src/foo.service';
chai.use(chaiAsPromised);
const { expect } = chai;
import { BarService } from '../src/bar.service.js';
import { FooService } from '../src/foo.service.js';
describe('Auto-Mocking Bar Deps', () => {
let service: BarService;
let fooService: FooService;
const stub = sinon.stub();
const stub = vi.fn();
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
providers: [BarService],
@@ -23,12 +17,12 @@ describe('Auto-Mocking Bar Deps', () => {
});
it('should be defined', () => {
expect(service).not.to.be.undefined;
expect(fooService).not.to.be.undefined;
expect(service).not.toBeUndefined();
expect(fooService).not.toBeUndefined();
});
it('should call bar.bar', () => {
service.bar();
expect(stub.called);
expect(stub).toHaveBeenCalled();
});
});
@@ -39,23 +33,25 @@ describe('Auto-Mocking with token in factory', () => {
})
.useMocker(token => {
if (token === FooService) {
return { foo: sinon.stub };
return { foo: vi.fn() };
}
})
.compile();
const service = moduleRef.get(BarService);
const fooServ = moduleRef.get<{ foo: sinon.SinonStub }>(FooService as any);
const fooServ = moduleRef.get<{ foo: ReturnType<typeof vi.fn> }>(
FooService as any,
);
service.bar();
expect(fooServ.foo.called);
expect(fooServ.foo).toHaveBeenCalled();
});
it('cannot mock the dependencies', async () => {
const moduleRef = Test.createTestingModule({
providers: [BarService],
}).useMocker(token => {
if (token === FooService.name + 'something that fails the token') {
return { foo: sinon.stub };
return { foo: vi.fn() };
}
}).compile;
expect(moduleRef()).to.eventually.throw();
await expect(moduleRef()).rejects.toThrow();
});
});

View File

@@ -1,13 +1,15 @@
{
"compilerOptions": {
"types": ["vitest/globals"],
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "ES2021",
"target": "ES2023",
"sourceMap": true,
"allowJs": true,
"strictNullChecks": true,

View File

@@ -1,7 +1,7 @@
import { NestExpressApplication } from '@nestjs/platform-express';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
describe('Express Cors', () => {
let app: NestExpressApplication;
@@ -25,7 +25,7 @@ describe('Express Cors', () => {
];
describe('Dynamic config', () => {
describe('enableCors', () => {
before(async () => {
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
@@ -66,13 +66,13 @@ describe('Express Cors', () => {
.expect('content-length', '0');
});
after(async () => {
afterAll(async () => {
await app.close();
});
});
describe('Application Options', () => {
before(async () => {
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
@@ -114,14 +114,14 @@ describe('Express Cors', () => {
.expect('content-length', '0');
});
after(async () => {
afterAll(async () => {
await app.close();
});
});
});
describe('Static config', () => {
describe('enableCors', () => {
before(async () => {
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
@@ -141,14 +141,14 @@ describe('Express Cors', () => {
.expect('access-control-expose-headers', 'foo,bar')
.expect('content-length', '0');
});
});
after(async () => {
await app.close();
afterAll(async () => {
await app.close();
});
});
describe('Application Options', () => {
before(async () => {
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
@@ -169,7 +169,7 @@ describe('Express Cors', () => {
.expect('content-length', '0');
});
after(async () => {
afterAll(async () => {
await app.close();
});
});

View File

@@ -3,8 +3,8 @@ import {
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
describe.skip('Fastify Cors', () => {
let app: NestFastifyApplication;
@@ -28,7 +28,7 @@ describe.skip('Fastify Cors', () => {
];
describe('Dynamic config', () => {
describe('enableCors', () => {
before(async () => {
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
@@ -73,13 +73,13 @@ describe.skip('Fastify Cors', () => {
.expect('content-length', '0');
});
after(async () => {
afterAll(async () => {
await app.close();
});
});
describe('Application Options', () => {
before(async () => {
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
@@ -124,7 +124,7 @@ describe.skip('Fastify Cors', () => {
.expect('content-length', '0');
});
after(async () => {
afterAll(async () => {
await app.close();
});
});
@@ -132,7 +132,7 @@ describe.skip('Fastify Cors', () => {
describe('Static config', () => {
describe('enableCors', () => {
before(async () => {
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
@@ -154,14 +154,14 @@ describe.skip('Fastify Cors', () => {
.expect('access-control-expose-headers', 'foo,bar')
.expect('content-length', '0');
});
});
after(async () => {
await app.close();
afterAll(async () => {
await app.close();
});
});
describe('Application Options', () => {
before(async () => {
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
}).compile();
@@ -184,10 +184,10 @@ describe.skip('Fastify Cors', () => {
.expect('access-control-expose-headers', 'foo,bar')
.expect('content-length', '0');
});
});
after(async () => {
await app.close();
afterAll(async () => {
await app.close();
});
});
});
});

View File

@@ -1,5 +1,5 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppController } from './app.controller.js';
@Module({
controllers: [AppController],

View File

@@ -1,13 +1,15 @@
{
"compilerOptions": {
"types": ["vitest/globals"],
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "ES2021",
"target": "ES2023",
"sourceMap": true,
"allowJs": true,
"strictNullChecks": true,

View File

@@ -1,9 +1,8 @@
import { Test, TestingModule } from '@nestjs/testing';
import { DiscoveryService } from '@nestjs/core';
import { expect } from 'chai';
import { AppModule } from '../src/app.module';
import { WebhooksExplorer } from '../src/webhooks.explorer';
import { NonAppliedDecorator } from '../src/decorators/non-applied.decorator';
import { Test, TestingModule } from '@nestjs/testing';
import { AppModule } from '../src/app.module.js';
import { NonAppliedDecorator } from '../src/decorators/non-applied.decorator.js';
import { WebhooksExplorer } from '../src/webhooks.explorer.js';
describe('DiscoveryModule', () => {
let moduleRef: TestingModule;
@@ -14,10 +13,14 @@ describe('DiscoveryModule', () => {
}).compile();
});
afterEach(async () => {
await moduleRef.close();
});
it('should discover all providers & handlers with corresponding annotations', async () => {
const webhooksExplorer = moduleRef.get(WebhooksExplorer);
expect(webhooksExplorer.getWebhooks()).to.be.eql([
expect(webhooksExplorer.getWebhooks()).toEqual([
{
handlers: [
{
@@ -45,7 +48,7 @@ describe('DiscoveryModule', () => {
const providers = discoveryService.getProviders({
metadataKey: NonAppliedDecorator.KEY,
});
expect(providers).to.be.eql([]);
expect(providers).toEqual([]);
});
it('should return an empty array if no controllers were found for a given discoverable decorator', () => {
@@ -54,6 +57,6 @@ describe('DiscoveryModule', () => {
const controllers = discoveryService.getControllers({
metadataKey: NonAppliedDecorator.KEY,
});
expect(controllers).to.be.eql([]);
expect(controllers).toEqual([]);
});
});

View File

@@ -1,7 +1,7 @@
import { Module } from '@nestjs/common';
import { DiscoveryModule } from '@nestjs/core';
import { MyWebhookModule } from './my-webhook/my-webhook.module';
import { WebhooksExplorer } from './webhooks.explorer';
import { MyWebhookModule } from './my-webhook/my-webhook.module.js';
import { WebhooksExplorer } from './webhooks.explorer.js';
@Module({
imports: [MyWebhookModule, DiscoveryModule],

View File

@@ -1,4 +1,4 @@
import { Webhook, WebhookHandler } from '../decorators/webhook.decorators';
import { Webhook, WebhookHandler } from '../decorators/webhook.decorators.js';
@Webhook({ name: 'cleanup' })
export class CleanupWebhook {

View File

@@ -1,4 +1,4 @@
import { Webhook, WebhookHandler } from '../decorators/webhook.decorators';
import { Webhook, WebhookHandler } from '../decorators/webhook.decorators.js';
@Webhook({ name: 'flush' })
export class FlushWebhook {

View File

@@ -1,6 +1,6 @@
import { Module } from '@nestjs/common';
import { CleanupWebhook } from './cleanup.webhook';
import { FlushWebhook } from './flush.webhook';
import { CleanupWebhook } from './cleanup.webhook.js';
import { FlushWebhook } from './flush.webhook.js';
@Module({ providers: [CleanupWebhook, FlushWebhook] })
export class MyWebhookModule {}

View File

@@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common';
import { DiscoveryService, MetadataScanner } from '@nestjs/core';
import { Webhook, WebhookHandler } from './decorators/webhook.decorators';
import { Webhook, WebhookHandler } from './decorators/webhook.decorators.js';
@Injectable()
export class WebhooksExplorer {

View File

@@ -1,13 +1,15 @@
{
"compilerOptions": {
"types": ["vitest/globals"],
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "ES2021",
"target": "ES2023",
"sourceMap": true,
"allowJs": true,
"strictNullChecks": true,

View File

@@ -25,7 +25,7 @@ services:
- "9001:9001"
restart: always
mysql:
image: mysql:9.5.0
image: mysql:9.6.0
environment:
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: root

View File

@@ -1,7 +1,7 @@
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
describe('GraphQL - Code-first', () => {
let app: INestApplication;

View File

@@ -1,7 +1,7 @@
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
describe('GraphQL - Guards', () => {
let app: INestApplication;

View File

@@ -1,7 +1,7 @@
import { INestApplication, ValidationPipe } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
describe('GraphQL Pipes', () => {
let app: INestApplication;

View File

@@ -2,7 +2,7 @@ import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';
import { RecipesModule } from './recipes/recipes.module';
import { RecipesModule } from './recipes/recipes.module.js';
@Module({
imports: [

View File

@@ -1,6 +1,6 @@
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { AppModule } from './app.module.js';
async function bootstrap() {
const app = await NestFactory.create(AppModule);

View File

@@ -1,9 +1,9 @@
import { Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
import { UnauthorizedFilter } from '../common/filters/unauthorized.filter';
import { DateScalar } from '../common/scalars/date.scalar';
import { RecipesResolver } from './recipes.resolver';
import { RecipesService } from './recipes.service';
import { UnauthorizedFilter } from '../common/filters/unauthorized.filter.js';
import { DateScalar } from '../common/scalars/date.scalar.js';
import { RecipesResolver } from './recipes.resolver.js';
import { RecipesService } from './recipes.service.js';
@Module({
providers: [

View File

@@ -1,12 +1,12 @@
import { NotFoundException, UseGuards, UseInterceptors } from '@nestjs/common';
import { Args, Mutation, Query, Resolver, Subscription } from '@nestjs/graphql';
import { PubSub } from 'graphql-subscriptions';
import { AuthGuard } from '../common/guards/auth.guard';
import { DataInterceptor } from '../common/interceptors/data.interceptor';
import { NewRecipeInput } from './dto/new-recipe.input';
import { RecipesArgs } from './dto/recipes.args';
import { Recipe } from './models/recipe';
import { RecipesService } from './recipes.service';
import { AuthGuard } from '../common/guards/auth.guard.js';
import { DataInterceptor } from '../common/interceptors/data.interceptor.js';
import { NewRecipeInput } from './dto/new-recipe.input.js';
import { RecipesArgs } from './dto/recipes.args.js';
import { Recipe } from './models/recipe.js';
import { RecipesService } from './recipes.service.js';
const pubSub = new PubSub();

View File

@@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common';
import { NewRecipeInput } from './dto/new-recipe.input';
import { RecipesArgs } from './dto/recipes.args';
import { Recipe } from './models/recipe';
import { NewRecipeInput } from './dto/new-recipe.input.js';
import { RecipesArgs } from './dto/recipes.args.js';
import { Recipe } from './models/recipe.js';
@Injectable()
export class RecipesService {

View File

@@ -1,13 +1,15 @@
{
"compilerOptions": {
"types": ["vitest/globals"],
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "ES2021",
"target": "ES2023",
"sourceMap": true,
"allowJs": true,
"strictNullChecks": true,

View File

@@ -1,7 +1,7 @@
import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import * as request from 'supertest';
import { AsyncClassApplicationModule } from '../src/async-options-class.module';
import request from 'supertest';
import { AsyncClassApplicationModule } from '../src/async-options-class.module.js';
describe('GraphQL (async class)', () => {
let app: INestApplication;

View File

@@ -1,7 +1,7 @@
import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import * as request from 'supertest';
import { AsyncExistingApplicationModule } from '../src/async-options-existing.module';
import request from 'supertest';
import { AsyncExistingApplicationModule } from '../src/async-options-existing.module.js';
describe('GraphQL (async existing)', () => {
let app: INestApplication;

View File

@@ -1,7 +1,7 @@
import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import * as request from 'supertest';
import { AsyncApplicationModule } from '../src/async-options.module';
import request from 'supertest';
import { AsyncApplicationModule } from '../src/async-options.module.js';
describe('GraphQL (async configuration)', () => {
let app: INestApplication;

View File

@@ -2,11 +2,10 @@ import { ApolloDriver } from '@nestjs/apollo';
import { INestApplication } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import { join } from 'path';
import * as request from 'supertest';
import { CatsRequestScopedService } from '../src/cats/cats-request-scoped.service';
import { CatsModule } from '../src/cats/cats.module';
import request from 'supertest';
import { CatsRequestScopedService } from '../src/cats/cats-request-scoped.service.js';
import { CatsModule } from '../src/cats/cats.module.js';
describe('GraphQL request scoped', () => {
let app: INestApplication;
@@ -17,7 +16,9 @@ describe('GraphQL request scoped', () => {
CatsModule.enableRequestScope(),
GraphQLModule.forRoot({
driver: ApolloDriver,
typePaths: [join(__dirname, '..', 'src', '**', '*.graphql')],
typePaths: [
join(import.meta.dirname, '..', 'src', '**', '*.graphql'),
],
}),
],
}).compile();
@@ -53,7 +54,7 @@ describe('GraphQL request scoped', () => {
});
it(`should create resolver for each incoming request`, () => {
expect(CatsRequestScopedService.COUNTER).to.be.eql(3);
expect(CatsRequestScopedService.COUNTER).toEqual(3);
});
afterEach(async () => {

View File

@@ -1,7 +1,7 @@
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
describe('GraphQL', () => {
let app: INestApplication;

View File

@@ -2,7 +2,7 @@ import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';
import { CatsModule } from './cats/cats.module';
import { CatsModule } from './cats/cats.module.js';
@Module({
imports: [
@@ -10,7 +10,7 @@ import { CatsModule } from './cats/cats.module';
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
includeStacktraceInErrorResponses: true,
typePaths: [join(__dirname, '**', '*.graphql')],
typePaths: [join(import.meta.dirname, '**', '*.graphql')],
}),
],
})

View File

@@ -2,12 +2,12 @@ import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GqlOptionsFactory, GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';
import { CatsModule } from './cats/cats.module';
import { CatsModule } from './cats/cats.module.js';
class ConfigService implements GqlOptionsFactory {
createGqlOptions(): ApolloDriverConfig {
return {
typePaths: [join(__dirname, '**', '*.graphql')],
typePaths: [join(import.meta.dirname, '**', '*.graphql')],
};
}
}

View File

@@ -1,9 +1,9 @@
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { CatsModule } from './cats/cats.module';
import { ConfigModule } from './config.module';
import { ConfigService } from './config.service';
import { CatsModule } from './cats/cats.module.js';
import { ConfigModule } from './config.module.js';
import { ConfigService } from './config.service.js';
@Module({
imports: [

View File

@@ -2,7 +2,7 @@ import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';
import { CatsModule } from './cats/cats.module';
import { CatsModule } from './cats/cats.module.js';
@Module({
imports: [
@@ -10,7 +10,7 @@ import { CatsModule } from './cats/cats.module';
GraphQLModule.forRootAsync<ApolloDriverConfig>({
driver: ApolloDriver,
useFactory: async () => ({
typePaths: [join(__dirname, '**', '*.graphql')],
typePaths: [join(import.meta.dirname, '**', '*.graphql')],
}),
}),
],

View File

@@ -1,5 +1,5 @@
import { Injectable, Scope } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';
import { Cat } from './interfaces/cat.interface.js';
@Injectable({ scope: Scope.REQUEST })
export class CatsRequestScopedService {

View File

@@ -1,7 +1,7 @@
import { DynamicModule, Module, Scope } from '@nestjs/common';
import { CatsRequestScopedService } from './cats-request-scoped.service';
import { CatsResolvers } from './cats.resolvers';
import { CatsService } from './cats.service';
import { CatsRequestScopedService } from './cats-request-scoped.service.js';
import { CatsResolvers } from './cats.resolvers.js';
import { CatsService } from './cats.service.js';
@Module({
providers: [CatsService, CatsResolvers],

View File

@@ -1,9 +1,9 @@
import { ParseIntPipe, UseGuards } from '@nestjs/common';
import { Args, Mutation, Query, Resolver, Subscription } from '@nestjs/graphql';
import { PubSub } from 'graphql-subscriptions';
import { CatsGuard } from './cats.guard';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';
import { CatsGuard } from './cats.guard.js';
import { CatsService } from './cats.service.js';
import { Cat } from './interfaces/cat.interface.js';
const pubSub = new PubSub();

View File

@@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';
import { Cat } from './interfaces/cat.interface.js';
@Injectable()
export class CatsService {

View File

@@ -1,5 +1,5 @@
import { Module } from '@nestjs/common';
import { ConfigService } from './config.service';
import { ConfigService } from './config.service.js';
@Module({
providers: [ConfigService],

View File

@@ -6,7 +6,7 @@ import { join } from 'path';
export class ConfigService implements GqlOptionsFactory {
createGqlOptions(): GqlModuleOptions {
return {
typePaths: [join(__dirname, '**', '*.graphql')],
typePaths: [join(import.meta.dirname, '**', '*.graphql')],
};
}
}

View File

@@ -1,5 +1,5 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { AppModule } from './app.module.js';
async function bootstrap() {
const app = await NestFactory.create(AppModule);

View File

@@ -1,13 +1,15 @@
{
"compilerOptions": {
"types": ["vitest/globals"],
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "ES2021",
"target": "ES2023",
"sourceMap": true,
"allowJs": true,
"strictNullChecks": true,

View File

@@ -4,10 +4,9 @@ import {
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import { RawServerDefault } from 'fastify';
import * as request from 'supertest';
import { ErrorsController } from '../src/errors/errors.controller';
import request from 'supertest';
import { ErrorsController } from '../src/errors/errors.controller.js';
describe('Error messages', () => {
let server: RawServerDefault;
@@ -82,14 +81,12 @@ describe('Error messages', () => {
url: '/sync',
})
.then(({ payload, statusCode }) => {
expect(statusCode).to.equal(HttpStatus.BAD_REQUEST);
expect(payload).to.equal(
JSON.stringify({
statusCode: 400,
error: 'Bad Request',
message: 'Integration test',
}),
);
expect(statusCode).toBe(HttpStatus.BAD_REQUEST);
expect(JSON.parse(payload)).toEqual({
statusCode: 400,
error: 'Bad Request',
message: 'Integration test',
});
});
});
@@ -97,17 +94,15 @@ describe('Error messages', () => {
return app
.inject({
method: 'GET',
url: '/sync',
url: '/async',
})
.then(({ payload, statusCode }) => {
expect(statusCode).to.equal(HttpStatus.BAD_REQUEST);
expect(payload).to.equal(
JSON.stringify({
statusCode: 400,
error: 'Bad Request',
message: 'Integration test',
}),
);
expect(statusCode).toBe(HttpStatus.BAD_REQUEST);
expect(JSON.parse(payload)).toEqual({
statusCode: 400,
error: 'Bad Request',
message: 'Integration test',
});
});
});
@@ -118,13 +113,11 @@ describe('Error messages', () => {
url: '/unexpected-error',
})
.then(({ payload, statusCode }) => {
expect(statusCode).to.equal(HttpStatus.INTERNAL_SERVER_ERROR);
expect(payload).to.equal(
JSON.stringify({
statusCode: 500,
message: 'Internal server error',
}),
);
expect(statusCode).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(JSON.parse(payload)).toEqual({
statusCode: 500,
message: 'Internal server error',
});
});
});

View File

@@ -12,8 +12,8 @@ import {
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
const RETURN_VALUE = 'test';
const MIDDLEWARE_VALUE = 'middleware';

View File

@@ -8,8 +8,8 @@ import {
RequestMethod,
} from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
const RETURN_VALUE = 'test';
const MIDDLEWARE_VALUE = 'middleware';

View File

@@ -1,10 +1,10 @@
import { INestApplication } from '@nestjs/common';
import { ExpressAdapter } from '@nestjs/platform-express';
import { Test } from '@nestjs/testing';
import * as express from 'express';
import * as request from 'supertest';
import express from 'express';
import request from 'supertest';
import { App } from 'supertest/types';
import { AppModule } from '../src/app.module';
import { AppModule } from '../src/app.module.js';
describe('Hello world (express instance)', () => {
let server: App;

View File

@@ -1,9 +1,9 @@
import { INestApplication } from '@nestjs/common';
import { ExpressAdapter } from '@nestjs/platform-express';
import { Test } from '@nestjs/testing';
import * as express from 'express';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import express from 'express';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
describe('Hello world (express instance with multiple applications)', () => {
let server;

View File

@@ -3,8 +3,7 @@ import {
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import { AppModule } from '../src/app.module';
import { AppModule } from '../src/app.module.js';
describe('Hello world (fastify adapter)', () => {
let app: NestFastifyApplication;
@@ -26,7 +25,10 @@ describe('Hello world (fastify adapter)', () => {
method: 'GET',
url: '/hello',
})
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
.then(({ payload, statusCode }) => {
expect(statusCode).toBe(200);
expect(payload).toEqual('Hello world!');
});
});
it(`/GET (Promise/async)`, () => {
@@ -35,7 +37,10 @@ describe('Hello world (fastify adapter)', () => {
method: 'GET',
url: '/hello/async',
})
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
.then(({ payload, statusCode }) => {
expect(statusCode).toBe(200);
expect(payload).toEqual('Hello world!');
});
});
it(`/GET (Observable stream)`, () => {
@@ -44,7 +49,10 @@ describe('Hello world (fastify adapter)', () => {
method: 'GET',
url: '/hello/stream',
})
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
.then(({ payload, statusCode }) => {
expect(statusCode).toBe(200);
expect(payload).toEqual('Hello world!');
});
});
it(`/GET { host: ":tenant.example.com" } not matched`, () => {
@@ -54,7 +62,7 @@ describe('Hello world (fastify adapter)', () => {
url: '/host',
})
.then(({ payload }) => {
expect(JSON.parse(payload)).to.be.eql({
expect(JSON.parse(payload)).toEqual({
error: 'Internal Server Error',
message:
'HTTP adapter does not support filtering on host: ":tenant.example.com"',
@@ -70,7 +78,7 @@ describe('Hello world (fastify adapter)', () => {
url: '/host-array',
})
.then(({ payload }) => {
expect(JSON.parse(payload)).to.be.eql({
expect(JSON.parse(payload)).toEqual({
error: 'Internal Server Error',
message:
'HTTP adapter does not support filtering on hosts: [":tenant.example1.com", ":tenant.example2.com"]',
@@ -84,7 +92,10 @@ describe('Hello world (fastify adapter)', () => {
.inject()
.get('/hello')
.end()
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
.then(({ payload, statusCode }) => {
expect(statusCode).toBe(200);
expect(payload).toEqual('Hello world!');
});
});
it('/HEAD should respond to with a 200', () => {
@@ -93,7 +104,7 @@ describe('Hello world (fastify adapter)', () => {
method: 'HEAD',
url: '/hello',
})
.then(({ statusCode }) => expect(statusCode).to.be.eq(200));
.then(({ statusCode }) => expect(statusCode).toBe(200));
});
afterEach(async () => {

View File

@@ -11,7 +11,6 @@ import {
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
describe('Middleware before init (FastifyAdapter)', () => {
let app: NestFastifyApplication;
@@ -81,11 +80,11 @@ describe('Middleware before init (FastifyAdapter)', () => {
url: '/test',
})
.then(({ statusCode, payload, headers }) => {
expect(statusCode).to.equal(200);
expect(JSON.parse(payload)).to.deep.equal({ data: 'test_data' });
expect(statusCode).toBe(200);
expect(JSON.parse(payload)).toEqual({ data: 'test_data' });
// Verify both module-level and global middleware were applied
expect(headers['x-middleware']).to.equal('applied');
expect(headers['x-global-middleware']).to.equal('applied');
expect(headers['x-middleware']).toBe('applied');
expect(headers['x-global-middleware']).toBe('applied');
});
});
@@ -123,8 +122,8 @@ describe('Middleware before init (FastifyAdapter)', () => {
url: '/test',
})
.then(({ statusCode, payload }) => {
expect(statusCode).to.equal(200);
expect(JSON.parse(payload)).to.deep.equal({ data: 'test_data' });
expect(statusCode).toBe(200);
expect(JSON.parse(payload)).toEqual({ data: 'test_data' });
});
});

View File

@@ -1,91 +1,4 @@
/* Temporarily disabled due to various regressions
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import { ApplicationModule } from '../src/app.module';
describe('Hello world (fastify adapter with multiple applications)', () => {
let adapter: FastifyAdapter;
let apps: NestFastifyApplication[];
beforeEach(async () => {
const module1 = await Test.createTestingModule({
imports: [ApplicationModule],
}).compile();
const module2 = await Test.createTestingModule({
imports: [ApplicationModule],
}).compile();
adapter = new FastifyAdapter();
apps = [
module1.createNestApplication<NestFastifyApplication>(adapter),
module2
.createNestApplication<NestFastifyApplication>(adapter, {
bodyParser: false,
})
.setGlobalPrefix('/app2'),
];
await Promise.all(apps.map(app => app.init()));
});
it(`/GET`, () => {
return adapter
.inject({
method: 'GET',
url: '/hello',
})
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
});
it(`/GET (app2)`, () => {
return adapter
.inject({
method: 'GET',
url: '/app2/hello',
})
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
});
it(`/GET (Promise/async)`, () => {
return adapter
.inject({
method: 'GET',
url: '/hello/async',
})
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
});
it(`/GET (app2 Promise/async)`, () => {
return adapter
.inject({
method: 'GET',
url: '/app2/hello/async',
})
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
});
it(`/GET (Observable stream)`, () => {
return adapter
.inject({
method: 'GET',
url: '/hello/stream',
})
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
});
it(`/GET (app2 Observable stream)`, () => {
return adapter
.inject({
method: 'GET',
url: '/app2/hello/stream',
})
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
});
afterEach(async () => {
await Promise.all(apps.map(app => app.close()));
await adapter.close();
});
});*/
// Temporarily disabled due to various regressions
describe.skip('Hello world (fastify adapter with multiple applications)', () => {
it('placeholder', () => {});
});

View File

@@ -1,25 +1,23 @@
import { ConsoleLogger, INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import * as sinon from 'sinon';
import { expect } from 'chai';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
describe('ForceConsole Option', () => {
let app: INestApplication;
describe('When forceConsole is true', () => {
let consoleLogSpy: sinon.SinonSpy;
let consoleErrorSpy: sinon.SinonSpy;
let processStdoutSpy: sinon.SinonSpy;
let processStderrSpy: sinon.SinonSpy;
let consoleLogSpy: ReturnType<typeof vi.fn>;
let consoleErrorSpy: ReturnType<typeof vi.fn>;
let processStdoutSpy: ReturnType<typeof vi.fn>;
let processStderrSpy: ReturnType<typeof vi.fn>;
beforeEach(async () => {
// Spy on console and process methods
consoleLogSpy = sinon.spy(console, 'log');
consoleErrorSpy = sinon.spy(console, 'error');
processStdoutSpy = sinon.spy(process.stdout, 'write');
processStderrSpy = sinon.spy(process.stderr, 'write');
consoleLogSpy = vi.spyOn(console, 'log');
consoleErrorSpy = vi.spyOn(console, 'error');
processStdoutSpy = vi.spyOn(process.stdout, 'write');
processStderrSpy = vi.spyOn(process.stderr, 'write');
const moduleRef = await Test.createTestingModule({
imports: [AppModule],
@@ -34,10 +32,10 @@ describe('ForceConsole Option', () => {
});
afterEach(async () => {
consoleLogSpy.restore();
consoleErrorSpy.restore();
processStdoutSpy.restore();
processStderrSpy.restore();
consoleLogSpy.mockRestore();
consoleErrorSpy.mockRestore();
processStdoutSpy.mockRestore();
processStderrSpy.mockRestore();
await app.close();
});
@@ -46,14 +44,12 @@ describe('ForceConsole Option', () => {
logger.log('Test log message');
// Should use console.log when forceConsole is true
expect(consoleLogSpy.called).to.be.true;
expect(consoleLogSpy).toHaveBeenCalled();
// Verify console.log was called with the message
const consoleLogCalls = consoleLogSpy
.getCalls()
.filter(call =>
call.args.some(arg => String(arg).includes('Test log message')),
);
expect(consoleLogCalls.length).to.be.greaterThan(0);
const consoleLogCalls = consoleLogSpy.mock.calls.filter(args =>
args.some(arg => String(arg).includes('Test log message')),
);
expect(consoleLogCalls.length).toBeGreaterThan(0);
});
it('should use console.error instead of process.stderr.write', async () => {
@@ -61,14 +57,12 @@ describe('ForceConsole Option', () => {
logger.error('Test error message');
// Should use console.error when forceConsole is true
expect(consoleErrorSpy.called).to.be.true;
expect(consoleErrorSpy).toHaveBeenCalled();
// Verify console.error was called with the message
const consoleErrorCalls = consoleErrorSpy
.getCalls()
.filter(call =>
call.args.some(arg => String(arg).includes('Test error message')),
);
expect(consoleErrorCalls.length).to.be.greaterThan(0);
const consoleErrorCalls = consoleErrorSpy.mock.calls.filter(args =>
args.some(arg => String(arg).includes('Test error message')),
);
expect(consoleErrorCalls.length).toBeGreaterThan(0);
});
it('should handle GET request with forceConsole option enabled', () => {
@@ -77,17 +71,17 @@ describe('ForceConsole Option', () => {
});
describe('When forceConsole is false (default)', () => {
let consoleLogSpy: sinon.SinonSpy;
let consoleErrorSpy: sinon.SinonSpy;
let processStdoutSpy: sinon.SinonSpy;
let processStderrSpy: sinon.SinonSpy;
let consoleLogSpy: ReturnType<typeof vi.fn>;
let consoleErrorSpy: ReturnType<typeof vi.fn>;
let processStdoutSpy: ReturnType<typeof vi.fn>;
let processStderrSpy: ReturnType<typeof vi.fn>;
beforeEach(async () => {
// Spy on console and process methods
consoleLogSpy = sinon.spy(console, 'log');
consoleErrorSpy = sinon.spy(console, 'error');
processStdoutSpy = sinon.spy(process.stdout, 'write');
processStderrSpy = sinon.spy(process.stderr, 'write');
consoleLogSpy = vi.spyOn(console, 'log');
consoleErrorSpy = vi.spyOn(console, 'error');
processStdoutSpy = vi.spyOn(process.stdout, 'write');
processStderrSpy = vi.spyOn(process.stderr, 'write');
const moduleRef = await Test.createTestingModule({
imports: [AppModule],
@@ -102,10 +96,10 @@ describe('ForceConsole Option', () => {
});
afterEach(async () => {
consoleLogSpy.restore();
consoleErrorSpy.restore();
processStdoutSpy.restore();
processStderrSpy.restore();
consoleLogSpy.mockRestore();
consoleErrorSpy.mockRestore();
processStdoutSpy.mockRestore();
processStderrSpy.mockRestore();
await app.close();
});
@@ -113,31 +107,31 @@ describe('ForceConsole Option', () => {
const logger = new ConsoleLogger('TestContext');
// Reset spy to ensure clean state
consoleLogSpy.resetHistory();
consoleLogSpy.mockClear();
logger.log('Test log message');
// When forceConsole is false, should not call console.log
expect(consoleLogSpy.called).to.be.false;
expect(consoleLogSpy).not.toHaveBeenCalled();
});
it('should not directly call console.error when forceConsole is false', async () => {
const logger = new ConsoleLogger('TestContext');
// Reset spy to ensure clean state
consoleErrorSpy.resetHistory();
consoleErrorSpy.mockClear();
logger.error('Test error message');
// When forceConsole is false, should not call console.error
expect(consoleErrorSpy.called).to.be.false;
expect(consoleErrorSpy).not.toHaveBeenCalled();
});
});
describe('When forceConsole is set via NestFactory.create', () => {
it('should apply forceConsole to the default logger', async () => {
const consoleLogSpy = sinon.spy(console, 'log');
const processStdoutSpy = sinon.spy(process.stdout, 'write');
const consoleLogSpy = vi.spyOn(console, 'log');
const processStdoutSpy = vi.spyOn(process.stdout, 'write');
const moduleRef = await Test.createTestingModule({
imports: [AppModule],
@@ -153,10 +147,10 @@ describe('ForceConsole Option', () => {
const logger = new ConsoleLogger('AppContext', { forceConsole: true });
logger.log('Application started');
expect(consoleLogSpy.called).to.be.true;
expect(consoleLogSpy).toHaveBeenCalled();
consoleLogSpy.restore();
processStdoutSpy.restore();
consoleLogSpy.mockRestore();
processStdoutSpy.mockRestore();
await testApp.close();
});
});

View File

@@ -5,8 +5,8 @@ import {
} from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
@Injectable()
export class AuthGuard {
@@ -33,10 +33,31 @@ function createTestModule(guard) {
describe('Guards', () => {
let app: INestApplication;
afterEach(async () => {
await app.close();
});
it(`should prevent access (unauthorized)`, async () => {
app = (await createTestModule(new AuthGuard())).createNestApplication();
await app.init();
return request(app.getHttpServer()).get('/hello').expect(401);
return request(app.getHttpServer())
.get('/hello')
.expect(401)
.expect(({ body }) => {
expect(body.message).toBe('Unauthorized');
expect(body.statusCode).toBe(401);
});
});
it(`should allow access when guard returns true`, async () => {
const allowGuard = { canActivate: () => true };
app = (await createTestModule(allowGuard)).createNestApplication();
await app.init();
return request(app.getHttpServer())
.get('/hello')
.expect(200)
.expect('Hello world!');
});
});

View File

@@ -1,7 +1,7 @@
import * as request from 'supertest';
import request from 'supertest';
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { AppModule } from '../src/app.module';
import { AppModule } from '../src/app.module.js';
describe('Hello world (default adapter)', () => {
let server;

View File

@@ -9,8 +9,8 @@ import { APP_INTERCEPTOR } from '@nestjs/core';
import { Test } from '@nestjs/testing';
import { of } from 'rxjs';
import { map } from 'rxjs/operators';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
const RETURN_VALUE = 'test';

View File

@@ -1,7 +1,7 @@
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
describe('Hello world (default adapter)', () => {
let server;

View File

@@ -9,8 +9,8 @@ import {
} from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { Response } from 'express';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
const INCLUDED_VALUE = 'test_included';
const RETURN_VALUE = 'test';

View File

@@ -5,7 +5,7 @@ import {
Module,
} from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import request from 'supertest';
const RETURN_VALUE_A = 'test_A';
const RETURN_VALUE_B = 'test_B';

View File

@@ -15,10 +15,9 @@ import {
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import { FastifyRequest } from 'fastify';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
describe('Middleware (FastifyAdapter)', () => {
let app: NestFastifyApplication;
@@ -117,7 +116,7 @@ describe('Middleware (FastifyAdapter)', () => {
method: 'GET',
url: '/hello',
})
.then(({ payload }) => expect(payload).to.be.eql(RETURN_VALUE));
.then(({ payload }) => expect(payload).toEqual(RETURN_VALUE));
});
it(`forRoutes(TestController)`, () => {
@@ -126,7 +125,7 @@ describe('Middleware (FastifyAdapter)', () => {
method: 'GET',
url: '/test',
})
.then(({ payload }) => expect(payload).to.be.eql(SCOPED_VALUE));
.then(({ payload }) => expect(payload).toEqual(SCOPED_VALUE));
});
it(`query?test=${QUERY_VALUE} forRoutes(query)`, () => {
@@ -138,7 +137,7 @@ describe('Middleware (FastifyAdapter)', () => {
test: QUERY_VALUE,
},
})
.then(({ payload }) => expect(payload).to.be.eql(QUERY_VALUE));
.then(({ payload }) => expect(payload).toEqual(QUERY_VALUE));
});
it(`${QUERY_VALUE}?test=${QUERY_VALUE} forRoutes(${QUERY_VALUE})`, () => {
@@ -150,7 +149,7 @@ describe('Middleware (FastifyAdapter)', () => {
test: QUERY_VALUE,
},
})
.then(({ payload }) => expect(payload).to.be.eql(QUERY_VALUE));
.then(({ payload }) => expect(payload).toEqual(QUERY_VALUE));
});
it(`forRoutes(tests/*path)`, () => {
@@ -159,7 +158,7 @@ describe('Middleware (FastifyAdapter)', () => {
method: 'GET',
url: '/tests/wildcard_nested',
})
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
.then(({ payload }) => expect(payload).toEqual(WILDCARD_VALUE));
});
it(`forRoutes(express_style_wildcard/*)`, () => {
@@ -168,7 +167,7 @@ describe('Middleware (FastifyAdapter)', () => {
method: 'GET',
url: '/express_style_wildcard/wildcard_nested',
})
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
.then(({ payload }) => expect(payload).toEqual(WILDCARD_VALUE));
});
it(`forRoutes(legacy_style_wildcard/*)`, () => {
@@ -177,7 +176,7 @@ describe('Middleware (FastifyAdapter)', () => {
method: 'GET',
url: '/legacy_style_wildcard/wildcard_nested',
})
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
.then(({ payload }) => expect(payload).toEqual(WILDCARD_VALUE));
});
it(`forRoutes(req/url/)`, () => {
@@ -187,7 +186,7 @@ describe('Middleware (FastifyAdapter)', () => {
method: 'GET',
url: `/req/url${reqUrl}`,
})
.then(({ payload }) => expect(payload).to.be.eql(REQ_URL_VALUE));
.then(({ payload }) => expect(payload).toEqual(REQ_URL_VALUE));
});
it(`GET forRoutes(POST tests/included)`, () => {
@@ -196,7 +195,7 @@ describe('Middleware (FastifyAdapter)', () => {
method: 'GET',
url: '/tests/included',
})
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
.then(({ payload }) => expect(payload).toEqual(WILDCARD_VALUE));
});
it(`POST forRoutes(POST tests/included)`, () => {
@@ -205,7 +204,7 @@ describe('Middleware (FastifyAdapter)', () => {
method: 'POST',
url: '/tests/included',
})
.then(({ payload }) => expect(payload).to.be.eql(INCLUDED_VALUE));
.then(({ payload }) => expect(payload).toEqual(INCLUDED_VALUE));
});
it(`GET forRoutes(POST /tests/%69ncluded) - ensure middleware is executed correctly with encoded characters`, () => {
@@ -214,7 +213,7 @@ describe('Middleware (FastifyAdapter)', () => {
method: 'POST',
url: '/tests/%69ncluded', // 'i' character is encoded
})
.then(({ payload }) => expect(payload).to.be.eql(INCLUDED_VALUE));
.then(({ payload }) => expect(payload).toEqual(INCLUDED_VALUE));
});
afterEach(async () => {
@@ -329,7 +328,7 @@ describe('Middleware (FastifyAdapter)', () => {
url: '/a/b/c',
})
.then(({ payload }) => {
expect(payload).to.be.eql(
expect(payload).toEqual(
JSON.stringify({
success: true,
actual: 1,
@@ -346,7 +345,7 @@ describe('Middleware (FastifyAdapter)', () => {
url: '/a/b',
})
.then(({ payload }) =>
expect(payload).to.be.eql(
expect(payload).toEqual(
JSON.stringify({
success: true,
actual: 1,
@@ -363,7 +362,7 @@ describe('Middleware (FastifyAdapter)', () => {
url: '/a',
})
.then(({ payload }) =>
expect(payload).to.be.eql(
expect(payload).toEqual(
JSON.stringify({
success: true,
actual: 1,
@@ -380,7 +379,7 @@ describe('Middleware (FastifyAdapter)', () => {
url: '/similar',
})
.then(({ payload }) =>
expect(payload).to.be.eql(
expect(payload).toEqual(
JSON.stringify({
success: true,
actual: 1,
@@ -397,7 +396,7 @@ describe('Middleware (FastifyAdapter)', () => {
url: '/similar/test',
})
.then(({ payload }) =>
expect(payload).to.be.eql(
expect(payload).toEqual(
JSON.stringify({
success: true,
actual: 1,
@@ -414,7 +413,7 @@ describe('Middleware (FastifyAdapter)', () => {
url: '/similar/arbitrary',
})
.then(({ payload }) =>
expect(payload).to.be.eql(
expect(payload).toEqual(
JSON.stringify({
success: true,
actual: 1,
@@ -494,7 +493,7 @@ describe('Middleware (FastifyAdapter)', () => {
url: '/api/pong',
})
.then(({ payload }) =>
expect(payload).to.be.eql(
expect(payload).toEqual(
JSON.stringify({
success: true,
pong: 'pong',
@@ -513,7 +512,7 @@ describe('Middleware (FastifyAdapter)', () => {
url: '/api',
})
.then(({ payload }) =>
expect(payload).to.be.eql(
expect(payload).toEqual(
JSON.stringify({
success: true,
pong: 'pong',
@@ -531,7 +530,7 @@ describe('Middleware (FastifyAdapter)', () => {
url: '/pong',
})
.then(({ payload }) =>
expect(payload).to.be.eql(
expect(payload).toEqual(
JSON.stringify({
success: true,
pong: 'pong',

View File

@@ -7,10 +7,8 @@ import {
NestMiddleware,
Module,
} from '@nestjs/common';
import { Test } from '../../../packages/testing';
import * as request from 'supertest';
import { expect } from 'chai';
import { Test } from '../../../packages/testing.js';
import request from 'supertest';
/**
* Number of times that the middleware was executed.
*/

View File

@@ -6,14 +6,14 @@ import {
Module,
RequestMethod,
Version,
VERSION_NEUTRAL,
VersioningOptions,
VersioningType,
VERSION_NEUTRAL,
} from '@nestjs/common';
import { CustomVersioningOptions } from '@nestjs/common/interfaces';
import { CustomVersioningOptions } from '@nestjs/common/interfaces/index.js';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
const RETURN_VALUE = 'test';
const VERSIONED_VALUE = 'test_versioned';

View File

@@ -6,8 +6,8 @@ import {
Module,
} from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
const RETURN_VALUE = 'test';
const SCOPED_VALUE = 'test_scoped';

View File

@@ -7,8 +7,8 @@ import {
} from '@nestjs/common';
import { RouterModule } from '@nestjs/core';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import request from 'supertest';
import { AppModule } from '../src/app.module.js';
const RETURN_VALUE = 'test';
const SCOPED_VALUE = 'test_scoped';

View File

@@ -1,7 +1,7 @@
import { Controller, Get, INestApplication, Module } from '@nestjs/common';
import { RouterModule, Routes } from '@nestjs/core';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import request from 'supertest';
describe('RouterModule', () => {
let app: INestApplication;
@@ -66,7 +66,7 @@ describe('RouterModule', () => {
})
class AppModule {}
before(async () => {
beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
imports: [MainModule, AppModule],
}).compile();

View File

@@ -0,0 +1,166 @@
import {
ArgumentMetadata,
Body,
Controller,
createParamDecorator,
ExecutionContext,
Get,
INestApplication,
Injectable,
Module,
Param,
PipeTransform,
Post,
Query,
} from '@nestjs/common';
import { Test } from '@nestjs/testing';
import type { StandardSchemaV1 } from '@standard-schema/spec';
import request from 'supertest';
const testSchema: StandardSchemaV1 = {
'~standard': {
version: 1,
vendor: 'test',
validate: (value: unknown) => ({ value }),
},
};
/**
* A pipe that captures the ArgumentMetadata it receives,
* so the test can verify that `schema` is propagated.
*/
@Injectable()
class SchemaCaptorPipe implements PipeTransform {
static lastMetadata: ArgumentMetadata | undefined;
transform(value: any, metadata: ArgumentMetadata) {
SchemaCaptorPipe.lastMetadata = metadata;
return value;
}
}
const CustomParam = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
return ctx.switchToHttp().getRequest().query;
},
);
@Controller('schema-test')
class SchemaTestController {
@Post('body')
bodyWithSchema(
@Body({ schema: testSchema, pipes: [SchemaCaptorPipe] }) body: any,
) {
return { received: body };
}
@Get('query')
queryWithSchema(
@Query({ schema: testSchema, pipes: [SchemaCaptorPipe] }) query: any,
) {
return { received: query };
}
@Get('param/:id')
paramWithSchema(
@Param('id', { schema: testSchema, pipes: [SchemaCaptorPipe] }) id: string,
) {
return { received: id };
}
@Get('custom')
customWithSchema(
@CustomParam({ schema: testSchema, pipes: [SchemaCaptorPipe] }) value: any,
) {
return { received: value };
}
@Post('body-property')
bodyPropertyWithSchema(
@Body('name', { schema: testSchema, pipes: [SchemaCaptorPipe] })
name: string,
) {
return { received: name };
}
}
@Module({
controllers: [SchemaTestController],
providers: [SchemaCaptorPipe],
})
class SchemaTestModule {}
describe('Schema propagation to pipes', () => {
let app: INestApplication;
let server: any;
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [SchemaTestModule],
}).compile();
app = module.createNestApplication();
server = app.getHttpServer();
await app.init();
});
beforeEach(() => {
SchemaCaptorPipe.lastMetadata = undefined;
});
afterAll(async () => {
await app.close();
});
it('should pass schema to pipe via @Body(options)', async () => {
await request(server)
.post('/schema-test/body')
.send({ name: 'test' })
.expect(201);
expect(SchemaCaptorPipe.lastMetadata).toBeDefined();
expect(SchemaCaptorPipe.lastMetadata!.schema).toBe(testSchema);
expect(SchemaCaptorPipe.lastMetadata!.type).toBe('body');
});
it('should pass schema to pipe via @Query(options)', async () => {
await request(server).get('/schema-test/query?user=john').expect(200);
expect(SchemaCaptorPipe.lastMetadata).toBeDefined();
expect(SchemaCaptorPipe.lastMetadata!.schema).toBe(testSchema);
expect(SchemaCaptorPipe.lastMetadata!.type).toBe('query');
});
it('should pass schema to pipe via @Param(property, options)', async () => {
await request(server)
.get('/schema-test/param/42')
.expect(200)
.expect({ received: '42' });
expect(SchemaCaptorPipe.lastMetadata).toBeDefined();
expect(SchemaCaptorPipe.lastMetadata!.schema).toBe(testSchema);
expect(SchemaCaptorPipe.lastMetadata!.type).toBe('param');
expect(SchemaCaptorPipe.lastMetadata!.data).toBe('id');
});
it('should pass schema to pipe via createParamDecorator(options)', async () => {
await request(server).get('/schema-test/custom?key=val').expect(200);
expect(SchemaCaptorPipe.lastMetadata).toBeDefined();
expect(SchemaCaptorPipe.lastMetadata!.schema).toBe(testSchema);
expect(SchemaCaptorPipe.lastMetadata!.type).toBe('custom');
});
it('should pass schema to pipe via @Body(property, options)', async () => {
await request(server)
.post('/schema-test/body-property')
.send({ name: 'Alice' })
.expect(201)
.expect({ received: 'Alice' });
expect(SchemaCaptorPipe.lastMetadata).toBeDefined();
expect(SchemaCaptorPipe.lastMetadata!.schema).toBe(testSchema);
expect(SchemaCaptorPipe.lastMetadata!.type).toBe('body');
expect(SchemaCaptorPipe.lastMetadata!.data).toBe('name');
});
});

View File

@@ -0,0 +1,316 @@
import {
Controller,
Get,
INestApplication,
Module,
SerializeOptions,
StandardSchemaSerializerInterceptor,
UseInterceptors,
} from '@nestjs/common';
import { APP_INTERCEPTOR, Reflector } from '@nestjs/core';
import { Test } from '@nestjs/testing';
import type { StandardSchemaV1 } from '@standard-schema/spec';
import request from 'supertest';
// ─── Test schemas ──────────────────────────────────────────────
/**
* Schema that strips out the `password` field (simulating a "safe user" DTO).
*/
const safeUserSchema: StandardSchemaV1 = {
'~standard': {
version: 1,
vendor: 'test',
validate: (value: unknown) => {
const { password, ...safe } = value as Record<string, unknown>;
return { value: safe };
},
},
};
/**
* Schema that adds a `serialized: true` flag (useful for asserting the schema ran).
*/
const flagSchema: StandardSchemaV1 = {
'~standard': {
version: 1,
vendor: 'test',
validate: (value: unknown) => ({
value: { ...(value as any), serialized: true },
}),
},
};
/**
* Schema that always fails — used for the error case.
*/
const failingSchema: StandardSchemaV1 = {
'~standard': {
version: 1,
vendor: 'test',
validate: () => ({
issues: [{ message: 'not allowed' }],
}),
},
};
/**
* Async schema — validates that the interceptor awaits promises.
*/
const asyncSchema: StandardSchemaV1 = {
'~standard': {
version: 1,
vendor: 'test',
validate: async (value: unknown) => ({
value: { ...(value as any), async: true },
}),
},
};
// ─── Controllers ───────────────────────────────────────────────
@Controller('serializer')
@UseInterceptors(StandardSchemaSerializerInterceptor)
class SerializerTestController {
@Get('user')
@SerializeOptions({ schema: safeUserSchema })
getUser() {
return { id: 1, name: 'Alice', password: 'secret123' };
}
@Get('users')
@SerializeOptions({ schema: safeUserSchema })
getUsers() {
return [
{ id: 1, name: 'Alice', password: 'pw1' },
{ id: 2, name: 'Bob', password: 'pw2' },
];
}
@Get('flagged')
@SerializeOptions({ schema: flagSchema })
getFlagged() {
return { id: 1 };
}
@Get('no-schema')
getNoSchema() {
return { id: 1, secret: 'visible' };
}
@Get('failing')
@SerializeOptions({ schema: failingSchema })
getFailing() {
return { id: 1 };
}
@Get('async')
@SerializeOptions({ schema: asyncSchema })
getAsync() {
return { id: 1 };
}
@Get('primitive')
@SerializeOptions({ schema: failingSchema })
getPrimitive() {
return 'plain string';
}
}
/**
* Controller-level schema applied via class decorator — all routes inherit it.
*/
@Controller('class-level')
@UseInterceptors(StandardSchemaSerializerInterceptor)
@SerializeOptions({ schema: safeUserSchema })
class ClassLevelSerializerController {
@Get('user')
getUser() {
return { id: 1, name: 'Carol', password: 'secret' };
}
@Get('override')
@SerializeOptions({ schema: flagSchema })
getOverride() {
return { id: 1, name: 'Carol', password: 'secret' };
}
}
/**
* Controller demonstrating global interceptor registration with a default schema.
*/
@Controller('global')
class GlobalSerializerController {
@Get('default')
getDefault() {
return { id: 1, name: 'Dave', password: 'global-secret' };
}
@Get('override')
@SerializeOptions({ schema: flagSchema })
getOverride() {
return { id: 1 };
}
}
@Module({
controllers: [SerializerTestController, ClassLevelSerializerController],
})
class SerializerTestModule {}
@Module({
controllers: [GlobalSerializerController],
providers: [
{
provide: APP_INTERCEPTOR,
useFactory: (reflector: Reflector) =>
new StandardSchemaSerializerInterceptor(reflector, {
schema: safeUserSchema,
}),
inject: [Reflector],
},
],
})
class GlobalSerializerTestModule {}
// ─── Tests ─────────────────────────────────────────────────────
describe('StandardSchemaSerializerInterceptor (integration)', () => {
let app: INestApplication;
afterEach(async () => {
await app.close();
});
describe('handler-level @SerializeOptions', () => {
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [SerializerTestModule],
}).compile();
app = module.createNestApplication();
await app.init();
});
it('should strip fields via schema on a single object', () => {
return request(app.getHttpServer())
.get('/serializer/user')
.expect(200)
.expect(({ body }) => {
expect(body).toEqual({ id: 1, name: 'Alice' });
expect(body).not.toHaveProperty('password');
});
});
it('should apply schema to each item in an array response', () => {
return request(app.getHttpServer())
.get('/serializer/users')
.expect(200)
.expect(({ body }) => {
expect(body).toEqual([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
]);
body.forEach((item: any) =>
expect(item).not.toHaveProperty('password'),
);
});
});
it('should augment response through the schema', () => {
return request(app.getHttpServer())
.get('/serializer/flagged')
.expect(200)
.expect({ id: 1, serialized: true });
});
it('should return response unchanged when no schema is set', () => {
return request(app.getHttpServer())
.get('/serializer/no-schema')
.expect(200)
.expect({ id: 1, secret: 'visible' });
});
it('should return 500 when schema validation fails', () => {
return request(app.getHttpServer())
.get('/serializer/failing')
.expect(500);
});
it('should handle async schemas', () => {
return request(app.getHttpServer())
.get('/serializer/async')
.expect(200)
.expect({ id: 1, async: true });
});
it('should pass primitive values through even when a schema is set', () => {
return request(app.getHttpServer())
.get('/serializer/primitive')
.expect(200)
.expect(({ text }) => {
expect(text).toBe('plain string');
});
});
});
describe('class-level @SerializeOptions', () => {
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [SerializerTestModule],
}).compile();
app = module.createNestApplication();
await app.init();
});
it('should apply class-level schema to all routes', () => {
return request(app.getHttpServer())
.get('/class-level/user')
.expect(200)
.expect(({ body }) => {
expect(body).toEqual({ id: 1, name: 'Carol' });
expect(body).not.toHaveProperty('password');
});
});
it('should allow handler-level schema to override class-level', () => {
return request(app.getHttpServer())
.get('/class-level/override')
.expect(200)
.expect(({ body }) => {
// flagSchema adds `serialized: true` but does NOT strip password
expect(body).toHaveProperty('serialized', true);
expect(body).toHaveProperty('password', 'secret');
});
});
});
describe('global interceptor with default schema', () => {
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [GlobalSerializerTestModule],
}).compile();
app = module.createNestApplication();
await app.init();
});
it('should apply the default schema globally', () => {
return request(app.getHttpServer())
.get('/global/default')
.expect(200)
.expect(({ body }) => {
expect(body).toEqual({ id: 1, name: 'Dave' });
expect(body).not.toHaveProperty('password');
});
});
it('should let @SerializeOptions override the global default', () => {
return request(app.getHttpServer())
.get('/global/override')
.expect(200)
.expect({ id: 1, serialized: true });
});
});
});

View File

@@ -1,7 +1,7 @@
import { Module } from '@nestjs/common';
import { HelloModule } from './hello/hello.module';
import { HostArrayModule } from './host-array/host-array.module';
import { HostModule } from './host/host.module';
import { HelloModule } from './hello/hello.module.js';
import { HostArrayModule } from './host-array/host-array.module.js';
import { HostModule } from './host/host.module.js';
@Module({
imports: [HelloModule, HostModule, HostArrayModule],

View File

@@ -1,7 +1,7 @@
import { Controller, Get, Header, Param } from '@nestjs/common';
import { Observable, of } from 'rxjs';
import { HelloService } from './hello.service';
import { UserByIdPipe } from './users/user-by-id.pipe';
import { HelloService } from './hello.service.js';
import { UserByIdPipe } from './users/user-by-id.pipe.js';
@Controller('hello')
export class HelloController {

View File

@@ -1,7 +1,7 @@
import { Module } from '@nestjs/common';
import { HelloController } from './hello.controller';
import { HelloService } from './hello.service';
import { UsersService } from './users/users.service';
import { HelloController } from './hello.controller.js';
import { HelloService } from './hello.service.js';
import { UsersService } from './users/users.service.js';
@Module({
controllers: [HelloController],

View File

@@ -1,5 +1,5 @@
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersService } from './users.service.js';
@Injectable()
export class UserByIdPipe implements PipeTransform<string> {

View File

@@ -1,7 +1,7 @@
import { Controller, Get, Header, HostParam, Param } from '@nestjs/common';
import { Observable, of } from 'rxjs';
import { HostArrayService } from './host-array.service';
import { UserByIdPipe } from './users/user-by-id.pipe';
import { HostArrayService } from './host-array.service.js';
import { UserByIdPipe } from './users/user-by-id.pipe.js';
@Controller({
path: 'host-array',

View File

@@ -1,7 +1,7 @@
import { Module } from '@nestjs/common';
import { HostArrayController } from './host-array.controller';
import { HostArrayService } from './host-array.service';
import { UsersService } from './users/users.service';
import { HostArrayController } from './host-array.controller.js';
import { HostArrayService } from './host-array.service.js';
import { UsersService } from './users/users.service.js';
@Module({
controllers: [HostArrayController],

View File

@@ -1,5 +1,5 @@
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersService } from './users.service.js';
@Injectable()
export class UserByIdPipe implements PipeTransform<string> {

View File

@@ -1,7 +1,7 @@
import { Controller, Get, Header, HostParam, Param } from '@nestjs/common';
import { Observable, of } from 'rxjs';
import { HostService } from './host.service';
import { UserByIdPipe } from './users/user-by-id.pipe';
import { HostService } from './host.service.js';
import { UserByIdPipe } from './users/user-by-id.pipe.js';
@Controller({
path: 'host',

View File

@@ -1,7 +1,7 @@
import { Module } from '@nestjs/common';
import { HostController } from './host.controller';
import { HostService } from './host.service';
import { UsersService } from './users/users.service';
import { HostController } from './host.controller.js';
import { HostService } from './host.service.js';
import { UsersService } from './users/users.service.js';
@Module({
controllers: [HostController],

View File

@@ -1,5 +1,5 @@
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersService } from './users.service.js';
@Injectable()
export class UserByIdPipe implements PipeTransform<string> {

View File

@@ -1,13 +1,15 @@
{
"compilerOptions": {
"types": ["vitest/globals"],
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "ES2021",
"target": "ES2023",
"sourceMap": true,
"allowJs": true,
"strictNullChecks": true,

View File

@@ -1,11 +1,8 @@
import { BeforeApplicationShutdown, Injectable, Module } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import * as Sinon from 'sinon';
@Injectable()
class TestInjectable implements BeforeApplicationShutdown {
beforeApplicationShutdown = Sinon.spy();
beforeApplicationShutdown = vi.fn();
}
describe('BeforeApplicationShutdown', () => {
@@ -17,13 +14,13 @@ describe('BeforeApplicationShutdown', () => {
const app = module.createNestApplication();
await app.close();
const instance = module.get(TestInjectable);
expect(instance.beforeApplicationShutdown.called).to.be.true;
expect(instance.beforeApplicationShutdown).toHaveBeenCalled();
});
it('should sort modules by distance (topological sort) - DESC order', async () => {
@Injectable()
class BB implements BeforeApplicationShutdown {
beforeApplicationShutdown = Sinon.spy();
beforeApplicationShutdown = vi.fn();
}
@Module({
@@ -35,7 +32,7 @@ describe('BeforeApplicationShutdown', () => {
@Injectable()
class AA implements BeforeApplicationShutdown {
constructor(private bb: BB) {}
beforeApplicationShutdown = Sinon.spy();
beforeApplicationShutdown = vi.fn();
}
@Module({
imports: [B],
@@ -53,9 +50,8 @@ describe('BeforeApplicationShutdown', () => {
const aa = module.get(AA);
const bb = module.get(BB);
Sinon.assert.callOrder(
aa.beforeApplicationShutdown,
bb.beforeApplicationShutdown,
);
expect(
aa.beforeApplicationShutdown.mock.invocationCallOrder[0],
).toBeLessThan(bb.beforeApplicationShutdown.mock.invocationCallOrder[0]);
});
});

View File

@@ -1,71 +1,81 @@
import { expect } from 'chai';
import { spawnSync } from 'child_process';
import { join } from 'path';
const nodeCmd = process.execPath;
function spawnTsNode(...args: string[]) {
return spawnSync(nodeCmd, ['--import', 'jiti/register', ...args]);
}
describe('enableShutdownHooks', () => {
it('should call the correct hooks if any shutdown signal gets invoked', done => {
const result = spawnSync('ts-node', [
join(__dirname, '../src/enable-shutdown-hooks-main.ts'),
'SIGHUP',
]);
const calls = result.stdout
.toString()
.split('\n')
.map((call: string) => call.trim());
expect(calls[0]).to.equal('beforeApplicationShutdown SIGHUP');
expect(calls[1]).to.equal('onApplicationShutdown SIGHUP');
done();
}).timeout(10000);
it('should call the correct hooks if any shutdown signal gets invoked', () =>
new Promise<void>(done => {
const result = spawnTsNode(
join(import.meta.dirname, '../src/enable-shutdown-hooks-main.ts'),
'SIGHUP',
);
const calls = result.stdout
.toString()
.split('\n')
.map((call: string) => call.trim());
expect(calls[0]).toBe('beforeApplicationShutdown SIGHUP');
expect(calls[1]).toBe('onApplicationShutdown SIGHUP');
done();
}));
it('should call the correct hooks if a specific shutdown signal gets invoked', done => {
const result = spawnSync('ts-node', [
join(__dirname, '../src/enable-shutdown-hooks-main.ts'),
'SIGINT',
'SIGINT',
]);
const calls = result.stdout
.toString()
.split('\n')
.map((call: string) => call.trim());
expect(calls[0]).to.equal('beforeApplicationShutdown SIGINT');
expect(calls[1]).to.equal('onApplicationShutdown SIGINT');
done();
}).timeout(10000);
it('should call the correct hooks if a specific shutdown signal gets invoked', () =>
new Promise<void>(done => {
const result = spawnTsNode(
join(import.meta.dirname, '../src/enable-shutdown-hooks-main.ts'),
'SIGINT',
'SIGINT',
);
const calls = result.stdout
.toString()
.split('\n')
.map((call: string) => call.trim());
expect(calls[0]).toBe('beforeApplicationShutdown SIGINT');
expect(calls[1]).toBe('onApplicationShutdown SIGINT');
done();
}));
it('should ignore system signals which are not specified', done => {
const result = spawnSync('ts-node', [
join(__dirname, '../src/enable-shutdown-hooks-main.ts'),
'SIGINT',
'SIGHUP',
]);
expect(result.stdout.toString().trim()).to.be.eq('');
done();
}).timeout(10000);
it('should ignore system signals which are not specified', () =>
new Promise<void>(done => {
const result = spawnTsNode(
join(import.meta.dirname, '../src/enable-shutdown-hooks-main.ts'),
'SIGINT',
'SIGHUP',
);
expect(result.stdout.toString().trim()).toBe('');
done();
}));
it('should ignore system signals if "enableShutdownHooks" was not called', done => {
const result = spawnSync('ts-node', [
join(__dirname, '../src/enable-shutdown-hooks-main.ts'),
'SIGINT',
'NONE',
]);
expect(result.stdout.toString().trim()).to.be.eq('');
done();
}).timeout(10000);
it('should ignore system signals if "enableShutdownHooks" was not called', () =>
new Promise<void>(done => {
const result = spawnTsNode(
join(import.meta.dirname, '../src/enable-shutdown-hooks-main.ts'),
'SIGINT',
'NONE',
);
expect(result.stdout.toString().trim()).toBe('');
done();
}));
it('should call the correct hooks with useProcessExit option', done => {
const result = spawnSync('ts-node', [
join(__dirname, '../src/enable-shutdown-hooks-main.ts'),
'SIGHUP',
'SIGHUP',
'graceful',
]);
const calls = result.stdout
.toString()
.split('\n')
.map((call: string) => call.trim());
expect(calls[0]).to.equal('beforeApplicationShutdown SIGHUP');
expect(calls[1]).to.equal('onApplicationShutdown SIGHUP');
expect(result.status).to.equal(0);
done();
}).timeout(10000);
it('should call the correct hooks with useProcessExit option', () =>
new Promise<void>(done => {
const result = spawnTsNode(
join(import.meta.dirname, '../src/enable-shutdown-hooks-main.ts'),
'SIGHUP',
'SIGHUP',
'graceful',
);
const calls = result.stdout
.toString()
.split('\n')
.map((call: string) => call.trim());
expect(calls[0]).toBe('beforeApplicationShutdown SIGHUP');
expect(calls[1]).toBe('onApplicationShutdown SIGHUP');
expect(result.status).toBe(0);
done();
}));
});

View File

@@ -1,13 +1,12 @@
import { Test } from '@nestjs/testing';
import * as Sinon from 'sinon';
import {
BeforeApplicationShutdown,
Injectable,
OnApplicationBootstrap,
OnApplicationShutdown,
OnModuleDestroy,
OnModuleInit,
BeforeApplicationShutdown,
} from '@nestjs/common';
import { Test } from '@nestjs/testing';
@Injectable()
class TestInjectable
@@ -18,11 +17,11 @@ class TestInjectable
OnApplicationShutdown,
BeforeApplicationShutdown
{
onApplicationBootstrap = Sinon.spy();
beforeApplicationShutdown = Sinon.spy();
onApplicationShutdown = Sinon.spy();
onModuleDestroy = Sinon.spy();
onModuleInit = Sinon.spy();
onApplicationBootstrap = vi.fn();
beforeApplicationShutdown = vi.fn();
onApplicationShutdown = vi.fn();
onModuleDestroy = vi.fn();
onModuleInit = vi.fn();
}
describe('Lifecycle Hook Order', () => {
@@ -36,12 +35,17 @@ describe('Lifecycle Hook Order', () => {
await app.close();
const instance = module.get(TestInjectable);
Sinon.assert.callOrder(
const order = [
instance.onModuleInit,
instance.onApplicationBootstrap,
instance.onModuleDestroy,
instance.beforeApplicationShutdown,
instance.onApplicationShutdown,
);
];
for (let i = 0; i < order.length - 1; i++) {
expect(order[i].mock.invocationCallOrder[0]).toBeLessThan(
order[i + 1].mock.invocationCallOrder[0],
);
}
});
});

Some files were not shown because too many files have changed in this diff Show More