STERFIELD

ZenStack を使用してデータベーススキーマを作成する

ZenStack を使用してデータベーススキーマを作成する

はじめに

Prisma でデータベーススキーマを書く際に、ZenStack というフレームワークが便利だったので紹介します。 ZenStack にはさまざまな機能がありますが、今回はデータベーススキーマの定義について重点的に説明します。

ZenStack とは

ZenStack は、Node.js と TypeScript 向けのフルスタック開発フレームワークです。データベーススキーマを定義するだけで、フロントエンドとバックエンドの実装を自動的に生成できます。 ZenStack は、Prisma ORM をベースとして構築されているので、Prisma のすべての機能を利用できます。

ZenStack を使用したデータベーススキーマの書き方

ZenStack では、ZModel というデータモデリング言語でデータベーススキーマを作成します。 Prisma Schema をベースとしているので、基本的な文法は Prisma Schema と同じように書くことができます。

また、VSCode 向けにZenStack の拡張機能が用意されています。 エラーチェックやコード補完をしてくれるので、ZModel でデータベーススキーマを書く際はインストールしておくと便利です。

ZModel を Prisma Schema に変換する方法

ZModel で定義したデータベーススキーマを Prisma で使用するには、以下のコマンドで ZModel → Prisma Schema に変換する必要があります。

npx zenstack generate

変換元と変換先のファイルパスを指定したい場合は package.json に以下の設定を記述します。

  "zenstack": {
    "schema": "[変換元のZModelファイル(デフォルト:./schema.zmodel)]"
    "prisma": "[変換先のSchemaファイル(デフォルト:./prisma/schema.prisma)]",
  },

ZModel の便利機能

Zmodel で利用できる便利な機能をいくつか紹介します。

abstract

ベースとなる抽象化 model を作成し、各項目を継承できます。 登録日時などのように、各テーブルに共通なフィールドがある場合に使うと便利です。

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url = env("DATABASE_URL")
}

abstract model Base {
  id Int @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model User extends Base {
  email String @unique
  name String
  posts Post[]
}

model Post extends Base {
  title     String
  content   String?
  published Boolean @default(false)
  author    User? @relation(fields:  [authorId], references: [id])
  authorId  Int?
}

上記 ZModel を変換すると、以下のような Prisma Schema が生成されます。

datasource db {
    provider = "postgresql"
    url = env("DATABASE_URL")
}

generator client {
    provider = "prisma-client-js"
}

model User {
    id Int @id() @default(autoincrement())
    createdAt DateTime @default(now())
    updatedAt DateTime @updatedAt()
    email String @unique()
    name String
    posts Post[]
}

model Post {
    id Int @id() @default(autoincrement())
    createdAt DateTime @default(now())
    updatedAt DateTime @updatedAt()
    title String
    content String?
    published Boolean @default(false)
    author User? @relation(fields: [authorId], references: [id])
    authorId Int?
}

ファイル分割

1 ファイルで全てのスキーマを定義すると、スキーマが増えてくるにつれて管理が大変になると思います。 そこで、ZModel ファイルを分割してスキーマ定義する方法を紹介します。

今回の例では ZModel ファイルを以下のように分割してみます。

  • base.zmodel: generator や datasource を記述するファイル
  • user.zmodel: user のスキーマ
  • post.zmodel: post のスキーマ

base.zmodel

// importに分割したZmodelファイルをすべて記載します
import "user"
import "post"

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url = env("DATABASE_URL")
}

user.zmodel

model User {
  id Int @id() @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt()
  email String @unique()
  name String
  posts Post[]
}

post.zmodel

model Post {
  id Int @id() @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt()
  title String
  content String?
  published Boolean @default(false)
  author User? @relation(fields: [authorId], references: [id])
  authorId Int?
}

変換元のファイルを「base.zmodel」に指定して変換すると、以下のような Prisma Schema が生成されます。

datasource db {
    provider = "postgresql"
    url = env("DATABASE_URL")
}

generator client {
    provider = "prisma-client-js"
}

model User {
    id Int @id() @default(autoincrement())
    createdAt DateTime @default(now())
    updatedAt DateTime @updatedAt()
    email String @unique()
    name String
    posts Post[]
}

model Post {
    id Int @id() @default(autoincrement())
    createdAt DateTime @default(now())
    updatedAt DateTime @updatedAt()
    title String
    content String?
    published Boolean @default(false)
    author User? @relation(fields: [authorId], references: [id])
    authorId Int?
}

属性

ZModel でのみ使用できる属性を一部紹介します。 詳しい内容は公式リファレンスをご確認ください。

@password

データベースにハッシュ化した文字列を登録/更新します。 内部的にはbcryptjsライブラリを使用してハッシュ化しているようです。

以下のように引数が定義されていて、saltLength からハッシュのコストを設定したり、salt の設定も可能です。

@password(saltLength: Int?, salt: String?)

@omit

この属性を指定したフィールドはデータ呼び出し時に値が取得されなくなります。 上記の@password と組み合わせて使用すると便利です。

まとめ

最近リリースされたばかりのフレームワークだからなのか、情報量が少なく調べるのに苦労しました。 今回は ZModel を重点的に紹介しましたが、他にも魅力的な機能がたくさんあるライブラリなので、次の機会に紹介したいと思います!

参考

Author Profile

著者近影

AIROU

プログラマーです 猫とラーメンが好きです

SHARE

合わせて読みたい