mirror of
https://github.com/nestjs/nest.git
synced 2026-02-24 00:02:56 +00:00
Compare commits
2 Commits
v10.4.8
...
fix/fastif
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5612e0197 | ||
|
|
6c54448bf7 |
@@ -1,31 +1,9 @@
|
||||
version: 2.1
|
||||
|
||||
parameters:
|
||||
check-legacy-node-version:
|
||||
type: boolean
|
||||
default: false
|
||||
legacy-node-version:
|
||||
type: string
|
||||
default: '14.21.3'
|
||||
maintenance-node-version:
|
||||
type: string
|
||||
default: '16.20'
|
||||
active-node-version:
|
||||
type: string
|
||||
default: '18.17'
|
||||
current-node-version:
|
||||
type: string
|
||||
default: '20.5'
|
||||
version: 2
|
||||
|
||||
aliases:
|
||||
- &restore-cache
|
||||
restore_cache:
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
- &save-cache
|
||||
save_cache:
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
paths:
|
||||
- ./node_modules
|
||||
- &install-deps
|
||||
run:
|
||||
name: Install dependencies
|
||||
@@ -39,89 +17,70 @@ aliases:
|
||||
name: Test
|
||||
command: npm run test
|
||||
|
||||
unit-tests-template: &unit-tests-template
|
||||
working_directory: ~/nest
|
||||
steps:
|
||||
- checkout
|
||||
- *restore-cache
|
||||
- *install-deps
|
||||
- *build-packages
|
||||
- *run-unit-tests
|
||||
|
||||
jobs:
|
||||
build:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:<< pipeline.parameters.maintenance-node-version >>
|
||||
- image: cimg/node:16.19
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Update NPM version
|
||||
command: 'sudo npm install -g npm@^9'
|
||||
- *restore-cache
|
||||
- *install-deps
|
||||
- *save-cache
|
||||
- *build-packages
|
||||
command: 'sudo npm install -g npm@^8'
|
||||
- restore_cache:
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm ci --legacy-peer-deps
|
||||
- save_cache:
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
paths:
|
||||
- ./node_modules
|
||||
- run:
|
||||
name: Build
|
||||
command: npm run build
|
||||
|
||||
test:
|
||||
parameters:
|
||||
node-version:
|
||||
type: string
|
||||
test_node_16:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:<< parameters.node-version >>
|
||||
- image: cimg/node:16.19
|
||||
steps:
|
||||
- when:
|
||||
condition:
|
||||
and:
|
||||
- equal:
|
||||
[
|
||||
'<< parameters.node-version >>',
|
||||
'<< pipeline.parameters.legacy-node-version >>',
|
||||
]
|
||||
- not: << pipeline.parameters.check-legacy-node-version >>
|
||||
steps:
|
||||
- run:
|
||||
name: Skip
|
||||
command: |
|
||||
echo Skipping
|
||||
- when:
|
||||
condition:
|
||||
or:
|
||||
- not:
|
||||
equal:
|
||||
[
|
||||
'<< parameters.node-version >>',
|
||||
'<< pipeline.parameters.legacy-node-version >>',
|
||||
]
|
||||
- << pipeline.parameters.check-legacy-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
|
||||
- checkout
|
||||
- *restore-cache
|
||||
- *install-deps
|
||||
- *build-packages
|
||||
- run:
|
||||
name: Test (coverage)
|
||||
command: npm run test:cov
|
||||
- run:
|
||||
name: Collect coverage
|
||||
command: npm run coverage
|
||||
- store_artifacts:
|
||||
path: coverage
|
||||
|
||||
test_node_18:
|
||||
<<: *unit-tests-template
|
||||
docker:
|
||||
- image: cimg/node:18.14
|
||||
|
||||
test_node_19:
|
||||
<<: *unit-tests-template
|
||||
docker:
|
||||
- image: cimg/node:19.8
|
||||
|
||||
lint:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:<< pipeline.parameters.maintenance-node-version >>
|
||||
- image: circleci/node:16
|
||||
steps:
|
||||
- checkout
|
||||
- *restore-cache
|
||||
@@ -129,6 +88,9 @@ jobs:
|
||||
- run:
|
||||
name: Lint
|
||||
command: npm run lint
|
||||
- run:
|
||||
name: Lint commit
|
||||
command: ./node_modules/.bin/commitlint-circle -c .commitlintrc.json
|
||||
|
||||
integration_tests:
|
||||
working_directory: ~/nest
|
||||
@@ -143,9 +105,9 @@ jobs:
|
||||
- run:
|
||||
name: Upgrade Node.js
|
||||
command: |
|
||||
nvm install << pipeline.parameters.maintenance-node-version >>
|
||||
nvm install v16
|
||||
node -v
|
||||
nvm alias default << pipeline.parameters.maintenance-node-version >>
|
||||
nvm alias default v16
|
||||
- run:
|
||||
name: Install Docker Compose
|
||||
command: |
|
||||
@@ -168,7 +130,7 @@ jobs:
|
||||
codechecks_benchmarks:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:<< pipeline.parameters.maintenance-node-version >>
|
||||
- image: cimg/node:16.19
|
||||
steps:
|
||||
- checkout
|
||||
- *restore-cache
|
||||
@@ -184,9 +146,9 @@ jobs:
|
||||
samples:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:<< pipeline.parameters.maintenance-node-version >>
|
||||
- image: cimg/node:16.19
|
||||
environment:
|
||||
DISABLE_OPENCOLLECTIVE: 'true'
|
||||
- DISABLE_OPENCOLLECTIVE: true
|
||||
steps:
|
||||
- checkout
|
||||
- *restore-cache
|
||||
@@ -196,21 +158,16 @@ jobs:
|
||||
command: npm run build:samples
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build-and-test:
|
||||
jobs:
|
||||
- build
|
||||
- test:
|
||||
- test_node_16:
|
||||
requires:
|
||||
- build
|
||||
- test_node_18:
|
||||
requires:
|
||||
- build
|
||||
matrix:
|
||||
parameters:
|
||||
node-version:
|
||||
[
|
||||
'<< pipeline.parameters.legacy-node-version >>',
|
||||
'<< pipeline.parameters.maintenance-node-version >>',
|
||||
'<< pipeline.parameters.active-node-version >>',
|
||||
'<< pipeline.parameters.current-node-version >>',
|
||||
]
|
||||
- lint:
|
||||
requires:
|
||||
- build
|
||||
|
||||
@@ -23,7 +23,6 @@ module.exports = {
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-array-constructor': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
10
.github/ISSUE_TEMPLATE/Bug_report.yml
vendored
10
.github/ISSUE_TEMPLATE/Bug_report.yml
vendored
@@ -6,7 +6,7 @@ body:
|
||||
attributes:
|
||||
value: |
|
||||
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
|
||||
|
||||
|
||||
If you are not sure that your issue is a bug, you could:
|
||||
|
||||
- read the [FAQ's common errors](https://docs.nestjs.com/faq/common-errors) page
|
||||
@@ -38,19 +38,15 @@ body:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Minimum reproduction code"
|
||||
description: "An URL to some Git repository/[StackBlitz](https://stackblitz.com/fork/github/nestjs/typescript-starter)/[CodeSandbox](https://codesandbox.io/s/github/nestjs/typescript-starter/tree/master) project that reproduces your issue. [Wtf is a minimum reproduction?](https://jmcdo29.github.io/wtf-is-a-minimum-reproduction)"
|
||||
placeholder: "https://github.com/..."
|
||||
description: |
|
||||
An URL to some Git repository/[StackBlitz](https://stackblitz.com/fork/github/nestjs/typescript-starter)/[CodeSandbox](https://codesandbox.io/s/github/nestjs/typescript-starter/tree/master) project that reproduces your issue. [What is a minimum reproduction?](https://jmcdo29.github.io/wtf-is-a-minimum-reproduction)
|
||||
|
||||
> [!WARNING]
|
||||
> We may close this Issue if we don't manage to reproduce the potential bug. [Read this](https://antfu.me/posts/why-reproductions-are-required) to understand why.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Steps to reproduce"
|
||||
description: |
|
||||
How the issue manifests?
|
||||
You could leave this blank if you already write this in your reproduction code
|
||||
You could leave this blank if you alread write this in your reproduction code
|
||||
placeholder: |
|
||||
1. `npm ci`
|
||||
2. `npm start:dev`
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/Feature_request.yml
vendored
2
.github/ISSUE_TEMPLATE/Feature_request.yml
vendored
@@ -6,7 +6,7 @@ body:
|
||||
attributes:
|
||||
value: |
|
||||
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
|
||||
|
||||
|
||||
If you are not sure that your issue is a bug, you could:
|
||||
|
||||
- read the [FAQ's common errors](https://docs.nestjs.com/faq/common-errors) page
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/Regression.yml
vendored
2
.github/ISSUE_TEMPLATE/Regression.yml
vendored
@@ -6,7 +6,7 @@ body:
|
||||
attributes:
|
||||
value: |
|
||||
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
|
||||
|
||||
|
||||
If you are not sure that your issue is a bug, you could:
|
||||
|
||||
- read the [FAQ's common errors](https://docs.nestjs.com/faq/common-errors) page
|
||||
|
||||
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
queries: +security-extended
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -58,4 +58,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,5 +1,3 @@
|
||||
packages/*/package-lock.json
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
@@ -8,9 +6,6 @@ node_modules/
|
||||
/.awcache
|
||||
/.vscode
|
||||
/.devcontainer
|
||||
/.classpath
|
||||
/.project
|
||||
/.settings
|
||||
*.code-workspace
|
||||
|
||||
# Vim
|
||||
@@ -49,5 +44,4 @@ yarn-error.log
|
||||
build/config\.gypi
|
||||
|
||||
.npmrc
|
||||
pnpm-lock.yaml
|
||||
/.history
|
||||
pnpm-lock.yaml
|
||||
@@ -1 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx --no-install commitlint --edit $1
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
||||
|
||||
@@ -164,7 +164,7 @@ You will need [Node.js](https://nodejs.org) version >= 10.13.0 (except for v13).
|
||||
1. After cloning the repo, run:
|
||||
|
||||
```bash
|
||||
$ npm ci --legacy-peer-deps # (or yarn install)
|
||||
$ npm ci # (or yarn install)
|
||||
```
|
||||
|
||||
2. In order to prepare your environment run `prepare.sh` shell script:
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2017-2024 Kamil Mysliwiec <https://kamilmysliwiec.com>
|
||||
Copyright (c) 2017-2023 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
|
||||
|
||||
164
Readme.md
164
Readme.md
@@ -23,21 +23,21 @@
|
||||
|
||||
## Description
|
||||
|
||||
Nest is a framework for building efficient, scalable <a href="https://nodejs.org" target="_blank">Node.js</a> server-side applications. It uses modern JavaScript, is built with <a href="https://www.typescriptlang.org" target="_blank">TypeScript</a> (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).
|
||||
Nest is a framework for building efficient, scalable <a href="http://nodejs.org" target="_blank">Node.js</a> server-side applications. It uses modern JavaScript, is built with <a href="http://www.typescriptlang.org" target="_blank">TypeScript</a> (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).
|
||||
|
||||
<p>Under the hood, Nest makes use of <a href="https://expressjs.com/" target="_blank">Express</a>, but also provides compatibility with a wide range of other libraries, like <a href="https://github.com/fastify/fastify" target="_blank">Fastify</a>, allowing for easy use of the myriad of third-party plugins which are available.</p>
|
||||
<p>Under the hood, Nest makes use of <a href="https://expressjs.com/" target="_blank">Express</a>, but also, provides compatibility with a wide range of other libraries, like e.g. <a href="https://github.com/fastify/fastify" target="_blank">Fastify</a>, allowing for easy use of the myriad third-party plugins which are available.</p>
|
||||
|
||||
## Philosophy
|
||||
|
||||
<p>In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like <a href="https://angular.io/" target="_blank">Angular</a>, <a href="https://github.com/facebook/react" target="_blank">React</a>, and <a href="https://github.com/vuejs/vue" target="_blank">Vue</a>, which improve developer productivity and enable the construction of fast, testable, and extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers, and tools for Node, none of them effectively solve the main problem - the architecture.</p>
|
||||
<p>Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, and loosely coupled and easily maintainable applications. The architecture is heavily inspired by Angular.</p>
|
||||
<p>In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like <a href="https://angular.io/" target="_blank">Angular</a>, <a href="https://github.com/facebook/react" target="_blank">React</a> and <a href="https://github.com/vuejs/vue" target="_blank">Vue</a> which improve developer productivity and enable the construction of fast, testable, extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers and tools for Node, none of them effectively solve the main problem - the architecture.</p>
|
||||
<p>Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, loosely coupled and easily maintainable applications. The architecture is heavily inspired by Angular.</p>
|
||||
|
||||
## Getting started
|
||||
|
||||
- To check out the [guide](https://docs.nestjs.com), visit [docs.nestjs.com](https://docs.nestjs.com). :books:
|
||||
- 要查看中文 [指南](readme_zh.md), 请访问 [docs.nestjs.cn](https://docs.nestjs.cn). :books:
|
||||
- [가이드](readme_kr.md) 문서는 [docs.nestjs.com](https://docs.nestjs.com)에서 확인하실 수 있습니다. :books:
|
||||
- [ガイド](readme_jp.md)は [docs.nestjs.com](https://docs.nestjs.com)でご確認ください。 :books:
|
||||
* To check out the [guide](https://docs.nestjs.com), visit [docs.nestjs.com](https://docs.nestjs.com). :books:
|
||||
* 要查看中文 [指南](readme_zh.md), 请访问 [docs.nestjs.cn](https://docs.nestjs.cn). :books:
|
||||
* [가이드](readme_kr.md) 문서는 [docs.nestjs.com](https://docs.nestjs.com)에서 확인하실 수 있습니다. :books:
|
||||
* [ガイド](readme_jp.md)は [docs.nestjs.com](https://docs.nestjs.com)でご確認ください。 :books:
|
||||
|
||||
## Questions
|
||||
|
||||
@@ -56,85 +56,89 @@ With official support, you can get expert help straight from Nest core team. We
|
||||
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support from the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
|
||||
|
||||
#### Principal Sponsors
|
||||
|
||||
<table style="text-align:center;">
|
||||
<tr>
|
||||
<td><a href="https://trilon.io" target="_blank"><img src="https://nestjs.com/img/trilon.svg" width="200" valign="middle" /></a></td>
|
||||
<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://marblism.com?utm_source=nest" target="_blank"><img src="https://nestjs.com/img/logos/marblism-logo.png" width="180" 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://amplication.com/" target="_blank"><img src="https://nestjs.com/img/logos/amplication-logo.svg" width="190" valign="middle" /></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table style="text-align:center;"><tr>
|
||||
<td><a href="https://trilon.io" target="_blank"><img src="https://nestjs.com/img/trilon.svg" width="200" valign="middle" /></a></td>
|
||||
<td><a href="https://www.redhat.com" target="_blank"><img src="https://nestjs.com/img/red-hat-logo.svg" width="200" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://github.com/Sanofi-IADC" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/sanofi.png" width="180" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/nx-logo.png" height="45" 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://amplication.com/" target="_blank"><img src="https://nestjs.com/img/amplication-logo.svg" width="190" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
#### Gold Sponsors
|
||||
|
||||
<table style="text-align:center;">
|
||||
<tr>
|
||||
<td><a href="https://www.redhat.com" target="_blank"><img src="https://nestjs.com/img/logos/red-hat-logo.svg" width="200" valign="middle" /></a></td>
|
||||
<td><a href="https://github.com/Sanofi-IADC" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/sanofi.png" width="180" valign="middle" /></a></td>
|
||||
<td><a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/logos/nx-logo.png" height="45" valign="middle" /></a></td>
|
||||
<td><a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/logos/intrinisic-logo.png" width="210" valign="middle" /></a></td>
|
||||
<td><a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/logos/jetbrains-logo.svg" width="90" valign="middle" /></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/logos/snyk-logo-black.png" width="185" valign="middle" /></a></td>
|
||||
<td><a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/logos/fuse-logo.svg" width="105" valign="middle" /></a></td>
|
||||
<td><a href="https://ridicorp.com/career/" target="_blank"><img src="https://nestjs.com/img/logos/ridi-logo.svg" width="105" valign="middle" /></a></td>
|
||||
<td><a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://nestjs.com/img/logos/movavi-logo.svg" width="105" valign="middle" /></a></td>
|
||||
<td><a href="https://skunk.team" target="_blank"><img src="https://nestjs.com/img/logos/skunk-logo.png" height="60" valign="middle" /></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table style="text-align:center;"><tr><td>
|
||||
<a href="https://weld.app/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="140" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/intrinisic-logo.png" width="210" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/jetbrains-logo.svg" width="110" valign="middle" /></a></td><td>
|
||||
<a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/snyk-logo-black.png" width="185" valign="middle" /></a></td><td>
|
||||
<a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/fuse-logo.svg" width="105" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://ridicorp.com/career/" target="_blank"><img src="https://nestjs.com/img/ridi-logo.svg" width="105" valign="middle" /></a></td><td>
|
||||
<a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://nestjs.com/img/movavi-logo.svg" width="105" valign="middle" /></a></td></</tr></table>
|
||||
|
||||
#### Silver Sponsors
|
||||
|
||||
<table style="text-align:center;">
|
||||
<tr>
|
||||
<td><a href="https://www.mercedes-benz.com/" target="_blank"><img src="https://nestjs.com/img/logos/mercedes-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td><a href="https://www.dinii.jp/" target="_blank"><img src="https://nestjs.com/img/logos/dinii-logo.png" width="65" valign="middle" /></a></td>
|
||||
<td><a href="https://bloodycase.com/?promocode=NEST" target="_blank"><img src="https://nestjs.com/img/logos/bloodycase-logo.png" width="65" valign="middle" /></a></td>
|
||||
<td><a href="https://handsontable.com/docs/react-data-grid/?utm_source=NestJS_GH&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024" target="_blank"><img src="https://nestjs.com/img/logos/handsontable-dark-logo.svg#2" width="150" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.itflashcards.com/" target="_blank"><img src="https://nestjs.com/img/logos/it_flashcards-logo.png" width="170" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://arcjet.com/?ref=nestjs" target="_blank"><img src="https://nestjs.com/img/logos/arcjet-logo.svg" width="170" valign="middle" /></a></td>
|
||||
</tr>
|
||||
<table style="text-align:center;"><tr><td>
|
||||
<a href="https://neoteric.eu/" target="_blank"><img src="https://nestjs.com/img/neoteric-cut.png" width="120" valign="middle" /></a> </td><td>
|
||||
<a href="http://gojob.com" target="_blank"><img src="http://nestjs.com/img/gojob-logo.png" valign="middle" width="100" /></a> </td><td>
|
||||
<a href="https://www.myleodsc.com/" target="_blank"><img src="https://nestjs.com/img/myleo-logo.png" width="180" valign="middle" /></td><td>
|
||||
<a href="https://careers.meetdandy.com/?gh_src=063ba61e3us" target="_blank"><img src="https://nestjs.com/img/dandy-roles-logo.svg" width="150" valign="middle" /></td><td>
|
||||
<a href="https://www.castlecraft.in" target="_blank"><img src="https://nestjs.com/img/castlecraft-logo.png" width="150" valign="middle" /></td>
|
||||
<td><a href="https://www.tinystacks.com" target="_blank"><img src="https://nestjs.com/img/tinystacks-logo.png#1" width="140" valign="middle" /></td>
|
||||
<td><a href="https://n.inc" target="_blank"><img src="https://nestjs.com/img/n-inc-logo.svg" width="120" valign="middle" /></td></tr><tr>
|
||||
<td><a href="https://bilberrry.com/" target="_blank"><img src="https://nestjs.com/img/bilberrry-logo.svg" width="180" valign="middle" /></td>
|
||||
<td><a href="https://ipinfo.ai/" target="_blank"><img src="https://nestjs.com/img/ipinfo-logo.png" width="130" valign="middle" /></td>
|
||||
<td><a href="https://chax.at" target="_blank"><img src="https://nestjs.com/img/chaxat-logo.png" width="100" valign="middle" /></td></tr>
|
||||
</table>
|
||||
|
||||
#### Sponsors
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center" valign="middle"><a href="https://www.swingdev.io" target="_blank"><img src="https://nestjs.com/img/logos/swingdev-logo.svg#1" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.novologic.com/" target="_blank"><img src="https://nestjs.com/img/logos/novologic.png" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://mantro.net/" target="_blank"><img src="https://nestjs.com/img/logos/mantro-logo.svg" width="95" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://triplebyte.com/" target="_blank"><img src="https://nestjs.com/img/logos/triplebyte.png" width="107" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nearpod.com/" target="_blank"><img src="https://nestjs.com/img/logos/nearpod-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://genuinebee.com/" target="_blank"><img src="https://nestjs.com/img/logos/genuinebee.svg" width="97" valign="middle" /></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="middle"><a href="https://vpn-review.com/vpn-for-torrenting" target="_blank"><img src="https://nestjs.com/img/logos/vpn-review-logo.png" width="85" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://lambda-it.ch/" target="_blank"><img src="https://nestjs.com/img/logos/lambda-it-logo.svg" width="115" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://rocketech.it/cases/?utm_source=google&utm_medium=badge&utm_campaign=nestjs" target="_blank"><img src="https://nestjs.com/img/logos/rocketech-logo.svg" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.anonymistic.com/" target="_blank"><img src="https://nestjs.com/img/logos/anonymistic-logo.png" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/logos/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/logos/triplecore-logo.svg" width="50" valign="middle" /></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="middle"><a href="https://thecasinowizard.com/bonuses/no-deposit-bonuses/" target="_blank"><img src="https://nestjs.com/img/logos/casinowizard-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://polygon-software.ch/" target="_blank"><img src="https://nestjs.com/img/logos/polygon-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/logos/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/logos/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/logos/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/logos/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="middle"><a href="https://julienferand.dev/" target="_blank"><img src="https://nestjs.com/img/logos/julienferand-logo.jpeg" width="55" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.tripoffice.com/" target="_blank"><img src="https://nestjs.com/img/logos/tripoffice-logo.png" width="140" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://solcellsforetag.se/" target="_blank"><img src="https://nestjs.com/img/logos/solcellsforetag-logo.svg" width="140" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.route4me.com/" target="_blank"><img src="https://nestjs.com/img/logos/route4me-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.slotsup.com/" target="_blank"><img src="https://nestjs.com/img/logos/slotsup-logo.png" width="60" valign="middle" /></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table><tr><td align="center" valign="middle">
|
||||
<a href="https://www.swingdev.io" target="_blank"><img src="https://nestjs.com/img/swingdev-logo.svg#1" width="110" valign="middle" /> </a></td><td align="center" valign="middle">
|
||||
<a href="https://www.novologic.com/" target="_blank"><img src="https://nestjs.com/img/novologic.png" width="110" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://ever.co/" target="_blank"><img src="https://nestjs.com/img/ever-logo.png" width="72" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://blokt.com" target="_blank"><img src="https://nestjs.com/img/blokt-logo.png" width="120" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="http://architectnow.net/" target="_blank"><img src="https://nestjs.com/img/architectnow.png" width="125" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://quander.io/" target="_blank"><img src="https://nestjs.com/img/quander.png" width="100" valign="middle" /></a> </td></tr><tr><td align="center" valign="middle">
|
||||
<a href="https://mantro.net/" target="_blank"><img src="https://nestjs.com/img/mantro-logo.svg" width="95" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://triplebyte.com/" target="_blank"><img src="https://nestjs.com/img/triplebyte.png" width="107" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://reposit.co.uk/" target="_blank"><img src="https://nestjs.com/img/reposit-logo.png" width="71" valign="middle" /></a></td><td align="center" valign="middle">
|
||||
<a href="https://nearpod.com/" target="_blank"><img src="https://nestjs.com/img/nearpod-logo.svg" width="100" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://clay.global/" target="_blank"><img src="https://nestjs.com/img/clay-logo.svg" width="75" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://firesticktricks.com" target="_blank"><img src="https://nestjs.com/img/firesticktricks-logo.png" width="120" valign="middle" /></a></td></tr><tr><td align="center" valign="middle">
|
||||
<a href="https://www.codeguesser.co.uk" target="_blank"><img src="https://nestjs.com/img/codeguesser-logo.svg" width="120" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://f-a.nz/" target="_blank"><img src="https://nestjs.com/img/franz.svg" width="80" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://sparkfabrik.com/" target="_blank"><img src="https://nestjs.com/img/sparkfabrik-logo.png" width="120" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://www.thebigphonestore.co.uk/" target="_blank"><img src="https://nestjs.com/img/the-big-phone-store-logo.png" width="65" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://genuinebee.com/" target="_blank"><img src="https://nestjs.com/img/genuinebee.svg" width="97" valign="middle" /></a> </td>
|
||||
<td align="center" valign="middle"><a href="https://sanyodigital.com/" target="_blank"><img src="https://nestjs.com/img/sanyo-digital.png" width="130" valign="middle" /></a></td></tr><tr><td align="center" valign="middle"><a href="https://vpn-review.com/vpn-for-torrenting" target="_blank"><img src="https://nestjs.com/img/vpn-review-logo.png" width="85" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://lambda-it.ch/" target="_blank"><img src="https://nestjs.com/img/lambda-it-logo.svg" width="115" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://pickwriters.com/top-10-translation-services" target="_blank"><img src="https://nestjs.com/img/pickwriters-logo.png" width="40" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://thewordpoint.com/services/localization" target="_blank"><img src="https://nestjs.com/img/thewordpoint-logo.png" width="40" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://meercode.io/" target="_blank"><img src="https://nestjs.com/img/meercode-logo.png" width="60" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.najlepszeplatformyforex.pl/blog/broker-xtb/" target="_blank"><img src="https://nestjs.com/img/npf-logo.jpg" width="200" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://thestandarddaily.com/" target="_blank"><img src="https://nestjs.com/img/the-standard-daily-logo.png" width="180" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://houseofangular.io/" target="_blank"><img src="https://nestjs.com/img/house-of-angular.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://rocketech.it/cases/?utm_source=google&utm_medium=badge&utm_campaign=nestjs" target="_blank"><img src="https://nestjs.com/img/rocketech-logo.svg" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.bystored.com/" target="_blank"><img src="https://nestjs.com/img/stored-logo.svg" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://studyclerk.com/pay-for-research-paper" target="_blank"><img src="https://nestjs.com/img/studyclerk-logo.png" width="125" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://xyndata.com" target="_blank"><img src="https://nestjs.com/img/xyndata-logo.png" width="125" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.anonymistic.com/" target="_blank"><img src="https://nestjs.com/img/anonymistic-logo.png" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://messaged.com/" target="_blank"><img src="https://nestjs.com/img/messaged-logo.png" width="50" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/triplecore-logo.svg" width="50" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://klqc.de" target="_blank"><img src="https://nestjs.com/img/klcqcl-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://thecasinowizard.com/bonuses/no-deposit-bonuses/" target="_blank"><img src="https://nestjs.com/img/casinowizard-logo.png" width="120" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://polygon-software.ch/" target="_blank"><img src="https://nestjs.com/img/polygon-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://themobilereality.com/" target="_blank"><img src="https://nestjs.com/img/mobile-reality-logo.png" width="45" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -142,9 +146,9 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
|
||||
## Stay in touch
|
||||
|
||||
- Author - [Kamil Myśliwiec](https://x.com/kammysliwiec)
|
||||
- Website - [https://nestjs.com](https://nestjs.com/)
|
||||
- X - [@nestframework](https://x.com/nestframework)
|
||||
* Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec)
|
||||
* Website - [https://nestjs.com](https://nestjs.com/)
|
||||
* Twitter - [@nestframework](https://twitter.com/nestframework)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
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';
|
||||
|
||||
describe('DiscoveryModule', () => {
|
||||
let moduleRef: TestingModule;
|
||||
|
||||
beforeEach(async () => {
|
||||
moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
});
|
||||
|
||||
it('should discover all providers & handlers with corresponding annotations', async () => {
|
||||
const webhooksExplorer = moduleRef.get(WebhooksExplorer);
|
||||
|
||||
expect(webhooksExplorer.getWebhooks()).to.be.eql([
|
||||
{
|
||||
handlers: [
|
||||
{
|
||||
event: 'start',
|
||||
methodName: 'onStart',
|
||||
},
|
||||
],
|
||||
name: 'cleanup',
|
||||
},
|
||||
{
|
||||
handlers: [
|
||||
{
|
||||
event: 'start',
|
||||
methodName: 'onStart',
|
||||
},
|
||||
],
|
||||
name: 'flush',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return an empty array if no providers were found for a given discoverable decorator', () => {
|
||||
const discoveryService = moduleRef.get(DiscoveryService);
|
||||
|
||||
const providers = discoveryService.getProviders({
|
||||
metadataKey: NonAppliedDecorator.KEY,
|
||||
});
|
||||
expect(providers).to.be.eql([]);
|
||||
});
|
||||
|
||||
it('should return an empty array if no controllers were found for a given discoverable decorator', () => {
|
||||
const discoveryService = moduleRef.get(DiscoveryService);
|
||||
|
||||
const controllers = discoveryService.getControllers({
|
||||
metadataKey: NonAppliedDecorator.KEY,
|
||||
});
|
||||
expect(controllers).to.be.eql([]);
|
||||
});
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { DiscoveryModule } from '@nestjs/core';
|
||||
import { MyWebhookModule } from './my-webhook/my-webhook.module';
|
||||
import { WebhooksExplorer } from './webhooks.explorer';
|
||||
|
||||
@Module({
|
||||
imports: [MyWebhookModule, DiscoveryModule],
|
||||
providers: [WebhooksExplorer],
|
||||
})
|
||||
export class AppModule {}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { DiscoveryService } from '@nestjs/core';
|
||||
|
||||
/**
|
||||
* This decorator must not be used anywhere!
|
||||
*
|
||||
* This will be used to test the scenario where we are trying to retrieving
|
||||
* metadata for a discoverable decorator that was not applied to any class.
|
||||
*/
|
||||
export const NonAppliedDecorator = DiscoveryService.createDecorator();
|
||||
@@ -1,6 +0,0 @@
|
||||
import { DiscoveryService } from '@nestjs/core';
|
||||
|
||||
export const Webhook = DiscoveryService.createDecorator<{ name: string }>();
|
||||
export const WebhookHandler = DiscoveryService.createDecorator<{
|
||||
event: string;
|
||||
}>();
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Webhook, WebhookHandler } from '../decorators/webhook.decorators';
|
||||
|
||||
@Webhook({ name: 'cleanup' })
|
||||
export class CleanupWebhook {
|
||||
@WebhookHandler({ event: 'start' })
|
||||
onStart() {
|
||||
console.log('cleanup started');
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Webhook, WebhookHandler } from '../decorators/webhook.decorators';
|
||||
|
||||
@Webhook({ name: 'flush' })
|
||||
export class FlushWebhook {
|
||||
@WebhookHandler({ event: 'start' })
|
||||
onStart() {
|
||||
console.log('flush started');
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { CleanupWebhook } from './cleanup.webhook';
|
||||
import { FlushWebhook } from './flush.webhook';
|
||||
|
||||
@Module({ providers: [CleanupWebhook, FlushWebhook] })
|
||||
export class MyWebhookModule {}
|
||||
@@ -1,39 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { DiscoveryService, MetadataScanner } from '@nestjs/core';
|
||||
import { Webhook, WebhookHandler } from './decorators/webhook.decorators';
|
||||
|
||||
@Injectable()
|
||||
export class WebhooksExplorer {
|
||||
constructor(
|
||||
private readonly discoveryService: DiscoveryService,
|
||||
private readonly metadataScanner: MetadataScanner,
|
||||
) {}
|
||||
|
||||
getWebhooks() {
|
||||
const webhooks = this.discoveryService.getProviders({
|
||||
metadataKey: Webhook.KEY,
|
||||
});
|
||||
return webhooks.map(wrapper => {
|
||||
const { name } = this.discoveryService.getMetadataByDecorator(
|
||||
Webhook,
|
||||
wrapper,
|
||||
);
|
||||
return {
|
||||
name,
|
||||
handlers: this.metadataScanner
|
||||
.getAllMethodNames(wrapper.metatype.prototype)
|
||||
.map(methodName => {
|
||||
const { event } = this.discoveryService.getMetadataByDecorator(
|
||||
WebhookHandler,
|
||||
wrapper,
|
||||
methodName,
|
||||
);
|
||||
return {
|
||||
methodName,
|
||||
event,
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"declaration": false,
|
||||
"noImplicitAny": false,
|
||||
"removeComments": true,
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES2021",
|
||||
"sourceMap": true,
|
||||
"allowJs": true,
|
||||
"outDir": "./dist",
|
||||
"paths": {
|
||||
"@nestjs/common": ["../../packages/common"],
|
||||
"@nestjs/common/*": ["../../packages/common/*"],
|
||||
"@nestjs/core": ["../../packages/core"],
|
||||
"@nestjs/core/*": ["../../packages/core/*"],
|
||||
"@nestjs/microservices": ["../../packages/microservices"],
|
||||
"@nestjs/microservices/*": ["../../packages/microservices/*"],
|
||||
"@nestjs/websockets": ["../../packages/websockets"],
|
||||
"@nestjs/websockets/*": ["../../packages/websockets/*"],
|
||||
"@nestjs/testing": ["../../packages/testing"],
|
||||
"@nestjs/testing/*": ["../../packages/testing/*"],
|
||||
"@nestjs/platform-express": ["../../packages/platform-express"],
|
||||
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
|
||||
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],
|
||||
"@nestjs/platform-socket.io/*": ["../../packages/platform-socket.io/*"],
|
||||
"@nestjs/platform-ws": ["../../packages/platform-ws"],
|
||||
"@nestjs/platform-ws/*": ["../../packages/platform-ws/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"e2e/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
]
|
||||
}
|
||||
@@ -25,7 +25,7 @@ services:
|
||||
- "9001:9001"
|
||||
restart: always
|
||||
mysql:
|
||||
image: mysql:8.3.0
|
||||
image: mysql:8.0.32
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: test
|
||||
@@ -50,7 +50,7 @@ services:
|
||||
zookeeper:
|
||||
container_name: test-zookeeper
|
||||
hostname: zookeeper
|
||||
image: confluentinc/cp-zookeeper:7.5.3
|
||||
image: confluentinc/cp-zookeeper:7.3.2
|
||||
ports:
|
||||
- "2181:2181"
|
||||
environment:
|
||||
@@ -59,7 +59,7 @@ services:
|
||||
kafka:
|
||||
container_name: test-kafka
|
||||
hostname: kafka
|
||||
image: confluentinc/cp-kafka:7.5.3
|
||||
image: confluentinc/cp-kafka:7.3.2
|
||||
depends_on:
|
||||
- zookeeper
|
||||
ports:
|
||||
|
||||
@@ -45,11 +45,6 @@ class TestController {
|
||||
overviewById() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('multiple/exclude')
|
||||
multipleExclude() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
@@ -64,7 +59,6 @@ class TestModule {
|
||||
path: 'middleware',
|
||||
method: RequestMethod.POST,
|
||||
})
|
||||
.exclude('multiple/exclude')
|
||||
.forRoutes('*');
|
||||
}
|
||||
}
|
||||
@@ -116,12 +110,6 @@ describe('Exclude middleware', () => {
|
||||
.expect(200, RETURN_VALUE);
|
||||
});
|
||||
|
||||
it(`should exclude "/multiple/exclude" endpoint`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple/exclude')
|
||||
.expect(200, RETURN_VALUE);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -45,10 +45,6 @@ describe('Hello world (express instance)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('/HEAD should respond to with a 200', () => {
|
||||
return request(server).head('/hello').expect(200);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -87,15 +87,6 @@ describe('Hello world (fastify adapter)', () => {
|
||||
.then(({ payload }) => expect(payload).to.be.eql('Hello world!'));
|
||||
});
|
||||
|
||||
it('/HEAD should respond to with a 200', () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'HEAD',
|
||||
url: '/hello',
|
||||
})
|
||||
.then(({ statusCode }) => expect(statusCode).to.be.eq(200));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -192,7 +192,7 @@ describe('Middleware (FastifyAdapter)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('should execute middleware only once for given routes', () => {
|
||||
describe.only('should execute middleware only once for given routes', () => {
|
||||
class Middleware implements NestMiddleware {
|
||||
use(request: any, reply: any, next: () => void) {
|
||||
if (request.middlewareExecutionCount === undefined) {
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
|
||||
import { Controller, Injectable, Module } from '@nestjs/common';
|
||||
|
||||
class B {}
|
||||
|
||||
@Injectable()
|
||||
class A {
|
||||
constructor(b: B) {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class BImpl {
|
||||
constructor(a: A) {}
|
||||
}
|
||||
|
||||
@Controller()
|
||||
class AppController {
|
||||
constructor(a: A) {}
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [AppController],
|
||||
providers: [A, { provide: B, useClass: BImpl }],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
describe('Circular custom providers', () => {
|
||||
it('should throw an exception (useClass + regular provider)', async () => {
|
||||
try {
|
||||
const builder = Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
});
|
||||
await builder.compile();
|
||||
|
||||
expect(true).to.be.eql(false);
|
||||
} catch (err) {
|
||||
expect(err.message).to.be.eql(
|
||||
'A circular dependency has been detected inside "A". Please, make sure that each side of a bidirectional relationships are decorated with "forwardRef()". Note that circular relationships between custom providers (e.g., factories) are not supported since functions cannot be called more than once.',
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw an exception (2 factories)', async () => {
|
||||
try {
|
||||
const builder = Test.createTestingModule({
|
||||
providers: [
|
||||
{ provide: 'ABC', useFactory: () => ({}), inject: ['DEF'] },
|
||||
{ provide: 'DEF', useFactory: () => ({}), inject: ['ABC'] },
|
||||
],
|
||||
});
|
||||
await builder.compile();
|
||||
|
||||
expect(true).to.be.eql(false);
|
||||
} catch (err) {
|
||||
expect(err.message).to.be.eql(
|
||||
'A circular dependency has been detected inside "ABC". Please, make sure that each side of a bidirectional relationships are decorated with "forwardRef()". Note that circular relationships between custom providers (e.g., factories) are not supported since functions cannot be called more than once.',
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -118,14 +118,14 @@ describe('Optional factory provider deps', () => {
|
||||
} catch (err) {
|
||||
expect(err).to.be.instanceOf(UnknownDependenciesException);
|
||||
expect(err.message).to
|
||||
.equal(`Nest can't resolve dependencies of the POSSIBLY_MISSING_DEP (?). Please make sure that the argument "MISSING_DEP" at index [0] is available in the RootTestModule context.
|
||||
.equal(`Nest can't resolve dependencies of the POSSIBLY_MISSING_DEP (?). Please make sure that the argument MISSING_DEP at index [0] is available in the RootTestModule context.
|
||||
|
||||
Potential solutions:
|
||||
- Is RootTestModule a valid NestJS module?
|
||||
- If "MISSING_DEP" is a provider, is it part of the current RootTestModule?
|
||||
- If "MISSING_DEP" is exported from a separate @Module, is that module imported within RootTestModule?
|
||||
- If MISSING_DEP is a provider, is it part of the current RootTestModule?
|
||||
- If MISSING_DEP is exported from a separate @Module, is that module imported within RootTestModule?
|
||||
@Module({
|
||||
imports: [ /* the Module containing "MISSING_DEP" */ ]
|
||||
imports: [ /* the Module containing MISSING_DEP */ ]
|
||||
})
|
||||
`);
|
||||
}
|
||||
|
||||
@@ -60,10 +60,10 @@
|
||||
"sourceModuleName": "InternalCoreModule",
|
||||
"durable": false,
|
||||
"static": true,
|
||||
"scope": 0,
|
||||
"transient": false,
|
||||
"exported": true,
|
||||
"token": "ExternalContextCreator",
|
||||
"initTime": 0
|
||||
"token": "ExternalContextCreator"
|
||||
}
|
||||
},
|
||||
"208171089": {
|
||||
@@ -800,10 +800,10 @@
|
||||
"sourceModuleName": "InternalCoreModule",
|
||||
"durable": false,
|
||||
"static": true,
|
||||
"scope": 0,
|
||||
"transient": false,
|
||||
"exported": true,
|
||||
"token": "ModulesContainer",
|
||||
"initTime": 0
|
||||
"token": "ModulesContainer"
|
||||
}
|
||||
},
|
||||
"-326832201": {
|
||||
@@ -816,10 +816,10 @@
|
||||
"sourceModuleName": "InternalCoreModule",
|
||||
"durable": false,
|
||||
"static": true,
|
||||
"scope": 0,
|
||||
"transient": false,
|
||||
"exported": true,
|
||||
"token": "HttpAdapterHost",
|
||||
"initTime": 0
|
||||
"token": "HttpAdapterHost"
|
||||
}
|
||||
},
|
||||
"-702581189": {
|
||||
@@ -848,10 +848,10 @@
|
||||
"sourceModuleName": "InternalCoreModule",
|
||||
"durable": false,
|
||||
"static": true,
|
||||
"scope": 0,
|
||||
"transient": false,
|
||||
"exported": true,
|
||||
"token": "SerializedGraph",
|
||||
"initTime": 0
|
||||
"token": "SerializedGraph"
|
||||
}
|
||||
},
|
||||
"-1251270035": {
|
||||
|
||||
@@ -60,10 +60,10 @@
|
||||
"sourceModuleName": "InternalCoreModule",
|
||||
"durable": false,
|
||||
"static": true,
|
||||
"scope": 0,
|
||||
"transient": false,
|
||||
"exported": true,
|
||||
"token": "ExternalContextCreator",
|
||||
"initTime": 0
|
||||
"token": "ExternalContextCreator"
|
||||
}
|
||||
},
|
||||
"208171089": {
|
||||
@@ -784,10 +784,10 @@
|
||||
"sourceModuleName": "InternalCoreModule",
|
||||
"durable": false,
|
||||
"static": true,
|
||||
"scope": 0,
|
||||
"transient": false,
|
||||
"exported": true,
|
||||
"token": "ModulesContainer",
|
||||
"initTime": 0
|
||||
"token": "ModulesContainer"
|
||||
}
|
||||
},
|
||||
"-326832201": {
|
||||
@@ -800,10 +800,10 @@
|
||||
"sourceModuleName": "InternalCoreModule",
|
||||
"durable": false,
|
||||
"static": true,
|
||||
"scope": 0,
|
||||
"transient": false,
|
||||
"exported": true,
|
||||
"token": "HttpAdapterHost",
|
||||
"initTime": 0
|
||||
"token": "HttpAdapterHost"
|
||||
}
|
||||
},
|
||||
"-702581189": {
|
||||
@@ -832,10 +832,10 @@
|
||||
"sourceModuleName": "InternalCoreModule",
|
||||
"durable": false,
|
||||
"static": true,
|
||||
"scope": 0,
|
||||
"transient": false,
|
||||
"exported": true,
|
||||
"token": "SerializedGraph",
|
||||
"initTime": 0
|
||||
"token": "SerializedGraph"
|
||||
}
|
||||
},
|
||||
"-1251270035": {
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import chaiAsPromised = require('chai-as-promised');
|
||||
import { AppModule } from '../src/app.module';
|
||||
chai.use(chaiAsPromised);
|
||||
|
||||
describe('Lazy imports', () => {
|
||||
let server;
|
||||
let app: INestApplication;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
server = app.getHttpAdapter().getInstance();
|
||||
});
|
||||
|
||||
it(`should allow imports of global modules`, async () => {
|
||||
await expect(app.init()).to.eventually.be.fulfilled;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { LazyModuleLoader } from '@nestjs/core';
|
||||
import { EagerModule } from './eager.module';
|
||||
import { GlobalModule } from './global.module';
|
||||
import { LazyModule } from './lazy.module';
|
||||
|
||||
@Module({
|
||||
imports: [GlobalModule, EagerModule],
|
||||
})
|
||||
export class AppModule {
|
||||
constructor(public loader: LazyModuleLoader) {}
|
||||
|
||||
async onApplicationBootstrap() {
|
||||
await this.loader.load(() => LazyModule);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Module, Injectable } from '@nestjs/common';
|
||||
import { GlobalService } from './global.module';
|
||||
|
||||
@Injectable()
|
||||
export class EagerService {
|
||||
constructor(public globalService: GlobalService) {}
|
||||
}
|
||||
|
||||
@Module({
|
||||
providers: [EagerService],
|
||||
})
|
||||
export class EagerModule {}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Module, Injectable, Global } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class GlobalService {
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
providers: [GlobalService],
|
||||
exports: [GlobalService],
|
||||
})
|
||||
export class GlobalModule {}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Module, Injectable } from '@nestjs/common';
|
||||
import { GlobalService } from './global.module';
|
||||
|
||||
@Injectable()
|
||||
export class LazyService {
|
||||
constructor(public globalService: GlobalService) {}
|
||||
}
|
||||
|
||||
@Module({
|
||||
providers: [LazyService],
|
||||
})
|
||||
export class LazyModule {}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
await app.listen(3000);
|
||||
}
|
||||
bootstrap();
|
||||
@@ -4,15 +4,11 @@ import { INestApplication } from '@nestjs/common';
|
||||
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { fail } from 'assert';
|
||||
import { expect, use } from 'chai';
|
||||
import * as chaiAsPromised from 'chai-as-promised';
|
||||
import { expect } from 'chai';
|
||||
import { join } from 'path';
|
||||
import * as sinon from 'sinon';
|
||||
import * as request from 'supertest';
|
||||
import { GrpcController } from '../src/grpc/grpc.controller';
|
||||
|
||||
use(chaiAsPromised);
|
||||
|
||||
describe('GRPC transport', () => {
|
||||
let server;
|
||||
let app: INestApplication;
|
||||
@@ -36,7 +32,6 @@ describe('GRPC transport', () => {
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
// Start gRPC microservice
|
||||
await app.startAllMicroservices();
|
||||
await app.init();
|
||||
@@ -133,71 +128,6 @@ describe('GRPC transport', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it(`GRPC with backpressure control`, async function () {
|
||||
// This test hit the gRPC server with 1000 messages, but the server
|
||||
// has to process large (> 1MB) messages, so it will definitely hit
|
||||
// issues where writing to the stream needs to be paused until a drain
|
||||
// event. Prior to this test, a bug existed where the server would
|
||||
// send the incorrect number of messages due to improper backpressure
|
||||
// handling that wrote messages more than once.
|
||||
this.timeout(10000);
|
||||
|
||||
const largeMessages = client.streamLargeMessages();
|
||||
// [0, 1, 2, ..., 999]
|
||||
const expectedIds = Array.from({ length: 1000 }, (_, n) => n);
|
||||
const receivedIds: number[] = [];
|
||||
|
||||
await largeMessages.forEach(msg => {
|
||||
receivedIds.push(msg.id);
|
||||
});
|
||||
|
||||
expect(receivedIds).to.deep.equal(expectedIds);
|
||||
});
|
||||
|
||||
describe('streaming calls that error', () => {
|
||||
// We want to assert that the application does not crash when an error is encountered with an unhandledRejection
|
||||
// the best way to do that is to listen for the unhandledRejection event and fail the test if it is called
|
||||
let processSpy: sinon.SinonSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
processSpy = sinon.spy();
|
||||
process.on('unhandledRejection', processSpy);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.off('unhandledRejection', processSpy);
|
||||
});
|
||||
|
||||
it('should not crash when replying with an error', async () => {
|
||||
const call = new Promise<void>((resolve, reject) => {
|
||||
const stream = client.streamDivide({
|
||||
data: [{ dividend: 1, divisor: 0 }],
|
||||
});
|
||||
|
||||
stream.on('data', () => {
|
||||
fail('Stream should not have emitted any data');
|
||||
});
|
||||
|
||||
stream.on('error', err => {
|
||||
if (err.code !== GRPC.status.CANCELLED) {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
|
||||
stream.on('end', () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
await expect(call).to.eventually.be.rejectedWith(
|
||||
'3 INVALID_ARGUMENT: dividing by 0 is not possible',
|
||||
);
|
||||
|
||||
// if this fails the application has crashed
|
||||
expect(processSpy.called).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
RpcException,
|
||||
} from '@nestjs/microservices';
|
||||
import { join } from 'path';
|
||||
import { Observable, of, catchError, from, mergeMap } from 'rxjs';
|
||||
import { Observable, of, catchError } from 'rxjs';
|
||||
|
||||
class ErrorHandlingProxy extends ClientGrpcProxy {
|
||||
serializeError(err) {
|
||||
@@ -107,17 +107,6 @@ export class GrpcController {
|
||||
};
|
||||
}
|
||||
|
||||
// contrived example meant to show when an error is encountered, like dividing by zero, the
|
||||
// application does not crash and the error is returned appropriately to the client
|
||||
@GrpcMethod('Math', 'StreamDivide')
|
||||
streamDivide({
|
||||
data,
|
||||
}: {
|
||||
data: { dividend: number; divisor: number }[];
|
||||
}): Observable<any> {
|
||||
return from(data).pipe(mergeMap(request => this.divide(request)));
|
||||
}
|
||||
|
||||
@GrpcMethod('Math2')
|
||||
async sum2({ data }: { data: number[] }): Promise<any> {
|
||||
return of({
|
||||
@@ -139,27 +128,6 @@ export class GrpcController {
|
||||
return svc.sum2({ data });
|
||||
}
|
||||
|
||||
@GrpcMethod('Math')
|
||||
streamLargeMessages(_req: unknown, _meta: unknown) {
|
||||
// Send 1000 messages of >1MB each relatively fast
|
||||
// This should be enough to trigger backpressure issues
|
||||
// while writing to the socket.
|
||||
return new Observable(subscriber => {
|
||||
let n = 0;
|
||||
const interval = setInterval(() => {
|
||||
// We'll be checking the ids. The `data` is just to make the
|
||||
// message large enough to trigger backpressure issues.
|
||||
subscriber.next({ id: n++, data: 'a'.repeat(1024 * 1024) });
|
||||
if (n === 1000) {
|
||||
subscriber.complete();
|
||||
}
|
||||
}, 0);
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@Post('error')
|
||||
@HttpCode(200)
|
||||
serializeError(
|
||||
|
||||
@@ -7,18 +7,8 @@ service Math {
|
||||
rpc SumStream(stream RequestSum) returns(stream SumResult);
|
||||
rpc SumStreamPass(stream RequestSum) returns(stream SumResult);
|
||||
rpc Divide (RequestDivide) returns (DivideResult);
|
||||
rpc StreamLargeMessages(Empty) returns (stream BackpressureData);
|
||||
/* Given a series of dividend and divisor, stream back the division results for each */
|
||||
rpc StreamDivide (StreamDivideRequest) returns (stream StreamDivideResponse);
|
||||
}
|
||||
|
||||
message BackpressureData {
|
||||
int32 id = 1;
|
||||
string data = 2;
|
||||
}
|
||||
|
||||
message Empty {}
|
||||
|
||||
message SumResult {
|
||||
int32 result = 1;
|
||||
}
|
||||
@@ -35,11 +25,3 @@ message RequestDivide {
|
||||
message DivideResult {
|
||||
int32 result = 1;
|
||||
}
|
||||
|
||||
message StreamDivideRequest {
|
||||
repeated RequestDivide data = 1;
|
||||
}
|
||||
|
||||
message StreamDivideResponse {
|
||||
DivideResult data = 1;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { Observable } from 'rxjs';
|
||||
import { SumDto } from './dto/sum.dto';
|
||||
|
||||
/**
|
||||
* The following function explicitly sends messages to the key representing the partition.
|
||||
* The following function explicity sends messages to the key representing the partition.
|
||||
*/
|
||||
const explicitPartitioner = () => {
|
||||
return ({ message }: PartitionerArgs) => {
|
||||
|
||||
@@ -4,7 +4,9 @@ import { CatsModule } from './cats/cats.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
MongooseModule.forRoot('mongodb://localhost:27017/test'),
|
||||
MongooseModule.forRoot('mongodb://localhost:27017/test', {
|
||||
useNewUrlParser: true,
|
||||
}),
|
||||
CatsModule,
|
||||
],
|
||||
})
|
||||
|
||||
@@ -10,6 +10,7 @@ class ConfigService implements MongooseOptionsFactory {
|
||||
createMongooseOptions(): MongooseModuleOptions {
|
||||
return {
|
||||
uri: 'mongodb://localhost:27017/test',
|
||||
useNewUrlParser: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class ConfigService implements MongooseOptionsFactory {
|
||||
createMongooseOptions(): MongooseModuleOptions {
|
||||
return {
|
||||
uri: 'mongodb://localhost:27017/test',
|
||||
useNewUrlParser: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { CatsModule } from './cats/cats.module';
|
||||
imports: [
|
||||
MongooseModule.forRootAsync({
|
||||
useFactory: () => ({
|
||||
useNewUrlParser: true,
|
||||
uri: 'mongodb://localhost:27017/test',
|
||||
}),
|
||||
}),
|
||||
|
||||
@@ -573,7 +573,7 @@ allow_anonymous true
|
||||
# not given then the access is read/write. <topic> can contain the + or #
|
||||
# wildcards as in subscriptions.
|
||||
#
|
||||
# The "deny" option can used to explicitly deny access to a topic that would
|
||||
# The "deny" option can used to explicity deny access to a topic that would
|
||||
# otherwise be granted by a broader read/write/readwrite statement. Any "deny"
|
||||
# topics are handled before topics that grant read/write access.
|
||||
#
|
||||
|
||||
@@ -130,18 +130,6 @@ describe('Global prefix', () => {
|
||||
.expect(200, { '0': 'params', tenantId: 'test' });
|
||||
});
|
||||
|
||||
it(`should execute middleware only once`, async () => {
|
||||
app.setGlobalPrefix('/api', { exclude: ['/'] });
|
||||
|
||||
server = app.getHttpServer();
|
||||
await app.init();
|
||||
|
||||
await request(server)
|
||||
.get('/')
|
||||
.expect(200, 'Extras: Data attached in middleware, Count: 1');
|
||||
await request(server).get('/api/count').expect(200, '2');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -26,14 +26,4 @@ export class AppController {
|
||||
postTest(): string {
|
||||
return 'test';
|
||||
}
|
||||
|
||||
@Get()
|
||||
getHome(@Req() req) {
|
||||
return 'Extras: ' + req.extras?.data + ', Count: ' + req.count;
|
||||
}
|
||||
|
||||
@Get('count')
|
||||
getCount(@Req() req) {
|
||||
return req.count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ export const MIDDLEWARE_PARAM_VALUE = 'middleware_param';
|
||||
controllers: [AppController],
|
||||
})
|
||||
export class AppModule {
|
||||
private count = 0;
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply((req, res, next) => res.end(MIDDLEWARE_VALUE))
|
||||
@@ -28,12 +27,6 @@ export class AppModule {
|
||||
req.middlewareParams = req.params;
|
||||
next();
|
||||
})
|
||||
.forRoutes({ path: '*', method: RequestMethod.GET })
|
||||
.apply((req, res, next) => {
|
||||
this.count += 1;
|
||||
req.count = this.count;
|
||||
next();
|
||||
})
|
||||
.forRoutes('*');
|
||||
.forRoutes({ path: '*', method: RequestMethod.GET });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ export class AppController {
|
||||
@Sse('sse')
|
||||
sse(): Observable<MessageEvent> {
|
||||
return interval(1000).pipe(
|
||||
map(_ => ({ data: { hello: 'world' } }) as MessageEvent),
|
||||
map(_ => ({ data: { hello: 'world' } } as MessageEvent)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,14 +27,10 @@ describe('Durable providers', () => {
|
||||
tenantId: number,
|
||||
end: (err?: any) => void,
|
||||
endpoint = '/durable',
|
||||
opts: {
|
||||
forceError: boolean;
|
||||
} = { forceError: false },
|
||||
) =>
|
||||
request(server)
|
||||
.get(endpoint)
|
||||
.set({ ['x-tenant-id']: tenantId })
|
||||
.set({ ['x-force-error']: opts.forceError ? 'true' : 'false' })
|
||||
.end((err, res) => {
|
||||
if (err) return end(err);
|
||||
end(res);
|
||||
@@ -88,23 +84,6 @@ describe('Durable providers', () => {
|
||||
);
|
||||
expect(result.body).deep.equal({ tenantId: '3' });
|
||||
});
|
||||
|
||||
it(`should not cache durable providers that throw errors`, async () => {
|
||||
let result: request.Response;
|
||||
|
||||
result = await new Promise<request.Response>(resolve =>
|
||||
performHttpCall(10, resolve, '/durable/echo', { forceError: true }),
|
||||
);
|
||||
|
||||
expect(result.statusCode).equal(412);
|
||||
|
||||
// The second request should be successful
|
||||
result = await new Promise<request.Response>(resolve =>
|
||||
performHttpCall(10, resolve, '/durable/echo'),
|
||||
);
|
||||
|
||||
expect(result.body).deep.equal({ tenantId: '10' });
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
|
||||
@@ -6,8 +6,6 @@ const tenants = new Map<string, ContextId>();
|
||||
export class DurableContextIdStrategy implements ContextIdStrategy {
|
||||
attach(contextId: ContextId, request: Request) {
|
||||
const tenantId = request.headers['x-tenant-id'] as string;
|
||||
const forceError = request.headers['x-force-error'] === 'true';
|
||||
|
||||
let tenantSubTreeId: ContextId;
|
||||
|
||||
if (tenants.has(tenantId)) {
|
||||
@@ -16,18 +14,10 @@ export class DurableContextIdStrategy implements ContextIdStrategy {
|
||||
tenantSubTreeId = { id: +tenantId } as ContextId;
|
||||
tenants.set(tenantId, tenantSubTreeId);
|
||||
}
|
||||
|
||||
const payload: {
|
||||
tenantId: string;
|
||||
forceError?: boolean;
|
||||
} = { tenantId };
|
||||
if (forceError) {
|
||||
payload.forceError = true;
|
||||
}
|
||||
return {
|
||||
resolve: (info: HostComponentInfo) =>
|
||||
info.isTreeDurable ? tenantSubTreeId : contextId,
|
||||
payload,
|
||||
payload: { tenantId },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
import {
|
||||
Inject,
|
||||
Injectable,
|
||||
PreconditionFailedException,
|
||||
Scope,
|
||||
} from '@nestjs/common';
|
||||
import { Inject, Injectable, Scope } from '@nestjs/common';
|
||||
import { REQUEST } from '@nestjs/core';
|
||||
|
||||
@Injectable({ scope: Scope.REQUEST, durable: true })
|
||||
export class DurableService {
|
||||
public instanceCounter = 0;
|
||||
|
||||
constructor(
|
||||
@Inject(REQUEST)
|
||||
public readonly requestPayload: { tenantId: string; forceError: boolean },
|
||||
) {
|
||||
if (requestPayload.forceError) {
|
||||
throw new PreconditionFailedException('Forced error');
|
||||
}
|
||||
}
|
||||
constructor(@Inject(REQUEST) public readonly requestPayload: unknown) {}
|
||||
|
||||
greeting() {
|
||||
++this.instanceCounter;
|
||||
|
||||
@@ -77,7 +77,7 @@ describe('Fastify FileSend', () => {
|
||||
expect(headers['content-disposition']).to.equal(
|
||||
'attachment; filename="Readme.md"',
|
||||
);
|
||||
expect(headers['content-length']).to.equal(`${readme.byteLength}`);
|
||||
expect(headers['content-length']).to.equal(readme.byteLength);
|
||||
expect(payload).to.equal(readmeString);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"type": "mysql",
|
||||
"host": "127.0.0.1",
|
||||
"host": "localhost",
|
||||
"port": 3306,
|
||||
"username": "root",
|
||||
"password": "root",
|
||||
|
||||
@@ -7,7 +7,7 @@ import { PhotoModule } from './photo/photo.module';
|
||||
imports: [
|
||||
TypeOrmModule.forRoot({
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: 'root',
|
||||
|
||||
@@ -11,7 +11,7 @@ class ConfigService implements TypeOrmOptionsFactory {
|
||||
createTypeOrmOptions(): TypeOrmModuleOptions {
|
||||
return {
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: 'root',
|
||||
|
||||
@@ -11,7 +11,7 @@ class ConfigService implements TypeOrmOptionsFactory {
|
||||
createTypeOrmOptions(): TypeOrmModuleOptions {
|
||||
return {
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: 'root',
|
||||
|
||||
@@ -8,7 +8,7 @@ import { PhotoModule } from './photo/photo.module';
|
||||
TypeOrmModule.forRootAsync({
|
||||
useFactory: () => ({
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: 'root',
|
||||
|
||||
@@ -11,7 +11,7 @@ export class DatabaseModule {
|
||||
imports: [
|
||||
TypeOrmModule.forRoot({
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: 'root',
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
import { INestApplication, VersioningType } from '@nestjs/common';
|
||||
import {
|
||||
FastifyAdapter,
|
||||
NestFastifyApplication,
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
/**
|
||||
* `.enableVersioning()` uses `VersioningType.URI` type by default
|
||||
* Regression test for #13496
|
||||
* @see [Versioning](https://docs.nestjs.com/techniques/versioning)
|
||||
*/
|
||||
describe('Default Versioning behavior', () => {
|
||||
// ======================================================================== //
|
||||
describe('Express', () => {
|
||||
let app: INestApplication;
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning();
|
||||
await app.init();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1')
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
// ======================================================================== //
|
||||
describe('Fastify', () => {
|
||||
let app: INestApplication;
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
);
|
||||
app.enableVersioning();
|
||||
await app.init();
|
||||
await app.getHttpAdapter().getInstance().ready();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1')
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -418,67 +418,4 @@ describe('URI Versioning', () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
// ======================================================================== //
|
||||
describe('with middleware applied', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.URI,
|
||||
defaultVersion: '1',
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
describe('GET /middleware', () => {
|
||||
it('should return "Hello from middleware function!"', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/middleware')
|
||||
.expect(200)
|
||||
.expect('Hello from middleware function!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /middleware/override', () => {
|
||||
it('should return "Hello from middleware function!"', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/middleware/override')
|
||||
.expect(200)
|
||||
.expect('Hello from middleware function!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /middleware/multiple', () => {
|
||||
it('should return "Hello from middleware function!" (v1)', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/middleware/multiple')
|
||||
.expect(200)
|
||||
.expect('Hello from middleware function!');
|
||||
});
|
||||
|
||||
it('should return "Hello from middleware function!" (v2)', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/middleware/multiple')
|
||||
.expect(200)
|
||||
.expect('Hello from middleware function!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /middleware/neutral', () => {
|
||||
it('should return "Hello from middleware function!"', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/middleware/neutral')
|
||||
.expect(200)
|
||||
.expect('Hello from middleware function!');
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { MiddlewareConsumer, Module } from '@nestjs/common';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AppV1Controller } from './app-v1.controller';
|
||||
import { AppV2Controller } from './app-v2.controller';
|
||||
import { MiddlewareController } from './middleware.controller';
|
||||
import { MultipleMiddlewareVersionController } from './multiple-middleware.controller';
|
||||
import { MultipleVersionController } from './multiple.controller';
|
||||
import { VersionNeutralMiddlewareController } from './neutral-middleware.controller';
|
||||
import { VersionNeutralController } from './neutral.controller';
|
||||
import { NoVersioningController } from './no-versioning.controller';
|
||||
import { OverridePartialController } from './override-partial.controller';
|
||||
import { VersionNeutralController } from './neutral.controller';
|
||||
import { OverrideController } from './override.controller';
|
||||
import { OverridePartialController } from './override-partial.controller';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
@@ -20,19 +17,6 @@ import { OverrideController } from './override.controller';
|
||||
VersionNeutralController,
|
||||
OverrideController,
|
||||
OverridePartialController,
|
||||
MiddlewareController,
|
||||
MultipleMiddlewareVersionController,
|
||||
VersionNeutralMiddlewareController,
|
||||
],
|
||||
})
|
||||
export class AppModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply((req, res) => res.end('Hello from middleware function!'))
|
||||
.forRoutes(
|
||||
MiddlewareController,
|
||||
MultipleMiddlewareVersionController,
|
||||
VersionNeutralMiddlewareController,
|
||||
);
|
||||
}
|
||||
}
|
||||
export class AppModule {}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Controller, Get, Version } from '@nestjs/common';
|
||||
|
||||
@Controller({
|
||||
path: 'middleware',
|
||||
version: '1',
|
||||
})
|
||||
export class MiddlewareController {
|
||||
@Get('/')
|
||||
hello() {
|
||||
return 'Hello from "MiddlewareController"!';
|
||||
}
|
||||
|
||||
@Version('2')
|
||||
@Get('/override')
|
||||
hellov2() {
|
||||
return 'Hello from "MiddlewareController"!';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
|
||||
@Controller({
|
||||
version: ['1', '2'],
|
||||
path: 'middleware',
|
||||
})
|
||||
export class MultipleMiddlewareVersionController {
|
||||
@Get('/multiple')
|
||||
multiple() {
|
||||
return 'Multiple Versions 1 or 2';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Controller, Get, VERSION_NEUTRAL } from '@nestjs/common';
|
||||
|
||||
@Controller({
|
||||
path: 'middleware',
|
||||
version: VERSION_NEUTRAL,
|
||||
})
|
||||
export class VersionNeutralMiddlewareController {
|
||||
@Get('/neutral')
|
||||
neutral() {
|
||||
return 'Neutral';
|
||||
}
|
||||
}
|
||||
@@ -66,37 +66,5 @@ describe('WebSocketGateway', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it(`should be able to get the pattern in an interceptor`, async () => {
|
||||
app = await createNestApp(ApplicationGateway);
|
||||
await app.listen(3000);
|
||||
|
||||
ws = io('http://localhost:8080');
|
||||
ws.emit('getClient', {
|
||||
test: 'test',
|
||||
});
|
||||
await new Promise<void>(resolve =>
|
||||
ws.on('popClient', data => {
|
||||
expect(data.path).to.be.eql('getClient');
|
||||
resolve();
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it(`should be able to get the pattern in a filter (when the error comes from a known handler)`, async () => {
|
||||
app = await createNestApp(ApplicationGateway);
|
||||
await app.listen(3000);
|
||||
|
||||
ws = io('http://localhost:8080');
|
||||
ws.emit('getClientWithError', {
|
||||
test: 'test',
|
||||
});
|
||||
await new Promise<void>(resolve =>
|
||||
ws.on('exception', data => {
|
||||
expect(data.pattern).to.be.eql('getClientWithError');
|
||||
resolve();
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => app.close());
|
||||
});
|
||||
|
||||
@@ -194,30 +194,6 @@ describe('WebSocketGateway (WsAdapter)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should let the execution context have a getPattern() method on getClient()', async () => {
|
||||
app = await createNestApp(ApplicationGateway);
|
||||
await app.listen(3000);
|
||||
|
||||
ws = new WebSocket('ws://localhost:8080');
|
||||
await new Promise(resolve => ws.on('open', resolve));
|
||||
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
event: 'getClient',
|
||||
data: {
|
||||
test: 'test',
|
||||
},
|
||||
}),
|
||||
);
|
||||
await new Promise<void>(resolve =>
|
||||
ws.on('message', data => {
|
||||
expect(JSON.parse(data).data.path).to.be.eql('getClient');
|
||||
ws.close();
|
||||
resolve();
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import { UseFilters, UseInterceptors } from '@nestjs/common';
|
||||
import {
|
||||
MessageBody,
|
||||
SubscribeMessage,
|
||||
WebSocketGateway,
|
||||
WsException,
|
||||
} from '@nestjs/websockets';
|
||||
import { RequestInterceptor } from './request.interceptor';
|
||||
import { throwError } from 'rxjs';
|
||||
import { RequestFilter } from './request.filter';
|
||||
|
||||
@WebSocketGateway(8080)
|
||||
export class ApplicationGateway {
|
||||
@@ -18,19 +13,4 @@ export class ApplicationGateway {
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
@UseInterceptors(RequestInterceptor)
|
||||
@SubscribeMessage('getClient')
|
||||
getPathCalled(client, data) {
|
||||
return {
|
||||
event: 'popClient',
|
||||
data: { ...data, path: client.pattern },
|
||||
};
|
||||
}
|
||||
|
||||
@UseFilters(RequestFilter)
|
||||
@SubscribeMessage('getClientWithError')
|
||||
getPathCalledWithError() {
|
||||
return throwError(() => new WsException('This is an error'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common';
|
||||
import { WsException } from '@nestjs/websockets';
|
||||
|
||||
@Catch(WsException)
|
||||
export class RequestFilter implements ExceptionFilter {
|
||||
catch(exception: WsException, host: ArgumentsHost) {
|
||||
const wsCtx = host.switchToWs();
|
||||
const pattern = wsCtx.getPattern();
|
||||
const client = wsCtx.getClient();
|
||||
client.emit('exception', { pattern, message: exception.message });
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { CallHandler, ExecutionContext, Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class RequestInterceptor {
|
||||
intercept(context: ExecutionContext, next: CallHandler) {
|
||||
const client = context.switchToWs().getClient();
|
||||
const pattern = context.switchToWs().getPattern();
|
||||
client.pattern = pattern;
|
||||
return next.handle();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
import { UseInterceptors } from '@nestjs/common';
|
||||
import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets';
|
||||
import { RequestInterceptor } from './request.interceptor';
|
||||
|
||||
@WebSocketGateway()
|
||||
export class ServerGateway {
|
||||
@@ -11,13 +9,4 @@ export class ServerGateway {
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
@UseInterceptors(RequestInterceptor)
|
||||
@SubscribeMessage('getClient')
|
||||
getPathCalled(client, data) {
|
||||
return {
|
||||
event: 'popClient',
|
||||
data: { ...data, path: client.pattern },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "10.4.8"
|
||||
"version": "9.4.2"
|
||||
}
|
||||
|
||||
62560
package-lock.json
generated
62560
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
164
package.json
164
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/core",
|
||||
"version": "10.4.5",
|
||||
"version": "9.4.0",
|
||||
"description": "Modern, fast, powerful node.js web framework",
|
||||
"homepage": "https://nestjs.com",
|
||||
"repository": {
|
||||
@@ -25,14 +25,14 @@
|
||||
"move:node_modules": "gulp move:node_modules",
|
||||
"build:samples": "gulp install:samples && npm run build && npm run move:samples && gulp build:samples && gulp test:samples && gulp test:e2e:samples",
|
||||
"codechecks:benchmarks": "codechecks ./tools/benchmarks/check-benchmarks.ts",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls -v",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls",
|
||||
"format": "prettier \"**/*.ts\" \"packages/**/*.json\" --ignore-path ./.prettierignore --write && git status",
|
||||
"postinstall": "opencollective",
|
||||
"test": "mocha packages/**/*.spec.ts",
|
||||
"test:dev": "mocha -w --watch-files \"packages\" packages/**/*.spec.ts",
|
||||
"pretest:cov": "npm run clean",
|
||||
"test:cov": "nyc mocha packages/**/*.spec.ts --reporter spec",
|
||||
"test:integration": "mocha --reporter-option maxDiffSize=0 \"integration/*/{,!(node_modules)/**/}/*.spec.ts\"",
|
||||
"test:integration": "mocha \"integration/*/{,!(node_modules)/**/}/*.spec.ts\"",
|
||||
"test:docker:up": "docker-compose -f integration/docker-compose.yml up -d",
|
||||
"test:docker:down": "docker-compose -f integration/docker-compose.yml down",
|
||||
"lint": "concurrently 'npm run lint:packages' 'npm run lint:integration' 'npm run lint:spec'",
|
||||
@@ -47,7 +47,7 @@
|
||||
"publish:next": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=next --access public --skip-git -m \"chore(@nestjs) publish %s release\"",
|
||||
"publish:rc": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=rc --access public -m \"chore(@nestjs) publish %s release\"",
|
||||
"publish:test": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --force-publish --access public --npm-tag=test --skip-git -m \"chore(@nestjs) publish %s release\"",
|
||||
"prepare": "husky"
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*.ts": [
|
||||
@@ -60,79 +60,80 @@
|
||||
"dependencies": {
|
||||
"@nuxtjs/opencollective": "0.3.2",
|
||||
"class-transformer": "0.5.1",
|
||||
"class-validator": "0.14.1",
|
||||
"cli-color": "2.0.4",
|
||||
"class-validator": "0.14.0",
|
||||
"cli-color": "2.0.3",
|
||||
"cors": "2.8.5",
|
||||
"express": "4.21.1",
|
||||
"fast-json-stringify": "6.0.0",
|
||||
"express": "4.18.2",
|
||||
"fast-json-stringify": "5.7.0",
|
||||
"fast-safe-stringify": "2.1.1",
|
||||
"graphql-subscriptions": "2.0.0",
|
||||
"iterare": "1.2.1",
|
||||
"object-hash": "3.0.0",
|
||||
"path-to-regexp": "3.2.0",
|
||||
"reflect-metadata": "0.2.2",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rxjs": "7.8.1",
|
||||
"socket.io": "4.8.0",
|
||||
"tslib": "2.7.0",
|
||||
"socket.io": "4.6.1",
|
||||
"tslib": "2.5.2",
|
||||
"uid": "2.0.2",
|
||||
"uuid": "10.0.0"
|
||||
"uuid": "9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apollo/server": "4.11.0",
|
||||
"@apollo/server": "4.7.1",
|
||||
"@codechecks/client": "0.1.12",
|
||||
"@commitlint/cli": "19.5.0",
|
||||
"@commitlint/config-angular": "19.5.0",
|
||||
"@fastify/cors": "9.0.1",
|
||||
"@commitlint/cli": "17.6.3",
|
||||
"@commitlint/config-angular": "17.6.3",
|
||||
"@fastify/cors": "8.2.1",
|
||||
"@fastify/formbody": "7.4.0",
|
||||
"@fastify/middie": "8.3.1",
|
||||
"@fastify/multipart": "8.3.0",
|
||||
"@fastify/static": "7.0.4",
|
||||
"@fastify/view": "9.1.0",
|
||||
"@grpc/grpc-js": "1.11.1",
|
||||
"@grpc/proto-loader": "0.7.13",
|
||||
"@nestjs/apollo": "12.2.0",
|
||||
"@nestjs/graphql": "12.2.0",
|
||||
"@nestjs/mongoose": "10.0.10",
|
||||
"@nestjs/typeorm": "10.0.2",
|
||||
"@types/amqplib": "0.10.5",
|
||||
"@types/bytes": "3.1.4",
|
||||
"@types/chai": "4.3.16",
|
||||
"@types/chai-as-promised": "7.1.8",
|
||||
"@types/cors": "2.8.17",
|
||||
"@types/express": "4.17.21",
|
||||
"@types/gulp": "4.0.17",
|
||||
"@types/http-errors": "2.0.4",
|
||||
"@types/mocha": "10.0.8",
|
||||
"@types/node": "22.5.5",
|
||||
"@types/sinon": "17.0.3",
|
||||
"@types/supertest": "2.0.16",
|
||||
"@types/ws": "8.5.12",
|
||||
"@typescript-eslint/eslint-plugin": "7.18.0",
|
||||
"@typescript-eslint/parser": "7.18.0",
|
||||
"amqp-connection-manager": "4.1.14",
|
||||
"amqplib": "0.10.4",
|
||||
"artillery": "2.0.20",
|
||||
"body-parser": "1.20.3",
|
||||
"@fastify/middie": "8.3.0",
|
||||
"@fastify/multipart": "7.6.0",
|
||||
"@fastify/static": "6.10.1",
|
||||
"@fastify/view": "7.4.1",
|
||||
"@grpc/grpc-js": "1.8.14",
|
||||
"@grpc/proto-loader": "0.7.7",
|
||||
"@nestjs/apollo": "11.0.5",
|
||||
"@nestjs/graphql": "11.0.5",
|
||||
"@nestjs/mongoose": "9.2.2",
|
||||
"@nestjs/typeorm": "9.0.1",
|
||||
"@types/amqplib": "0.10.1",
|
||||
"@types/bytes": "3.1.1",
|
||||
"@types/chai": "4.3.5",
|
||||
"@types/chai-as-promised": "7.1.5",
|
||||
"@types/cors": "2.8.13",
|
||||
"@types/express": "4.17.17",
|
||||
"@types/gulp": "4.0.10",
|
||||
"@types/http-errors": "2.0.1",
|
||||
"@types/mocha": "10.0.1",
|
||||
"@types/node": "20.2.3",
|
||||
"@types/sinon": "10.0.15",
|
||||
"@types/supertest": "2.0.12",
|
||||
"@types/ws": "8.5.4",
|
||||
"@typescript-eslint/eslint-plugin": "4.33.0",
|
||||
"@typescript-eslint/parser": "4.33.0",
|
||||
"amqp-connection-manager": "4.1.13",
|
||||
"amqplib": "0.10.3",
|
||||
"artillery": "1.7.9",
|
||||
"body-parser": "1.20.2",
|
||||
"bytes": "3.1.2",
|
||||
"cache-manager": "5.7.6",
|
||||
"cache-manager": "5.2.1",
|
||||
"cache-manager-redis-store": "3.0.1",
|
||||
"chai": "4.5.0",
|
||||
"chai-as-promised": "7.1.2",
|
||||
"chai": "4.3.7",
|
||||
"chai-as-promised": "7.1.1",
|
||||
"clang-format": "1.8.0",
|
||||
"concurrently": "9.0.1",
|
||||
"conventional-changelog": "6.0.0",
|
||||
"core-js": "3.38.1",
|
||||
"commitlint-circle": "1.0.0",
|
||||
"concurrently": "8.0.1",
|
||||
"conventional-changelog": "3.1.25",
|
||||
"core-js": "3.30.2",
|
||||
"coveralls": "3.1.1",
|
||||
"delete-empty": "3.0.0",
|
||||
"engine.io-client": "6.6.1",
|
||||
"eslint": "8.57.1",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"engine.io-client": "6.4.0",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eventsource": "2.0.2",
|
||||
"fancy-log": "2.0.0",
|
||||
"fastify": "4.28.1",
|
||||
"graphql": "16.9.0",
|
||||
"graphql-tools": "9.0.1",
|
||||
"fastify": "4.17.0",
|
||||
"graphql": "16.6.0",
|
||||
"graphql-tools": "9.0.0",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-clang-format": "1.0.27",
|
||||
"gulp-clean": "0.4.0",
|
||||
@@ -140,41 +141,42 @@
|
||||
"gulp-typescript": "5.0.1",
|
||||
"gulp-watch": "5.0.1",
|
||||
"http-errors": "2.0.0",
|
||||
"husky": "9.1.5",
|
||||
"imports-loader": "5.0.0",
|
||||
"ioredis": "5.4.1",
|
||||
"husky": "8.0.3",
|
||||
"imports-loader": "4.0.1",
|
||||
"ioredis": "5.3.2",
|
||||
"json-loader": "0.5.7",
|
||||
"kafkajs": "2.2.4",
|
||||
"lerna": "2.11.0",
|
||||
"lerna-changelog": "2.2.0",
|
||||
"light-my-request": "6.1.0",
|
||||
"lint-staged": "15.2.10",
|
||||
"light-my-request": "5.9.1",
|
||||
"lint-staged": "13.2.2",
|
||||
"markdown-table": "2.0.0",
|
||||
"mocha": "10.7.3",
|
||||
"mongoose": "8.6.2",
|
||||
"mqtt": "5.6.0",
|
||||
"merge-graphql-schemas": "1.7.8",
|
||||
"mocha": "10.2.0",
|
||||
"mongoose": "7.2.0",
|
||||
"mqtt": "4.3.7",
|
||||
"multer": "1.4.4",
|
||||
"mysql2": "3.11.3",
|
||||
"nats": "2.28.2",
|
||||
"nodemon": "3.1.5",
|
||||
"nyc": "14.1.1",
|
||||
"prettier": "3.3.3",
|
||||
"redis": "4.7.0",
|
||||
"mysql2": "3.3.1",
|
||||
"nats": "2.13.1",
|
||||
"nodemon": "2.0.22",
|
||||
"nyc": "15.1.0",
|
||||
"prettier": "2.8.8",
|
||||
"redis": "4.6.6",
|
||||
"rxjs-compat": "6.6.7",
|
||||
"sinon": "19.0.2",
|
||||
"sinon": "15.1.0",
|
||||
"sinon-chai": "3.7.0",
|
||||
"socket.io-client": "4.8.0",
|
||||
"socket.io-client": "4.6.1",
|
||||
"subscriptions-transport-ws": "0.11.0",
|
||||
"supertest": "7.0.0",
|
||||
"ts-morph": "23.0.0",
|
||||
"ts-node": "10.9.2",
|
||||
"typeorm": "0.3.20",
|
||||
"typescript": "5.6.2",
|
||||
"supertest": "6.3.3",
|
||||
"ts-morph": "18.0.0",
|
||||
"ts-node": "10.9.1",
|
||||
"typeorm": "0.3.16",
|
||||
"typescript": "5.0.4",
|
||||
"wrk": "1.2.1",
|
||||
"ws": "8.18.0"
|
||||
"ws": "8.13.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 12.9.0"
|
||||
},
|
||||
"collective": {
|
||||
"type": "opencollective",
|
||||
|
||||
@@ -23,21 +23,21 @@
|
||||
|
||||
## Description
|
||||
|
||||
Nest is a framework for building efficient, scalable <a href="https://nodejs.org" target="_blank">Node.js</a> server-side applications. It uses modern JavaScript, is built with <a href="https://www.typescriptlang.org" target="_blank">TypeScript</a> (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).
|
||||
Nest is a framework for building efficient, scalable <a href="http://nodejs.org" target="_blank">Node.js</a> server-side applications. It uses modern JavaScript, is built with <a href="http://www.typescriptlang.org" target="_blank">TypeScript</a> (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).
|
||||
|
||||
<p>Under the hood, Nest makes use of <a href="https://expressjs.com/" target="_blank">Express</a>, but also provides compatibility with a wide range of other libraries, like <a href="https://github.com/fastify/fastify" target="_blank">Fastify</a>, allowing for easy use of the myriad of third-party plugins which are available.</p>
|
||||
<p>Under the hood, Nest makes use of <a href="https://expressjs.com/" target="_blank">Express</a>, but also, provides compatibility with a wide range of other libraries, like e.g. <a href="https://github.com/fastify/fastify" target="_blank">Fastify</a>, allowing for easy use of the myriad third-party plugins which are available.</p>
|
||||
|
||||
## Philosophy
|
||||
|
||||
<p>In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like <a href="https://angular.io/" target="_blank">Angular</a>, <a href="https://github.com/facebook/react" target="_blank">React</a>, and <a href="https://github.com/vuejs/vue" target="_blank">Vue</a>, which improve developer productivity and enable the construction of fast, testable, and extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers, and tools for Node, none of them effectively solve the main problem - the architecture.</p>
|
||||
<p>Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, and loosely coupled and easily maintainable applications. The architecture is heavily inspired by Angular.</p>
|
||||
<p>In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like <a href="https://angular.io/" target="_blank">Angular</a>, <a href="https://github.com/facebook/react" target="_blank">React</a> and <a href="https://github.com/vuejs/vue" target="_blank">Vue</a> which improve developer productivity and enable the construction of fast, testable, extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers and tools for Node, none of them effectively solve the main problem - the architecture.</p>
|
||||
<p>Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, loosely coupled and easily maintainable applications. The architecture is heavily inspired by Angular.</p>
|
||||
|
||||
## Getting started
|
||||
|
||||
- To check out the [guide](https://docs.nestjs.com), visit [docs.nestjs.com](https://docs.nestjs.com). :books:
|
||||
- 要查看中文 [指南](readme_zh.md), 请访问 [docs.nestjs.cn](https://docs.nestjs.cn). :books:
|
||||
- [가이드](readme_kr.md) 문서는 [docs.nestjs.com](https://docs.nestjs.com)에서 확인하실 수 있습니다. :books:
|
||||
- [ガイド](readme_jp.md)は [docs.nestjs.com](https://docs.nestjs.com)でご確認ください。 :books:
|
||||
* To check out the [guide](https://docs.nestjs.com), visit [docs.nestjs.com](https://docs.nestjs.com). :books:
|
||||
* 要查看中文 [指南](readme_zh.md), 请访问 [docs.nestjs.cn](https://docs.nestjs.cn). :books:
|
||||
* [가이드](readme_kr.md) 문서는 [docs.nestjs.com](https://docs.nestjs.com)에서 확인하실 수 있습니다. :books:
|
||||
* [ガイド](readme_jp.md)は [docs.nestjs.com](https://docs.nestjs.com)でご確認ください。 :books:
|
||||
|
||||
## Questions
|
||||
|
||||
@@ -56,85 +56,88 @@ With official support, you can get expert help straight from Nest core team. We
|
||||
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support from the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
|
||||
|
||||
#### Principal Sponsors
|
||||
|
||||
<table style="text-align:center;">
|
||||
<tr>
|
||||
<td><a href="https://trilon.io" target="_blank"><img src="https://nestjs.com/img/trilon.svg" width="200" valign="middle" /></a></td>
|
||||
<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://marblism.com?utm_source=nest" target="_blank"><img src="https://nestjs.com/img/logos/marblism-logo.png" width="180" 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://amplication.com/" target="_blank"><img src="https://nestjs.com/img/logos/amplication-logo.svg" width="190" valign="middle" /></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table style="text-align:center;"><tr>
|
||||
<td><a href="https://trilon.io" target="_blank"><img src="https://nestjs.com/img/trilon.svg" width="200" valign="middle" /></a></td>
|
||||
<td><a href="https://www.redhat.com" target="_blank"><img src="https://nestjs.com/img/red-hat-logo.svg" width="200" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://github.com/Sanofi-IADC" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/sanofi.png" width="180" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/nx-logo.png" height="45" 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://amplication.com/" target="_blank"><img src="https://nestjs.com/img/amplication-logo.svg" width="190" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
#### Gold Sponsors
|
||||
|
||||
<table style="text-align:center;">
|
||||
<tr>
|
||||
<td><a href="https://www.redhat.com" target="_blank"><img src="https://nestjs.com/img/logos/red-hat-logo.svg" width="200" valign="middle" /></a></td>
|
||||
<td><a href="https://github.com/Sanofi-IADC" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/sanofi.png" width="180" valign="middle" /></a></td>
|
||||
<td><a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/logos/nx-logo.png" height="45" valign="middle" /></a></td>
|
||||
<td><a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/logos/intrinisic-logo.png" width="210" valign="middle" /></a></td>
|
||||
<td><a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/logos/jetbrains-logo.svg" width="90" valign="middle" /></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/logos/snyk-logo-black.png" width="185" valign="middle" /></a></td>
|
||||
<td><a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/logos/fuse-logo.svg" width="105" valign="middle" /></a></td>
|
||||
<td><a href="https://ridicorp.com/career/" target="_blank"><img src="https://nestjs.com/img/logos/ridi-logo.svg" width="105" valign="middle" /></a></td>
|
||||
<td><a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://nestjs.com/img/logos/movavi-logo.svg" width="105" valign="middle" /></a></td>
|
||||
<td><a href="https://skunk.team" target="_blank"><img src="https://nestjs.com/img/logos/skunk-logo.png" height="60" valign="middle" /></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table style="text-align:center;"><tr><td>
|
||||
<a href="https://weld.app/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="140" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/intrinisic-logo.png" width="210" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/jetbrains-logo.svg" width="110" valign="middle" /></a></td><td>
|
||||
<a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/snyk-logo-black.png" width="185" valign="middle" /></a></td><td>
|
||||
<a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/fuse-logo.svg" width="105" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://ridicorp.com/career/" target="_blank"><img src="https://nestjs.com/img/ridi-logo.svg" width="105" valign="middle" /></a></td><td>
|
||||
<a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://nestjs.com/img/movavi-logo.svg" width="105" valign="middle" /></a></td></</tr></table>
|
||||
|
||||
#### Silver Sponsors
|
||||
|
||||
<table style="text-align:center;">
|
||||
<tr>
|
||||
<td><a href="https://www.mercedes-benz.com/" target="_blank"><img src="https://nestjs.com/img/logos/mercedes-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td><a href="https://www.dinii.jp/" target="_blank"><img src="https://nestjs.com/img/logos/dinii-logo.png" width="65" valign="middle" /></a></td>
|
||||
<td><a href="https://bloodycase.com/?promocode=NEST" target="_blank"><img src="https://nestjs.com/img/logos/bloodycase-logo.png" width="65" valign="middle" /></a></td>
|
||||
<td><a href="https://handsontable.com/docs/react-data-grid/?utm_source=NestJS_GH&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024" target="_blank"><img src="https://nestjs.com/img/logos/handsontable-logo.svg" width="150" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.itflashcards.com/" target="_blank"><img src="https://nestjs.com/img/logos/it_flashcards-logo.png" width="170" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://arcjet.com/?ref=nestjs" target="_blank"><img src="https://nestjs.com/img/logos/arcjet-logo.svg" width="170" valign="middle" /></a></td>
|
||||
</tr>
|
||||
<table style="text-align:center;"><tr><td>
|
||||
<a href="https://neoteric.eu/" target="_blank"><img src="https://nestjs.com/img/neoteric-cut.png" width="120" valign="middle" /></a> </td><td>
|
||||
<a href="http://gojob.com" target="_blank"><img src="http://nestjs.com/img/gojob-logo.png" valign="middle" width="100" /></a> </td><td>
|
||||
<a href="https://www.myleodsc.com/" target="_blank"><img src="https://nestjs.com/img/myleo-logo.png" width="180" valign="middle" /></td><td>
|
||||
<a href="https://careers.meetdandy.com/?gh_src=063ba61e3us" target="_blank"><img src="https://nestjs.com/img/dandy-roles-logo.svg" width="150" valign="middle" /></td><td>
|
||||
<a href="https://www.castlecraft.in" target="_blank"><img src="https://nestjs.com/img/castlecraft-logo.png" width="150" valign="middle" /></td>
|
||||
<td><a href="https://www.tinystacks.com" target="_blank"><img src="https://nestjs.com/img/tinystacks-logo.png#1" width="140" valign="middle" /></td>
|
||||
<td><a href="https://n.inc" target="_blank"><img src="https://nestjs.com/img/n-inc-logo.svg" width="120" valign="middle" /></td></tr><tr>
|
||||
<td><a href="https://bilberrry.com/" target="_blank"><img src="https://nestjs.com/img/bilberrry-logo.svg" width="180" valign="middle" /></td>
|
||||
<td><a href="https://ipinfo.ai/" target="_blank"><img src="https://nestjs.com/img/ipinfo-logo.png" width="130" valign="middle" /></td>
|
||||
<td><a href="https://chax.at" target="_blank"><img src="https://nestjs.com/img/chaxat-logo.png" width="100" valign="middle" /></td></tr>
|
||||
</table>
|
||||
|
||||
#### Sponsors
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center" valign="middle"><a href="https://www.swingdev.io" target="_blank"><img src="https://nestjs.com/img/logos/swingdev-logo.svg#1" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.novologic.com/" target="_blank"><img src="https://nestjs.com/img/logos/novologic.png" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://mantro.net/" target="_blank"><img src="https://nestjs.com/img/logos/mantro-logo.svg" width="95" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://triplebyte.com/" target="_blank"><img src="https://nestjs.com/img/logos/triplebyte.png" width="107" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nearpod.com/" target="_blank"><img src="https://nestjs.com/img/logos/nearpod-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://genuinebee.com/" target="_blank"><img src="https://nestjs.com/img/logos/genuinebee.svg" width="97" valign="middle" /></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="middle"><a href="https://vpn-review.com/vpn-for-torrenting" target="_blank"><img src="https://nestjs.com/img/logos/vpn-review-logo.png" width="85" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://lambda-it.ch/" target="_blank"><img src="https://nestjs.com/img/logos/lambda-it-logo.svg" width="115" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://rocketech.it/cases/?utm_source=google&utm_medium=badge&utm_campaign=nestjs" target="_blank"><img src="https://nestjs.com/img/logos/rocketech-logo.svg" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.anonymistic.com/" target="_blank"><img src="https://nestjs.com/img/logos/anonymistic-logo.png" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/logos/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/logos/triplecore-logo.svg" width="50" valign="middle" /></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="middle"><a href="https://thecasinowizard.com/bonuses/no-deposit-bonuses/" target="_blank"><img src="https://nestjs.com/img/logos/casinowizard-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://polygon-software.ch/" target="_blank"><img src="https://nestjs.com/img/logos/polygon-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/logos/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/logos/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/logos/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/logos/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="middle"><a href="https://julienferand.dev/" target="_blank"><img src="https://nestjs.com/img/logos/julienferand-logo.jpeg" width="55" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.tripoffice.com/" target="_blank"><img src="https://nestjs.com/img/logos/tripoffice-logo.png" width="140" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://solcellsforetag.se/" target="_blank"><img src="https://nestjs.com/img/logos/solcellsforetag-logo.svg" width="140" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.route4me.com/" target="_blank"><img src="https://nestjs.com/img/logos/route4me-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.slotsup.com/" target="_blank"><img src="https://nestjs.com/img/logos/slotsup-logo.png" width="60" valign="middle" /></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table><tr><td align="center" valign="middle">
|
||||
<a href="https://www.swingdev.io" target="_blank"><img src="https://nestjs.com/img/swingdev-logo.svg#1" width="110" valign="middle" /> </a></td><td align="center" valign="middle">
|
||||
<a href="https://www.novologic.com/" target="_blank"><img src="https://nestjs.com/img/novologic.png" width="110" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://ever.co/" target="_blank"><img src="https://nestjs.com/img/ever-logo.png" width="72" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://blokt.com" target="_blank"><img src="https://nestjs.com/img/blokt-logo.png" width="120" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="http://architectnow.net/" target="_blank"><img src="https://nestjs.com/img/architectnow.png" width="125" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://quander.io/" target="_blank"><img src="https://nestjs.com/img/quander.png" width="100" valign="middle" /></a> </td></tr><tr><td align="center" valign="middle">
|
||||
<a href="https://mantro.net/" target="_blank"><img src="https://nestjs.com/img/mantro-logo.svg" width="95" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://triplebyte.com/" target="_blank"><img src="https://nestjs.com/img/triplebyte.png" width="107" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://reposit.co.uk/" target="_blank"><img src="https://nestjs.com/img/reposit-logo.png" width="71" valign="middle" /></a></td><td align="center" valign="middle">
|
||||
<a href="https://nearpod.com/" target="_blank"><img src="https://nestjs.com/img/nearpod-logo.svg" width="100" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://clay.global/" target="_blank"><img src="https://nestjs.com/img/clay-logo.svg" width="75" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://firesticktricks.com" target="_blank"><img src="https://nestjs.com/img/firesticktricks-logo.png" width="120" valign="middle" /></a></td></tr><tr><td align="center" valign="middle">
|
||||
<a href="https://www.codeguesser.co.uk" target="_blank"><img src="https://nestjs.com/img/codeguesser-logo.svg" width="120" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://f-a.nz/" target="_blank"><img src="https://nestjs.com/img/franz.svg" width="80" valign="middle" /></a> </td><td align="center" valign="middle">
|
||||
<a href="https://sparkfabrik.com/" target="_blank"><img src="https://nestjs.com/img/sparkfabrik-logo.png" width="120" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://www.thebigphonestore.co.uk/" target="_blank"><img src="https://nestjs.com/img/the-big-phone-store-logo.png" width="65" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://genuinebee.com/" target="_blank"><img src="https://nestjs.com/img/genuinebee.svg" width="97" valign="middle" /></a> </td>
|
||||
<td align="center" valign="middle"><a href="https://sanyodigital.com/" target="_blank"><img src="https://nestjs.com/img/sanyo-digital.png" width="130" valign="middle" /></a></td></tr><tr><td align="center" valign="middle"><a href="https://vpn-review.com/vpn-for-torrenting" target="_blank"><img src="https://nestjs.com/img/vpn-review-logo.png" width="85" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://lambda-it.ch/" target="_blank"><img src="https://nestjs.com/img/lambda-it-logo.svg" width="115" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://pickwriters.com/top-10-translation-services" target="_blank"><img src="https://nestjs.com/img/pickwriters-logo.png" width="40" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://thewordpoint.com/services/localization" target="_blank"><img src="https://nestjs.com/img/thewordpoint-logo.png" width="40" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://meercode.io/" target="_blank"><img src="https://nestjs.com/img/meercode-logo.png" width="60" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.najlepszeplatformyforex.pl/blog/broker-xtb/" target="_blank"><img src="https://nestjs.com/img/npf-logo.jpg" width="200" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://thestandarddaily.com/" target="_blank"><img src="https://nestjs.com/img/the-standard-daily-logo.png" width="180" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://houseofangular.io/" target="_blank"><img src="https://nestjs.com/img/house-of-angular.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://rocketech.it/cases/?utm_source=google&utm_medium=badge&utm_campaign=nestjs" target="_blank"><img src="https://nestjs.com/img/rocketech-logo.svg" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.bystored.com/" target="_blank"><img src="https://nestjs.com/img/stored-logo.svg" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://studyclerk.com/pay-for-research-paper" target="_blank"><img src="https://nestjs.com/img/studyclerk-logo.png" width="125" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://xyndata.com" target="_blank"><img src="https://nestjs.com/img/xyndata-logo.png" width="125" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.anonymistic.com/" target="_blank"><img src="https://nestjs.com/img/anonymistic-logo.png" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://messaged.com/" target="_blank"><img src="https://nestjs.com/img/messaged-logo.png" width="50" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/triplecore-logo.svg" width="50" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://klqc.de" target="_blank"><img src="https://nestjs.com/img/klcqcl-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://thecasinowizard.com/bonuses/no-deposit-bonuses/" target="_blank"><img src="https://nestjs.com/img/casinowizard-logo.png" width="120" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://polygon-software.ch/" target="_blank"><img src="https://nestjs.com/img/polygon-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://themobilereality.com/" target="_blank"><img src="https://nestjs.com/img/mobile-reality-logo.png" width="45" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -142,9 +145,9 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
|
||||
## Stay in touch
|
||||
|
||||
- Author - [Kamil Myśliwiec](https://x.com/kammysliwiec)
|
||||
- Website - [https://nestjs.com](https://nestjs.com/)
|
||||
- X - [@nestframework](https://x.com/nestframework)
|
||||
* Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec)
|
||||
* Website - [https://nestjs.com](https://nestjs.com/)
|
||||
* Twitter - [@nestframework](https://twitter.com/nestframework)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -158,15 +158,15 @@ export function Controller(
|
||||
)
|
||||
? [defaultPath, undefined, undefined, undefined]
|
||||
: isString(prefixOrOptions) || Array.isArray(prefixOrOptions)
|
||||
? [prefixOrOptions, undefined, undefined, undefined]
|
||||
: [
|
||||
prefixOrOptions.path || defaultPath,
|
||||
prefixOrOptions.host,
|
||||
{ scope: prefixOrOptions.scope, durable: prefixOrOptions.durable },
|
||||
Array.isArray(prefixOrOptions.version)
|
||||
? Array.from(new Set(prefixOrOptions.version))
|
||||
: prefixOrOptions.version,
|
||||
];
|
||||
? [prefixOrOptions, undefined, undefined, undefined]
|
||||
: [
|
||||
prefixOrOptions.path || defaultPath,
|
||||
prefixOrOptions.host,
|
||||
{ scope: prefixOrOptions.scope, durable: prefixOrOptions.durable },
|
||||
Array.isArray(prefixOrOptions.version)
|
||||
? Array.from(new Set(prefixOrOptions.version))
|
||||
: prefixOrOptions.version,
|
||||
];
|
||||
|
||||
return (target: object) => {
|
||||
Reflect.defineMetadata(CONTROLLER_WATERMARK, true, target);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
PARAMTYPES_METADATA,
|
||||
PROPERTY_DEPS_METADATA,
|
||||
SELF_DECLARED_DEPS_METADATA,
|
||||
} from '../../constants';
|
||||
@@ -37,14 +36,8 @@ import { isUndefined } from '../../utils/shared.utils';
|
||||
export function Inject<T = any>(
|
||||
token?: T,
|
||||
): PropertyDecorator & ParameterDecorator {
|
||||
const injectCallHasArguments = arguments.length > 0;
|
||||
|
||||
return (target: object, key: string | symbol | undefined, index?: number) => {
|
||||
let type = token || Reflect.getMetadata('design:type', target, key);
|
||||
// Try to infer the token in a constructor-based injection
|
||||
if (!type && !injectCallHasArguments) {
|
||||
type = Reflect.getMetadata(PARAMTYPES_METADATA, target, key)?.[index];
|
||||
}
|
||||
const type = token || Reflect.getMetadata('design:type', target, key);
|
||||
|
||||
if (!isUndefined(index)) {
|
||||
let dependencies =
|
||||
|
||||
@@ -15,7 +15,7 @@ export type CustomDecorator<TKey = string> = MethodDecorator &
|
||||
*
|
||||
* Example: `@SetMetadata('roles', ['admin'])`
|
||||
*
|
||||
* @see [Reflection](https://docs.nestjs.com/fundamentals/execution-context#reflection-and-metadata)
|
||||
* @see [Reflection](https://docs.nestjs.com/guards#reflection)
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
|
||||
@@ -12,7 +12,6 @@ export type ParamDecoratorEnhancer = ParameterDecorator;
|
||||
* Defines HTTP route param decorator
|
||||
*
|
||||
* @param factory
|
||||
* @param enhancers
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,6 @@ import { extendArrayMetadata } from '../../utils/extend-metadata.util';
|
||||
*
|
||||
* For example:
|
||||
* `@Header('Cache-Control', 'none')`
|
||||
* `@Header('Cache-Control', () => 'none')`
|
||||
*
|
||||
* @param name string to be used for header name
|
||||
* @param value string to be used for header value
|
||||
@@ -15,10 +14,7 @@ import { extendArrayMetadata } from '../../utils/extend-metadata.util';
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function Header(
|
||||
name: string,
|
||||
value: string | (() => string),
|
||||
): MethodDecorator {
|
||||
export function Header(name: string, value: string): MethodDecorator {
|
||||
return (
|
||||
target: object,
|
||||
key: string | symbol,
|
||||
|
||||
@@ -111,7 +111,7 @@ export const Head = createMappingDecorator(RequestMethod.HEAD);
|
||||
export const All = createMappingDecorator(RequestMethod.ALL);
|
||||
|
||||
/**
|
||||
* Route handler (method) Decorator. Routes HTTP SEARCH requests to the specified path.
|
||||
* Route handler (method) Decorator. Routes all HTTP requests to the specified path.
|
||||
*
|
||||
* @see [Routing](https://docs.nestjs.com/controllers#routing)
|
||||
*
|
||||
|
||||
@@ -508,53 +508,6 @@ export function Body(
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route handler parameter decorator. Extracts the `rawBody` Buffer
|
||||
* property from the `req` object and populates the decorated parameter with that value.
|
||||
*
|
||||
* For example:
|
||||
* ```typescript
|
||||
* async create(@RawBody() rawBody: Buffer | undefined)
|
||||
* ```
|
||||
*
|
||||
* @see [Request object](https://docs.nestjs.com/controllers#request-object)
|
||||
* @see [Raw body](https://docs.nestjs.com/faq/raw-body)
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function RawBody(): ParameterDecorator;
|
||||
|
||||
/**
|
||||
* Route handler parameter decorator. Extracts the `rawBody` Buffer
|
||||
* property from the `req` object and populates the decorated parameter with that value.
|
||||
* Also applies pipes to the bound rawBody parameter.
|
||||
*
|
||||
* For example:
|
||||
* ```typescript
|
||||
* async create(@RawBody(new ValidationPipe()) rawBody: Buffer)
|
||||
* ```
|
||||
*
|
||||
* @param pipes one or more pipes - either instances or classes - to apply to
|
||||
* the bound body parameter.
|
||||
*
|
||||
* @see [Request object](https://docs.nestjs.com/controllers#request-object)
|
||||
* @see [Raw body](https://docs.nestjs.com/faq/raw-body)
|
||||
* @see [Working with pipes](https://docs.nestjs.com/custom-decorators#working-with-pipes)
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function RawBody(
|
||||
...pipes: (
|
||||
| Type<PipeTransform<Buffer | undefined>>
|
||||
| PipeTransform<Buffer | undefined>
|
||||
)[]
|
||||
): ParameterDecorator {
|
||||
return createPipesRouteParamDecorator(RouteParamtypes.RAW_BODY)(
|
||||
undefined,
|
||||
...pipes,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route handler parameter decorator. Extracts the `params`
|
||||
* property from the `req` object and populates the decorated
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
export enum RouteParamtypes {
|
||||
REQUEST = 0,
|
||||
RESPONSE = 1,
|
||||
NEXT = 2,
|
||||
BODY = 3,
|
||||
QUERY = 4,
|
||||
PARAM = 5,
|
||||
HEADERS = 6,
|
||||
SESSION = 7,
|
||||
FILE = 8,
|
||||
FILES = 9,
|
||||
HOST = 10,
|
||||
IP = 11,
|
||||
RAW_BODY = 12,
|
||||
REQUEST,
|
||||
RESPONSE,
|
||||
NEXT,
|
||||
BODY,
|
||||
QUERY,
|
||||
PARAM,
|
||||
HEADERS,
|
||||
SESSION,
|
||||
FILE,
|
||||
FILES,
|
||||
HOST,
|
||||
IP,
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
import { isObject, isString } from '../utils/shared.utils';
|
||||
|
||||
export interface HttpExceptionOptions {
|
||||
/** original cause of the error */
|
||||
cause?: unknown;
|
||||
cause?: Error;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
@@ -28,6 +27,7 @@ export class HttpException extends Error {
|
||||
* Instantiate a plain HTTP Exception.
|
||||
*
|
||||
* @example
|
||||
* throw new HttpException()
|
||||
* throw new HttpException('message', HttpStatus.BAD_REQUEST)
|
||||
* throw new HttpException('custom message', HttpStatus.BAD_REQUEST, {
|
||||
* cause: new Error('Cause Error'),
|
||||
@@ -68,13 +68,14 @@ export class HttpException extends Error {
|
||||
this.initCause();
|
||||
}
|
||||
|
||||
public cause: unknown;
|
||||
public cause: Error | undefined;
|
||||
|
||||
/**
|
||||
* Configures error chaining support
|
||||
*
|
||||
* @see https://nodejs.org/en/blog/release/v16.9.0/#error-cause
|
||||
* @see https://github.com/microsoft/TypeScript/issues/45167
|
||||
* See:
|
||||
* - https://nodejs.org/en/blog/release/v16.9.0/#error-cause
|
||||
* - https://github.com/microsoft/TypeScript/issues/45167
|
||||
*/
|
||||
public initCause(): void {
|
||||
if (this.options?.cause) {
|
||||
|
||||
@@ -1,22 +1,10 @@
|
||||
/**
|
||||
* Options for `StreamableFile`
|
||||
*
|
||||
* @see [Streaming files](https://docs.nestjs.com/techniques/streaming-files)
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export interface StreamableFileOptions {
|
||||
/**
|
||||
* The value that will be used for the `Content-Type` response header.
|
||||
* @default `"application/octet-stream"`
|
||||
*/
|
||||
type?: string;
|
||||
/**
|
||||
* The value that will be used for the `Content-Disposition` response header.
|
||||
*/
|
||||
disposition?: string;
|
||||
/**
|
||||
* The value that will be used for the `Content-Length` response header.
|
||||
*/
|
||||
length?: number;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { types } from 'util';
|
||||
import { HttpStatus } from '../enums';
|
||||
import { isFunction } from '../utils/shared.utils';
|
||||
import { StreamableFileOptions, StreamableHandlerResponse } from './interfaces';
|
||||
import { Logger } from '../services';
|
||||
|
||||
/**
|
||||
* @see [Streaming files](https://docs.nestjs.com/techniques/streaming-files)
|
||||
@@ -12,7 +11,6 @@ import { Logger } from '../services';
|
||||
*/
|
||||
export class StreamableFile {
|
||||
private readonly stream: Readable;
|
||||
protected logger = new Logger('StreamableFile');
|
||||
|
||||
protected handleError: (
|
||||
err: Error,
|
||||
@@ -30,10 +28,6 @@ export class StreamableFile {
|
||||
res.send(err.message);
|
||||
};
|
||||
|
||||
protected logError: (err: Error) => void = (err: Error) => {
|
||||
this.logger.error(err.message, err.stack);
|
||||
};
|
||||
|
||||
constructor(buffer: Uint8Array, options?: StreamableFileOptions);
|
||||
constructor(readable: Readable, options?: StreamableFileOptions);
|
||||
constructor(
|
||||
@@ -80,13 +74,4 @@ export class StreamableFile {
|
||||
this.handleError = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
get errorLogger() {
|
||||
return this.logError;
|
||||
}
|
||||
|
||||
setErrorLogger(handler: (err: Error) => void) {
|
||||
this.logError = handler;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ export {
|
||||
HttpServer,
|
||||
HttpExceptionBody,
|
||||
HttpExceptionBodyMessage,
|
||||
HttpRedirectResponse,
|
||||
INestApplication,
|
||||
INestApplicationContext,
|
||||
INestMicroservice,
|
||||
|
||||
@@ -56,7 +56,7 @@ export interface CorsOptions {
|
||||
}
|
||||
|
||||
export interface CorsOptionsCallback {
|
||||
(error: Error | null, options: CorsOptions): void;
|
||||
(error: Error, options: CorsOptions): void;
|
||||
}
|
||||
export interface CorsOptionsDelegate<T> {
|
||||
(req: T, cb: CorsOptionsCallback): void;
|
||||
|
||||
@@ -96,10 +96,4 @@ export interface HttpsOptions {
|
||||
* the default callback with high-level API will be used.
|
||||
*/
|
||||
SNICallback?: (servername: string, cb: (err: Error, ctx: any) => any) => any;
|
||||
/**
|
||||
* Optionally affect the OpenSSL protocol behavior, which is not usually necessary.
|
||||
* This should be used carefully if at all! Value is a numeric bitmask of the SSL_OP_* options
|
||||
* from OpenSSL Options.
|
||||
*/
|
||||
secureOptions?: number;
|
||||
}
|
||||
|
||||
@@ -31,10 +31,6 @@ export interface WsArgumentsHost {
|
||||
* Returns the client object.
|
||||
*/
|
||||
getClient<T = any>(): T;
|
||||
/**
|
||||
* Returns the pattern for the event
|
||||
*/
|
||||
getPattern(): string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import { HttpStatus } from '../../enums';
|
||||
|
||||
export interface HttpRedirectResponse {
|
||||
url: string;
|
||||
statusCode: HttpStatus;
|
||||
}
|
||||
@@ -51,8 +51,6 @@ export interface HttpServer<
|
||||
all(handler: RequestHandler<TRequest, TResponse>): any;
|
||||
options(handler: RequestHandler<TRequest, TResponse>): any;
|
||||
options(path: string, handler: RequestHandler<TRequest, TResponse>): any;
|
||||
search?(handler: RequestHandler<TRequest, TResponse>): any;
|
||||
search?(path: string, handler: RequestHandler<TRequest, TResponse>): any;
|
||||
listen(port: number | string, callback?: () => void): any;
|
||||
listen(port: number | string, hostname: string, callback?: () => void): any;
|
||||
reply(response: any, body: any, statusCode?: number): any;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export * from './http-exception-body.interface';
|
||||
export * from './http-redirect-response.interface';
|
||||
export * from './http-server.interface';
|
||||
export * from './message-event.interface';
|
||||
export * from './raw-body-request.interface';
|
||||
|
||||
@@ -7,7 +7,7 @@ import { MiddlewareConsumer } from './middleware-consumer.interface';
|
||||
*/
|
||||
export interface MiddlewareConfigProxy {
|
||||
/**
|
||||
* Routes to exclude from the current middleware.
|
||||
* Excludes routes from the currently processed middleware.
|
||||
*
|
||||
* @param {(string | RouteInfo)[]} routes
|
||||
* @returns {MiddlewareConfigProxy}
|
||||
@@ -15,9 +15,8 @@ export interface MiddlewareConfigProxy {
|
||||
exclude(...routes: (string | RouteInfo)[]): MiddlewareConfigProxy;
|
||||
|
||||
/**
|
||||
* Attaches either routes or controllers to the current middleware.
|
||||
* If you pass a controller class, Nest will attach the current middleware to every path
|
||||
* defined within it.
|
||||
* Attaches passed either routes or controllers to the currently configured middleware.
|
||||
* If you pass a class, Nest would attach middleware to every path defined within this controller.
|
||||
*
|
||||
* @param {(string | Type | RouteInfo)[]} routes
|
||||
* @returns {MiddlewareConsumer}
|
||||
|
||||
@@ -20,7 +20,7 @@ import { generateOptionsInjectionToken, getInjectionProviders } from './utils';
|
||||
*/
|
||||
export interface ConfigurableModuleBuilderOptions {
|
||||
/**
|
||||
* Specifies what injection token should be used for the module options provider.
|
||||
* Specified what injection token should be used for the module options provider.
|
||||
* By default, an auto-generated UUID will be used.
|
||||
*/
|
||||
optionsInjectionToken?: string | symbol;
|
||||
@@ -29,11 +29,11 @@ export interface ConfigurableModuleBuilderOptions {
|
||||
* Explicitly specifying the "moduleName" will instruct the "ConfigurableModuleBuilder"
|
||||
* to use a more descriptive provider token.
|
||||
*
|
||||
* For example, `moduleName: "Cache"` will auto-generate the provider token: "CACHE_MODULE_OPTIONS".
|
||||
* For example, if `moduleName: "Cache"` then auto-generated provider token will be "CACHE_MODULE_OPTIONS".
|
||||
*/
|
||||
moduleName?: string;
|
||||
/**
|
||||
* Indicates whether module should always be "transient" - meaning,
|
||||
* Indicates whether module should always be "transient", meaning,
|
||||
* every time you call the static method to construct a dynamic module,
|
||||
* regardless of what arguments you pass in, a new "unique" module will be created.
|
||||
*
|
||||
@@ -51,8 +51,7 @@ export interface ConfigurableModuleBuilderOptions {
|
||||
export class ConfigurableModuleBuilder<
|
||||
ModuleOptions,
|
||||
StaticMethodKey extends string = typeof DEFAULT_METHOD_KEY,
|
||||
FactoryClassMethodKey extends
|
||||
string = typeof DEFAULT_FACTORY_CLASS_METHOD_KEY,
|
||||
FactoryClassMethodKey extends string = typeof DEFAULT_FACTORY_CLASS_METHOD_KEY,
|
||||
ExtraModuleDefinitionOptions = {},
|
||||
> {
|
||||
protected staticMethodKey: StaticMethodKey;
|
||||
|
||||
@@ -28,8 +28,7 @@ export type ConfigurableModuleOptionsFactory<
|
||||
*/
|
||||
export interface ConfigurableModuleAsyncOptions<
|
||||
ModuleOptions,
|
||||
FactoryClassMethodKey extends
|
||||
string = typeof DEFAULT_FACTORY_CLASS_METHOD_KEY,
|
||||
FactoryClassMethodKey extends string = typeof DEFAULT_FACTORY_CLASS_METHOD_KEY,
|
||||
> extends Pick<ModuleMetadata, 'imports'> {
|
||||
/**
|
||||
* Injection token resolving to an existing provider. The provider must implement
|
||||
|
||||
@@ -15,8 +15,7 @@ import { ConfigurableModuleAsyncOptions } from './configurable-module-async-opti
|
||||
export type ConfigurableModuleCls<
|
||||
ModuleOptions,
|
||||
MethodKey extends string = typeof DEFAULT_METHOD_KEY,
|
||||
FactoryClassMethodKey extends
|
||||
string = typeof DEFAULT_FACTORY_CLASS_METHOD_KEY,
|
||||
FactoryClassMethodKey extends string = typeof DEFAULT_FACTORY_CLASS_METHOD_KEY,
|
||||
ExtraModuleDefinitionOptions = {},
|
||||
> = {
|
||||
new (): any;
|
||||
|
||||
@@ -42,7 +42,8 @@ export function getInjectionProviders(
|
||||
// get injection tokens of the matched providers, if any
|
||||
search = match
|
||||
.filter(p => (p as any)?.inject)
|
||||
.flatMap(p => (p as FactoryProvider).inject)
|
||||
.map(p => (p as FactoryProvider).inject)
|
||||
.flat()
|
||||
.map(mapInjectToTokens);
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/common",
|
||||
"version": "10.4.8",
|
||||
"version": "9.4.2",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@common)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"homepage": "https://nestjs.com",
|
||||
@@ -19,13 +19,13 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iterare": "1.2.1",
|
||||
"tslib": "2.7.0",
|
||||
"tslib": "2.5.2",
|
||||
"uid": "2.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"class-transformer": "*",
|
||||
"class-validator": "*",
|
||||
"reflect-metadata": "^0.1.12 || ^0.2.0",
|
||||
"reflect-metadata": "^0.1.12",
|
||||
"rxjs": "^7.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
|
||||
@@ -16,21 +16,17 @@ export type FileTypeValidatorOptions = {
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export class FileTypeValidator extends FileValidator<
|
||||
FileTypeValidatorOptions,
|
||||
IFile
|
||||
> {
|
||||
export class FileTypeValidator extends FileValidator<FileTypeValidatorOptions> {
|
||||
buildErrorMessage(): string {
|
||||
return `Validation failed (expected type is ${this.validationOptions.fileType})`;
|
||||
}
|
||||
|
||||
isValid(file?: IFile): boolean {
|
||||
isValid<TFile extends IFile = any>(file: TFile): boolean {
|
||||
if (!this.validationOptions) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (
|
||||
!!file &&
|
||||
'mimetype' in file &&
|
||||
!!file.mimetype.match(this.validationOptions.fileType)
|
||||
);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user