import 'dotenv/config'; import { pool } from '../src/lib/server/db/client'; import { runRemindersOnce, type RunResult } from '../src/lib/server/services/maintenance-reminders'; function stripSurroundingQuotes(s: string | undefined): string | undefined { if (!s || s.length < 2) return s; const first = s[0]; const last = s[s.length - 1]; if ((first === "'" && last === "'") || (first === '"' && last === '"')) { return s.slice(1, -1); } return s; } function readArg(flag: string, fallback?: string): string | undefined { const i = process.argv.indexOf(flag); return stripSurroundingQuotes(i >= 0 ? process.argv[i + 1] : fallback); } function hasFlag(flag: string): boolean { return process.argv.includes(flag); } async function main(): Promise { const soonRaw = readArg('--soon-days', '7') ?? '7'; const soonDays = Number.parseInt(soonRaw, 10); if (!Number.isFinite(soonDays) || soonDays < 0 || soonDays > 365) { console.error('--soon-days must be an integer in [0, 365]'); process.exit(2); } const companyId = readArg('--company'); const dryRun = hasFlag('--dry-run'); const backfill = hasFlag('--backfill'); if (dryRun && backfill) { console.error('--dry-run and --backfill are mutually exclusive'); process.exit(2); } const startedAt = new Date(); let result: RunResult; try { result = await runRemindersOnce({ companyId, soonDays, dryRun, backfill }); } catch (e) { console.error(JSON.stringify({ ok: false, error: (e as Error).message })); process.exit(1); } const out = { ok: true, startedAt: startedAt.toISOString(), durationMs: Date.now() - startedAt.getTime(), soonDays, companyId: companyId ?? null, ...result }; // Single-line JSON so journald/grep handle it cleanly. console.log(JSON.stringify(out)); } main() .catch((e) => { console.error(JSON.stringify({ ok: false, error: (e as Error).message })); process.exitCode = 1; }) .finally(async () => { await pool.end().catch(() => {}); });