drizzle orm sqlite

소개

프로젝트 기본 구조

📦 <project root>
 ├ 📂 drizzle
 ├ 📂 src
 │   ├ 📂 db
 │   │  └ 📜 schema.ts
 │   └ 📜 index.ts
 ├ 📜 .env
 ├ 📜 drizzle.config.ts
 ├ 📜 package.json
 └ 📜 tsconfig.json

설치

bun add drizzle-orm
bun add -D drizzle-kit @types/bun

환경 설정

.env 파일에 DB_FILE_NAME을 등록해야 한다. (필수는 아닌듯)

DB_FILE_NAME=db.sqlite

db 연결

// import 'dotenv/config';
import { drizzle } from 'drizzle-orm/bun-sqlite';
import { Database } from 'bun:sqlite';

const sqlite = new Database(process.env.DB_FILE_NAME!);
const db = drizzle({ client: sqlite });

테이블 정의

src/db/schema.ts

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

export const usersTable = sqliteTable("users_table", {
  id: int().primaryKey({ autoIncrement: true }),
  name: text().notNull(),
  email: text().notNull().unique(),
});

config 설정

drizzle.config.ts 루트에 생성

import 'dotenv/config';
import { defineConfig } from 'drizzle-kit';

export default defineConfig({
  out: './drizzle',
  schema: './src/db/schema.ts',
  dialect: 'sqlite',
  dbCredentials: {
    url: process.env.DB_FILE_NAME!,
  },
});

테이블 생성

# 개발용 의존성 설치
bun add better-sqlite3 @types/better-sqlite3 -d

# 테이블 생성 (스키마 적용)
bun drizzle-kit push

# bun drizzle-kit generate : 변경사항 기록
# bun drizzle-kit migrate : 변경사항 적용

제네릭 CRUD 코드

import { db } from "./connecter";
import { eq } from "drizzle-orm";
import { type SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core';

export async function createRecord<T extends SQLiteTableWithColumns<any>>(
  table: T,
  data: T['$inferInsert']) {
  return await db
    .insert(table)
    .values(data)
    .returning(); // SQLite에서도 returning() 지원 (단, 최신 SQLite 버전에 한함)
}

export async function readRecord<T extends SQLiteTableWithColumns<any>>(
  table: T,
  id?: number) {
    if (id) {
      return await db
        .select()
        .from(table)
        .where(eq(table.id, id));
    } else {
      return await db
        .select()
        .from(table);
    }
}

export async function updateRecord<T extends SQLiteTableWithColumns<any>>(
  table: T,
  id: number,
  data: Partial<T['$inferUpdate']>
) {
  return await db
    .update(table)
    .set(data)
    .where(eq(table.id, id))
    .returning();
}

export async function deleteRecord<T extends SQLiteTableWithColumns<any>>(
  table: T,
  id: number
) {
  return await db
    .delete(table)
    .where(eq(table.id, id))
    .returning();
}

const crud = {
  createRecord,
  readRecord,
  updateRecord,
  deleteRecord
};

export default crud;