diff --git a/.gitignore b/.gitignore index 92a67e4..71bcace 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .env node_modules/ .direnv/ -.pre-commit-config.yaml \ No newline at end of file +.pre-commit-config.yaml +data/ +src/database/db.sqlite3 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 6bf691e..5f2e887 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,6 +32,10 @@ COPY --from=builder /app/tsconfig.json ./ # Set environment variables ENV NODE_ENV=production ENV LOG_LEVEL=info +ENV DATABASE_PATH=/data/db.sqlite3 + +# Persist runtime data (SQLite) +VOLUME ["/data"] # Run the bot CMD ["bun", "run", "src/index.ts"] diff --git a/README.md b/README.md index 522652f..9fe7bce 100644 --- a/README.md +++ b/README.md @@ -47,10 +47,31 @@ src/ | `ELEVENLABS_API_KEY` | ElevenLabs API key for voiceover | | `ELEVENLABS_VOICE_ID` | Default ElevenLabs voice ID (optional) | | `ELEVENLABS_MODEL` | ElevenLabs model ID (default: `eleven_multilingual_v2`) | +| `DATABASE_PATH` | SQLite file path (default: `./data/db.sqlite3`) | | `WEB_PORT` | Port for web dashboard (default: 3000) | | `WEB_BASE_URL` | Base URL for web dashboard | | `SESSION_SECRET` | Secret for session encryption | +## Data Persistence + +- Bot options and other runtime state are stored in SQLite. +- Keep `DATABASE_PATH` on persistent storage so updates/redeploys do not reset settings. +- Backward compatibility: if `DATABASE_PATH` is unset and `src/database/db.sqlite3` exists, it is used automatically. +- Recommended one-time migration: + +```bash +mkdir -p data && cp src/database/db.sqlite3 data/db.sqlite3 +``` +- Docker example: + +```bash +docker run -d \ + --name joel-discord \ + -v joel_data:/data \ + --env-file .env \ + your-image:latest +``` + ## Scripts | Script | Description | diff --git a/drizzle.config.ts b/drizzle.config.ts index fc29e0d..9926057 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -5,7 +5,7 @@ export default { out: "./src/database/drizzle", dialect: "turso", dbCredentials: { - url: "./src/database/db.sqlite3", + url: process.env.DATABASE_PATH ?? "./data/db.sqlite3", }, verbose: true, strict: true, diff --git a/src/database/connection.ts b/src/database/connection.ts index 09cfb62..1419eed 100644 --- a/src/database/connection.ts +++ b/src/database/connection.ts @@ -4,9 +4,22 @@ import { drizzle } from "drizzle-orm/bun-sqlite"; import { Database } from "bun:sqlite"; +import { dirname } from "node:path"; +import { existsSync, mkdirSync } from "node:fs"; import * as schema from "./schema"; -const DATABASE_PATH = `${import.meta.dir}/db.sqlite3`; +const DEFAULT_DATABASE_PATH = "./data/db.sqlite3"; +const LEGACY_DATABASE_PATH = `${import.meta.dir}/db.sqlite3`; + +const DATABASE_PATH = + Bun.env.DATABASE_PATH ?? + (existsSync(DEFAULT_DATABASE_PATH) + ? DEFAULT_DATABASE_PATH + : existsSync(LEGACY_DATABASE_PATH) + ? LEGACY_DATABASE_PATH + : DEFAULT_DATABASE_PATH); + +mkdirSync(dirname(DATABASE_PATH), { recursive: true }); const sqlite = new Database(DATABASE_PATH); diff --git a/src/database/db.sqlite3 b/src/database/db.sqlite3 deleted file mode 100644 index 6c15ade..0000000 Binary files a/src/database/db.sqlite3 and /dev/null differ