chore(db): setup drizzle orm with postgres driver and drizzle-kit configuration
This commit is contained in:
parent
9d175303f5
commit
6eab20eaa4
7 changed files with 1973 additions and 6 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -39,3 +39,8 @@ yarn-error.log*
|
|||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
# SQLite Datenbanken
|
||||
*.db
|
||||
*.db-journal
|
||||
/db/migrations/
|
||||
12
README.md
12
README.md
|
|
@ -6,22 +6,28 @@ A modern, high-performance real-time chat application, designed for seamless com
|
|||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## 🛠️ 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/)
|
||||
- **Database & ORM:** [PostgreSQL](https://www.postgresql.org/) managed via [Drizzle ORM](https://orm.drizzle.team/) & Drizzle Kit (Studio included)
|
||||
- **Authentication:** [Auth.js v5 (NextAuth)](https://authjs.dev/) with Credentials Provider & bcrypt hashing _(planned)_
|
||||
- **Database & ORM:** [PostgreSQL](https://www.postgresql.org/) managed via [Drizzle ORM](https://orm.drizzle.team/) & Drizzle Kit _(planned)_
|
||||
- **DevOps & Infrastructure:** Docker & Docker Compose, Caddy Reverse Proxy, Forgejo Actions _(planned)_
|
||||
|
||||
## 📂 Architecture & Structure
|
||||
|
||||
The project uses Next.js Route Groups without a `src/` directory to maintain a clean root layout:
|
||||
|
||||
- `app/(app)/` — Application routes (Layout, Home)
|
||||
- `app/(app)/` — Application routes (Layout, Home, Components)
|
||||
- `components/` — Modular UI components (Chat, Navigation, Sidebars)
|
||||
- `db/` — Database schema definitions, migrations, and Drizzle configuration (`drizzle.config.ts`)
|
||||
- `lib/` — Centralized core logic folder containing:
|
||||
- `store/` — State management stores
|
||||
- `public/` — Static assets (images, icons, fonts)
|
||||
|
||||
## 🎯 Current Status
|
||||
|
||||
_In Progress_ — Application scaffold initialized with Next.js 16, React 19, Tailwind CSS v4, and TypeScript. Database integration, authentication, and DevOps infrastructure will be implemented in subsequent phases.
|
||||
_In Progress_ — Application scaffold initialized with Next.js 16, React 19, Tailwind CSS v4, and TypeScript. Database layer fully set up with PostgreSQL and Drizzle ORM schemas. Authentication and DevOps infrastructure will be implemented in subsequent phases.
|
||||
|
|
|
|||
24
db/index.ts
Normal file
24
db/index.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @file db/index.ts
|
||||
* @description Database connection initialization module using Drizzle ORM and Postgres.js client.
|
||||
*/
|
||||
|
||||
import { drizzle } from "drizzle-orm/postgres-js";
|
||||
import postgres from "postgres";
|
||||
import * as schema from "./schema";
|
||||
|
||||
const connectionString = process.env.DATABASE_URL;
|
||||
|
||||
if (!connectionString) {
|
||||
throw new Error("DATABASE_URL variable environment is missing.");
|
||||
}
|
||||
|
||||
/**
|
||||
* PostgreSQL client instance initialized with the environment database connection string.
|
||||
*/
|
||||
const client = postgres(connectionString);
|
||||
|
||||
/**
|
||||
* Drizzle ORM database instance configured with the schema definition and PostgreSQL client.
|
||||
*/
|
||||
export const db = drizzle(client, { schema });
|
||||
162
db/schema.ts
Normal file
162
db/schema.ts
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* @file db/schema.ts
|
||||
* @description Database schema definition file utilizing Drizzle ORM for PostgreSQL. Defines tables, enums, relations, and exported TypeScript types for users, servers, members, channels, and messages.
|
||||
*/
|
||||
|
||||
import { relations } from "drizzle-orm";
|
||||
import {
|
||||
pgEnum,
|
||||
pgTable,
|
||||
text,
|
||||
timestamp,
|
||||
uuid,
|
||||
varchar,
|
||||
} from "drizzle-orm/pg-core";
|
||||
|
||||
// ==========================================
|
||||
// Enums
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Enum representing member access roles within a server.
|
||||
*/
|
||||
export const roleEnum = pgEnum("role", ["OWNER", "ADMIN", "MEMBER"]);
|
||||
|
||||
// ==========================================
|
||||
// Tables
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Database table definition for application users.
|
||||
*/
|
||||
export const users = pgTable("users", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
username: text("username").notNull(),
|
||||
email: varchar("email", { length: 255 }).notNull().unique(),
|
||||
password: text("password").notNull(),
|
||||
color: varchar("color", { length: 50 }).default("bg-indigo-500").notNull(),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Database table definition for chat servers.
|
||||
*/
|
||||
export const servers = pgTable("servers", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
name: text("name").notNull(),
|
||||
color: varchar("color", { length: 50 }).default("bg-indigo-500").notNull(),
|
||||
inviteCode: text("invite_code").notNull().unique(),
|
||||
ownerId: uuid("owner_id")
|
||||
.references(() => users.id, { onDelete: "cascade" })
|
||||
.notNull(),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Database table definition linking users to servers with specific roles.
|
||||
*/
|
||||
export const members = pgTable("members", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
role: roleEnum("role").default("MEMBER").notNull(),
|
||||
userId: uuid("user_id")
|
||||
.references(() => users.id, { onDelete: "cascade" })
|
||||
.notNull(),
|
||||
serverId: uuid("server_id")
|
||||
.references(() => servers.id, { onDelete: "cascade" })
|
||||
.notNull(),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Database table definition for text channels within servers.
|
||||
*/
|
||||
export const channels = pgTable("channels", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
name: text("name").notNull(),
|
||||
serverId: uuid("server_id")
|
||||
.references(() => servers.id, { onDelete: "cascade" })
|
||||
.notNull(),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Database table definition for chat messages sent within channels by members.
|
||||
*/
|
||||
export const messages = pgTable("messages", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
content: text("content").notNull(),
|
||||
channelId: uuid("channel_id")
|
||||
.references(() => channels.id, { onDelete: "cascade" })
|
||||
.notNull(),
|
||||
memberId: uuid("member_id")
|
||||
.references(() => members.id, { onDelete: "cascade" })
|
||||
.notNull(),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
// ==========================================
|
||||
// Drizzle Relations
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Relational definitions for the users table.
|
||||
*/
|
||||
export const usersRelations = relations(users, ({ many }) => ({
|
||||
memberships: many(members),
|
||||
}));
|
||||
|
||||
/**
|
||||
* Relational definitions for the servers table.
|
||||
*/
|
||||
export const serversRelations = relations(servers, ({ many }) => ({
|
||||
channels: many(channels),
|
||||
members: many(members),
|
||||
}));
|
||||
|
||||
/**
|
||||
* Relational definitions for the members table.
|
||||
*/
|
||||
export const membersRelations = relations(members, ({ one, many }) => ({
|
||||
user: one(users, { fields: [members.userId], references: [users.id] }),
|
||||
server: one(servers, {
|
||||
fields: [members.serverId],
|
||||
references: [servers.id],
|
||||
}),
|
||||
messages: many(messages),
|
||||
}));
|
||||
|
||||
/**
|
||||
* Relational definitions for the channels table.
|
||||
*/
|
||||
export const channelsRelations = relations(channels, ({ one, many }) => ({
|
||||
server: one(servers, {
|
||||
fields: [channels.serverId],
|
||||
references: [servers.id],
|
||||
}),
|
||||
messages: many(messages),
|
||||
}));
|
||||
|
||||
/**
|
||||
* Relational definitions for the messages table.
|
||||
*/
|
||||
export const messagesRelations = relations(messages, ({ one }) => ({
|
||||
channel: one(channels, {
|
||||
fields: [messages.channelId],
|
||||
references: [channels.id],
|
||||
}),
|
||||
member: one(members, {
|
||||
fields: [messages.memberId],
|
||||
references: [members.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
// ==========================================
|
||||
// Type Exports
|
||||
// ==========================================
|
||||
|
||||
export type User = typeof users.$inferSelect;
|
||||
export type Server = typeof servers.$inferSelect;
|
||||
export type Member = typeof members.$inferSelect;
|
||||
export type Channel = typeof channels.$inferSelect;
|
||||
export type Message = typeof messages.$inferSelect;
|
||||
18
drizzle.config.ts
Normal file
18
drizzle.config.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* @file drizzle.config.ts
|
||||
* @description Drizzle Kit configuration file for managing database migrations, schema paths, and database credentials.
|
||||
*/
|
||||
|
||||
import { defineConfig } from "drizzle-kit";
|
||||
|
||||
/**
|
||||
* Configuration object exported for Drizzle Kit CLI commands.
|
||||
*/
|
||||
export default defineConfig({
|
||||
schema: "./db/schema.ts",
|
||||
out: "./db/migrations",
|
||||
dialect: "postgresql",
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL!,
|
||||
},
|
||||
});
|
||||
1747
package-lock.json
generated
1747
package-lock.json
generated
File diff suppressed because it is too large
Load diff
11
package.json
11
package.json
|
|
@ -6,12 +6,19 @@
|
|||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint"
|
||||
"lint": "next lint",
|
||||
"db:generate": "drizzle-kit generate",
|
||||
"db:migrate": "drizzle-kit migrate",
|
||||
"db:push": "drizzle-kit push",
|
||||
"db:studio": "drizzle-kit studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"clsx": "^2.1.1",
|
||||
"dotenv": "^17.4.2",
|
||||
"drizzle-orm": "^0.45.2",
|
||||
"lucide-react": "^1.35.0",
|
||||
"next": "16.3.3",
|
||||
"postgres": "^3.4.9",
|
||||
"react": "^19.2.8",
|
||||
"react-dom": "^19.2.8",
|
||||
"zustand": "^5.0.15"
|
||||
|
|
@ -19,8 +26,10 @@
|
|||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.3.3",
|
||||
"@types/node": "^20",
|
||||
"@types/pg": "^8.23.1",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"drizzle-kit": "^0.31.10",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "16.3.3",
|
||||
"tailwindcss": "^4.3.3",
|
||||
|
|
|
|||
Loading…
Reference in a new issue