mirror of
https://github.com/nestjs/nest.git
synced 2026-02-26 06:35:32 +00:00
Compare commits
143 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b29461a68 | ||
|
|
a763e00507 | ||
|
|
649d99e09f | ||
|
|
581e183246 | ||
|
|
375028dbf2 | ||
|
|
97c6ae4481 | ||
|
|
325748d945 | ||
|
|
e8d017398c | ||
|
|
0c06d41c9d | ||
|
|
7fb15113fa | ||
|
|
d489788248 | ||
|
|
ebf5dad9bb | ||
|
|
7bc156f01e | ||
|
|
2c0902f248 | ||
|
|
edaf60fea9 | ||
|
|
5c47ccd78e | ||
|
|
6bb6286761 | ||
|
|
9ca38166dd | ||
|
|
a2a00ad31a | ||
|
|
5fe79633bf | ||
|
|
450368779c | ||
|
|
4feba7504f | ||
|
|
d804d65cde | ||
|
|
3e2d887a12 | ||
|
|
e4549f8701 | ||
|
|
80481a5117 | ||
|
|
86e32f6aed | ||
|
|
7415021ba1 | ||
|
|
cd5ab322cb | ||
|
|
ea1f1b14bd | ||
|
|
b6817403ad | ||
|
|
bc13118eb7 | ||
|
|
b1502a6028 | ||
|
|
9147a12705 | ||
|
|
236cf1853f | ||
|
|
27c083985c | ||
|
|
4c92b9418e | ||
|
|
7fdd07cfa5 | ||
|
|
11253f5009 | ||
|
|
1279602f1c | ||
|
|
ec6b89160d | ||
|
|
0dd55875f7 | ||
|
|
2296d30900 | ||
|
|
75600bc725 | ||
|
|
bc7914e1df | ||
|
|
2003c1e7ff | ||
|
|
cf5fcbdf0b | ||
|
|
fde169636f | ||
|
|
7af4a012b4 | ||
|
|
8cd42f519b | ||
|
|
8fdf428143 | ||
|
|
e089a4730f | ||
|
|
d843678ec4 | ||
|
|
e6825dcc7b | ||
|
|
08fc594349 | ||
|
|
68edfda978 | ||
|
|
68014d8f95 | ||
|
|
aaab2bc6ef | ||
|
|
f0c92bb328 | ||
|
|
327f402c1c | ||
|
|
708e36b7ed | ||
|
|
ff229b522f | ||
|
|
9992996104 | ||
|
|
eebd72c5e4 | ||
|
|
9ae0953b50 | ||
|
|
7357007a50 | ||
|
|
8ae0a43282 | ||
|
|
2f3732ec77 | ||
|
|
dd7ceafc4d | ||
|
|
e2ede3e976 | ||
|
|
f854ae6180 | ||
|
|
122c145b6c | ||
|
|
ba00ce65a6 | ||
|
|
dc24a2072e | ||
|
|
fbd2fea4f1 | ||
|
|
fad0e6a208 | ||
|
|
18125677b2 | ||
|
|
43e99499a7 | ||
|
|
74468739a6 | ||
|
|
214037f1bb | ||
|
|
3ea0bd9d45 | ||
|
|
ee05a31f64 | ||
|
|
fc3e2fde78 | ||
|
|
b6cba3784d | ||
|
|
957929e31d | ||
|
|
4bcfe79e07 | ||
|
|
77b778f044 | ||
|
|
466dc841c0 | ||
|
|
5caef83200 | ||
|
|
6cbe49604c | ||
|
|
3bb2e2489e | ||
|
|
e57203c2b8 | ||
|
|
23624dec23 | ||
|
|
37392212c9 | ||
|
|
4d32bc3508 | ||
|
|
4359785f5b | ||
|
|
ceb0ecbdcd | ||
|
|
df48878d6b | ||
|
|
cfa9115526 | ||
|
|
496285d9d1 | ||
|
|
acbb857fcd | ||
|
|
6e9f432d06 | ||
|
|
9e3b07de6f | ||
|
|
46a961c8d7 | ||
|
|
e12141dc70 | ||
|
|
e9dcac6124 | ||
|
|
ab86e44f0a | ||
|
|
5ed8c5980b | ||
|
|
601de0fe46 | ||
|
|
3150c19a8e | ||
|
|
5e58318894 | ||
|
|
13ddd03356 | ||
|
|
606557864b | ||
|
|
2b1898c00b | ||
|
|
74d6c37c8b | ||
|
|
d2875bfcab | ||
|
|
200e6cb673 | ||
|
|
e83aca183d | ||
|
|
2a6ca015fc | ||
|
|
864fac9cea | ||
|
|
2a727b9024 | ||
|
|
d7b0e0557b | ||
|
|
52e0128258 | ||
|
|
bb0ce8ce3f | ||
|
|
8afafc6c34 | ||
|
|
028c8aacf0 | ||
|
|
b605b8871e | ||
|
|
81be8a0fbc | ||
|
|
27b54d567a | ||
|
|
4d4f7a448c | ||
|
|
ade7aed794 | ||
|
|
fe24ae456b | ||
|
|
3e0ee2108f | ||
|
|
49bb841615 | ||
|
|
ca3ff1b2d8 | ||
|
|
62adce80c8 | ||
|
|
82cb61aa2b | ||
|
|
447b8ab624 | ||
|
|
5b92c33cb2 | ||
|
|
77817b232f | ||
|
|
40194281b1 | ||
|
|
2984df1395 | ||
|
|
c4a3e0296d |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,6 @@
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
package-lock.json
|
||||
# IDE
|
||||
/.idea
|
||||
/.awcache
|
||||
|
||||
4
.prettierrc
Normal file
4
.prettierrc
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
72
CHANGELOG.md
72
CHANGELOG.md
@@ -1,4 +1,74 @@
|
||||
## 4.5.0@soon
|
||||
## 4.6.3
|
||||
### Bug Fixes
|
||||
- **core**: error thrown when connecting to microservice (hybrid applicaton) [#425](https://github.com/nestjs/nest/issues/425)
|
||||
|
||||
## 4.6.2
|
||||
### Improvements
|
||||
- **core**: simplify `NestFactory.create(...args)` signature
|
||||
|
||||
## 4.6.1
|
||||
### Improvements
|
||||
- **common**: create `ModuleMetadata` interface
|
||||
- **core**: majority of methods (`INestApplication`, `INestMicroservice`, and `INestApplicationContext`) return `this` instead of `void`
|
||||
- **core**: remove static dependencies & relationships inside `NestFactory`
|
||||
|
||||
### Features
|
||||
- **core**: [feature] add `appOptions` property to `create[..]` methods of `NestFactory`
|
||||
|
||||
### Bug Fixes
|
||||
- **common**: [bugfix] update `class-validator` [#417](https://github.com/nestjs/nest/issues/417)
|
||||
- **core**: [bugfix] catch error thrown by `bodyParser` in exception filter [#422](https://github.com/nestjs/nest/issues/422)
|
||||
|
||||
## 4.6.0
|
||||
### Features
|
||||
- **common**: `ValidationPipe` improvements [#383](https://github.com/nestjs/nest/pull/383)
|
||||
- **common**: `ParseIntPipe` improvements [#385](https://github.com/nestjs/nest/pull/385)
|
||||
- **common**: add `FileInterceptor`, `FilesInterceptor`, `@UploadedFile()` and `@UploadedFiles()` (`multer` integration)
|
||||
- **common**: add `HttpModule` that exposes `HttpService` (`axios` integration)
|
||||
- **core**: add `app.disable()` and `app.enable()` wrappers around `express` app
|
||||
- **core**: add ability to inject `express` reference (`EXPRESS_REF` token)
|
||||
- **core**: enable possibility to extend metadata (inheritance support) [#228](https://github.com/nestjs/nest/issues/228)
|
||||
- **core**: `NestFactory.create()` now accepts third argument `HttpsOptions`
|
||||
- **core**: add `app.enableCors()` to `INestApplication` (`cors` integration)
|
||||
- **core**: add `@Render()` decorator (MVC applications)
|
||||
- **core**: provide `Logger.overrideLogger()` [#247](https://github.com/nestjs/nest/issues/247)
|
||||
- **microservices**: add `listenAsync()` to `INestMicroservice` instance
|
||||
|
||||
### Bug Fixes
|
||||
- **core**: simplify HTTPS protocol usage
|
||||
- **core**: custom transport strategy - thrown exceptions issue [#290](https://github.com/nestjs/nest/issues/290)
|
||||
- **core**: injector fails silently [#287](https://github.com/nestjs/nest/issues/287)
|
||||
- **core**: secure websockets (`wss://`) [#384](https://github.com/nestjs/nest/issues/384)
|
||||
- **core**: can't select/get from context when using `NestFactory.createMicroservice()` [#398](https://github.com/nestjs/nest/issues/398)
|
||||
- **core**: interceptor `$stream` observable returns another observable instead of the response object [#376](https://github.com/nestjs/nest/issues/376)
|
||||
- **core**: `Observable.throw` from controller results in unhandled rejection promise [#373](https://github.com/nestjs/nest/issues/373)
|
||||
|
||||
## 4.5.10
|
||||
- **core**: [bugfix] #343
|
||||
- **core**: [bugfix] #337
|
||||
|
||||
## 4.5.6
|
||||
- **core**: [bugfix] dynamic modules `exports`
|
||||
|
||||
## 4.5.5
|
||||
- **core**: [bugfix] add missing `app.engine()` wrapper
|
||||
|
||||
## 4.5.4
|
||||
- **core**: [bugfix] dynamic modules recurrent imports fix
|
||||
|
||||
## 4.5.3
|
||||
- **testing**: [bugfix] issue #326
|
||||
|
||||
## 4.5.2
|
||||
- **common**: [feature] rename `modules` to `imports` (`@Module()` decorator)
|
||||
- **core**: [feature] exception filters with empty `@Catch()` metadata handle each occurred exception
|
||||
- **core**: [improvement] increase performance
|
||||
|
||||
## 4.5.1
|
||||
- **common**: [feature] `INestAplication` provides a `getHttpServer()` method now
|
||||
- **websockets**: [bugfix] `IoAdapter` bugfix
|
||||
|
||||
## 4.5.0
|
||||
- **common**: bugfix #286
|
||||
- **core**: dynamic modules feature
|
||||
- **core**: global scope feature
|
||||
|
||||
271
CONTRIBUTING.md
Normal file
271
CONTRIBUTING.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# Contributing to Nest
|
||||
|
||||
We would love for you to contribute to Nest and help make it even better than it is
|
||||
today! As a contributor, here are the guidelines we would like you to follow:
|
||||
|
||||
- [Code of Conduct](#coc)
|
||||
- [Question or Problem?](#question)
|
||||
- [Issues and Bugs](#issue)
|
||||
- [Feature Requests](#feature)
|
||||
- [Submission Guidelines](#submit)
|
||||
- [Coding Rules](#rules)
|
||||
- [Commit Message Guidelines](#commit)
|
||||
<!-- - [Signing the CLA](#cla) -->
|
||||
|
||||
<!-- ## <a name="coc"></a> Code of Conduct
|
||||
Help us keep Nest open and inclusive. Please read and follow our [Code of Conduct][coc]. -->
|
||||
|
||||
## <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](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:
|
||||
|
||||
<!-- - there are thousands of people willing to help on Stack Overflow [maybe one day] -->
|
||||
- questions and answers stay available for public viewing so your question / answer might help someone else
|
||||
- Stack Overflow's voting system assures that the best answers are prominently visible.
|
||||
|
||||
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
||||
|
||||
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
|
||||
|
||||
## <a name="issue"></a> Found a Bug?
|
||||
If you find a bug in the source code, you can help us by
|
||||
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
|
||||
[submit a Pull Request](#submit-pr) with a fix.
|
||||
|
||||
## <a name="feature"></a> Missing a Feature?
|
||||
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub
|
||||
Repository. If you would like to *implement* a new feature, please submit an issue with
|
||||
a proposal for your work first, to be sure that we can use it.
|
||||
Please consider what kind of change it is:
|
||||
|
||||
* For a **Major Feature**, first open an issue and outline your proposal so that it can be
|
||||
discussed. This will also allow us to better coordinate our efforts, prevent duplication of work,
|
||||
and help you to craft the change so that it is successfully accepted into the project. For your issue name, please prefix your proposal with `[discussion]`, for example "[discussion]: your feature idea".
|
||||
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
||||
|
||||
## <a name="submit"></a> Submission Guidelines
|
||||
|
||||
### <a name="submit-issue"></a> Submitting an Issue
|
||||
|
||||
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
|
||||
|
||||
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs we will systematically ask you to provide a minimal reproduction scenario using a repository or [Gist](https://gist.github.com/). Having a live, reproducible scenario gives us wealth of important information without going back & forth to you with additional questions like:
|
||||
|
||||
- version of NestJS used
|
||||
- 3rd-party libraries and their versions
|
||||
- and most importantly - a use-case that fails
|
||||
|
||||
<!--
|
||||
// TODO we need to create a playground, similar to plunkr
|
||||
|
||||
A minimal reproduce scenario using a repository or Gist allows us to quickly confirm a bug (or point out coding problem) as well as confirm that we are fixing the right problem. If neither of these are not a suitable way to demonstrate the problem (for example for issues related to our npm packaging), please create a standalone git repository demonstrating the problem. -->
|
||||
|
||||
<!-- We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it. -->
|
||||
|
||||
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 don't have enough info to be reproduced.
|
||||
|
||||
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)
|
||||
Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
|
||||
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. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||
We cannot accept code without this. -->
|
||||
1. Fork the nestjs/nest repo.
|
||||
1. Make your changes in a new git branch:
|
||||
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
|
||||
1. Create your patch, **including appropriate test cases**.
|
||||
1. Follow our [Coding Rules](#rules).
|
||||
1. Run the full Nest test suite, as described in the [developer documentation][dev-doc],
|
||||
and ensure that all tests pass.
|
||||
1. Commit your changes using a descriptive commit message that follows our
|
||||
[commit message conventions](#commit). Adherence to these conventions
|
||||
is necessary because release notes are automatically generated from these messages.
|
||||
|
||||
```shell
|
||||
git commit -a
|
||||
```
|
||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||
|
||||
1. Push your branch to GitHub:
|
||||
|
||||
```shell
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
1. In GitHub, send a pull request to `nestjs:master`.
|
||||
* If we suggest changes then:
|
||||
* Make the required updates.
|
||||
* Re-run the Nest test suites to ensure tests are still passing.
|
||||
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||
|
||||
```shell
|
||||
git rebase master -i
|
||||
git push -f
|
||||
```
|
||||
|
||||
That's it! Thank you for your contribution!
|
||||
|
||||
#### After your pull request is merged
|
||||
|
||||
After your pull request is merged, you can safely delete your branch and pull the changes
|
||||
from the main (upstream) repository:
|
||||
|
||||
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
||||
|
||||
```shell
|
||||
git push origin --delete my-fix-branch
|
||||
```
|
||||
|
||||
* Check out the master branch:
|
||||
|
||||
```shell
|
||||
git checkout master -f
|
||||
```
|
||||
|
||||
* Delete the local branch:
|
||||
|
||||
```shell
|
||||
git branch -D my-fix-branch
|
||||
```
|
||||
|
||||
* Update your master with the latest upstream version:
|
||||
|
||||
```shell
|
||||
git pull --ff upstream master
|
||||
```
|
||||
|
||||
## <a name="rules"></a> Coding Rules
|
||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||
|
||||
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
||||
<!--
|
||||
// We're working on auto-documentation.
|
||||
* All public API methods **must be documented**. (Details TBC). -->
|
||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at
|
||||
**100 characters**. An automated formatter is available, see
|
||||
[DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||
|
||||
## <a name="commit"></a> Commit Message Guidelines
|
||||
|
||||
We have very precise rules over how our git commit messages can be formatted. This leads to **more
|
||||
readable messages** that are easy to follow when looking through the **project history**. But also,
|
||||
we use the git commit messages to **generate the Nest change log**.
|
||||
|
||||
### Commit Message Format
|
||||
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
|
||||
format that includes a **type**, a **scope** and a **subject**:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The **header** is mandatory and the **scope** of the header is optional.
|
||||
|
||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
||||
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](https://github.com/nestjs/nest/commits/master))
|
||||
|
||||
```
|
||||
docs(changelog): update change log to beta.5
|
||||
```
|
||||
```
|
||||
fix(release): need to depend on latest rxjs and zone.js
|
||||
|
||||
The version in our package.json gets copied to the one we publish, and users need the latest of these.
|
||||
```
|
||||
|
||||
### Revert
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||
|
||||
### Type
|
||||
Must be one of the following:
|
||||
|
||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
|
||||
* **docs**: Documentation only changes
|
||||
* **feat**: A new feature
|
||||
* **fix**: A bug fix
|
||||
* **perf**: A code change that improves performance
|
||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||
* **test**: Adding missing tests or correcting existing tests
|
||||
|
||||
### Scope
|
||||
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**
|
||||
* **core**
|
||||
* **examples**
|
||||
* **microservices**
|
||||
* **testing**
|
||||
* **websockets**
|
||||
|
||||
There are currently a few exceptions to the "use package name" rule:
|
||||
|
||||
* **packaging**: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
|
||||
* **changelog**: used for updating the release notes in CHANGELOG.md
|
||||
* **examples/#**: for the example apps directory, replacing # with the example app number
|
||||
<!-- * **aio**: used for docs-app (angular.io) related changes within the /aio directory of the repo -->
|
||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`)
|
||||
|
||||
### Subject
|
||||
The subject contains succinct description of the change:
|
||||
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize first letter
|
||||
* no dot (.) at the end
|
||||
|
||||
### Body
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
|
||||
The body should include the motivation for the change and contrast this with previous behavior.
|
||||
|
||||
### Footer
|
||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||
reference GitHub issues that this commit **Closes**.
|
||||
|
||||
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
|
||||
|
||||
A detailed explanation can be found in this [document][commit-message-format].
|
||||
|
||||
<!-- ## <a name="cla"></a> Signing the CLA
|
||||
|
||||
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
|
||||
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
|
||||
|
||||
* For individuals we have a [simple click-through form][individual-cla].
|
||||
* For corporations we'll need you to
|
||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla]. -->
|
||||
|
||||
|
||||
<!-- [angular-group]: https://groups.google.com/forum/#!forum/angular -->
|
||||
<!-- [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#
|
||||
[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
|
||||
[gitter]: https://gitter.im/nestjs/nest
|
||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
||||
[jsfiddle]: http://jsfiddle.net
|
||||
[plunker]: http://plnkr.co/edit
|
||||
[runnable]: http://runnable.com
|
||||
<!-- [stackoverflow]: http://stackoverflow.com/questions/tagged/angular -->
|
||||
@@ -7,14 +7,14 @@
|
||||
[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux
|
||||
[linux-url]: https://travis-ci.org/nestjs/nest
|
||||
|
||||
<p align="center">A progressive <a href="http://nodejs.org" target="blank">Node.js</a> framework for building efficient and scalable web applications, heavily inspired by <a href="https://angular.io" target="blank">Angular</a>.</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, heavily inspired by <a href="https://angular.io" target="blank">Angular</a>.</p>
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/dm/@nestjs/core.svg" alt="NPM Downloads" /></a>
|
||||
<a href="https://travis-ci.org/nestjs/nest"><img src="https://api.travis-ci.org/nestjs/nest.svg?branch=master" alt="Travis" /></a>
|
||||
<a href="https://travis-ci.org/nestjs/nest"><img src="https://img.shields.io/travis/nestjs/nest/master.svg?label=linux" alt="Linux" /></a>
|
||||
<a href="https://coveralls.io/github/nestjs/nest?branch=master"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#4" alt="Coverage" /></a>
|
||||
<a href="https://coveralls.io/github/nestjs/nest?branch=master"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#5" alt="Coverage" /></a>
|
||||
<a href="https://gitter.im/nestjs/nestjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge"><img src="https://badges.gitter.im/nestjs/nestjs.svg" alt="Gitter" /></a>
|
||||
<a href="https://opencollective.com/nest#backer"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
|
||||
<a href="https://opencollective.com/nest#sponsor"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
## Description
|
||||
|
||||
<p>Nest is a framework for building efficient, scalable <a href="http://nodejs.org" target="_blank">Node.js</a> web 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>
|
||||
<p>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>
|
||||
<p>Under the hood, Nest makes use of <a href="https://expressjs.com/" target="_blank">Express</a>, allowing for easy use of the myriad third-party plugins which are available.</p>
|
||||
|
||||
## Philosophy
|
||||
@@ -40,7 +40,7 @@ To check out the [guide](https://docs.nestjs.com), visit [docs.nestjs.com](https
|
||||
|
||||
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://opencollective.com/nest). Thanks! :heart_eyes:
|
||||
|
||||
<a href="https://valor-software.com/"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="210" /></a>
|
||||
<a href="https://valor-software.com/"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="210" /></a> <a href="https://scal.io"><img src="https://nestjs.com/img/scalio-logo.png" width="160" /></a>
|
||||
|
||||
## Backers
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as express from 'express';
|
||||
import * as request from 'supertest';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { CatsModule } from '../../src/modules/cats/cats.module';
|
||||
import { CatsService } from '../../src/modules/cats/cats.service';
|
||||
import { CatsModule } from '../../src/cats/cats.module';
|
||||
import { CatsService } from '../../src/cats/cats.service';
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
|
||||
describe('Cats', () => {
|
||||
@@ -13,7 +13,7 @@ describe('Cats', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
modules: [CatsModule],
|
||||
imports: [CatsModule],
|
||||
})
|
||||
.overrideComponent(CatsService)
|
||||
.useValue(catsService)
|
||||
|
||||
@@ -1,14 +1,2 @@
|
||||
require('ts-node/register');
|
||||
require('./src/server');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require('./src/main');
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"prestart:prod": "tsc",
|
||||
"start:prod": "node dist/server.js",
|
||||
"start:prod": "node dist/main.js",
|
||||
"test": "jest --config=jest.json",
|
||||
"test:watch": "jest --watch --config=jest.json",
|
||||
"test:coverage": "jest --config=jest.json --coverage --coverageDirectory=coverage",
|
||||
|
||||
@@ -4,12 +4,13 @@ import { CatsModule } from './cats/cats.module';
|
||||
import { CatsController } from './cats/cats.controller';
|
||||
|
||||
@Module({
|
||||
modules: [CatsModule],
|
||||
imports: [CatsModule],
|
||||
})
|
||||
export class ApplicationModule implements NestModule {
|
||||
configure(consumer: MiddlewaresConsumer): void {
|
||||
consumer.apply(LoggerMiddleware)
|
||||
.with('ApplicationModule')
|
||||
.forRoutes(CatsController);
|
||||
}
|
||||
}
|
||||
configure(consumer: MiddlewaresConsumer): void {
|
||||
consumer
|
||||
.apply(LoggerMiddleware)
|
||||
.with('ApplicationModule')
|
||||
.forRoutes(CatsController);
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,9 @@ describe('CatsController', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
controllers: [CatsController],
|
||||
components: [CatsService],
|
||||
}).compile();
|
||||
controllers: [CatsController],
|
||||
components: [CatsService],
|
||||
}).compile();
|
||||
|
||||
catsService = module.get<CatsService>(CatsService);
|
||||
catsController = module.get<CatsController>(CatsController);
|
||||
@@ -24,4 +24,4 @@ describe('CatsController', () => {
|
||||
expect(await catsController.findAll()).toBe(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,13 @@
|
||||
import { Controller, Get, Post, Body, UseGuards, ReflectMetadata, UseInterceptors, Param } from '@nestjs/common';
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Body,
|
||||
UseGuards,
|
||||
ReflectMetadata,
|
||||
UseInterceptors,
|
||||
Param,
|
||||
} from '@nestjs/common';
|
||||
import { CreateCatDto } from './dto/create-cat.dto';
|
||||
import { CatsService } from './cats.service';
|
||||
import { Cat } from './interfaces/cat.interface';
|
||||
@@ -26,7 +35,10 @@ export class CatsController {
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
findOne(@Param('id', new ParseIntPipe()) id) {
|
||||
findOne(
|
||||
@Param('id', new ParseIntPipe())
|
||||
id,
|
||||
) {
|
||||
// logic
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,4 +13,4 @@ export class CatsService {
|
||||
findAll(): Cat[] {
|
||||
return this.cats;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
examples/01-cats-app/src/cats/dto/create-cat.dto.ts
Normal file
9
examples/01-cats-app/src/cats/dto/create-cat.dto.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { IsString, IsInt } from 'class-validator';
|
||||
|
||||
export class CreateCatDto {
|
||||
@IsString() readonly name: string;
|
||||
|
||||
@IsInt() readonly age: number;
|
||||
|
||||
@IsString() readonly breed: string;
|
||||
}
|
||||
@@ -2,4 +2,4 @@ export interface Cat {
|
||||
readonly name: string;
|
||||
readonly age: number;
|
||||
readonly breed: string;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
import { ReflectMetadata } from '@nestjs/common';
|
||||
|
||||
export const Roles = (...roles: string[]) => ReflectMetadata('roles', roles);
|
||||
export const Roles = (...roles: string[]) => ReflectMetadata('roles', roles);
|
||||
@@ -5,4 +5,4 @@ export class ForbiddenException extends HttpException {
|
||||
constructor() {
|
||||
super('Forbidden', HttpStatus.FORBIDDEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,4 +11,4 @@ export class HttpExceptionFilter implements ExceptionFilter {
|
||||
message: `It's a message from the exception filter`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,8 @@ export class RolesGuard implements CanActivate {
|
||||
}
|
||||
|
||||
const user = req.user;
|
||||
const hasRole = () => !!user.roles.find((role) => !!roles.find((item) => item === role));
|
||||
const hasRole = () =>
|
||||
!!user.roles.find(role => !!roles.find(item => item === role));
|
||||
return user && user.roles && hasRole();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,14 @@ import 'rxjs/add/observable/of';
|
||||
export abstract class CacheInterceptor implements NestInterceptor {
|
||||
protected abstract readonly isCached: () => boolean;
|
||||
|
||||
intercept(dataOrRequest, context: ExecutionContext, stream$: Observable<any>): Observable<any> {
|
||||
intercept(
|
||||
dataOrRequest,
|
||||
context: ExecutionContext,
|
||||
stream$: Observable<any>,
|
||||
): Observable<any> {
|
||||
if (this.isCached()) {
|
||||
return Observable.of([]);
|
||||
}
|
||||
return stream$;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import {
|
||||
Interceptor,
|
||||
NestInterceptor,
|
||||
ExecutionContext,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
import { HttpException } from '@nestjs/common';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/observable/throw';
|
||||
|
||||
@Interceptor()
|
||||
export class ExceptionInterceptor implements NestInterceptor {
|
||||
intercept(
|
||||
dataOrRequest,
|
||||
context: ExecutionContext,
|
||||
stream$: Observable<any>,
|
||||
): Observable<any> {
|
||||
return stream$.catch(err =>
|
||||
Observable.throw(
|
||||
new HttpException(
|
||||
'Exception interceptor message',
|
||||
HttpStatus.BAD_GATEWAY,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,14 @@ import 'rxjs/add/operator/do';
|
||||
|
||||
@Interceptor()
|
||||
export class LoggingInterceptor implements NestInterceptor {
|
||||
intercept(dataOrRequest, context: ExecutionContext, stream$: Observable<any>): Observable<any> {
|
||||
intercept(
|
||||
dataOrRequest,
|
||||
context: ExecutionContext,
|
||||
stream$: Observable<any>,
|
||||
): Observable<any> {
|
||||
console.log('Before...');
|
||||
const now = Date.now();
|
||||
|
||||
return stream$.do(
|
||||
() => console.log(`After... ${Date.now() - now}ms`),
|
||||
);
|
||||
return stream$.do(() => console.log(`After... ${Date.now() - now}ms`));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,9 @@ import { mixin } from '@nestjs/common';
|
||||
import { CacheInterceptor } from './cache.interceptor';
|
||||
|
||||
export function mixinCacheInterceptor(isCached: () => boolean) {
|
||||
return mixin(class extends CacheInterceptor {
|
||||
protected readonly isCached = isCached;
|
||||
});
|
||||
}
|
||||
return mixin(
|
||||
class extends CacheInterceptor {
|
||||
protected readonly isCached = isCached;
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -4,7 +4,11 @@ import 'rxjs/add/operator/map';
|
||||
|
||||
@Interceptor()
|
||||
export class TransformInterceptor implements NestInterceptor {
|
||||
intercept(dataOrRequest, context: ExecutionContext, stream$: Observable<any>): Observable<any> {
|
||||
return stream$.map((data) => ({ data }));
|
||||
intercept(
|
||||
dataOrRequest,
|
||||
context: ExecutionContext,
|
||||
stream$: Observable<any>,
|
||||
): Observable<any> {
|
||||
return stream$.map(data => ({ data }));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,5 +7,5 @@ export class LoggerMiddleware implements NestMiddleware {
|
||||
console.log(`[${name}] Request...`); // [ApplicationModule] Request...
|
||||
next();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
import { HttpException } from '@nestjs/common';
|
||||
import { PipeTransform, Pipe, ArgumentMetadata, HttpStatus } from '@nestjs/common';
|
||||
import {
|
||||
PipeTransform,
|
||||
Pipe,
|
||||
ArgumentMetadata,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
|
||||
@Pipe()
|
||||
export class ParseIntPipe implements PipeTransform<string> {
|
||||
@@ -10,4 +15,4 @@ export class ParseIntPipe implements PipeTransform<string> {
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
30
examples/01-cats-app/src/common/pipes/validation.pipe.ts
Normal file
30
examples/01-cats-app/src/common/pipes/validation.pipe.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { HttpException } from '@nestjs/common';
|
||||
import {
|
||||
PipeTransform,
|
||||
Pipe,
|
||||
ArgumentMetadata,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
import { validate } from 'class-validator';
|
||||
import { plainToClass } from 'class-transformer';
|
||||
|
||||
@Pipe()
|
||||
export class ValidationPipe implements PipeTransform<any> {
|
||||
async transform(value, metadata: ArgumentMetadata) {
|
||||
const { metatype } = metadata;
|
||||
if (!metatype || !this.toValidate(metatype)) {
|
||||
return value;
|
||||
}
|
||||
const object = plainToClass(metatype, value);
|
||||
const errors = await validate(object);
|
||||
if (errors.length > 0) {
|
||||
throw new HttpException('Validation failed', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private toValidate(metatype): boolean {
|
||||
const types = [String, Boolean, Number, Array, Object];
|
||||
return !types.find(type => metatype === type);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { ApplicationModule } from './modules/app.module';
|
||||
import { ValidationPipe } from './modules/common/pipes/validation.pipe';
|
||||
import { ApplicationModule } from './app.module';
|
||||
import { ValidationPipe } from './common/pipes/validation.pipe';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(ApplicationModule);
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { CatsController } from './cats.controller';
|
||||
import { CatsService } from './cats.service';
|
||||
|
||||
@Module({
|
||||
controllers: [CatsController],
|
||||
components: [CatsService],
|
||||
})
|
||||
export class CatsModule {}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { IsString, IsInt } from 'class-validator';
|
||||
|
||||
export class CreateCatDto {
|
||||
@IsString()
|
||||
readonly name: string;
|
||||
|
||||
@IsInt()
|
||||
readonly age: number;
|
||||
|
||||
@IsString()
|
||||
readonly breed: string;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { Interceptor, NestInterceptor, ExecutionContext, HttpStatus } from '@nestjs/common';
|
||||
import { HttpException } from '@nestjs/common';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/observable/throw';
|
||||
|
||||
@Interceptor()
|
||||
export class ExceptionInterceptor implements NestInterceptor {
|
||||
intercept(dataOrRequest, context: ExecutionContext, stream$: Observable<any>): Observable<any> {
|
||||
return stream$.catch((err) => Observable.throw(
|
||||
new HttpException('Exception interceptor message', HttpStatus.BAD_GATEWAY),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { HttpException } from '@nestjs/common';
|
||||
import { PipeTransform, Pipe, ArgumentMetadata, HttpStatus } from '@nestjs/common';
|
||||
import { validate } from 'class-validator';
|
||||
import { plainToClass } from 'class-transformer';
|
||||
|
||||
@Pipe()
|
||||
export class ValidationPipe implements PipeTransform<any> {
|
||||
async transform(value, metadata: ArgumentMetadata) {
|
||||
const { metatype } = metadata;
|
||||
if (!metatype || !this.toValidate(metatype)) {
|
||||
return value;
|
||||
}
|
||||
const object = plainToClass(metatype, value);
|
||||
const errors = await validate(object);
|
||||
if (errors.length > 0) {
|
||||
throw new HttpException('Validation failed', HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private toValidate(metatype): boolean {
|
||||
const types = [String, Boolean, Number, Array, Object];
|
||||
return !types.find((type) => metatype === type);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<head>
|
||||
<script src="socket.io.js"></script>
|
||||
<script>
|
||||
const socket = io('http://localhost:81');
|
||||
const socket = io('http://localhost:3000');
|
||||
socket.on('connect', function() {
|
||||
console.log('Connected');
|
||||
socket.emit('events', { test: 'test' });
|
||||
|
||||
@@ -1,14 +1,2 @@
|
||||
require('ts-node/register');
|
||||
require('./src/server');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require('./src/main');
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"prestart:prod": "tsc",
|
||||
"start:prod": "node dist/server.js"
|
||||
"start:prod": "node dist/main.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^4.3.0",
|
||||
|
||||
@@ -2,6 +2,6 @@ import { Module } from '@nestjs/common';
|
||||
import { EventsModule } from './events/events.module';
|
||||
|
||||
@Module({
|
||||
modules: [EventsModule],
|
||||
imports: [EventsModule],
|
||||
})
|
||||
export class ApplicationModule {}
|
||||
export class ApplicationModule {}
|
||||
@@ -22,9 +22,9 @@ export class WsAdapter implements WebSocketAdapter {
|
||||
process: (data: any) => Observable<any>,
|
||||
) {
|
||||
Observable.fromEvent(client, 'message')
|
||||
.switchMap((buffer) => this.bindMessageHandler(buffer, handlers, process))
|
||||
.filter((result) => !!result)
|
||||
.subscribe((response) => client.send(JSON.stringify(response)));
|
||||
.switchMap(buffer => this.bindMessageHandler(buffer, handlers, process))
|
||||
.filter(result => !!result)
|
||||
.subscribe(response => client.send(JSON.stringify(response)));
|
||||
}
|
||||
|
||||
public bindMessageHandler(
|
||||
@@ -33,11 +33,13 @@ export class WsAdapter implements WebSocketAdapter {
|
||||
process: (data: any) => Observable<any>,
|
||||
): Observable<any> {
|
||||
const data = JSON.parse(buffer.data);
|
||||
const messageHandler = handlers.find((handler) => handler.message === data.type);
|
||||
const messageHandler = handlers.find(
|
||||
handler => handler.message === data.type,
|
||||
);
|
||||
if (!messageHandler) {
|
||||
return Observable.empty();
|
||||
}
|
||||
const { callback } = messageHandler;
|
||||
return process(callback(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
import { ReflectMetadata } from '@nestjs/common';
|
||||
|
||||
export const Roles = (...roles: string[]) => ReflectMetadata('roles', roles);
|
||||
export const Roles = (...roles: string[]) => ReflectMetadata('roles', roles);
|
||||
@@ -9,4 +9,4 @@ export class ExceptionFilter implements WsExceptionFilter {
|
||||
message: `It's a message from the exception filter`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,8 @@ export class RolesGuard implements CanActivate {
|
||||
}
|
||||
|
||||
const user = data.user;
|
||||
const hasRole = () => !!user.roles.find((role) => !!roles.find((item) => item === role));
|
||||
const hasRole = () =>
|
||||
!!user.roles.find(role => !!roles.find(item => item === role));
|
||||
return user && user.roles && hasRole();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,15 @@ import 'rxjs/add/observable/of';
|
||||
|
||||
@Interceptor()
|
||||
export class CacheInterceptor implements NestInterceptor {
|
||||
intercept(dataOrRequest, context: ExecutionContext, stream$: Observable<any>): Observable<any> {
|
||||
intercept(
|
||||
dataOrRequest,
|
||||
context: ExecutionContext,
|
||||
stream$: Observable<any>,
|
||||
): Observable<any> {
|
||||
const isCached = true;
|
||||
if (isCached) {
|
||||
return Observable.of([]);
|
||||
}
|
||||
return stream$;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,14 @@ import 'rxjs/add/operator/do';
|
||||
|
||||
@Interceptor()
|
||||
export class LoggingInterceptor implements NestInterceptor {
|
||||
intercept(dataOrRequest, context: ExecutionContext, stream$: Observable<any>): Observable<any> {
|
||||
intercept(
|
||||
dataOrRequest,
|
||||
context: ExecutionContext,
|
||||
stream$: Observable<any>,
|
||||
): Observable<any> {
|
||||
console.log('Before...');
|
||||
const now = Date.now();
|
||||
|
||||
return stream$.do(
|
||||
() => console.log(`After... ${Date.now() - now}ms`),
|
||||
);
|
||||
return stream$.do(() => console.log(`After... ${Date.now() - now}ms`));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,11 @@ import 'rxjs/add/operator/map';
|
||||
|
||||
@Interceptor()
|
||||
export class TransformInterceptor implements NestInterceptor {
|
||||
intercept(dataOrRequest, context: ExecutionContext, stream$: Observable<any>): Observable<any> {
|
||||
return stream$.map((data) => ({ data }));
|
||||
intercept(
|
||||
dataOrRequest,
|
||||
context: ExecutionContext,
|
||||
stream$: Observable<any>,
|
||||
): Observable<any> {
|
||||
return stream$.map(data => ({ data }));
|
||||
}
|
||||
}
|
||||
}
|
||||
30
examples/02-gateways/src/common/pipes/validation.pipe.ts
Normal file
30
examples/02-gateways/src/common/pipes/validation.pipe.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import {
|
||||
PipeTransform,
|
||||
Pipe,
|
||||
ArgumentMetadata,
|
||||
HttpStatus,
|
||||
} from '@nestjs/common';
|
||||
import { validate } from 'class-validator';
|
||||
import { plainToClass } from 'class-transformer';
|
||||
import { WsException } from '@nestjs/websockets';
|
||||
|
||||
@Pipe()
|
||||
export class ValidationPipe implements PipeTransform<any> {
|
||||
async transform(value, metadata: ArgumentMetadata) {
|
||||
const { metatype } = metadata;
|
||||
if (!metatype || !this.toValidate(metatype)) {
|
||||
return value;
|
||||
}
|
||||
const object = plainToClass(metatype, value);
|
||||
const errors = await validate(object);
|
||||
if (errors.length > 0) {
|
||||
throw new WsException('Validation failed');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private toValidate(metatype): boolean {
|
||||
const types = [String, Boolean, Number, Array, Object];
|
||||
return !types.find(type => metatype === type);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,15 @@
|
||||
import { WebSocketGateway, SubscribeMessage, WsResponse, WebSocketServer, WsException } from '@nestjs/websockets';
|
||||
import {
|
||||
WebSocketGateway,
|
||||
SubscribeMessage,
|
||||
WsResponse,
|
||||
WebSocketServer,
|
||||
WsException,
|
||||
} from '@nestjs/websockets';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/observable/from';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
@WebSocketGateway(81)
|
||||
@WebSocketGateway()
|
||||
export class EventsGateway {
|
||||
@WebSocketServer() server;
|
||||
|
||||
@@ -12,7 +18,6 @@ export class EventsGateway {
|
||||
const event = 'events';
|
||||
const response = [1, 2, 3];
|
||||
|
||||
return Observable.from(response)
|
||||
.map((res) => ({ event, data: res }));
|
||||
return Observable.from(response).map(res => ({ event, data: res }));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,6 @@ import { Module } from '@nestjs/common';
|
||||
import { EventsGateway } from './events.gateway';
|
||||
|
||||
@Module({
|
||||
components: [EventsGateway],
|
||||
components: [EventsGateway],
|
||||
})
|
||||
export class EventsModule {}
|
||||
export class EventsModule {}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { ApplicationModule } from './modules/app.module';
|
||||
import { ApplicationModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(ApplicationModule);
|
||||
@@ -1,25 +0,0 @@
|
||||
import { PipeTransform, Pipe, ArgumentMetadata, HttpStatus } from '@nestjs/common';
|
||||
import { validate } from 'class-validator';
|
||||
import { plainToClass } from 'class-transformer';
|
||||
import { WsException } from '@nestjs/websockets';
|
||||
|
||||
@Pipe()
|
||||
export class ValidationPipe implements PipeTransform<any> {
|
||||
async transform(value, metadata: ArgumentMetadata) {
|
||||
const { metatype } = metadata;
|
||||
if (!metatype || !this.toValidate(metatype)) {
|
||||
return value;
|
||||
}
|
||||
const object = plainToClass(metatype, value);
|
||||
const errors = await validate(object);
|
||||
if (errors.length > 0) {
|
||||
throw new WsException('Validation failed');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private toValidate(metatype): boolean {
|
||||
const types = [String, Boolean, Number, Array, Object];
|
||||
return !types.find((type) => metatype === type);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,2 @@
|
||||
require('ts-node/register');
|
||||
require('./src/server');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require('./src/main');
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"prestart:prod": "tsc",
|
||||
"start:prod": "node dist/server.js"
|
||||
"start:prod": "node dist/main.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^4.3.0",
|
||||
|
||||
@@ -2,6 +2,6 @@ import { Module } from '@nestjs/common';
|
||||
import { MathModule } from './math/math.module';
|
||||
|
||||
@Module({
|
||||
modules: [MathModule],
|
||||
imports: [MathModule],
|
||||
})
|
||||
export class ApplicationModule {}
|
||||
export class ApplicationModule {}
|
||||
@@ -2,13 +2,14 @@ import * as amqp from 'amqplib';
|
||||
import { ClientProxy } from '@nestjs/microservices';
|
||||
|
||||
export class RabbitMQClient extends ClientProxy {
|
||||
constructor(
|
||||
private readonly host: string,
|
||||
private readonly queue: string) {
|
||||
super();
|
||||
}
|
||||
constructor(private readonly host: string, private readonly queue: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async sendSingleMessage(messageObj, callback: (err, result, disposed?: boolean) => void) {
|
||||
protected async sendSingleMessage(
|
||||
messageObj,
|
||||
callback: (err, result, disposed?: boolean) => void,
|
||||
) {
|
||||
const server = await amqp.connect(this.host);
|
||||
const channel = await server.createChannel();
|
||||
const { sub, pub } = this.getQueues();
|
||||
@@ -16,15 +17,23 @@ export class RabbitMQClient extends ClientProxy {
|
||||
channel.assertQueue(sub, { durable: false });
|
||||
channel.assertQueue(pub, { durable: false });
|
||||
|
||||
channel.consume(pub, (message) => this.handleMessage(message, server, callback), { noAck: true });
|
||||
channel.consume(
|
||||
pub,
|
||||
message => this.handleMessage(message, server, callback),
|
||||
{ noAck: true },
|
||||
);
|
||||
channel.sendToQueue(sub, Buffer.from(JSON.stringify(messageObj)));
|
||||
}
|
||||
|
||||
private handleMessage(message, server, callback: (err, result, disposed?: boolean) => void) {
|
||||
private handleMessage(
|
||||
message,
|
||||
server,
|
||||
callback: (err, result, disposed?: boolean) => void,
|
||||
) {
|
||||
const { content } = message;
|
||||
const { err, response, disposed } = JSON.parse(content.toString());
|
||||
if (disposed) {
|
||||
server.close();
|
||||
server.close();
|
||||
}
|
||||
callback(err, response, disposed);
|
||||
}
|
||||
@@ -32,4 +41,4 @@ export class RabbitMQClient extends ClientProxy {
|
||||
private getQueues() {
|
||||
return { pub: `${this.queue}_pub`, sub: `${this.queue}_sub` };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,12 @@ import { Server, CustomTransportStrategy } from '@nestjs/microservices';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
export class RabbitMQServer extends Server implements CustomTransportStrategy {
|
||||
private server: amqp.Connection = null;
|
||||
private channel: amqp.Channel = null;
|
||||
private server: amqp.Connection = null;
|
||||
private channel: amqp.Channel = null;
|
||||
|
||||
constructor(
|
||||
private readonly host: string,
|
||||
private readonly queue: string) {
|
||||
super();
|
||||
}
|
||||
constructor(private readonly host: string, private readonly queue: string) {
|
||||
super();
|
||||
}
|
||||
|
||||
public async listen(callback: () => void) {
|
||||
await this.init();
|
||||
@@ -31,12 +29,14 @@ export class RabbitMQServer extends Server implements CustomTransportStrategy {
|
||||
const handlers = this.getHandlers();
|
||||
const pattern = JSON.stringify(messageObj.pattern);
|
||||
if (!this.messageHandlers[pattern]) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
const handler = this.messageHandlers[pattern];
|
||||
const response$ = this.transformToObservable(await handler(messageObj.data)) as Observable<any>;
|
||||
response$ && this.send(response$, (data) => this.sendMessage(data));
|
||||
const response$ = this.transformToObservable(
|
||||
await handler(messageObj.data),
|
||||
) as Observable<any>;
|
||||
response$ && this.send(response$, data => this.sendMessage(data));
|
||||
}
|
||||
|
||||
private sendMessage(message) {
|
||||
@@ -50,4 +50,4 @@ export class RabbitMQServer extends Server implements CustomTransportStrategy {
|
||||
this.channel.assertQueue(`${this.queue}_sub`, { durable: false });
|
||||
this.channel.assertQueue(`${this.queue}_pub`, { durable: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
import { ReflectMetadata } from '@nestjs/common';
|
||||
|
||||
export const Roles = (...roles: string[]) => ReflectMetadata('roles', roles);
|
||||
export const Roles = (...roles: string[]) => ReflectMetadata('roles', roles);
|
||||
@@ -8,4 +8,4 @@ export class ExceptionFilter implements RpcExceptionFilter {
|
||||
catch(exception: RpcException): Observable<any> {
|
||||
return Observable.throw(exception.getError());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,8 @@ export class RolesGuard implements CanActivate {
|
||||
}
|
||||
|
||||
const user = data.user;
|
||||
const hasRole = () => !!user.roles.find((role) => !!roles.find((item) => item === role));
|
||||
const hasRole = () =>
|
||||
!!user.roles.find(role => !!roles.find(item => item === role));
|
||||
return user && user.roles && hasRole();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,15 @@ import 'rxjs/add/observable/of';
|
||||
|
||||
@Interceptor()
|
||||
export class CacheInterceptor implements NestInterceptor {
|
||||
intercept(dataOrRequest, context: ExecutionContext, stream$: Observable<any>): Observable<any> {
|
||||
intercept(
|
||||
dataOrRequest,
|
||||
context: ExecutionContext,
|
||||
stream$: Observable<any>,
|
||||
): Observable<any> {
|
||||
const isCached = true;
|
||||
if (isCached) {
|
||||
return Observable.of([]);
|
||||
}
|
||||
return stream$;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,14 @@ import 'rxjs/add/operator/do';
|
||||
|
||||
@Interceptor()
|
||||
export class LoggingInterceptor implements NestInterceptor {
|
||||
intercept(dataOrRequest, context: ExecutionContext, stream$: Observable<any>): Observable<any> {
|
||||
intercept(
|
||||
dataOrRequest,
|
||||
context: ExecutionContext,
|
||||
stream$: Observable<any>,
|
||||
): Observable<any> {
|
||||
console.log('Before...');
|
||||
const now = Date.now();
|
||||
|
||||
return stream$.do(
|
||||
() => console.log(`After... ${Date.now() - now}ms`),
|
||||
);
|
||||
return stream$.do(() => console.log(`After... ${Date.now() - now}ms`));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,11 @@ import 'rxjs/add/operator/map';
|
||||
|
||||
@Interceptor()
|
||||
export class TransformInterceptor implements NestInterceptor {
|
||||
intercept(dataOrRequest, context: ExecutionContext, stream$: Observable<any>): Observable<any> {
|
||||
return stream$.map((data) => ({ data }));
|
||||
intercept(
|
||||
dataOrRequest,
|
||||
context: ExecutionContext,
|
||||
stream$: Observable<any>,
|
||||
): Observable<any> {
|
||||
return stream$.map(data => ({ data }));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { PipeTransform, Pipe, ArgumentMetadata } from '@nestjs/common';
|
||||
import { validate } from 'class-validator';
|
||||
import { plainToClass } from 'class-transformer';
|
||||
import { RpcException } from '@nestjs/microservices';
|
||||
|
||||
@Pipe()
|
||||
export class ValidationPipe implements PipeTransform<any> {
|
||||
async transform(value, metadata: ArgumentMetadata) {
|
||||
const { metatype } = metadata;
|
||||
if (!metatype || !this.toValidate(metatype)) {
|
||||
return value;
|
||||
}
|
||||
const object = plainToClass(metatype, value);
|
||||
const errors = await validate(object);
|
||||
if (errors.length > 0) {
|
||||
throw new RpcException('Validation failed');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private toValidate(metatype): boolean {
|
||||
const types = [String, Boolean, Number, Array, Object];
|
||||
return !types.find(type => metatype === type);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,18 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { ApplicationModule } from './modules/app.module';
|
||||
import { Transport } from '@nestjs/microservices';
|
||||
import { ApplicationModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.createMicroservice(ApplicationModule);
|
||||
await app.listenAsync();
|
||||
|
||||
/** Hybrid application (HTTP + (n)Microservices)
|
||||
const app = await NestFactory.create(ApplicationModule);
|
||||
app.connectMicroservice({
|
||||
transport: Transport.TCP,
|
||||
});
|
||||
|
||||
await app.startAllMicroservicesAsync();
|
||||
await app.listen(3001);
|
||||
await app.listen(3001); */
|
||||
}
|
||||
bootstrap();
|
||||
@@ -1,5 +1,10 @@
|
||||
import { Controller, Get, UseInterceptors } from '@nestjs/common';
|
||||
import { ClientProxy, Client, Transport, MessagePattern } from '@nestjs/microservices';
|
||||
import {
|
||||
ClientProxy,
|
||||
Client,
|
||||
Transport,
|
||||
MessagePattern,
|
||||
} from '@nestjs/microservices';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { LoggingInterceptor } from '../common/interceptors/logging.interceptor';
|
||||
|
||||
@@ -20,4 +25,4 @@ export class MathController {
|
||||
sum(data: number[]): number {
|
||||
return (data || []).reduce((a, b) => a + b);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,6 @@ import { Module } from '@nestjs/common';
|
||||
import { MathController } from './math.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [MathController],
|
||||
controllers: [MathController],
|
||||
})
|
||||
export class MathModule {}
|
||||
export class MathModule {}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { PipeTransform, Pipe, ArgumentMetadata } from '@nestjs/common';
|
||||
import { validate } from 'class-validator';
|
||||
import { plainToClass } from 'class-transformer';
|
||||
import { RpcException } from '@nestjs/microservices';
|
||||
|
||||
@Pipe()
|
||||
export class ValidationPipe implements PipeTransform<any> {
|
||||
async transform(value, metadata: ArgumentMetadata) {
|
||||
const { metatype } = metadata;
|
||||
if (!metatype || !this.toValidate(metatype)) {
|
||||
return value;
|
||||
}
|
||||
const object = plainToClass(metatype, value);
|
||||
const errors = await validate(object);
|
||||
if (errors.length > 0) {
|
||||
throw new RpcException('Validation failed');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private toValidate(metatype): boolean {
|
||||
const types = [String, Boolean, Number, Array, Object];
|
||||
return !types.find((type) => metatype === type);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,2 @@
|
||||
require('ts-node/register');
|
||||
require('./src/server');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require('./src/main');
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"prestart:prod": "tsc",
|
||||
"start:prod": "node dist/server.js"
|
||||
"start:prod": "node dist/main.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^4.3.0",
|
||||
|
||||
@@ -3,6 +3,6 @@ import { CoreModule } from './core/core.module';
|
||||
import { FeatureModule } from './feature/feature.module';
|
||||
|
||||
@Module({
|
||||
modules: [FeatureModule],
|
||||
imports: [FeatureModule],
|
||||
})
|
||||
export class ApplicationModule {}
|
||||
export class ApplicationModule {}
|
||||
@@ -5,4 +5,4 @@ import { CommonService } from './common.service';
|
||||
components: [CommonService],
|
||||
exports: [CommonService],
|
||||
})
|
||||
export class CommonModule {}
|
||||
export class CommonModule {}
|
||||
@@ -6,4 +6,4 @@ export class CommonService {
|
||||
constructor(private readonly coreService: CoreService) {
|
||||
console.log('CommonService', coreService);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,4 @@ export class ContextService {
|
||||
constructor(private readonly commonService: CoreService) {
|
||||
console.log('ContextService', commonService);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import { ContextService } from './context.service';
|
||||
import { FeatureModule } from '../feature/feature.module';
|
||||
|
||||
@Module({
|
||||
modules: [CommonModule],
|
||||
imports: [CommonModule],
|
||||
components: [CoreService, ContextService],
|
||||
exports: [CommonModule],
|
||||
})
|
||||
export class CoreModule {}
|
||||
export class CoreModule {}
|
||||
@@ -5,4 +5,4 @@ export class CoreService {
|
||||
constructor() {
|
||||
console.log('CoreService');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { FeatureService } from './feature.service';
|
||||
import { CoreModule } from '../core/core.module';
|
||||
|
||||
@Module({
|
||||
modules: [CoreModule],
|
||||
imports: [CoreModule],
|
||||
components: [FeatureService],
|
||||
})
|
||||
export class FeatureModule {}
|
||||
export class FeatureModule {}
|
||||
@@ -3,8 +3,7 @@ import { CommonService } from '../common/common.service';
|
||||
|
||||
@Component()
|
||||
export class FeatureService {
|
||||
constructor(
|
||||
private readonly commonService: CommonService) {
|
||||
constructor(private readonly commonService: CommonService) {
|
||||
console.log('FeatureService', commonService);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { ApplicationModule } from './modules/app.module';
|
||||
import { ApplicationModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(ApplicationModule);
|
||||
@@ -1,14 +1,2 @@
|
||||
require('ts-node/register');
|
||||
require('./src/server');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require('./src/main');
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
"password": "root",
|
||||
"database": "test",
|
||||
"entities": ["src/**/**.entity{.ts,.js}"],
|
||||
"autoSchemaSync": true
|
||||
}
|
||||
"synchronize": true
|
||||
}
|
||||
|
||||
@@ -6,15 +6,12 @@
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"prestart:prod": "tsc",
|
||||
"start:prod": "node dist/server.js"
|
||||
"start:prod": "node dist/main.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^4.3.0",
|
||||
"@nestjs/core": "^4.3.0",
|
||||
"@nestjs/microservices": "^4.3.0",
|
||||
"@nestjs/testing": "^4.3.0",
|
||||
"@nestjs/typeorm": "^1.0.0",
|
||||
"@nestjs/websockets": "^4.3.0",
|
||||
"@nestjs/common": "^4.5.0",
|
||||
"@nestjs/core": "^4.5.0",
|
||||
"@nestjs/typeorm": "^2.0.0",
|
||||
"mysql": "^2.14.1",
|
||||
"redis": "^2.7.1",
|
||||
"reflect-metadata": "^0.1.10",
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { PhotoModule } from './photo/photo.module';
|
||||
import { Photo } from './photo/photo.entity';
|
||||
|
||||
@Module({
|
||||
modules: [
|
||||
TypeOrmModule.forRoot([Photo]),
|
||||
PhotoModule,
|
||||
],
|
||||
imports: [TypeOrmModule.forRoot(), PhotoModule],
|
||||
})
|
||||
export class ApplicationModule {}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { ApplicationModule } from './modules/app.module';
|
||||
import { ApplicationModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(ApplicationModule);
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
@Entity()
|
||||
export class Photo {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ length: 500 })
|
||||
name: string;
|
||||
|
||||
@Column('text')
|
||||
description: string;
|
||||
|
||||
@Column()
|
||||
filename: string;
|
||||
|
||||
@Column('int')
|
||||
views: number;
|
||||
|
||||
@Column()
|
||||
isPublished: boolean;
|
||||
}
|
||||
17
examples/05-sql-typeorm/src/photo/photo.entity.ts
Normal file
17
examples/05-sql-typeorm/src/photo/photo.entity.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
@Entity()
|
||||
export class Photo {
|
||||
@PrimaryGeneratedColumn() id: number;
|
||||
|
||||
@Column({ length: 500 })
|
||||
name: string;
|
||||
|
||||
@Column('text') description: string;
|
||||
|
||||
@Column() filename: string;
|
||||
|
||||
@Column('int') views: number;
|
||||
|
||||
@Column() isPublished: boolean;
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { PhotoService } from './photo.service';
|
||||
import { PhotoController } from './photo.controller';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Photo } from './photo.entity';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Photo])],
|
||||
components: [PhotoService],
|
||||
controllers: [PhotoController],
|
||||
})
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, Inject } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { Photo } from './photo.entity';
|
||||
|
||||
@Component()
|
||||
@@ -1,14 +1,2 @@
|
||||
require('ts-node/register');
|
||||
require('./src/server');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require('./src/main');
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"prestart:prod": "tsc",
|
||||
"start:prod": "node dist/server.js"
|
||||
"start:prod": "node dist/main.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^4.3.0",
|
||||
@@ -14,7 +14,7 @@
|
||||
"@nestjs/microservices": "^4.3.0",
|
||||
"@nestjs/testing": "^4.3.0",
|
||||
"@nestjs/websockets": "^4.3.0",
|
||||
"mongoose": "^4.11.13",
|
||||
"mongoose": "^5.0.1",
|
||||
"redis": "^2.7.1",
|
||||
"reflect-metadata": "^0.1.10",
|
||||
"rxjs": "^5.4.3",
|
||||
|
||||
@@ -2,6 +2,6 @@ import { Module } from '@nestjs/common';
|
||||
import { CatsModule } from './cats/cats.module';
|
||||
|
||||
@Module({
|
||||
modules: [CatsModule],
|
||||
imports: [CatsModule],
|
||||
})
|
||||
export class ApplicationModule {}
|
||||
export class ApplicationModule {}
|
||||
@@ -16,4 +16,4 @@ export class CatsController {
|
||||
async findAll(): Promise<Cat[]> {
|
||||
return this.catsService.findAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,8 @@ import { catsProviders } from './cats.providers';
|
||||
import { DatabaseModule } from '../database/database.module';
|
||||
|
||||
@Module({
|
||||
modules: [DatabaseModule],
|
||||
imports: [DatabaseModule],
|
||||
controllers: [CatsController],
|
||||
components: [
|
||||
CatsService,
|
||||
...catsProviders,
|
||||
],
|
||||
components: [CatsService, ...catsProviders],
|
||||
})
|
||||
export class CatsModule {}
|
||||
export class CatsModule {}
|
||||
@@ -7,4 +7,4 @@ export const catsProviders = [
|
||||
useFactory: (connection: Connection) => connection.model('Cat', CatSchema),
|
||||
inject: ['DbConnectionToken'],
|
||||
},
|
||||
];
|
||||
];
|
||||
@@ -5,8 +5,7 @@ import { CreateCatDto } from './dto/create-cat.dto';
|
||||
|
||||
@Component()
|
||||
export class CatsService {
|
||||
constructor(
|
||||
@Inject('CatModelToken') private readonly catModel: Model<Cat>) {}
|
||||
constructor(@Inject('CatModelToken') private readonly catModel: Model<Cat>) {}
|
||||
|
||||
async create(createCatDto: CreateCatDto): Promise<Cat> {
|
||||
const createdCat = new this.catModel(createCatDto);
|
||||
@@ -16,4 +15,4 @@ export class CatsService {
|
||||
async findAll(): Promise<Cat[]> {
|
||||
return await this.catModel.find().exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,4 @@ export class CreateCatDto {
|
||||
readonly name: string;
|
||||
readonly age: number;
|
||||
readonly breed: string;
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,4 @@ export interface Cat extends Document {
|
||||
readonly name: string;
|
||||
readonly age: number;
|
||||
readonly breed: string;
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,4 @@ export const CatSchema = new mongoose.Schema({
|
||||
name: String,
|
||||
age: Number,
|
||||
breed: String,
|
||||
});
|
||||
});
|
||||
@@ -5,4 +5,4 @@ import { databaseProviders } from './database.providers';
|
||||
components: [...databaseProviders],
|
||||
exports: [...databaseProviders],
|
||||
})
|
||||
export class DatabaseModule {}
|
||||
export class DatabaseModule {}
|
||||
9
examples/06-mongoose/src/database/database.providers.ts
Normal file
9
examples/06-mongoose/src/database/database.providers.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import * as mongoose from 'mongoose';
|
||||
|
||||
export const databaseProviders = [
|
||||
{
|
||||
provide: 'DbConnectionToken',
|
||||
useFactory: async (): Promise<mongoose.Connection> =>
|
||||
await mongoose.connect('mongodb://localhost/nest'),
|
||||
},
|
||||
];
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { ApplicationModule } from './modules/app.module';
|
||||
import { ApplicationModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(ApplicationModule);
|
||||
@@ -1,13 +0,0 @@
|
||||
import * as mongoose from 'mongoose';
|
||||
|
||||
export const databaseProviders = [
|
||||
{
|
||||
provide: 'DbConnectionToken',
|
||||
useFactory: async (): Promise<mongoose.Connection> => {
|
||||
(mongoose as any).Promise = global.Promise;
|
||||
return await mongoose.connect('mongodb://localhost/nest', {
|
||||
useMongoClient: true,
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -1,14 +1,2 @@
|
||||
require('ts-node/register');
|
||||
require('./src/server');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
require('./src/main');
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user