はじめに
30代未経験からエンジニアを目指して勉強中のYNと申します。
この記事はBen Awad
さんのFullstack React GraphQL TypeScript Tutorialを初学者が進めていく、という内容です。
Ben
さんの動画は本当に質が高く、とても学びが多いのですが、自分のような初学者は躓きが多く、なかなか前に進まなかったので、振り返りのメモとして書きます。
今回の対象
動画の下記内容までです。
0:00:00 Intro
0:02:02 Node/TypeScript Setup
0:11:29 MikroORM Setup
#始める前に
ローカルにコードをクローン
まずはBenさんのレポジトリを自分のgithubアカウントにFork。
そしてローカルにクローン。
git clone https://github.com/your-account-name/lireddit.git
ブランチをコピー
動画の内容ごとに細かくブランチを切ってくれています。ありがたや。
まずはブランチをローカルにコピーして、そのブランチに移ります。
git pull origin 1_mikroORM-setup:1_mikroORM-setup
git checkout 1_mikroORM-setup
Typescriptのはじめかた
tsconfig.json
を作成
動画のこの部分です
ルートディレクトリで下記コマンドを実行してtsconfig.jsonを作成。コンパイルやデバックなどに関するtypescriptの設定ファイルを作成します。
npx tsconfig.json
tsc -w
とnodemon dist/index.js
を同時に実行する
動画のこの部分です
ts-node
でtsファイルを実行するよりも、tsc
でtsファイルをコンパイルした後にjsファイルを実行した方が速いとのことです。
MikroORMの設定
データベースの作成
動画のこの部分です
この動画では PostgreSQLを使っています。ない人はインストールしましょう。
動画のように、createdb database-name
コマンドでデータベースを作成できますが、下記SQLコマンドでもできます。
psql
# ログイン
CREATE DATABASE database-name;
# データベース作成
\l
# データベースの一覧を表示
DROP DATABASE database-name;
# データベースの削除
\q
# 退出
VScodeのオートコンプリートについて
動画のこの部分です
(自分のMac/JISキーボード環境では)cmd + .
でオートコンプリートが使えます。
mikro-ORMの全体像について
動画のこの部分です
ORMとはObject-relational mapperのことで、面倒なSQL文を用いることなく、TypeScriptのみでデータベースとデータのやりとりをすることができます。
const main = async () => {
const orm = await MikroORM.init({
dbname : 'lireddit',
type : 'postgresql',
entities : [Post]
});
};
main()
上記のようにコードでMikroORM
を初期化し、Postテーブルと情報をやりとりできるようになります。
Entityについて
動画のこの部分です
Entityとはつまりテーブルのことです。
今回、TypeScriptのクラス構文とデコレータを使って下記テーブルのスキーマを定義します。
(公式ドキュメントはこちら)
import { Entity, PrimaryKey, Property } from "@mikro-orm/core";
@Entity() // クラスをテーブルスキーマに変換する
export class Post {
@PrimaryKey() // idをプライマリキーのカラムとして定義する。SQLでインサートする際にはオートインクリメントしてくれる。
id!: number // プライマリキーなので!をつける。nullを許さない。
@Property({ type: "date" }) // createdAtをカラムとして定義する。SQLにDateという型はないので、date型を明示する。
createdAt = new Date();
@Property({ type: "date", onUpdate: () => new Date() }) // 同上。updateの度に新しい日付で上書きするhookを書き足す。
updatedAt = new Date();
@Property({ type: "text" }) // 同上。SQLにstringという型はないので、SQLではtext型を使うことを明示的に示す。
title!: string;
}
まずもって最初に@~~
とかいう見慣れない構文が唐突に出てきて困惑します。(しました。)
これがデコレータです。
デコレータはTypeScriptに導入された新しい構文で、近いうちにJavaScriptにも実装されるみたいです。
デコレータの機能を使うには、tsconfig.json
に下記の設定を付け加える必要があります。
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
},
}
@Entity()
はクラスを修飾するクラスデコレータ、@PrimaeryKey()
はプロパティを修飾するプロパティデコレータです。
このデコレータを使うことによって、TypeScriptのclassをSQLのスキーマに翻訳できる魔法のようなものと捉えればいいと思います。
実際にどうやって翻訳するかが気になるひとはこちらに中身が書いてありますが、中身を意識せずありがたく使わせていただきましょう。
自分としては、
- クラスデコレータはクラスを引数として受け取って、編集したクラスを返す関数
- プロパティデコレータはプロパティを引数として受け取って、何かをする関数
- デコレータを作るためには、決まった引数と決まったやり方がある
ぐらいを抑えておけば十分かなと思いました。
(自分はUdemyでデコレータについて勉強しましたが、デコレータを「使う」分には「便利だな」ぐらいに捉えておけばよいと感じました。)
Postテーブルを作成する
1) mikro-orm.config.ts
を作成
export default {
...
} as Parameters<typeof MikroORM.init>[0];
ここでの一番の学びは、最後のas Parameters<typeof MikroORM.init>[0]
です。
Parameters<>
を付け加えることで、オブジェクトからMikroORMの初期化に関する引数以外を排除することができます。
2) migrationの設定
migration
プロパティに、テーブルを作成するためのmigrationファイルを保存/実行する場所を設定します。
export default {
migrations: {
path: path.join(__dirname, "./migrations"),
pattern: /^[\w-]+\d+\.[tj]s$/,
},
...
} as Parameters<typeof MikroORM.init>[0];
3) migrationファイルの作成
動画のこの部分です
mikro-orm.config.ts
に記載されたmigrationファイルを実行します。
npx mikro-orm migration:create
これにより、Entity
プロパティに記載されているテーブルでまだ作成されていないものを自動的に検知し、(今回はPostテーブル)、Post.ts
に記述されたスキーマに従ってテーブルを作成します。
4) migrationファイルの実行
const main = async () => {
const orm = await MikroORM.init(microConfig);
await orm.getMigrator().up(); // 先ほど作成したmigrationファイルを実行する
};
main()
ちなみに、orm.getMigrator().up()
の部分で、一度実行されたmigrationファイルは裏で履歴をカウントされており、main()
が再度実行されても、同じmigrationが再度実行されることはありません。動画のここにて言及されています。
Postテーブルにデータをinsertする
const main = async () => {
const orm = await MikroORM.init(microConfig);
const post = orm.em.create(Post, { title: "my first post" });
// SQLのcreate tableとinsertを実行する。Postテーブルのスキーマに記載の通り、入力が必要なカラムはtitleだけであることに注意。
// https://mikro-orm.io/docs/entity-manager-api#createentityname-entitynamet-data-entitydatat-newt-p
await orm.em.persistAndFlush(post);
const posts = await orm.em.find(Post, {});
// 空オブジェクトを第二引数とすると、テーブル内のすべての行が帰ってくる
};
main()
persistAndFlush
の使い方はこちらを参照。
Mikro-ORMによるSQL文の実行についてはこちらを参照。
最後に
今回はMikroORM
の設定まで書きました。
チュートリアル全14時間のうち、40分ぐらい進みました。
先は長い。。。
次回=>https://qiita.com/theFirstPenguin/items/5ce4ca5b424b4fb4d9ef