NestJSでREST(その1) | 株式会社ROBON
はじめに当社では、クラウドネイティブなSaaSの開発をしており、いつもはWebAPIの実装ならサーバーレスで。となるのですが、今回は、サーバーレスでないWebAPIの実現方法として、NestJS...
https://www.wantedly.com/companies/company_5181558/post_articles/897233
NestJSのCLIでWebサーバー部分はできちゃいました。👏
本家を含めて、mysqlが多いような気がしますが、今回は、別件でPostgesを使っていたので、Postgresでやります。
$ npm install --save @nestjs/typeorm typeorm pg
まず、テーブルを作ります。
CREATE TABLE CUSTOMER (
CUSTOMER_ID int,
NAME text,
ADDRESS text,
CONSTRAINT PK_CUSTOMER PRIMARY KEY(CUSTOMER_ID)
);
ここで英大文字で書いても、Postgresさんは英小文字で認識されていて、後でハマります。
TypeORMにデータベースの設定をしつつ、NestJSのモジュールとしてAppModuleに組み込みます。
@@ -1,10 +1,25 @@
import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CustomersModule } from './customers/customers.module';
+import { Customer } from './customers/entities/customer.entity';
@Module({
- imports: [CustomersModule],
+ imports: [
+ CustomersModule,
+ TypeOrmModule.forRoot({
+ type: 'postgres',
+ host: '■■■■',
+ port: 5432,
+ username: '■■■■',
+ password: '■■■■',
+ database: 'postgres',
+ entities: [Customer],
+ logging: true,
+ synchronize: false,
+ }),
+ ],
controllers: [AppController],
providers: [AppService],
})
loggingをtrueにしておくとハマったときに助かります。(ハマってからtrueにしました)
設定がこんな感じだと丸見えなので、あとでなんとかします。
Java界隈でお馴染みの香りがします。
@@ -1 +1,13 @@
-export class Customer {}
+import { Entity, Column, PrimaryColumn } from 'typeorm';
+
+@Entity()
+export class Customer {
+ @PrimaryColumn({ name: 'customer_id' })
+ customerId: number;
+
+ @Column()
+ name: string;
+
+ @Column()
+ address: string;
+}
ここでハマりました。TypeORMさんは、テーブル名やカラム名をダブルクォートで囲んで渡してます。SQLの世界では大文字小文字の区別はしないのですが、Postgresさんは、ダブルクォートで囲むと書かれたとおりの文字列としてマッチングするそうです。
ですから、上で、@PrimaryColumn({ name: 'customer_id' })としているところをCREATE TABLE文のとおりに'CUSTOMER_ID'としてしまうと、「そんなカラムはありません」の一点張りで動きません。
今回に限らず、実は、ORマッパー嫌いです(笑)。今回は、logging: trueにして、TypeORMが表示したSQLを直叩きしないと解決できませんでした。「な。だから最初から俺にSQL書かせろよ」
前回のイメージのJSONになるように定義します。
@@ -1 +1,5 @@
-export class CreateCustomerDto {}
+export class CreateCustomerDto {
+ customerId: number;
+ name: string;
+ address: string;
+}
Update用のクラスは、以下のように、生成された状態のまま変更しなくても大丈夫です。
export class UpdateCustomerDto extends PartialType(CreateCustomerDto) {}
PartialTypeって何?ってなりますよね。
The PartialType() function returns a type (class) with all the properties of the input type set to optional.
むむむ。ということで、ソースコードを遡ると
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
ということで、?が付いてオプショナル。作成の時は全部だけど、更新の時は欠けてもいい。というのができるのね。TypeScriptは深い。
serviceからやります。