NestJS学習記録 middleware

Middleware

ミドルウェアは、routeハンドラの前に呼び出される関数。リクエストとレスポンスにアクセスすることができる。ミドルウェアは通常nextという名前で変数名を表す。

ミドルウェアはNestMiddlewareを継承したクラスで@Injectable()である。

import { Injectable, NestMiddleware } from '@nestjs/common';

@Injectable()
export class LooggerMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    console.log('Request...');
    next();
  }
}

app.moduleでConfigureに登録することで利用可能になる。

import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatsModule } from './cats/cats.module';
import { LooggerMiddleware } from './loogger.middleware';

@Module({
  imports: [CatsModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
    .apply(LooggerMiddleware)
    .forRoutes('cats');
  }
}

NestJS学習記録

Module

各アプリケーションには、少なくとも1つのモジュールがある。ルートモジュールはNestがアプリケーショングラフの作成に使用する最初の箇所である。小さなアプリケーションではルートモジュールしかないかもしれませんが、大きなアプリケーションではコンポーネントを整理する効果的な方法としてモジュールを利用することが推奨されている。

@Moduleデコレータは単一のオブジェクトを受け取る。

  • providers
    Nestによってインスタンス化され、このモジュールで共有される可能性のあるプロバイダ
  • controllers   インスタンス化する必要のあるコントローラー
  • imports このモジュールで必要とされるプロバイダをインポートされたモジュールのリスト
  • exports   このモジュールをインポートする他のモジュールで利用可能であるべきプロバイダをセット

Feature Module

CatsControllerとCatsServiceは同じドメインに属している。 kono 2つは密接に関連しているのでルートモジュールから機能モジュールに分割することができる

nest g module cats

import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}

そして機能を分割したことによりapp.moduleも整理することができる

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Shared modules

Nestではモジュールはデフォルトでシングルトンである。複数のモジュールで任意のプロバイダの同じインスタンスを共有することができる。 CatsServiceを他のモジュールでも共有したい場合は、exportにCatsServiceを追加する

import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
  exports: [CatsService]
})
export class CatsModule {}

これでCatsModuleをインポートする全てのモジュールでCatsServiceにアクセスすることができる.

Module re-export

インポートしたモジュールを再度エクスポートすることもできる。

@Module({
  imports: [CommonModule],
  exports: [CommonModule],
})
export class CoreModule {}

NestJs 学習記録 Providers

Providers

プロバイダはNestの基本コンセプトで、サービス、リポジトリ、ファクトリ、ヘルパーなどをプロバイダとして扱うことができる。 プロバイダの主な考え方は依存性の注入(DI)できること。 プロバイダは@Injectable()のデコレーションがアノテートされたただのクラス。 オブジェクトの様々な関係を作成、オブジェクトのインスタンスを結ぶ機能はNestのランタイムに大部分移譲することができる。

import { Injectable } from '@nestjs/common';
import { Cat } from './interface/cat.interface';

@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  create(cat: Cat) {
    this.cats.push(cat);
  }

  findAll(): Cat[] {
    return this.cats;
  }
}

Nestjs学習記録 controller

controller

コントローラーの目的はアプリケーションに対する特定の要求を受け取ることです。 routingはどのコントローラーがどの要求を受信するかを制御します。 多くの場合、書くコントローラーには複数にrouteがあり、routeごとに異なるアクションを実行することができます。

コントローラーを作成するために、クラスとでコレータを用いります。 でコレータはクラスを必要なメタデータに関連付け、Nestがルーティングマップを作成します。

Routing

Controllerを作成する時はnest g controller contoller-nameで作成できます。

作成されたコントローラー

import { Controller } from '@nestjs/common';

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

コントローラーを定義するために、@Controller()というでコレータを使用します。@Controller('cats')と書くことにによりcatsコントローラーにマッピングされます。 ただし、今の状態ではPOSTもGETも容易されていません。 この状態でhttp://localhost:3000/catsにアクセスすると{"statusCode":404,"error":"Not Found","message":"Cannot GET /cats"} となり404が返ってきます。 そこで以下のように追加してみました。 これによりhttp://localhost:3000/catsにアクセスした場合は404ではなくThis cation retunrs all catsという文字列が返ってきます。

import { Request } from 'express';

@Controller('cats')
export class CatsController {
  @Get()
  findAll(@Req() requrest: Request ): string {
    return 'This cation retunrs all cats';
  }

  @Get(':id')
  findOne(@Param() params): string {
    console.log(params.id);
    return 'This action return a #${params.id} cat';
  }

  @Post()
  @HttpCode(200)
  @Header('Cache-Control', 'none')
  create(): string {
    return 'This action adds a new cats';
  }
}

リクエストに対してのデコレータは用意されているので場合によって使い分けることができる。

@Request()   req
@Response() 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]

コントローラーを作成した場合はapp.modle.tsインスタンス化する必要がある。 今回はcliツールを利用してるため自動で行われているが

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatsController } from './cats/cats.controller';

@Module({
  imports: [],
  controllers: [AppController, CatsController],
  providers: [AppService],
})
export class AppModule {}

このように

  controllers: [AppController, CatsController],

controllersCatsControllerが追加されている

Nestjs学習記録

what is Nest.js

Nest.jsはNode.jsのフルスタックフレームワークで、scalableである。
また、TypeScriptをサポートしているのでテストが容易である。 Angularからの影響を強く受けている。

How to install

npm install -g @nestjs/cli

Create a new project

nest new project-name

Angularぽい

app.controller.ts 基本となるコントローラー
app.module.ts アプリケーションのrootモジュール
main.ts アプリケーションインスタンスを作成する為のコア関数NestFactoryを使用するアプリケーションのエントリーファイル

Running the application

npm run start

localhost:3000にアクセスすると起動を確認することができます。

caseクラスのインデントをきれいにする

intellijでcaseクラスを書くと

case class User(
                userID: UUID, 
                loginInfo: LoginInfo,
                firstName: Option[String],
                lastName: Option[String], 
                fullName: Option[String], 
                email: Option[String],
) extends Identity

こんなインデントになって気持ち悪い。 しかも自動補正されてしまうので残念

そこでcode styleを変更する Settings -> Editor -> Code Style -> Scala -> Wrapping and Braces -> Method declaration parameters の
Align when multilineのチェックを外す
Use normal indent for parametersにチェックを入れる

f:id:mo121_7:20190401202719p:plain