はじめに

nestjs/nest のチュートリアルなどを触った際のメモ。

自分の中で知見がまとまったら内容ごとに別記事に分離するかも。

チュートリアル: Documentation | NestJS - A progressive Node.js framework

TL;DR

  • 別途記載

目次

  1. はじめに
  2. TL;DR
  3. 環境・条件
  4. 詳細
    1. NestJS(Nest) とは
    2. インストール/HelloWorld など
    3. HMR(Hot-Module Replacement) の設定
    4. Fastify の利用
    5. Controller/Routing
      1. nest generate controller
      2. デコレータ
      3. async/await
      4. Request payloads
    6. Provides
  5. まとめ
  6. その他・メモ
    1. nest g まとめ
    2. 参考文献の候補
  7. 参考文献

環境・条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.4
BuildVersion: 19E287

$ node -v
v12.7.0

$ npm -v
6.14.5

$ nest -v
7.1.5

$ tsc -v
Version 3.5.3

$ nest i
[System Information]
OS Version : macOS Catalina
NodeJS Version : v12.7.0
NPM Version : 6.14.5

[Nest CLI]
Nest CLI Version : 7.1.5

[Nest Platform Information]
platform-express version : 7.0.0
platform-fastify version : 7.1.0
common version : 7.0.0
core version : 7.0.0

詳細

参考リポジトリ: 17number/nestjs-practice

NestJS(Nest) とは

NestJSとは - NestJSのススメ ~Expressを超えてゆけ~ - Qiita がわかりやすい。以下、引用。

  • Typescript製のバックエンドフレームワーク
  • デフォルトではExpressをコアとして動作
  • Fastifyをコアとして動作させることもできる
  • Node.jsで上で動く
  • 実装と疎結合になるようなアーキテクチャ
  • nest cli で簡単にプロジェクトやソースファイルのテンプレートを生成できる
  • Expressのミドルウェアをそのまま使える
  • テストフレームワークが用意されている
  • 認証ライブラリはPassportなどが使える
  • GraphQLもサポート
  • WebSocketももちろんOK
  • class-validatorを使って楽々バリデーション
  • TypeORMで型の恩恵を最大限に受けつつDB操作できる
  • とにかく拡張性が高い

合わせて、公式ドキュメント から引用。

Introduction
Nest (NestJS) is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with and fully supports TypeScript (yet still enables developers to code in pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).
Under the hood, Nest makes use of robust HTTP Server frameworks like Express (the default) and optionally can be configured to use Fastify as well!
Nest provides a level of abstraction above these common Node.js frameworks (Express/Fastify), but also exposes their APIs directly to the developer. This allows developers the freedom to use the myriad of third-party modules which are available for the underlying platform.

Philosophy
In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications. This has given rise to awesome projects like Angular, React and Vue, which improve developer productivity and enable the creation of fast, testable, and extensible frontend applications. However, while plenty of superb libraries, helpers, and tools exist for Node (and server-side JavaScript), none of them effectively solve the main problem of - Architecture.
Nest provides an out-of-the-box application architecture which allows developers and teams to create highly testable, scalable, loosely coupled, and easily maintainable applications. The architecture is heavily inspired by Angular.

DeepL での翻訳。

序章
Nest (NestJS) は効率的でスケーラブルな Node.js サーバーサイドアプリケーションを構築するためのフレームワークです。プログレッシブJavaScriptを使用し、TypeScriptを使用して構築され、完全にサポートしています(それでも開発者は純粋なJavaScriptでコーディングすることができます)。
Nest は Express (デフォルト) のような堅牢な HTTP サーバフレームワークを利用しており、オプションで Fastify を使用するように設定することもできます。
Nestはこれらの一般的なNode.jsフレームワーク(Express/Fastify)よりも抽象化されたレベルを提供しますが、そのAPIを開発者に直接公開しています。これにより、開発者は基盤となるプラットフォームで利用可能な無数のサードパーティモジュールを自由に使用することができます。

哲学
近年、Node.jsのおかげで、JavaScriptはフロントエンドとバックエンドの両方のアプリケーションのためのウェブの「共通言語」となりました。これにより、Angular、React、Vue のような素晴らしいプロジェクトが生まれ、開発者の生産性を向上させ、高速でテスト可能で拡張性のあるフロントエンドアプリケーションの作成を可能にしました。しかし、多くの優れたライブラリ、ヘルパー、ツールが Node (とサーバーサイド JavaScript) のために存在する一方で、それらのどれもが主な問題であるアーキテクチャを効果的に解決するものではありません。
Nest は、開発者やチームが高度にテスト可能で、スケーラブルで、疎結合で、保守が容易なアプリケーションを作成することを可能にする、すぐに使えるアプリケーションアーキテクチャを提供しています。このアーキテクチャはAngularに大きく影響を受けています。

インストール/HelloWorld など

参考: First steps | NestJS - A progressive Node.js framework

nest CLI をグローバルインストール。

1
$ npm i -g @nestjs/cli

プロジェクト作成。

1
$ nest new nestjs-practice

ディレクトリ構成はこんな感じ。

サーバの起動は npm run start

1
2
3
4
5
6
$ npm run start
[Nest] 2158 - 2020-05-24 21:36:42 [NestFactory] Starting Nest application...
[Nest] 2158 - 2020-05-24 21:36:42 [InstanceLoader] AppModule dependencies initialized +35ms
[Nest] 2158 - 2020-05-24 21:36:42 [RoutesResolver] AppController {}: +15ms
[Nest] 2158 - 2020-05-24 21:36:42 [RouterExplorer] Mapped {, GET} route +7ms
[Nest] 2158 - 2020-05-24 21:36:42 [NestApplication] Nest application successfully started +5ms

http://localhost:3000/ にアクセスすると Hello World! が表示される。

start 以外にも start:dev, start:debug, start:prod などがある。

npm run start:devnpm run start:debug を使うとファイル変更を検知して、自動的にサーバを再起動してくれる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ npm run start:dev
[22:04:59] Starting compilation in watch mode...
[22:05:02] Found 0 errors. Watching for file changes.
[Nest] 5735 - 2020-05-24 22:05:03 [NestFactory] Starting Nest application...
[Nest] 5735 - 2020-05-24 22:05:03 [InstanceLoader] AppModule dependencies initialized +16ms
[Nest] 5735 - 2020-05-24 22:05:03 [RoutesResolver] AppController {}: +6ms
[Nest] 5735 - 2020-05-24 22:05:03 [RouterExplorer] Mapped {, GET} route +3ms
[Nest] 5735 - 2020-05-24 22:05:03 [NestApplication] Nest application successfully started +3ms

# ↓ファイル変更を検知
[22:05:08] File change detected. Starting incremental compilation...
[22:05:08] Found 0 errors. Watching for file changes.
[Nest] 5773 - 2020-05-24 22:05:09 [NestFactory] Starting Nest application...
[Nest] 5773 - 2020-05-24 22:05:09 [InstanceLoader] AppModule dependencies initialized +19ms
[Nest] 5773 - 2020-05-24 22:05:09 [RoutesResolver] AppController {}: +6ms
[Nest] 5773 - 2020-05-24 22:05:09 [RouterExplorer] Mapped {, GET} route +4ms
[Nest] 5773 - 2020-05-24 22:05:09 [NestApplication] Nest application successfully started +4ms

以下は package.jsonscripts 抜粋。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
...,
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
...,
}

HMR(Hot-Module Replacement) の設定

参考PR: HMR(Hot-Module Replacement) の設定 by 17number · Pull Request #1 · 17number/nestjs-practice

参考: Hot reload | NestJS - A progressive Node.js framework

npm run start:dev などで変更検知はしてくれるが、nodemon を使ったサーバ全体の再起動になっており重いらしい。

そこで Webpack を使った HMR(Hot module replacement)の設定を行う。

必要なパッケージのインストール。Installation の内容に @types/webpack-env を追加。
参考: NestJSでHot Module Replacementを使った開発環境構築 - Fusic Tech Blog

1
$ npm i -D webpack-node-externals start-server-webpack-plugin @types/webpack-env

webpack-hmr.config.js を作成。Configuration の内容そのまま。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
const StartServerPlugin = require('start-server-webpack-plugin');

module.exports = function(options) {
return {
...options,
entry: ['webpack/hot/poll?100', options.entry],
watch: true,
externals: [
nodeExternals({
whitelist: ['webpack/hot/poll?100'],
}),
],
plugins: [
...options.plugins,
new webpack.HotModuleReplacementPlugin(),
new webpack.WatchIgnorePlugin([/\.js$/, /\.d\.ts$/]),
new StartServerPlugin({ name: options.output.filename }),
],
};
};

Hot-Module Replacement の記述に従い、src/main.tspackage.json を修正。

src/main.ts

1
2
3
4
5
6
7
8
9
10
 async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
+
+ if (module.hot) {
+ module.hot.accept();
+ module.hot.dispose(() => app.close());
+ }
}
bootstrap();

package.json

1
2
3
4
     "start": "nest start",
- "start:dev": "nest start --watch",
+ "start:dev": "nest build --webpack --webpackPath webpack-hmr.config.js",
"start:debug": "nest start --debug --watch",

npm run start:dev での挙動が変わっているはず。(新規作成したばかりなので、現時点ではあまり恩恵は感じられない)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ npm run start:dev
Info Webpack is building your sources...

Starting type checking service...
Type checking in progress...
Hash: d5e0aacd706a66612726
Version: webpack 4.43.0
Time: 3714ms
Built at: 2020-05-24 22:34:53
Entrypoint main = main.js
[Nest] 8093 - 2020-05-24 22:34:54 [NestFactory] Starting Nest application...
[Nest] 8093 - 2020-05-24 22:34:54 [InstanceLoader] AppModule dependencies initialized +17ms
[Nest] 8093 - 2020-05-24 22:34:54 [RoutesResolver] AppController {}: +8ms
[Nest] 8093 - 2020-05-24 22:34:54 [RouterExplorer] Mapped {, GET} route +4ms
[Nest] 8093 - 2020-05-24 22:34:54 [NestApplication] Nest application successfully started +3ms
No type errors found
Version: typescript 3.9.3
Time: 6639 ms

Info Webpack is building your sources...

No type errors found
Version: typescript 3.9.3
Time: 1441 ms
Hash: f535c18437c7f00721db
Version: webpack 4.43.0
Time: 1447ms
Built at: 2020-05-24 22:35:17
Entrypoint main = main.js 0.d5e0aacd706a66612726.hot-update.js
[Nest] 8093 - 2020-05-24 22:35:17 [NestFactory] Starting Nest application... +22662ms
[HMR] Updated modules:
[HMR] - 9
[HMR] - 8
[HMR] - 6
[HMR] - 4
[HMR] Consider using the NamedModulesPlugin for module names.
[HMR] Update applied.
[Nest] 8093 - 2020-05-24 22:35:17 [InstanceLoader] AppModule dependencies initialized +8ms
[Nest] 8093 - 2020-05-24 22:35:17 [RoutesResolver] AppController {}: +1ms
[Nest] 8093 - 2020-05-24 22:35:17 [RouterExplorer] Mapped {, GET} route +2ms
[Nest] 8093 - 2020-05-24 22:35:17 [NestApplication] Nest application successfully started +1ms

Fastify の利用

参考PR: Fastify の利用 by 17number · Pull Request #2 · 17number/nestjs-practice

参考: Performance (Fastify) | NestJS - A progressive Node.js framework

@nestjs/platform-fastify をインストール。

1
$ npm i @nestjs/platform-fastify

src/main.ts を修正、Adapter の内容そのまま。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 import { NestFactory } from '@nestjs/core';
+import {
+ FastifyAdapter,
+ NestFastifyApplication,
+} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';

async function bootstrap() {
- const app = await NestFactory.create(AppModule);
+ const app = await NestFactory.create<NestFastifyApplication>(
+ AppModule,
+ new FastifyAdapter()
+ );
await app.listen(3000);

lodalhost, 127.0.0.1 以外からの接続を受け付けるには app.listen() を修正。

1
2
-  await app.listen(3000);
+ await app.listen(3000, '0.0.0.0');

Fastify options の例のように FastifyAdapter にオプションを渡すこともできる

1
new FastifyAdapter({ logger: true });

Fastify | MVC | NestJS - A progressive Node.js framework にも Fastify の設定方法が書かれている。
※微妙に↑と異なるが、ちゃんと見てない。

Controller/Routing

参考PR: Overview controllers by 17number · Pull Request #3 · 17number/nestjs-practice

参考: Routing | Controllers | NestJS - A progressive Node.js framework

nest generate controller

nest g co(= nest generate controller) で Controller 一式を追加。

1
2
$ nest g --help
Usage: nest generate|g [options] <schematic> [name] [path]

nest g co cats を実行すると、以下のファイルが生成される。

1
2
3
4
$ nest g co cats
CREATE src/cats/cats.controller.spec.ts (479 bytes)
CREATE src/cats/cats.controller.ts (97 bytes)
UPDATE src/app.module.ts (322 bytes)

src/cats/cats.controller.ts

1
2
3
4
import { Controller } from '@nestjs/common';

@Controller('cats')
export class CatsController {}

src/cats/cats.controller.spec.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { Test, TestingModule } from '@nestjs/testing';
import { CatsController } from './cats.controller';

describe('Cats Controller', () => {
let controller: CatsController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [CatsController],
}).compile();

controller = module.get<CatsController>(CatsController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});

src/app.module.ts

1
2
3
4
5
6
7
 import { AppService } from './app.service';
+import { CatsController } from './cats/cats.controller';
...
imports: [],
- controllers: [AppController],
+ controllers: [AppController, CatsController],
providers: [AppService],

nest g コマンドは -d オプションで Dry Run できる。

1
2
3
4
$ nest g -d co dogs
CREATE src/dogs/dogs.controller.spec.ts (479 bytes)
CREATE src/dogs/dogs.controller.ts (97 bytes)
UPDATE src/app.module.ts (395 bytes)

path を指定すると、src/<path>/<name> でディレクトリが作成される。

1
2
3
4
$ nest g -d co dogs my-dogs
CREATE src/my-dogs/dogs/dogs.controller.spec.ts (479 bytes)
CREATE src/my-dogs/dogs/dogs.controller.ts (97 bytes)
UPDATE src/app.module.ts (403 bytes)

デコレータ

@Controller

@Controller() でベースとなる URL(URI) の指定。@Controller() だと / で、@Controller('cats') だと /cats となる。

1
2
3
4
import { Controller } from '@nestjs/common';

@Controller('cats') // *****
export class CatsController {}
@Get, @Post, @Put, @Patch, @Delete, @Options, @Head, @All

参考: Resources

メソッドの前に @Get(), @Post などを記述することで、HTTP Request とメソッドとを対応付けられる。

  • @Get
  • @Post
  • @Put
  • @Patch
  • @Delete
  • @Options
  • @Head
  • @All
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { Controller, Get, Post } from '@nestjs/common';

@Controller('cats')
export class CatsController {
@Get() // GET /cats で findAll が動作
findAll(): string {
return 'All cats';
}

@Post() // POST /cats で create が動作
create(): string {
return 'New cat';
}
}

@Get('mine') のようにデコレータ内にパスを記述すると /cats/mine が URL となる。

1
2
3
4
5
6
7
8
9
import { Controller, Get } from '@nestjs/common';

@Controller('cats')
export class CatsController {
@Get('mine') // GET /cats/mine で myCat が動作
myCat(): string {
return 'My cat';
}
}

@Get('ab*cd') のようにワイルドカード(*, ?, +, ())も使用可能。
参考: Route wildcards

@Param

@Get(':id') のように :xx で動的なパラメータをパスに指定可能。
参考: Route parameters

id を利用するには @Param() params を引数として渡して params.id のようにするか、あるいは @Param('id') id のようにパラメータ名を @Param にわたすと良い。

@Param() params を渡すパターン。

1
2
3
4
5
6
7
8
9
import { Controller, Get } from '@nestjs/common';

@Controller('cats')
export class CatsController {
@Get(':id') // GET /cats/:id で cat が動作
cat(@Param() params): string {
return `cat ${params.id}`;
}
}

@Param('id') id を渡すパターン。

1
2
3
4
5
6
7
8
9
10
import { Controller, Get } from '@nestjs/common';

@Controller('cats')
export class CatsController {
// 別の記述例
@Get(':id') // GET /cats/:id で cat が動作
cat(@Param('id') id): string {
return `cat ${id}`;
}
}
@Request, @Response, @Res, @Next, @Session, @Param, @Body, @Query, @Headers, @Ip

参考: Request object

@Req() などを使うことでリクエスト(のオブジェクト)の内容を参照可能。

前章の @Param() も Request Object のひとつなので、@Req() req を使って req.params でもアクセス可能。

@Request(), @Req() req
@Response(), @Res()* res
@Next() next
@Session() req.session
@Param(key?: string) req.params / req.params[key]
@Body(key?: string) req.body / req.body[key]
@Query(key?: string) req.query / req.query[key]
@Headers(name?: string) req.headers / req.headers[name]
@Ip() req.ip

@Req() を使う例。

1
2
3
4
5
6
7
8
9
10
11
import { Controller, Get, Req } from '@nestjs/common';
import { FastifyRequest } from 'fastify'; // fastify

@Controller('cats')
export class CatsController {
@Get()
findAll(@Req() request: FastifyRequest): string {
console.log({request});
return 'All cats';
}
}

request をログ出力するとこんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
{
request: Request {
params: {},
raw: IncomingMessage {
_readableState: [ReadableState],
readable: true,
_events: [Object: null prototype],
_eventsCount: 1,
_maxListeners: undefined,
socket: [Socket],
connection: [Socket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: [Object],
rawHeaders: [Array],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '/cats',
method: 'GET',
statusCode: null,
statusMessage: null,
client: [Socket],
_consuming: false,
_dumped: false,
id: 1,
originalUrl: '/cats',
hostname: 'localhost:3000',
ip: '127.0.0.1',
ips: undefined,
log: [Pino]
},
query: [Object: null prototype] {},
headers: {
'user-agent': 'vscode-restclient',
'accept-encoding': 'gzip, deflate',
host: 'localhost:3000',
connection: 'close'
},
log: Pino {
trace: [Function: noop],
debug: [Function: noop],
info: [Function: LOG],
warn: [Function: LOG],
error: [Function: LOG],
fatal: [Function: fatal],
[Symbol(pino.serializers)]: [Object],
[Symbol(pino.chindings)]: ',"pid":2210,"hostname":"MacBook-Pro.local","reqId":1',
[Symbol(pino.levelVal)]: 30,
[Symbol(fastify.disableRequestLogging)]: false
},
body: null,
ip: '127.0.0.1',
ips: undefined,
hostname: 'localhost:3000'
}
}

なお、express を使う場合は @types/express が必要っぽい。

1
$ npm i @types/express
1
2
3
4
5
6
7
8
9
10
import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express'; // *****

@Controller('cats')
export class CatsController {
@Get()
findAll(@Req() request: Request): string { // *****
return 'All cats';
}
}

fastify の場合はたぶん FastifyRequest が適切そう。(引数の型未設定(= any) でも動く)

1
2
3
4
5
6
7
8
9
10
11
import { Controller, Get, Req } from '@nestjs/common';
import { FastifyRequest } from 'fastify'; // *****

@Controller('cats')
export class CatsController {
@Get()
findAll(@Req() request: FastifyRequest): string { // *****
console.log({request});
return 'All cats';
}
}

ちなみに、VSCode 使ってるなら簡単な確認は REST Client を使うのが楽。

@HttpCode

参考: Status code

HTTP Status code はデフォルトで 200(POST は 201)になっている。

@HttpCode() で変更可能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Controller, Get, Post, HttpCode } from '@nestjs/common';

@Controller('cats')
export class CatsController {
@Get()
@HttpCode(204) // *****
findAll(): string {
return 'All cats';
}

@Post()
@HttpCode(202) // *****
create(): string {
return 'New cat';
}
}

参考: Headers

@Header() で Response Header を設定できる。

1
2
3
4
5
6
7
8
9
10
import { Controller, Get, Header } from '@nestjs/common';

@Controller('cats')
export class CatsController {
@Get()
@Header('Foo', 'Bar') // *****
findAll(): string {
return 'All cats';
}
}

@Redirect

@Redirect() でリダイレクトできる。デフォルトの Status Code は 302 だが、@Redirect('path', 301) のように第2引数で設定も可能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { Controller, Get, Redirect } from '@nestjs/common';

@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'All cats';
}

@Get('redirect')
@Redirect('/cats') // *****
redirect() {
console.log('redirect');
}
}

/cats/redirect にアクセスすると、redirect() メソッドの処理後(= console.log の動作後)に /cats にリダイレクトされる。


以下はリダイレクト先についてのメモ

  • @Redirect(''): NG: /cats/redirect でリダイレクトを繰り返す
  • @Redirect('cats'): NG: /cats/cats にリダイレクト
  • @Redirect('/'): NG(場合による): / にリダイレクト

条件次第でリダイレクト先や Status Code を動的に変更したい場合は { url: string, statusCode: number } の Object を返却すると上書き(オーバーライド)される。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Controller, Get, Redirect } from '@nestjs/common';

@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
console.log({request});
return 'All cats';
}

@Get('redirect')
@Redirect('/cats')
redirect() {
return { url: '/', statusCode: 301 }; // *****
}
}

/cats/redirect にアクセスすると、/cats ではなく / にリダイレクトされる。

async/await

参考: Asynchronicity

メソッドを async/await を使って定義可能、戻り値の型を Promise にする必要がある。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { Controller, Get } from '@nestjs/common';

@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'All cats';
}

@Get('async')
async findAllAsync(): Promise<string> { // *****
return 'All cats(async)';
}
}

RxJS Observable を使う書き方もできるらしい。
(RxJS 自体も詳しくないし、試したらエラーになったこともあり、こっちはよくわかってない

Request payloads

参考: Request payloads

POST などでのリソース作成時のパラメータや、GET のリソース取得時のクエリなどは DTO(Data Transfer Object) を使う(のが好ましい)。

Interface を使う方法と Class を使う方法とがあるが、Class を使う方法が推奨されている。

src/cats/dto/create-cat.dto.ts を作成。

1
2
3
4
5
export class CreateCatDto {
name: string;
age: number;
breed: string;
}

src/cats/cats.controller.tsimport して、@Body の型として指定。

1
2
3
4
5
6
7
8
9
10
11
import { Controller, Post, Body } from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto'; // *****

@Controller('cats')
export class CatsController {
@Post()
create(@Body() createCatDto: CreateCatDto): string { // *****
console.log({ createCatDto }); // => { createCatDto: { name: 'tim', age: 3, breed: 'mix' } }
return 'New cat';
}
}

同じように src/cats/dto/update-cat.dto.ts, src/cats/dto/list-all-entities.dto.ts を作成。(中身は要件次第、今回は適当)

src/cats/dto/update-cat.dto.ts

1
2
3
4
5
export class UpdateCatDto {
name: string;
age: number;
breed: string;
}

src/cats/dto/list-all-entities.dto.ts

1
2
3
4
5
6
export class ListAllEntities {
name: string;
age: number;
breed: string;
limit: number;
}

src/cats/cats.controller.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { Controller, Get, Post, Body, Put, Param, Query } from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
import { UpdateCatDto } from './dto/update-cat.dto';
import { ListAllEntities } from './dto/list-all-entities.dto';

@Controller('cats')
export class CatsController {
@Get()
findAll(@Query() query: ListAllEntities): string {
// some logic
return 'All cats';
}

@Post()
create(@Body() createCatDto: CreateCatDto): string {
// some logic
return 'New cat';
}

@Put(':id')
update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) {
// some logic
return `Update cat(id ${id})`;
}
}

Provides

参考: Providers | NestJS - A progressive Node.js framework

ここまで(2020/06/03 01:30 現在)。※すでに長くなってるので記事わけようかな

まとめ

  • 別途記載

その他・メモ

nest g まとめ

nest を実行するとヘルプが表示される。

1
2
3
$ nest
Usage: nest <command> [options]
...

ヘルプの一番下に nest g で使用可能(生成可能)なスキーマが表示されている。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
generate|g [options] <schematic> [name] [path]  Generate a Nest element.
Available schematics:
┌───────────────┬─────────────┐
│ name │ alias │
│ application │ application │
│ class │ cl │
│ configuration │ config │
│ controller │ co │
│ decorator │ d │
│ filter │ f │
│ gateway │ ga │
│ guard │ gu │
│ interceptor │ in │
│ interface │ interface │
│ middleware │ mi │
│ module │ mo │
│ pipe │ pi │
│ provider │ pr │
│ resolver │ r │
│ service │ s │
│ library │ lib │
│ sub-app │ app │
└───────────────┴─────────────┘

-d で Dry Run が可能。

1
2
3
4
5
6
7
8
9
$ nest g -d co dogs
CREATE src/dogs/dogs.controller.spec.ts (479 bytes)
CREATE src/dogs/dogs.controller.ts (97 bytes)
UPDATE src/app.module.ts (395 bytes)

$ nest g -d co dogs my-dogs
CREATE src/my-dogs/dogs/dogs.controller.spec.ts (479 bytes)
CREATE src/my-dogs/dogs/dogs.controller.ts (97 bytes)
UPDATE src/app.module.ts (403 bytes)

参考文献の候補

ちゃんと見れてないやつ。

参考文献

関連記事