iT邦幫忙

2023 iThome 鐵人賽

DAY 1
0
Modern Web

一些讓你看來很強的全端- trcp 伴讀系列 第 9

Day-09. 一些讓你看來很強的全端 TRPC 伴讀 - prisma

  • 分享至 

  • xImage
  •  

今天要來介紹一個本人非常喜歡的 ORM 框架 prisma,會選擇他的原因是他是一套有 type-safeORM,同時語法也非常直觀,再加上主流在用 trpc 的開發者都會採用 prisam 來操作 db

介紹 prisma

prisma 一款 developer experience 有好的 orm 框架, prisma 對與 date model 定義都非常直觀且簡單易用,同時提供 cli 指定自動幫你 migrations model,對於 tabel schema 的 interface 也自動幫你生成,同時 prisma 支援多種 sqlnosql ,可以算是學依照 orm 就可以應付大部分的 db ,開發成本與性價比非常低,還有另外一個筆者特別喜歡的是在 prisma 整合多種 db 指令,甚至 prisma 本身還可以自己寫 sql 語法操作,所以不用擔心特定的 db 功能無法使用的情況。

const result = await prisma.$executeRawUnsafe(
  `UPDATE User SET active = ${active} WHERE emailValidated = ${emailValidated}`
)

創建 prisma

step1 install package

大家要記得使用 prisma 記得是 ts 專案,所以所有跟 node 有關的 @type 請確保有 install

> npm install typescript ts-node @types/node --save-
> npm install prisma --save-dev
> npx tsc --init

step2 init prisma

之後初始化 prisma 設定,這邊筆者先用 sqlite 示範,如果讀者有習觀的 db 例如 postgresql 可以改成 --datasource-provider postgresql

npx prisma init --datasource-provider sqlite

以下是 prisma 目前有支援的 db

圖片來源

之後你會發現在你的專案資料夾中會多一個 prisma 的資料夾,接著我們來簡單看看 schema.prisma 內容~

之後我們定義 prisma schema

// prisma/schema.prisma

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

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

model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String?
  published Boolean @default(false)
}

generator client

主要是 pirmsa 透過 cli 生成的行為
provider : 採用的模板這是預設值,通常不需要更改。

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

datasource db

相關 db 設定:
provider: db 種類。
url : db url, env() 則是去抓 .env 的 DATABASE_URL

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}
// .env
DATABASE_URL="file:./dev.db"

model

這邊先定義一個 Postmodal

介紹 model 欄位
@id: 指定 modelid 欄位為 primary key,通常會搭配 @default(autoincrement()) 這樣之後新增的資料 id 會自動 +1。
@default : 預設值。
autoincrement : 這是 prisma 提供的 function
? : prisma 預設所有欄位都是必填,? 則是代表這個欄位是可選狀況。

model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String?
  published Boolean @default(false)
}

step3 migrate prisma

但現在你只有 schema 並沒有 database table,所以需要將定義好 schemamigrate,透過 migrate prisma 會自動根據你的 schema 生成 sql 指令。

> npx prisma migrate dev --name init

如果你在 terminal 中看到以下內容就代表你成功摟~

The following migration(s) have been created and applied from new schema changes:

migrations/
  └─ 20230827150206_/
    └─ migration.sql

Your database is now in sync with your schema.

✔ Generated Prisma Client (v5.2.0) to ./node_modules/@prisma/client in 37ms

你會看到 prisma 自動幫生成 table~

// migration.sql

-- CreateTable
CREATE TABLE "Post" (
    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "title" TEXT NOT NULL,
    "content" TEXT,
    "published" BOOLEAN NOT NULL DEFAULT false
);

step4 generate prisma

之後你需要透過 cli generate prisma client ,如此以來你就成功設定好 prisma 了~

> npx prisma generate 

step5 create prisma client

首先我們在 ~/server/db.ts 中創建 prisma client,這邊你一定很好奇為什麼不要直接 return new PrismaClient 就好,原因是如果直接 return 得話會造成太多 sql connect,所以透過 globalThis 去減少多個 client instance 被創建 。

// ~/server/db.ts
import { PrismaClient } from "@prisma/client";

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined;
};

export const prisma =
  globalForPrisma.prisma ??
  new PrismaClient({
    log:
      process.env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"],
  });

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

之後把 prisma 放到 trpc context function 中~

export const createTRPCContext = async (opts: CreateNextContextOptions) => {

  return {
    prisma
  };
};

prisma studio

prisma 很貼心的提供 studio 功能讓我們檢視我們生成的 schema 內容是否符合預期,最後我們來看看結果吧~

> npx prisma studio

看來一切都很順利呢~好拉今天先到這邊,明天我們來用 prisma 簡單做個 todo 給大家玩玩~

相關連結:

https://www.prisma.io/docs/concepts/database-connectors

✅ 前端社群 :
https://lihi3.cc/kBe0Y


上一篇
Day-08. 一些讓你看來很強的全端 TRPC 伴讀 - Context / middleware
下一篇
Day-010. 一些讓你看來很強的全端 TRPC 伴讀 - TodoList (上)
系列文
一些讓你看來很強的全端- trcp 伴讀30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言