fix(worker): S2 proactive tips logic, i18n parity, hardened test DB reset

- processProactiveTips now iterates all expiring items sorted by urgency and
  emits the first candidate with a recipe that clears 7-day dedup.
- Add pt-PT proactive-tip templates; remove en-GB duplicate; parity test
  asserts against shared-types SUPPORTED_LANGUAGE_TAGS.
- Serialize DB test setup via turbo dependencies; seed truncates only *_test
  DBs, guarded by both --test flag and DB name suffix.
This commit is contained in:
Sven (AAMOS AI)
2026-08-10 04:35:22 +07:00
parent 1de1c68485
commit 881c5bb1e3
9 changed files with 163 additions and 125 deletions
+1 -1
View File
@@ -12,7 +12,7 @@
},
"scripts": {
"typecheck": "tsc --noEmit",
"test": "pnpm run db:test-setup && vitest run --passWithNoTests",
"test": "vitest run --passWithNoTests",
"db:generate": "drizzle-kit generate",
"db:migrate": "tsx src/migrate.ts",
"db:seed": "tsx src/seed/run.ts",
+27
View File
@@ -40,6 +40,16 @@ if (!connectionString) {
throw new Error("Sätt DATABASE_URL innan seed körs.");
}
function assertTestDatabaseName(url: string): void {
const parsed = new URL(url);
const dbName = parsed.pathname.replace(/^\//, "");
if (!/_test$/.test(dbName)) {
throw new Error(
`[seed] Vägrar nollställa databas "${dbName}". Truncation kräver att databasnamnet slutar på _test.`,
);
}
}
/**
* Näring, allergener och kostnad för recepten beräknas HÄR, deterministiskt,
* ur ingredienserna (spec §61.12) aldrig hårdkodade och aldrig från AI.
@@ -48,6 +58,23 @@ async function main() {
const { db, pool } = createDatabase(connectionString);
console.log("[seed] Startar …");
// Testläge: nollställ allt användardata så att upprepade körningar blir deterministiska.
// Dubbelgrind: (a) --test / SEED_TARGET=test, OCH (b) URL:en pekar på en *_test-databas.
if (isTestTarget) {
assertTestDatabaseName(connectionString!);
console.log("[seed] Nollställer testdatabasen …");
const tables = await pool.query<{ tablename: string }>(
`SELECT tablename FROM pg_tables
WHERE schemaname = 'public'
AND tablename NOT LIKE 'pg_%'
AND tablename NOT LIKE 'drizzle_%'`,
);
for (const { tablename } of tables.rows) {
await pool.query(`TRUNCATE TABLE "${tablename}" CASCADE`);
}
console.log(`[seed] Nollställde ${tables.rows.length} tabeller.`);
}
// 1. Kanoniska ingredienser
for (const ing of SEED_INGREDIENTS) {
await db
+1 -1
View File
@@ -13,7 +13,7 @@
},
"scripts": {
"typecheck": "tsc --noEmit",
"test": "pnpm --filter=@app/database run db:test-setup && vitest run"
"test": "vitest run"
},
"dependencies": {
"@app/ai-contracts": "workspace:*",
+16
View File
@@ -31,6 +31,22 @@ export interface LocaleContext {
currencyCode: string;
}
/** Kanoniska UI-språk (BCP 47) som alla notismallar måste täcka. */
export const SUPPORTED_LANGUAGE_TAGS = [
"sv-SE",
"en-US",
"de-DE",
"fr-FR",
"es-ES",
"it-IT",
"pl-PL",
"nl-NL",
"fi-FI",
"da-DK",
"nb-NO",
"pt-PT",
] as const;
export const DEFAULT_LOCALE_PREFERENCES: UserLocalePreferences = {
languageTag: "sv-SE",
regionCode: "SE",