Open49

Turso の DB を drizzle でマイグレーションやってみる。

Coji MizoguchiCoji Mizoguchi

pnpm init します。

$ pnpm init
Wrote to /Users/coji/progs/spike/turso/turso-drizzle-migration-example/package.json

{
  "name": "turso-drizzle-migration-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
Coji MizoguchiCoji Mizoguchi

turso のサインアップは済んでるので以下はやらない。

turso auth signup
Coji MizoguchiCoji Mizoguchi

テスト用のDBを作成。

$ turso db create drizzle-turso-db
Created database drizzle-turso-db at group default in 4.024s.

Start an interactive SQL shell with:

   turso db shell drizzle-turso-db

To see information about the database, including a connection URL, run:

   turso db show drizzle-turso-db

To get an authentication token for the database, run:

   turso db tokens create drizzle-turso-db
Coji MizoguchiCoji Mizoguchi

DBの情報表示。

turso db show drizzle-turso-db
Name:           drizzle-turso-db
URL:            libsql://drizzle-turso-db-coji.turso.io
ID:             ce5baf12-3212-4a87-84cc-fa3793daa931
Group:          default
Version:        0.23.7
Locations:      bos, cdg, nrt
Size:           4.1 kB
Sleeping:       No
Bytes Synced:   0 B

Database Instances:
NAME     TYPE        LOCATION
nrt      primary     nrt
cdg      replica     cdg
bos      replica     bos
Coji MizoguchiCoji Mizoguchi

トークンつくります。

$ turso db tokens create drizzle-turso-db
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Coji MizoguchiCoji Mizoguchi

.env を書きます

.env
TURSO_CONNECTION_URL=libsql://drizzle-turso-db-coji.turso.io
TURSO_AUTH_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Coji MizoguchiCoji Mizoguchi

drizzle 関係の npm module を入れます。

$ pnpm add drizzle-orm @libsql/client
$ pnpm add -D drizzle-kit
Packages: +32
++++++++++++++++++++++++++++++++
Progress: resolved 38, reused 31, downloaded 1, added 32, done

dependencies:
+ @libsql/client 0.5.6
+ drizzle-orm 0.30.2

Done in 6.4s
Packages: +60
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 141, reused 76, downloaded 16, added 60, done

devDependencies:
+ drizzle-kit 0.20.14

Done in 5.1s
Coji MizoguchiCoji Mizoguchi

drizzle のインスタンス作るヘルパーですね。

mkdir -p src/db
src/db/db.ts
import 'dotenv/config';
import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';

const client = createClient({
  url: process.env.TURSO_CONNECTION_URL!,
  authToken: process.env.TURSO_AUTH_TOKEN!,
});

export const db = drizzle(client);
Coji MizoguchiCoji Mizoguchi

次に drizzle.config.ts。

drizzle.config.ts
import 'dotenv/config';
import type { Config } from 'drizzle-kit';
export default {
  schema: './src/db/schema.ts',
  out: './migrations',
  driver: 'turso',
  dbCredentials: {
    url: process.env.TURSO_CONNECTION_URL!,
    authToken: process.env.TURSO_AUTH_TOKEN!,
  },
} satisfies Config;

これは、Drizzle Kit というものによる、マイグレーション用の設定のようです。

Coji MizoguchiCoji Mizoguchi

スキーマの定義を書きます。ああ、こうなるのかあ。

src/db/schema.ts
import { sql } from 'drizzle-orm';
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core';

export const users = sqliteTable('users', {
  id: integer('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').unique().notNull(),
});

export const posts = sqliteTable('posts', {
  id: integer('id').primaryKey(),
  title: text('title').notNull(),
  content: text('content').notNull(),
  userId: integer('user_id')
    .notNull()
    .references(() => users.id, { onDelete: 'cascade' }),
  createdAt: text('created_at')
    .default(sql`CURRENT_TIMESTAMP`)
    .notNull(),
});

export type InsertUser = typeof users.$inferInsert;
export type SelectUser = typeof users.$inferSelect;

export type InsertPost = typeof posts.$inferInsert;
export type SelectPost = typeof posts.$inferSelect;
Coji MizoguchiCoji Mizoguchi

これでマイグレーションを作成して、DBに apply するそうです。

npx drizzle-kit generate:sqlite
drizzle-kit: v0.20.14
drizzle-orm: v0.30.2

No config path provided, using default 'drizzle.config.ts'
Reading config file '/Users/coji/progs/spike/turso/turso-drizzle-migration-example/drizzle.config.ts'
node:internal/modules/cjs/loader:1144
  const err = new Error(message);
              ^

Error: Cannot find module 'dotenv/config'
Require stack:
- /Users/coji/progs/spike/turso/turso-drizzle-migration-example/drizzle.config.ts
- /Users/coji/progs/spike/turso/turso-drizzle-migration-example/node_modules/.pnpm/drizzle-kit@0.20.14/node_modules/drizzle-kit/bin.cjs
    at Module._resolveFilename (node:internal/modules/cjs/loader:1144:15)
    at Module._load (node:internal/modules/cjs/loader:985:27)
    at Module.require (node:internal/modules/cjs/loader:1235:19)
    at require (node:internal/modules/helpers:176:18)
    at Object.<anonymous> (/Users/coji/progs/spike/turso/turso-drizzle-migration-example/drizzle.config.ts:1:8)
    at Module._compile (node:internal/modules/cjs/loader:1376:14)
    at Module._compile (/Users/coji/progs/spike/turso/turso-drizzle-migration-example/node_modules/.pnpm/drizzle-kit@0.20.14/node_modules/drizzle-kit/bin.cjs:8644:30)
    at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
    at Object.newLoader [as .ts] (/Users/coji/progs/spike/turso/turso-drizzle-migration-example/node_modules/.pnpm/drizzle-kit@0.20.14/node_modules/drizzle-kit/bin.cjs:8648:13)
    at Module.load (node:internal/modules/cjs/loader:1207:32) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/coji/progs/spike/turso/turso-drizzle-migration-example/drizzle.config.ts',
    '/Users/coji/progs/spike/turso/turso-drizzle-migration-example/node_modules/.pnpm/drizzle-kit@0.20.14/node_modules/drizzle-kit/bin.cjs'
  ]
}

Node.js v20.11.1

あかん

Coji MizoguchiCoji Mizoguchi

cjs なのが気になったので package.json に "type": "module", 足して esm にします。

package.json
{
  "name": "turso-drizzle-migration-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
+  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@libsql/client": "^0.5.6",
    "drizzle-orm": "^0.30.2"
  },
  "devDependencies": {
    "drizzle-kit": "^0.20.14"
  }
}
Coji MizoguchiCoji Mizoguchi

dotenv 入れてなかったのでいれます。

$ pnpm i dotenv
Packages: +1
+
Progress: resolved 142, reused 93, downloaded 0, added 0, done

dependencies:
+ dotenv 16.4.5

Done in 560ms
Coji MizoguchiCoji Mizoguchi

もっかい drizzle-kit generate:sqlite します。

$ npx drizzle-kit generate:sqlite

drizzle-kit: v0.20.14
drizzle-orm: v0.30.2

No config path provided, using default 'drizzle.config.ts'
Reading config file '/Users/coji/progs/spike/turso/turso-drizzle-migration-example/drizzle.config.ts'
2 tables
posts 5 columns 0 indexes 1 fks
users 3 columns 1 indexes 0 fks

[] Your SQL migration file ➜ migrations/0000_optimal_overlord.sql 🚀

なんかできたっぽい。

Coji MizoguchiCoji Mizoguchi

できた migration 用の SQL ファイル。

migrations/0000_optimal_overlord.sql
CREATE TABLE `posts` (
	`id` integer PRIMARY KEY NOT NULL,
	`title` text NOT NULL,
	`content` text NOT NULL,
	`user_id` integer NOT NULL,
	`created_at` text DEFAULT CURRENT_TIMESTAMP NOT NULL,
	FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE TABLE `users` (
	`id` integer PRIMARY KEY NOT NULL,
	`name` text NOT NULL,
	`email` text NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX `users_email_unique` ON `users` (`email`);
Coji MizoguchiCoji Mizoguchi

これではまだ DB には反映されてないみたい。一応確認する。

$ turso db shell drizzle-turso-db
Connected to drizzle-turso-db at libsql://drizzle-turso-db-coji.turso.io

Welcome to Turso SQL shell!

Type ".quit" to exit the shell and ".help" to list all available commands.

→  .tables
→  .schema
→  .quit

確かに、空っぽのままですね。

Coji MizoguchiCoji Mizoguchi

マイグレーションを実行するには drizzle の migrate 関数を実行するそうです。
この関数は DB 接続と、マイグレーションファイルの場所を指定して、実行するとまだ適用されていないマイグレーションSQLをあててくれるそうな。

Coji MizoguchiCoji Mizoguchi

で、その migrate 関数を実行するコードを src/db/index.ts に置くと。

src/db/index.ts
import 'dotenv/config';
import { resolve } from 'node:path';
import { db } from './db/db';
import { migrate } from 'drizzle-orm/libsql/migrator';
(async () => {
  await migrate(db, { migrationsFolder: resolve(__dirname, '../migrations') });
})();
Coji MizoguchiCoji Mizoguchi

そもそも typescript 入れてなかったので入れよう。実行用に tsx も入れとく。

$ pnpm i -D typescript tsx
Packages: +3
+++
Progress: resolved 145, reused 96, downloaded 0, added 3, done

devDependencies:
+ tsx 4.7.1
+ typescript 5.4.2

Done in 1.3s
Coji MizoguchiCoji Mizoguchi

tsconfig.jsonを作る。一旦初期で。

$ pnpm tsc --init

Created a new tsconfig.json with:
                                                                              TS
  target: es2016
  module: commonjs
  strict: true
  esModuleInterop: true
  skipLibCheck: true
  forceConsistentCasingInFileNames: true


You can learn more at https://aka.ms/tsconfig
Coji MizoguchiCoji Mizoguchi

とりあえずこんな感じにしておく。

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
Coji MizoguchiCoji Mizoguchi

現時点のディレクトリツリー。

.
├── drizzle.config.ts
├── migrations
│   ├── 0000_optimal_overlord.sql
│   └── meta
│       ├── 0000_snapshot.json
│       └── _journal.json
├── package.json
├── pnpm-lock.yaml
├── src
│   ├── index.ts
│   └── db
│       ├── db.ts
│       └── schema.ts
└── tsconfig.json
Coji MizoguchiCoji Mizoguchi

マイグレーションの名前 (今回は optimal_overload) ってどうやって指定するのかな。

Coji MizoguchiCoji Mizoguchi

drizzle-kit generate:sqlite のヘルプを見てみる。ていうかなんで :sqlite って毎回指定しないといけないんだろう

npx drizzle-kit generate:sqlite --help
Usage: bin generate:sqlite [options]

Options:
  --schema <schema...>  Path to a schema file or folder
  --out <out>           Output folder, 'drizzle' by default
  --breakpoints         Prepare SQL statements with breakpoints
  --custom              Prepare empty migration file for custom SQL
  --config <config>     Path to a config.json file, drizzle.config.ts by default
  -h, --help            display
Coji MizoguchiCoji Mizoguchi

drizzle-kit のヘルプを見てみよう。

npx drizzle-kit --help
Usage: bin [options] [command]

Options:
  --version, -v                output the version number
  -h, --help                   display help for command

Commands:
  generate:pg [options]
  generate:mysql [options]
  generate:sqlite [options]
  check:pg [options]
  check:sqlite [options]
  up:pg [options]
  up:mysql [options]
  up:sqlite [options]
  introspect:pg [options]
  introspect:mysql [options]
  drop [options]
  push:mysql [options]
  introspect:sqlite [options]
  push:sqlite [options]
  check:mysql [options]
  push:pg [options]
  studio [options]
  help [command]               display help for command
Coji MizoguchiCoji Mizoguchi

なぜかコマンドの並びがソートされてないのでソート眺める

  check:mysql [options]
  check:pg [options]
  check:sqlite [options]
  drop [options]
  generate:mysql [options]
  generate:pg [options]
  generate:sqlite [options]
  help [command]               display help for command
  introspect:mysql [options]
  introspect:pg [options]
  introspect:sqlite [options]
  push:mysql [options]
  push:pg [options]
  push:sqlite [options]
  studio [options]
  up:mysql [options]
  up:pg [options]
  up:sqlite [options]
Coji MizoguchiCoji Mizoguchi

うーん、push は想像つくけど、up ってなんだろう。まあいいや。
そもそも db に apply させる処理はどうやってやるの。 src/index.ts を自分で実行するのかな?なんで、index.ts なんだ。。

Coji MizoguchiCoji Mizoguchi

てか、このチュートリアルでは以下の様に書いてあるから、src/index.ts なのは普通ではないのだろう。

To run migrations, use the migrate function. This function takes your database connection and the path to your migrations directory as arguments. In the provided example, we call it in index.ts, applying all pending migrations to the database.

日本語訳

マイグレーションを実行するには、migrate関数を使います。この関数はデータベース接続と migrations ディレクトリへのパスを引数として受け取ります。提供されている例では、index.tsの中でこの関数を呼び出し、保留中のすべてのマイグレーションをデータベースに適用しています。

The basic file structure outlines how the project is organized, with the src directory containing your database and schema definitions (db.ts and schema.ts) and the entry point to your application (index.ts). The migrations directory holds your migrations and their metadata.

日本語訳

基本的なファイル構造はプロジェクトがどのように構成されているかを示しており、srcディレクトリにはデータベースとスキーマの定義(db.tsとschema.ts)とアプリケーションのエントリポイント(index.ts)があります。migrationsディレクトリには、マイグレーションとそのメタデータが格納されています。

Coji MizoguchiCoji Mizoguchi

ディレクトリ構造の説明したあとで以下のように急に書いてある。alternative のまえに、普通はどうするのか知りたい

As an alternative to generating migration files, you can apply your schema changes directly to the database without generating any migrations files using drizzle-kit push:sqlite command:

日本語訳

マイグレーションファイルを生成する代わりに、drizzle-kit push:sqliteコマンドを使用して、マイグレーションファイルを生成せずにスキーマの変更をデータベースに直接適用することができます:

npx drizzle-kit push:sqlite

It is good for situations where you need to quickly test new schema designs or changes in a local development environment, allowing for fast iterations without the overhead of managing migration files.

日本語訳

ローカルの開発環境で新しいスキーマ設計や変更を素早くテストする必要がある場合に適しており、マイグレーションファイルの管理にかかるオーバーヘッドなしに、迅速な反復を可能にする。

Coji MizoguchiCoji Mizoguchi

とりあえず何も考えずに migrate 関数が書かれた src/index.ts を実行してみよう。

$ pnpm tsx src/index.ts
/Users/coji/progs/spike/turso/turso-drizzle-migration-example/src/index.ts:6
  await migrate(db, { migrationsFolder: resolve(__dirname, "../migrations") });
                                                ^


ReferenceError: __dirname is not defined
    at <anonymous> (/Users/coji/progs/spike/turso/turso-drizzle-migration-example/src/index.ts:6:49)
    at <anonymous> (/Users/coji/progs/spike/turso/turso-drizzle-migration-example/src/index.ts:7:1)
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:28:7)
    at async handleMainPromise (node:internal/modules/run_main:113:12)

Node.js v20.11.1

おっと、ESM だ。

Coji MizoguchiCoji Mizoguchi

__dirname を用意して top-level await に。

src/index.ts
import "dotenv/config";
import { resolve, dirname } from "node:path";
import { db } from "./db/db";
import { migrate } from "drizzle-orm/libsql/migrator";

+const __dirname = dirname(new URL(import.meta.url).pathname);

-(async () => {
  await migrate(db, { migrationsFolder: resolve(__dirname, "../migrations") });
-})();
Coji MizoguchiCoji Mizoguchi

DB の中身を確認してみる。

$ turso db shell drizzle-turso-db
Connected to drizzle-turso-db at libsql://drizzle-turso-db-coji.turso.io

Welcome to Turso SQL shell!

Type ".quit" to exit the shell and ".help" to list all available commands.

→  .schema
CREATE TABLE "__drizzle_migrations" (                                                      
                        id SERIAL PRIMARY KEY,                                                                     
                        hash text NOT NULL,                                                                        
                        created_at numeric                                                                         
                );                                                                                         
CREATE TABLE `posts` (                                                                     
        `id` integer PRIMARY KEY NOT NULL,                                                         
        `title` text NOT NULL,                                                                     
        `content` text NOT NULL,                                                                   
        `user_id` integer NOT NULL,                                                                
        `created_at` text DEFAULT CURRENT_TIMESTAMP NOT NULL,                                      
        FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade     
);                                                                                         
CREATE TABLE `users` (                                                                     
        `id` integer PRIMARY KEY NOT NULL,                                                         
        `name` text NOT NULL,                                                                      
        `email` text NOT NULL                                                                      
);                                                                                         
CREATE UNIQUE INDEX `users_email_unique` ON `users` (`email`);

おお、適用されている。
けど、migrate ってなにも表示されないのw

Coji MizoguchiCoji Mizoguchi

__drizzle_migrations の中身

→  select * from __drizzle_migrations;
ID       HASH                                                                 CREATED AT    
NULL     4bef5132616629fad7fc94e9db67b5bd0feeb3f3ea08793668c3ed4691a58b1d     1710654206169

created_at unix シリアルみたいだなあ。prisma と一緒か。。

Coji MizoguchiCoji Mizoguchi

drizzle-kit push:sqlite をやってみたい。
src/db/schema.ts を編集して、 users テーブルに photoUrl カラムを足してみよう。

src/db/schema.ts
import { sql } from "drizzle-orm";
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";

export const users = sqliteTable("users", {
  id: integer("id").primaryKey(),
  name: text("name").notNull(),
  email: text("email").unique().notNull(),
+  photoUrl: text("photo_url"),
});

export const posts = sqliteTable("posts", {
  id: integer("id").primaryKey(),
  title: text("title").notNull(),
  content: text("content").notNull(),
  userId: integer("user_id")
    .notNull()
    .references(() => users.id, { onDelete: "cascade" }),
  createdAt: text("created_at")
    .default(sql`CURRENT_TIMESTAMP`)
    .notNull(),
});

export type InsertUser = typeof users.$inferInsert;
export type SelectUser = typeof users.$inferSelect;

export type InsertPost = typeof posts.$inferInsert;
export type SelectPost = typeof posts.$inferSelect;
Coji MizoguchiCoji Mizoguchi

push してみる。

$ npx drizzle-kit push:sqlite
No config path provided, using default path
Reading config file '/Users/coji/progs/spike/turso/turso-drizzle-migration-example/drizzle.config.ts'
drizzle-kit: v0.20.14
drizzle-orm: v0.30.2

 Warning  Found data-loss statements:
· You're about to delete __drizzle_migrations table with 1 items

THIS ACTION WILL CAUSE DATA LOSS AND CANNOT BE REVERTED

Do you still want to push changes?
❯ No, abort
  Yes, I want to remove 1 table
Coji MizoguchiCoji Mizoguchi

デフォ指定がないから削除するってでるのかね。
デフォ指定入れてやってみる

Coji MizoguchiCoji Mizoguchi

default NULL に。これでいいのかしら。

import { sql } from "drizzle-orm";
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";

export const users = sqliteTable("users", {
  id: integer("id").primaryKey(),
  name: text("name").notNull(),
  email: text("email").unique().notNull(),
-  photoUrl: text("photo_url"),
+  photoUrl: text("photo_url").default(sql`NULL`),
});

export const posts = sqliteTable("posts", {
  id: integer("id").primaryKey(),
  title: text("title").notNull(),
  content: text("content").notNull(),
  userId: integer("user_id")
    .notNull()
    .references(() => users.id, { onDelete: "cascade" }),
  createdAt: text("created_at")
    .default(sql`CURRENT_TIMESTAMP`)
    .notNull(),
});

export type InsertUser = typeof users.$inferInsert;
export type SelectUser = typeof users.$inferSelect;

export type InsertPost = typeof posts.$inferInsert;
export type SelectPost = typeof posts.$inferSelect;
Coji MizoguchiCoji Mizoguchi

もっかい。

$ npx drizzle-kit push:sqlite
No config path provided, using default path
Reading config file '/Users/coji/progs/spike/turso/turso-drizzle-migration-example/drizzle.config.ts'
drizzle-kit: v0.20.14
drizzle-orm: v0.30.2

 Warning  Found data-loss statements:
· You're about to delete __drizzle_migrations table with 1 items

THIS ACTION WILL CAUSE DATA LOSS AND CANNOT BE REVERTED

Do you still want to push changes?
❯ No, abort
  Yes, I want to remove 1 table

あ、削除されるの __drizzle_migrations テーブルじゃん。あれ、これいいの消して。

Coji MizoguchiCoji Mizoguchi

確認。たしかに消えたね。users.photoUrl カラムはデフォ NULL で増えた。

$ turso db shell drizzle-turso-db
Connected to drizzle-turso-db at libsql://drizzle-turso-db-coji.turso.io

Welcome to Turso SQL shell!

Type ".quit" to exit the shell and ".help" to list all available commands.

→  .schema
CREATE TABLE `posts` (                                                                     
        `id` integer PRIMARY KEY NOT NULL,                                                         
        `title` text NOT NULL,                                                                     
        `content` text NOT NULL,                                                                   
        `user_id` integer NOT NULL,                                                                
        `created_at` text DEFAULT CURRENT_TIMESTAMP NOT NULL,                                      
        FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade     
);                                                                                         
CREATE TABLE `users` (                                                                     
        `id` integer PRIMARY KEY NOT NULL,                                                         
        `name` text NOT NULL,                                                                      
        `email` text NOT NULL                                                                      
, `photo_url` text DEFAULT NULL);                                                          
CREATE UNIQUE INDEX `users_email_unique` ON `users` (`email`);
Coji MizoguchiCoji Mizoguchi

所感。

good

  • migrations SQLが残って、未適用のマイグレーションをSQLファイル指定せずにあてられるのは嬉しい (vs prisma+turso / kysely)
  • エンティティの型が inferInsert / inferSelect できれいに取り出せるのは良い (vs kysely)

no good

  • migration 用の cli がないのがダルい。(vs prisma)
    • マイグレーションをあてるのを flyio で本番デプロイ時にやる、みたいのは面倒そう (dockerイメージを小さくするため / メモリ消費を小さくするため、tsx, ts などを入れないで済むほうが楽だから)
  • エンティティの型名が SelectUser とかになるのがちょっとダルい (vs prisma)

総じて、turso を使う前提だと以下の順になりそう。僅差だけどなあ。

  1. drizzle
  2. prisma+kysely+kysely-libsql (マイグレーション管理がダルい)
  3. prisma+turso EA (マイグレーション管理がダルい)
Coji MizoguchiCoji Mizoguchi

flyio で使うなら:
3. prisma+turso EA (やっぱ prisma が楽)

cloudflare pages で使うなら:

  1. drizzle OR 2. prisma+kysely+kysely-libsql (prisma は 1MB 制限に対してデカすぎ)

prisma.schema はやっぱり便利なんだよなあ。慣れてるし、仕事でやってるクライアントの案件でも使ってて剥がすのはちょっと想像つかない。

drizzle のマイグレーション管理は良いんだけど、スキーマ定義と migration の CLI がないので、慣れるのに気合がいるなあ。

Coji MizoguchiCoji Mizoguchi

ORM のクエリーの書きやすさについては、あんまりこだわりがなかったりします。
型がついてくれて、柔軟にできるのがいいけれど、フロント用だと別に prisma でも十分だし。
管理系の集計クエリなどには prisma だときついので kysely か drizzle か、ってかんじ。

決定的なのがないなあ。