mirror of
https://github.com/nestjs/nest.git
synced 2026-02-24 00:02:56 +00:00
Compare commits
1 Commits
feat/allow
...
renovate/n
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e304e50c89 |
@@ -1,127 +1,89 @@
|
||||
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
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
- &install-deps
|
||||
run:
|
||||
name: Install dependencies
|
||||
command: npm ci --legacy-peer-deps
|
||||
name: Install dependencies
|
||||
command: npm ci
|
||||
- &build-packages
|
||||
run:
|
||||
name: Build
|
||||
command: npm run build
|
||||
name: Build
|
||||
command: npm run build
|
||||
- &run-unit-tests
|
||||
run:
|
||||
name: Test
|
||||
command: npm run test
|
||||
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: circleci/node:12
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Update NPM version
|
||||
command: 'sudo npm install -g npm@^9'
|
||||
- *restore-cache
|
||||
- *install-deps
|
||||
- *save-cache
|
||||
- *build-packages
|
||||
|
||||
test:
|
||||
parameters:
|
||||
node-version:
|
||||
type: string
|
||||
command: 'sudo npm install -g npm@latest'
|
||||
- restore_cache:
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm ci
|
||||
- save_cache:
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
paths:
|
||||
- ./node_modules
|
||||
- run:
|
||||
name: Build
|
||||
command: npm run build
|
||||
|
||||
test_node_12:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:<< parameters.node-version >>
|
||||
- image: circleci/node:12
|
||||
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-unit-tests
|
||||
- run:
|
||||
name: Collect coverage
|
||||
command: npm run coverage
|
||||
- store_artifacts:
|
||||
path: coverage
|
||||
|
||||
test_node_10:
|
||||
<<: *unit-tests-template
|
||||
docker:
|
||||
- image: circleci/node:10
|
||||
|
||||
test_node_14:
|
||||
<<: *unit-tests-template
|
||||
docker:
|
||||
- image: circleci/node:14
|
||||
|
||||
test_node_16:
|
||||
<<: *unit-tests-template
|
||||
docker:
|
||||
- image: circleci/node:16
|
||||
|
||||
lint:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:<< pipeline.parameters.maintenance-node-version >>
|
||||
- image: circleci/node:12
|
||||
steps:
|
||||
- checkout
|
||||
- *restore-cache
|
||||
@@ -129,23 +91,26 @@ 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
|
||||
machine: true
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
- run:
|
||||
name: Prepare nvm
|
||||
command: |
|
||||
echo 'export NVM_DIR="/opt/circleci/.nvm"' >> $BASH_ENV
|
||||
echo ' [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV
|
||||
- run:
|
||||
- run:
|
||||
name: Upgrade Node.js
|
||||
command: |
|
||||
nvm install << pipeline.parameters.maintenance-node-version >>
|
||||
nvm install v12
|
||||
node -v
|
||||
nvm alias default << pipeline.parameters.maintenance-node-version >>
|
||||
nvm alias default v12
|
||||
- run:
|
||||
name: Install Docker Compose
|
||||
command: |
|
||||
@@ -164,11 +129,11 @@ jobs:
|
||||
- run:
|
||||
name: Integration tests
|
||||
command: npm run test:integration
|
||||
|
||||
|
||||
codechecks_benchmarks:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:<< pipeline.parameters.maintenance-node-version >>
|
||||
- image: circleci/node:12
|
||||
steps:
|
||||
- checkout
|
||||
- *restore-cache
|
||||
@@ -184,9 +149,9 @@ jobs:
|
||||
samples:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:<< pipeline.parameters.maintenance-node-version >>
|
||||
- image: circleci/node:12
|
||||
environment:
|
||||
DISABLE_OPENCOLLECTIVE: 'true'
|
||||
- DISABLE_OPENCOLLECTIVE: true
|
||||
steps:
|
||||
- checkout
|
||||
- *restore-cache
|
||||
@@ -196,21 +161,22 @@ jobs:
|
||||
command: npm run build:samples
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build-and-test:
|
||||
jobs:
|
||||
- build
|
||||
- test:
|
||||
- test_node_16:
|
||||
requires:
|
||||
- build
|
||||
- test_node_14:
|
||||
requires:
|
||||
- build
|
||||
- test_node_12:
|
||||
requires:
|
||||
- build
|
||||
- test_node_10:
|
||||
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
|
||||
|
||||
@@ -6,8 +6,8 @@ cd "$(dirname "$0")"
|
||||
|
||||
cd /tmp/
|
||||
sudo apt-get install build-essential libssl-dev git -y
|
||||
git clone --depth=1 https://github.com/wg/wrk.git wrk
|
||||
git clone https://github.com/wg/wrk.git wrk
|
||||
cd wrk
|
||||
sudo make
|
||||
# move the executable to somewhere in your PATH, ex:
|
||||
sudo cp wrk /usr/local/bin
|
||||
sudo cp wrk /usr/local/bin
|
||||
@@ -23,22 +23,6 @@
|
||||
"test",
|
||||
"sample"
|
||||
]
|
||||
],
|
||||
"scope-enum": [
|
||||
1,
|
||||
"always",
|
||||
[
|
||||
"common",
|
||||
"core",
|
||||
"sample",
|
||||
"microservices",
|
||||
"express",
|
||||
"fastify",
|
||||
"socket.io",
|
||||
"ws",
|
||||
"testing",
|
||||
"websockets"
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
**/node_modules/**
|
||||
*.d.ts
|
||||
*.js
|
||||
**/node_modules/**
|
||||
60
.eslintrc.js
60
.eslintrc.js
@@ -1,47 +1,25 @@
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'prettier',
|
||||
],
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'prettier',
|
||||
],
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/*.ts'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
sourceType: 'module',
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/interface-name-prefix': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-array-constructor': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.spec.ts', 'integration/**/*.ts'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.spec.json',
|
||||
sourceType: 'module',
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/interface-name-prefix': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
},
|
||||
}
|
||||
]
|
||||
rules: {
|
||||
'@typescript-eslint/interface-name-prefix': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
},
|
||||
};
|
||||
|
||||
13
.eslintrc.spec.js
Normal file
13
.eslintrc.spec.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const baseConfig = require('./.eslintrc');
|
||||
|
||||
module.exports = {
|
||||
...baseConfig,
|
||||
parserOptions: {
|
||||
project: 'tsconfig.spec.json',
|
||||
sourceType: 'module',
|
||||
},
|
||||
rules: {
|
||||
...baseConfig.rules,
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
},
|
||||
};
|
||||
12
.github/ISSUE_TEMPLATE/Bug_report.yml
vendored
12
.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`
|
||||
@@ -61,7 +57,7 @@ body:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Expected behavior"
|
||||
description: "A clear and concise description of what you expected to happened (or code)"
|
||||
description: "A clear and concise description of what you expected to happend (or code)"
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
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
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/Regression.yml
vendored
4
.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
|
||||
@@ -74,7 +74,7 @@ body:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Expected behavior"
|
||||
description: "A clear and concise description of what you expected to happened (or code)"
|
||||
description: "A clear and concise description of what you expected to happend (or code)"
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
||||
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
@@ -5,8 +5,3 @@ updates:
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 10
|
||||
|
||||
15
.github/workflows/codeql-analysis.yml
vendored
15
.github/workflows/codeql-analysis.yml
vendored
@@ -9,19 +9,14 @@ on:
|
||||
schedule:
|
||||
- cron: '0 17 * * 4'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
analyse:
|
||||
permissions:
|
||||
security-events: write
|
||||
name: Analyse
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
@@ -34,9 +29,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
queries: +security-extended
|
||||
uses: github/codeql-action/init@v1
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
@@ -44,7 +37,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@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -58,4 +51,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v1
|
||||
|
||||
17
.gitignore
vendored
17
.gitignore
vendored
@@ -1,5 +1,3 @@
|
||||
packages/*/package-lock.json
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
@@ -7,19 +5,8 @@ node_modules/
|
||||
/.idea
|
||||
/.awcache
|
||||
/.vscode
|
||||
/.devcontainer
|
||||
/.classpath
|
||||
/.project
|
||||
/.settings
|
||||
*.code-workspace
|
||||
|
||||
# Vim
|
||||
[._]*.s[a-v][a-z]
|
||||
[._]*.sw[a-p]
|
||||
[._]s[a-rt-v][a-z]
|
||||
[._]ss[a-gi-z]
|
||||
[._]sw[a-p]
|
||||
|
||||
# bundle
|
||||
packages/**/*.d.ts
|
||||
packages/**/*.js
|
||||
@@ -32,7 +19,6 @@ yarn-error.log
|
||||
/**/npm-debug.log
|
||||
/packages/**/.npmignore
|
||||
/packages/**/LICENSE
|
||||
*.tsbuildinfo
|
||||
|
||||
# example
|
||||
/quick-start
|
||||
@@ -47,6 +33,3 @@ yarn-error.log
|
||||
/packages/graphql
|
||||
/benchmarks/memory
|
||||
build/config\.gypi
|
||||
|
||||
.npmrc
|
||||
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
|
||||
|
||||
7
.mocharc.js
Normal file
7
.mocharc.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
mochaHooks: {
|
||||
beforeAll: function() {
|
||||
require('reflect-metadata');
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -10,6 +10,4 @@
|
||||
package-lock.json
|
||||
tslint.json
|
||||
tsconfig.json
|
||||
.prettierrc
|
||||
|
||||
*.tsbuildinfo
|
||||
.prettierrc
|
||||
@@ -1,3 +1,2 @@
|
||||
packages/**/*.d.ts
|
||||
packages/**/*.js
|
||||
.nyc_output
|
||||
packages/**/*.js
|
||||
@@ -19,7 +19,7 @@ Help us keep Nest open and inclusive. Please read and follow our [Code of Conduc
|
||||
|
||||
## <a name="question"></a> Got a Question or Problem?
|
||||
|
||||
**Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.** You've got much better chances of getting your question answered on [Stack Overflow][stackoverflow] where the questions should be tagged with tag `nestjs`.
|
||||
**Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.** You've got much better chances of getting your question answered on [Stack Overflow](https://stackoverflow.com/questions/tagged/nestjs) where the questions should be tagged with tag `nestjs`.
|
||||
|
||||
Stack Overflow is a much better place to ask questions since:
|
||||
|
||||
@@ -71,7 +71,7 @@ A minimal reproduce scenario using a repository or Gist allows us to quickly con
|
||||
|
||||
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced.
|
||||
|
||||
You can file new issues by filling out our [new issue form][new_issue].
|
||||
You can file new issues by filling out our [new issue form](https://github.com/nestjs/nest/issues/new).
|
||||
|
||||
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
||||
|
||||
@@ -84,9 +84,9 @@ To the first point
|
||||
We cannot accept code without this.
|
||||
-->
|
||||
|
||||
1. Search [GitHub Pull Requests][gh_prs] for an open or closed PR
|
||||
1. Search [GitHub](https://github.com/nestjs/nest/pulls) for an open or closed PR
|
||||
that relates to your submission. You don't want to duplicate effort.
|
||||
1. Fork this repository.
|
||||
1. Fork the nestjs/nest repo.
|
||||
1. Make your changes in a new git branch:
|
||||
|
||||
```shell
|
||||
@@ -159,12 +159,12 @@ from the main (upstream) repository:
|
||||
|
||||
## <a name="development"></a> Development Setup
|
||||
|
||||
You will need [Node.js](https://nodejs.org) version >= 10.13.0 (except for v13).
|
||||
You will need Node.js version 8.9.0+.
|
||||
|
||||
1. After cloning the repo, run:
|
||||
|
||||
```bash
|
||||
$ npm ci --legacy-peer-deps # (or yarn install)
|
||||
$ npm i # (or yarn install)
|
||||
```
|
||||
|
||||
2. In order to prepare your environment run `prepare.sh` shell script:
|
||||
@@ -233,7 +233,7 @@ to read on GitHub as well as in various git tools.
|
||||
|
||||
Footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
|
||||
|
||||
Samples: (even more [samples][commits_samples])
|
||||
Samples: (even more [samples](https://github.com/nestjs/nest/commits/master))
|
||||
|
||||
```
|
||||
docs(changelog): update change log to beta.5
|
||||
@@ -262,22 +262,16 @@ Must be one of the following:
|
||||
|
||||
### Scope
|
||||
|
||||
The scope should have the name of the npm package affected (as perceived by person reading changelog generated from commit messages).
|
||||
The scope should be the name of the npm package affected (as perceived by person reading changelog generated from commit messages.
|
||||
|
||||
The following is the list of supported scopes:
|
||||
|
||||
- **common**: for changes made on `packages/common` directory
|
||||
- **core**: for changes made on `packages/core` directory
|
||||
- **sample**: for changes made on `packages/sample` directory
|
||||
- **microservices**: for changes made on `packages/microservices` directory
|
||||
- **express**: for changes made on `packages/platform-express` directory
|
||||
- **fastify**: for changes made on `packages/platform-fastify` directory
|
||||
- **socket.io**: for changes made on `packages/platform-socket.io` directory
|
||||
- **ws**: for changes made on `packages/platform-ws` directory
|
||||
- **testing**: for changes made on `packages/testing` directory
|
||||
- **websockets**: for changes made on `packages/websockets` directory
|
||||
|
||||
If your change affect more than one package, separate the scopes with a comma (e.g. `common,core`).
|
||||
- **common**
|
||||
- **core**
|
||||
- **sample**
|
||||
- **microservices**
|
||||
- **testing**
|
||||
- **websockets**
|
||||
|
||||
There are currently a few exceptions to the "use package name" rule:
|
||||
|
||||
@@ -285,6 +279,7 @@ There are currently a few exceptions to the "use package name" rule:
|
||||
- **changelog**: used for updating the release notes in CHANGELOG.md
|
||||
- **sample/#**: for the example apps directory, replacing # with the example app number
|
||||
- none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`)
|
||||
<!-- * **aio**: used for docs-app (angular.io) related changes within the /aio directory of the repo -->
|
||||
|
||||
### Subject
|
||||
|
||||
@@ -322,13 +317,14 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
|
||||
<!-- [coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md -->
|
||||
|
||||
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
||||
<!-- [individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html -->
|
||||
<!-- [corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html -->
|
||||
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
||||
[dev-doc]: https://github.com/nestjs/nest/blob/master/docs/DEVELOPER.md
|
||||
[github]: https://github.com/nestjs/nest
|
||||
[stackoverflow]: https://stackoverflow.com/questions/tagged/nestjs
|
||||
[discord]: https://discordapp.com/invite/G7Qnnhy
|
||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
||||
[new_issue]: https://github.com/nestjs/nest/issues/new
|
||||
[gh_prs]: https://github.com/nestjs/nest/pulls
|
||||
[commits_samples]: https://github.com/nestjs/nest/commits/master
|
||||
[jsfiddle]: http://jsfiddle.net
|
||||
[plunker]: http://plnkr.co/edit
|
||||
[runnable]: http://runnable.com
|
||||
|
||||
<!-- [stackoverflow]: http://stackoverflow.com/questions/tagged/angular -->
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2017-2024 Kamil Mysliwiec <https://kamilmysliwiec.com>
|
||||
Copyright (c) 2017-2022 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
|
||||
|
||||
156
Readme.md
156
Readme.md
@@ -1,16 +1,17 @@
|
||||
<p align="center">
|
||||
<a href="https://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="120" alt="Nest Logo" /></a>
|
||||
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="120" alt="Nest Logo" /></a>
|
||||
</p>
|
||||
|
||||
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
|
||||
[circleci-url]: https://circleci.com/gh/nestjs/nest
|
||||
|
||||
<p align="center">A progressive <a href="https://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
|
||||
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
|
||||
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
|
||||
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
|
||||
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
|
||||
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
|
||||
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
|
||||
@@ -23,21 +24,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 +57,74 @@ 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>
|
||||
</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://careers.labster.com/departments/platform" target="_blank"><img src="https://nestjs.com/img/labster-logo.png" width="170" valign="middle" /></a></td><td>
|
||||
<a href="https://weld.app/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="150" 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://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/intrinisic-logo.png" width="210" 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>
|
||||
<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></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://mobilereality.pl/" 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>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -142,9 +132,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
|
||||
|
||||
|
||||
@@ -2,6 +2,4 @@
|
||||
|
||||
const fastify = require('fastify')();
|
||||
fastify.get('/', async (req, reply) => reply.send('Hello world'));
|
||||
fastify.listen({
|
||||
port: 3000
|
||||
});
|
||||
fastify.listen(3000);
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
export const mochaHooks = (): Mocha.RootHookObject => {
|
||||
return {
|
||||
async beforeAll(this: Mocha.Context) {
|
||||
await import('reflect-metadata');
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -3,9 +3,10 @@ import { FooService } from './foo.service';
|
||||
|
||||
@Injectable()
|
||||
export class BarService {
|
||||
|
||||
constructor(private readonly foo: FooService) {}
|
||||
|
||||
bar() {
|
||||
this.foo.foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ describe('Auto-Mocking with token in factory', () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
providers: [BarService],
|
||||
})
|
||||
.useMocker(token => {
|
||||
.useMocker((token) => {
|
||||
if (token === FooService) {
|
||||
return { foo: sinon.stub };
|
||||
}
|
||||
@@ -48,13 +48,16 @@ describe('Auto-Mocking with token in factory', () => {
|
||||
expect(fooServ.foo.called);
|
||||
});
|
||||
it('cannot mock the dependencies', async () => {
|
||||
|
||||
const moduleRef = Test.createTestingModule({
|
||||
providers: [BarService],
|
||||
}).useMocker(token => {
|
||||
if (token === FooService.name + 'something that fails the token') {
|
||||
return { foo: sinon.stub };
|
||||
}
|
||||
}).compile;
|
||||
expect(moduleRef()).to.eventually.throw();
|
||||
})
|
||||
.useMocker((token) => {
|
||||
if (token === FooService.name + 'something that fails the token') {
|
||||
return { foo: sinon.stub };
|
||||
}
|
||||
})
|
||||
.compile;
|
||||
expect(moduleRef()).to.eventually.throw()
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,28 +7,10 @@
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES2021",
|
||||
"target": "es6",
|
||||
"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/*"]
|
||||
}
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
|
||||
31
integration/cache/e2e/multi-store.spec.ts
vendored
Normal file
31
integration/cache/e2e/multi-store.spec.ts
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { MultiStoreModule } from '../src/multi-store/multi-store.module';
|
||||
|
||||
describe('Caching Multi Store', () => {
|
||||
let server;
|
||||
let app: INestApplication;
|
||||
|
||||
before(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [MultiStoreModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
server = app.getHttpServer();
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`should return empty`, async () => {
|
||||
return request(server).get('/').expect(200, '');
|
||||
});
|
||||
|
||||
it(`should return data`, async () => {
|
||||
return request(server).get('/').expect(200, 'multi-store-value');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
16
integration/cache/src/multi-store/multi-store.controller.ts
vendored
Normal file
16
integration/cache/src/multi-store/multi-store.controller.ts
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Controller, Get, Inject, CACHE_MANAGER } from '@nestjs/common';
|
||||
import { Cache } from 'cache-manager';
|
||||
|
||||
@Controller()
|
||||
export class MultiStoreController {
|
||||
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
|
||||
|
||||
@Get()
|
||||
async getFromMultiStore(): Promise<unknown> {
|
||||
const value = await this.cacheManager.get('multi-store-key');
|
||||
if (!value) {
|
||||
await this.cacheManager.set('multi-store-key', 'multi-store-value');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
24
integration/cache/src/multi-store/multi-store.module.ts
vendored
Normal file
24
integration/cache/src/multi-store/multi-store.module.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import { CacheModule, Module } from '@nestjs/common';
|
||||
import * as redisStore from 'cache-manager-redis-store';
|
||||
import { MultiStoreController } from './multi-store.controller';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
CacheModule.register([
|
||||
{
|
||||
store: 'memory',
|
||||
max: 100,
|
||||
ttl: 10,
|
||||
},
|
||||
{
|
||||
store: redisStore,
|
||||
host: 'localhost',
|
||||
port: 6379,
|
||||
db: 0,
|
||||
ttl: 600,
|
||||
},
|
||||
]),
|
||||
],
|
||||
controllers: [MultiStoreController],
|
||||
})
|
||||
export class MultiStoreModule {}
|
||||
@@ -4,11 +4,10 @@
|
||||
"declaration": false,
|
||||
"noImplicitAny": false,
|
||||
"removeComments": true,
|
||||
"lib": ["dom"],
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES2021",
|
||||
"target": "es6",
|
||||
"sourceMap": true,
|
||||
"allowJs": true,
|
||||
"outDir": "./dist"
|
||||
@@ -18,6 +17,6 @@
|
||||
"e2e/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
"node_modules",
|
||||
]
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { NestExpressApplication } from '@nestjs/platform-express';
|
||||
import { NestFastifyApplication } from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
describe('Express Cors', () => {
|
||||
let app: NestExpressApplication;
|
||||
let app: NestFastifyApplication;
|
||||
const configs = [
|
||||
{
|
||||
origin: 'example.com',
|
||||
@@ -30,7 +30,7 @@ describe('Express Cors', () => {
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication<NestExpressApplication>();
|
||||
app = module.createNestApplication<NestFastifyApplication>();
|
||||
|
||||
let requestId = 0;
|
||||
const configDelegation = function (req, cb) {
|
||||
@@ -84,7 +84,7 @@ describe('Express Cors', () => {
|
||||
cb(null, config);
|
||||
};
|
||||
|
||||
app = module.createNestApplication<NestExpressApplication>({
|
||||
app = module.createNestApplication<NestFastifyApplication>(null, {
|
||||
cors: configDelegation,
|
||||
});
|
||||
|
||||
@@ -126,7 +126,7 @@ describe('Express Cors', () => {
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication<NestExpressApplication>();
|
||||
app = module.createNestApplication<NestFastifyApplication>();
|
||||
app.enableCors(configs[0]);
|
||||
|
||||
await app.init();
|
||||
@@ -153,7 +153,7 @@ describe('Express Cors', () => {
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication<NestExpressApplication>({
|
||||
app = module.createNestApplication<NestFastifyApplication>(null, {
|
||||
cors: configs[0],
|
||||
});
|
||||
await app.init();
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import {
|
||||
FastifyAdapter,
|
||||
NestFastifyApplication,
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { NestFastifyApplication } from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
describe.skip('Fastify Cors', () => {
|
||||
describe('Fastify Cors', () => {
|
||||
let app: NestFastifyApplication;
|
||||
const configs = [
|
||||
{
|
||||
@@ -33,9 +30,7 @@ describe.skip('Fastify Cors', () => {
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
);
|
||||
app = module.createNestApplication<NestFastifyApplication>();
|
||||
|
||||
let requestId = 0;
|
||||
const configDelegation = function (req, cb) {
|
||||
@@ -89,12 +84,9 @@ describe.skip('Fastify Cors', () => {
|
||||
cb(null, config);
|
||||
};
|
||||
|
||||
app = module.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
{
|
||||
cors: configDelegation,
|
||||
},
|
||||
);
|
||||
app = module.createNestApplication<NestFastifyApplication>(null, {
|
||||
cors: configDelegation,
|
||||
});
|
||||
|
||||
await app.init();
|
||||
});
|
||||
@@ -135,9 +127,7 @@ describe.skip('Fastify Cors', () => {
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
);
|
||||
app = module.createNestApplication<NestFastifyApplication>();
|
||||
app.enableCors(configs[0]);
|
||||
|
||||
await app.init();
|
||||
@@ -157,19 +147,16 @@ describe.skip('Fastify Cors', () => {
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
|
||||
describe('Application Options', () => {
|
||||
before(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
{
|
||||
cors: configs[0],
|
||||
},
|
||||
);
|
||||
app = module.createNestApplication<NestFastifyApplication>(null, {
|
||||
cors: configs[0],
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
|
||||
@@ -7,28 +7,10 @@
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES2021",
|
||||
"target": "es6",
|
||||
"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/*"]
|
||||
}
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
}
|
||||
@@ -17,15 +17,13 @@ services:
|
||||
restart: always
|
||||
mqtt:
|
||||
container_name: test-mqtt
|
||||
image: eclipse-mosquitto
|
||||
volumes:
|
||||
- ./mosquitto.conf:/mosquitto/config/mosquitto.conf
|
||||
image: toke/mosquitto
|
||||
ports:
|
||||
- "1883:1883"
|
||||
- "9001:9001"
|
||||
restart: always
|
||||
mysql:
|
||||
image: mysql:8.3.0
|
||||
image: mysql:8.0.27
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: test
|
||||
@@ -50,7 +48,7 @@ services:
|
||||
zookeeper:
|
||||
container_name: test-zookeeper
|
||||
hostname: zookeeper
|
||||
image: confluentinc/cp-zookeeper:7.5.3
|
||||
image: confluentinc/cp-zookeeper:7.0.1
|
||||
ports:
|
||||
- "2181:2181"
|
||||
environment:
|
||||
@@ -59,7 +57,7 @@ services:
|
||||
kafka:
|
||||
container_name: test-kafka
|
||||
hostname: kafka
|
||||
image: confluentinc/cp-kafka:7.5.3
|
||||
image: confluentinc/cp-kafka:7.0.1
|
||||
depends_on:
|
||||
- zookeeper
|
||||
ports:
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
describe('GraphQL - Code-first', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
describe('GraphQL - Guards', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { INestApplication, ValidationPipe } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
describe('GraphQL Pipes', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
@@ -30,8 +30,8 @@ describe('GraphQL Pipes', () => {
|
||||
errors: [
|
||||
{
|
||||
extensions: {
|
||||
code: 'BAD_REQUEST',
|
||||
originalError: {
|
||||
code: 'BAD_USER_INPUT',
|
||||
response: {
|
||||
error: 'Bad Request',
|
||||
message: [
|
||||
'description must be longer than or equal to 30 characters',
|
||||
@@ -39,14 +39,7 @@ describe('GraphQL Pipes', () => {
|
||||
statusCode: 400,
|
||||
},
|
||||
},
|
||||
locations: [
|
||||
{
|
||||
column: 3,
|
||||
line: 2,
|
||||
},
|
||||
],
|
||||
message: 'Bad Request Exception',
|
||||
path: ['addRecipe'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -15,7 +15,7 @@ scalar Date
|
||||
|
||||
type Query {
|
||||
recipe(id: String!): Recipe!
|
||||
recipes(skip: Int! = 0, take: Int! = 25): [Recipe!]!
|
||||
recipes(skip: Int = 0, take: Int = 25): [Recipe!]!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
@@ -31,4 +31,4 @@ input NewRecipeInput {
|
||||
|
||||
type Subscription {
|
||||
recipeAdded: Recipe!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { RecipesModule } from './recipes/recipes.module';
|
||||
RecipesModule,
|
||||
GraphQLModule.forRoot<ApolloDriverConfig>({
|
||||
driver: ApolloDriver,
|
||||
includeStacktraceInErrorResponses: false,
|
||||
debug: false,
|
||||
installSubscriptionHandlers: true,
|
||||
autoSchemaFile: join(
|
||||
process.cwd(),
|
||||
@@ -18,4 +18,4 @@ import { RecipesModule } from './recipes/recipes.module';
|
||||
}),
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
export class ApplicationModule {}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ValidationPipe } from '@nestjs/common';
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
import { ApplicationModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
const app = await NestFactory.create(ApplicationModule);
|
||||
app.useGlobalPipes(new ValidationPipe());
|
||||
await app.listen(3000);
|
||||
}
|
||||
|
||||
@@ -7,34 +7,16 @@
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES2021",
|
||||
"target": "es6",
|
||||
"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/*"]
|
||||
}
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"e2e/**/*"
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
describe('GraphQL', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
|
||||
@@ -9,9 +9,8 @@ import { CatsModule } from './cats/cats.module';
|
||||
CatsModule,
|
||||
GraphQLModule.forRoot<ApolloDriverConfig>({
|
||||
driver: ApolloDriver,
|
||||
includeStacktraceInErrorResponses: true,
|
||||
typePaths: [join(__dirname, '**', '*.graphql')],
|
||||
}),
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
export class ApplicationModule {}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
import { ApplicationModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
const app = await NestFactory.create(ApplicationModule);
|
||||
await app.listen(3000);
|
||||
}
|
||||
bootstrap();
|
||||
|
||||
@@ -7,34 +7,17 @@
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES2021",
|
||||
"target": "es6",
|
||||
"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/*"]
|
||||
}
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"e2e/**/*"
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
@@ -1,135 +1,39 @@
|
||||
import { HttpStatus, INestApplication } from '@nestjs/common';
|
||||
import {
|
||||
FastifyAdapter,
|
||||
NestFastifyApplication,
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import { RawServerDefault } from 'fastify';
|
||||
import * as request from 'supertest';
|
||||
import { ErrorsController } from '../src/errors/errors.controller';
|
||||
|
||||
describe('Error messages', () => {
|
||||
let server: RawServerDefault;
|
||||
let server;
|
||||
let app: INestApplication;
|
||||
|
||||
describe('Express', () => {
|
||||
let app: INestApplication;
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
controllers: [ErrorsController],
|
||||
}).compile();
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
controllers: [ErrorsController],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
server = app.getHttpServer();
|
||||
await app.init();
|
||||
});
|
||||
app = module.createNestApplication();
|
||||
server = app.getHttpServer();
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`/GET`, () => {
|
||||
return request(server)
|
||||
.get('/sync')
|
||||
.expect(HttpStatus.BAD_REQUEST)
|
||||
.expect({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'Integration test',
|
||||
});
|
||||
});
|
||||
|
||||
it(`/GET (Promise/async)`, () => {
|
||||
return request(server)
|
||||
.get('/async')
|
||||
.expect(HttpStatus.BAD_REQUEST)
|
||||
.expect({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'Integration test',
|
||||
});
|
||||
});
|
||||
|
||||
it(`/GET (InternalServerError despite custom content-type)`, async () => {
|
||||
return request(server)
|
||||
.get('/unexpected-error')
|
||||
.expect(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.expect({
|
||||
statusCode: 500,
|
||||
message: 'Internal server error',
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
it(`/GET`, () => {
|
||||
return request(server).get('/sync').expect(HttpStatus.BAD_REQUEST).expect({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'Integration test',
|
||||
});
|
||||
});
|
||||
|
||||
describe('Fastify', () => {
|
||||
let app: NestFastifyApplication;
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
controllers: [ErrorsController],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
);
|
||||
server = app.getHttpServer();
|
||||
await app.init();
|
||||
it(`/GET (Promise/async)`, () => {
|
||||
return request(server).get('/async').expect(HttpStatus.BAD_REQUEST).expect({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'Integration test',
|
||||
});
|
||||
});
|
||||
|
||||
it(`/GET`, async () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/sync',
|
||||
})
|
||||
.then(({ payload, statusCode }) => {
|
||||
expect(statusCode).to.equal(HttpStatus.BAD_REQUEST);
|
||||
expect(payload).to.equal(
|
||||
JSON.stringify({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'Integration test',
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it(`/GET (Promise/async)`, async () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/sync',
|
||||
})
|
||||
.then(({ payload, statusCode }) => {
|
||||
expect(statusCode).to.equal(HttpStatus.BAD_REQUEST);
|
||||
expect(payload).to.equal(
|
||||
JSON.stringify({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: 'Integration test',
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it(`/GET (InternalServerError despite custom content-type)`, async () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/unexpected-error',
|
||||
})
|
||||
.then(({ payload, statusCode }) => {
|
||||
expect(statusCode).to.equal(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
expect(payload).to.equal(
|
||||
JSON.stringify({
|
||||
statusCode: 500,
|
||||
message: 'Internal server error',
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
const RETURN_VALUE = 'test';
|
||||
const MIDDLEWARE_VALUE = 'middleware';
|
||||
@@ -57,7 +57,7 @@ class TestController {
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
controllers: [TestController],
|
||||
})
|
||||
class TestModule {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
const RETURN_VALUE = 'test';
|
||||
const MIDDLEWARE_VALUE = 'middleware';
|
||||
@@ -45,15 +45,10 @@ class TestController {
|
||||
overviewById() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('multiple/exclude')
|
||||
multipleExclude() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
controllers: [TestController],
|
||||
})
|
||||
class TestModule {
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ExpressAdapter } from '@nestjs/platform-express';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as express from 'express';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
describe('Hello world (express instance)', () => {
|
||||
let server;
|
||||
@@ -11,7 +11,7 @@ describe('Hello world (express instance)', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication(new ExpressAdapter(express()));
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ExpressAdapter } from '@nestjs/platform-express';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as express from 'express';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
describe('Hello world (express instance with multiple applications)', () => {
|
||||
let server;
|
||||
@@ -11,10 +11,10 @@ describe('Hello world (express instance with multiple applications)', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
const module1 = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
}).compile();
|
||||
const module2 = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
}).compile();
|
||||
|
||||
const adapter = new ExpressAdapter(express());
|
||||
|
||||
@@ -4,14 +4,14 @@ import {
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
describe('Hello world (fastify adapter)', () => {
|
||||
let app: NestFastifyApplication;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication<NestFastifyApplication>(
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
import { APP_GUARD } from '@nestjs/core';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuard {
|
||||
@@ -20,7 +20,7 @@ export class AuthGuard {
|
||||
|
||||
function createTestModule(guard) {
|
||||
return Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
providers: [
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as request from 'supertest';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
describe('Hello world (default adapter)', () => {
|
||||
let server;
|
||||
@@ -9,7 +9,7 @@ describe('Hello world (default adapter)', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Test } from '@nestjs/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
const RETURN_VALUE = 'test';
|
||||
|
||||
@@ -58,7 +58,7 @@ export class HeaderInterceptor {
|
||||
|
||||
function createTestModule(interceptor) {
|
||||
return Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
providers: [
|
||||
{
|
||||
provide: APP_INTERCEPTOR,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
describe('Hello world (default adapter)', () => {
|
||||
let server;
|
||||
@@ -9,7 +9,7 @@ describe('Hello world (default adapter)', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
import { Response } from 'express';
|
||||
|
||||
const INCLUDED_VALUE = 'test_included';
|
||||
@@ -32,7 +32,7 @@ class TestController {
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
controllers: [TestController],
|
||||
})
|
||||
class TestModule {
|
||||
|
||||
@@ -3,10 +3,7 @@ import {
|
||||
Get,
|
||||
MiddlewareConsumer,
|
||||
Module,
|
||||
NestMiddleware,
|
||||
NestModule,
|
||||
Query,
|
||||
Req,
|
||||
RequestMethod,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
@@ -15,387 +12,180 @@ import {
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
const INCLUDED_VALUE = 'test_included';
|
||||
const QUERY_VALUE = 'test_query';
|
||||
const REQ_URL_VALUE = 'test_req_url';
|
||||
const RETURN_VALUE = 'test';
|
||||
const SCOPED_VALUE = 'test_scoped';
|
||||
const WILDCARD_VALUE = 'test_wildcard';
|
||||
|
||||
@Controller()
|
||||
class TestController {
|
||||
@Get('express_style_wildcard/wildcard_nested')
|
||||
express_style_wildcard() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('test')
|
||||
test() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('query')
|
||||
query() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('tests/wildcard_nested')
|
||||
wildcard_nested() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('tests/included')
|
||||
included() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Controller(QUERY_VALUE)
|
||||
class TestQueryController {
|
||||
@Get()
|
||||
[QUERY_VALUE](@Query('test') test: string) {
|
||||
return test;
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [ApplicationModule],
|
||||
controllers: [TestController, TestQueryController],
|
||||
})
|
||||
class TestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply((req, res, next) => res.end(INCLUDED_VALUE))
|
||||
.forRoutes({ path: 'tests/included', method: RequestMethod.POST })
|
||||
.apply((req, res, next) => res.end(`${REQ_URL_VALUE}${req.url}`))
|
||||
.forRoutes('req/url/')
|
||||
.apply((req, res, next) => res.end(WILDCARD_VALUE))
|
||||
.forRoutes('express_style_wildcard/*', 'tests/(.*)')
|
||||
.apply((req, res, next) => res.end(QUERY_VALUE))
|
||||
.forRoutes('query')
|
||||
.apply((req, res, next) => next())
|
||||
.forRoutes(TestQueryController)
|
||||
.apply((req, res, next) => res.end(SCOPED_VALUE))
|
||||
.forRoutes(TestController)
|
||||
.apply((req, res, next) => res.end(RETURN_VALUE))
|
||||
.exclude({ path: QUERY_VALUE, method: -1 })
|
||||
.forRoutes('(.*)');
|
||||
}
|
||||
}
|
||||
|
||||
describe('Middleware (FastifyAdapter)', () => {
|
||||
let app: NestFastifyApplication;
|
||||
|
||||
describe('should return expected values depending on the route', () => {
|
||||
const INCLUDED_VALUE = 'test_included';
|
||||
const QUERY_VALUE = 'test_query';
|
||||
const REQ_URL_VALUE = 'test_req_url';
|
||||
const RETURN_VALUE = 'test';
|
||||
const SCOPED_VALUE = 'test_scoped';
|
||||
const WILDCARD_VALUE = 'test_wildcard';
|
||||
beforeEach(async () => {
|
||||
app = (
|
||||
await Test.createTestingModule({
|
||||
imports: [TestModule],
|
||||
}).compile()
|
||||
).createNestApplication<NestFastifyApplication>(new FastifyAdapter());
|
||||
|
||||
@Controller()
|
||||
class TestController {
|
||||
@Get('express_style_wildcard/wildcard_nested')
|
||||
express_style_wildcard() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('test')
|
||||
test() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('query')
|
||||
query() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('tests/wildcard_nested')
|
||||
wildcard_nested() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('tests/included')
|
||||
included() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Controller(QUERY_VALUE)
|
||||
class TestQueryController {
|
||||
@Get()
|
||||
[QUERY_VALUE](@Query('test') test: string) {
|
||||
return test;
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [AppModule],
|
||||
controllers: [TestController, TestQueryController],
|
||||
})
|
||||
class TestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply((req, res, next) => res.end(INCLUDED_VALUE))
|
||||
.forRoutes({ path: 'tests/included', method: RequestMethod.POST })
|
||||
.apply((req, res, next) => res.end(REQ_URL_VALUE))
|
||||
.forRoutes('req/url/(.*)')
|
||||
.apply((req, res, next) => res.end(WILDCARD_VALUE))
|
||||
.forRoutes('express_style_wildcard/*', 'tests/(.*)')
|
||||
.apply((req, res, next) => res.end(QUERY_VALUE))
|
||||
.forRoutes('query')
|
||||
.apply((req, res, next) => next())
|
||||
.forRoutes(TestQueryController)
|
||||
.apply((req, res, next) => res.end(SCOPED_VALUE))
|
||||
.forRoutes(TestController)
|
||||
.apply((req, res, next) => res.end(RETURN_VALUE))
|
||||
.exclude({ path: QUERY_VALUE, method: -1 as any })
|
||||
.forRoutes('(.*)');
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
app = (
|
||||
await Test.createTestingModule({
|
||||
imports: [TestModule],
|
||||
}).compile()
|
||||
).createNestApplication<NestFastifyApplication>(new FastifyAdapter());
|
||||
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`forRoutes((.*))`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/hello',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(RETURN_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(TestController)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/test',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(SCOPED_VALUE));
|
||||
});
|
||||
|
||||
it(`query?test=${QUERY_VALUE} forRoutes(query)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/query',
|
||||
query: {
|
||||
test: QUERY_VALUE,
|
||||
},
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(QUERY_VALUE));
|
||||
});
|
||||
|
||||
it(`${QUERY_VALUE}?test=${QUERY_VALUE} forRoutes(${QUERY_VALUE})`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: QUERY_VALUE,
|
||||
query: {
|
||||
test: QUERY_VALUE,
|
||||
},
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(QUERY_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(tests/(.*))`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/tests/wildcard_nested',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(express_style_wildcard/*)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/express_style_wildcard/wildcard_nested',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(req/url/)`, () => {
|
||||
const reqUrl = '/test';
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: `/req/url${reqUrl}`,
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(REQ_URL_VALUE));
|
||||
});
|
||||
|
||||
it(`GET forRoutes(POST tests/included)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/tests/included',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
it(`POST forRoutes(POST tests/included)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'POST',
|
||||
url: '/tests/included',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(INCLUDED_VALUE));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
describe('should execute middleware only once for given routes', () => {
|
||||
class Middleware implements NestMiddleware {
|
||||
use(request: any, reply: any, next: () => void) {
|
||||
if (request.middlewareExecutionCount === undefined) {
|
||||
request.middlewareExecutionCount = 1;
|
||||
} else {
|
||||
request.middlewareExecutionCount++;
|
||||
}
|
||||
next();
|
||||
}
|
||||
}
|
||||
it(`forRoutes((.*))`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/hello',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(RETURN_VALUE));
|
||||
});
|
||||
|
||||
@Controller()
|
||||
class AbcController {
|
||||
@Get('/a')
|
||||
async a(@Req() request: any) {
|
||||
return this.validateExecutionCount({
|
||||
request,
|
||||
expected: 1,
|
||||
});
|
||||
}
|
||||
it(`forRoutes(TestController)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/test',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(SCOPED_VALUE));
|
||||
});
|
||||
|
||||
@Get('/a/b')
|
||||
async ab(@Req() request: any) {
|
||||
return this.validateExecutionCount({
|
||||
request,
|
||||
expected: 1,
|
||||
});
|
||||
}
|
||||
it(`query?test=${QUERY_VALUE} forRoutes(query)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/query',
|
||||
query: {
|
||||
test: QUERY_VALUE,
|
||||
},
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(QUERY_VALUE));
|
||||
});
|
||||
|
||||
@Get('/a/b/c')
|
||||
async abc(@Req() request: any) {
|
||||
return this.validateExecutionCount({
|
||||
request,
|
||||
expected: 1,
|
||||
});
|
||||
}
|
||||
it(`${QUERY_VALUE}?test=${QUERY_VALUE} forRoutes(${QUERY_VALUE})`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: QUERY_VALUE,
|
||||
query: {
|
||||
test: QUERY_VALUE,
|
||||
},
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(QUERY_VALUE));
|
||||
});
|
||||
|
||||
@Get('/similar')
|
||||
async withSimilar(@Req() request: any) {
|
||||
return this.validateExecutionCount({
|
||||
request,
|
||||
expected: 1,
|
||||
});
|
||||
}
|
||||
it(`forRoutes(tests/(.*))`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/tests/wildcard_nested',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
@Get('/similar/test')
|
||||
async withSimilarTest(@Req() request: any) {
|
||||
return this.validateExecutionCount({
|
||||
request,
|
||||
expected: 1,
|
||||
});
|
||||
}
|
||||
it(`forRoutes(express_style_wildcard/*)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/express_style_wildcard/wildcard_nested',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
@Get('/similar/:id')
|
||||
async withSimilarId(@Req() request: any) {
|
||||
return this.validateExecutionCount({
|
||||
request,
|
||||
expected: 1,
|
||||
});
|
||||
}
|
||||
it(`forRoutes(req/url/)`, () => {
|
||||
const reqUrl = '/test';
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: `/req/url${reqUrl}`,
|
||||
})
|
||||
.then(({ payload }) =>
|
||||
expect(payload).to.be.eql(`${REQ_URL_VALUE}${reqUrl}`),
|
||||
);
|
||||
});
|
||||
|
||||
private validateExecutionCount({
|
||||
request,
|
||||
expected,
|
||||
}: {
|
||||
request: any;
|
||||
expected: number;
|
||||
}) {
|
||||
let actual: number | undefined;
|
||||
actual = request.raw.middlewareExecutionCount;
|
||||
actual ??= 0;
|
||||
it(`GET forRoutes(POST tests/included)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/tests/included',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
return {
|
||||
success: actual === expected,
|
||||
actual,
|
||||
expected,
|
||||
};
|
||||
}
|
||||
}
|
||||
it(`POST forRoutes(POST tests/included)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'POST',
|
||||
url: '/tests/included',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(INCLUDED_VALUE));
|
||||
});
|
||||
|
||||
@Module({
|
||||
controllers: [AbcController],
|
||||
})
|
||||
class TestModule implements NestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer.apply(Middleware).forRoutes(AbcController);
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
app = (
|
||||
await Test.createTestingModule({
|
||||
imports: [TestModule],
|
||||
}).compile()
|
||||
).createNestApplication<NestFastifyApplication>(new FastifyAdapter());
|
||||
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`GET forRoutes(/a/b/c)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/a/b/c',
|
||||
})
|
||||
.then(({ payload }) => {
|
||||
expect(payload).to.be.eql(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
actual: 1,
|
||||
expected: 1,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it(`GET forRoutes(/a/b)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/a/b',
|
||||
})
|
||||
.then(({ payload }) =>
|
||||
expect(payload).to.be.eql(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
actual: 1,
|
||||
expected: 1,
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it(`GET forRoutes(/a)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/a',
|
||||
})
|
||||
.then(({ payload }) =>
|
||||
expect(payload).to.be.eql(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
actual: 1,
|
||||
expected: 1,
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it(`GET forRoutes(/similar)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/similar',
|
||||
})
|
||||
.then(({ payload }) =>
|
||||
expect(payload).to.be.eql(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
actual: 1,
|
||||
expected: 1,
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it(`GET forRoutes(/similar/test)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/similar/test',
|
||||
})
|
||||
.then(({ payload }) =>
|
||||
expect(payload).to.be.eql(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
actual: 1,
|
||||
expected: 1,
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it(`GET forRoutes(/similar/arbitrary)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/similar/arbitrary',
|
||||
})
|
||||
.then(({ payload }) =>
|
||||
expect(payload).to.be.eql(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
actual: 1,
|
||||
expected: 1,
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
INestApplication,
|
||||
Injectable,
|
||||
MiddlewareConsumer,
|
||||
NestMiddleware,
|
||||
Module,
|
||||
} from '@nestjs/common';
|
||||
import { Test } from '../../../packages/testing';
|
||||
import * as request from 'supertest';
|
||||
import { expect } from 'chai';
|
||||
|
||||
/**
|
||||
* Number of times that the middleware was executed.
|
||||
*/
|
||||
let triggerCounter = 0;
|
||||
@Injectable()
|
||||
class Middleware implements NestMiddleware {
|
||||
use(req, res, next) {
|
||||
triggerCounter++;
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
@Controller()
|
||||
class TestController {
|
||||
@Get('/test')
|
||||
testA() {}
|
||||
|
||||
@Get('/:id')
|
||||
testB() {}
|
||||
|
||||
@Get('/static/route')
|
||||
testC() {}
|
||||
|
||||
@Get('/:id/:nested')
|
||||
testD() {}
|
||||
}
|
||||
|
||||
@Module({
|
||||
controllers: [TestController],
|
||||
})
|
||||
class TestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer.apply(Middleware).forRoutes(TestController);
|
||||
}
|
||||
}
|
||||
|
||||
describe('Middleware (run on route match)', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
beforeEach(async () => {
|
||||
triggerCounter = 0;
|
||||
app = (
|
||||
await Test.createTestingModule({
|
||||
imports: [TestModule],
|
||||
}).compile()
|
||||
).createNestApplication();
|
||||
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`forRoutes(TestController) should execute middleware once when request url is equal match`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/test')
|
||||
.expect(200)
|
||||
.then(() => {
|
||||
expect(triggerCounter).to.be.eq(1);
|
||||
});
|
||||
});
|
||||
|
||||
it(`forRoutes(TestController) should execute middleware once when request url is not equal match`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/1')
|
||||
.expect(200)
|
||||
.then(() => {
|
||||
expect(triggerCounter).to.be.eq(1);
|
||||
});
|
||||
});
|
||||
|
||||
it(`forRoutes(TestController) should execute middleware once when request url is not of nested params`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/static/route')
|
||||
.expect(200)
|
||||
.then(() => {
|
||||
expect(triggerCounter).to.be.eq(1);
|
||||
});
|
||||
});
|
||||
|
||||
it(`forRoutes(TestController) should execute middleware once when request url is of nested params`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/1/abc')
|
||||
.expect(200)
|
||||
.then(() => {
|
||||
expect(triggerCounter).to.be.eq(1);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
@@ -1,171 +0,0 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
INestApplication,
|
||||
MiddlewareConsumer,
|
||||
Module,
|
||||
RequestMethod,
|
||||
Version,
|
||||
VersioningOptions,
|
||||
VersioningType,
|
||||
VERSION_NEUTRAL,
|
||||
} from '@nestjs/common';
|
||||
import { CustomVersioningOptions } from '@nestjs/common/interfaces';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
const RETURN_VALUE = 'test';
|
||||
const VERSIONED_VALUE = 'test_versioned';
|
||||
|
||||
@Controller()
|
||||
class TestController {
|
||||
@Version('1')
|
||||
@Get('versioned')
|
||||
versionedTest() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [AppModule],
|
||||
controllers: [TestController],
|
||||
})
|
||||
class TestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply((req, res, next) => res.send(VERSIONED_VALUE))
|
||||
.forRoutes({
|
||||
path: '/versioned',
|
||||
version: '1',
|
||||
method: RequestMethod.ALL,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
describe('Middleware', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
describe('when using default URI versioning', () => {
|
||||
beforeEach(async () => {
|
||||
app = await createAppWithVersioning({
|
||||
type: VersioningType.URI,
|
||||
defaultVersion: VERSION_NEUTRAL,
|
||||
});
|
||||
});
|
||||
|
||||
it(`forRoutes({ path: '/versioned', version: '1', method: RequestMethod.ALL })`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/versioned')
|
||||
.expect(200, VERSIONED_VALUE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when default URI versioning with an alternative prefix', () => {
|
||||
beforeEach(async () => {
|
||||
app = await createAppWithVersioning({
|
||||
type: VersioningType.URI,
|
||||
defaultVersion: VERSION_NEUTRAL,
|
||||
prefix: 'version',
|
||||
});
|
||||
});
|
||||
|
||||
it(`forRoutes({ path: '/versioned', version: '1', method: RequestMethod.ALL })`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/version1/versioned')
|
||||
.expect(200, VERSIONED_VALUE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when using default URI versioning with the global prefix', () => {
|
||||
beforeEach(async () => {
|
||||
app = await createAppWithVersioning(
|
||||
{
|
||||
type: VersioningType.URI,
|
||||
defaultVersion: VERSION_NEUTRAL,
|
||||
},
|
||||
async (app: INestApplication) => {
|
||||
app.setGlobalPrefix('api');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it(`forRoutes({ path: '/versioned', version: '1', method: RequestMethod.ALL })`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/api/v1/versioned')
|
||||
.expect(200, VERSIONED_VALUE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when using HEADER versioning', () => {
|
||||
beforeEach(async () => {
|
||||
app = await createAppWithVersioning({
|
||||
type: VersioningType.HEADER,
|
||||
header: 'version',
|
||||
});
|
||||
});
|
||||
|
||||
it(`forRoutes({ path: '/versioned', version: '1', method: RequestMethod.ALL })`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/versioned')
|
||||
.set('version', '1')
|
||||
.expect(200, VERSIONED_VALUE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when using MEDIA TYPE versioning', () => {
|
||||
beforeEach(async () => {
|
||||
app = await createAppWithVersioning({
|
||||
type: VersioningType.MEDIA_TYPE,
|
||||
key: 'v',
|
||||
defaultVersion: VERSION_NEUTRAL,
|
||||
});
|
||||
});
|
||||
|
||||
it(`forRoutes({ path: '/versioned', version: '1', method: RequestMethod.ALL })`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/versioned')
|
||||
.expect(200, VERSIONED_VALUE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when using CUSTOM TYPE versioning', () => {
|
||||
beforeEach(async () => {
|
||||
const extractor: CustomVersioningOptions['extractor'] = () => '1';
|
||||
|
||||
app = await createAppWithVersioning({
|
||||
type: VersioningType.CUSTOM,
|
||||
extractor,
|
||||
});
|
||||
});
|
||||
|
||||
it(`forRoutes({ path: '/versioned', version: '1', method: RequestMethod.ALL })`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/versioned')
|
||||
.expect(200, VERSIONED_VALUE);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
async function createAppWithVersioning(
|
||||
versioningOptions: VersioningOptions,
|
||||
beforeInit?: (app: INestApplication) => Promise<void>,
|
||||
): Promise<INestApplication> {
|
||||
const app = (
|
||||
await Test.createTestingModule({
|
||||
imports: [TestModule],
|
||||
}).compile()
|
||||
).createNestApplication();
|
||||
|
||||
app.enableVersioning(versioningOptions);
|
||||
if (beforeInit) {
|
||||
await beforeInit(app);
|
||||
}
|
||||
await app.init();
|
||||
|
||||
return app;
|
||||
}
|
||||
@@ -7,12 +7,11 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
const RETURN_VALUE = 'test';
|
||||
const SCOPED_VALUE = 'test_scoped';
|
||||
const WILDCARD_VALUE = 'test_wildcard';
|
||||
const EXCLUDE_VALUE = 'test_exclude';
|
||||
|
||||
@Controller()
|
||||
class TestController {
|
||||
@@ -25,15 +24,10 @@ class TestController {
|
||||
wildcard_nested() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('exclude')
|
||||
exclude() {
|
||||
return EXCLUDE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
controllers: [TestController],
|
||||
})
|
||||
class TestModule {
|
||||
@@ -42,10 +36,8 @@ class TestModule {
|
||||
.apply((req, res, next) => res.send(WILDCARD_VALUE))
|
||||
.forRoutes('tests/*')
|
||||
.apply((req, res, next) => res.send(SCOPED_VALUE))
|
||||
.exclude('exclude')
|
||||
.forRoutes(TestController)
|
||||
.apply((req, res, next) => res.send(RETURN_VALUE))
|
||||
.exclude('exclude')
|
||||
.forRoutes('*');
|
||||
}
|
||||
}
|
||||
@@ -53,34 +45,25 @@ class TestModule {
|
||||
describe('Middleware', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
it(`forRoutes(*)`, async () => {
|
||||
app = await createApp();
|
||||
await request(app.getHttpServer()).get('/hello').expect(200, RETURN_VALUE);
|
||||
await request(app.getHttpServer())
|
||||
.get('/exclude')
|
||||
.expect(200, EXCLUDE_VALUE);
|
||||
beforeEach(async () => {
|
||||
app = (
|
||||
await Test.createTestingModule({
|
||||
imports: [TestModule],
|
||||
}).compile()
|
||||
).createNestApplication();
|
||||
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`forRoutes(*) with global prefix`, async () => {
|
||||
app = await createApp(app => app.setGlobalPrefix('api'));
|
||||
await request(app.getHttpServer())
|
||||
.get('/api/hello')
|
||||
.expect(200, RETURN_VALUE);
|
||||
await request(app.getHttpServer())
|
||||
.get('/api/exclude')
|
||||
.expect(200, EXCLUDE_VALUE);
|
||||
it(`forRoutes(*)`, () => {
|
||||
return request(app.getHttpServer()).get('/hello').expect(200, RETURN_VALUE);
|
||||
});
|
||||
|
||||
it(`forRoutes(TestController)`, async () => {
|
||||
app = await createApp();
|
||||
await request(app.getHttpServer()).get('/test').expect(200, SCOPED_VALUE);
|
||||
await request(app.getHttpServer())
|
||||
.get('/exclude')
|
||||
.expect(200, EXCLUDE_VALUE);
|
||||
it(`forRoutes(TestController)`, () => {
|
||||
return request(app.getHttpServer()).get('/test').expect(200, SCOPED_VALUE);
|
||||
});
|
||||
|
||||
it(`forRoutes(tests/*)`, async () => {
|
||||
app = await createApp();
|
||||
it(`forRoutes(tests/*)`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/tests/wildcard')
|
||||
.expect(200, WILDCARD_VALUE);
|
||||
@@ -90,20 +73,3 @@ describe('Middleware', () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
async function createApp(
|
||||
beforeInit?: (app: INestApplication) => void,
|
||||
): Promise<INestApplication> {
|
||||
const app = (
|
||||
await Test.createTestingModule({
|
||||
imports: [TestModule],
|
||||
}).compile()
|
||||
).createNestApplication();
|
||||
|
||||
if (beforeInit) {
|
||||
beforeInit(app);
|
||||
}
|
||||
await app.init();
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import { RouterModule } from '@nestjs/core';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
const RETURN_VALUE = 'test';
|
||||
const SCOPED_VALUE = 'test_scoped';
|
||||
@@ -27,7 +27,7 @@ class TestController {
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [AppModule],
|
||||
imports: [ApplicationModule],
|
||||
controllers: [TestController],
|
||||
})
|
||||
class TestModule {
|
||||
|
||||
@@ -6,4 +6,4 @@ import { HostModule } from './host/host.module';
|
||||
@Module({
|
||||
imports: [HelloModule, HostModule, HostArrayModule],
|
||||
})
|
||||
export class AppModule {}
|
||||
export class ApplicationModule {}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BadRequestException, Controller, Get, Header } from '@nestjs/common';
|
||||
import { BadRequestException, Controller, Get } from '@nestjs/common';
|
||||
|
||||
@Controller()
|
||||
export class ErrorsController {
|
||||
@@ -12,12 +12,6 @@ export class ErrorsController {
|
||||
this.throwError();
|
||||
}
|
||||
|
||||
@Get('unexpected-error')
|
||||
@Header('Content-Type', 'application/pdf')
|
||||
unexpectedError() {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
throwError() {
|
||||
throw new BadRequestException({
|
||||
statusCode: 400,
|
||||
|
||||
@@ -7,28 +7,10 @@
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES2021",
|
||||
"target": "es6",
|
||||
"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/*"]
|
||||
}
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
|
||||
@@ -43,7 +43,10 @@ describe('OnModuleDestroy', () => {
|
||||
it('should sort modules by distance (topological sort) - DESC order', async () => {
|
||||
@Injectable()
|
||||
class BB implements OnModuleDestroy {
|
||||
onModuleDestroy = Sinon.spy();
|
||||
public field: string;
|
||||
async onModuleDestroy() {
|
||||
this.field = 'b-field';
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
@@ -54,10 +57,13 @@ describe('OnModuleDestroy', () => {
|
||||
|
||||
@Injectable()
|
||||
class AA implements OnModuleDestroy {
|
||||
public field: string;
|
||||
constructor(private bb: BB) {}
|
||||
onModuleDestroy = Sinon.spy();
|
||||
}
|
||||
|
||||
async onModuleDestroy() {
|
||||
this.field = this.bb.field + '_a-field';
|
||||
}
|
||||
}
|
||||
@Module({
|
||||
imports: [B],
|
||||
providers: [AA],
|
||||
@@ -72,8 +78,7 @@ describe('OnModuleDestroy', () => {
|
||||
await app.init();
|
||||
await app.close();
|
||||
|
||||
const aa = module.get(AA);
|
||||
const bb = module.get(BB);
|
||||
Sinon.assert.callOrder(aa.onModuleDestroy, bb.onModuleDestroy);
|
||||
const instance = module.get(AA);
|
||||
expect(instance.field).to.equal('b-field_a-field');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -39,39 +39,11 @@ describe('OnModuleInit', () => {
|
||||
});
|
||||
|
||||
it('should sort modules by distance (topological sort) - DESC order', async () => {
|
||||
@Injectable()
|
||||
class CC implements OnModuleInit {
|
||||
public field: string;
|
||||
|
||||
async onModuleInit() {
|
||||
this.field = 'c-field';
|
||||
}
|
||||
}
|
||||
|
||||
@Module({})
|
||||
class C {
|
||||
static forRoot() {
|
||||
return {
|
||||
module: C,
|
||||
global: true,
|
||||
providers: [
|
||||
{
|
||||
provide: CC,
|
||||
useValue: new CC(),
|
||||
},
|
||||
],
|
||||
exports: [CC],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class BB implements OnModuleInit {
|
||||
public field: string;
|
||||
constructor(private cc: CC) {}
|
||||
|
||||
async onModuleInit() {
|
||||
this.field = this.cc.field + '_b-field';
|
||||
this.field = 'b-field';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,19 +68,14 @@ describe('OnModuleInit', () => {
|
||||
})
|
||||
class A {}
|
||||
|
||||
@Module({
|
||||
imports: [A, C.forRoot()],
|
||||
})
|
||||
class AppModule {}
|
||||
|
||||
const module = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
imports: [A],
|
||||
}).compile();
|
||||
|
||||
const app = module.createNestApplication();
|
||||
await app.init();
|
||||
|
||||
const instance = module.get(AA);
|
||||
expect(instance.field).to.equal('c-field_b-field_a-field');
|
||||
expect(instance.field).to.equal('b-field_a-field');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,28 +7,10 @@
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES2021",
|
||||
"target": "es6",
|
||||
"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/*"]
|
||||
}
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
|
||||
@@ -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.',
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,10 +1,7 @@
|
||||
import { RuntimeException } from '@nestjs/core/errors/exceptions/runtime.exception';
|
||||
import { UnknownDependenciesException } from '@nestjs/core/errors/exceptions/unknown-dependencies.exception';
|
||||
import { UnknownExportException } from '@nestjs/core/errors/exceptions/unknown-export.exception';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import * as chai from 'chai';
|
||||
import * as chaiAsPromised from 'chai-as-promised';
|
||||
import {
|
||||
DYNAMIC_TOKEN,
|
||||
DYNAMIC_VALUE,
|
||||
@@ -12,13 +9,6 @@ import {
|
||||
} from '../src/dynamic/dynamic.module';
|
||||
import { ExportsModule } from '../src/exports/exports.module';
|
||||
import { InjectModule } from '../src/inject/inject.module';
|
||||
import { InjectSameNameModule } from '../src/inject/inject-same-name.module';
|
||||
import {
|
||||
SelfInjectionProviderModule,
|
||||
SelfInjectionProviderCustomTokenModule,
|
||||
SelfInjectionForwardProviderModule,
|
||||
} from '../src/self-injection/self-injection-provider.module';
|
||||
chai.use(chaiAsPromised);
|
||||
|
||||
describe('Injector', () => {
|
||||
describe('when "providers" and "exports" properties are inconsistent', () => {
|
||||
@@ -34,16 +24,6 @@ describe('Injector', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("When class injects a provider with the same as class's name", () => {
|
||||
it('should compile with success', async () => {
|
||||
const builder = Test.createTestingModule({
|
||||
imports: [InjectSameNameModule],
|
||||
});
|
||||
|
||||
await expect(builder.compile()).to.eventually.be.fulfilled;
|
||||
});
|
||||
});
|
||||
|
||||
describe('when Nest cannot resolve dependencies', () => {
|
||||
it(`should fail with "RuntimeException"`, async () => {
|
||||
try {
|
||||
@@ -55,42 +35,6 @@ describe('Injector', () => {
|
||||
expect(err).to.be.instanceof(RuntimeException);
|
||||
}
|
||||
});
|
||||
|
||||
describe('due to self-injection providers', () => {
|
||||
it('should fail with "UnknownDependenciesException" due to self-injection via same class reference', async () => {
|
||||
const builder = Test.createTestingModule({
|
||||
imports: [SelfInjectionProviderModule],
|
||||
});
|
||||
|
||||
await expect(
|
||||
builder.compile(),
|
||||
).to.eventually.be.rejected.and.be.an.instanceOf(
|
||||
UnknownDependenciesException,
|
||||
);
|
||||
});
|
||||
it('should fail with "UnknownDependenciesException" due to self-injection via forwardRef to the same class reference', async () => {
|
||||
const builder = Test.createTestingModule({
|
||||
imports: [SelfInjectionForwardProviderModule],
|
||||
});
|
||||
|
||||
await expect(
|
||||
builder.compile(),
|
||||
).to.eventually.be.rejected.and.be.an.instanceOf(
|
||||
UnknownDependenciesException,
|
||||
);
|
||||
});
|
||||
it('should fail with "UnknownDependenciesException" due to self-injection via custom provider', async () => {
|
||||
const builder = Test.createTestingModule({
|
||||
imports: [SelfInjectionProviderCustomTokenModule],
|
||||
});
|
||||
|
||||
await expect(
|
||||
builder.compile(),
|
||||
).to.eventually.be.rejected.and.be.an.instanceOf(
|
||||
UnknownDependenciesException,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when dynamic module', () => {
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import { MultipleProvidersModule } from '../src/multiple-providers/multiple-providers.module';
|
||||
|
||||
describe('Multiple providers under the same token ("each" feature)', () => {
|
||||
describe('get()', () => {
|
||||
it('should return an array of providers', async () => {
|
||||
const builder = Test.createTestingModule({
|
||||
imports: [MultipleProvidersModule],
|
||||
});
|
||||
const testingModule = await builder.compile();
|
||||
|
||||
const multiProviderInstances = testingModule.get<string>(
|
||||
'MULTI_PROVIDER',
|
||||
{
|
||||
each: true,
|
||||
},
|
||||
);
|
||||
|
||||
// @ts-expect-error: make sure "multiProviderInstances" is string[] not string
|
||||
multiProviderInstances.charAt;
|
||||
|
||||
expect(multiProviderInstances).to.be.eql(['A', 'B', 'C']);
|
||||
});
|
||||
});
|
||||
describe('resolve()', () => {
|
||||
it('should return an array of providers', async () => {
|
||||
const builder = Test.createTestingModule({
|
||||
imports: [MultipleProvidersModule],
|
||||
});
|
||||
const testingModule = await builder.compile();
|
||||
|
||||
const multiProviderInstances = await testingModule.resolve<string>(
|
||||
'REQ_SCOPED_MULTI_PROVIDER',
|
||||
undefined,
|
||||
{
|
||||
each: true,
|
||||
},
|
||||
);
|
||||
|
||||
// @ts-expect-error: make sure "multiProviderInstances" is string[] not string
|
||||
multiProviderInstances.charAt;
|
||||
|
||||
expect(multiProviderInstances).to.be.eql(['A', 'B', 'C']);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,134 +0,0 @@
|
||||
import { Scope } from '@nestjs/common';
|
||||
import { UnknownDependenciesException } from '@nestjs/core/errors/exceptions/unknown-dependencies.exception';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('Optional factory provider deps', () => {
|
||||
describe('when dependency is optional', () => {
|
||||
describe('and it is available', () => {
|
||||
it('then it should be injected into the factory function', async () => {
|
||||
const defaultValue = 'DEFAULT_VALUE';
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
providers: [
|
||||
{
|
||||
provide: 'FACTORY',
|
||||
useFactory: dep => dep ?? defaultValue,
|
||||
inject: [{ token: 'MISSING_DEP', optional: true }],
|
||||
},
|
||||
{ provide: 'MISSING_DEP', useValue: 'OPTIONAL_DEP_VALUE' },
|
||||
],
|
||||
}).compile();
|
||||
|
||||
const factoryProvider = moduleRef.get('FACTORY');
|
||||
expect(factoryProvider).to.equal('OPTIONAL_DEP_VALUE');
|
||||
});
|
||||
});
|
||||
describe('otherwise', () => {
|
||||
it('"undefined" should be injected into the factory function', async () => {
|
||||
const defaultValue = 'DEFAULT_VALUE';
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
providers: [
|
||||
{
|
||||
provide: 'FACTORY',
|
||||
useFactory: dep => dep ?? defaultValue,
|
||||
inject: [{ token: 'MISSING_DEP', optional: true }],
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
const factoryProvider = moduleRef.get('FACTORY');
|
||||
expect(factoryProvider).to.equal(defaultValue);
|
||||
});
|
||||
it('"undefined" should be injected into the factory function (scoped provider)', async () => {
|
||||
const MY_PROVIDER = 'MY_PROVIDER';
|
||||
const FIRST_OPTIONAL_DEPENDENCY = 'FIRST_OPTIONAL_DEPENDENCY';
|
||||
const SECOND_OPTIONAL_DEPENDENCY = 'SECOND_OPTIONAL_DEPENDENCY';
|
||||
|
||||
const module = await Test.createTestingModule({
|
||||
providers: [
|
||||
{
|
||||
provide: SECOND_OPTIONAL_DEPENDENCY,
|
||||
useValue: 'second',
|
||||
},
|
||||
{
|
||||
provide: MY_PROVIDER,
|
||||
scope: Scope.REQUEST,
|
||||
inject: [
|
||||
{
|
||||
token: FIRST_OPTIONAL_DEPENDENCY,
|
||||
optional: true,
|
||||
},
|
||||
{
|
||||
token: SECOND_OPTIONAL_DEPENDENCY,
|
||||
optional: true,
|
||||
},
|
||||
],
|
||||
useFactory: (first?: string, second?: string) => {
|
||||
return { first, second };
|
||||
},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
expect(await module.resolve(MY_PROVIDER)).to.deep.equal({
|
||||
first: undefined,
|
||||
second: 'second',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('otherwise', () => {
|
||||
describe('and dependency is not registered', () => {
|
||||
it('should error out', async () => {
|
||||
try {
|
||||
const builder = Test.createTestingModule({
|
||||
providers: [
|
||||
{
|
||||
provide: 'FACTORY',
|
||||
useFactory: () => 'RETURNED_VALUE',
|
||||
inject: ['MISSING_DEP'],
|
||||
},
|
||||
],
|
||||
});
|
||||
await builder.compile();
|
||||
} catch (err) {
|
||||
expect(err).to.be.instanceOf(UnknownDependenciesException);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('and dependency is registered but it cannot be instantiated', () => {
|
||||
it('should error out', async () => {
|
||||
try {
|
||||
const builder = Test.createTestingModule({
|
||||
providers: [
|
||||
{
|
||||
provide: 'POSSIBLY_MISSING_DEP',
|
||||
useFactory: () => null,
|
||||
inject: ['MISSING_DEP'],
|
||||
},
|
||||
{
|
||||
provide: 'FACTORY',
|
||||
useFactory: () => 'RETURNED_VALUE',
|
||||
inject: [{ token: 'POSSIBLY_MISSING_DEP', optional: false }],
|
||||
},
|
||||
],
|
||||
});
|
||||
await builder.compile();
|
||||
} 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.
|
||||
|
||||
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?
|
||||
@Module({
|
||||
imports: [ /* the Module containing "MISSING_DEP" */ ]
|
||||
})
|
||||
`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Module, Injectable, Inject } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
class CoreService {
|
||||
constructor(@Inject(CoreService.name) private readonly coreService: any) {}
|
||||
}
|
||||
|
||||
@Module({
|
||||
providers: [
|
||||
{
|
||||
provide: CoreService.name,
|
||||
useValue: 'anything',
|
||||
},
|
||||
],
|
||||
})
|
||||
export class InjectSameNameModule {}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Module, Scope } from '@nestjs/common';
|
||||
|
||||
@Module({
|
||||
providers: [
|
||||
{
|
||||
provide: 'MULTI_PROVIDER',
|
||||
useValue: 'A',
|
||||
},
|
||||
{
|
||||
provide: 'REQ_SCOPED_MULTI_PROVIDER',
|
||||
useFactory: () => 'A',
|
||||
scope: Scope.REQUEST,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class AModule {}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Module, Scope } from '@nestjs/common';
|
||||
|
||||
@Module({
|
||||
providers: [
|
||||
{
|
||||
provide: 'MULTI_PROVIDER',
|
||||
useValue: 'B',
|
||||
},
|
||||
{
|
||||
provide: 'REQ_SCOPED_MULTI_PROVIDER',
|
||||
useFactory: () => 'B',
|
||||
scope: Scope.REQUEST,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class BModule {}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Module, Scope } from '@nestjs/common';
|
||||
|
||||
@Module({
|
||||
providers: [
|
||||
{
|
||||
provide: 'MULTI_PROVIDER',
|
||||
useValue: 'C',
|
||||
},
|
||||
{
|
||||
provide: 'REQ_SCOPED_MULTI_PROVIDER',
|
||||
useFactory: () => 'C',
|
||||
scope: Scope.REQUEST,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class CModule {}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AModule } from './a.module';
|
||||
import { BModule } from './b.module';
|
||||
import { CModule } from './c.module';
|
||||
|
||||
@Module({
|
||||
imports: [AModule, BModule, CModule],
|
||||
})
|
||||
export class MultipleProvidersModule {}
|
||||
@@ -1,40 +0,0 @@
|
||||
import { Module, Injectable, Inject, forwardRef } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
class ServiceInjectingItself {
|
||||
constructor(private readonly coreService: ServiceInjectingItself) {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class ServiceInjectingItselfForward {
|
||||
constructor(
|
||||
@Inject(forwardRef(() => ServiceInjectingItself))
|
||||
private readonly coreService: ServiceInjectingItself,
|
||||
) {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
class ServiceInjectingItselfViaCustomToken {
|
||||
constructor(@Inject('AnotherToken') private readonly coreService: any) {}
|
||||
}
|
||||
|
||||
@Module({
|
||||
providers: [ServiceInjectingItself],
|
||||
})
|
||||
export class SelfInjectionProviderModule {}
|
||||
|
||||
@Module({
|
||||
providers: [ServiceInjectingItselfForward],
|
||||
})
|
||||
export class SelfInjectionForwardProviderModule {}
|
||||
|
||||
@Module({
|
||||
providers: [
|
||||
ServiceInjectingItselfViaCustomToken,
|
||||
{
|
||||
provide: 'AnotherToken',
|
||||
useClass: ServiceInjectingItselfViaCustomToken,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class SelfInjectionProviderCustomTokenModule {}
|
||||
@@ -7,28 +7,10 @@
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES2021",
|
||||
"target": "es6",
|
||||
"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/*"]
|
||||
}
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,69 +0,0 @@
|
||||
import { ValidationPipe } from '@nestjs/common';
|
||||
import { Injector } from '@nestjs/core/injector/injector';
|
||||
import { SerializedGraph } from '@nestjs/core/inspector/serialized-graph';
|
||||
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import * as sinon from 'sinon';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { HttpExceptionFilter } from '../src/common/filters/http-exception.filter';
|
||||
import { TimeoutInterceptor } from '../src/common/interceptors/timeout.interceptor';
|
||||
|
||||
describe('Graph inspector', () => {
|
||||
let testingModule: TestingModule;
|
||||
|
||||
before(async () => {
|
||||
sinon.stub(Injector.prototype as any, 'getNowTimestamp').callsFake(() => 0);
|
||||
|
||||
testingModule = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile({ snapshot: true });
|
||||
});
|
||||
|
||||
it('should generate a pre-initialization graph and match snapshot', () => {
|
||||
const graph = testingModule.get(SerializedGraph);
|
||||
|
||||
// Update snapshot:
|
||||
// writeFileSync(
|
||||
// join(__dirname, 'fixtures', 'pre-init-graph.json'),
|
||||
// graph.toString(),
|
||||
// );
|
||||
|
||||
const snapshot = readFileSync(
|
||||
join(__dirname, 'fixtures', 'pre-init-graph.json'),
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
expect(JSON.parse(graph.toString())).to.deep.equal(JSON.parse(snapshot));
|
||||
});
|
||||
|
||||
it('should generate a post-initialization graph and match snapshot', async () => {
|
||||
const app = testingModule.createNestApplication({ preview: true });
|
||||
app.useGlobalPipes(new ValidationPipe());
|
||||
app.useGlobalFilters(new HttpExceptionFilter());
|
||||
app.useGlobalInterceptors(new TimeoutInterceptor());
|
||||
app.enableVersioning();
|
||||
app.connectMicroservice<MicroserviceOptions>({
|
||||
transport: Transport.TCP,
|
||||
options: {},
|
||||
});
|
||||
await app.init();
|
||||
|
||||
const graph = testingModule.get(SerializedGraph);
|
||||
|
||||
// Update snapshot:
|
||||
// writeFileSync(
|
||||
// join(__dirname, 'fixtures', 'post-init-graph.json'),
|
||||
// graph.toString(),
|
||||
// );
|
||||
|
||||
const snapshot = readFileSync(
|
||||
join(__dirname, 'fixtures', 'post-init-graph.json'),
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
expect(graph.toString()).to.equal(snapshot);
|
||||
});
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
|
||||
@Controller({
|
||||
version: '1',
|
||||
})
|
||||
export class AppV1Controller {
|
||||
@Get('/')
|
||||
helloWorldV1() {
|
||||
return 'Hello World V1!';
|
||||
}
|
||||
|
||||
@Get('/:param/hello')
|
||||
paramV1() {
|
||||
return 'Parameter V1!';
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Controller, Get, Version } from '@nestjs/common';
|
||||
|
||||
@Controller({
|
||||
version: '2',
|
||||
})
|
||||
export class AppV2Controller {
|
||||
@Get('/')
|
||||
helloWorldV2() {
|
||||
return 'Hello World V2!';
|
||||
}
|
||||
|
||||
@Version('3')
|
||||
@Get('/:param/hello')
|
||||
paramV1() {
|
||||
return 'Parameter V2!';
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import { Module, Scope } from '@nestjs/common';
|
||||
import { AppV1Controller } from './app-v1.controller';
|
||||
import { AppV2Controller } from './app-v2.controller';
|
||||
import { CatsModule } from './cats/cats.module';
|
||||
import { ChatModule } from './chat/chat.module';
|
||||
import { HelloModule as CircularHelloModule } from './circular-hello/hello.module';
|
||||
import { HelloService } from './circular-hello/hello.service';
|
||||
import { InputModule } from './circular-modules/input.module';
|
||||
import { CoreModule } from './core/core.module';
|
||||
import { DatabaseModule } from './database/database.module';
|
||||
import { DogsModule } from './dogs/dogs.module';
|
||||
import { DurableModule } from './durable/durable.module';
|
||||
import { ExternalSvcModule } from './external-svc/external-svc.module';
|
||||
import { PropertiesModule } from './properties/properties.module';
|
||||
import { RequestChainModule } from './request-chain/request-chain.module';
|
||||
import { UsersModule } from './users/users.module';
|
||||
|
||||
class Meta {
|
||||
static COUNTER = 0;
|
||||
constructor(private readonly helloService: HelloService) {
|
||||
Meta.COUNTER++;
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
CoreModule,
|
||||
CatsModule,
|
||||
CircularHelloModule.forRoot({
|
||||
provide: 'META',
|
||||
useClass: Meta,
|
||||
scope: Scope.REQUEST,
|
||||
}),
|
||||
DurableModule,
|
||||
DogsModule,
|
||||
UsersModule,
|
||||
DatabaseModule,
|
||||
ExternalSvcModule,
|
||||
ChatModule,
|
||||
RequestChainModule,
|
||||
PropertiesModule,
|
||||
InputModule,
|
||||
],
|
||||
controllers: [AppV1Controller, AppV2Controller],
|
||||
})
|
||||
export class AppModule {}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
|
||||
import { RolesGuard } from '../common/guards/roles.guard';
|
||||
import { ParseIntPipe } from '../common/pipes/parse-int.pipe';
|
||||
import { CatsService } from './cats.service';
|
||||
import { CreateCatDto } from './dto/create-cat.dto';
|
||||
import { Cat } from './interfaces/cat.interface';
|
||||
|
||||
@UseGuards(RolesGuard)
|
||||
@Controller('cats')
|
||||
export class CatsController {
|
||||
constructor(private readonly catsService: CatsService) {}
|
||||
|
||||
@Post()
|
||||
async create(@Body() createCatDto: CreateCatDto) {
|
||||
this.catsService.create(createCatDto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
async findAll(): Promise<Cat[]> {
|
||||
return this.catsService.findAll();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
findOne(
|
||||
@Param('id', new ParseIntPipe())
|
||||
id: number,
|
||||
) {
|
||||
// get by ID logic
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { CatsController } from './cats.controller';
|
||||
import { CatsService } from './cats.service';
|
||||
|
||||
@Module({
|
||||
controllers: [CatsController],
|
||||
providers: [CatsService],
|
||||
})
|
||||
export class CatsModule {}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Cat } from './interfaces/cat.interface';
|
||||
|
||||
@Injectable()
|
||||
export class CatsService {
|
||||
private readonly cats: Cat[] = [];
|
||||
|
||||
create(cat: Cat) {
|
||||
this.cats.push(cat);
|
||||
}
|
||||
|
||||
findAll(): Cat[] {
|
||||
return this.cats;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { IsInt, IsString } from 'class-validator';
|
||||
|
||||
export class CreateCatDto {
|
||||
@IsString()
|
||||
readonly name: string;
|
||||
|
||||
@IsInt()
|
||||
readonly age: number;
|
||||
|
||||
@IsString()
|
||||
readonly breed: string;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export interface Cat {
|
||||
name: string;
|
||||
age: number;
|
||||
breed: string;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import {
|
||||
WebSocketGateway,
|
||||
SubscribeMessage,
|
||||
MessageBody,
|
||||
} from '@nestjs/websockets';
|
||||
import { ChatService } from './chat.service';
|
||||
import { CreateChatDto } from './dto/create-chat.dto';
|
||||
import { UpdateChatDto } from './dto/update-chat.dto';
|
||||
|
||||
@WebSocketGateway()
|
||||
export class ChatGateway {
|
||||
constructor(private readonly chatService: ChatService) {}
|
||||
|
||||
@SubscribeMessage('createChat')
|
||||
create(@MessageBody() createChatDto: CreateChatDto) {
|
||||
return this.chatService.create(createChatDto);
|
||||
}
|
||||
|
||||
@SubscribeMessage('findAllChat')
|
||||
findAll() {
|
||||
return this.chatService.findAll();
|
||||
}
|
||||
|
||||
@SubscribeMessage('findOneChat')
|
||||
findOne(@MessageBody() id: number) {
|
||||
return this.chatService.findOne(id);
|
||||
}
|
||||
|
||||
@SubscribeMessage('updateChat')
|
||||
update(@MessageBody() updateChatDto: UpdateChatDto) {
|
||||
return this.chatService.update(updateChatDto.id, updateChatDto);
|
||||
}
|
||||
|
||||
@SubscribeMessage('removeChat')
|
||||
remove(@MessageBody() id: number) {
|
||||
return this.chatService.remove(id);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ChatService } from './chat.service';
|
||||
import { ChatGateway } from './chat.gateway';
|
||||
|
||||
@Module({
|
||||
providers: [ChatGateway, ChatService],
|
||||
})
|
||||
export class ChatModule {}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CreateChatDto } from './dto/create-chat.dto';
|
||||
import { UpdateChatDto } from './dto/update-chat.dto';
|
||||
|
||||
@Injectable()
|
||||
export class ChatService {
|
||||
create(createChatDto: CreateChatDto) {
|
||||
return 'This action adds a new chat';
|
||||
}
|
||||
|
||||
findAll() {
|
||||
return `This action returns all chat`;
|
||||
}
|
||||
|
||||
findOne(id: number) {
|
||||
return `This action returns a #${id} chat`;
|
||||
}
|
||||
|
||||
update(id: number, updateChatDto: UpdateChatDto) {
|
||||
return `This action updates a #${id} chat`;
|
||||
}
|
||||
|
||||
remove(id: number) {
|
||||
return `This action removes a #${id} chat`;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user