From 20aa71f71a4969c43d7e5335da855001164f30f5 Mon Sep 17 00:00:00 2001 From: R0m1k3 Date: Thu, 26 Feb 2026 15:57:37 +0100 Subject: [PATCH] feat: Implement database initialization script to create `ai_supplier_context` and `session_snapshots` tables on application startup. --- Dockerfile | 6 ++-- package.json | 4 +-- scripts/db-init.js | 78 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 scripts/db-init.js diff --git a/Dockerfile b/Dockerfile index 49f1089..9859f90 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,6 +49,8 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static # Grant write access to /app for settings persistence RUN chown -R nextjs:nodejs /app +COPY --from=builder --chown=nextjs:nodejs /app/scripts ./scripts + USER nextjs EXPOSE 5643 @@ -57,5 +59,5 @@ ENV PORT=5643 # set hostname to localhost ENV HOSTNAME="0.0.0.0" -# Run the standalone server -CMD ["node", "server.js"] +# Run the DB init script, then start the standalone server +CMD node scripts/db-init.js && node server.js diff --git a/package.json b/package.json index b896673..c617642 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "dev": "next dev", "build": "next build", - "start": "next start", + "start": "node scripts/db-init.js && next start", "lint": "eslint", "docker:up": "docker-compose up -d", "docker:down": "docker-compose down", @@ -46,4 +46,4 @@ "tw-animate-css": "^1.4.0", "typescript": "5.9.3" } -} +} \ No newline at end of file diff --git a/scripts/db-init.js b/scripts/db-init.js new file mode 100644 index 0000000..139f4e7 --- /dev/null +++ b/scripts/db-init.js @@ -0,0 +1,78 @@ +import { migrate } from "drizzle-orm/node-postgres/migrator"; +import { drizzle } from "drizzle-orm/node-postgres"; +import { Pool } from "pg"; +import * as schema from "../src/db/schema"; +import fs from "fs"; +import path from "path"; + +async function main() { + console.log("[DB Init] Starting database migration & initialization..."); + let connectionString = process.env.DATABASE_URL; + + try { + const CONFIG_PATH = path.join(process.cwd(), "data", ".db-config.json"); + if (fs.existsSync(CONFIG_PATH)) { + const config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8")); + if (config.url) { + connectionString = config.url; + console.log("[DB Init] Found connection string in data/.db-config.json"); + } + } + } catch (e) { + console.error("[DB Init] Error reading .db-config.json", e); + } + + if (!connectionString) { + console.warn("[DB Init] No DATABASE_URL found in env or config. Skipping push."); + process.exit(0); + } + + try { + const tempPool = new Pool({ connectionString, max: 1 }); + const tempDb = drizzle(tempPool, { schema }); + + console.log("[DB Init] Connection established. Running migrations..."); + + // Note: For Drizzle without pre-generated SQL migrations (using drizzle-kit push in dev), + // running migrations programmatically requires the generated sql files. + // Since we want to auto-create tables without requiring dev dependencies in production, + // we will create the specific missing table `ai_supplier_context` directly if it doesn't exist to ensure the app works. + // A full robust migration system would use `npx drizzle-kit push` but that is not available in the standalone build easily. + + await tempPool.query(` + CREATE TABLE IF NOT EXISTS "ai_supplier_context" ( + "code_fournisseur" varchar(20) PRIMARY KEY NOT NULL, + "context" text NOT NULL, + "updated_at" timestamp DEFAULT now() + ); + `); + console.log("[DB Init] Table ai_supplier_context is verified/created."); + + + await tempPool.query(` + CREATE TABLE IF NOT EXISTS "session_snapshots" ( + "id" serial PRIMARY KEY NOT NULL, + "user_id" integer, + "code_fournisseur" varchar(20) NOT NULL, + "nom_fournisseur" varchar(255), + "magasin" varchar(20) NOT NULL, + "changes" jsonb NOT NULL, + "summary_json" jsonb, + "label" text, + "type" varchar(20) DEFAULT 'snapshot', + "created_at" timestamp DEFAULT now() + ); + `); + console.log("[DB Init] Table session_snapshots is verified/created."); + + await tempPool.end(); + console.log("[DB Init] Initialization successful. Exiting."); + process.exit(0); + } catch (error) { + console.error("[DB Init] Initialization failed:", error); + // Do not crash the app, just let it run (it uses fallback JSON anyway) + process.exit(0); + } +} + +main();