From c785b1bd462b176652efbf430e4d6e585d76b447 Mon Sep 17 00:00:00 2001 From: Chneemann Date: Mon, 3 Aug 2026 19:37:03 +0200 Subject: [PATCH] feat(db): migrate from SQLite to PostgreSQL via Drizzle ORM --- README.md | 5 +++-- db/index.ts | 14 +++++++------- db/schema.ts | 14 ++++++-------- drizzle.config.ts | 8 ++++---- package-lock.json | 47 ++++++++++++++--------------------------------- package.json | 3 +-- 6 files changed, 35 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 04faed0..697d2b9 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,14 @@ A modern, high-performance Kanban & Workflow web application designed to help yo ![Tailwind CSS](https://img.shields.io/badge/Tailwind-v4-38bdf8?style=flat-square&logo=tailwind-css) ![Auth.js](https://img.shields.io/badge/Auth.js-v5-purple?style=flat-square) ![Drizzle ORM](https://img.shields.io/badge/Drizzle-ORM-C5F74F?style=flat-square&logo=drizzle) +![PostgreSQL](https://img.shields.io/badge/PostgreSQL-16-4169E1?style=flat-square&logo=postgresql) ## 🛠️ Tech Stack - **Framework:** [Next.js 16](https://nextjs.org/) (App Router, Route Groups) - **UI & Styling:** [React 19](https://react.dev/), [Tailwind CSS v4](https://tailwindcss.com/) - **Authentication:** [Auth.js v5 (NextAuth)](https://authjs.dev/) with Credentials Provider & bcrypt hashing -- **Database & ORM:** [Drizzle ORM](https://orm.drizzle.team/) & Drizzle Kit +- **Database & ORM:** [PostgreSQL](https://www.postgresql.org/) managed via [Drizzle ORM](https://orm.drizzle.team/) & Drizzle Kit ## 📂 Architecture & Structure @@ -27,4 +28,4 @@ The project uses Next.js Route Groups to separate public and protected applicati ## 🎯 Current Status -_In Progress_ — Core layout structure, responsive navigation, and authentication (Auth.js v5) are implemented. Next up: Migration from SQLite to PostgreSQL via Drizzle ORM. +_In Progress_ — Core layout structure, responsive navigation, PostgreSQL database integration via Drizzle ORM, and full authentication (Auth.js v5) are implemented. diff --git a/db/index.ts b/db/index.ts index 8b67446..db82a9b 100644 --- a/db/index.ts +++ b/db/index.ts @@ -1,15 +1,15 @@ /** - * @file db/index.ts (oder ähnlich) - * @description Initializes the SQLite database connection using better-sqlite3 and sets up the Drizzle ORM instance with the provided schema. + * @file db/index.ts + * @description Initializes the PostgreSQL database connection using postgres-js and configures the Drizzle ORM instance. */ -import { drizzle } from "drizzle-orm/better-sqlite3"; -import Database from "better-sqlite3"; +import { drizzle } from "drizzle-orm/postgres-js"; import * as schema from "./schema"; +import postgres from "postgres"; -const sqlite = new Database("./sqlite.db"); +const client = postgres(process.env.DATABASE_URL!, { prepare: false }); /** - * The Drizzle ORM database instance configured for SQLite with type definitions from the schema. + * The Drizzle ORM database instance configured for PostgreSQL with type definitions from the schema. */ -export const db = drizzle(sqlite, { schema }); +export const db = drizzle(client, { schema }); diff --git a/db/schema.ts b/db/schema.ts index 16d11da..b958af0 100644 --- a/db/schema.ts +++ b/db/schema.ts @@ -1,20 +1,18 @@ /** - * @file db/schema.ts (oder ähnlich) - * @description Defines the SQLite database schema for users and exports related TypeScript types using Drizzle ORM. + * @file db/schema.ts + * @description Defines the PostgreSQL database schema for users using UUIDs, timestamps, and Drizzle ORM. */ -import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core"; +import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"; /** * Database table definition for application users. */ -export const usersTable = sqliteTable("users", { - id: integer("id").primaryKey({ autoIncrement: true }), +export const usersTable = pgTable("users", { + id: uuid("id").defaultRandom().primaryKey(), email: text("email").notNull().unique(), password: text("password").notNull(), - createdAt: integer("created_at", { mode: "timestamp" }) - .$defaultFn(() => new Date()) - .notNull(), + createdAt: timestamp("created_at").defaultNow().notNull(), }); /** diff --git a/drizzle.config.ts b/drizzle.config.ts index c3cc6ff..b68762e 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -1,18 +1,18 @@ /** * @file drizzle.config.ts - * @description Drizzle Kit configuration file specifying schema locations, migration output directories, and database connection credentials for SQLite. + * @description Drizzle Kit configuration file for managing database migrations, schema paths, and database credentials. */ import { defineConfig } from "drizzle-kit"; /** - * Configuration object for Drizzle Kit CLI commands (migrations, introspection, studio). + * Configuration object exported for Drizzle Kit CLI commands. */ export default defineConfig({ schema: "./db/schema.ts", out: "./db/migrations", - dialect: "sqlite", + dialect: "postgresql", dbCredentials: { - url: "./sqlite.db", + url: process.env.DATABASE_URL!, }, }); diff --git a/package-lock.json b/package-lock.json index ea36ccf..8ecb968 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,17 +9,16 @@ "version": "0.1.0", "dependencies": { "bcryptjs": "^3.0.3", - "better-sqlite3": "^13.0.2", "drizzle-orm": "^0.45.2", "lucide-react": "^1.28.0", "next": "16.2.12", "next-auth": "^5.0.0-beta.32", + "postgres": "^3.4.9", "react": "19.2.4", "react-dom": "19.2.4" }, "devDependencies": { "@tailwindcss/postcss": "^4", - "@types/better-sqlite3": "^9.6.0", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", @@ -2584,16 +2583,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@types/better-sqlite3": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-9.6.0.tgz", - "integrity": "sha512-ZEEwBSgMu7GYJOynoagg5X9JbxfL6dTJDsgViJIqh67jV44kyOr9RXfmFjLK5rzC4MWssP06t9hu/JwGDnUbCg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", @@ -3608,18 +3597,6 @@ "bcrypt": "bin/bcrypt" } }, - "node_modules/better-sqlite3": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-13.0.2.tgz", - "integrity": "sha512-jW6oufeDhXZaiX9Lw5A+oerVClx4iFrI6uDj1zu7SqUAjak9vbJvA0NEcKLNxHiQHb6kYCoFzzXYV0YOauhV3g==", - "license": "MIT", - "dependencies": { - "node-addon-api": "^8.0.0" - }, - "engines": { - "node": ">=22" - } - }, "node_modules/brace-expansion": { "version": "1.1.18", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", @@ -6501,15 +6478,6 @@ } } }, - "node_modules/node-addon-api": { - "version": "8.9.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.9.1.tgz", - "integrity": "sha512-4eUQWVPCUUUiBjLnHS3cXWeC6ryoPUc0U3rP7IuzapoGbzMqd/r6KKO0clr0b+snQhsrueFEhCZDdK+LK7hxKg==", - "license": "MIT", - "engines": { - "node": "^18 || ^20 || >= 21" - } - }, "node_modules/node-exports-info": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", @@ -6837,6 +6805,19 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postgres": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.9.tgz", + "integrity": "sha512-GD3qdB0x1z9xgFI6cdRD6xu2Sp2WCOEoe3mtnyB5Ee0XrrL5Pe+e4CCnJrRMnL1zYtRDZmQQVbvOttLnKDLnaw==", + "license": "Unlicense", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } + }, "node_modules/preact": { "version": "10.24.3", "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", diff --git a/package.json b/package.json index 7236133..9fdfcb8 100644 --- a/package.json +++ b/package.json @@ -10,17 +10,16 @@ }, "dependencies": { "bcryptjs": "^3.0.3", - "better-sqlite3": "^13.0.2", "drizzle-orm": "^0.45.2", "lucide-react": "^1.28.0", "next": "16.2.12", "next-auth": "^5.0.0-beta.32", + "postgres": "^3.4.9", "react": "19.2.4", "react-dom": "19.2.4" }, "devDependencies": { "@tailwindcss/postcss": "^4", - "@types/better-sqlite3": "^9.6.0", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19",