diff --git a/apps/worker/src/context.ts b/apps/worker/src/context.ts index ca595e7..5cc163f 100644 --- a/apps/worker/src/context.ts +++ b/apps/worker/src/context.ts @@ -24,7 +24,11 @@ export interface WorkerContext { } export function createContext(): WorkerContext { - const { db, pool } = createDatabase(); + const databaseUrl = process.env.DATABASE_URL; + if (!databaseUrl) { + throw new Error("Missing DATABASE_URL. Worker must connect explicitly to the app database."); + } + const { db, pool } = createDatabase(databaseUrl); const aamos = createAamosClient(); const apiBaseUrl = process.env.API_BASE_URL ?? "http://localhost:4000"; const secret = process.env.ENTITLEMENT_SIGNING_SECRET ?? "dev-only-change-me-three"; diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 87a7e89..1b9666d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -17,7 +17,20 @@ använder `DATABASE_URL`. - Dedikerad testdatabas `cibello_test` skapad; `TEST_DATABASE_URL` lagd i `.env` och `.env.example`. `packages/database` test-skript migrerar - automatiskt testdatabasen före varje körning. + automatiskt testdatabasen före varje körning (`tsx src/migrate.ts --test`). +- **Buggrättning (kritisk):** `createDatabase()` var lägesberoende men + föredrog ändå `TEST_DATABASE_URL` före `DATABASE_URL`. Åtgärdat så att + runtime **endast** ser `DATABASE_URL` och tester **endast** ser + `TEST_DATABASE_URL`. +- `apps/worker/src/context.ts`: skickar nu `DATABASE_URL` explicit till + `createDatabase()`, samma mönster som API:et. +- `packages/database/src/migrate.ts` och `src/seed/run.ts`: stöd för + `--test` / `MIGRATE_TARGET=test` / `SEED_TARGET=test`. Utan flagga + används endast `DATABASE_URL` – deploy kan aldrig migrera/seed test-DB. +- Driftsreparation: staging migrerad explicit, worker omstartad med ny + build, expiry-notis skapad i staging-databasens `notifications`-tabell. + Kontroll av `cibello_test` visade 0 worker-skrivna rader i + `notifications` / `domain_events` / `inventory_items` / `households`. - Bevis: radantal i staging-databasen före/efter full `pnpm test` är identiska (users=6, households=0, household_members=0, product_analytics_events=0, user_consents=3). diff --git a/packages/database/package.json b/packages/database/package.json index d46c106..a6718c5 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -11,7 +11,7 @@ }, "scripts": { "typecheck": "tsc --noEmit", - "test": "tsx src/migrate.ts && vitest run --passWithNoTests", + "test": "tsx src/migrate.ts --test && vitest run --passWithNoTests", "db:generate": "drizzle-kit generate", "db:migrate": "tsx src/migrate.ts", "db:seed": "tsx src/seed/run.ts" diff --git a/packages/database/src/client.ts b/packages/database/src/client.ts index 6e22333..dcfb2d7 100644 --- a/packages/database/src/client.ts +++ b/packages/database/src/client.ts @@ -13,7 +13,7 @@ let sharedPool: pg.Pool | undefined; */ export function createDatabase(connectionString?: string) { const isTest = process.env.NODE_ENV === "test" || process.env.VITEST !== undefined; - const url = connectionString ?? process.env.TEST_DATABASE_URL ?? process.env.DATABASE_URL; + const url = connectionString ?? (isTest ? process.env.TEST_DATABASE_URL : process.env.DATABASE_URL); if (!url) { if (isTest) { @@ -24,12 +24,6 @@ export function createDatabase(connectionString?: string) { throw new Error("Missing DATABASE_URL. Set it in your .env or environment before starting the app."); } - if (isTest && !process.env.TEST_DATABASE_URL) { - throw new Error( - "Sätt TEST_DATABASE_URL till en dedikerad testdatabas. Tester får aldrig använda DATABASE_URL.", - ); - } - const pool = new pg.Pool({ connectionString: url, max: Number(process.env.DATABASE_POOL_MAX ?? 10), diff --git a/packages/database/src/migrate.ts b/packages/database/src/migrate.ts index 2bd7cbe..ea2d6f1 100644 --- a/packages/database/src/migrate.ts +++ b/packages/database/src/migrate.ts @@ -17,14 +17,27 @@ import { createDatabase } from "./client.js"; /** * Kör alla väntande SQL-migrationer från infrastructure/migrations. * Används i dev, CI och deploy (spec §63: migration + rollback + kontroll). + * + * `--test` eller `MIGRATE_TARGET=test` migrerar TEST_DATABASE_URL. + * Utan flagga används ENDAST DATABASE_URL – deploy kan aldrig röra testdatabasen. */ +const isTestTarget = process.argv.includes("--test") || process.env.MIGRATE_TARGET === "test"; +const connectionString = isTestTarget ? process.env.TEST_DATABASE_URL : process.env.DATABASE_URL; + +if (!connectionString) { + if (isTestTarget) { + throw new Error("Sätt TEST_DATABASE_URL för test-migrationer."); + } + throw new Error("Sätt DATABASE_URL innan migration körs."); +} + const migrationsFolder = path.resolve( path.dirname(fileURLToPath(import.meta.url)), "../../../infrastructure/migrations", ); async function main() { - const { db, pool } = createDatabase(); + const { db, pool } = createDatabase(connectionString); console.log(`[migrate] Kör migrationer från ${migrationsFolder}`); await migrate(db, { migrationsFolder }); diff --git a/packages/database/src/seed/run.ts b/packages/database/src/seed/run.ts index 0fa4817..8dc0ee7 100644 --- a/packages/database/src/seed/run.ts +++ b/packages/database/src/seed/run.ts @@ -27,11 +27,25 @@ import { SEED_SEASON_EVENTS } from "./data/seasonEvents.js"; /** * Seed-körning. Idempotent: onConflictDoNothing/Update där det är säkert. * + * `--test` eller `SEED_TARGET=test` kör mot TEST_DATABASE_URL. + * Utan flagga används ENDAST DATABASE_URL – deploy seedar aldrig testdatabasen. + */ +const isTestTarget = process.argv.includes("--test") || process.env.SEED_TARGET === "test"; +const connectionString = isTestTarget ? process.env.TEST_DATABASE_URL : process.env.DATABASE_URL; + +if (!connectionString) { + if (isTestTarget) { + throw new Error("Sätt TEST_DATABASE_URL för test-seed."); + } + throw new Error("Sätt DATABASE_URL innan seed körs."); +} + +/** * Näring, allergener och kostnad för recepten beräknas HÄR, deterministiskt, * ur ingredienserna (spec §61.1–2) – aldrig hårdkodade och aldrig från AI. */ async function main() { - const { db, pool } = createDatabase(); + const { db, pool } = createDatabase(connectionString); console.log("[seed] Startar …"); // 1. Kanoniska ingredienser