@cronwatch/sdk 0.3.0 → 0.3.1
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/README.md +0 -5
- package/dist/anthropic.d.cts +1 -1
- package/dist/anthropic.d.ts +1 -1
- package/dist/discord.d.cts +1 -1
- package/dist/discord.d.ts +1 -1
- package/dist/index.cjs +234 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -16
- package/dist/index.d.ts +48 -16
- package/dist/index.js +235 -84
- package/dist/index.js.map +1 -1
- package/dist/postgres.cjs +13 -1
- package/dist/postgres.cjs.map +1 -1
- package/dist/postgres.d.cts +1 -1
- package/dist/postgres.d.ts +1 -1
- package/dist/postgres.js +13 -1
- package/dist/postgres.js.map +1 -1
- package/dist/slack.d.cts +1 -1
- package/dist/slack.d.ts +1 -1
- package/dist/sqlite.cjs +44 -5
- package/dist/sqlite.cjs.map +1 -1
- package/dist/sqlite.d.cts +1 -1
- package/dist/sqlite.d.ts +1 -1
- package/dist/sqlite.js +44 -5
- package/dist/sqlite.js.map +1 -1
- package/dist/{types-C1PyRjI5.d.cts → types-DUt2apl0.d.cts} +21 -2
- package/dist/{types-C1PyRjI5.d.ts → types-DUt2apl0.d.ts} +21 -2
- package/dist/webhook.d.cts +1 -1
- package/dist/webhook.d.ts +1 -1
- package/package.json +4 -4
package/dist/index.js.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":["graceMs","tail","previous","evaluation"],"mappings":"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","file":"index.js","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"]}
|
|
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":["graceMs","tail"],"mappings":"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","file":"index.js","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/**\n * An evaluation as it is saved and sent: while the job was silenced when it\n * began, nothing opens and nothing is sent.\n */\nexport function applySilence(previous: JobState, evaluation: Evaluation, now: number): Evaluation {\n if (!isSilenced(previous, now)) return evaluation;\n return { state: muteOpens(previous, evaluation.state), alerts: [] };\n}\n\n/**\n * Whether an alert waiting to be retried no longer describes the job, so it\n * is dropped rather than sent late. An alert for a condition is stale once\n * that condition has closed, or has closed and opened again (it opened at a\n * time other than the alert's). A recovery is stale when any condition it\n * names is open again; while they all stay closed it is kept.\n */\nexport function staleAlert(alert: AlertDraft & { at: number }, state: JobState): boolean {\n if (alert.type === \"recovered\") return alert.details.after.some((condition) => state.open[condition] !== undefined);\n return state.open[alert.type] !== alert.at;\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 return summary(stored, recent, state, nextExpectedAt, (lastRun) => jobHealth(stored.definition, lastRun, state, now));\n}\n\n/**\n * The summary of a job that could not be evaluated, say because its stored\n * schedule no longer parses. It reads nothing from the definition. The job\n * shows as failing (or silenced, while it is), since it needs a look, and\n * nothing is known about when it is next due.\n */\nexport function unevaluableSummary(stored: StoredJob, recent: Run[], state: JobState, now: number): JobSummary {\n return summary(stored, recent, state, null, () => (isSilenced(state, now) ? \"silenced\" : \"failing\"));\n}\n\nfunction summary(stored: StoredJob, recent: Run[], state: JobState, nextExpectedAt: number | null, health: (lastRun: Run | null) => JobHealth): 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: health(lastRun),\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\n/**\n * NUL characters are removed first, since Postgres refuses them in TEXT and\n * JSONB and the whole run row would be lost. The cap then applies to what is\n * left.\n */\nexport function capOutput(text: string): string {\n const clean = stripNul(text);\n if (clean.length <= OUTPUT_CAP) return clean;\n return \"[earlier output trimmed]\\n\" + clean.slice(clean.length - OUTPUT_CAP);\n}\n\n/** Removes every U+0000. */\nexport function stripNul(text: string): string {\n return text.includes(\"\\u0000\") ? text.replace(/\\u0000/g, \"\") : text;\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.\n// They apply in this order, each to the text the ones before it left.\nconst SECRET_PATTERNS: [RegExp, string | ((match: string, ...groups: string[]) => string)][] = [\n // A PEM private key, header to footer. Without a footer (the output was\n // trimmed) it runs to the end of the base64 body. A \"-\" that starts five\n // dashes ends the body, so the footer is never swallowed into it.\n [\n /-----BEGIN (?:[A-Z0-9]{1,20} ){0,3}PRIVATE KEY-----(?:[A-Za-z0-9+/=\\s,:]|-(?!----)){0,16384}(?:-----END (?:[A-Z0-9]{1,20} ){0,3}PRIVATE KEY-----)?/g,\n REDACTED,\n ],\n // password=..., API_KEY: ..., \"client_secret\": \"...\", TOKEN='...', token=...,\n // :password=>\"...\" (but not max_tokens: 800). A quoted value is blanked to\n // 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 // Authorization: Basic <base64> and Authorization: Token <token>, also as a JSON or hash entry.\n [/\\b((?:proxy-)?authorization[\"']?\\s{0,3}(?:=>|[=:])\\s{0,3}[\"']?\\s{0,3}(?:basic|token)\\s{1,3})[A-Za-z0-9._~+/=:-]{1,4096}/gi, `$1${REDACTED}`],\n // Credentials inside a URL: postgres://user:password@host. The password\n // runs to the last \"@\" before a \"/\" or a space, so one that contains \"@\"\n // is blanked whole.\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 // A bare JWT: three base64url segments, the first starting eyJ.\n [/\\beyJ[A-Za-z0-9_-]{4,4096}\\.[A-Za-z0-9_-]{4,4096}\\.[A-Za-z0-9_-]{0,4096}/g, REDACTED],\n // Incoming webhook URLs carry their secret in the path.\n [/(\\bhooks\\.slack\\.com\\/(?:services|workflows|triggers)\\/)[A-Za-z0-9/_-]{1,255}/gi, `$1${REDACTED}`],\n [/(\\bdiscord(?:app)?\\.com\\/api\\/(?:v\\d{1,2}\\/)?webhooks\\/)[A-Za-z0-9/_-]{1,255}/gi, `$1${REDACTED}`],\n // Well-known token shapes: AWS, GitHub, Slack, Stripe, Anthropic, OpenAI and Google 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 [/\\bwhsec_[A-Za-z0-9+/=]{16,255}/g, REDACTED],\n [/\\bsk-[A-Za-z0-9_-]{20,255}/g, REDACTED],\n [/\\bAIza[0-9A-Za-z_-]{35}(?![0-9A-Za-z_-])/g, REDACTED],\n];\n\n/**\n * The default `redact`: blanks values that look like secrets (key=value pairs\n * with secret-ish names, Authorization headers, URL credentials, bearer\n * tokens, JWTs, PEM private keys, webhook URLs and well-known token formats)\n * 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, randomBytes } 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 while NODE_ENV is \"development\" or \"test\", the routes make\n * a random one and print a sign-in link to the server log on their first\n * request; with no token otherwise they answer 503. Pass `null` to opt out\n * and serve them 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 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\n/**\n * A token for one routes instance in development, when none is configured:\n * 32 random bytes, base64url (43 characters).\n */\nfunction developmentToken(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\n/**\n * The line a development token is announced with, printed once with\n * console.info on the routes' first request:\n *\n * [cronwatch] CRONWATCH_TOKEN is not set, so this development server made a token for the dashboard. Sign in: <origin><base>/?token=<token>\n *\n * <origin> is the first request's URL origin (scheme, host and any port),\n * <base> the base path without a trailing slash (\"\" when mounted at the\n * root), and <token> the token as generated (base64url, so nothing needs\n * escaping).\n */\nfunction developmentSignInLine(origin: string, base: string, token: string): string {\n return `[cronwatch] CRONWATCH_TOKEN is not set, so this development server made a token for the dashboard. Sign in: ${origin}${base}/?token=${token}`;\n}\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 configured = 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 // A fetch handler cannot tell a local caller from a remote one (proxies,\n // tunnels and `next dev` listening on every interface all look alike), so\n // development gets a token too: made here, and shown only in the server log.\n const generated = !configured && !optedOut && developing;\n const token = generated ? developmentToken() : configured;\n let announced = false;\n\n const serve = async (request: Request, url: URL, path: string, wantsHtml: boolean): Promise<Response> => {\n const method = request.method.toUpperCase();\n\n if (generated && !announced) {\n announced = true;\n console.info(developmentSignInLine(url.origin, base, token!));\n }\n\n // No token outside development: fail closed.\n if (!token && !optedOut) {\n return wantsHtml\n ? html(messagePage(\"CronWatch routes are locked\", \"Set CRONWATCH_TOKEN (or pass token to cw.routes()), or pass token: null to serve them open behind your own auth.\", 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 if (generated) {\n return wantsHtml\n ? html(messagePage(\"Sign in\", \"CRONWATCH_TOKEN is not set, so this development server made a token. The sign-in link is in the server log: open it once and this browser stays signed in.\", base), 401)\n : api({ ok: false, error: \"Unauthorized: CRONWATCH_TOKEN is not set, so this development server made a token; it is in the server log\" }, 401);\n }\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 compareAndSetState(state, expectedVersion) {\n if ((states.get(state.job)?.version ?? 0) !== expectedVersion) return false;\n states.set(state.job, clone(state));\n return true;\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 applySilence,\n BASELINE_WINDOW,\n emptyState,\n hasFullBaseline,\n isSilenced,\n isStuck,\n normalizeState,\n onCheck,\n onRunFinish,\n onRunStart,\n staleAlert,\n summarize,\n timeoutMs,\n unevaluableSummary,\n} 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, stripNul } 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=..., Authorization headers, URL credentials, bearer\n * tokens, JWTs, PEM private keys, webhook URLs, AWS, GitHub, Slack, Stripe,\n * Google and API key formats). Pass your own function, or false to keep\n * output exactly as logged. A function that throws or returns something\n * other than a string is reported to onError and the default is used.\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/**\n * Wall-clock time one check spends retrying undelivered alerts, across every\n * job. Once it is spent the rest wait for the next check.\n */\nconst RETRY_BUDGET_MS = 20_000;\n/** Reads and writes of one job's state before an update gives up on a store that keeps changing under it. */\nconst STATE_ATTEMPTS = 10;\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 private warnedDeferredStart = 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 const redact = options.redact;\n this.redact = redact === false ? (text) => text\n : typeof redact === \"function\" ? (text) => {\n try {\n const out: unknown = redact(text);\n if (typeof out !== \"string\") throw new TypeError(`redact must return a string, not ${out === null ? \"null\" : typeof out}`);\n return out;\n } catch (e) {\n // A broken redact must not stop the run finishing, nor leak what it was given.\n this.report(e, \"redact\");\n return redactSecrets(text);\n }\n }\n : 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 /** onError, for places that must carry on even when onError itself throws. */\n private report(error: unknown, where: string): void {\n try {\n this.onError(error, where);\n } catch {\n // Nothing more can be done with it.\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 })().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 coordinated by\n * updateState() instead.\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 * Every read-modify-write of a job's state goes through here. In turn with\n * this process's other updates to the job (serial()), it reads the state,\n * asks `change` for the next one, and writes it with the version one\n * higher, only if the stored version is still the one read. When another\n * process wrote in between, the write is refused and it starts again from\n * a fresh read, up to STATE_ATTEMPTS times. So `change` may run more than\n * once and must only compute: whatever it returns from the attempt that\n * was written is the result. Nothing is written when the state is\n * unchanged. Returns the state as stored.\n */\n private updateState<T>(\n job: string,\n change: (current: JobState) => { state: JobState; result: T } | Promise<{ state: JobState; result: T }>,\n ): Promise<{ state: JobState; result: T }> {\n return this.serial(job, async () => {\n for (let attempt = 1; ; attempt++) {\n const current = await this.readState(job);\n const { state, result } = await change(current);\n if (sameState(state, current)) return { state: current, result };\n const version = current.version ?? 0;\n const next: JobState = { ...state, version: version + 1 };\n if (await this.writeState(next, version)) return { state: next, result };\n if (attempt >= STATE_ATTEMPTS) {\n throw new Error(`the state of ${job} changed under ${STATE_ATTEMPTS} attempts in a row to update it; gave up`);\n }\n }\n });\n }\n\n /** A conditional write, or for a store without compareAndSetState, a plain one that always succeeds. */\n private async writeState(state: JobState, expectedVersion: number): Promise<boolean> {\n if (typeof this.store.compareAndSetState === \"function\") return this.store.compareAndSetState(state, expectedVersion);\n await this.store.setState(state);\n return true;\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.updateState(name, (before) => ({ state: onRunStart(before), result: undefined }))\n .then(() => {}, (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\n // logged. NULs go last, so not even a custom redact can store one.\n if (run.output !== null) run.output = stripNul(this.redact(run.output));\n if (run.error !== null) run.error = stripNul(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 let history: Run[] | null = null;\n ({ result: drafts } = await this.updateState(run.job, async (previous) => {\n history ??= await this.history(run);\n const settled = applySilence(previous, onRunFinish(definition, run, previous, history, now), now);\n return { state: settled.state, result: settled.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. One that cannot be judged (its job's\n // stored timeout no longer parses, say) is reported and skipped.\n for (const run of await this.store.runningRuns()) {\n try {\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 const timeout = timeoutMs(definition);\n run.status = \"timeout\";\n run.finishedAt = now;\n run.durationMs = now - run.startedAt;\n run.error = `Still running after ${formatDuration(timeout)}; marked as timed out`;\n alerts.push(...(await this.finishRun(definition, run, now, true)));\n } catch (e) {\n this.onError(e, `checking ${run.job}`);\n }\n }\n\n // Each job on its own: one that cannot be evaluated is reported, shown\n // as failing (see unevaluableSummary) and does not stop the others.\n const jobs: JobSummary[] = [];\n const retries = { spentMs: 0 };\n for (const stored of await this.store.listJobs()) {\n try {\n const recent = await this.store.listRuns(stored.name, BASELINE_WINDOW);\n let nextExpectedAt: number | null = null;\n const { state, result: drafts } = await this.updateState(stored.name, (previous) => {\n const evaluation = onCheck(stored.definition, stored, recent[0] ?? null, previous, now);\n nextExpectedAt = evaluation.nextExpectedAt;\n const settled = applySilence(previous, evaluation, now);\n return { state: settled.state, result: settled.alerts };\n });\n alerts.push(...(await this.retryUndelivered(stored.name, state, now, retries)));\n alerts.push(...(await this.dispatch(drafts, stored.definition, now)));\n jobs.push(summarize(stored, recent, state, nextExpectedAt, now));\n } catch (e) {\n this.onError(e, `checking ${stored.name}`);\n jobs.push(await this.unevaluable(stored, now));\n }\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. A job that cannot be evaluated is reported and shown as failing. */\n private async snapshot(stored: StoredJob, now: number, runs: number): Promise<{ job: JobSummary; runs: Run[] }> {\n let recent: Run[] = [];\n try {\n 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 } catch (e) {\n this.onError(e, `reading ${stored.name}`);\n return { job: await this.unevaluable(stored, now), runs: recent.slice(0, runs) };\n }\n }\n\n /** The summary of a job whose evaluation failed, from whatever can still be read. */\n private async unevaluable(stored: StoredJob, now: number): Promise<JobSummary> {\n const recent = await this.store.listRuns(stored.name, BASELINE_WINDOW).catch((): Run[] => []);\n const state = await this.readState(stored.name).catch(() => emptyState(stored.name));\n return unevaluableSummary(stored, recent, state, now);\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 const { state } = await this.updateState(name, (current) => {\n const next = normalizeState(current, name);\n change(next);\n return { state: next, result: undefined };\n });\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 if (this.deferDelivery && !this.warnedDeferredStart) {\n this.warnedDeferredStart = true;\n console.warn('[cronwatch] start() was called with deliver: \"check\", so these checks send no alerts. Another process must run checks with deliver: \"now\" (the default) to send them.');\n }\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 /**\n * Compose, triage and send each draft. The state was saved before this\n * (updateState), so a slow channel holds up nothing else; afterwards only\n * the 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, TRIAGE_TIMEOUT_MS);\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 /**\n * Send the alerts that no channel accepted last time, once each, oldest\n * first. `state` is the job's state as this check left it: an alert that\n * no longer describes it (staleAlert) is dropped instead. Retries across a\n * check share RETRY_BUDGET_MS of wall-clock time; once it is spent the rest\n * stay queued for the next check.\n */\n private async retryUndelivered(name: string, state: JobState, now: number, budget: { spentMs: 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 const dropped = pending.filter((alert) => staleAlert(alert, state));\n for (const alert of pending) {\n if (dropped.includes(alert)) continue;\n const left = RETRY_BUDGET_MS - budget.spentMs;\n if (left <= 0) break;\n const started = Date.now();\n // An alert queued by a process that delivers at check time was never\n // triaged. One that was tried (triage: null) is not tried again.\n if (this.triage && alert.type !== \"recovered\" && alert.triage === undefined) await this.addTriage(alert, Math.min(TRIAGE_TIMEOUT_MS, left));\n (await this.deliver(alert) ? delivered : failed).push(alert);\n budget.spentMs += Math.max(0, Date.now() - started);\n }\n await this.recordDelivery(name, delivered, failed, dropped, now);\n return delivered;\n }\n\n /**\n * Mark delivered alerts done, drop stale ones, and keep failed ones for the\n * next check. A failed alert replaces its stored copy, so a triage made on\n * this attempt is kept. lastAlertAt moves only on a delivery.\n */\n private async recordDelivery(name: string, delivered: Alert[], failed: Alert[], dropped: Alert[], now: number): Promise<void> {\n try {\n const { result: trimmed } = await this.updateState(name, (previous) => {\n const state = normalizeState(previous, name);\n const done = new Set([...delivered, ...dropped].map(alertKey));\n const retried = new Map(failed.map((a) => [alertKey(a), a]));\n const kept = state.undelivered!.filter((a) => !done.has(alertKey(a))).map((a) => retried.get(alertKey(a)) ?? 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 return { state, result: Math.max(0, kept.length - MAX_UNDELIVERED) };\n });\n if (trimmed > 0) {\n this.onError(\n new Error(`${trimmed} undelivered alert${trimmed === 1 ? \"\" : \"s\"} for ${name} dropped: only the newest ${MAX_UNDELIVERED} are kept for retry`),\n `alert queue for ${name}`,\n );\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 /** Sets alert.triage to the diagnosis, or to null when there is none, so it is tried once per alert. */\n private async addTriage(alert: Alert, timeout: number): 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 }), timeout);\n alert.triage = typeof diagnosis === \"string\" && diagnosis !== \"\" ? diagnosis : null;\n } catch (e) {\n controller.abort();\n alert.triage = null;\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"]}
|