fix(api,web): env startup validation, QueryClient defaults, warn on missing REDIS_URL

- Throw at startup in production if REDIS_URL/DATABASE_URL/NEXTAUTH_SECRET missing
- Warn in development when REDIS_URL falls back to localhost
- QueryClient: add gcTime, disable refetchOnWindowFocus, skip retry on 4xx

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-09 16:42:34 +02:00
parent 3c0179fcec
commit 485e220c49
6 changed files with 40 additions and 3 deletions
+1
View File
@@ -13,3 +13,4 @@ export { lookupRate, type RateCardLookupParams, type RateCardLookupResult } from
export { autoImportPublicHolidays, type AutoImportResult } from "./lib/holiday-auto-import.js";
export { createAuditEntry, computeDiff, generateSummary } from "./lib/audit.js";
export { loggedAiCall } from "./ai-client.js";
export { assertProductionEnv } from "./lib/env.js";
+5 -1
View File
@@ -1,7 +1,11 @@
import { Redis } from "ioredis";
import { logger } from "./logger.js";
const REDIS_URL = process.env["REDIS_URL"] ?? "redis://localhost:6380";
const REDIS_URL = process.env["REDIS_URL"] ?? (
process.env["NODE_ENV"] !== "production"
? (console.warn("[env] REDIS_URL not set, using localhost fallback"), "redis://localhost:6380")
: (() => { throw new Error("REDIS_URL required in production"); })()
);
const KEY_PREFIX = "dashboard:";
const DEFAULT_TTL_SECONDS = 60;
+15
View File
@@ -0,0 +1,15 @@
/**
* Startup environment validation.
* Call assertProductionEnv() early in the server lifecycle to surface missing
* critical configuration before any requests are served.
*/
export function assertProductionEnv(): void {
if (process.env["NODE_ENV"] !== "production") return;
const required = ["REDIS_URL", "DATABASE_URL", "NEXTAUTH_SECRET"] as const;
const missing = required.filter((k) => !process.env[k]);
if (missing.length > 0) {
throw new Error(`Missing required env vars: ${missing.join(", ")}`);
}
}
+5 -1
View File
@@ -180,7 +180,11 @@ export function cancelPendingEvents(): void {
}
// Redis connection — use env var REDIS_URL or fallback to default dev URL
const REDIS_URL = process.env["REDIS_URL"] ?? "redis://localhost:6380";
const REDIS_URL = process.env["REDIS_URL"] ?? (
process.env["NODE_ENV"] !== "production"
? (console.warn("[env] REDIS_URL not set, using localhost fallback"), "redis://localhost:6380")
: (() => { throw new Error("REDIS_URL required in production"); })()
);
const CHANNEL = "capakraken:sse";
let publisher: Redis | null = null;