Express
+ TypeScript
+ MySQL
+ typeORM
+ routing-controllers
でのサーバーサイド開発の雰囲気を掴むために知識を埋めていく過程のログです。
node: 12.2.0
typeorm: 0.2.17
typescript: 3.4.5
インストールと Typescript の設定
必要なパッケージのインストール。
yarn add mysql typeorm reflect-metadata
yarn add --dev @types/node nodemon ts-node typescript
tsconfig
はゆるく作ります。
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["es2019"],
"sourceMap": true,
"outDir": "./build",
"incremental": true,
"removeComments": false,
"downlevelIteration": true,
"strict": true,
"noImplicitAny": false,
"strictNullChecks": true,
"strictFunctionTypes": false,
"strictBindCallApply": false,
"strictPropertyInitialization": false,
"noImplicitThis": false,
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true
}
}
package.json
に run & watch を追加します。
...
"scripts": {
"start": "nodemon --exec ts-node -- ./src/index.ts"
},
...
typeORMのQuick Start
ここからtypeORMのQuick Start を進めます。typeorm
のコマンドを使ってプロジェクトを作るように指示されます。すでにプロジェクトを作っていたので typeorm init --database mysql
しました。
You can also run
typeorm init
on an existing node project
typeorm init
するとtsconfig.json
とpackage.json
が上書きされ、typescript
関連モジュールのバージョンがダウングレードされてしまいます。これは嬉しくないのでpackage.json
とtsconfig.json
の変更を捨てて手動で変更します。
変更を捨ててtsconfig.json
に以下を追加する必要があるようです。
...
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
...
動作確認
Quick Start に戻って指示通りormconfig.json
にデータベースの情報を入れるとコードを動かせます。
npm run start
して起動確認、データベースに正常に書き込まれているかどうかも mySQL Workbench
などで確認します。
指定したデータベースにUser
テーブルが追加されユーザーが追加されていれば正解です。
@Enityでテーブルを定義する
@Enityでテーブルを定義できます。column
の型は自動で入りますが、指定することもできます。参考: Column types
@Entity()
export class Photo {
@PrimaryColumn()
id: number;
@Column({ length: 100 })
name: string;
@Column("text")
description: string;
@Column("double")
views: number;
@Column()
isPublished: boolean;
}
ここで気になったのがentity
を変更するとデータベースのテーブルも変更してしまう点です。レコードがあろうとentity
を変更して実行するたびにデータベースのテーブルが変更されます。これは怖い。
この動作はormconfig.json
のsynchronize
をfalse
にすることで解決することができました。
TypeORM Migrations
上記のとおりsynchronize: false
にするとEntityのコード変更でデータベースが変更されることはなくなります。
変わりに「Entity
を作る → migration
ファイルの生成 → migration
ファイルの実行」という流れにします。
migration ファイルを作る
テーブルの追加や変更はtypeorm migration
を使ってすることになります。データベース上のテーブルとEntityの差分からmigration
ファイルを作ってくれます。
typeorm migration:generate -n changeEntity
ところでSyntaxError: Unexpected token {
というimportできないエラーがでてしまいました。ググったところts-nodeで解決するようなので ./node_modules/.bin/ts-node ./node_modules/.bin/typeorm migration:generate -n changeEntity
します。
migration ファイルを実行する
generateしたmigrationファイルを実行します。
typeorm migration:run // したい
./node_modules/.bin/ts-node ./node_modules/.bin/typeorm migration:run
./node_modules/.bin/ts-node ./node_modules/.bin/typeorm
はめんどうなので他の解決作を探したいところですが。時間がもったいないので、そのまま npm scripts
に入れておきます。
typeORM + routing-controllers
最後にrouting-controllers
を試します。typeorm-routing-controllers-extensions
があるのでこれを導入していきます。 https://github.com/typeorm/typeorm-routing-controllers-extensions のReadmeを参考に進めました。
必要なパッケージなどをインストールします。
yarn add express typeorm-routing-controllers-extensions routing-controllers
yarn add --dev @types/express
typeORM
の Quick Start で作ったデータベースとデータを使ってrouting-controllers
を試していきます。
ここでsrc
以下のファイル構成はおさらいしておきます。
src/
├ entity/
│ └ User.ts
├ migration/ ...
├ index.ts ← 変更します。
└ controller/ ← 新規ディレクトリ。
└ UserController.ts ← 新規ファイル。
UserController
を作ってindex.ts
から読み込みます。
import { Get, JsonController } from 'routing-controllers';
import { User } from '../entity/User';
import { EntityFromParam } from 'typeorm-routing-controllers-extensions';
@JsonController()
export class UserController {
@Get('/users/:id')
get(@EntityFromParam('id') user: User) {
return user;
}
}
import 'reflect-metadata';
import { createConnection } from 'typeorm';
import { createExpressServer } from 'routing-controllers';
import { UserController } from './controller/UserController';
createConnection()
.then(async connection => {
createExpressServer({
controllers: [UserController]
}).listen(3000);
console.log('Server is up and running on port 3000.');
})
.catch(error => console.log('Error: ', error));
npm run start
してブラウザからhttp://localhost:3000/users/1
すると確認することができます。
後半が雑になってしまいましたが。これくらいからドキュメントを読んでいけばサクサクすすめられそうです。typeORM
+ routing-controllers
はシンプルで気にいったので、しばらく使ってみようと思います。