diff --git a/.env.local.example b/.env.local.example index ce21d76..cac8555 100644 --- a/.env.local.example +++ b/.env.local.example @@ -7,8 +7,8 @@ DISCORD_TOKEN=your_bot_token_here CLIENT_ID=your_client_id_here SERVER_ID=your_server_id_here -# Database Configuration (Optional - uncomment and add to config.ts when needed) -# DATABASE_URL=postgresql://user:password@localhost:5432/botdb +# Database Configuration (Required) +DATABASE_URL=file:../data/moderation.db # API Keys (Optional - uncomment and add to config.ts when needed) # FOO_API_KEY=sk-1234567890abcdef diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3d1015d..de225c1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -83,6 +83,7 @@ jobs: DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} CLIENT_ID=${{ secrets.CLIENT_ID }} SERVER_ID=${{ secrets.SERVER_ID }} + DATABASE_URL=file:../data/moderation.db EOF echo "🐳 Stopping existing containers..." diff --git a/Dockerfile b/Dockerfile index ed48a78..2c48a2e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,7 +45,6 @@ COPY --from=build /app/dist ./dist COPY --from=build /app/generated ./generated COPY --from=build /app/prisma ./prisma COPY package.json ./ -COPY prisma.config.ts ./ # Create data directory and set permissions for node user RUN mkdir -p /app/data && chown -R node:node /app/data @@ -53,7 +52,7 @@ RUN mkdir -p /app/data && chown -R node:node /app/data # Run as non-root user for security USER node -CMD ["node", "dist/index.js"] +CMD ["sh", "-c", "npx prisma migrate deploy && node dist/index.js"] # Development stage - Full dev environment with hot reload FROM deps-dev AS development @@ -71,4 +70,4 @@ RUN mkdir -p /app/data && chown -R node:node /app/data # Run as non-root user for security USER node -CMD ["pnpm", "run", "dev"] \ No newline at end of file +CMD ["sh", "-c", "npx prisma migrate deploy && pnpm run dev"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index f55bf56..8979122 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,6 +13,7 @@ services: - .env.local environment: - NODE_ENV=production + - DATABASE_URL=file:../data/moderation.db volumes: - prod_logs:/app/logs - prod_data:/app/data # Named volume - persists outside repo @@ -29,6 +30,7 @@ services: - .env.local environment: - NODE_ENV=development + - DATABASE_URL=file:../data/moderation.db volumes: - .:/app - ./logs:/app/logs @@ -46,6 +48,8 @@ services: profiles: ["tools"] env_file: - .env.local + environment: + - DATABASE_URL=file:../data/moderation.db volumes: - prod_data:/app/data # Use same named volume as production command: npx prisma migrate deploy diff --git a/package.json b/package.json index 9c7eea3..ecb9ac6 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,13 @@ "check:fix": "biome check --write .", "prepare": "husky", "pre-commit": "lint-staged", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + + "db:migrate": "npx prisma migrate deploy", + "db:migrate:dev": "npx prisma migrate dev", + "db:generate": "npx prisma generate", + "db:studio": "npx prisma studio", + "db:reset": "npx prisma migrate reset" }, "license": "MIT", "packageManager": "pnpm@10.17.1", diff --git a/prisma.config.ts b/prisma.config.ts index e33aad4..ec27cb5 100644 --- a/prisma.config.ts +++ b/prisma.config.ts @@ -1,4 +1,5 @@ import { defineConfig } from "prisma/config"; +import "./src/loadEnvFile.js"; export default defineConfig({ schema: "prisma/schema.prisma", @@ -7,6 +8,6 @@ export default defineConfig({ }, engine: "classic", datasource: { - url: "file:../data/moderation.db", // Match schema.prisma + url: process.env.DATABASE_URL!, }, }); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 0c4d34e..d288343 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -2,13 +2,13 @@ // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" output = "../generated/prisma" } datasource db { provider = "sqlite" - url = "file:../data/moderation.db" + url = env("DATABASE_URL") } enum Role { @@ -54,13 +54,13 @@ enum ActionReason { } model User { - userId Int @id @default(autoincrement()) - discordUserId String @unique - role Role @default(MEMBER) + userId Int @id @default(autoincrement()) + discordUserId String @unique + role Role @default(MEMBER) // A user can have many actions performed on them - actions Action[] @relation("UserActions") - + actions Action[] @relation("UserActions") + // A user (as moderator) can perform many moderation actions moderatedActions Action[] @relation("ModeratorActions") } @@ -78,14 +78,14 @@ model Action { revertingActionId Int? @unique // Relationship to the user this action was performed on - user User @relation("UserActions", fields: [userId], references: [userId]) - + user User @relation("UserActions", fields: [userId], references: [userId]) + // Relationship to the moderator who performed this action - moderator User @relation("ModeratorActions", fields: [moderatorUserId], references: [userId]) - + moderator User @relation("ModeratorActions", fields: [moderatorUserId], references: [userId]) + // Self-referential relationship: this action reverts another action - revertingAction Action? @relation("ActionCorrections", fields: [revertingActionId], references: [actionId]) - + revertingAction Action? @relation("ActionCorrections", fields: [revertingActionId], references: [actionId]) + // Self-referential relationship: actions that revert this action - revertedByActions Action[] @relation("ActionCorrections") -} \ No newline at end of file + revertedByActions Action[] @relation("ActionCorrections") +} diff --git a/src/env.ts b/src/env.ts index e3f4db6..9ef6f8a 100644 --- a/src/env.ts +++ b/src/env.ts @@ -17,10 +17,10 @@ export const config = { clientId: requireEnv("CLIENT_ID"), serverId: requireEnv("SERVER_ID"), }, + database: { + url: requireEnv("DATABASE_URL"), + }, // Add more config sections as needed: - // database: { - // url: requireEnv('DATABASE_URL'), - // }, // api: { // openaiKey: optionalEnv('OPENAI_API_KEY'), // }, @@ -33,3 +33,4 @@ console.log("✅ Configuration loaded successfully"); console.log(`📋 Client ID: ${config.discord.clientId ? config.discord.clientId : "❌ missing"}`); console.log(`🔑 Token: ${config.discord.token ? "***configured***" : "❌ missing"}`); console.log(`🔑 Guild ID: ${config.discord.serverId ? config.discord.serverId : "Global"}`); +console.log(`🗄️ Database: ${config.database.url ? "***configured***" : "❌ missing"}`);