@cronwatch/sdk 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +32 -12
- package/dist/anthropic.cjs +19 -5
- package/dist/anthropic.cjs.map +1 -1
- package/dist/anthropic.d.cts +1 -1
- package/dist/anthropic.d.ts +1 -1
- package/dist/anthropic.js +19 -5
- package/dist/anthropic.js.map +1 -1
- package/dist/discord.cjs +14 -2
- package/dist/discord.cjs.map +1 -1
- package/dist/discord.d.cts +6 -2
- package/dist/discord.d.ts +6 -2
- package/dist/discord.js +13 -3
- package/dist/discord.js.map +1 -1
- package/dist/index.cjs +676 -285
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +100 -44
- package/dist/index.d.ts +100 -44
- package/dist/index.js +677 -283
- package/dist/index.js.map +1 -1
- package/dist/postgres.cjs +140 -73
- package/dist/postgres.cjs.map +1 -1
- package/dist/postgres.d.cts +2 -2
- package/dist/postgres.d.ts +2 -2
- package/dist/postgres.js +140 -73
- package/dist/postgres.js.map +1 -1
- package/dist/slack.cjs +12 -6
- package/dist/slack.cjs.map +1 -1
- package/dist/slack.d.cts +1 -1
- package/dist/slack.d.ts +1 -1
- package/dist/slack.js +12 -6
- package/dist/slack.js.map +1 -1
- package/dist/sqlite.cjs +142 -71
- package/dist/sqlite.cjs.map +1 -1
- package/dist/sqlite.d.cts +3 -1
- package/dist/sqlite.d.ts +3 -1
- package/dist/sqlite.js +143 -72
- package/dist/sqlite.js.map +1 -1
- package/dist/{types-BQ1P8z55.d.cts → types-C1PyRjI5.d.cts} +63 -5
- package/dist/{types-BQ1P8z55.d.ts → types-C1PyRjI5.d.ts} +63 -5
- package/dist/webhook.cjs +10 -2
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +1 -1
- package/dist/webhook.d.ts +1 -1
- package/dist/webhook.js +10 -2
- package/dist/webhook.js.map +1 -1
- package/package.json +95 -32
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/duration.ts","../src/schedule.ts","../src/stats.ts","../src/evaluate.ts","../src/format.ts","../src/http.ts","../src/output.ts","../src/job.ts","../src/serialize.ts","../src/routes/html.ts","../src/routes/index.ts","../src/stores/memory.ts","../src/client.ts","../src/index.ts"],"names":["Cron","graceMs","constantTimeEqual"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Duration } from \"./types.js\";\n\nconst UNIT_MS: Record<string, number> = {\n ms: 1,\n s: 1000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n};\n\n/**\n * \"15m\" -> 900000. Accepts a plain number of milliseconds, and compound\n * strings such as \"1h30m\". Whitespace between parts is fine.\n */\nexport function parseDuration(value: Duration, label = \"duration\"): number {\n if (typeof value === \"number\") {\n if (!Number.isFinite(value) || value < 0) throw new Error(`${label} must be a non-negative number of milliseconds`);\n return value;\n }\n const text = value.trim().toLowerCase();\n if (text === \"\") throw new Error(`${label} is empty`);\n const re = /(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h|d|w)/g;\n let total = 0;\n let consumed = \"\";\n let match: RegExpExecArray | null;\n while ((match = re.exec(text)) !== null) {\n total += parseFloat(match[1]!) * UNIT_MS[match[2]!]!;\n consumed += match[0];\n }\n if (consumed.replace(/\\s+/g, \"\") !== text.replace(/\\s+/g, \"\")) {\n throw new Error(`${label} \"${value}\" is not a duration like \"15m\", \"1h30m\" or \"90s\"`);\n }\n return Math.round(total);\n}\n\n/** 90000 -> \"1m 30s\". For messages, not for parsing back. */\nexport function formatDuration(ms: number): string {\n if (!Number.isFinite(ms)) return \"?\";\n if (ms < 1000) return `${Math.round(ms)}ms`;\n const parts: string[] = [];\n let rest = Math.round(ms / 1000);\n const units: [string, number][] = [[\"d\", 86_400], [\"h\", 3_600], [\"m\", 60], [\"s\", 1]];\n for (const [unit, size] of units) {\n if (rest >= size) {\n const n = Math.floor(rest / size);\n rest -= n * size;\n parts.push(`${n}${unit}`);\n }\n if (parts.length === 2) break;\n }\n return parts.join(\" \") || \"0s\";\n}\n\n/** \"5 minutes ago\", \"in 2h\". Relative to `now`. */\nexport function formatRelative(at: number, now: number): string {\n const diff = at - now;\n const abs = Math.abs(diff);\n const text = abs < 5_000 ? \"now\" : formatDuration(abs);\n if (abs < 5_000) return text;\n return diff < 0 ? `${text} ago` : `in ${text}`;\n}\n","import { Cron } from \"croner\";\nimport { parseDuration } from \"./duration.js\";\n\nexport interface ParsedSchedule {\n kind: \"cron\" | \"interval\";\n source: string;\n /** For intervals, the period in milliseconds. */\n everyMs?: number;\n cron?: Cron;\n}\n\nconst cache = new Map<string, ParsedSchedule>();\n\n/**\n * \"0 2 * * *\" (cron, five or six fields), \"@hourly\", or \"every 5m\".\n * Parsed once per (schedule, timezone) pair and cached. The croner instance\n * gets no callback, so it schedules nothing; it is only used to compute fire\n * times. Without a timezone the expression is read in the process timezone,\n * like crontab. Vercel and GitHub Actions run their crons in UTC, so pass\n * timezone: \"UTC\" for those.\n */\nexport function parseSchedule(schedule: string, timezone?: string): ParsedSchedule {\n const key = `${timezone ?? \"\"}|${schedule}`;\n const hit = cache.get(key);\n if (hit) return hit;\n\n const text = schedule.trim();\n const every = /^every\\s+(.+)$/i.exec(text);\n let parsed: ParsedSchedule;\n if (every) {\n const everyMs = parseDuration(every[1]!, \"schedule interval\");\n if (everyMs < 1000) throw new Error(`schedule \"${schedule}\" is shorter than one second`);\n parsed = { kind: \"interval\", source: text, everyMs };\n } else {\n let cron: Cron;\n try {\n cron = new Cron(text, timezone ? { timezone } : {});\n } catch (error) {\n throw new Error(`schedule \"${schedule}\" is not a cron expression or \"every <duration>\": ${(error as Error).message}`);\n }\n parsed = { kind: \"cron\", source: text, cron };\n }\n cache.set(key, parsed);\n return parsed;\n}\n\n/** The next time the cron fires strictly after `from`. */\nexport function nextFire(parsed: ParsedSchedule, from: number, lastRunAt: number | null): number | null {\n if (parsed.kind === \"interval\") {\n const base = lastRunAt ?? from;\n return base + parsed.everyMs!;\n }\n const next = parsed.cron!.nextRun(new Date(from));\n return next ? next.getTime() : null;\n}\n\n/**\n * The most recent time the cron fired at or before `now`, or null when the\n * expression never fires in the year before `now`.\n *\n * croner only looks forward, so this searches: widen a window behind `now`\n * until a fire time falls inside it, then bisect on the window's start for\n * the latest start whose next fire is still at or before `now`.\n */\nexport function previousFire(parsed: ParsedSchedule, now: number): number | null {\n if (parsed.kind !== \"cron\") throw new Error(\"previousFire is for cron schedules\");\n const cron = parsed.cron!;\n // nextRun(from) is strictly after `from`, so start one millisecond behind.\n const fireAtOrBefore = (from: number): number | null => {\n const next = cron.nextRun(new Date(from - 1));\n if (!next) return null;\n const t = next.getTime();\n return t <= now ? t : null;\n };\n\n const YEAR = 366 * 86_400_000;\n let step = 60_000;\n let lo: number | null = null;\n while (step <= YEAR) {\n if (fireAtOrBefore(now - step) !== null) {\n lo = now - step;\n break;\n }\n step *= 2;\n }\n if (lo === null) return null;\n\n // Invariant: fireAtOrBefore(lo) !== null. Find the largest start that still\n // has a fire at or before now; its fire is the previous one.\n let hi = now;\n while (hi - lo > 1) {\n const mid = Math.floor((lo + hi) / 2);\n if (fireAtOrBefore(mid) !== null) lo = mid;\n else hi = mid;\n }\n return fireAtOrBefore(lo);\n}\n\nexport interface Expectation {\n /** When the current period's run was due. */\n dueAt: number;\n /** Missed once now passes this. */\n deadline: number;\n}\n\n/**\n * What the schedule expects given the last run. Returns null when nothing is\n * due yet (a cron whose first fire since registration is still ahead, or an\n * interval that has not elapsed).\n */\nexport function expectation(\n parsed: ParsedSchedule,\n now: number,\n lastRunAt: number | null,\n registeredAt: number,\n graceMs: number,\n): Expectation | null {\n if (parsed.kind === \"interval\") {\n const dueAt = (lastRunAt ?? registeredAt) + parsed.everyMs!;\n return { dueAt, deadline: dueAt + graceMs };\n }\n const prev = previousFire(parsed, now);\n if (prev === null || prev < registeredAt) return null;\n return { dueAt: prev, deadline: prev + graceMs };\n}\n\n/**\n * Whether a run starting at `startedAt` covers the fire at `dueAt`. A minute of\n * slack before the tick absorbs schedulers that fire a touch early.\n */\nexport function runCovers(startedAt: number, dueAt: number): boolean {\n return startedAt >= dueAt - 60_000;\n}\n","export function percentile(values: number[], p: number): number | null {\n if (values.length === 0) return null;\n const sorted = [...values].sort((a, b) => a - b);\n const index = Math.min(sorted.length - 1, Math.max(0, Math.ceil((p / 100) * sorted.length) - 1));\n return sorted[index]!;\n}\n\nexport function median(values: number[]): number | null {\n if (values.length === 0) return null;\n const sorted = [...values].sort((a, b) => a - b);\n const mid = Math.floor(sorted.length / 2);\n return sorted.length % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;\n}\n","/**\n * Pure decisions about a job's health. Each function takes the current state\n * and returns the new state plus the alerts that should go out. Nothing here\n * touches a store or a network, which is what makes it testable.\n */\nimport { formatDuration } from \"./duration.js\";\nimport { parseDuration } from \"./duration.js\";\nimport { expectation, parseSchedule, runCovers } from \"./schedule.js\";\nimport { median, percentile } from \"./stats.js\";\nimport type { Condition, JobDefinition, JobState, Run, StoredJob, StoredJobDefinition } from \"./types.js\";\n\nexport interface AlertDraft {\n type: Condition | \"recovered\";\n run: Run | null;\n details: Record<string, unknown>;\n}\n\nexport interface Evaluation {\n state: JobState;\n alerts: AlertDraft[];\n}\n\nexport const DEFAULT_GRACE_MS = 10 * 60_000;\nexport const DEFAULT_TIMEOUT_MS = 60 * 60_000;\n/** Runs faster than this are never called slow, whatever the baseline says. */\nexport const SLOW_FLOOR_MS = 10_000;\n/** How many earlier runs a baseline needs before it is trusted. */\nexport const BASELINE_MIN_RUNS = 5;\nexport const BASELINE_WINDOW = 20;\n\nexport function emptyState(job: string): JobState {\n return { job, open: {}, consecutiveFailures: 0, silencedUntil: null, lastAlertAt: null };\n}\n\nfunction cloneState(state: JobState): JobState {\n return { ...state, open: { ...state.open } };\n}\n\nfunction openCondition(state: JobState, condition: Condition, now: number): boolean {\n if (state.open[condition] !== undefined) return false;\n state.open[condition] = now;\n return true;\n}\n\nfunction closeCondition(state: JobState, condition: Condition): boolean {\n if (state.open[condition] === undefined) return false;\n delete state.open[condition];\n return true;\n}\n\nexport function openConditions(state: JobState): Condition[] {\n return Object.keys(state.open) as Condition[];\n}\n\nexport function graceMs(def: Pick<JobDefinition, \"grace\">): number {\n return def.grace === undefined ? DEFAULT_GRACE_MS : parseDuration(def.grace, \"grace\");\n}\n\nexport function timeoutMs(def: Pick<JobDefinition, \"timeout\">): number {\n return def.timeout === undefined ? DEFAULT_TIMEOUT_MS : parseDuration(def.timeout, \"timeout\");\n}\n\n/** Slow threshold for a successful run, or null when there is nothing to compare against yet. */\nexport function slowThreshold(def: Pick<JobDefinition, \"maxDuration\">, history: Run[]): { thresholdMs: number; basis: string } | null {\n if (def.maxDuration !== undefined) {\n return { thresholdMs: parseDuration(def.maxDuration, \"maxDuration\"), basis: \"maxDuration\" };\n }\n const durations = history\n .filter((r) => r.status === \"ok\" && r.durationMs !== null)\n .slice(0, BASELINE_WINDOW)\n .map((r) => r.durationMs!);\n if (durations.length < BASELINE_MIN_RUNS) return null;\n const p95 = percentile(durations, 95)!;\n return { thresholdMs: Math.max(2 * p95, SLOW_FLOOR_MS), basis: `twice the p95 of the last ${durations.length} runs (${formatDuration(p95)})` };\n}\n\nexport interface BudgetBreach {\n metric: string;\n value: number;\n limit: number;\n basis: string;\n}\n\nexport function budgetBreaches(def: Pick<JobDefinition, \"budget\">, run: Run, history: Run[]): BudgetBreach[] {\n const breaches: BudgetBreach[] = [];\n for (const [metric, value] of Object.entries(run.metrics)) {\n const ceiling = def.budget?.[metric];\n if (ceiling !== undefined) {\n if (value > ceiling) breaches.push({ metric, value, limit: ceiling, basis: \"budget\" });\n continue;\n }\n const past = history\n .filter((r) => r.status === \"ok\" && typeof r.metrics[metric] === \"number\")\n .slice(0, BASELINE_WINDOW)\n .map((r) => r.metrics[metric]!);\n if (past.length < BASELINE_MIN_RUNS) continue;\n const usual = median(past)!;\n if (usual > 0 && value > 3 * usual) {\n breaches.push({ metric, value, limit: 3 * usual, basis: `three times the usual ${formatNumber(usual)}` });\n }\n }\n return breaches;\n}\n\nexport function formatNumber(n: number): string {\n if (Number.isInteger(n)) return n.toLocaleString(\"en-US\");\n return n.toLocaleString(\"en-US\", { maximumFractionDigits: 4 });\n}\n\n/**\n * Called when a run starts. Missed and stuck are about the absence of a run,\n * so a run starting closes them without an alert. Returns which conditions\n * were open beforehand, for the recovered message at the end.\n */\nexport function onRunStart(state: JobState): { state: JobState; openBefore: Condition[] } {\n const next = cloneState(state);\n const openBefore = openConditions(next);\n closeCondition(next, \"missed\");\n closeCondition(next, \"stuck\");\n return { state: next, openBefore };\n}\n\n/**\n * Called when a run finishes with status ok, failed or timeout. `history` is\n * the job's earlier runs, newest first, not including this one.\n */\nexport function onRunFinish(\n def: JobDefinition | StoredJobDefinition,\n run: Run,\n state: JobState,\n history: Run[],\n openBefore: Condition[],\n now: number,\n): Evaluation {\n const next = cloneState(state);\n const alerts: AlertDraft[] = [];\n\n if (run.status === \"ok\") {\n next.consecutiveFailures = 0;\n closeCondition(next, \"failed\");\n closeCondition(next, \"missed\");\n closeCondition(next, \"stuck\");\n\n const slow = slowThreshold(def, history);\n if (slow && run.durationMs !== null && run.durationMs > slow.thresholdMs) {\n if (openCondition(next, \"slow\", now)) {\n alerts.push({ type: \"slow\", run, details: { durationMs: run.durationMs, thresholdMs: slow.thresholdMs, basis: slow.basis } });\n }\n } else {\n closeCondition(next, \"slow\");\n }\n\n const breaches = budgetBreaches(def, run, history);\n if (breaches.length > 0) {\n if (openCondition(next, \"over_budget\", now)) {\n alerts.push({ type: \"over_budget\", run, details: { breaches } });\n }\n } else {\n closeCondition(next, \"over_budget\");\n }\n\n const wasOpen = new Set([...openBefore, ...openConditions(state)]);\n if (wasOpen.size > 0 && openConditions(next).length === 0) {\n alerts.push({ type: \"recovered\", run, details: { after: [...wasOpen] } });\n }\n return { state: next, alerts };\n }\n\n // failed or timeout\n next.consecutiveFailures += 1;\n closeCondition(next, \"missed\");\n const threshold = Math.max(1, def.failuresBeforeAlert ?? 1);\n const condition: Condition = run.status === \"timeout\" ? \"stuck\" : \"failed\";\n if (next.consecutiveFailures >= threshold) {\n if (openCondition(next, condition, now)) {\n alerts.push({ type: condition, run, details: { consecutiveFailures: next.consecutiveFailures, threshold } });\n }\n }\n return { state: next, alerts };\n}\n\n/**\n * Called by check(). Decides whether the schedule has been missed. `lastRun`\n * is the most recent run of any status.\n */\nexport function onCheck(\n def: StoredJobDefinition,\n stored: StoredJob,\n lastRun: Run | null,\n state: JobState,\n now: number,\n): Evaluation & { nextExpectedAt: number | null; dueAt: number | null } {\n const next = cloneState(state);\n const alerts: AlertDraft[] = [];\n if (!def.schedule) return { state: next, alerts, nextExpectedAt: null, dueAt: null };\n\n const parsed = parseSchedule(def.schedule, def.timezone);\n const grace = graceMs(def);\n const exp = expectation(parsed, now, lastRun?.startedAt ?? null, stored.createdAt, grace);\n\n let nextExpectedAt: number | null = null;\n if (parsed.kind === \"interval\") {\n nextExpectedAt = (lastRun?.startedAt ?? stored.createdAt) + parsed.everyMs!;\n } else {\n const upcoming = parsed.cron!.nextRun(new Date(now));\n nextExpectedAt = upcoming ? upcoming.getTime() : null;\n }\n\n if (!exp) return { state: next, alerts, nextExpectedAt, dueAt: null };\n\n // For a cron, a run at or after the fire covers it. For an interval the due\n // time is computed from the last run itself, so only the deadline matters.\n const covered = parsed.kind === \"cron\" && lastRun !== null && runCovers(lastRun.startedAt, exp.dueAt);\n if (covered) {\n closeCondition(next, \"missed\");\n } else if (now > exp.deadline) {\n if (openCondition(next, \"missed\", now)) {\n alerts.push({\n type: \"missed\",\n run: lastRun,\n details: { dueAt: exp.dueAt, deadline: exp.deadline, graceMs: grace, lastRunAt: lastRun?.startedAt ?? null },\n });\n }\n }\n return { state: next, alerts, nextExpectedAt, dueAt: exp.dueAt };\n}\n\n/** Whether a running run has gone on longer than the job's timeout. */\nexport function isStuck(def: Pick<JobDefinition, \"timeout\">, run: Run, now: number): boolean {\n return run.status === \"running\" && now - run.startedAt > timeoutMs(def);\n}\n\n/**\n * While a job is silenced nothing new is recorded as an incident: conditions\n * may close (so a job that recovered during the silence shows as healthy) but\n * none may open, so the first problem after the silence ends alerts normally.\n */\nexport function muteOpens(previous: JobState, next: JobState): JobState {\n const muted = cloneState(next);\n for (const condition of openConditions(muted)) {\n if (previous.open[condition] === undefined) delete muted.open[condition];\n }\n return muted;\n}\n\nexport function isSilenced(state: JobState, now: number): boolean {\n return state.silencedUntil !== null && state.silencedUntil > now;\n}\n","import { formatDuration, formatRelative } from \"./duration.js\";\nimport type { AlertDraft, BudgetBreach } from \"./evaluate.js\";\nimport { formatNumber } from \"./evaluate.js\";\nimport type { Alert, StoredJobDefinition } from \"./types.js\";\n\nfunction when(at: number | null | undefined, now: number): string {\n if (at === null || at === undefined) return \"never\";\n return `${new Date(at).toISOString().replace(\"T\", \" \").slice(0, 19)} UTC (${formatRelative(at, now)})`;\n}\n\nfunction firstLines(text: string | null, n: number): string {\n if (!text) return \"\";\n return text.split(\"\\n\").slice(0, n).join(\"\\n\");\n}\n\nfunction tail(text: string | null, n: number): string {\n if (!text) return \"\";\n const lines = text.trimEnd().split(\"\\n\");\n return lines.slice(Math.max(0, lines.length - n)).join(\"\\n\");\n}\n\n/** Turns a draft into the title and message every channel shows. */\nexport function composeAlert(draft: AlertDraft, def: StoredJobDefinition, now: number): Alert {\n const name = def.name;\n const run = draft.run;\n const d = draft.details;\n let title: string;\n const lines: string[] = [];\n\n switch (draft.type) {\n case \"missed\": {\n title = `${name} missed its scheduled run`;\n lines.push(`Due ${when(d.dueAt as number, now)}, and no run had started by ${when(d.deadline as number, now)} (grace ${formatDuration(d.graceMs as number)}).`);\n lines.push(`Schedule: ${def.schedule}${def.timezone ? ` (${def.timezone})` : \"\"}.`);\n lines.push(`Last run: ${run ? `${run.status} ${when(run.startedAt, now)}` : \"never\"}.`);\n break;\n }\n case \"failed\": {\n title = `${name} failed`;\n const n = d.consecutiveFailures as number;\n if (n > 1) lines.push(`${n} consecutive failures.`);\n if (run) {\n lines.push(`Started ${when(run.startedAt, now)}${run.durationMs !== null ? `, ran ${formatDuration(run.durationMs)}` : \"\"}.`);\n if (run.error) lines.push(`Error: ${firstLines(run.error, 4)}`);\n const out = tail(run.output, 8);\n if (out) lines.push(`Output (tail):\\n${out}`);\n }\n break;\n }\n case \"stuck\": {\n title = `${name} is stuck`;\n if (run) {\n lines.push(`Started ${when(run.startedAt, now)} and never reported finishing. Marked as timed out after ${formatDuration(run.durationMs ?? now - run.startedAt)}.`);\n const out = tail(run.output, 8);\n if (out) lines.push(`Output so far (tail):\\n${out}`);\n }\n lines.push(`If the process was killed mid-run (a serverless timeout, a deploy), this is what that looks like.`);\n break;\n }\n case \"slow\": {\n title = `${name} was slow`;\n lines.push(`Took ${formatDuration(d.durationMs as number)}; the limit is ${formatDuration(d.thresholdMs as number)} (${d.basis}).`);\n if (run) lines.push(`Started ${when(run.startedAt, now)}.`);\n break;\n }\n case \"over_budget\": {\n title = `${name} went over budget`;\n for (const b of d.breaches as BudgetBreach[]) {\n lines.push(`${b.metric}: ${formatNumber(b.value)}, limit ${formatNumber(b.limit)} (${b.basis}).`);\n }\n if (run) lines.push(`Started ${when(run.startedAt, now)}.`);\n break;\n }\n case \"recovered\": {\n title = `${name} recovered`;\n const after = (d.after as string[]).map((c) => c.replace(\"_\", \" \")).join(\", \");\n lines.push(`A run ${run ? when(run.startedAt, now) : \"just now\"} succeeded${after ? ` after: ${after}` : \"\"}.`);\n if (run?.durationMs !== null && run?.durationMs !== undefined) lines.push(`Ran ${formatDuration(run.durationMs)}.`);\n break;\n }\n }\n\n return {\n type: draft.type,\n job: name,\n definition: def,\n run,\n title,\n message: lines.join(\"\\n\"),\n details: d,\n at: now,\n };\n}\n","export function json(body: unknown, status = 200, headers: Record<string, string> = {}): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"content-type\": \"application/json; charset=utf-8\", \"cache-control\": \"no-store\", ...headers },\n });\n}\n","/** Output is capped so a chatty job cannot fill the store. The tail is kept. */\nexport const OUTPUT_CAP = 16 * 1024;\n\nexport function capOutput(text: string): string {\n if (text.length <= OUTPUT_CAP) return text;\n return \"[earlier output trimmed]\\n\" + text.slice(text.length - OUTPUT_CAP);\n}\n\nexport function errorMessage(error: unknown): string {\n if (error instanceof Error) {\n const stack = error.stack ? `\\n${error.stack.split(\"\\n\").slice(1, 6).join(\"\\n\")}` : \"\";\n return `${error.name}: ${error.message}${stack}`;\n }\n if (typeof error === \"string\") return error;\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n}\n","import { capOutput } from \"./output.js\";\nimport type { Run } from \"./types.js\";\n\n/** What a job function receives. */\nexport interface JobContext {\n readonly name: string;\n readonly runId: string;\n readonly startedAt: number;\n /** Aborts when the job's timeout elapses. Honour it if the work can stop. */\n readonly signal: AbortSignal;\n /** Append a line of output. Kept with the run, capped at 16 KB, shown in alerts and the dashboard. */\n log(...parts: unknown[]): void;\n /** Report a number for this run: tokens, cost, rows, anything. Watched against budgets and baselines. */\n metric(name: string, value: number): void;\n metrics(values: Record<string, number>): void;\n}\n\nexport interface RunRecorder {\n context: JobContext;\n output(): string | null;\n metrics(): Record<string, number>;\n abort(): void;\n}\n\nfunction stringify(part: unknown): string {\n if (typeof part === \"string\") return part;\n if (part instanceof Error) return `${part.name}: ${part.message}`;\n try {\n return JSON.stringify(part);\n } catch {\n return String(part);\n }\n}\n\nexport function createRecorder(run: Run): RunRecorder {\n const lines: string[] = [];\n let size = 0;\n const metrics: Record<string, number> = {};\n const controller = new AbortController();\n\n const context: JobContext = {\n name: run.job,\n runId: run.id,\n startedAt: run.startedAt,\n signal: controller.signal,\n log(...parts) {\n const line = parts.map(stringify).join(\" \");\n lines.push(line);\n size += line.length + 1;\n // Drop from the front once well past the cap; capOutput trims exactly at the end.\n while (size > 64 * 1024 && lines.length > 1) {\n size -= lines.shift()!.length + 1;\n }\n },\n metric(name, value) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(`metric \"${name}\" must be a finite number`);\n }\n metrics[name] = value;\n },\n metrics(values) {\n for (const [k, v] of Object.entries(values)) context.metric(k, v);\n },\n };\n\n return {\n context,\n output: () => (lines.length === 0 ? null : capOutput(lines.join(\"\\n\"))),\n metrics: () => ({ ...metrics }),\n abort: () => controller.abort(),\n };\n}\n","import type { JobDefinition, StoredJobDefinition } from \"./types.js\";\n\n/** A definition as a store can hold it: `expect` becomes a description. */\nexport function toStored(def: JobDefinition): StoredJobDefinition {\n const { expect, ...rest } = def;\n const stored: StoredJobDefinition = { ...rest };\n if (expect !== undefined) {\n stored.expect =\n typeof expect === \"string\" ? `contains ${JSON.stringify(expect)}`\n : expect instanceof RegExp ? `matches ${expect.toString()}`\n : \"custom function\";\n }\n return stored;\n}\n\nexport function checkExpectation(expect: JobDefinition[\"expect\"], output: string | null): string | null {\n if (expect === undefined) return null;\n const text = output ?? \"\";\n if (typeof expect === \"string\") {\n return text.includes(expect) ? null : `Output did not contain ${JSON.stringify(expect)}`;\n }\n if (expect instanceof RegExp) {\n return expect.test(text) ? null : `Output did not match ${expect.toString()}`;\n }\n let ok = false;\n try {\n ok = expect(text);\n } catch (error) {\n return `Output check threw: ${(error as Error).message}`;\n }\n return ok ? null : \"Output did not pass the expect() check\";\n}\n","import { formatDuration, formatRelative } from \"../duration.js\";\nimport type { JobSummary, Run } from \"../types.js\";\n\nexport function escapeHtml(value: unknown): string {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nconst h = escapeHtml;\n\nconst CSS = `\n:root{--bg:#fbfbf9;--fg:#1b1b18;--muted:#6b6b64;--line:#e6e5df;--card:#fff;--ok:#1f8a4c;--warn:#b7791f;--bad:#c62828;--info:#2b5fb3;--pill:#f1f0ea;--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;--sans:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Inter,Roboto,sans-serif}\n@media(prefers-color-scheme:dark){:root{--bg:#121311;--fg:#ecece6;--muted:#9a9a91;--line:#2a2b27;--card:#1a1b18;--pill:#24251f}}\n*{box-sizing:border-box}html{-webkit-text-size-adjust:100%}\nbody{margin:0;background:var(--bg);color:var(--fg);font:15px/1.5 var(--sans)}\na{color:inherit}main{max-width:1080px;margin:0 auto;padding:24px 16px 64px}\nheader{display:flex;align-items:baseline;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:20px}\nheader h1{font-size:18px;margin:0;letter-spacing:-.01em}header h1 a{text-decoration:none}\nheader .meta{color:var(--muted);font-size:13px}\n.card{background:var(--card);border:1px solid var(--line);border-radius:10px;overflow:hidden}\ntable{width:100%;border-collapse:collapse;font-size:14px}\nth{text-align:left;font-weight:600;color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 12px;border-bottom:1px solid var(--line);white-space:nowrap}\ntd{padding:10px 12px;border-bottom:1px solid var(--line);vertical-align:top}\ntr:last-child td{border-bottom:0}\n.name{font-weight:600;white-space:nowrap}.name a{text-decoration:none}.name a:hover{text-decoration:underline}\n.mono{font-family:var(--mono);font-size:13px}.muted{color:var(--muted)}.nowrap{white-space:nowrap}\n.pill{display:inline-flex;align-items:center;gap:6px;padding:2px 9px;border-radius:999px;background:var(--pill);font-size:12px;font-weight:600;white-space:nowrap}\n.pill::before{content:\"\";width:7px;height:7px;border-radius:50%;background:currentColor}\n.ok{color:var(--ok)}.warn{color:var(--warn)}.bad{color:var(--bad)}.info{color:var(--info)}.mutedpill{color:var(--muted)}\n.spark{display:block}\nform.inline{display:inline}\nbutton,select{font:inherit;font-size:13px;padding:5px 10px;border:1px solid var(--line);border-radius:7px;background:var(--card);color:var(--fg);cursor:pointer}\nbutton:hover{border-color:var(--muted)}\n.actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}\n.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin:0 0 20px}\n.stat{padding:12px 14px}.stat .k{font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}.stat .v{font-size:20px;font-weight:600;margin-top:2px}\npre{margin:0;padding:10px 12px;background:var(--pill);border-radius:8px;font:12.5px/1.45 var(--mono);white-space:pre-wrap;word-break:break-word;max-height:320px;overflow:auto}\ndetails summary{cursor:pointer;color:var(--muted);font-size:13px}details{margin-top:6px}\n.empty{padding:40px 16px;text-align:center;color:var(--muted)}\ndl{display:grid;grid-template-columns:max-content 1fr;gap:6px 16px;margin:0;padding:14px 16px;font-size:14px}dt{color:var(--muted)}dd{margin:0}\nfooter{margin-top:28px;color:var(--muted);font-size:12px}\n@media(max-width:720px){.hide-sm{display:none}main{padding:16px 16px 48px}}\n`;\n\nexport function layout(title: string, body: string, options: { refresh?: number } = {}): string {\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<meta name=\"robots\" content=\"noindex,nofollow\">\n${options.refresh ? `<meta http-equiv=\"refresh\" content=\"${options.refresh}\">` : \"\"}\n<title>${h(title)}</title>\n<style>${CSS}</style>\n</head>\n<body><main>${body}</main></body>\n</html>`;\n}\n\nfunction healthPill(job: JobSummary): string {\n const map: Record<JobSummary[\"health\"], [string, string]> = {\n healthy: [\"ok\", \"healthy\"],\n late: [\"warn\", \"late\"],\n failing: [\"bad\", \"failing\"],\n stuck: [\"bad\", \"stuck\"],\n silenced: [\"mutedpill\", \"silenced\"],\n never_ran: [\"info\", \"never ran\"],\n };\n const [cls, label] = map[job.health];\n const extras = job.open.filter((c) => ![\"missed\", \"failed\", \"stuck\"].includes(c)).map((c) => c.replace(\"_\", \" \"));\n return `<span class=\"pill ${cls}\">${label}</span>${extras.length ? ` <span class=\"pill warn\">${h(extras.join(\", \"))}</span>` : \"\"}`;\n}\n\nfunction runPill(run: Run): string {\n const cls = run.status === \"ok\" ? \"ok\" : run.status === \"running\" ? \"info\" : \"bad\";\n return `<span class=\"pill ${cls}\">${h(run.status)}</span>`;\n}\n\nfunction sparkline(runs: Run[]): string {\n const points = [...runs].reverse().filter((r) => r.durationMs !== null).slice(-20);\n if (points.length < 2) return \"\";\n const w = 96, hgt = 22;\n const max = Math.max(...points.map((r) => r.durationMs!), 1);\n const step = w / (points.length - 1);\n const path = points.map((r, i) => `${i === 0 ? \"M\" : \"L\"}${(i * step).toFixed(1)},${(hgt - 2 - (r.durationMs! / max) * (hgt - 4)).toFixed(1)}`).join(\" \");\n const dots = points.map((r, i) => r.status === \"ok\" ? \"\" : `<circle cx=\"${(i * step).toFixed(1)}\" cy=\"${(hgt - 2 - (r.durationMs! / max) * (hgt - 4)).toFixed(1)}\" r=\"2.2\" fill=\"var(--bad)\"/>`).join(\"\");\n return `<svg class=\"spark\" width=\"${w}\" height=\"${hgt}\" viewBox=\"0 0 ${w} ${hgt}\" aria-hidden=\"true\"><path d=\"${path}\" fill=\"none\" stroke=\"var(--muted)\" stroke-width=\"1.5\"/>${dots}</svg>`;\n}\n\nfunction stamp(at: number | null, now: number): string {\n if (at === null) return `<span class=\"muted\">never</span>`;\n const iso = new Date(at).toISOString().replace(\"T\", \" \").slice(0, 19);\n return `<span class=\"nowrap\" title=\"${iso} UTC\">${h(formatRelative(at, now))}</span>`;\n}\n\nexport function dashboardPage(jobs: JobSummary[], runsByJob: Map<string, Run[]>, now: number, base: string, checkedAt: number | null): string {\n const rows = jobs.map((job) => {\n const last = job.lastRun;\n return `<tr>\n<td class=\"name\"><a href=\"${h(base)}/jobs/${encodeURIComponent(job.name)}\">${h(job.name)}</a>${job.definition.description ? `<div class=\"muted\" style=\"font-weight:400;font-size:13px;white-space:normal\">${h(job.definition.description)}</div>` : \"\"}</td>\n<td>${healthPill(job)}</td>\n<td class=\"mono nowrap\">${h(job.definition.schedule ?? \"\")}<span class=\"muted\">${job.definition.schedule ? \"\" : \"no schedule\"}</span></td>\n<td class=\"nowrap\">${last ? `${runPill(last)} ${stamp(last.startedAt, now)}${last.durationMs !== null ? ` <span class=\"muted\">${h(formatDuration(last.durationMs))}</span>` : \"\"}` : `<span class=\"muted\">never</span>`}</td>\n<td class=\"nowrap hide-sm\">${stamp(job.nextExpectedAt, now)}</td>\n<td class=\"hide-sm\">${sparkline(runsByJob.get(job.name) ?? [])}</td>\n</tr>`;\n }).join(\"\\n\");\n\n const body = `\n<header>\n <h1><a href=\"${h(base)}/\">CronWatch</a></h1>\n <div class=\"actions\">\n <span class=\"meta\">${jobs.length} job${jobs.length === 1 ? \"\" : \"s\"}${checkedAt ? `, checked ${h(formatRelative(checkedAt, now))}` : \"\"}</span>\n <form class=\"inline\" method=\"post\" action=\"${h(base)}/check\"><button type=\"submit\">Run check now</button></form>\n </div>\n</header>\n<div class=\"card\">\n${jobs.length === 0 ? `<div class=\"empty\">No jobs yet. Declare one with <code class=\"mono\">cw.job(\"name\", { schedule: \"0 2 * * *\" })</code> and run it once.</div>` : `<table>\n<thead><tr><th>Job</th><th>Health</th><th>Schedule</th><th>Last run</th><th class=\"hide-sm\">Next due</th><th class=\"hide-sm\">Durations</th></tr></thead>\n<tbody>${rows}</tbody></table>`}\n</div>\n<footer>Refreshes every minute. <a href=\"${h(base)}/api/jobs\">JSON</a></footer>`;\n return layout(\"CronWatch\", body, { refresh: 60 });\n}\n\nexport function jobPage(job: JobSummary, runs: Run[], now: number, base: string): string {\n const d = job.definition;\n const okRate = `${Math.round(job.stats.okRate * 100)}%`;\n const runRows = runs.map((run) => {\n const detail = [\n run.error ? `<details open><summary>error</summary><pre>${h(run.error)}</pre></details>` : \"\",\n run.output ? `<details${run.status === \"ok\" ? \"\" : \" open\"}><summary>output</summary><pre>${h(run.output)}</pre></details>` : \"\",\n ].join(\"\");\n const metrics = Object.entries(run.metrics).map(([k, v]) => `<span class=\"pill mutedpill\">${h(k)} ${h(Number.isInteger(v) ? v : v.toFixed(4))}</span>`).join(\" \");\n return `<tr>\n<td class=\"nowrap\">${runPill(run)}</td>\n<td class=\"nowrap\">${stamp(run.startedAt, now)}</td>\n<td class=\"nowrap\">${run.durationMs !== null ? h(formatDuration(run.durationMs)) : `<span class=\"muted\">running</span>`}</td>\n<td class=\"hide-sm\">${metrics}</td>\n<td class=\"mono hide-sm muted\">${h(run.trigger)}</td>\n</tr>${detail ? `<tr><td colspan=\"5\" style=\"padding-top:0\">${detail}</td></tr>` : \"\"}`;\n }).join(\"\\n\");\n\n const silenced = job.silencedUntil !== null && job.silencedUntil > now;\n const body = `\n<header>\n <h1><a href=\"${h(base)}/\">CronWatch</a> <span class=\"muted\">/</span> ${h(job.name)}</h1>\n <div class=\"actions\">\n ${healthPill(job)}\n ${silenced\n ? `<form class=\"inline\" method=\"post\" action=\"${h(base)}/jobs/${encodeURIComponent(job.name)}/unsilence\"><button type=\"submit\">Unsilence (until ${h(formatRelative(job.silencedUntil!, now))})</button></form>`\n : `<form class=\"inline\" method=\"post\" action=\"${h(base)}/jobs/${encodeURIComponent(job.name)}/silence\"><select name=\"for\"><option value=\"1h\">1 hour</option><option value=\"4h\">4 hours</option><option value=\"1d\">1 day</option><option value=\"7d\">1 week</option></select> <button type=\"submit\">Silence</button></form>`}\n <form class=\"inline\" method=\"post\" action=\"${h(base)}/jobs/${encodeURIComponent(job.name)}/forget\" onsubmit=\"return confirm('Remove this job and its runs from the store?')\"><button type=\"submit\">Forget</button></form>\n </div>\n</header>\n<div class=\"grid\">\n <div class=\"card stat\"><div class=\"k\">Last run</div><div class=\"v\">${job.lastRun ? h(formatRelative(job.lastRun.startedAt, now)) : \"never\"}</div></div>\n <div class=\"card stat\"><div class=\"k\">Next due</div><div class=\"v\">${job.nextExpectedAt ? h(formatRelative(job.nextExpectedAt, now)) : \"no schedule\"}</div></div>\n <div class=\"card stat\"><div class=\"k\">Success, last ${job.stats.runs}</div><div class=\"v\">${okRate}</div></div>\n <div class=\"card stat\"><div class=\"k\">p50 / p95</div><div class=\"v\">${job.stats.p50Ms !== null ? h(formatDuration(job.stats.p50Ms)) : \"?\"} <span class=\"muted\">/</span> ${job.stats.p95Ms !== null ? h(formatDuration(job.stats.p95Ms)) : \"?\"}</div></div>\n</div>\n<div class=\"card\" style=\"margin-bottom:20px\">\n<dl>\n <dt>Schedule</dt><dd class=\"mono\">${d.schedule ? h(d.schedule) + (d.timezone ? ` <span class=\"muted\">${h(d.timezone)}</span>` : \"\") : `<span class=\"muted\">none</span>`}</dd>\n <dt>Grace</dt><dd class=\"mono\">${h(d.grace ?? \"10m\")}</dd>\n <dt>Timeout</dt><dd class=\"mono\">${h(d.timeout ?? \"1h\")}</dd>\n ${d.maxDuration ? `<dt>Max duration</dt><dd class=\"mono\">${h(d.maxDuration)}</dd>` : \"\"}\n ${d.budget ? `<dt>Budget</dt><dd class=\"mono\">${h(Object.entries(d.budget).map(([k, v]) => `${k} ≤ ${v}`).join(\", \"))}</dd>` : \"\"}\n ${d.expect ? `<dt>Expect</dt><dd class=\"mono\">${h(d.expect)}</dd>` : \"\"}\n ${d.failuresBeforeAlert && d.failuresBeforeAlert > 1 ? `<dt>Alert after</dt><dd>${d.failuresBeforeAlert} consecutive failures</dd>` : \"\"}\n ${d.description ? `<dt>Description</dt><dd>${h(d.description)}</dd>` : \"\"}\n ${d.tags?.length ? `<dt>Tags</dt><dd>${d.tags.map((t) => `<span class=\"pill mutedpill\">${h(t)}</span>`).join(\" \")}</dd>` : \"\"}\n ${job.open.length ? `<dt>Open</dt><dd>${job.open.map((c) => `<span class=\"pill warn\">${h(c.replace(\"_\", \" \"))}</span>`).join(\" \")}</dd>` : \"\"}\n ${job.consecutiveFailures > 0 ? `<dt>Consecutive failures</dt><dd>${job.consecutiveFailures}</dd>` : \"\"}\n</dl>\n</div>\n<div class=\"card\">\n${runs.length === 0 ? `<div class=\"empty\">No runs yet.</div>` : `<table>\n<thead><tr><th>Status</th><th>Started</th><th>Duration</th><th class=\"hide-sm\">Metrics</th><th class=\"hide-sm\">Trigger</th></tr></thead>\n<tbody>${runRows}</tbody></table>`}\n</div>\n<footer><a href=\"${h(base)}/api/jobs/${encodeURIComponent(job.name)}\">JSON</a></footer>`;\n return layout(`${job.name}: CronWatch`, body, { refresh: 60 });\n}\n\nexport function messagePage(title: string, message: string, base: string): string {\n return layout(title, `<header><h1><a href=\"${h(base)}/\">CronWatch</a></h1></header><div class=\"card\"><div class=\"empty\"><strong>${h(title)}</strong><br>${h(message)}</div></div>`);\n}\n","import type { CronWatch } from \"../client.js\";\nimport { json } from \"../http.js\";\nimport { parseDuration } from \"../duration.js\";\nimport type { Run } from \"../types.js\";\nimport { dashboardPage, jobPage, messagePage } from \"./html.js\";\n\nexport interface RoutesOptions {\n /**\n * Required to reach anything. Send it as `Authorization: Bearer <token>`,\n * or open the dashboard once with `?token=<token>` and a cookie is set.\n * Defaults to process.env.CRONWATCH_TOKEN. With no token at all, the routes\n * are open in development and refuse to serve in production.\n *\n * The check endpoint (/api/check) also accepts the client's cronSecret, so\n * a platform cron that sends `Authorization: Bearer <CRON_SECRET>` can\n * trigger checks without knowing the dashboard token.\n */\n token?: string | null;\n /** Where the routes are mounted, so links resolve. Default \"/cronwatch\". */\n basePath?: string;\n}\n\nexport type FetchHandler = (request: Request) => Promise<Response>;\n\nexport interface Routes {\n handler: FetchHandler;\n GET: FetchHandler;\n POST: FetchHandler;\n DELETE: FetchHandler;\n}\n\nconst COOKIE = \"cronwatch_token\";\n\nfunction constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n\nfunction readCookie(request: Request, name: string): string | null {\n const header = request.headers.get(\"cookie\");\n if (!header) return null;\n for (const part of header.split(\";\")) {\n const [k, ...rest] = part.trim().split(\"=\");\n if (k === name) return decodeURIComponent(rest.join(\"=\"));\n }\n return null;\n}\n\nfunction stripBase(pathname: string, base: string): string {\n let path = pathname.startsWith(base) ? pathname.slice(base.length) : pathname;\n if (path === \"\") path = \"/\";\n if (path.length > 1 && path.endsWith(\"/\")) path = path.slice(0, -1);\n return path;\n}\n\nasync function readBody(request: Request): Promise<Record<string, string>> {\n const type = request.headers.get(\"content-type\") ?? \"\";\n try {\n if (type.includes(\"application/json\")) {\n const data = await request.json();\n return typeof data === \"object\" && data !== null ? Object.fromEntries(Object.entries(data).map(([k, v]) => [k, String(v)])) : {};\n }\n if (type.includes(\"application/x-www-form-urlencoded\") || type.includes(\"multipart/form-data\")) {\n const form = await request.formData();\n const out: Record<string, string> = {};\n for (const [k, v] of form.entries()) out[k] = String(v);\n return out;\n }\n } catch {\n return {};\n }\n return {};\n}\n\n/**\n * A fetch-style handler serving the dashboard and a small JSON API. Mount it\n * in a Next.js app at app/cronwatch/[[...path]]/route.ts:\n *\n * export const { GET, POST, DELETE } = cw.routes();\n */\nexport function createRoutes(cw: CronWatch, options: RoutesOptions = {}): Routes {\n const token = options.token === undefined ? (process.env.CRONWATCH_TOKEN ?? null) : options.token;\n const base = (options.basePath ?? \"/cronwatch\").replace(/\\/+$/, \"\");\n const production = process.env.NODE_ENV === \"production\";\n\n const handler: FetchHandler = async (request) => {\n const url = new URL(request.url);\n const path = stripBase(url.pathname, base);\n const wantsHtml = !path.startsWith(\"/api\");\n const method = request.method.toUpperCase();\n\n if (!token && production) {\n return wantsHtml\n ? html(messagePage(\"CronWatch routes are locked\", \"Set CRONWATCH_TOKEN (or pass token to cw.routes()) to use them in production.\", base), 503)\n : json({ ok: false, error: \"CRONWATCH_TOKEN is not set\" }, 503);\n }\n\n if (token) {\n const bearer = request.headers.get(\"authorization\")?.replace(/^Bearer\\s+/i, \"\") ?? null;\n const query = url.searchParams.get(\"token\");\n const cookie = readCookie(request, COOKIE);\n const presented = bearer ?? query ?? cookie;\n const isCheck = path === \"/api/check\";\n const cronSecretOk = isCheck && bearer !== null && cw.cronSecret !== null && constantTimeEqual(bearer, cw.cronSecret);\n if (!cronSecretOk && (presented === null || !constantTimeEqual(presented, token))) {\n return wantsHtml\n ? html(messagePage(\"Sign in\", `Open this page with ?token=<your CRONWATCH_TOKEN> once and it will stay signed in.`, base), 401)\n : json({ ok: false, error: \"Unauthorized\" }, 401);\n }\n if (query !== null && wantsHtml && method === \"GET\") {\n // Move the token from the URL into a cookie so it is not in history or logs.\n url.searchParams.delete(\"token\");\n const secure = url.protocol === \"https:\" ? \"; Secure\" : \"\";\n return new Response(null, {\n status: 303,\n headers: {\n location: url.pathname + (url.search || \"\"),\n \"set-cookie\": `${COOKIE}=${encodeURIComponent(token)}; Path=${base || \"/\"}; HttpOnly; SameSite=Lax; Max-Age=${60 * 60 * 24 * 30}${secure}`,\n },\n });\n }\n }\n\n const redirectBack = () => {\n const referer = request.headers.get(\"referer\") ?? \"\";\n const location = referer.startsWith(url.origin + \"/\") ? referer : `${base}/`;\n return new Response(null, { status: 303, headers: { location } });\n };\n const jobName = (segment: string | undefined) => (segment ? decodeURIComponent(segment) : \"\");\n const parts = path.split(\"/\").filter(Boolean);\n\n // HTML\n if (method === \"GET\" && path === \"/\") {\n const jobs = await cw.jobs();\n const runsByJob = new Map<string, Run[]>();\n for (const job of jobs) runsByJob.set(job.name, await cw.runs(job.name, 20));\n return html(dashboardPage(jobs, runsByJob, cw.now(), base, null));\n }\n if (method === \"GET\" && parts[0] === \"jobs\" && parts.length === 2) {\n const job = await cw.jobSummary(jobName(parts[1]));\n if (!job) return html(messagePage(\"No such job\", `${jobName(parts[1])} is not in the store.`, base), 404);\n return html(jobPage(job, await cw.runs(job.name, 50), cw.now(), base));\n }\n if (method === \"POST\" && path === \"/check\") {\n await cw.check();\n return redirectBack();\n }\n if (method === \"POST\" && parts[0] === \"jobs\" && parts.length === 3) {\n const name = jobName(parts[1]);\n const body = await readBody(request);\n if (parts[2] === \"silence\") await cw.silence(name, safeDuration(body.for, \"1h\"));\n else if (parts[2] === \"unsilence\") await cw.unsilence(name);\n else if (parts[2] === \"forget\") {\n await cw.forget(name);\n return new Response(null, { status: 303, headers: { location: `${base}/` } });\n } else return html(messagePage(\"Not found\", path, base), 404);\n return redirectBack();\n }\n\n // JSON API\n if (parts[0] === \"api\") {\n const rest = parts.slice(1);\n if (method === \"GET\" && rest[0] === \"jobs\" && rest.length === 1) {\n return json({ ok: true, jobs: await cw.jobs() });\n }\n if (rest[0] === \"jobs\" && rest.length === 2) {\n const name = jobName(rest[1]);\n if (method === \"GET\") {\n const job = await cw.jobSummary(name);\n if (!job) return json({ ok: false, error: \"No such job\" }, 404);\n const limit = Number(url.searchParams.get(\"runs\") ?? 20);\n return json({ ok: true, job, runs: await cw.runs(name, Number.isFinite(limit) ? limit : 20) });\n }\n if (method === \"DELETE\") {\n await cw.forget(name);\n return json({ ok: true });\n }\n }\n if (method === \"POST\" && rest[0] === \"jobs\" && rest.length === 3) {\n const name = jobName(rest[1]);\n if (!(await cw.jobSummary(name))) return json({ ok: false, error: \"No such job\" }, 404);\n const body = await readBody(request);\n if (rest[2] === \"silence\") return json({ ok: true, state: await cw.silence(name, safeDuration(body.for ?? url.searchParams.get(\"for\"), \"1h\")) });\n if (rest[2] === \"unsilence\") return json({ ok: true, state: await cw.unsilence(name) });\n }\n if ((method === \"GET\" || method === \"POST\") && rest[0] === \"check\" && rest.length === 1) {\n const result = await cw.check();\n return json({ ok: true, ...result });\n }\n if (method === \"GET\" && rest[0] === \"runs\" && rest.length === 2) {\n const run = await cw.getRun(rest[1]!);\n return run ? json({ ok: true, run }) : json({ ok: false, error: \"No such run\" }, 404);\n }\n return json({ ok: false, error: \"Not found\" }, 404);\n }\n\n return html(messagePage(\"Not found\", path, base), 404);\n };\n\n return { handler, GET: handler, POST: handler, DELETE: handler };\n}\n\nfunction safeDuration(value: string | null | undefined, fallback: string): string {\n if (!value) return fallback;\n try {\n parseDuration(value);\n return value;\n } catch {\n return fallback;\n }\n}\n\nfunction html(body: string, status = 200): Response {\n return new Response(body, {\n status,\n headers: { \"content-type\": \"text/html; charset=utf-8\", \"cache-control\": \"no-store\", \"x-robots-tag\": \"noindex\" },\n });\n}\n","import type { JobState, Run, Store, StoredJob, StoredJobDefinition } from \"../types.js\";\n\n/**\n * Keeps everything in process memory. The default when no store is given,\n * good for tests and for trying the library out. State is gone on restart,\n * so a missed run cannot be noticed across one.\n */\nexport function memory(): Store {\n const jobs = new Map<string, StoredJob>();\n const runs = new Map<string, Run>();\n const order = new Map<string, number>();\n const states = new Map<string, JobState>();\n let seq = 0;\n\n const clone = <T>(v: T): T => JSON.parse(JSON.stringify(v));\n\n return {\n async upsertJob(definition: StoredJobDefinition, now: number) {\n const existing = jobs.get(definition.name);\n jobs.set(definition.name, {\n name: definition.name,\n definition: clone(definition),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n });\n },\n async getJob(name) {\n const j = jobs.get(name);\n return j ? clone(j) : null;\n },\n async listJobs() {\n return [...jobs.values()].map(clone).sort((a, b) => a.name.localeCompare(b.name));\n },\n async deleteJob(name) {\n jobs.delete(name);\n states.delete(name);\n for (const [id, run] of runs) if (run.job === name) { runs.delete(id); order.delete(id); }\n },\n async insertRun(run) {\n runs.set(run.id, clone(run));\n order.set(run.id, ++seq);\n },\n async updateRun(run) {\n runs.set(run.id, clone(run));\n },\n async getRun(id) {\n const r = runs.get(id);\n return r ? clone(r) : null;\n },\n async listRuns(job, limit) {\n return [...runs.values()]\n .filter((r) => r.job === job)\n .sort((a, b) => b.startedAt - a.startedAt || order.get(b.id)! - order.get(a.id)!)\n .slice(0, limit)\n .map(clone);\n },\n async lastRun(job) {\n const list = await this.listRuns(job, 1);\n return list[0] ?? null;\n },\n async runningRuns() {\n return [...runs.values()].filter((r) => r.status === \"running\").map(clone);\n },\n async getState(job) {\n const s = states.get(job);\n return s ? clone(s) : null;\n },\n async setState(state) {\n states.set(state.job, clone(state));\n },\n async prune(before) {\n let n = 0;\n for (const [id, run] of runs) {\n if (run.status !== \"running\" && run.startedAt < before) {\n runs.delete(id);\n order.delete(id);\n n++;\n }\n }\n return n;\n },\n };\n}\n","import { parseDuration } from \"./duration.js\";\nimport {\n BASELINE_WINDOW,\n emptyState,\n isSilenced,\n isStuck,\n muteOpens,\n onCheck,\n onRunFinish,\n onRunStart,\n openConditions,\n timeoutMs,\n} from \"./evaluate.js\";\nimport type { AlertDraft, Evaluation } from \"./evaluate.js\";\nimport { composeAlert } from \"./format.js\";\nimport { json } from \"./http.js\";\nimport { createRecorder } from \"./job.js\";\nimport type { JobContext } from \"./job.js\";\nimport { errorMessage } from \"./output.js\";\nimport { parseSchedule } from \"./schedule.js\";\nimport { checkExpectation, toStored } from \"./serialize.js\";\nimport { percentile } from \"./stats.js\";\nimport { createRoutes } from \"./routes/index.js\";\nimport type { Routes, RoutesOptions } from \"./routes/index.js\";\nimport { memory } from \"./stores/memory.js\";\nimport type {\n Alert,\n AlertChannel,\n CheckResult,\n Condition,\n Duration,\n JobDefinition,\n JobOptions,\n JobState,\n JobSummary,\n Run,\n Store,\n StoredJob,\n StoredJobDefinition,\n TriageFn,\n} from \"./types.js\";\n\nexport type JobFn<T> = (job: JobContext) => Promise<T> | T;\nexport type HandlerFn<T> = (job: JobContext, request: Request) => Promise<T> | T;\n\nexport interface HandlerOptions {\n /**\n * Callers must send `Authorization: Bearer <secret>`. Defaults to the\n * client's cronSecret, which defaults to process.env.CRON_SECRET (what\n * Vercel sends its cron requests with). Pass null to allow anyone.\n */\n secret?: string | null;\n}\n\nexport interface JobHandle {\n readonly name: string;\n readonly definition: JobDefinition;\n /** Run the function now, recording the run. Rethrows whatever the function throws. */\n run<T>(fn: JobFn<T>, options?: { trigger?: string }): Promise<T>;\n /** A fetch-style request handler (Next.js route, Hono, Bun, Deno) that runs the function and records the run. */\n handler<T>(fn: HandlerFn<T>, options?: HandlerOptions): (request: Request) => Promise<Response>;\n}\n\nexport interface CronWatchOptions {\n /** Where jobs, runs and state live. Defaults to an in-memory store that forgets on restart. */\n store?: Store;\n /** Where alerts go. Defaults to the console. */\n alerts?: AlertChannel[];\n /** Adds a short diagnosis to failure alerts. See @cronwatch/sdk/anthropic. */\n triage?: TriageFn;\n /** Shared secret that handler() requests must carry. Defaults to process.env.CRON_SECRET. */\n cronSecret?: string | null;\n /** How long finished runs are kept. Default \"30d\". */\n retention?: Duration;\n /** Applied to every job unless the job sets its own. */\n defaults?: Pick<JobOptions, \"grace\" | \"timeout\" | \"timezone\" | \"failuresBeforeAlert\">;\n /** Called with anything that goes wrong outside a job: an alert channel failing, a triage timeout. */\n onError?: (error: unknown, where: string) => void;\n /** The clock. Tests use this. */\n now?: () => number;\n}\n\nexport interface ExecuteResult<T> {\n run: Run;\n result: T | undefined;\n error: unknown;\n threw: boolean;\n}\n\nconst NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,119}$/;\nconst TRIAGE_TIMEOUT_MS = 25_000;\nconst PRUNE_INTERVAL_MS = 60 * 60_000;\n\nfunction constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n\nexport class CronWatch {\n readonly store: Store;\n readonly alerts: AlertChannel[];\n readonly triage: TriageFn | undefined;\n readonly cronSecret: string | null;\n readonly retentionMs: number;\n readonly now: () => number;\n readonly onError: (error: unknown, where: string) => void;\n private readonly defaults: NonNullable<CronWatchOptions[\"defaults\"]>;\n private readonly definitions = new Map<string, JobDefinition>();\n private readonly synced = new Set<string>();\n private ready: Promise<void> | null = null;\n private checking: Promise<CheckResult> | null = null;\n private lastPruneAt = 0;\n private timer: ReturnType<typeof setInterval> | null = null;\n private usingDefaultStore = false;\n\n constructor(options: CronWatchOptions = {}) {\n this.store = options.store ?? (this.usingDefaultStore = true, memory());\n this.alerts = options.alerts ?? [consoleChannel()];\n this.triage = options.triage;\n this.cronSecret = options.cronSecret === undefined ? (process.env.CRON_SECRET ?? null) : options.cronSecret;\n this.retentionMs = parseDuration(options.retention ?? \"30d\", \"retention\");\n this.defaults = options.defaults ?? {};\n this.now = options.now ?? (() => Date.now());\n this.onError = options.onError ?? ((error, where) => console.error(`[cronwatch] ${where}:`, error));\n }\n\n /** Declare a job. Call it once, at module level, and keep the handle. */\n job(name: string, options: JobOptions = {}): JobHandle {\n if (!NAME_RE.test(name)) {\n throw new Error(`job name \"${name}\" must be 1 to 120 characters of letters, digits, \".\", \"_\", \":\" or \"-\"`);\n }\n const definition: JobDefinition = { ...this.defaults, ...options, name };\n if (definition.schedule) parseSchedule(definition.schedule, definition.timezone);\n if (definition.grace !== undefined) parseDuration(definition.grace, \"grace\");\n if (definition.timeout !== undefined) parseDuration(definition.timeout, \"timeout\");\n if (definition.maxDuration !== undefined) parseDuration(definition.maxDuration, \"maxDuration\");\n this.definitions.set(name, definition);\n this.synced.delete(name);\n return this.handle(definition);\n }\n\n /** Run a job by name without keeping a handle. Defines it on first use. */\n run<T>(name: string, fn: JobFn<T>): Promise<T>;\n run<T>(name: string, options: JobOptions, fn: JobFn<T>): Promise<T>;\n run<T>(name: string, optionsOrFn: JobOptions | JobFn<T>, maybeFn?: JobFn<T>): Promise<T> {\n const fn = typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!;\n const options = typeof optionsOrFn === \"function\" ? undefined : optionsOrFn;\n const handle = options || !this.definitions.has(name) ? this.job(name, options) : this.handle(this.definitions.get(name)!);\n return handle.run(fn);\n }\n\n /** The definitions declared in this process. */\n definedJobs(): JobDefinition[] {\n return [...this.definitions.values()];\n }\n\n private handle(definition: JobDefinition): JobHandle {\n const self = this;\n return {\n name: definition.name,\n definition,\n async run<T>(fn: JobFn<T>, options?: { trigger?: string }): Promise<T> {\n const outcome = await self.execute(definition, fn, options?.trigger ?? \"run\");\n if (outcome.threw) throw outcome.error;\n return outcome.result as T;\n },\n handler<T>(fn: HandlerFn<T>, options?: HandlerOptions) {\n const secret = options?.secret === undefined ? self.cronSecret : options.secret;\n return async (request: Request): Promise<Response> => {\n if (secret) {\n const header = request.headers.get(\"authorization\") ?? \"\";\n if (!constantTimeEqual(header, `Bearer ${secret}`)) {\n return json({ ok: false, error: \"Unauthorized\" }, 401);\n }\n }\n const outcome = await self.execute(definition, (job) => fn(job, request), \"handler\");\n if (outcome.result instanceof Response) return outcome.result;\n const body = {\n ok: outcome.run.status === \"ok\",\n job: definition.name,\n run: outcome.run.id,\n status: outcome.run.status,\n durationMs: outcome.run.durationMs,\n ...(outcome.run.error ? { error: outcome.run.error.split(\"\\n\")[0] } : {}),\n };\n return json(body, outcome.run.status === \"ok\" ? 200 : 500);\n };\n },\n };\n }\n\n private async ensureReady(): Promise<void> {\n if (!this.ready) {\n this.ready = (async () => {\n if (this.store.init) await this.store.init();\n if (this.usingDefaultStore && process.env.NODE_ENV === \"production\") {\n console.warn(\"[cronwatch] using the in-memory store: runs and state are lost on restart. Pass a store from @cronwatch/sdk/sqlite or @cronwatch/sdk/postgres.\");\n }\n })();\n }\n await this.ready;\n }\n\n private async sync(definition: JobDefinition): Promise<void> {\n await this.ensureReady();\n if (this.synced.has(definition.name)) return;\n await this.store.upsertJob(toStored(definition), this.now());\n this.synced.add(definition.name);\n }\n\n /** Runs a function as a recorded run. Never throws for the job's own error; see `threw`. */\n async execute<T>(definition: JobDefinition, fn: JobFn<T>, trigger: string): Promise<ExecuteResult<T>> {\n await this.sync(definition);\n const startedAt = this.now();\n const run: Run = {\n id: crypto.randomUUID(),\n job: definition.name,\n status: \"running\",\n startedAt,\n finishedAt: null,\n durationMs: null,\n error: null,\n output: null,\n metrics: {},\n trigger,\n };\n await this.store.insertRun(run);\n\n const before = (await this.store.getState(definition.name)) ?? emptyState(definition.name);\n const started = onRunStart(before);\n if (openConditions(started.state).length !== openConditions(before).length) {\n await this.store.setState(started.state);\n }\n\n const recorder = createRecorder(run);\n const timer = setTimeout(() => recorder.abort(), timeoutMs(definition));\n if (typeof timer === \"object\" && \"unref\" in timer) timer.unref();\n\n let result: T | undefined;\n let error: unknown;\n let threw = false;\n try {\n result = await fn(recorder.context);\n } catch (e) {\n error = e;\n threw = true;\n } finally {\n clearTimeout(timer);\n }\n\n const finishedAt = this.now();\n run.finishedAt = finishedAt;\n run.durationMs = Math.max(0, finishedAt - startedAt);\n run.metrics = recorder.metrics();\n run.output = recorder.output() ?? (typeof result === \"string\" ? result : null);\n\n if (threw) {\n run.status = \"failed\";\n run.error = errorMessage(error);\n } else if (result instanceof Response && result.status >= 400) {\n run.status = \"failed\";\n run.error = `HTTP ${result.status}${result.statusText ? ` ${result.statusText}` : \"\"}`;\n } else {\n const unmet = checkExpectation(definition.expect, run.output);\n if (unmet) {\n run.status = \"failed\";\n run.error = unmet;\n } else {\n run.status = \"ok\";\n }\n }\n await this.store.updateRun(run);\n\n try {\n const history = (await this.store.listRuns(definition.name, BASELINE_WINDOW + 5)).filter((r) => r.id !== run.id);\n const state = (await this.store.getState(definition.name)) ?? emptyState(definition.name);\n const evaluation = onRunFinish(definition, run, state, history, started.openBefore, finishedAt);\n await this.settle(state, evaluation, toStored(definition), finishedAt);\n } catch (e) {\n this.onError(e, `evaluating ${definition.name}`);\n }\n\n return { run, result, error, threw };\n }\n\n /**\n * Look for missed and stuck runs across every job, send alerts, and prune\n * old runs. Call it from an interval (start()), a cron hitting the mounted\n * routes, or by hand. Concurrent calls share one check.\n */\n check(): Promise<CheckResult> {\n if (!this.checking) {\n this.checking = this.runCheck().finally(() => {\n this.checking = null;\n });\n }\n return this.checking;\n }\n\n private async runCheck(): Promise<CheckResult> {\n await this.ensureReady();\n for (const definition of this.definitions.values()) await this.sync(definition);\n const now = this.now();\n const alerts: Alert[] = [];\n\n // Runs that never reported back.\n for (const run of await this.store.runningRuns()) {\n const stored = await this.store.getJob(run.job);\n const declared = this.definitions.get(run.job);\n const definition = declared ? toStored(declared) : stored?.definition;\n if (!definition || !isStuck(definition, run, now)) continue;\n run.status = \"timeout\";\n run.finishedAt = now;\n run.durationMs = now - run.startedAt;\n run.error = `Still running after ${Math.round(timeoutMs(definition) / 60_000)} minutes; marked as timed out`;\n await this.store.updateRun(run);\n const history = (await this.store.listRuns(run.job, BASELINE_WINDOW + 5)).filter((r) => r.id !== run.id);\n const state = (await this.store.getState(run.job)) ?? emptyState(run.job);\n const evaluation = onRunFinish(definition, run, state, history, [], now);\n alerts.push(...(await this.settle(state, evaluation, definition, now)));\n }\n\n const jobs: JobSummary[] = [];\n for (const stored of await this.store.listJobs()) {\n const definition = stored.definition;\n const lastRun = await this.store.lastRun(stored.name);\n const state = (await this.store.getState(stored.name)) ?? emptyState(stored.name);\n const evaluation = onCheck(definition, stored, lastRun, state, now);\n alerts.push(...(await this.settle(state, evaluation, definition, now)));\n jobs.push(await this.summarize(stored, lastRun, evaluation.state, evaluation.nextExpectedAt, now));\n }\n\n let pruned = 0;\n if (now - this.lastPruneAt > PRUNE_INTERVAL_MS) {\n this.lastPruneAt = now;\n try {\n pruned = await this.store.prune(now - this.retentionMs);\n } catch (e) {\n this.onError(e, \"pruning\");\n }\n }\n\n return { checkedAt: now, jobs, alerts, pruned };\n }\n\n /** Every job the store knows about, with its health. Does not send alerts. */\n async jobs(): Promise<JobSummary[]> {\n await this.ensureReady();\n for (const definition of this.definitions.values()) await this.sync(definition);\n const now = this.now();\n const out: JobSummary[] = [];\n for (const stored of await this.store.listJobs()) {\n const lastRun = await this.store.lastRun(stored.name);\n const state = (await this.store.getState(stored.name)) ?? emptyState(stored.name);\n const { nextExpectedAt } = onCheck(stored.definition, stored, lastRun, state, now);\n out.push(await this.summarize(stored, lastRun, state, nextExpectedAt, now));\n }\n return out;\n }\n\n async jobSummary(name: string): Promise<JobSummary | null> {\n await this.ensureReady();\n const definition = this.definitions.get(name);\n if (definition) await this.sync(definition);\n const stored = await this.store.getJob(name);\n if (!stored) return null;\n const now = this.now();\n const lastRun = await this.store.lastRun(name);\n const state = (await this.store.getState(name)) ?? emptyState(name);\n const { nextExpectedAt } = onCheck(stored.definition, stored, lastRun, state, now);\n return this.summarize(stored, lastRun, state, nextExpectedAt, now);\n }\n\n async runs(name: string, limit = 50): Promise<Run[]> {\n await this.ensureReady();\n return this.store.listRuns(name, Math.min(500, Math.max(1, limit)));\n }\n\n async getRun(id: string): Promise<Run | null> {\n await this.ensureReady();\n return this.store.getRun(id);\n }\n\n /** Stop alerts for a job for a while. State keeps updating underneath. */\n async silence(name: string, duration: Duration): Promise<JobState> {\n await this.ensureReady();\n const state = (await this.store.getState(name)) ?? emptyState(name);\n state.silencedUntil = this.now() + parseDuration(duration, \"silence duration\");\n await this.store.setState(state);\n return state;\n }\n\n async unsilence(name: string): Promise<JobState> {\n await this.ensureReady();\n const state = (await this.store.getState(name)) ?? emptyState(name);\n state.silencedUntil = null;\n await this.store.setState(state);\n return state;\n }\n\n /** Remove a job and its runs from the store. A job still declared in code comes back on its next run. */\n async forget(name: string): Promise<void> {\n await this.ensureReady();\n this.definitions.delete(name);\n this.synced.delete(name);\n await this.store.deleteJob(name);\n }\n\n /** The dashboard and JSON API as fetch-style handlers. See createRoutes(). */\n routes(options?: RoutesOptions): Routes {\n return createRoutes(this, options);\n }\n\n /** Check on an interval, for long-running servers. Default every minute. */\n start(every: Duration = \"1m\"): void {\n if (this.timer) return;\n const ms = Math.max(5_000, parseDuration(every, \"check interval\"));\n const tick = () => this.check().catch((e) => this.onError(e, \"check\"));\n this.timer = setInterval(tick, ms);\n if (typeof this.timer === \"object\" && \"unref\" in this.timer) this.timer.unref();\n setTimeout(tick, 1_000).unref?.();\n }\n\n stop(): void {\n if (this.timer) clearInterval(this.timer);\n this.timer = null;\n }\n\n async close(): Promise<void> {\n this.stop();\n if (this.store.close) await this.store.close();\n }\n\n private async summarize(stored: StoredJob, lastRun: Run | null, state: JobState, nextExpectedAt: number | null, now: number): Promise<JobSummary> {\n const recent = await this.store.listRuns(stored.name, BASELINE_WINDOW);\n const finished = recent.filter((r) => r.status !== \"running\");\n const okDurations = recent.filter((r) => r.status === \"ok\" && r.durationMs !== null).map((r) => r.durationMs!);\n const open = openConditions(state);\n let health: JobSummary[\"health\"];\n if (state.silencedUntil !== null && state.silencedUntil > now) health = \"silenced\";\n else if (open.includes(\"stuck\") || (lastRun && isStuck(stored.definition, lastRun, now))) health = \"stuck\";\n else if (open.includes(\"failed\") || lastRun?.status === \"failed\" || lastRun?.status === \"timeout\") health = \"failing\";\n else if (open.includes(\"missed\")) health = \"late\";\n else if (!lastRun) health = \"never_ran\";\n else health = \"healthy\";\n return {\n name: stored.name,\n definition: stored.definition,\n health,\n open,\n lastRun,\n nextExpectedAt,\n consecutiveFailures: state.consecutiveFailures,\n silencedUntil: state.silencedUntil,\n stats: {\n runs: finished.length,\n okRate: finished.length === 0 ? 1 : finished.filter((r) => r.status === \"ok\").length / finished.length,\n p50Ms: percentile(okDurations, 50),\n p95Ms: percentile(okDurations, 95),\n },\n };\n }\n\n /** Save an evaluation's state, honouring silence, and send its alerts. */\n private async settle(previous: JobState, evaluation: Evaluation, definition: StoredJobDefinition, now: number): Promise<Alert[]> {\n if (isSilenced(previous, now)) {\n evaluation.state = muteOpens(previous, evaluation.state);\n evaluation.alerts = [];\n }\n if (JSON.stringify(evaluation.state) !== JSON.stringify(previous)) await this.store.setState(evaluation.state);\n return this.dispatch(evaluation.alerts, definition, evaluation.state, now);\n }\n\n private async dispatch(drafts: AlertDraft[], definition: StoredJobDefinition, state: JobState, now: number): Promise<Alert[]> {\n if (drafts.length === 0) return [];\n const sent: Alert[] = [];\n for (const draft of drafts) {\n const alert = composeAlert(draft, definition, now);\n if (this.triage && alert.type !== \"recovered\") {\n try {\n const recentRuns = await this.store.listRuns(alert.job, 5);\n const diagnosis = await withTimeout(this.triage({ alert, recentRuns }), TRIAGE_TIMEOUT_MS);\n if (diagnosis) alert.triage = diagnosis;\n } catch (e) {\n this.onError(e, `triage for ${alert.job}`);\n }\n }\n for (const channel of this.alerts) {\n try {\n await channel.send(alert);\n } catch (e) {\n this.onError(e, `alert channel ${channel.name}`);\n }\n }\n sent.push(alert);\n }\n state.lastAlertAt = now;\n await this.store.setState(state);\n return sent;\n }\n}\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const t = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);\n promise.then((v) => { clearTimeout(t); resolve(v); }, (e) => { clearTimeout(t); reject(e); });\n });\n}\n\n/** Writes alerts to the console. The default channel. */\nexport function consoleChannel(): AlertChannel {\n return {\n name: \"console\",\n async send(alert) {\n const line = `[cronwatch] ${alert.title}\\n${alert.message}${alert.triage ? `\\nTriage: ${alert.triage}` : \"\"}`;\n if (alert.type === \"recovered\") console.info(line);\n else console.error(line);\n },\n };\n}\n\n/** Wrap any function as an alert channel. */\nexport function custom(name: string, send: (alert: Alert) => Promise<void> | void): AlertChannel {\n return { name, send: async (alert) => { await send(alert); } };\n}\n\nexport type { Condition };\n","import { CronWatch } from \"./client.js\";\nimport type { CronWatchOptions } from \"./client.js\";\n\n/**\n * Create a CronWatch client. One per app, at module level:\n *\n * export const cw = cronwatch({ store: sqlite({ path: \"./data/cronwatch.db\" }), alerts: [slack({ webhookUrl })] });\n * export const nightly = cw.job(\"nightly-report\", { schedule: \"0 2 * * *\", grace: \"15m\" });\n */\nexport function cronwatch(options: CronWatchOptions = {}): CronWatch {\n return new CronWatch(options);\n}\n\nexport { CronWatch, consoleChannel, custom } from \"./client.js\";\nexport { json } from \"./http.js\";\nexport type { CronWatchOptions, HandlerFn, HandlerOptions, JobFn, JobHandle } from \"./client.js\";\nexport type { JobContext } from \"./job.js\";\nexport { memory } from \"./stores/memory.js\";\nexport { createRoutes } from \"./routes/index.js\";\nexport type { RoutesOptions, Routes } from \"./routes/index.js\";\nexport { parseDuration, formatDuration, formatRelative } from \"./duration.js\";\nexport { parseSchedule, previousFire, nextFire } from \"./schedule.js\";\nexport { composeAlert } from \"./format.js\";\nexport type {\n Alert,\n AlertChannel,\n AlertType,\n CheckResult,\n Condition,\n Duration,\n ExpectRule,\n JobDefinition,\n JobHealth,\n JobOptions,\n JobState,\n JobSummary,\n Run,\n RunStatus,\n Store,\n StoredJob,\n StoredJobDefinition,\n TriageContext,\n TriageFn,\n} from \"./types.js\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/duration.ts","../src/schedule.ts","../src/stats.ts","../src/evaluate.ts","../src/format.ts","../src/http.ts","../src/output.ts","../src/job.ts","../src/serialize.ts","../src/routes/html.ts","../src/routes/index.ts","../src/stores/memory.ts","../src/client.ts","../src/index.ts"],"names":["Cron","graceMs","createHash","tail","previous","evaluation"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Duration } from \"./types.js\";\n\nconst UNIT_MS: Record<string, number> = {\n ms: 1,\n s: 1000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n};\n\n/**\n * \"15m\" -> 900000. Accepts a plain number of milliseconds, and compound\n * strings such as \"1h30m\". Whitespace between parts is fine.\n */\nexport function parseDuration(value: Duration, label = \"duration\"): number {\n if (typeof value === \"number\") {\n if (!Number.isFinite(value) || value < 0) throw new Error(`${label} must be a non-negative number of milliseconds`);\n return value;\n }\n const text = value.trim().toLowerCase();\n if (text === \"\") throw new Error(`${label} is empty`);\n const re = /(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h|d|w)/g;\n let total = 0;\n let consumed = \"\";\n let match: RegExpExecArray | null;\n while ((match = re.exec(text)) !== null) {\n total += parseFloat(match[1]!) * UNIT_MS[match[2]!]!;\n consumed += match[0];\n }\n if (consumed.replace(/\\s+/g, \"\") !== text.replace(/\\s+/g, \"\")) {\n throw new Error(`${label} \"${value}\" is not a duration like \"15m\", \"1h30m\" or \"90s\"`);\n }\n return Math.round(total);\n}\n\n/** 90000 -> \"1m 30s\". For messages, not for parsing back. */\nexport function formatDuration(ms: number): string {\n if (!Number.isFinite(ms)) return \"?\";\n if (ms < 1000) return `${Math.round(ms)}ms`;\n const parts: string[] = [];\n let rest = Math.round(ms / 1000);\n const units: [string, number][] = [[\"d\", 86_400], [\"h\", 3_600], [\"m\", 60], [\"s\", 1]];\n for (const [unit, size] of units) {\n if (rest >= size) {\n const n = Math.floor(rest / size);\n rest -= n * size;\n parts.push(`${n}${unit}`);\n }\n if (parts.length === 2) break;\n }\n return parts.join(\" \") || \"0s\";\n}\n\n/** \"5 minutes ago\", \"in 2h\". Relative to `now`. */\nexport function formatRelative(at: number, now: number): string {\n const diff = at - now;\n const abs = Math.abs(diff);\n const text = abs < 5_000 ? \"now\" : formatDuration(abs);\n if (abs < 5_000) return text;\n return diff < 0 ? `${text} ago` : `in ${text}`;\n}\n","import { Cron } from \"croner\";\nimport { parseDuration } from \"./duration.js\";\n\nexport interface ParsedSchedule {\n kind: \"cron\" | \"interval\";\n source: string;\n /** The IANA timezone a cron is read in, when one was given. */\n timezone?: string;\n /** For intervals, the period in milliseconds. */\n everyMs?: number;\n}\n\nconst cache = new Map<string, ParsedSchedule>();\n/** The croner instance behind each cron schedule, kept out of the public type. */\nconst crons = new WeakMap<ParsedSchedule, Cron>();\n\n/** How early a run may start and still count for the fire it was meant for. */\nexport const EARLY_SLACK_MS = 60_000;\n\n/**\n * \"0 2 * * *\" (cron, five or six fields), \"@hourly\", or \"every 5m\".\n * Parsed once per (schedule, timezone) pair and cached. The croner instance\n * gets no callback, so it schedules nothing; it is only used to compute fire\n * times. Without a timezone the expression is read in the process timezone,\n * like crontab. Vercel and GitHub Actions run their crons in UTC, so pass\n * timezone: \"UTC\" for those.\n */\nexport function parseSchedule(schedule: string, timezone?: string): ParsedSchedule {\n const key = `${timezone ?? \"\"}|${schedule}`;\n const hit = cache.get(key);\n if (hit) return hit;\n\n const text = schedule.trim();\n const every = /^every\\s+(.+)$/i.exec(text);\n let parsed: ParsedSchedule;\n if (every) {\n const everyMs = parseDuration(every[1]!, \"schedule interval\");\n if (everyMs < 1000) throw new Error(`schedule \"${schedule}\" is shorter than one second`);\n parsed = { kind: \"interval\", source: text, everyMs };\n } else {\n let cron: Cron;\n try {\n cron = new Cron(text, timezone ? { timezone } : {});\n } catch (error) {\n throw new Error(`schedule \"${schedule}\" is not a cron expression or \"every <duration>\": ${(error as Error).message}`);\n }\n parsed = { kind: \"cron\", source: text, ...(timezone ? { timezone } : {}) };\n crons.set(parsed, cron);\n }\n cache.set(key, parsed);\n return parsed;\n}\n\n/**\n * The first fire strictly after `from`, or null when the cron never fires\n * again. croner answers with times in the past when asked from inside the\n * hour that repeats when clocks go back, so its answers are filtered, and a\n * stretch of nothing but past times is stepped over an hour at a time.\n */\nfunction fireAfter(parsed: ParsedSchedule, from: number): number | null {\n const cron = crons.get(parsed);\n if (!cron) throw new Error(`schedule \"${parsed.source}\" was not made by parseSchedule`);\n let probe = from;\n for (let attempt = 0; attempt < 4; attempt++) {\n const runs = cron.nextRuns(8, new Date(probe));\n if (runs.length === 0) return null;\n const found = runs.find((d) => d.getTime() > from);\n if (found) return found.getTime();\n probe += 3_600_000;\n }\n return null;\n}\n\n/** The next time the schedule fires strictly after `from`. For an interval, counted from the last run when there is one. */\nexport function nextFire(parsed: ParsedSchedule, from: number, lastRunAt: number | null): number | null {\n if (parsed.kind === \"interval\") {\n const base = lastRunAt ?? from;\n return base + parsed.everyMs!;\n }\n return fireAfter(parsed, from);\n}\n\nexport interface Expectation {\n /** When the next run the schedule asks for is due. */\n dueAt: number;\n /** Missed once now passes this. */\n deadline: number;\n}\n\n/**\n * When the schedule next wants a run, given the last one. For a cron that is\n * the first fire the last run does not already cover; with no run yet, the\n * first fire at or after registration. For an interval it is the last run's\n * start (or registration) plus the interval. Null for a cron that never\n * fires again.\n *\n * Counting forward from the last run, rather than back from now, is what\n * lets a job whose period is shorter than its grace be missed at all, and it\n * works for a cron that fires once a year or less.\n */\nexport function expectation(\n parsed: ParsedSchedule,\n lastRunAt: number | null,\n registeredAt: number,\n graceMs: number,\n): Expectation | null {\n let dueAt: number | null;\n if (parsed.kind === \"interval\") {\n dueAt = (lastRunAt ?? registeredAt) + parsed.everyMs!;\n } else if (lastRunAt === null) {\n dueAt = fireAfter(parsed, registeredAt - 1);\n } else {\n dueAt = dueAfterRun(parsed, lastRunAt);\n }\n return dueAt === null ? null : { dueAt, deadline: dueAt + graceMs };\n}\n\n/** The first fire that a run starting at `startedAt` does not cover. */\nfunction dueAfterRun(parsed: ParsedSchedule, startedAt: number): number | null {\n // A fire at or before the start is covered by the run itself.\n const next = fireAfter(parsed, startedAt);\n if (next === null) return null;\n const following = fireAfter(parsed, next);\n const covers = runCovers(startedAt, next, following) || inSpringForwardGap(parsed, startedAt, next);\n return covers ? following : next;\n}\n\n/**\n * Whether a run starting at `startedAt` covers the fire at `dueAt`. A minute\n * of slack before the tick absorbs schedulers that fire a touch early. When\n * the fire after `dueAt` is known, the slack is at most half the gap between\n * the two, so one run of an every-minute cron never covers two fires.\n */\nexport function runCovers(startedAt: number, dueAt: number, followingAt: number | null = null): boolean {\n const slack = followingAt === null ? EARLY_SLACK_MS : Math.min(EARLY_SLACK_MS, Math.floor((followingAt - dueAt) / 2));\n return startedAt >= dueAt - slack;\n}\n\n/**\n * On the night clocks spring forward, a fire whose local time does not exist\n * (02:30 when 02:00 jumps to 03:00) is moved by croner to the same distance\n * past the jump (03:30), while vixie cron runs it at the jump itself (03:00).\n * A run that starts at or after the jump, and before the first fire after\n * it when that fire lies within one gap of it, is taken to cover that fire,\n * so neither scheduler's run is reported as missed. A cron that really fires\n * at 03:30 that night is treated the same way, which only matters if it also\n * ran early by up to an hour.\n */\nfunction inSpringForwardGap(parsed: ParsedSchedule, startedAt: number, fireAt: number): boolean {\n const LOOKBACK = 3 * 3_600_000;\n const after = utcOffset(fireAt, parsed.timezone);\n const before = utcOffset(fireAt - LOOKBACK, parsed.timezone);\n const gap = after - before;\n if (gap <= 0) return false;\n // Find the jump: the first minute in the window with the later offset.\n let lo = fireAt - LOOKBACK;\n let hi = fireAt;\n while (hi - lo > 60_000) {\n const mid = lo + Math.floor((hi - lo) / 2);\n if (utcOffset(mid, parsed.timezone) === after) hi = mid;\n else lo = mid;\n }\n const jumpAt = Math.floor(hi / 60_000) * 60_000;\n if (fireAt - jumpAt >= gap || startedAt < jumpAt - EARLY_SLACK_MS || startedAt >= fireAt) return false;\n // Only the first fire after the jump can be a moved one; a cron that also\n // fires at the jump (every 10 minutes, say) was not moved at all.\n return fireAfter(parsed, jumpAt - 1) === fireAt;\n}\n\nconst formatters = new Map<string, Intl.DateTimeFormat>();\n\n/** Milliseconds the zone's wall clock is ahead of UTC at `at`. */\nfunction utcOffset(at: number, timezone: string | undefined): number {\n const key = timezone ?? \"\";\n let format = formatters.get(key);\n if (!format) {\n format = new Intl.DateTimeFormat(\"en-US\", {\n ...(timezone ? { timeZone: timezone } : {}),\n hourCycle: \"h23\",\n year: \"numeric\", month: \"numeric\", day: \"numeric\", hour: \"numeric\", minute: \"numeric\", second: \"numeric\",\n });\n formatters.set(key, format);\n }\n const parts: Record<string, number> = {};\n for (const part of format.formatToParts(new Date(at))) {\n if (part.type !== \"literal\") parts[part.type] = Number(part.value);\n }\n const wall = Date.UTC(parts.year!, parts.month! - 1, parts.day!, parts.hour!, parts.minute!, parts.second!);\n return wall - Math.floor(at / 1000) * 1000;\n}\n","export function percentile(values: number[], p: number): number | null {\n if (values.length === 0) return null;\n const sorted = [...values].sort((a, b) => a - b);\n const index = Math.min(sorted.length - 1, Math.max(0, Math.ceil((p / 100) * sorted.length) - 1));\n return sorted[index]!;\n}\n\nexport function median(values: number[]): number | null {\n if (values.length === 0) return null;\n const sorted = [...values].sort((a, b) => a - b);\n const mid = Math.floor(sorted.length / 2);\n return sorted.length % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;\n}\n","/**\n * Pure decisions about a job's health. Each function takes the current state\n * and returns the new state plus the alerts that should go out. Nothing here\n * touches a store or a network, which is what makes it testable.\n */\nimport { formatDuration } from \"./duration.js\";\nimport { parseDuration } from \"./duration.js\";\nimport { expectation, nextFire, parseSchedule } from \"./schedule.js\";\nimport { median, percentile } from \"./stats.js\";\nimport type {\n AlertDraft,\n BudgetBreach,\n Condition,\n JobDefinition,\n JobHealth,\n JobState,\n JobSummary,\n Run,\n StoredJob,\n StoredJobDefinition,\n} from \"./types.js\";\n\nexport type { AlertDraft, BudgetBreach };\n\nexport interface Evaluation {\n state: JobState;\n alerts: AlertDraft[];\n}\n\nexport const DEFAULT_GRACE_MS = 10 * 60_000;\nexport const DEFAULT_TIMEOUT_MS = 60 * 60_000;\n/** Runs faster than this are never called slow, whatever the baseline says. */\nexport const SLOW_FLOOR_MS = 10_000;\n/** How many earlier runs a baseline needs before it is trusted. */\nexport const BASELINE_MIN_RUNS = 5;\n/** How many successful runs a baseline looks at, and how many runs a summary covers. */\nexport const BASELINE_WINDOW = 20;\n\nexport function emptyState(job: string): JobState {\n return { job, open: {}, consecutiveFailures: 0, silencedUntil: null, lastAlertAt: null, pendingRecovery: [], undelivered: [] };\n}\n\n/** A stored state with every field present, or a fresh one. State written by an older version lacks the newer fields. */\nexport function normalizeState(state: JobState | null, job: string): JobState {\n if (!state) return emptyState(job);\n return {\n ...emptyState(job),\n ...state,\n open: { ...state.open },\n pendingRecovery: [...(state.pendingRecovery ?? [])],\n undelivered: [...(state.undelivered ?? [])],\n };\n}\n\nfunction cloneState(state: JobState): JobState {\n return normalizeState(state, state.job);\n}\n\nfunction openCondition(state: JobState, condition: Condition, now: number): boolean {\n if (state.open[condition] !== undefined) return false;\n state.open[condition] = now;\n return true;\n}\n\n/**\n * Every open condition has alerted, so closing one owes a recovered message.\n * It is remembered until a successful run leaves nothing open and sends it.\n */\nfunction closeCondition(state: JobState, condition: Condition): boolean {\n if (state.open[condition] === undefined) return false;\n delete state.open[condition];\n const pending = (state.pendingRecovery ??= []);\n if (!pending.includes(condition)) pending.push(condition);\n return true;\n}\n\nexport function openConditions(state: JobState): Condition[] {\n return Object.keys(state.open) as Condition[];\n}\n\nexport function graceMs(def: Pick<JobDefinition, \"grace\">): number {\n return def.grace === undefined ? DEFAULT_GRACE_MS : parseDuration(def.grace, \"grace\");\n}\n\nexport function timeoutMs(def: Pick<JobDefinition, \"timeout\">): number {\n return def.timeout === undefined ? DEFAULT_TIMEOUT_MS : parseDuration(def.timeout, \"timeout\");\n}\n\n/** Slow threshold for a successful run, or null when there is nothing to compare against yet. */\nexport function slowThreshold(def: Pick<JobDefinition, \"maxDuration\">, history: Run[]): { thresholdMs: number; basis: string } | null {\n if (def.maxDuration !== undefined) {\n return { thresholdMs: parseDuration(def.maxDuration, \"maxDuration\"), basis: \"maxDuration\" };\n }\n const durations = history\n .filter((r) => r.status === \"ok\" && r.durationMs !== null)\n .slice(0, BASELINE_WINDOW)\n .map((r) => r.durationMs!);\n if (durations.length < BASELINE_MIN_RUNS) return null;\n const p95 = percentile(durations, 95)!;\n return { thresholdMs: Math.max(2 * p95, SLOW_FLOOR_MS), basis: `twice the p95 of the last ${durations.length} runs (${formatDuration(p95)})` };\n}\n\nexport function budgetBreaches(def: Pick<JobDefinition, \"budget\">, run: Run, history: Run[]): BudgetBreach[] {\n const breaches: BudgetBreach[] = [];\n for (const [metric, value] of Object.entries(run.metrics)) {\n const ceiling = def.budget?.[metric];\n if (ceiling !== undefined) {\n if (value > ceiling) breaches.push({ metric, value, limit: ceiling, basis: \"budget\" });\n continue;\n }\n const past = history\n .filter((r) => r.status === \"ok\" && typeof r.metrics[metric] === \"number\")\n .slice(0, BASELINE_WINDOW)\n .map((r) => r.metrics[metric]!);\n if (past.length < BASELINE_MIN_RUNS) continue;\n const usual = median(past)!;\n if (usual > 0 && value > 3 * usual) {\n breaches.push({ metric, value, limit: 3 * usual, basis: `three times the usual ${formatNumber(usual)}` });\n }\n }\n return breaches;\n}\n\n/** Whether `history` (newest first) holds a full baseline window of successful runs. */\nexport function hasFullBaseline(history: Run[]): boolean {\n return history.filter((r) => r.status === \"ok\").length >= BASELINE_WINDOW;\n}\n\nexport function formatNumber(n: number): string {\n if (Number.isInteger(n)) return n.toLocaleString(\"en-US\");\n return n.toLocaleString(\"en-US\", { maximumFractionDigits: 4 });\n}\n\n/**\n * Called when a run starts. Missed and stuck are about the absence of a run,\n * so a run starting closes them without an alert; the recovered message\n * waits for a successful finish.\n */\nexport function onRunStart(state: JobState): JobState {\n const next = cloneState(state);\n closeCondition(next, \"missed\");\n closeCondition(next, \"stuck\");\n return next;\n}\n\n/**\n * Called when a run finishes with status ok, failed or timeout. `history` is\n * the job's earlier runs, newest first, not including this one.\n */\nexport function onRunFinish(\n def: JobDefinition | StoredJobDefinition,\n run: Run,\n state: JobState,\n history: Run[],\n now: number,\n): Evaluation {\n const next = cloneState(state);\n const alerts: AlertDraft[] = [];\n\n if (run.status === \"ok\") {\n next.consecutiveFailures = 0;\n closeCondition(next, \"missed\");\n closeCondition(next, \"stuck\");\n closeCondition(next, \"failed\");\n\n const slow = slowThreshold(def, history);\n if (slow && run.durationMs !== null && run.durationMs > slow.thresholdMs) {\n if (openCondition(next, \"slow\", now)) {\n alerts.push({ type: \"slow\", run, details: { durationMs: run.durationMs, thresholdMs: slow.thresholdMs, basis: slow.basis } });\n }\n } else {\n closeCondition(next, \"slow\");\n }\n\n const breaches = budgetBreaches(def, run, history);\n if (breaches.length > 0) {\n if (openCondition(next, \"over_budget\", now)) {\n alerts.push({ type: \"over_budget\", run, details: { breaches } });\n }\n } else {\n closeCondition(next, \"over_budget\");\n }\n\n const pending = next.pendingRecovery ?? [];\n if (pending.length > 0 && openConditions(next).length === 0) {\n alerts.push({ type: \"recovered\", run, details: { after: [...pending] } });\n next.pendingRecovery = [];\n }\n return { state: next, alerts };\n }\n\n // failed or timeout\n next.consecutiveFailures += 1;\n closeCondition(next, \"missed\");\n const threshold = Math.max(1, def.failuresBeforeAlert ?? 1);\n const condition = run.status === \"timeout\" ? \"stuck\" : \"failed\";\n if (next.consecutiveFailures >= threshold) {\n if (openCondition(next, condition, now)) {\n alerts.push({ type: condition, run, details: { consecutiveFailures: next.consecutiveFailures, threshold } });\n }\n }\n return { state: next, alerts };\n}\n\n/**\n * Called by check(). Decides whether the schedule has been missed: the run\n * the schedule wants next (see expectation()) has not started and its grace\n * has run out. `lastRun` is the most recent run of any status.\n */\nexport function onCheck(\n def: StoredJobDefinition,\n stored: StoredJob,\n lastRun: Run | null,\n state: JobState,\n now: number,\n): Evaluation & { nextExpectedAt: number | null; dueAt: number | null } {\n const next = cloneState(state);\n const alerts: AlertDraft[] = [];\n if (!def.schedule) return { state: next, alerts, nextExpectedAt: null, dueAt: null };\n\n const parsed = parseSchedule(def.schedule, def.timezone);\n const grace = graceMs(def);\n const lastRunAt = lastRun?.startedAt ?? null;\n const exp = expectation(parsed, lastRunAt, stored.createdAt, grace);\n const nextExpectedAt = parsed.kind === \"interval\" ? nextFire(parsed, stored.createdAt, lastRunAt) : nextFire(parsed, now, null);\n if (!exp) return { state: next, alerts, nextExpectedAt, dueAt: null };\n\n // An interval's next run is due a period after the last one started. If that\n // run is still going, the job is busy, not late; stuck covers one that never ends.\n if (parsed.kind === \"interval\" && lastRun?.status === \"running\") {\n return { state: next, alerts, nextExpectedAt, dueAt: exp.dueAt };\n }\n\n if (now > exp.deadline) {\n if (openCondition(next, \"missed\", now)) {\n alerts.push({ type: \"missed\", run: lastRun, details: { dueAt: exp.dueAt, deadline: exp.deadline, graceMs: grace, lastRunAt } });\n }\n } else {\n // A run has started since it opened, or the grace was widened.\n closeCondition(next, \"missed\");\n }\n return { state: next, alerts, nextExpectedAt, dueAt: exp.dueAt };\n}\n\n/** Whether a running run has gone on longer than the job's timeout. */\nexport function isStuck(def: Pick<JobDefinition, \"timeout\">, run: Run, now: number): boolean {\n return run.status === \"running\" && now - run.startedAt > timeoutMs(def);\n}\n\n/**\n * While a job is silenced nothing new is recorded as an incident: conditions\n * may close (so a job that recovered during the silence shows as healthy) but\n * none may open, so the first problem after the silence ends alerts normally.\n */\nexport function muteOpens(previous: JobState, next: JobState): JobState {\n const muted = cloneState(next);\n for (const condition of openConditions(muted)) {\n if (previous.open[condition] === undefined) delete muted.open[condition];\n }\n return muted;\n}\n\nexport function isSilenced(state: JobState, now: number): boolean {\n return state.silencedUntil !== null && state.silencedUntil > now;\n}\n\n/** How a job looks at a glance. Silence wins, then stuck, failing and late. */\nexport function jobHealth(def: Pick<JobDefinition, \"timeout\">, lastRun: Run | null, state: JobState, now: number): JobHealth {\n const open = openConditions(state);\n if (isSilenced(state, now)) return \"silenced\";\n if (open.includes(\"stuck\") || (lastRun && isStuck(def, lastRun, now))) return \"stuck\";\n if (open.includes(\"failed\") || lastRun?.status === \"failed\" || lastRun?.status === \"timeout\") return \"failing\";\n if (open.includes(\"missed\")) return \"late\";\n if (!lastRun) return \"never_ran\";\n return \"healthy\";\n}\n\n/**\n * A job's summary from its most recent runs (newest first; the first\n * BASELINE_WINDOW are used) and its state. Stats cover runs of any status;\n * the percentiles are over the successful ones among them.\n */\nexport function summarize(stored: StoredJob, recent: Run[], state: JobState, nextExpectedAt: number | null, now: number): JobSummary {\n const window = recent.slice(0, BASELINE_WINDOW);\n const lastRun = window[0] ?? null;\n const finished = window.filter((r) => r.status !== \"running\");\n const okDurations = window.filter((r) => r.status === \"ok\" && r.durationMs !== null).map((r) => r.durationMs!);\n return {\n name: stored.name,\n definition: stored.definition,\n health: jobHealth(stored.definition, lastRun, state, now),\n open: openConditions(state),\n lastRun,\n nextExpectedAt,\n consecutiveFailures: state.consecutiveFailures,\n silencedUntil: state.silencedUntil,\n stats: {\n runs: finished.length,\n okRate: finished.length === 0 ? 1 : finished.filter((r) => r.status === \"ok\").length / finished.length,\n p50Ms: percentile(okDurations, 50),\n p95Ms: percentile(okDurations, 95),\n },\n };\n}\n","import { formatDuration, formatRelative } from \"./duration.js\";\nimport { formatNumber } from \"./evaluate.js\";\nimport type { Alert, AlertDraft, StoredJobDefinition } from \"./types.js\";\n\nfunction when(at: number | null | undefined, now: number): string {\n if (at === null || at === undefined) return \"never\";\n return `${new Date(at).toISOString().replace(\"T\", \" \").slice(0, 19)} UTC (${formatRelative(at, now)})`;\n}\n\nfunction firstLines(text: string | null, n: number): string {\n if (!text) return \"\";\n return text.split(\"\\n\").slice(0, n).join(\"\\n\");\n}\n\nfunction tail(text: string | null, n: number): string {\n if (!text) return \"\";\n const lines = text.trimEnd().split(\"\\n\");\n return lines.slice(Math.max(0, lines.length - n)).join(\"\\n\");\n}\n\n/** \"Error: x\" for a bare message, but not \"Error: TypeError: x\" for one that already names itself. */\nfunction errorLine(error: string): string {\n const text = firstLines(error, 4);\n return /^[A-Za-z_$][\\w$]*: /.test(text) ? text : `Error: ${text}`;\n}\n\n/** Turns a draft into the title and message every channel shows. */\nexport function composeAlert(draft: AlertDraft, def: StoredJobDefinition, now: number): Alert {\n const name = def.name;\n const run = draft.run;\n let title: string;\n const lines: string[] = [];\n\n switch (draft.type) {\n case \"missed\": {\n const d = draft.details;\n title = `${name} missed its scheduled run`;\n lines.push(`Due ${when(d.dueAt, now)}, and no run had started by ${when(d.deadline, now)} (grace ${formatDuration(d.graceMs)}).`);\n lines.push(`Schedule: ${def.schedule}${def.timezone ? ` (${def.timezone})` : \"\"}.`);\n lines.push(`Last run: ${run ? `${run.status} ${when(run.startedAt, now)}` : \"never\"}.`);\n break;\n }\n case \"failed\": {\n title = `${name} failed`;\n const n = draft.details.consecutiveFailures;\n if (n > 1) lines.push(`${n} consecutive failures.`);\n if (run) {\n lines.push(`Started ${when(run.startedAt, now)}${run.durationMs !== null ? `, ran ${formatDuration(run.durationMs)}` : \"\"}.`);\n if (run.error) lines.push(errorLine(run.error));\n const out = tail(run.output, 8);\n if (out) lines.push(`Output (tail):\\n${out}`);\n }\n break;\n }\n case \"stuck\": {\n title = `${name} is stuck`;\n if (run) {\n lines.push(`Started ${when(run.startedAt, now)} and never reported finishing. Marked as timed out after ${formatDuration(run.durationMs ?? now - run.startedAt)}.`);\n const out = tail(run.output, 8);\n if (out) lines.push(`Output so far (tail):\\n${out}`);\n }\n lines.push(`If the process was killed mid-run (a serverless timeout, a deploy), this is what that looks like.`);\n break;\n }\n case \"slow\": {\n const d = draft.details;\n title = `${name} was slow`;\n lines.push(`Took ${formatDuration(d.durationMs)}; the limit is ${formatDuration(d.thresholdMs)} (${d.basis}).`);\n if (run) lines.push(`Started ${when(run.startedAt, now)}.`);\n break;\n }\n case \"over_budget\": {\n title = `${name} went over budget`;\n for (const b of draft.details.breaches) {\n lines.push(`${b.metric}: ${formatNumber(b.value)}, limit ${formatNumber(b.limit)} (${b.basis}).`);\n }\n if (run) lines.push(`Started ${when(run.startedAt, now)}.`);\n break;\n }\n case \"recovered\": {\n title = `${name} recovered`;\n const after = draft.details.after.map((c) => c.replace(\"_\", \" \")).join(\", \");\n lines.push(`A run ${run ? when(run.startedAt, now) : \"just now\"} succeeded${after ? ` after: ${after}` : \"\"}.`);\n if (run?.durationMs !== null && run?.durationMs !== undefined) lines.push(`Ran ${formatDuration(run.durationMs)}.`);\n break;\n }\n }\n\n return { ...draft, job: name, definition: def, title, message: lines.join(\"\\n\"), at: now };\n}\n","export function json(body: unknown, status = 200, headers: Record<string, string> = {}): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"content-type\": \"application/json; charset=utf-8\", \"cache-control\": \"no-store\", ...headers },\n });\n}\n\n/** Compares two secrets without stopping at the first differing character. */\nexport function constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n","/** Output is capped so a chatty job cannot fill the store. The tail is kept. */\nexport const OUTPUT_CAP = 16 * 1024;\n\nexport function capOutput(text: string): string {\n if (text.length <= OUTPUT_CAP) return text;\n return \"[earlier output trimmed]\\n\" + text.slice(text.length - OUTPUT_CAP);\n}\n\n/** \"Name: message\" and the first five stack frames, capped like output. */\nexport function errorMessage(error: unknown): string {\n return capOutput(describeError(error));\n}\n\nfunction describeError(error: unknown): string {\n if (error instanceof Error) {\n // The stack repeats the header (over several lines when the message has\n // newlines), so take only its frames.\n const frames = (error.stack ?? \"\").split(\"\\n\").filter((line) => /^\\s+at /.test(line)).slice(0, 5);\n return `${error.name}: ${error.message}${frames.length ? `\\n${frames.join(\"\\n\")}` : \"\"}`;\n }\n if (typeof error === \"string\") return error;\n try {\n return JSON.stringify(error) ?? String(error);\n } catch {\n return String(error);\n }\n}\n\nconst REDACTED = \"[redacted]\";\n\n// Bounded quantifiers throughout, so a long line cannot make these backtrack.\nconst SECRET_PATTERNS: [RegExp, string | ((match: string, ...groups: string[]) => string)][] = [\n // password=..., API_KEY: ..., \"client_secret\": \"...\", TOKEN='...', token=... (but not max_tokens: 800).\n // A quoted value is blanked to its closing quote, spaces and all, and keeps its quotes.\n [\n /\\b([A-Za-z0-9_-]{0,40}(?:secret|token|passw(?:or)?d|pwd|api[_-]?key|access[_-]?key|private[_-]?key|credential)[A-Za-z0-9_-]{0,40}(?<![Tt][Oo][Kk][Ee][Nn][Ss])\"?\\s{0,3}[=:]\\s{0,3})(?:(\")[^\"\\n]{1,4096}\"|(')[^'\\n]{1,4096}'|[\"']?[^\\s\"',;&]{1,4096})/gi,\n (_match, name: string, double?: string, single?: string) => {\n const quote = double ?? single ?? \"\";\n return `${name}${quote}${REDACTED}${quote}`;\n },\n ],\n // Credentials inside a URL: postgres://user:password@host\n [/(\\b[a-z][a-z0-9+.-]{0,30}:\\/\\/[^\\s/:@]{0,256}:)[^\\s/@]{1,256}@/gi, `$1${REDACTED}@`],\n // Authorization: Bearer <token>\n [/\\b(Bearer\\s{1,3})[A-Za-z0-9._~+/=-]{8,4096}/g, `$1${REDACTED}`],\n // Well-known token shapes: AWS, GitHub, Slack, Stripe, Anthropic and OpenAI style keys.\n [/\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b/g, REDACTED],\n [/\\b(?:gh[pousr]_[A-Za-z0-9]{30,255}|github_pat_[A-Za-z0-9_]{20,255})\\b/g, REDACTED],\n [/\\bxox[abposr]-[A-Za-z0-9-]{10,255}/g, REDACTED],\n [/\\b[rsp]k_(?:live|test)_[A-Za-z0-9]{10,255}\\b/g, REDACTED],\n [/\\bsk-[A-Za-z0-9_-]{20,255}/g, REDACTED],\n];\n\n/**\n * The default `redact`: blanks values that look like secrets (key=value pairs\n * with secret-ish names, URL credentials, bearer tokens and well-known token\n * formats) before output or an error is stored, shown or sent anywhere.\n */\nexport function redactSecrets(text: string): string {\n let out = text;\n for (const [pattern, replacement] of SECRET_PATTERNS) out = out.replace(pattern, replacement as string);\n return out;\n}\n","import { capOutput, OUTPUT_CAP } from \"./output.js\";\nimport type { Run } from \"./types.js\";\n\n/** What a job function receives. */\nexport interface JobContext {\n readonly name: string;\n readonly runId: string;\n readonly startedAt: number;\n /** Aborts when the job's timeout elapses. Honour it if the work can stop. */\n readonly signal: AbortSignal;\n /** Append a line of output. Kept with the run, capped at 16 KB, shown in alerts and the dashboard. */\n log(...parts: unknown[]): void;\n /** Report a number for this run: tokens, cost, rows, anything. Watched against budgets and baselines. */\n metric(name: string, value: number): void;\n metrics(values: Record<string, number>): void;\n}\n\nexport interface RunRecorder {\n context: JobContext;\n output(): string | null;\n /**\n * What an expect rule is checked against: everything logged, or when that\n * ran long, the first 16 KB and the last 16 KB. The stored output keeps only\n * the tail, so a \"done\" line printed early would otherwise be lost.\n */\n expectText(): string | null;\n metrics(): Record<string, number>;\n abort(): void;\n}\n\nfunction stringify(part: unknown): string {\n if (typeof part === \"string\") return part;\n if (part instanceof Error) return `${part.name}: ${part.message}`;\n try {\n return JSON.stringify(part);\n } catch {\n return String(part);\n }\n}\n\nexport function createRecorder(run: Run): RunRecorder {\n const lines: string[] = [];\n let size = 0;\n const head: string[] = [];\n let headSize = 0;\n let dropped = false;\n const metrics: Record<string, number> = {};\n const controller = new AbortController();\n\n const context: JobContext = {\n name: run.job,\n runId: run.id,\n startedAt: run.startedAt,\n signal: controller.signal,\n log(...parts) {\n const line = parts.map(stringify).join(\" \");\n if (headSize < OUTPUT_CAP) {\n head.push(line);\n headSize += line.length + 1;\n }\n lines.push(line);\n size += line.length + 1;\n // Drop from the front once well past the cap; capOutput trims exactly at the end.\n while (size > 64 * 1024 && lines.length > 1) {\n size -= lines.shift()!.length + 1;\n dropped = true;\n }\n },\n metric(name, value) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(`metric \"${name}\" must be a finite number`);\n }\n metrics[name] = value;\n },\n metrics(values) {\n for (const [k, v] of Object.entries(values)) context.metric(k, v);\n },\n };\n\n return {\n context,\n output: () => (lines.length === 0 ? null : capOutput(lines.join(\"\\n\"))),\n expectText: () => {\n if (lines.length === 0) return null;\n const all = lines.join(\"\\n\");\n if (!dropped && all.length <= 2 * OUTPUT_CAP) return all;\n return head.join(\"\\n\").slice(0, OUTPUT_CAP) + \"\\n\" + all.slice(-OUTPUT_CAP);\n },\n metrics: () => ({ ...metrics }),\n abort: () => controller.abort(),\n };\n}\n","import type { JobDefinition, StoredJobDefinition } from \"./types.js\";\n\n/** A definition as a store can hold it: `expect` becomes a description. */\nexport function toStored(def: JobDefinition): StoredJobDefinition {\n const { expect, ...rest } = def;\n const stored: StoredJobDefinition = { ...rest };\n if (expect !== undefined) {\n stored.expect =\n typeof expect === \"string\" ? `contains ${JSON.stringify(expect)}`\n : expect instanceof RegExp ? `matches ${expect.toString()}`\n : \"custom function\";\n }\n return stored;\n}\n\nexport function checkExpectation(expect: JobDefinition[\"expect\"], output: string | null): string | null {\n if (expect === undefined) return null;\n const text = output ?? \"\";\n if (typeof expect === \"string\") {\n return text.includes(expect) ? null : `Output did not contain ${JSON.stringify(expect)}`;\n }\n if (expect instanceof RegExp) {\n expect.lastIndex = 0; // a /g or /y pattern would otherwise resume where the last run stopped\n return expect.test(text) ? null : `Output did not match ${expect.toString()}`;\n }\n let ok = false;\n try {\n ok = expect(text);\n } catch (error) {\n return `Output check threw: ${(error as Error).message}`;\n }\n return ok ? null : \"Output did not pass the expect() check\";\n}\n","import { formatDuration, formatRelative } from \"../duration.js\";\nimport type { JobSummary, Run } from \"../types.js\";\n\nexport function escapeHtml(value: unknown): string {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nconst h = escapeHtml;\n\nconst CSS = `\n:root{--bg:#fbfbf9;--fg:#1b1b18;--muted:#6b6b64;--line:#e6e5df;--card:#fff;--ok:#1f8a4c;--warn:#b7791f;--bad:#c62828;--info:#2b5fb3;--pill:#f1f0ea;--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;--sans:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Inter,Roboto,sans-serif}\n@media(prefers-color-scheme:dark){:root{--bg:#121311;--fg:#ecece6;--muted:#9a9a91;--line:#2a2b27;--card:#1a1b18;--pill:#24251f}}\n*{box-sizing:border-box}html{-webkit-text-size-adjust:100%}\nbody{margin:0;background:var(--bg);color:var(--fg);font:15px/1.5 var(--sans)}\na{color:inherit}main{max-width:1080px;margin:0 auto;padding:24px 16px 64px}\nheader{display:flex;align-items:baseline;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:20px}\nheader h1{font-size:18px;margin:0;letter-spacing:-.01em}header h1 a{text-decoration:none}\nheader .meta{color:var(--muted);font-size:13px}\n.card{background:var(--card);border:1px solid var(--line);border-radius:10px;overflow:hidden}\ntable{width:100%;border-collapse:collapse;font-size:14px}\nth{text-align:left;font-weight:600;color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 12px;border-bottom:1px solid var(--line);white-space:nowrap}\ntd{padding:10px 12px;border-bottom:1px solid var(--line);vertical-align:top}\ntr:last-child td{border-bottom:0}\n.name{font-weight:600;white-space:nowrap}.name a{text-decoration:none}.name a:hover{text-decoration:underline}\n.mono{font-family:var(--mono);font-size:13px}.muted{color:var(--muted)}.nowrap{white-space:nowrap}\n.pill{display:inline-flex;align-items:center;gap:6px;padding:2px 9px;border-radius:999px;background:var(--pill);font-size:12px;font-weight:600;white-space:nowrap}\n.pill::before{content:\"\";width:7px;height:7px;border-radius:50%;background:currentColor}\n.ok{color:var(--ok)}.warn{color:var(--warn)}.bad{color:var(--bad)}.info{color:var(--info)}.mutedpill{color:var(--muted)}\n.spark{display:block}\nform.inline{display:inline}\nbutton,select{font:inherit;font-size:13px;padding:5px 10px;border:1px solid var(--line);border-radius:7px;background:var(--card);color:var(--fg);cursor:pointer}\nbutton:hover{border-color:var(--muted)}\n.actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}\n.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin:0 0 20px}\n.stat{padding:12px 14px}.stat .k{font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}.stat .v{font-size:20px;font-weight:600;margin-top:2px}\npre{margin:0;padding:10px 12px;background:var(--pill);border-radius:8px;font:12.5px/1.45 var(--mono);white-space:pre-wrap;word-break:break-word;max-height:320px;overflow:auto}\ndetails summary{cursor:pointer;color:var(--muted);font-size:13px}details{margin-top:6px}\ndetails.confirm{margin:0}details.confirm summary{list-style:none;display:inline-block;font-size:13px;padding:5px 10px;border:1px solid var(--line);border-radius:7px;background:var(--card);color:var(--fg)}\ndetails.confirm summary::-webkit-details-marker{display:none}details.confirm[open] summary{border-color:var(--muted)}details.confirm form{margin-left:8px;font-size:13px}\n.empty{padding:40px 16px;text-align:center;color:var(--muted)}\ndl{display:grid;grid-template-columns:max-content 1fr;gap:6px 16px;margin:0;padding:14px 16px;font-size:14px}dt{color:var(--muted)}dd{margin:0}\nfooter{margin-top:28px;color:var(--muted);font-size:12px}\n@media(max-width:720px){.hide-sm{display:none}main{padding:16px 16px 48px}}\n`;\n\nexport function layout(title: string, body: string, options: { refresh?: number } = {}): string {\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<meta name=\"robots\" content=\"noindex,nofollow\">\n${options.refresh ? `<meta http-equiv=\"refresh\" content=\"${options.refresh}\">` : \"\"}\n<title>${h(title)}</title>\n<style>${CSS}</style>\n</head>\n<body><main>${body}</main></body>\n</html>`;\n}\n\nfunction healthPill(job: JobSummary): string {\n const map: Record<JobSummary[\"health\"], [string, string]> = {\n healthy: [\"ok\", \"healthy\"],\n late: [\"warn\", \"late\"],\n failing: [\"bad\", \"failing\"],\n stuck: [\"bad\", \"stuck\"],\n silenced: [\"mutedpill\", \"silenced\"],\n never_ran: [\"info\", \"never ran\"],\n };\n const [cls, label] = map[job.health];\n const extras = job.open.filter((c) => ![\"missed\", \"failed\", \"stuck\"].includes(c)).map((c) => c.replace(\"_\", \" \"));\n return `<span class=\"pill ${cls}\">${label}</span>${extras.length ? ` <span class=\"pill warn\">${h(extras.join(\", \"))}</span>` : \"\"}`;\n}\n\nfunction runPill(run: Run): string {\n const cls = run.status === \"ok\" ? \"ok\" : run.status === \"running\" ? \"info\" : \"bad\";\n return `<span class=\"pill ${cls}\">${h(run.status)}</span>`;\n}\n\nfunction sparkline(runs: Run[]): string {\n const points = [...runs].reverse().filter((r) => r.durationMs !== null).slice(-20);\n if (points.length < 2) return \"\";\n const w = 96, hgt = 22;\n const max = Math.max(...points.map((r) => r.durationMs!), 1);\n const step = w / (points.length - 1);\n const path = points.map((r, i) => `${i === 0 ? \"M\" : \"L\"}${(i * step).toFixed(1)},${(hgt - 2 - (r.durationMs! / max) * (hgt - 4)).toFixed(1)}`).join(\" \");\n const dots = points.map((r, i) => r.status === \"ok\" ? \"\" : `<circle cx=\"${(i * step).toFixed(1)}\" cy=\"${(hgt - 2 - (r.durationMs! / max) * (hgt - 4)).toFixed(1)}\" r=\"2.2\" fill=\"var(--bad)\"/>`).join(\"\");\n return `<svg class=\"spark\" width=\"${w}\" height=\"${hgt}\" viewBox=\"0 0 ${w} ${hgt}\" aria-hidden=\"true\"><path d=\"${path}\" fill=\"none\" stroke=\"var(--muted)\" stroke-width=\"1.5\"/>${dots}</svg>`;\n}\n\nfunction stamp(at: number | null, now: number): string {\n if (at === null) return `<span class=\"muted\">never</span>`;\n const iso = new Date(at).toISOString().replace(\"T\", \" \").slice(0, 19);\n return `<span class=\"nowrap\" title=\"${iso} UTC\">${h(formatRelative(at, now))}</span>`;\n}\n\nexport function dashboardPage(jobs: JobSummary[], runsByJob: Map<string, Run[]>, now: number, base: string, checkedAt: number | null): string {\n const rows = jobs.map((job) => {\n const last = job.lastRun;\n return `<tr>\n<td class=\"name\"><a href=\"${h(base)}/jobs/${encodeURIComponent(job.name)}\">${h(job.name)}</a>${job.definition.description ? `<div class=\"muted\" style=\"font-weight:400;font-size:13px;white-space:normal\">${h(job.definition.description)}</div>` : \"\"}</td>\n<td>${healthPill(job)}</td>\n<td class=\"mono nowrap\">${h(job.definition.schedule ?? \"\")}<span class=\"muted\">${job.definition.schedule ? \"\" : \"no schedule\"}</span></td>\n<td class=\"nowrap\">${last ? `${runPill(last)} ${stamp(last.startedAt, now)}${last.durationMs !== null ? ` <span class=\"muted\">${h(formatDuration(last.durationMs))}</span>` : \"\"}` : `<span class=\"muted\">never</span>`}</td>\n<td class=\"nowrap hide-sm\">${stamp(job.nextExpectedAt, now)}</td>\n<td class=\"hide-sm\">${sparkline(runsByJob.get(job.name) ?? [])}</td>\n</tr>`;\n }).join(\"\\n\");\n\n const body = `\n<header>\n <h1><a href=\"${h(base)}/\">CronWatch</a></h1>\n <div class=\"actions\">\n <span class=\"meta\">${jobs.length} job${jobs.length === 1 ? \"\" : \"s\"}${checkedAt ? `, checked ${h(formatRelative(checkedAt, now))}` : \"\"}</span>\n <form class=\"inline\" method=\"post\" action=\"${h(base)}/check\"><button type=\"submit\">Run check now</button></form>\n </div>\n</header>\n<div class=\"card\">\n${jobs.length === 0 ? `<div class=\"empty\">No jobs yet. Declare one with <code class=\"mono\">cw.job(\"name\", { schedule: \"0 2 * * *\" })</code> and run it once.</div>` : `<table>\n<thead><tr><th>Job</th><th>Health</th><th>Schedule</th><th>Last run</th><th class=\"hide-sm\">Next due</th><th class=\"hide-sm\">Durations</th></tr></thead>\n<tbody>${rows}</tbody></table>`}\n</div>\n<footer>Refreshes every minute. <a href=\"${h(base)}/api/jobs\">JSON</a></footer>`;\n return layout(\"CronWatch\", body, { refresh: 60 });\n}\n\nexport function jobPage(job: JobSummary, runs: Run[], now: number, base: string): string {\n const d = job.definition;\n const okRate = `${Math.round(job.stats.okRate * 100)}%`;\n const runRows = runs.map((run) => {\n const detail = [\n run.error ? `<details open><summary>error</summary><pre>${h(run.error)}</pre></details>` : \"\",\n run.output ? `<details${run.status === \"ok\" ? \"\" : \" open\"}><summary>output</summary><pre>${h(run.output)}</pre></details>` : \"\",\n ].join(\"\");\n const metrics = Object.entries(run.metrics).map(([k, v]) => `<span class=\"pill mutedpill\">${h(k)} ${h(Number.isInteger(v) ? v : v.toFixed(4))}</span>`).join(\" \");\n return `<tr>\n<td class=\"nowrap\">${runPill(run)}</td>\n<td class=\"nowrap\">${stamp(run.startedAt, now)}</td>\n<td class=\"nowrap\">${run.durationMs !== null ? h(formatDuration(run.durationMs)) : `<span class=\"muted\">running</span>`}</td>\n<td class=\"hide-sm\">${metrics}</td>\n<td class=\"mono hide-sm muted\">${h(run.trigger)}</td>\n</tr>${detail ? `<tr><td colspan=\"5\" style=\"padding-top:0\">${detail}</td></tr>` : \"\"}`;\n }).join(\"\\n\");\n\n const silenced = job.silencedUntil !== null && job.silencedUntil > now;\n const body = `\n<header>\n <h1><a href=\"${h(base)}/\">CronWatch</a> <span class=\"muted\">/</span> ${h(job.name)}</h1>\n <div class=\"actions\">\n ${healthPill(job)}\n ${silenced\n ? `<form class=\"inline\" method=\"post\" action=\"${h(base)}/jobs/${encodeURIComponent(job.name)}/unsilence\"><button type=\"submit\">Unsilence (until ${h(formatRelative(job.silencedUntil!, now))})</button></form>`\n : `<form class=\"inline\" method=\"post\" action=\"${h(base)}/jobs/${encodeURIComponent(job.name)}/silence\"><select name=\"for\"><option value=\"1h\">1 hour</option><option value=\"4h\">4 hours</option><option value=\"1d\">1 day</option><option value=\"7d\">1 week</option></select> <button type=\"submit\">Silence</button></form>`}\n <details class=\"confirm\"><summary>Forget</summary><form class=\"inline\" method=\"post\" action=\"${h(base)}/jobs/${encodeURIComponent(job.name)}/forget\"><span class=\"muted\">Remove this job and its runs from the store?</span> <button type=\"submit\">Forget</button></form></details>\n </div>\n</header>\n<div class=\"grid\">\n <div class=\"card stat\"><div class=\"k\">Last run</div><div class=\"v\">${job.lastRun ? h(formatRelative(job.lastRun.startedAt, now)) : \"never\"}</div></div>\n <div class=\"card stat\"><div class=\"k\">Next due</div><div class=\"v\">${job.nextExpectedAt ? h(formatRelative(job.nextExpectedAt, now)) : \"no schedule\"}</div></div>\n <div class=\"card stat\"><div class=\"k\">Success, last ${h(job.stats.runs)}</div><div class=\"v\">${h(okRate)}</div></div>\n <div class=\"card stat\"><div class=\"k\">p50 / p95</div><div class=\"v\">${job.stats.p50Ms !== null ? h(formatDuration(job.stats.p50Ms)) : \"?\"} <span class=\"muted\">/</span> ${job.stats.p95Ms !== null ? h(formatDuration(job.stats.p95Ms)) : \"?\"}</div></div>\n</div>\n<div class=\"card\" style=\"margin-bottom:20px\">\n<dl>\n <dt>Schedule</dt><dd class=\"mono\">${d.schedule ? h(d.schedule) + (d.timezone ? ` <span class=\"muted\">${h(d.timezone)}</span>` : \"\") : `<span class=\"muted\">none</span>`}</dd>\n <dt>Grace</dt><dd class=\"mono\">${h(d.grace ?? \"10m\")}</dd>\n <dt>Timeout</dt><dd class=\"mono\">${h(d.timeout ?? \"1h\")}</dd>\n ${d.maxDuration ? `<dt>Max duration</dt><dd class=\"mono\">${h(d.maxDuration)}</dd>` : \"\"}\n ${d.budget ? `<dt>Budget</dt><dd class=\"mono\">${h(Object.entries(d.budget).map(([k, v]) => `${k} ≤ ${v}`).join(\", \"))}</dd>` : \"\"}\n ${d.expect ? `<dt>Expect</dt><dd class=\"mono\">${h(d.expect)}</dd>` : \"\"}\n ${d.failuresBeforeAlert && d.failuresBeforeAlert > 1 ? `<dt>Alert after</dt><dd>${h(d.failuresBeforeAlert)} consecutive failures</dd>` : \"\"}\n ${d.description ? `<dt>Description</dt><dd>${h(d.description)}</dd>` : \"\"}\n ${d.tags?.length ? `<dt>Tags</dt><dd>${d.tags.map((t) => `<span class=\"pill mutedpill\">${h(t)}</span>`).join(\" \")}</dd>` : \"\"}\n ${job.open.length ? `<dt>Open</dt><dd>${job.open.map((c) => `<span class=\"pill warn\">${h(c.replace(\"_\", \" \"))}</span>`).join(\" \")}</dd>` : \"\"}\n ${job.consecutiveFailures > 0 ? `<dt>Consecutive failures</dt><dd>${h(job.consecutiveFailures)}</dd>` : \"\"}\n</dl>\n</div>\n<div class=\"card\">\n${runs.length === 0 ? `<div class=\"empty\">No runs yet.</div>` : `<table>\n<thead><tr><th>Status</th><th>Started</th><th>Duration</th><th class=\"hide-sm\">Metrics</th><th class=\"hide-sm\">Trigger</th></tr></thead>\n<tbody>${runRows}</tbody></table>`}\n</div>\n<footer><a href=\"${h(base)}/api/jobs/${encodeURIComponent(job.name)}\">JSON</a></footer>`;\n return layout(`${job.name}: CronWatch`, body, { refresh: 60 });\n}\n\nexport function messagePage(title: string, message: string, base: string): string {\n return layout(title, `<header><h1><a href=\"${h(base)}/\">CronWatch</a></h1></header><div class=\"card\"><div class=\"empty\"><strong>${h(title)}</strong><br>${h(message)}</div></div>`);\n}\n","import { createHash } from \"node:crypto\";\nimport type { CronWatch } from \"../client.js\";\nimport { constantTimeEqual, json } from \"../http.js\";\nimport { parseDuration } from \"../duration.js\";\nimport type { Duration, Run } from \"../types.js\";\nimport { dashboardPage, jobPage, messagePage } from \"./html.js\";\n\nexport interface RoutesOptions {\n /**\n * Required to reach anything. Send it as `Authorization: Bearer <token>`,\n * or open the dashboard once with `?token=<token>` and a cookie is set.\n * Defaults to process.env.CRONWATCH_TOKEN; an empty string counts as unset.\n * With no token, the routes answer only requests to localhost while NODE_ENV\n * is \"development\" or \"test\", and 503 otherwise. Pass `null` to opt out and serve them\n * open everywhere, for example behind your own auth.\n *\n * The check endpoint (/api/check) also accepts the client's cronSecret, so\n * a platform cron that sends `Authorization: Bearer <CRON_SECRET>` can\n * trigger checks without knowing the dashboard token.\n */\n token?: string | null;\n /** Where the routes are mounted, so links resolve. Default \"/cronwatch\". */\n basePath?: string;\n}\n\nexport type FetchHandler = (request: Request) => Promise<Response>;\n\nexport interface Routes {\n handler: FetchHandler;\n GET: FetchHandler;\n POST: FetchHandler;\n DELETE: FetchHandler;\n}\n\nconst COOKIE = \"cronwatch_token\";\n\n/** The cookie holds a digest of the token, so a leaked cookie does not reveal the bearer token itself. */\nfunction cookieValue(token: string): string {\n return createHash(\"sha256\").update(`cronwatch-cookie:${token}`).digest(\"hex\");\n}\n\nconst LOOPBACK = new Set([\"localhost\", \"127.0.0.1\", \"[::1]\"]);\nconst DEFAULT_RUNS = 20;\nconst MAX_RUNS = 500;\n\nconst CSP = \"default-src 'none'; style-src 'unsafe-inline'; img-src 'self' data:; form-action 'self'; frame-ancestors 'none'; base-uri 'none'\";\n// same-origin rather than no-referrer: under no-referrer browsers send\n// `Origin: null` on form posts, which the CSRF check would refuse, and the\n// forms redirect back to the page named by the same-origin Referer.\nconst SECURITY_HEADERS = { \"x-content-type-options\": \"nosniff\", \"referrer-policy\": \"same-origin\", \"x-robots-tag\": \"noindex\" };\n\nfunction safeDecode(value: string): string | null {\n try {\n return decodeURIComponent(value);\n } catch {\n return null;\n }\n}\n\nfunction readCookie(request: Request, name: string): string | null {\n const header = request.headers.get(\"cookie\");\n if (!header) return null;\n for (const part of header.split(\";\")) {\n const [k, ...rest] = part.trim().split(\"=\");\n // A malformed escape counts as no cookie.\n if (k === name) return safeDecode(rest.join(\"=\"));\n }\n return null;\n}\n\nfunction stripBase(pathname: string, base: string): string {\n let path = pathname.startsWith(base) ? pathname.slice(base.length) : pathname;\n if (path === \"\") path = \"/\";\n if (path.length > 1 && path.endsWith(\"/\")) path = path.slice(0, -1);\n return path;\n}\n\nasync function readBody(request: Request): Promise<Record<string, string>> {\n const type = request.headers.get(\"content-type\") ?? \"\";\n try {\n if (type.includes(\"application/json\")) {\n const data = await request.json();\n return typeof data === \"object\" && data !== null ? Object.fromEntries(Object.entries(data).map(([k, v]) => [k, String(v)])) : {};\n }\n if (type.includes(\"application/x-www-form-urlencoded\") || type.includes(\"multipart/form-data\")) {\n const form = await request.formData();\n const out: Record<string, string> = {};\n for (const [k, v] of form.entries()) out[k] = String(v);\n return out;\n }\n } catch {\n return {};\n }\n return {};\n}\n\n/**\n * A browser attaches Origin or Sec-Fetch-Site to a cross-site form post, and\n * a page cannot forge either. Non-browser clients send neither.\n */\nfunction crossSite(request: Request, url: URL): boolean {\n const origin = request.headers.get(\"origin\");\n if (origin !== null && origin !== url.origin) return true;\n const site = request.headers.get(\"sec-fetch-site\");\n return site !== null && site !== \"same-origin\" && site !== \"none\";\n}\n\n/** Absent means one hour; a number or numeric string is milliseconds. Throws on anything else. */\nfunction silenceDuration(value: string | null | undefined): Duration {\n if (value === undefined || value === null) return \"1h\";\n const text = value.trim();\n const duration: Duration = /^\\d+(\\.\\d+)?$/.test(text) ? Number(text) : text;\n parseDuration(duration, \"silence duration\");\n return duration;\n}\n\nfunction runsLimit(value: string | null): number {\n const n = value === null || value.trim() === \"\" ? NaN : Math.trunc(Number(value));\n return Number.isFinite(n) ? Math.min(MAX_RUNS, Math.max(1, n)) : DEFAULT_RUNS;\n}\n\n/**\n * A fetch-style handler serving the dashboard and a small JSON API. Mount it\n * in a Next.js app at app/cronwatch/[[...path]]/route.ts:\n *\n * export const { GET, POST, DELETE } = cw.routes();\n */\nexport function createRoutes(cw: CronWatch, options: RoutesOptions = {}): Routes {\n const optedOut = options.token === null;\n const token = optedOut ? null : (options.token || process.env.CRONWATCH_TOKEN || null);\n const base = (options.basePath ?? \"/cronwatch\").replace(/\\/+$/, \"\");\n const developing = process.env.NODE_ENV === \"development\" || process.env.NODE_ENV === \"test\";\n\n const serve = async (request: Request, url: URL, path: string, wantsHtml: boolean): Promise<Response> => {\n const method = request.method.toUpperCase();\n\n // No token: fail closed, except for a developer on their own machine. The\n // Host check also stops a DNS-rebinding page from reaching a dev server.\n if (!token && !optedOut && !(developing && LOOPBACK.has(url.hostname))) {\n return wantsHtml\n ? html(messagePage(\"CronWatch routes are locked\", \"Set CRONWATCH_TOKEN (or pass token to cw.routes()). Without one the routes only answer localhost in development.\", base), 503)\n : api({ ok: false, error: \"CRONWATCH_TOKEN is not set\" }, 503);\n }\n\n if (method !== \"GET\" && method !== \"HEAD\" && crossSite(request, url)) {\n return wantsHtml\n ? html(messagePage(\"Cross-site request refused\", \"Changes can only be made from the dashboard itself.\", base), 403)\n : api({ ok: false, error: \"Cross-site request refused\" }, 403);\n }\n\n const bearer = request.headers.get(\"authorization\")?.replace(/^Bearer\\s+/i, \"\") ?? null;\n if (token) {\n // ?token= is only the sign-in that moves the token into a cookie.\n const query = wantsHtml && method === \"GET\" ? url.searchParams.get(\"token\") : null;\n const cookie = readCookie(request, COOKIE);\n const isCheck = path === \"/api/check\";\n const cronSecretOk = isCheck && bearer !== null && cw.cronSecret !== null && constantTimeEqual(bearer, cw.cronSecret);\n const tokenOk =\n bearer !== null ? constantTimeEqual(bearer, token)\n : query !== null ? constantTimeEqual(query, token)\n : cookie !== null && constantTimeEqual(cookie, cookieValue(token));\n if (!cronSecretOk && !tokenOk) {\n return wantsHtml\n ? html(messagePage(\"Sign in\", `Open this page with ?token=<your CRONWATCH_TOKEN> once and it will stay signed in.`, base), 401)\n : api({ ok: false, error: \"Unauthorized\" }, 401);\n }\n if (query !== null) {\n // Move the token from the URL into a cookie so it is not in history or logs.\n url.searchParams.delete(\"token\");\n const secure = url.protocol === \"https:\" ? \"; Secure\" : \"\";\n return redirect(url.pathname + (url.search || \"\"), {\n \"set-cookie\": `${COOKIE}=${cookieValue(token)}; Path=${base || \"/\"}; HttpOnly; SameSite=Lax; Max-Age=${60 * 60 * 24 * 30}${secure}`,\n });\n }\n }\n\n const redirectBack = () => {\n const referer = request.headers.get(\"referer\") ?? \"\";\n return redirect(referer.startsWith(url.origin + \"/\") ? referer : `${base}/`);\n };\n const decoded = path.split(\"/\").filter(Boolean).map(safeDecode);\n if (decoded.some((part) => part === null)) {\n return wantsHtml ? html(messagePage(\"Bad request\", \"The path is not valid.\", base), 400) : api({ ok: false, error: \"Bad path\" }, 400);\n }\n const parts = decoded as string[];\n\n // HTML\n if (method === \"GET\" && path === \"/\") {\n const entries = await cw.jobsWithRuns(20);\n const runsByJob = new Map<string, Run[]>(entries.map((entry) => [entry.job.name, entry.runs]));\n return html(dashboardPage(entries.map((entry) => entry.job), runsByJob, cw.now(), base, null));\n }\n if (method === \"GET\" && parts[0] === \"jobs\" && parts.length === 2) {\n const job = await cw.jobSummary(parts[1]!);\n if (!job) return html(messagePage(\"No such job\", `${parts[1]} is not in the store.`, base), 404);\n return html(jobPage(job, await cw.runs(job.name, 50), cw.now(), base));\n }\n if (method === \"POST\" && path === \"/check\") {\n await cw.check();\n return redirectBack();\n }\n if (method === \"POST\" && parts[0] === \"jobs\" && parts.length === 3) {\n const name = parts[1]!;\n if (parts[2] === \"forget\") {\n await cw.forget(name);\n return redirect(`${base}/`);\n }\n if (parts[2] !== \"silence\" && parts[2] !== \"unsilence\") return html(messagePage(\"Not found\", path, base), 404);\n if (!(await cw.jobSummary(name))) return html(messagePage(\"No such job\", `${name} is not in the store.`, base), 404);\n if (parts[2] === \"silence\") {\n let duration: Duration;\n try {\n duration = silenceDuration((await readBody(request)).for);\n } catch (e) {\n return html(messagePage(\"Not silenced\", (e as Error).message, base), 400);\n }\n await cw.silence(name, duration);\n } else await cw.unsilence(name);\n return redirectBack();\n }\n\n // JSON API\n if (parts[0] === \"api\") {\n const rest = parts.slice(1);\n if (method === \"GET\" && rest[0] === \"jobs\" && rest.length === 1) {\n return api({ ok: true, jobs: await cw.jobs() });\n }\n if (rest[0] === \"jobs\" && rest.length === 2) {\n const name = rest[1]!;\n if (method === \"GET\") {\n const job = await cw.jobSummary(name);\n if (!job) return api({ ok: false, error: \"No such job\" }, 404);\n return api({ ok: true, job, runs: await cw.runs(name, runsLimit(url.searchParams.get(\"runs\"))) });\n }\n if (method === \"DELETE\") {\n if (!(await cw.jobSummary(name))) return api({ ok: false, error: \"No such job\" }, 404);\n await cw.forget(name);\n return api({ ok: true });\n }\n }\n if (method === \"POST\" && rest[0] === \"jobs\" && rest.length === 3) {\n const name = rest[1]!;\n if (!(await cw.jobSummary(name))) return api({ ok: false, error: \"No such job\" }, 404);\n if (rest[2] === \"silence\") {\n const body = await readBody(request);\n let duration: Duration;\n try {\n duration = silenceDuration(body.for ?? url.searchParams.get(\"for\"));\n } catch (e) {\n return api({ ok: false, error: (e as Error).message }, 400);\n }\n return api({ ok: true, state: await cw.silence(name, duration) });\n }\n if (rest[2] === \"unsilence\") return api({ ok: true, state: await cw.unsilence(name) });\n }\n if (rest[0] === \"check\" && rest.length === 1) {\n // A page cannot send an Authorization header cross-site, so a GET\n // may only run the check when it carries a bearer (token or cron secret).\n if (method === \"GET\" && bearer === null) {\n return api({ ok: false, error: \"Use POST, or GET with an Authorization bearer\" }, 405, { allow: \"POST\" });\n }\n if (method === \"GET\" || method === \"POST\") {\n const result = await cw.check();\n return api({ ok: true, ...result });\n }\n }\n if (method === \"GET\" && rest[0] === \"runs\" && rest.length === 2) {\n const run = await cw.getRun(rest[1]!);\n return run ? api({ ok: true, run }) : api({ ok: false, error: \"No such run\" }, 404);\n }\n return api({ ok: false, error: \"Not found\" }, 404);\n }\n\n return html(messagePage(\"Not found\", path, base), 404);\n };\n\n const handler: FetchHandler = async (request) => {\n let wantsHtml = true;\n try {\n const url = new URL(request.url);\n const path = stripBase(url.pathname, base);\n wantsHtml = !path.startsWith(\"/api\");\n return await serve(request, url, path, wantsHtml);\n } catch (e) {\n try {\n cw.onError(e, \"routes\");\n } catch {\n // An onError that throws must not turn a 500 into an unhandled rejection.\n }\n return wantsHtml\n ? html(messagePage(\"Something went wrong\", \"The request failed and the error was reported.\", base), 500)\n : api({ ok: false, error: \"Internal error\" }, 500);\n }\n };\n\n return { handler, GET: handler, POST: handler, DELETE: handler };\n}\n\nfunction api(body: unknown, status = 200, headers: Record<string, string> = {}): Response {\n return json(body, status, { ...SECURITY_HEADERS, ...headers });\n}\n\nfunction redirect(location: string, headers: Record<string, string> = {}): Response {\n return new Response(null, { status: 303, headers: { location, \"cache-control\": \"no-store\", ...SECURITY_HEADERS, ...headers } });\n}\n\nfunction html(body: string, status = 200): Response {\n return new Response(body, {\n status,\n headers: {\n \"content-type\": \"text/html; charset=utf-8\",\n \"cache-control\": \"no-store\",\n \"content-security-policy\": CSP,\n \"x-frame-options\": \"DENY\",\n ...SECURITY_HEADERS,\n },\n });\n}\n","import type { JobState, Run, Store, StoredJob, StoredJobDefinition } from \"../types.js\";\n\n/**\n * Keeps everything in process memory. The default when no store is given,\n * good for tests and for trying the library out. State is gone on restart,\n * so a missed run cannot be noticed across one.\n */\nexport function memory(): Store {\n const jobs = new Map<string, StoredJob>();\n const runs = new Map<string, Run>();\n const order = new Map<string, number>();\n const states = new Map<string, JobState>();\n let seq = 0;\n\n const clone = <T>(v: T): T => JSON.parse(JSON.stringify(v));\n // Code unit order, as the SQL stores sort by bytes rather than by locale.\n const byName = (a: StoredJob, b: StoredJob) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0);\n\n return {\n async upsertJob(definition: StoredJobDefinition, now: number) {\n const existing = jobs.get(definition.name);\n jobs.set(definition.name, {\n name: definition.name,\n definition: clone(definition),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n });\n },\n async getJob(name) {\n const j = jobs.get(name);\n return j ? clone(j) : null;\n },\n async listJobs() {\n return [...jobs.values()].map(clone).sort(byName);\n },\n async deleteJob(name) {\n jobs.delete(name);\n states.delete(name);\n for (const [id, run] of runs) if (run.job === name) { runs.delete(id); order.delete(id); }\n },\n async insertRun(run) {\n runs.set(run.id, clone(run));\n order.set(run.id, ++seq);\n },\n async updateRun(run) {\n // Like SQL's UPDATE: a run that is gone (its job was forgotten) stays gone, and only these fields change.\n const existing = runs.get(run.id);\n if (!existing) return;\n const { status, finishedAt, durationMs, error, output, metrics } = clone(run);\n runs.set(run.id, { ...existing, status, finishedAt, durationMs, error, output, metrics });\n },\n async getRun(id) {\n const r = runs.get(id);\n return r ? clone(r) : null;\n },\n async listRuns(job, limit) {\n return [...runs.values()]\n .filter((r) => r.job === job)\n .sort((a, b) => b.startedAt - a.startedAt || order.get(b.id)! - order.get(a.id)!)\n .slice(0, limit)\n .map(clone);\n },\n async lastRun(job) {\n const list = await this.listRuns(job, 1);\n return list[0] ?? null;\n },\n async runningRuns() {\n return [...runs.values()]\n .filter((r) => r.status === \"running\")\n .sort((a, b) => a.startedAt - b.startedAt || order.get(a.id)! - order.get(b.id)!)\n .map(clone);\n },\n async getState(job) {\n const s = states.get(job);\n return s ? clone(s) : null;\n },\n async setState(state) {\n states.set(state.job, clone(state));\n },\n async prune(before) {\n // Each job's newest run is kept whatever its age: without it, a job\n // that runs less often than the retention looks like it never ran.\n const newest = new Map<string, number>();\n for (const run of runs.values()) newest.set(run.job, Math.max(newest.get(run.job) ?? -Infinity, run.startedAt));\n let n = 0;\n for (const [id, run] of runs) {\n if (run.status !== \"running\" && run.startedAt < before && run.startedAt < newest.get(run.job)!) {\n runs.delete(id);\n order.delete(id);\n n++;\n }\n }\n return n;\n },\n };\n}\n","import { formatDuration, parseDuration } from \"./duration.js\";\nimport {\n BASELINE_WINDOW,\n hasFullBaseline,\n isSilenced,\n isStuck,\n muteOpens,\n normalizeState,\n onCheck,\n onRunFinish,\n onRunStart,\n summarize,\n timeoutMs,\n} from \"./evaluate.js\";\nimport type { Evaluation } from \"./evaluate.js\";\nimport { composeAlert } from \"./format.js\";\nimport { constantTimeEqual, json } from \"./http.js\";\nimport { createRecorder } from \"./job.js\";\nimport type { JobContext } from \"./job.js\";\nimport { capOutput, errorMessage, redactSecrets } from \"./output.js\";\nimport { parseSchedule } from \"./schedule.js\";\nimport { checkExpectation, toStored } from \"./serialize.js\";\nimport { createRoutes } from \"./routes/index.js\";\nimport type { Routes, RoutesOptions } from \"./routes/index.js\";\nimport { memory } from \"./stores/memory.js\";\nimport type {\n Alert,\n AlertChannel,\n AlertDraft,\n CheckResult,\n Condition,\n Duration,\n JobDefinition,\n JobOptions,\n JobState,\n JobSummary,\n Run,\n Store,\n StoredJob,\n StoredJobDefinition,\n TriageFn,\n} from \"./types.js\";\n\nexport type JobFn<T> = (job: JobContext) => Promise<T> | T;\nexport type HandlerFn<T> = (job: JobContext, request: Request) => Promise<T> | T;\n\nexport interface HandlerOptions {\n /**\n * Callers must send `Authorization: Bearer <secret>`. Defaults to the\n * client's cronSecret, which defaults to process.env.CRON_SECRET (what\n * Vercel sends its cron requests with). An empty string counts as unset.\n * With no secret at all the handler answers 503 unless NODE_ENV is\n * \"development\" or \"test\". Pass null to allow anyone.\n */\n secret?: string | null;\n}\n\nexport interface JobHandle {\n readonly name: string;\n readonly definition: JobDefinition;\n /** Run the function now, recording the run. Rethrows whatever the function throws. */\n run<T>(fn: JobFn<T>, options?: { trigger?: string }): Promise<T>;\n /** A fetch-style request handler (Next.js route, Hono, Bun, Deno) that runs the function and records the run. */\n handler<T>(fn: HandlerFn<T>, options?: HandlerOptions): (request: Request) => Promise<Response>;\n}\n\nexport interface CronWatchOptions {\n /** Where jobs, runs and state live. Defaults to an in-memory store that forgets on restart. */\n store?: Store;\n /** Where alerts go. Defaults to the console. */\n alerts?: AlertChannel[];\n /** Adds a short diagnosis to every alert except recoveries. See @cronwatch/sdk/anthropic. */\n triage?: TriageFn;\n /**\n * Shared secret that handler() requests must carry. Defaults to\n * process.env.CRON_SECRET; an empty string counts as unset. Pass null to\n * let handlers run without one.\n */\n cronSecret?: string | null;\n /** How long finished runs are kept. Default \"30d\". */\n retention?: Duration;\n /** Applied to every job unless the job sets its own. */\n defaults?: Pick<JobOptions, \"grace\" | \"timeout\" | \"timezone\" | \"failuresBeforeAlert\">;\n /**\n * Applied to every run's output and error before it is stored, shown or\n * sent to an alert channel or triage. The default blanks values that look\n * like secrets (password=..., URL credentials, bearer tokens, AWS, GitHub,\n * Slack, Stripe and API key formats). Pass your own function, or false to\n * keep output exactly as logged.\n */\n redact?: ((text: string) => string) | false;\n /**\n * \"now\" (the default) sends alerts from this process. \"check\" sends nothing\n * from here: each alert is queued in the store and the next check, in a\n * process that delivers now, sends it (with triage). For a process that\n * records runs but cannot reach the network, such as a sandboxed backup job.\n * Its `alerts` and `triage` are not used.\n */\n deliver?: \"now\" | \"check\";\n /** Called with anything that goes wrong outside a job: the store failing, an alert channel failing, a triage timeout. */\n onError?: (error: unknown, where: string) => void;\n /** The clock. Tests use this. */\n now?: () => number;\n}\n\ninterface ExecuteResult<T> {\n run: Run;\n result: T | undefined;\n error: unknown;\n threw: boolean;\n}\n\nconst NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,119}$/;\nconst TRIAGE_TIMEOUT_MS = 25_000;\n/** How long one channel may take to send one alert. */\nconst CHANNEL_TIMEOUT_MS = 15_000;\nconst PRUNE_INTERVAL_MS = 60 * 60_000;\n/** Undelivered alerts kept per job for retry; the oldest go first. */\nconst MAX_UNDELIVERED = 20;\n/** Runs read for a baseline, and the most read when failures crowd out the successes. */\nconst HISTORY_PAGE = BASELINE_WINDOW + 5;\nconst HISTORY_MAX = 200;\n\n/** Throws a clear error for options that would otherwise quietly turn a check off. */\nfunction validateDefinition(def: JobDefinition): void {\n const name = def.name;\n if (def.schedule !== undefined) {\n if (typeof def.schedule !== \"string\" || def.schedule.trim() === \"\") throw new Error(`job \"${name}\": schedule must be a non-empty string`);\n parseSchedule(def.schedule, def.timezone);\n }\n if (def.timezone !== undefined) {\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone: def.timezone });\n } catch {\n throw new Error(`job \"${name}\": timezone \"${def.timezone}\" is not an IANA timezone`);\n }\n }\n if (def.grace !== undefined) parseDuration(def.grace, \"grace\");\n if (def.timeout !== undefined && parseDuration(def.timeout, \"timeout\") <= 0) throw new Error(`job \"${name}\": timeout must be longer than zero`);\n if (def.maxDuration !== undefined && parseDuration(def.maxDuration, \"maxDuration\") <= 0) {\n throw new Error(`job \"${name}\": maxDuration must be longer than zero`);\n }\n if (def.failuresBeforeAlert !== undefined && !(Number.isInteger(def.failuresBeforeAlert) && def.failuresBeforeAlert >= 1)) {\n throw new Error(`job \"${name}\": failuresBeforeAlert must be a whole number, 1 or more (got ${String(def.failuresBeforeAlert)})`);\n }\n if (def.budget !== undefined) {\n if (typeof def.budget !== \"object\" || def.budget === null) throw new Error(`job \"${name}\": budget must be an object of { metric: ceiling }`);\n for (const [metric, ceiling] of Object.entries(def.budget)) {\n if (typeof ceiling !== \"number\" || !Number.isFinite(ceiling) || ceiling < 0) {\n throw new Error(`job \"${name}\": budget.${metric} must be a finite number, 0 or more (got ${String(ceiling)})`);\n }\n }\n }\n if (def.expect !== undefined && typeof def.expect !== \"string\" && !(def.expect instanceof RegExp) && typeof def.expect !== \"function\") {\n throw new Error(`job \"${name}\": expect must be a string, a RegExp or a function`);\n }\n}\n\nfunction sameState(a: JobState, b: JobState): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/** Identifies an alert across retries. */\nfunction alertKey(alert: Alert): string {\n return `${alert.type}|${alert.at}|${alert.run?.id ?? \"\"}`;\n}\n\nexport class CronWatch {\n readonly store: Store;\n readonly alerts: AlertChannel[];\n readonly triage: TriageFn | undefined;\n /** The secret handler() requests must carry, or null when none is set. */\n readonly cronSecret: string | null;\n readonly retentionMs: number;\n readonly now: () => number;\n readonly onError: (error: unknown, where: string) => void;\n /** cronSecret was passed as null: handlers may run without a secret. */\n private readonly secretOptOut: boolean;\n private readonly redact: (text: string) => string;\n /** \"check\": queue alerts for another process's check instead of sending them. See CronWatchOptions.deliver. */\n private readonly deferDelivery: boolean;\n private readonly defaults: NonNullable<CronWatchOptions[\"defaults\"]>;\n private readonly definitions = new Map<string, JobDefinition>();\n private readonly synced = new Set<string>();\n /** The tail of each job's queue of state updates. See serial(). */\n private readonly queues = new Map<string, Promise<void>>();\n private ready: Promise<void> | null = null;\n private checking: Promise<CheckResult> | null = null;\n private lastPruneAt = 0;\n private timer: ReturnType<typeof setInterval> | null = null;\n private firstTick: ReturnType<typeof setTimeout> | null = null;\n private usingDefaultStore = false;\n private warnedNoSecret = false;\n\n constructor(options: CronWatchOptions = {}) {\n this.store = options.store ?? (this.usingDefaultStore = true, memory());\n this.alerts = options.alerts ?? [consoleChannel()];\n this.triage = options.triage;\n const secret = options.cronSecret === undefined ? process.env.CRON_SECRET : options.cronSecret;\n this.cronSecret = secret ? secret : null;\n this.secretOptOut = options.cronSecret === null;\n this.retentionMs = parseDuration(options.retention ?? \"30d\", \"retention\");\n this.defaults = options.defaults ?? {};\n this.now = options.now ?? (() => Date.now());\n this.redact = options.redact === false ? (text) => text : (options.redact ?? redactSecrets);\n if (options.deliver !== undefined && options.deliver !== \"now\" && options.deliver !== \"check\") {\n throw new Error(`deliver must be \"now\" or \"check\", not ${JSON.stringify(options.deliver)}`);\n }\n this.deferDelivery = options.deliver === \"check\";\n this.onError = options.onError ?? ((error, where) => console.error(`[cronwatch] ${where}:`, error));\n }\n\n /** Declare a job. Call it once, at module level, and keep the handle. */\n job(name: string, options: JobOptions = {}): JobHandle {\n if (!NAME_RE.test(name)) {\n throw new Error(`job name \"${name}\" must be 1 to 120 characters of letters, digits, \".\", \"_\", \":\" or \"-\"`);\n }\n const definition: JobDefinition = { ...this.defaults, ...options, name };\n validateDefinition(definition);\n this.definitions.set(name, definition);\n this.synced.delete(name);\n return this.handle(definition);\n }\n\n /** Run a job by name without keeping a handle. Defines it on first use. */\n run<T>(name: string, fn: JobFn<T>): Promise<T>;\n run<T>(name: string, options: JobOptions, fn: JobFn<T>): Promise<T>;\n run<T>(name: string, optionsOrFn: JobOptions | JobFn<T>, maybeFn?: JobFn<T>): Promise<T> {\n const fn = typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!;\n const options = typeof optionsOrFn === \"function\" ? undefined : optionsOrFn;\n const handle = options || !this.definitions.has(name) ? this.job(name, options) : this.handle(this.definitions.get(name)!);\n return handle.run(fn);\n }\n\n /** The definitions declared in this process. */\n definedJobs(): JobDefinition[] {\n return [...this.definitions.values()];\n }\n\n private handle(definition: JobDefinition): JobHandle {\n const self = this;\n return {\n name: definition.name,\n definition,\n async run<T>(fn: JobFn<T>, options?: { trigger?: string }): Promise<T> {\n const outcome = await self.execute(definition, fn, options?.trigger ?? \"run\");\n if (outcome.threw) throw outcome.error;\n return outcome.result as T;\n },\n handler<T>(fn: HandlerFn<T>, options?: HandlerOptions) {\n const own = options?.secret;\n const secret = own === null ? null : own ? own : self.cronSecret;\n const optedOut = own === null || (!own && self.secretOptOut);\n return async (request: Request): Promise<Response> => {\n if (!secret && !optedOut && !isDevelopment()) {\n self.warnNoSecret();\n return json({ ok: false, error: \"CRON_SECRET is not set, so this job will not run for an unauthenticated request. Set it, or pass secret: null to handler() to allow anyone.\" }, 503);\n }\n if (secret) {\n const header = request.headers.get(\"authorization\") ?? \"\";\n if (!constantTimeEqual(header, `Bearer ${secret}`)) {\n return json({ ok: false, error: \"Unauthorized\" }, 401);\n }\n }\n const outcome = await self.execute(definition, (job) => fn(job, request), \"handler\");\n if (outcome.result instanceof Response) return outcome.result;\n const body = {\n ok: outcome.run.status === \"ok\",\n job: definition.name,\n run: outcome.run.id,\n status: outcome.run.status,\n durationMs: outcome.run.durationMs,\n // Error text only goes to a caller who proved they hold the secret.\n ...(secret && outcome.run.error ? { error: outcome.run.error.split(\"\\n\")[0] } : {}),\n };\n return json(body, outcome.run.status === \"ok\" ? 200 : 500);\n };\n },\n };\n }\n\n private warnNoSecret(): void {\n if (this.warnedNoSecret) return;\n this.warnedNoSecret = true;\n this.onError(new Error(\"handler() refused a request because no CRON_SECRET is set; pass secret: null to allow unauthenticated requests\"), \"handler\");\n }\n\n private async ensureReady(): Promise<void> {\n if (!this.ready) {\n this.ready = (async () => {\n if (this.store.init) await this.store.init();\n if (this.usingDefaultStore && process.env.NODE_ENV === \"production\") {\n console.warn(\"[cronwatch] using the in-memory store: runs and state are lost on restart. Pass a store from @cronwatch/sdk/sqlite or @cronwatch/sdk/postgres.\");\n }\n })().catch((error: unknown) => {\n // Let the next call try again rather than failing forever.\n this.ready = null;\n throw error;\n });\n }\n await this.ready;\n }\n\n private async sync(definition: JobDefinition): Promise<void> {\n await this.ensureReady();\n if (this.synced.has(definition.name)) return;\n await this.store.upsertJob(toStored(definition), this.now());\n this.synced.add(definition.name);\n }\n\n /**\n * Runs `fn` after every earlier state update for the same job has settled,\n * so two runs (or a run and a check) in this process never read and write\n * the job's state over each other. Other processes are not coordinated.\n */\n private serial<T>(job: string, fn: () => Promise<T>): Promise<T> {\n const result = (this.queues.get(job) ?? Promise.resolve()).then(fn);\n const tail = result.then(() => {}, () => {});\n this.queues.set(job, tail);\n void tail.then(() => {\n if (this.queues.get(job) === tail) this.queues.delete(job);\n });\n return result;\n }\n\n private async readState(job: string): Promise<JobState> {\n return normalizeState(await this.store.getState(job), job);\n }\n\n /**\n * Runs a function as a recorded run. The function always runs, whatever\n * the store is doing: store errors go to onError, and the result is the\n * function's own outcome. Never throws for the job's own error; see `threw`.\n */\n private async execute<T>(definition: JobDefinition, fn: JobFn<T>, trigger: string): Promise<ExecuteResult<T>> {\n const name = definition.name;\n const startedAt = this.now();\n const run: Run = {\n id: crypto.randomUUID(),\n job: name,\n status: \"running\",\n startedAt,\n finishedAt: null,\n durationMs: null,\n error: null,\n output: null,\n metrics: {},\n trigger,\n };\n let recorded = false;\n try {\n await this.sync(definition);\n await this.store.insertRun({ ...run });\n recorded = true;\n } catch (e) {\n this.onError(e, `recording ${name}`);\n }\n // Closing missed and stuck happens beside the job, which never waits on it.\n const started = recorded\n ? this.serial(name, async () => {\n const before = await this.readState(name);\n const after = onRunStart(before);\n if (!sameState(before, after)) await this.store.setState(after);\n }).catch((e) => this.onError(e, `starting ${name}`))\n : Promise.resolve();\n\n const recorder = createRecorder(run);\n const timer = setTimeout(() => recorder.abort(), timeoutMs(definition));\n if (typeof timer === \"object\" && \"unref\" in timer) timer.unref();\n\n let result: T | undefined;\n let error: unknown;\n let threw = false;\n try {\n result = await fn(recorder.context);\n } catch (e) {\n error = e;\n threw = true;\n } finally {\n clearTimeout(timer);\n }\n\n const finishedAt = this.now();\n run.finishedAt = finishedAt;\n run.durationMs = Math.max(0, finishedAt - startedAt);\n run.metrics = recorder.metrics();\n run.output = recorder.output() ?? (typeof result === \"string\" ? capOutput(result) : null);\n\n if (threw) {\n run.status = \"failed\";\n run.error = errorMessage(error);\n } else if (result instanceof Response && result.status >= 400) {\n run.status = \"failed\";\n run.error = `HTTP ${result.status}${result.statusText ? ` ${result.statusText}` : \"\"}`;\n } else {\n const expectText = recorder.expectText() ?? (typeof result === \"string\" ? result : null);\n const unmet = checkExpectation(definition.expect, expectText);\n if (unmet) {\n run.status = \"failed\";\n run.error = unmet;\n } else {\n run.status = \"ok\";\n }\n }\n // Redacted after the expect check, so a rule can still match what was logged.\n if (run.output !== null) run.output = this.redact(run.output);\n if (run.error !== null) run.error = this.redact(run.error);\n\n await started;\n if (!recorded) {\n // The start was never written; the store may be back by now.\n try {\n await this.sync(definition);\n await this.store.insertRun(run);\n recorded = true;\n } catch (e) {\n this.onError(e, `recording ${name}`);\n }\n if (recorded) await this.finishRun(toStored(definition), run, finishedAt, false);\n } else if (await this.markedTimedOut(run)) {\n // A check gave up on this run while it was going and already counted it\n // as a stuck failure. A late failure must not count twice; a late\n // success still closes stuck and recovers.\n try {\n await this.store.updateRun(run);\n } catch (e) {\n this.onError(e, `recording ${name}`);\n }\n } else {\n await this.finishRun(toStored(definition), run, finishedAt, true);\n }\n\n return { run, result, error, threw };\n }\n\n /** Whether a check already marked this run as timed out, for a failure that finished late. */\n private async markedTimedOut(run: Run): Promise<boolean> {\n if (run.status === \"ok\") return false;\n try {\n return (await this.store.getRun(run.id))?.status === \"timeout\";\n } catch {\n return false;\n }\n }\n\n /**\n * Record a finished run (ok, failed, or timed out by a check), evaluate it\n * against the job's state and send what that produces. Never throws.\n */\n private async finishRun(definition: StoredJobDefinition, run: Run, now: number, write: boolean): Promise<Alert[]> {\n let drafts: AlertDraft[];\n try {\n if (write) await this.store.updateRun(run);\n drafts = await this.serial(run.job, async () => {\n const history = await this.history(run);\n const previous = await this.readState(run.job);\n return (await this.settle(previous, onRunFinish(definition, run, previous, history, now), now)).alerts;\n });\n } catch (e) {\n this.onError(e, `evaluating ${run.job}`);\n return [];\n }\n return this.dispatch(drafts, definition, now);\n }\n\n /**\n * The runs before `run`, newest first, with up to BASELINE_WINDOW\n * successful ones when the store has them. One small read normally; a\n * larger one only when failures crowd the successes out of it.\n */\n private async history(run: Run): Promise<Run[]> {\n let runs = await this.store.listRuns(run.job, HISTORY_PAGE);\n if (runs.length === HISTORY_PAGE && !hasFullBaseline(runs.filter((r) => r.id !== run.id))) {\n runs = await this.store.listRuns(run.job, HISTORY_MAX);\n }\n return runs.filter((r) => r.id !== run.id);\n }\n\n /**\n * Look for missed and stuck runs across every job, send alerts, retry\n * alerts no channel accepted, and prune old runs. Call it from an interval\n * (start()), a cron hitting the mounted routes, or by hand. Concurrent\n * calls share one check.\n */\n check(): Promise<CheckResult> {\n if (!this.checking) {\n this.checking = this.runCheck().finally(() => {\n this.checking = null;\n });\n }\n return this.checking;\n }\n\n private async runCheck(): Promise<CheckResult> {\n await this.ensureReady();\n for (const definition of this.definitions.values()) await this.sync(definition);\n const now = this.now();\n const alerts: Alert[] = [];\n\n // Runs that never reported back.\n for (const run of await this.store.runningRuns()) {\n const declared = this.definitions.get(run.job);\n const definition = declared ? toStored(declared) : (await this.store.getJob(run.job))?.definition;\n if (!definition || !isStuck(definition, run, now)) continue;\n run.status = \"timeout\";\n run.finishedAt = now;\n run.durationMs = now - run.startedAt;\n run.error = `Still running after ${formatDuration(timeoutMs(definition))}; marked as timed out`;\n alerts.push(...(await this.finishRun(definition, run, now, true)));\n }\n\n const jobs: JobSummary[] = [];\n for (const stored of await this.store.listJobs()) {\n const recent = await this.store.listRuns(stored.name, BASELINE_WINDOW);\n const { previous, evaluation, settled } = await this.serial(stored.name, async () => {\n const previous = await this.readState(stored.name);\n const evaluation = onCheck(stored.definition, stored, recent[0] ?? null, previous, now);\n return { previous, evaluation, settled: await this.settle(previous, evaluation, now) };\n });\n alerts.push(...(await this.retryUndelivered(stored.name, previous, now)));\n alerts.push(...(await this.dispatch(settled.alerts, stored.definition, now)));\n jobs.push(summarize(stored, recent, settled.state, evaluation.nextExpectedAt, now));\n }\n\n let pruned = 0;\n if (now - this.lastPruneAt > PRUNE_INTERVAL_MS) {\n this.lastPruneAt = now;\n try {\n pruned = await this.store.prune(now - this.retentionMs);\n } catch (e) {\n this.onError(e, \"pruning\");\n }\n }\n\n return { checkedAt: now, jobs, alerts, pruned };\n }\n\n /** A job's summary and its newest runs, without alerting. */\n private async snapshot(stored: StoredJob, now: number, runs: number): Promise<{ job: JobSummary; runs: Run[] }> {\n const recent = await this.store.listRuns(stored.name, Math.max(runs, BASELINE_WINDOW));\n const state = await this.readState(stored.name);\n const { nextExpectedAt } = onCheck(stored.definition, stored, recent[0] ?? null, state, now);\n return { job: summarize(stored, recent, state, nextExpectedAt, now), runs: recent.slice(0, runs) };\n }\n\n /** Every job the store knows about, with its health. Does not send alerts. */\n async jobs(): Promise<JobSummary[]> {\n return (await this.jobsWithRuns(0)).map((entry) => entry.job);\n }\n\n /** Every job's summary with its newest `limit` runs, read together. What the dashboard shows. */\n async jobsWithRuns(limit = 20): Promise<{ job: JobSummary; runs: Run[] }[]> {\n await this.ensureReady();\n for (const definition of this.definitions.values()) await this.sync(definition);\n const now = this.now();\n const out: { job: JobSummary; runs: Run[] }[] = [];\n for (const stored of await this.store.listJobs()) out.push(await this.snapshot(stored, now, clampLimit(limit, 20, 0)));\n return out;\n }\n\n async jobSummary(name: string): Promise<JobSummary | null> {\n await this.ensureReady();\n const definition = this.definitions.get(name);\n if (definition) await this.sync(definition);\n const stored = await this.store.getJob(name);\n if (!stored) return null;\n return (await this.snapshot(stored, this.now(), 0)).job;\n }\n\n /** A job's runs, newest first. `limit` is a whole number from 1 to 500. */\n async runs(name: string, limit = 50): Promise<Run[]> {\n await this.ensureReady();\n return this.store.listRuns(name, clampLimit(limit, 50, 1));\n }\n\n async getRun(id: string): Promise<Run | null> {\n await this.ensureReady();\n return this.store.getRun(id);\n }\n\n /** Stop alerts for a job for a while. State keeps updating underneath. */\n async silence(name: string, duration: Duration): Promise<JobState> {\n const ms = parseDuration(duration, \"silence duration\");\n return this.patchState(name, (state) => { state.silencedUntil = this.now() + ms; });\n }\n\n async unsilence(name: string): Promise<JobState> {\n return this.patchState(name, (state) => { state.silencedUntil = null; });\n }\n\n /** Read, change and write one job's state, in turn with every other update to it. */\n private async patchState(name: string, change: (state: JobState) => void): Promise<JobState> {\n await this.ensureReady();\n return this.serial(name, async () => {\n const state = await this.readState(name);\n change(state);\n await this.store.setState(state);\n return state;\n });\n }\n\n /** Remove a job and its runs from the store. A job still declared in code comes back on its next run. */\n async forget(name: string): Promise<void> {\n await this.ensureReady();\n this.definitions.delete(name);\n this.synced.delete(name);\n await this.store.deleteJob(name);\n }\n\n /** The dashboard and JSON API as fetch-style handlers. See createRoutes(). */\n routes(options?: RoutesOptions): Routes {\n return createRoutes(this, options);\n }\n\n /** Check on an interval, for long-running servers. Default every minute. */\n start(every: Duration = \"1m\"): void {\n if (this.timer) return;\n const ms = Math.max(5_000, parseDuration(every, \"check interval\"));\n const tick = () => this.check().catch((e) => this.onError(e, \"check\"));\n this.timer = setInterval(tick, ms);\n if (typeof this.timer === \"object\" && \"unref\" in this.timer) this.timer.unref();\n this.firstTick = setTimeout(() => {\n this.firstTick = null;\n void tick();\n }, 1_000);\n if (typeof this.firstTick === \"object\" && \"unref\" in this.firstTick) this.firstTick.unref();\n }\n\n stop(): void {\n if (this.timer) clearInterval(this.timer);\n if (this.firstTick) clearTimeout(this.firstTick);\n this.timer = null;\n this.firstTick = null;\n }\n\n async close(): Promise<void> {\n this.stop();\n if (this.store.close) await this.store.close();\n }\n\n /** Save an evaluation's state, honouring silence, and return what should be sent. Call inside serial(). */\n private async settle(previous: JobState, evaluation: Evaluation, now: number): Promise<Evaluation> {\n let { state, alerts } = evaluation;\n if (isSilenced(previous, now)) {\n state = muteOpens(previous, state);\n alerts = [];\n }\n if (!sameState(state, previous)) await this.store.setState(state);\n return { state, alerts };\n }\n\n /**\n * Compose, triage and send each draft. The state was saved before this\n * (settle), so a slow channel holds up nothing else; afterwards only the\n * delivery fields are written back, onto a fresh read of the state.\n */\n private async dispatch(drafts: AlertDraft[], definition: StoredJobDefinition, now: number): Promise<Alert[]> {\n if (drafts.length === 0) return [];\n const composed: Alert[] = [];\n const delivered: Alert[] = [];\n const failed: Alert[] = [];\n for (const draft of drafts) {\n const alert = composeAlert(draft, definition, now);\n if (this.deferDelivery) {\n failed.push(alert);\n } else {\n if (this.triage && alert.type !== \"recovered\") await this.addTriage(alert);\n (await this.deliver(alert) ? delivered : failed).push(alert);\n }\n composed.push(alert);\n }\n await this.recordDelivery(definition.name, delivered, failed, now);\n return composed;\n }\n\n /** Send the alerts that no channel accepted last time, once each. */\n private async retryUndelivered(name: string, state: JobState, now: number): Promise<Alert[]> {\n const pending = state.undelivered ?? [];\n if (pending.length === 0 || isSilenced(state, now) || this.deferDelivery) return [];\n const delivered: Alert[] = [];\n const failed: Alert[] = [];\n for (const alert of pending) {\n // An alert queued by a process that delivers at check time was never triaged.\n if (this.triage && alert.type !== \"recovered\" && alert.triage === undefined) await this.addTriage(alert);\n (await this.deliver(alert) ? delivered : failed).push(alert);\n }\n await this.recordDelivery(name, delivered, failed, now);\n return delivered;\n }\n\n /** Mark delivered alerts done and keep failed ones for the next check. lastAlertAt moves only on a delivery. */\n private async recordDelivery(name: string, delivered: Alert[], failed: Alert[], now: number): Promise<void> {\n try {\n await this.serial(name, async () => {\n const previous = await this.readState(name);\n const state = normalizeState(previous, name);\n const done = new Set(delivered.map(alertKey));\n const kept = state.undelivered!.filter((a) => !done.has(alertKey(a)));\n const known = new Set(kept.map(alertKey));\n kept.push(...failed.filter((a) => !known.has(alertKey(a))));\n state.undelivered = kept.slice(-MAX_UNDELIVERED);\n if (delivered.length > 0) state.lastAlertAt = now;\n if (!sameState(state, previous)) await this.store.setState(state);\n });\n } catch (e) {\n this.onError(e, `recording alert delivery for ${name}`);\n }\n }\n\n /** Send to every channel at once. True when at least one accepted it, or there are none. */\n private async deliver(alert: Alert): Promise<boolean> {\n if (this.alerts.length === 0) return true;\n const results = await Promise.all(\n this.alerts.map(async (channel) => {\n try {\n await withTimeout(channel.send(alert), CHANNEL_TIMEOUT_MS);\n return true;\n } catch (e) {\n this.onError(e, `alert channel ${channel.name}`);\n return false;\n }\n }),\n );\n return results.includes(true);\n }\n\n private async addTriage(alert: Alert): Promise<void> {\n const controller = new AbortController();\n try {\n const recentRuns = await this.store.listRuns(alert.job, 5);\n const diagnosis = await withTimeout(this.triage!({ alert, recentRuns, signal: controller.signal }), TRIAGE_TIMEOUT_MS);\n if (diagnosis) alert.triage = diagnosis;\n } catch (e) {\n controller.abort();\n this.onError(e, `triage for ${alert.job}`);\n }\n }\n}\n\nfunction isDevelopment(): boolean {\n return process.env.NODE_ENV === \"development\" || process.env.NODE_ENV === \"test\";\n}\n\n/** A whole number in range, or the fallback for anything that is not a number. */\nfunction clampLimit(limit: number, fallback: number, min: number): number {\n const n = typeof limit === \"number\" && Number.isFinite(limit) ? Math.trunc(limit) : fallback;\n return Math.min(500, Math.max(min, n));\n}\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const t = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);\n if (typeof t === \"object\" && \"unref\" in t) t.unref();\n promise.then((v) => { clearTimeout(t); resolve(v); }, (e) => { clearTimeout(t); reject(e); });\n });\n}\n\n/** Writes alerts to the console. The default channel. */\nexport function consoleChannel(): AlertChannel {\n return {\n name: \"console\",\n async send(alert) {\n const line = `[cronwatch] ${alert.title}\\n${alert.message}${alert.triage ? `\\nTriage: ${alert.triage}` : \"\"}`;\n if (alert.type === \"recovered\") console.info(line);\n else console.error(line);\n },\n };\n}\n\n/** Wrap any function as an alert channel. */\nexport function custom(name: string, send: (alert: Alert) => Promise<void> | void): AlertChannel {\n return { name, send: async (alert) => { await send(alert); } };\n}\n\nexport type { Condition };\n","import { CronWatch } from \"./client.js\";\nimport type { CronWatchOptions } from \"./client.js\";\n\n/**\n * Create a CronWatch client. One per app, at module level:\n *\n * export const cw = cronwatch({ store: sqlite({ path: \"./data/cronwatch.db\" }), alerts: [slack({ webhookUrl })] });\n * export const nightly = cw.job(\"nightly-report\", { schedule: \"0 2 * * *\", grace: \"15m\" });\n */\nexport function cronwatch(options: CronWatchOptions = {}): CronWatch {\n return new CronWatch(options);\n}\n\nexport { CronWatch, consoleChannel, custom } from \"./client.js\";\nexport type { CronWatchOptions, HandlerFn, HandlerOptions, JobFn, JobHandle } from \"./client.js\";\nexport type { JobContext } from \"./job.js\";\nexport { memory } from \"./stores/memory.js\";\nexport { createRoutes } from \"./routes/index.js\";\nexport type { FetchHandler, Routes, RoutesOptions } from \"./routes/index.js\";\nexport { parseDuration, formatDuration } from \"./duration.js\";\nexport { parseSchedule, nextFire } from \"./schedule.js\";\nexport type { ParsedSchedule } from \"./schedule.js\";\nexport { composeAlert } from \"./format.js\";\nexport type {\n Alert,\n AlertChannel,\n AlertDetails,\n AlertDraft,\n AlertType,\n BudgetBreach,\n CheckResult,\n Condition,\n Duration,\n ExpectRule,\n JobDefinition,\n JobHealth,\n JobOptions,\n JobState,\n JobSummary,\n Run,\n RunStatus,\n Store,\n StoredJob,\n StoredJobDefinition,\n TriageContext,\n TriageFn,\n} from \"./types.js\";\n"]}
|