From 8b8d220b1326f3ddfaa7cbb466b710cc73b29467 Mon Sep 17 00:00:00 2001 From: sai80082 Date: Mon, 23 Mar 2026 10:46:46 +0530 Subject: [PATCH] feat: add sqlite db --- .gitignore | 5 +++++ drizzle.app.config.ts | 12 ++++++++++++ instrumentation.ts | 7 +++++++ package.json | 6 +++++- src/db/index.ts | 20 ++++++++++++++++++++ src/db/migrations/meta/_journal.json | 5 +++++ src/db/schema/index.ts | 1 + src/db/schema/settings.schema.ts | 9 +++++++++ 8 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 drizzle.app.config.ts create mode 100644 instrumentation.ts create mode 100644 src/db/index.ts create mode 100644 src/db/migrations/meta/_journal.json create mode 100644 src/db/schema/index.ts create mode 100644 src/db/schema/settings.schema.ts diff --git a/.gitignore b/.gitignore index b9f8d23..315d974 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,11 @@ yarn-error.log* # local env files .env*.local +# SQLite database files +/data/*.db +/data/*.db-shm +/data/*.db-wal + # vercel .vercel diff --git a/drizzle.app.config.ts b/drizzle.app.config.ts new file mode 100644 index 0000000..3e3ede5 --- /dev/null +++ b/drizzle.app.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from "drizzle-kit"; + +export default defineConfig({ + dialect: "sqlite", + schema: "./src/db/schema/index.ts", + out: "./src/db/migrations", + dbCredentials: { + url: process.env.APP_DB_PATH + ? `file:${process.env.APP_DB_PATH}` + : "file:./data/app.db", + }, +}); diff --git a/instrumentation.ts b/instrumentation.ts new file mode 100644 index 0000000..e8982e3 --- /dev/null +++ b/instrumentation.ts @@ -0,0 +1,7 @@ +export async function register() { + // Only run on the Node.js server, not in the Edge runtime or client + if (process.env.NEXT_RUNTIME === "nodejs") { + const { runMigrations } = await import("./src/db"); + await runMigrations(); + } +} diff --git a/package.json b/package.json index 75dd287..9301dc6 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,11 @@ "dev": "next dev", "build": "next build", "start": "next start -p ${PORT:=3000} -H ${HOST:=0.0.0.0}", - "lint": "next lint" + "lint": "next lint", + "db:generate": "drizzle-kit generate --config=drizzle.app.config.ts", + "db:migrate": "drizzle-kit migrate --config=drizzle.app.config.ts", + "db:studio": "drizzle-kit studio --config=drizzle.app.config.ts", + "db:push": "drizzle-kit push --config=drizzle.app.config.ts" }, "author": { "name": "Varun Raj Manoharan", diff --git a/src/db/index.ts b/src/db/index.ts new file mode 100644 index 0000000..ea91391 --- /dev/null +++ b/src/db/index.ts @@ -0,0 +1,20 @@ +import { createClient } from "@libsql/client"; +import { drizzle } from "drizzle-orm/libsql"; +import { migrate } from "drizzle-orm/libsql/migrator"; +import path from "path"; +import * as schema from "./schema"; + +const DB_PATH = + process.env.APP_DB_PATH || path.join(process.cwd(), "data", "app.db"); + +const client = createClient({ url: `file:${DB_PATH}` }); + +export const appDb = drizzle(client, { schema }); + +// Run pending migrations automatically on startup. +// migrate() is idempotent — safe to call on every boot. +export async function runMigrations() { + await migrate(appDb, { + migrationsFolder: path.join(process.cwd(), "src", "db", "migrations"), + }); +} diff --git a/src/db/migrations/meta/_journal.json b/src/db/migrations/meta/_journal.json new file mode 100644 index 0000000..7e7f287 --- /dev/null +++ b/src/db/migrations/meta/_journal.json @@ -0,0 +1,5 @@ +{ + "version": "5", + "dialect": "sqlite", + "entries": [] +} diff --git a/src/db/schema/index.ts b/src/db/schema/index.ts new file mode 100644 index 0000000..a58fe37 --- /dev/null +++ b/src/db/schema/index.ts @@ -0,0 +1 @@ +export * from "./settings.schema"; diff --git a/src/db/schema/settings.schema.ts b/src/db/schema/settings.schema.ts new file mode 100644 index 0000000..463a2ee --- /dev/null +++ b/src/db/schema/settings.schema.ts @@ -0,0 +1,9 @@ +import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core"; + +export const settings = sqliteTable("settings", { + key: text("key").primaryKey(), + value: text("value").notNull(), + updatedAt: integer("updated_at", { mode: "timestamp" }).$onUpdate( + () => new Date() + ), +});