@cronwatch/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -0
- package/dist/anthropic.cjs +84 -0
- package/dist/anthropic.cjs.map +1 -0
- package/dist/anthropic.d.cts +35 -0
- package/dist/anthropic.d.ts +35 -0
- package/dist/anthropic.js +78 -0
- package/dist/anthropic.js.map +1 -0
- package/dist/discord.cjs +42 -0
- package/dist/discord.cjs.map +1 -0
- package/dist/discord.d.cts +11 -0
- package/dist/discord.d.ts +11 -0
- package/dist/discord.js +40 -0
- package/dist/discord.js.map +1 -0
- package/dist/index.cjs +1317 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +219 -0
- package/dist/index.d.ts +219 -0
- package/dist/index.js +1302 -0
- package/dist/index.js.map +1 -0
- package/dist/postgres.cjs +142 -0
- package/dist/postgres.cjs.map +1 -0
- package/dist/postgres.d.cts +19 -0
- package/dist/postgres.d.ts +19 -0
- package/dist/postgres.js +136 -0
- package/dist/postgres.js.map +1 -0
- package/dist/slack.cjs +44 -0
- package/dist/slack.cjs.map +1 -0
- package/dist/slack.d.cts +12 -0
- package/dist/slack.d.ts +12 -0
- package/dist/slack.js +42 -0
- package/dist/slack.js.map +1 -0
- package/dist/sqlite.cjs +151 -0
- package/dist/sqlite.cjs.map +1 -0
- package/dist/sqlite.d.cts +17 -0
- package/dist/sqlite.d.ts +17 -0
- package/dist/sqlite.js +144 -0
- package/dist/sqlite.js.map +1 -0
- package/dist/types-BQ1P8z55.d.cts +159 -0
- package/dist/types-BQ1P8z55.d.ts +159 -0
- package/dist/webhook.cjs +24 -0
- package/dist/webhook.cjs.map +1 -0
- package/dist/webhook.d.cts +20 -0
- package/dist/webhook.d.ts +20 -0
- package/dist/webhook.js +22 -0
- package/dist/webhook.js.map +1 -0
- package/package.json +114 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/duration.ts","../src/schedule.ts","../src/stats.ts","../src/evaluate.ts","../src/format.ts","../src/http.ts","../src/output.ts","../src/job.ts","../src/serialize.ts","../src/routes/html.ts","../src/routes/index.ts","../src/stores/memory.ts","../src/client.ts","../src/index.ts"],"names":["Cron","graceMs","constantTimeEqual"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Duration } from \"./types.js\";\n\nconst UNIT_MS: Record<string, number> = {\n ms: 1,\n s: 1000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n};\n\n/**\n * \"15m\" -> 900000. Accepts a plain number of milliseconds, and compound\n * strings such as \"1h30m\". Whitespace between parts is fine.\n */\nexport function parseDuration(value: Duration, label = \"duration\"): number {\n if (typeof value === \"number\") {\n if (!Number.isFinite(value) || value < 0) throw new Error(`${label} must be a non-negative number of milliseconds`);\n return value;\n }\n const text = value.trim().toLowerCase();\n if (text === \"\") throw new Error(`${label} is empty`);\n const re = /(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h|d|w)/g;\n let total = 0;\n let consumed = \"\";\n let match: RegExpExecArray | null;\n while ((match = re.exec(text)) !== null) {\n total += parseFloat(match[1]!) * UNIT_MS[match[2]!]!;\n consumed += match[0];\n }\n if (consumed.replace(/\\s+/g, \"\") !== text.replace(/\\s+/g, \"\")) {\n throw new Error(`${label} \"${value}\" is not a duration like \"15m\", \"1h30m\" or \"90s\"`);\n }\n return Math.round(total);\n}\n\n/** 90000 -> \"1m 30s\". For messages, not for parsing back. */\nexport function formatDuration(ms: number): string {\n if (!Number.isFinite(ms)) return \"?\";\n if (ms < 1000) return `${Math.round(ms)}ms`;\n const parts: string[] = [];\n let rest = Math.round(ms / 1000);\n const units: [string, number][] = [[\"d\", 86_400], [\"h\", 3_600], [\"m\", 60], [\"s\", 1]];\n for (const [unit, size] of units) {\n if (rest >= size) {\n const n = Math.floor(rest / size);\n rest -= n * size;\n parts.push(`${n}${unit}`);\n }\n if (parts.length === 2) break;\n }\n return parts.join(\" \") || \"0s\";\n}\n\n/** \"5 minutes ago\", \"in 2h\". Relative to `now`. */\nexport function formatRelative(at: number, now: number): string {\n const diff = at - now;\n const abs = Math.abs(diff);\n const text = abs < 5_000 ? \"now\" : formatDuration(abs);\n if (abs < 5_000) return text;\n return diff < 0 ? `${text} ago` : `in ${text}`;\n}\n","import { Cron } from \"croner\";\nimport { parseDuration } from \"./duration.js\";\n\nexport interface ParsedSchedule {\n kind: \"cron\" | \"interval\";\n source: string;\n /** For intervals, the period in milliseconds. */\n everyMs?: number;\n cron?: Cron;\n}\n\nconst cache = new Map<string, ParsedSchedule>();\n\n/**\n * \"0 2 * * *\" (cron, five or six fields), \"@hourly\", or \"every 5m\".\n * Parsed once per (schedule, timezone) pair and cached. The croner instance\n * gets no callback, so it schedules nothing; it is only used to compute fire\n * times. Without a timezone the expression is read in the process timezone,\n * like crontab. Vercel and GitHub Actions run their crons in UTC, so pass\n * timezone: \"UTC\" for those.\n */\nexport function parseSchedule(schedule: string, timezone?: string): ParsedSchedule {\n const key = `${timezone ?? \"\"}|${schedule}`;\n const hit = cache.get(key);\n if (hit) return hit;\n\n const text = schedule.trim();\n const every = /^every\\s+(.+)$/i.exec(text);\n let parsed: ParsedSchedule;\n if (every) {\n const everyMs = parseDuration(every[1]!, \"schedule interval\");\n if (everyMs < 1000) throw new Error(`schedule \"${schedule}\" is shorter than one second`);\n parsed = { kind: \"interval\", source: text, everyMs };\n } else {\n let cron: Cron;\n try {\n cron = new Cron(text, timezone ? { timezone } : {});\n } catch (error) {\n throw new Error(`schedule \"${schedule}\" is not a cron expression or \"every <duration>\": ${(error as Error).message}`);\n }\n parsed = { kind: \"cron\", source: text, cron };\n }\n cache.set(key, parsed);\n return parsed;\n}\n\n/** The next time the cron fires strictly after `from`. */\nexport function nextFire(parsed: ParsedSchedule, from: number, lastRunAt: number | null): number | null {\n if (parsed.kind === \"interval\") {\n const base = lastRunAt ?? from;\n return base + parsed.everyMs!;\n }\n const next = parsed.cron!.nextRun(new Date(from));\n return next ? next.getTime() : null;\n}\n\n/**\n * The most recent time the cron fired at or before `now`, or null when the\n * expression never fires in the year before `now`.\n *\n * croner only looks forward, so this searches: widen a window behind `now`\n * until a fire time falls inside it, then bisect on the window's start for\n * the latest start whose next fire is still at or before `now`.\n */\nexport function previousFire(parsed: ParsedSchedule, now: number): number | null {\n if (parsed.kind !== \"cron\") throw new Error(\"previousFire is for cron schedules\");\n const cron = parsed.cron!;\n // nextRun(from) is strictly after `from`, so start one millisecond behind.\n const fireAtOrBefore = (from: number): number | null => {\n const next = cron.nextRun(new Date(from - 1));\n if (!next) return null;\n const t = next.getTime();\n return t <= now ? t : null;\n };\n\n const YEAR = 366 * 86_400_000;\n let step = 60_000;\n let lo: number | null = null;\n while (step <= YEAR) {\n if (fireAtOrBefore(now - step) !== null) {\n lo = now - step;\n break;\n }\n step *= 2;\n }\n if (lo === null) return null;\n\n // Invariant: fireAtOrBefore(lo) !== null. Find the largest start that still\n // has a fire at or before now; its fire is the previous one.\n let hi = now;\n while (hi - lo > 1) {\n const mid = Math.floor((lo + hi) / 2);\n if (fireAtOrBefore(mid) !== null) lo = mid;\n else hi = mid;\n }\n return fireAtOrBefore(lo);\n}\n\nexport interface Expectation {\n /** When the current period's run was due. */\n dueAt: number;\n /** Missed once now passes this. */\n deadline: number;\n}\n\n/**\n * What the schedule expects given the last run. Returns null when nothing is\n * due yet (a cron whose first fire since registration is still ahead, or an\n * interval that has not elapsed).\n */\nexport function expectation(\n parsed: ParsedSchedule,\n now: number,\n lastRunAt: number | null,\n registeredAt: number,\n graceMs: number,\n): Expectation | null {\n if (parsed.kind === \"interval\") {\n const dueAt = (lastRunAt ?? registeredAt) + parsed.everyMs!;\n return { dueAt, deadline: dueAt + graceMs };\n }\n const prev = previousFire(parsed, now);\n if (prev === null || prev < registeredAt) return null;\n return { dueAt: prev, deadline: prev + graceMs };\n}\n\n/**\n * Whether a run starting at `startedAt` covers the fire at `dueAt`. A minute of\n * slack before the tick absorbs schedulers that fire a touch early.\n */\nexport function runCovers(startedAt: number, dueAt: number): boolean {\n return startedAt >= dueAt - 60_000;\n}\n","export function percentile(values: number[], p: number): number | null {\n if (values.length === 0) return null;\n const sorted = [...values].sort((a, b) => a - b);\n const index = Math.min(sorted.length - 1, Math.max(0, Math.ceil((p / 100) * sorted.length) - 1));\n return sorted[index]!;\n}\n\nexport function median(values: number[]): number | null {\n if (values.length === 0) return null;\n const sorted = [...values].sort((a, b) => a - b);\n const mid = Math.floor(sorted.length / 2);\n return sorted.length % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!;\n}\n","/**\n * Pure decisions about a job's health. Each function takes the current state\n * and returns the new state plus the alerts that should go out. Nothing here\n * touches a store or a network, which is what makes it testable.\n */\nimport { formatDuration } from \"./duration.js\";\nimport { parseDuration } from \"./duration.js\";\nimport { expectation, parseSchedule, runCovers } from \"./schedule.js\";\nimport { median, percentile } from \"./stats.js\";\nimport type { Condition, JobDefinition, JobState, Run, StoredJob, StoredJobDefinition } from \"./types.js\";\n\nexport interface AlertDraft {\n type: Condition | \"recovered\";\n run: Run | null;\n details: Record<string, unknown>;\n}\n\nexport interface Evaluation {\n state: JobState;\n alerts: AlertDraft[];\n}\n\nexport const DEFAULT_GRACE_MS = 10 * 60_000;\nexport const DEFAULT_TIMEOUT_MS = 60 * 60_000;\n/** Runs faster than this are never called slow, whatever the baseline says. */\nexport const SLOW_FLOOR_MS = 10_000;\n/** How many earlier runs a baseline needs before it is trusted. */\nexport const BASELINE_MIN_RUNS = 5;\nexport const BASELINE_WINDOW = 20;\n\nexport function emptyState(job: string): JobState {\n return { job, open: {}, consecutiveFailures: 0, silencedUntil: null, lastAlertAt: null };\n}\n\nfunction cloneState(state: JobState): JobState {\n return { ...state, open: { ...state.open } };\n}\n\nfunction openCondition(state: JobState, condition: Condition, now: number): boolean {\n if (state.open[condition] !== undefined) return false;\n state.open[condition] = now;\n return true;\n}\n\nfunction closeCondition(state: JobState, condition: Condition): boolean {\n if (state.open[condition] === undefined) return false;\n delete state.open[condition];\n return true;\n}\n\nexport function openConditions(state: JobState): Condition[] {\n return Object.keys(state.open) as Condition[];\n}\n\nexport function graceMs(def: Pick<JobDefinition, \"grace\">): number {\n return def.grace === undefined ? DEFAULT_GRACE_MS : parseDuration(def.grace, \"grace\");\n}\n\nexport function timeoutMs(def: Pick<JobDefinition, \"timeout\">): number {\n return def.timeout === undefined ? DEFAULT_TIMEOUT_MS : parseDuration(def.timeout, \"timeout\");\n}\n\n/** Slow threshold for a successful run, or null when there is nothing to compare against yet. */\nexport function slowThreshold(def: Pick<JobDefinition, \"maxDuration\">, history: Run[]): { thresholdMs: number; basis: string } | null {\n if (def.maxDuration !== undefined) {\n return { thresholdMs: parseDuration(def.maxDuration, \"maxDuration\"), basis: \"maxDuration\" };\n }\n const durations = history\n .filter((r) => r.status === \"ok\" && r.durationMs !== null)\n .slice(0, BASELINE_WINDOW)\n .map((r) => r.durationMs!);\n if (durations.length < BASELINE_MIN_RUNS) return null;\n const p95 = percentile(durations, 95)!;\n return { thresholdMs: Math.max(2 * p95, SLOW_FLOOR_MS), basis: `twice the p95 of the last ${durations.length} runs (${formatDuration(p95)})` };\n}\n\nexport interface BudgetBreach {\n metric: string;\n value: number;\n limit: number;\n basis: string;\n}\n\nexport function budgetBreaches(def: Pick<JobDefinition, \"budget\">, run: Run, history: Run[]): BudgetBreach[] {\n const breaches: BudgetBreach[] = [];\n for (const [metric, value] of Object.entries(run.metrics)) {\n const ceiling = def.budget?.[metric];\n if (ceiling !== undefined) {\n if (value > ceiling) breaches.push({ metric, value, limit: ceiling, basis: \"budget\" });\n continue;\n }\n const past = history\n .filter((r) => r.status === \"ok\" && typeof r.metrics[metric] === \"number\")\n .slice(0, BASELINE_WINDOW)\n .map((r) => r.metrics[metric]!);\n if (past.length < BASELINE_MIN_RUNS) continue;\n const usual = median(past)!;\n if (usual > 0 && value > 3 * usual) {\n breaches.push({ metric, value, limit: 3 * usual, basis: `three times the usual ${formatNumber(usual)}` });\n }\n }\n return breaches;\n}\n\nexport function formatNumber(n: number): string {\n if (Number.isInteger(n)) return n.toLocaleString(\"en-US\");\n return n.toLocaleString(\"en-US\", { maximumFractionDigits: 4 });\n}\n\n/**\n * Called when a run starts. Missed and stuck are about the absence of a run,\n * so a run starting closes them without an alert. Returns which conditions\n * were open beforehand, for the recovered message at the end.\n */\nexport function onRunStart(state: JobState): { state: JobState; openBefore: Condition[] } {\n const next = cloneState(state);\n const openBefore = openConditions(next);\n closeCondition(next, \"missed\");\n closeCondition(next, \"stuck\");\n return { state: next, openBefore };\n}\n\n/**\n * Called when a run finishes with status ok, failed or timeout. `history` is\n * the job's earlier runs, newest first, not including this one.\n */\nexport function onRunFinish(\n def: JobDefinition | StoredJobDefinition,\n run: Run,\n state: JobState,\n history: Run[],\n openBefore: Condition[],\n now: number,\n): Evaluation {\n const next = cloneState(state);\n const alerts: AlertDraft[] = [];\n\n if (run.status === \"ok\") {\n next.consecutiveFailures = 0;\n closeCondition(next, \"failed\");\n closeCondition(next, \"missed\");\n closeCondition(next, \"stuck\");\n\n const slow = slowThreshold(def, history);\n if (slow && run.durationMs !== null && run.durationMs > slow.thresholdMs) {\n if (openCondition(next, \"slow\", now)) {\n alerts.push({ type: \"slow\", run, details: { durationMs: run.durationMs, thresholdMs: slow.thresholdMs, basis: slow.basis } });\n }\n } else {\n closeCondition(next, \"slow\");\n }\n\n const breaches = budgetBreaches(def, run, history);\n if (breaches.length > 0) {\n if (openCondition(next, \"over_budget\", now)) {\n alerts.push({ type: \"over_budget\", run, details: { breaches } });\n }\n } else {\n closeCondition(next, \"over_budget\");\n }\n\n const wasOpen = new Set([...openBefore, ...openConditions(state)]);\n if (wasOpen.size > 0 && openConditions(next).length === 0) {\n alerts.push({ type: \"recovered\", run, details: { after: [...wasOpen] } });\n }\n return { state: next, alerts };\n }\n\n // failed or timeout\n next.consecutiveFailures += 1;\n closeCondition(next, \"missed\");\n const threshold = Math.max(1, def.failuresBeforeAlert ?? 1);\n const condition: Condition = run.status === \"timeout\" ? \"stuck\" : \"failed\";\n if (next.consecutiveFailures >= threshold) {\n if (openCondition(next, condition, now)) {\n alerts.push({ type: condition, run, details: { consecutiveFailures: next.consecutiveFailures, threshold } });\n }\n }\n return { state: next, alerts };\n}\n\n/**\n * Called by check(). Decides whether the schedule has been missed. `lastRun`\n * is the most recent run of any status.\n */\nexport function onCheck(\n def: StoredJobDefinition,\n stored: StoredJob,\n lastRun: Run | null,\n state: JobState,\n now: number,\n): Evaluation & { nextExpectedAt: number | null; dueAt: number | null } {\n const next = cloneState(state);\n const alerts: AlertDraft[] = [];\n if (!def.schedule) return { state: next, alerts, nextExpectedAt: null, dueAt: null };\n\n const parsed = parseSchedule(def.schedule, def.timezone);\n const grace = graceMs(def);\n const exp = expectation(parsed, now, lastRun?.startedAt ?? null, stored.createdAt, grace);\n\n let nextExpectedAt: number | null = null;\n if (parsed.kind === \"interval\") {\n nextExpectedAt = (lastRun?.startedAt ?? stored.createdAt) + parsed.everyMs!;\n } else {\n const upcoming = parsed.cron!.nextRun(new Date(now));\n nextExpectedAt = upcoming ? upcoming.getTime() : null;\n }\n\n if (!exp) return { state: next, alerts, nextExpectedAt, dueAt: null };\n\n // For a cron, a run at or after the fire covers it. For an interval the due\n // time is computed from the last run itself, so only the deadline matters.\n const covered = parsed.kind === \"cron\" && lastRun !== null && runCovers(lastRun.startedAt, exp.dueAt);\n if (covered) {\n closeCondition(next, \"missed\");\n } else if (now > exp.deadline) {\n if (openCondition(next, \"missed\", now)) {\n alerts.push({\n type: \"missed\",\n run: lastRun,\n details: { dueAt: exp.dueAt, deadline: exp.deadline, graceMs: grace, lastRunAt: lastRun?.startedAt ?? null },\n });\n }\n }\n return { state: next, alerts, nextExpectedAt, dueAt: exp.dueAt };\n}\n\n/** Whether a running run has gone on longer than the job's timeout. */\nexport function isStuck(def: Pick<JobDefinition, \"timeout\">, run: Run, now: number): boolean {\n return run.status === \"running\" && now - run.startedAt > timeoutMs(def);\n}\n\n/**\n * While a job is silenced nothing new is recorded as an incident: conditions\n * may close (so a job that recovered during the silence shows as healthy) but\n * none may open, so the first problem after the silence ends alerts normally.\n */\nexport function muteOpens(previous: JobState, next: JobState): JobState {\n const muted = cloneState(next);\n for (const condition of openConditions(muted)) {\n if (previous.open[condition] === undefined) delete muted.open[condition];\n }\n return muted;\n}\n\nexport function isSilenced(state: JobState, now: number): boolean {\n return state.silencedUntil !== null && state.silencedUntil > now;\n}\n","import { formatDuration, formatRelative } from \"./duration.js\";\nimport type { AlertDraft, BudgetBreach } from \"./evaluate.js\";\nimport { formatNumber } from \"./evaluate.js\";\nimport type { Alert, StoredJobDefinition } from \"./types.js\";\n\nfunction when(at: number | null | undefined, now: number): string {\n if (at === null || at === undefined) return \"never\";\n return `${new Date(at).toISOString().replace(\"T\", \" \").slice(0, 19)} UTC (${formatRelative(at, now)})`;\n}\n\nfunction firstLines(text: string | null, n: number): string {\n if (!text) return \"\";\n return text.split(\"\\n\").slice(0, n).join(\"\\n\");\n}\n\nfunction tail(text: string | null, n: number): string {\n if (!text) return \"\";\n const lines = text.trimEnd().split(\"\\n\");\n return lines.slice(Math.max(0, lines.length - n)).join(\"\\n\");\n}\n\n/** Turns a draft into the title and message every channel shows. */\nexport function composeAlert(draft: AlertDraft, def: StoredJobDefinition, now: number): Alert {\n const name = def.name;\n const run = draft.run;\n const d = draft.details;\n let title: string;\n const lines: string[] = [];\n\n switch (draft.type) {\n case \"missed\": {\n title = `${name} missed its scheduled run`;\n lines.push(`Due ${when(d.dueAt as number, now)}, and no run had started by ${when(d.deadline as number, now)} (grace ${formatDuration(d.graceMs as number)}).`);\n lines.push(`Schedule: ${def.schedule}${def.timezone ? ` (${def.timezone})` : \"\"}.`);\n lines.push(`Last run: ${run ? `${run.status} ${when(run.startedAt, now)}` : \"never\"}.`);\n break;\n }\n case \"failed\": {\n title = `${name} failed`;\n const n = d.consecutiveFailures as number;\n if (n > 1) lines.push(`${n} consecutive failures.`);\n if (run) {\n lines.push(`Started ${when(run.startedAt, now)}${run.durationMs !== null ? `, ran ${formatDuration(run.durationMs)}` : \"\"}.`);\n if (run.error) lines.push(`Error: ${firstLines(run.error, 4)}`);\n const out = tail(run.output, 8);\n if (out) lines.push(`Output (tail):\\n${out}`);\n }\n break;\n }\n case \"stuck\": {\n title = `${name} is stuck`;\n if (run) {\n lines.push(`Started ${when(run.startedAt, now)} and never reported finishing. Marked as timed out after ${formatDuration(run.durationMs ?? now - run.startedAt)}.`);\n const out = tail(run.output, 8);\n if (out) lines.push(`Output so far (tail):\\n${out}`);\n }\n lines.push(`If the process was killed mid-run (a serverless timeout, a deploy), this is what that looks like.`);\n break;\n }\n case \"slow\": {\n title = `${name} was slow`;\n lines.push(`Took ${formatDuration(d.durationMs as number)}; the limit is ${formatDuration(d.thresholdMs as number)} (${d.basis}).`);\n if (run) lines.push(`Started ${when(run.startedAt, now)}.`);\n break;\n }\n case \"over_budget\": {\n title = `${name} went over budget`;\n for (const b of d.breaches as BudgetBreach[]) {\n lines.push(`${b.metric}: ${formatNumber(b.value)}, limit ${formatNumber(b.limit)} (${b.basis}).`);\n }\n if (run) lines.push(`Started ${when(run.startedAt, now)}.`);\n break;\n }\n case \"recovered\": {\n title = `${name} recovered`;\n const after = (d.after as string[]).map((c) => c.replace(\"_\", \" \")).join(\", \");\n lines.push(`A run ${run ? when(run.startedAt, now) : \"just now\"} succeeded${after ? ` after: ${after}` : \"\"}.`);\n if (run?.durationMs !== null && run?.durationMs !== undefined) lines.push(`Ran ${formatDuration(run.durationMs)}.`);\n break;\n }\n }\n\n return {\n type: draft.type,\n job: name,\n definition: def,\n run,\n title,\n message: lines.join(\"\\n\"),\n details: d,\n at: now,\n };\n}\n","export function json(body: unknown, status = 200, headers: Record<string, string> = {}): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { \"content-type\": \"application/json; charset=utf-8\", \"cache-control\": \"no-store\", ...headers },\n });\n}\n","/** Output is capped so a chatty job cannot fill the store. The tail is kept. */\nexport const OUTPUT_CAP = 16 * 1024;\n\nexport function capOutput(text: string): string {\n if (text.length <= OUTPUT_CAP) return text;\n return \"[earlier output trimmed]\\n\" + text.slice(text.length - OUTPUT_CAP);\n}\n\nexport function errorMessage(error: unknown): string {\n if (error instanceof Error) {\n const stack = error.stack ? `\\n${error.stack.split(\"\\n\").slice(1, 6).join(\"\\n\")}` : \"\";\n return `${error.name}: ${error.message}${stack}`;\n }\n if (typeof error === \"string\") return error;\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n}\n","import { capOutput } from \"./output.js\";\nimport type { Run } from \"./types.js\";\n\n/** What a job function receives. */\nexport interface JobContext {\n readonly name: string;\n readonly runId: string;\n readonly startedAt: number;\n /** Aborts when the job's timeout elapses. Honour it if the work can stop. */\n readonly signal: AbortSignal;\n /** Append a line of output. Kept with the run, capped at 16 KB, shown in alerts and the dashboard. */\n log(...parts: unknown[]): void;\n /** Report a number for this run: tokens, cost, rows, anything. Watched against budgets and baselines. */\n metric(name: string, value: number): void;\n metrics(values: Record<string, number>): void;\n}\n\nexport interface RunRecorder {\n context: JobContext;\n output(): string | null;\n metrics(): Record<string, number>;\n abort(): void;\n}\n\nfunction stringify(part: unknown): string {\n if (typeof part === \"string\") return part;\n if (part instanceof Error) return `${part.name}: ${part.message}`;\n try {\n return JSON.stringify(part);\n } catch {\n return String(part);\n }\n}\n\nexport function createRecorder(run: Run): RunRecorder {\n const lines: string[] = [];\n let size = 0;\n const metrics: Record<string, number> = {};\n const controller = new AbortController();\n\n const context: JobContext = {\n name: run.job,\n runId: run.id,\n startedAt: run.startedAt,\n signal: controller.signal,\n log(...parts) {\n const line = parts.map(stringify).join(\" \");\n lines.push(line);\n size += line.length + 1;\n // Drop from the front once well past the cap; capOutput trims exactly at the end.\n while (size > 64 * 1024 && lines.length > 1) {\n size -= lines.shift()!.length + 1;\n }\n },\n metric(name, value) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(`metric \"${name}\" must be a finite number`);\n }\n metrics[name] = value;\n },\n metrics(values) {\n for (const [k, v] of Object.entries(values)) context.metric(k, v);\n },\n };\n\n return {\n context,\n output: () => (lines.length === 0 ? null : capOutput(lines.join(\"\\n\"))),\n metrics: () => ({ ...metrics }),\n abort: () => controller.abort(),\n };\n}\n","import type { JobDefinition, StoredJobDefinition } from \"./types.js\";\n\n/** A definition as a store can hold it: `expect` becomes a description. */\nexport function toStored(def: JobDefinition): StoredJobDefinition {\n const { expect, ...rest } = def;\n const stored: StoredJobDefinition = { ...rest };\n if (expect !== undefined) {\n stored.expect =\n typeof expect === \"string\" ? `contains ${JSON.stringify(expect)}`\n : expect instanceof RegExp ? `matches ${expect.toString()}`\n : \"custom function\";\n }\n return stored;\n}\n\nexport function checkExpectation(expect: JobDefinition[\"expect\"], output: string | null): string | null {\n if (expect === undefined) return null;\n const text = output ?? \"\";\n if (typeof expect === \"string\") {\n return text.includes(expect) ? null : `Output did not contain ${JSON.stringify(expect)}`;\n }\n if (expect instanceof RegExp) {\n return expect.test(text) ? null : `Output did not match ${expect.toString()}`;\n }\n let ok = false;\n try {\n ok = expect(text);\n } catch (error) {\n return `Output check threw: ${(error as Error).message}`;\n }\n return ok ? null : \"Output did not pass the expect() check\";\n}\n","import { formatDuration, formatRelative } from \"../duration.js\";\nimport type { JobSummary, Run } from \"../types.js\";\n\nexport function escapeHtml(value: unknown): string {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nconst h = escapeHtml;\n\nconst CSS = `\n:root{--bg:#fbfbf9;--fg:#1b1b18;--muted:#6b6b64;--line:#e6e5df;--card:#fff;--ok:#1f8a4c;--warn:#b7791f;--bad:#c62828;--info:#2b5fb3;--pill:#f1f0ea;--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;--sans:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Inter,Roboto,sans-serif}\n@media(prefers-color-scheme:dark){:root{--bg:#121311;--fg:#ecece6;--muted:#9a9a91;--line:#2a2b27;--card:#1a1b18;--pill:#24251f}}\n*{box-sizing:border-box}html{-webkit-text-size-adjust:100%}\nbody{margin:0;background:var(--bg);color:var(--fg);font:15px/1.5 var(--sans)}\na{color:inherit}main{max-width:1080px;margin:0 auto;padding:24px 16px 64px}\nheader{display:flex;align-items:baseline;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:20px}\nheader h1{font-size:18px;margin:0;letter-spacing:-.01em}header h1 a{text-decoration:none}\nheader .meta{color:var(--muted);font-size:13px}\n.card{background:var(--card);border:1px solid var(--line);border-radius:10px;overflow:hidden}\ntable{width:100%;border-collapse:collapse;font-size:14px}\nth{text-align:left;font-weight:600;color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 12px;border-bottom:1px solid var(--line);white-space:nowrap}\ntd{padding:10px 12px;border-bottom:1px solid var(--line);vertical-align:top}\ntr:last-child td{border-bottom:0}\n.name{font-weight:600;white-space:nowrap}.name a{text-decoration:none}.name a:hover{text-decoration:underline}\n.mono{font-family:var(--mono);font-size:13px}.muted{color:var(--muted)}.nowrap{white-space:nowrap}\n.pill{display:inline-flex;align-items:center;gap:6px;padding:2px 9px;border-radius:999px;background:var(--pill);font-size:12px;font-weight:600;white-space:nowrap}\n.pill::before{content:\"\";width:7px;height:7px;border-radius:50%;background:currentColor}\n.ok{color:var(--ok)}.warn{color:var(--warn)}.bad{color:var(--bad)}.info{color:var(--info)}.mutedpill{color:var(--muted)}\n.spark{display:block}\nform.inline{display:inline}\nbutton,select{font:inherit;font-size:13px;padding:5px 10px;border:1px solid var(--line);border-radius:7px;background:var(--card);color:var(--fg);cursor:pointer}\nbutton:hover{border-color:var(--muted)}\n.actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}\n.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin:0 0 20px}\n.stat{padding:12px 14px}.stat .k{font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}.stat .v{font-size:20px;font-weight:600;margin-top:2px}\npre{margin:0;padding:10px 12px;background:var(--pill);border-radius:8px;font:12.5px/1.45 var(--mono);white-space:pre-wrap;word-break:break-word;max-height:320px;overflow:auto}\ndetails summary{cursor:pointer;color:var(--muted);font-size:13px}details{margin-top:6px}\n.empty{padding:40px 16px;text-align:center;color:var(--muted)}\ndl{display:grid;grid-template-columns:max-content 1fr;gap:6px 16px;margin:0;padding:14px 16px;font-size:14px}dt{color:var(--muted)}dd{margin:0}\nfooter{margin-top:28px;color:var(--muted);font-size:12px}\n@media(max-width:720px){.hide-sm{display:none}main{padding:16px 16px 48px}}\n`;\n\nexport function layout(title: string, body: string, options: { refresh?: number } = {}): string {\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<meta name=\"robots\" content=\"noindex,nofollow\">\n${options.refresh ? `<meta http-equiv=\"refresh\" content=\"${options.refresh}\">` : \"\"}\n<title>${h(title)}</title>\n<style>${CSS}</style>\n</head>\n<body><main>${body}</main></body>\n</html>`;\n}\n\nfunction healthPill(job: JobSummary): string {\n const map: Record<JobSummary[\"health\"], [string, string]> = {\n healthy: [\"ok\", \"healthy\"],\n late: [\"warn\", \"late\"],\n failing: [\"bad\", \"failing\"],\n stuck: [\"bad\", \"stuck\"],\n silenced: [\"mutedpill\", \"silenced\"],\n never_ran: [\"info\", \"never ran\"],\n };\n const [cls, label] = map[job.health];\n const extras = job.open.filter((c) => ![\"missed\", \"failed\", \"stuck\"].includes(c)).map((c) => c.replace(\"_\", \" \"));\n return `<span class=\"pill ${cls}\">${label}</span>${extras.length ? ` <span class=\"pill warn\">${h(extras.join(\", \"))}</span>` : \"\"}`;\n}\n\nfunction runPill(run: Run): string {\n const cls = run.status === \"ok\" ? \"ok\" : run.status === \"running\" ? \"info\" : \"bad\";\n return `<span class=\"pill ${cls}\">${h(run.status)}</span>`;\n}\n\nfunction sparkline(runs: Run[]): string {\n const points = [...runs].reverse().filter((r) => r.durationMs !== null).slice(-20);\n if (points.length < 2) return \"\";\n const w = 96, hgt = 22;\n const max = Math.max(...points.map((r) => r.durationMs!), 1);\n const step = w / (points.length - 1);\n const path = points.map((r, i) => `${i === 0 ? \"M\" : \"L\"}${(i * step).toFixed(1)},${(hgt - 2 - (r.durationMs! / max) * (hgt - 4)).toFixed(1)}`).join(\" \");\n const dots = points.map((r, i) => r.status === \"ok\" ? \"\" : `<circle cx=\"${(i * step).toFixed(1)}\" cy=\"${(hgt - 2 - (r.durationMs! / max) * (hgt - 4)).toFixed(1)}\" r=\"2.2\" fill=\"var(--bad)\"/>`).join(\"\");\n return `<svg class=\"spark\" width=\"${w}\" height=\"${hgt}\" viewBox=\"0 0 ${w} ${hgt}\" aria-hidden=\"true\"><path d=\"${path}\" fill=\"none\" stroke=\"var(--muted)\" stroke-width=\"1.5\"/>${dots}</svg>`;\n}\n\nfunction stamp(at: number | null, now: number): string {\n if (at === null) return `<span class=\"muted\">never</span>`;\n const iso = new Date(at).toISOString().replace(\"T\", \" \").slice(0, 19);\n return `<span class=\"nowrap\" title=\"${iso} UTC\">${h(formatRelative(at, now))}</span>`;\n}\n\nexport function dashboardPage(jobs: JobSummary[], runsByJob: Map<string, Run[]>, now: number, base: string, checkedAt: number | null): string {\n const rows = jobs.map((job) => {\n const last = job.lastRun;\n return `<tr>\n<td class=\"name\"><a href=\"${h(base)}/jobs/${encodeURIComponent(job.name)}\">${h(job.name)}</a>${job.definition.description ? `<div class=\"muted\" style=\"font-weight:400;font-size:13px;white-space:normal\">${h(job.definition.description)}</div>` : \"\"}</td>\n<td>${healthPill(job)}</td>\n<td class=\"mono nowrap\">${h(job.definition.schedule ?? \"\")}<span class=\"muted\">${job.definition.schedule ? \"\" : \"no schedule\"}</span></td>\n<td class=\"nowrap\">${last ? `${runPill(last)} ${stamp(last.startedAt, now)}${last.durationMs !== null ? ` <span class=\"muted\">${h(formatDuration(last.durationMs))}</span>` : \"\"}` : `<span class=\"muted\">never</span>`}</td>\n<td class=\"nowrap hide-sm\">${stamp(job.nextExpectedAt, now)}</td>\n<td class=\"hide-sm\">${sparkline(runsByJob.get(job.name) ?? [])}</td>\n</tr>`;\n }).join(\"\\n\");\n\n const body = `\n<header>\n <h1><a href=\"${h(base)}/\">CronWatch</a></h1>\n <div class=\"actions\">\n <span class=\"meta\">${jobs.length} job${jobs.length === 1 ? \"\" : \"s\"}${checkedAt ? `, checked ${h(formatRelative(checkedAt, now))}` : \"\"}</span>\n <form class=\"inline\" method=\"post\" action=\"${h(base)}/check\"><button type=\"submit\">Run check now</button></form>\n </div>\n</header>\n<div class=\"card\">\n${jobs.length === 0 ? `<div class=\"empty\">No jobs yet. Declare one with <code class=\"mono\">cw.job(\"name\", { schedule: \"0 2 * * *\" })</code> and run it once.</div>` : `<table>\n<thead><tr><th>Job</th><th>Health</th><th>Schedule</th><th>Last run</th><th class=\"hide-sm\">Next due</th><th class=\"hide-sm\">Durations</th></tr></thead>\n<tbody>${rows}</tbody></table>`}\n</div>\n<footer>Refreshes every minute. <a href=\"${h(base)}/api/jobs\">JSON</a></footer>`;\n return layout(\"CronWatch\", body, { refresh: 60 });\n}\n\nexport function jobPage(job: JobSummary, runs: Run[], now: number, base: string): string {\n const d = job.definition;\n const okRate = `${Math.round(job.stats.okRate * 100)}%`;\n const runRows = runs.map((run) => {\n const detail = [\n run.error ? `<details open><summary>error</summary><pre>${h(run.error)}</pre></details>` : \"\",\n run.output ? `<details${run.status === \"ok\" ? \"\" : \" open\"}><summary>output</summary><pre>${h(run.output)}</pre></details>` : \"\",\n ].join(\"\");\n const metrics = Object.entries(run.metrics).map(([k, v]) => `<span class=\"pill mutedpill\">${h(k)} ${h(Number.isInteger(v) ? v : v.toFixed(4))}</span>`).join(\" \");\n return `<tr>\n<td class=\"nowrap\">${runPill(run)}</td>\n<td class=\"nowrap\">${stamp(run.startedAt, now)}</td>\n<td class=\"nowrap\">${run.durationMs !== null ? h(formatDuration(run.durationMs)) : `<span class=\"muted\">running</span>`}</td>\n<td class=\"hide-sm\">${metrics}</td>\n<td class=\"mono hide-sm muted\">${h(run.trigger)}</td>\n</tr>${detail ? `<tr><td colspan=\"5\" style=\"padding-top:0\">${detail}</td></tr>` : \"\"}`;\n }).join(\"\\n\");\n\n const silenced = job.silencedUntil !== null && job.silencedUntil > now;\n const body = `\n<header>\n <h1><a href=\"${h(base)}/\">CronWatch</a> <span class=\"muted\">/</span> ${h(job.name)}</h1>\n <div class=\"actions\">\n ${healthPill(job)}\n ${silenced\n ? `<form class=\"inline\" method=\"post\" action=\"${h(base)}/jobs/${encodeURIComponent(job.name)}/unsilence\"><button type=\"submit\">Unsilence (until ${h(formatRelative(job.silencedUntil!, now))})</button></form>`\n : `<form class=\"inline\" method=\"post\" action=\"${h(base)}/jobs/${encodeURIComponent(job.name)}/silence\"><select name=\"for\"><option value=\"1h\">1 hour</option><option value=\"4h\">4 hours</option><option value=\"1d\">1 day</option><option value=\"7d\">1 week</option></select> <button type=\"submit\">Silence</button></form>`}\n <form class=\"inline\" method=\"post\" action=\"${h(base)}/jobs/${encodeURIComponent(job.name)}/forget\" onsubmit=\"return confirm('Remove this job and its runs from the store?')\"><button type=\"submit\">Forget</button></form>\n </div>\n</header>\n<div class=\"grid\">\n <div class=\"card stat\"><div class=\"k\">Last run</div><div class=\"v\">${job.lastRun ? h(formatRelative(job.lastRun.startedAt, now)) : \"never\"}</div></div>\n <div class=\"card stat\"><div class=\"k\">Next due</div><div class=\"v\">${job.nextExpectedAt ? h(formatRelative(job.nextExpectedAt, now)) : \"no schedule\"}</div></div>\n <div class=\"card stat\"><div class=\"k\">Success, last ${job.stats.runs}</div><div class=\"v\">${okRate}</div></div>\n <div class=\"card stat\"><div class=\"k\">p50 / p95</div><div class=\"v\">${job.stats.p50Ms !== null ? h(formatDuration(job.stats.p50Ms)) : \"?\"} <span class=\"muted\">/</span> ${job.stats.p95Ms !== null ? h(formatDuration(job.stats.p95Ms)) : \"?\"}</div></div>\n</div>\n<div class=\"card\" style=\"margin-bottom:20px\">\n<dl>\n <dt>Schedule</dt><dd class=\"mono\">${d.schedule ? h(d.schedule) + (d.timezone ? ` <span class=\"muted\">${h(d.timezone)}</span>` : \"\") : `<span class=\"muted\">none</span>`}</dd>\n <dt>Grace</dt><dd class=\"mono\">${h(d.grace ?? \"10m\")}</dd>\n <dt>Timeout</dt><dd class=\"mono\">${h(d.timeout ?? \"1h\")}</dd>\n ${d.maxDuration ? `<dt>Max duration</dt><dd class=\"mono\">${h(d.maxDuration)}</dd>` : \"\"}\n ${d.budget ? `<dt>Budget</dt><dd class=\"mono\">${h(Object.entries(d.budget).map(([k, v]) => `${k} ≤ ${v}`).join(\", \"))}</dd>` : \"\"}\n ${d.expect ? `<dt>Expect</dt><dd class=\"mono\">${h(d.expect)}</dd>` : \"\"}\n ${d.failuresBeforeAlert && d.failuresBeforeAlert > 1 ? `<dt>Alert after</dt><dd>${d.failuresBeforeAlert} consecutive failures</dd>` : \"\"}\n ${d.description ? `<dt>Description</dt><dd>${h(d.description)}</dd>` : \"\"}\n ${d.tags?.length ? `<dt>Tags</dt><dd>${d.tags.map((t) => `<span class=\"pill mutedpill\">${h(t)}</span>`).join(\" \")}</dd>` : \"\"}\n ${job.open.length ? `<dt>Open</dt><dd>${job.open.map((c) => `<span class=\"pill warn\">${h(c.replace(\"_\", \" \"))}</span>`).join(\" \")}</dd>` : \"\"}\n ${job.consecutiveFailures > 0 ? `<dt>Consecutive failures</dt><dd>${job.consecutiveFailures}</dd>` : \"\"}\n</dl>\n</div>\n<div class=\"card\">\n${runs.length === 0 ? `<div class=\"empty\">No runs yet.</div>` : `<table>\n<thead><tr><th>Status</th><th>Started</th><th>Duration</th><th class=\"hide-sm\">Metrics</th><th class=\"hide-sm\">Trigger</th></tr></thead>\n<tbody>${runRows}</tbody></table>`}\n</div>\n<footer><a href=\"${h(base)}/api/jobs/${encodeURIComponent(job.name)}\">JSON</a></footer>`;\n return layout(`${job.name}: CronWatch`, body, { refresh: 60 });\n}\n\nexport function messagePage(title: string, message: string, base: string): string {\n return layout(title, `<header><h1><a href=\"${h(base)}/\">CronWatch</a></h1></header><div class=\"card\"><div class=\"empty\"><strong>${h(title)}</strong><br>${h(message)}</div></div>`);\n}\n","import type { CronWatch } from \"../client.js\";\nimport { json } from \"../http.js\";\nimport { parseDuration } from \"../duration.js\";\nimport type { Run } from \"../types.js\";\nimport { dashboardPage, jobPage, messagePage } from \"./html.js\";\n\nexport interface RoutesOptions {\n /**\n * Required to reach anything. Send it as `Authorization: Bearer <token>`,\n * or open the dashboard once with `?token=<token>` and a cookie is set.\n * Defaults to process.env.CRONWATCH_TOKEN. With no token at all, the routes\n * are open in development and refuse to serve in production.\n *\n * The check endpoint (/api/check) also accepts the client's cronSecret, so\n * a platform cron that sends `Authorization: Bearer <CRON_SECRET>` can\n * trigger checks without knowing the dashboard token.\n */\n token?: string | null;\n /** Where the routes are mounted, so links resolve. Default \"/cronwatch\". */\n basePath?: string;\n}\n\nexport type FetchHandler = (request: Request) => Promise<Response>;\n\nexport interface Routes {\n handler: FetchHandler;\n GET: FetchHandler;\n POST: FetchHandler;\n DELETE: FetchHandler;\n}\n\nconst COOKIE = \"cronwatch_token\";\n\nfunction constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n\nfunction readCookie(request: Request, name: string): string | null {\n const header = request.headers.get(\"cookie\");\n if (!header) return null;\n for (const part of header.split(\";\")) {\n const [k, ...rest] = part.trim().split(\"=\");\n if (k === name) return decodeURIComponent(rest.join(\"=\"));\n }\n return null;\n}\n\nfunction stripBase(pathname: string, base: string): string {\n let path = pathname.startsWith(base) ? pathname.slice(base.length) : pathname;\n if (path === \"\") path = \"/\";\n if (path.length > 1 && path.endsWith(\"/\")) path = path.slice(0, -1);\n return path;\n}\n\nasync function readBody(request: Request): Promise<Record<string, string>> {\n const type = request.headers.get(\"content-type\") ?? \"\";\n try {\n if (type.includes(\"application/json\")) {\n const data = await request.json();\n return typeof data === \"object\" && data !== null ? Object.fromEntries(Object.entries(data).map(([k, v]) => [k, String(v)])) : {};\n }\n if (type.includes(\"application/x-www-form-urlencoded\") || type.includes(\"multipart/form-data\")) {\n const form = await request.formData();\n const out: Record<string, string> = {};\n for (const [k, v] of form.entries()) out[k] = String(v);\n return out;\n }\n } catch {\n return {};\n }\n return {};\n}\n\n/**\n * A fetch-style handler serving the dashboard and a small JSON API. Mount it\n * in a Next.js app at app/cronwatch/[[...path]]/route.ts:\n *\n * export const { GET, POST, DELETE } = cw.routes();\n */\nexport function createRoutes(cw: CronWatch, options: RoutesOptions = {}): Routes {\n const token = options.token === undefined ? (process.env.CRONWATCH_TOKEN ?? null) : options.token;\n const base = (options.basePath ?? \"/cronwatch\").replace(/\\/+$/, \"\");\n const production = process.env.NODE_ENV === \"production\";\n\n const handler: FetchHandler = async (request) => {\n const url = new URL(request.url);\n const path = stripBase(url.pathname, base);\n const wantsHtml = !path.startsWith(\"/api\");\n const method = request.method.toUpperCase();\n\n if (!token && production) {\n return wantsHtml\n ? html(messagePage(\"CronWatch routes are locked\", \"Set CRONWATCH_TOKEN (or pass token to cw.routes()) to use them in production.\", base), 503)\n : json({ ok: false, error: \"CRONWATCH_TOKEN is not set\" }, 503);\n }\n\n if (token) {\n const bearer = request.headers.get(\"authorization\")?.replace(/^Bearer\\s+/i, \"\") ?? null;\n const query = url.searchParams.get(\"token\");\n const cookie = readCookie(request, COOKIE);\n const presented = bearer ?? query ?? cookie;\n const isCheck = path === \"/api/check\";\n const cronSecretOk = isCheck && bearer !== null && cw.cronSecret !== null && constantTimeEqual(bearer, cw.cronSecret);\n if (!cronSecretOk && (presented === null || !constantTimeEqual(presented, token))) {\n return wantsHtml\n ? html(messagePage(\"Sign in\", `Open this page with ?token=<your CRONWATCH_TOKEN> once and it will stay signed in.`, base), 401)\n : json({ ok: false, error: \"Unauthorized\" }, 401);\n }\n if (query !== null && wantsHtml && method === \"GET\") {\n // Move the token from the URL into a cookie so it is not in history or logs.\n url.searchParams.delete(\"token\");\n const secure = url.protocol === \"https:\" ? \"; Secure\" : \"\";\n return new Response(null, {\n status: 303,\n headers: {\n location: url.pathname + (url.search || \"\"),\n \"set-cookie\": `${COOKIE}=${encodeURIComponent(token)}; Path=${base || \"/\"}; HttpOnly; SameSite=Lax; Max-Age=${60 * 60 * 24 * 30}${secure}`,\n },\n });\n }\n }\n\n const redirectBack = () => {\n const referer = request.headers.get(\"referer\") ?? \"\";\n const location = referer.startsWith(url.origin + \"/\") ? referer : `${base}/`;\n return new Response(null, { status: 303, headers: { location } });\n };\n const jobName = (segment: string | undefined) => (segment ? decodeURIComponent(segment) : \"\");\n const parts = path.split(\"/\").filter(Boolean);\n\n // HTML\n if (method === \"GET\" && path === \"/\") {\n const jobs = await cw.jobs();\n const runsByJob = new Map<string, Run[]>();\n for (const job of jobs) runsByJob.set(job.name, await cw.runs(job.name, 20));\n return html(dashboardPage(jobs, runsByJob, cw.now(), base, null));\n }\n if (method === \"GET\" && parts[0] === \"jobs\" && parts.length === 2) {\n const job = await cw.jobSummary(jobName(parts[1]));\n if (!job) return html(messagePage(\"No such job\", `${jobName(parts[1])} is not in the store.`, base), 404);\n return html(jobPage(job, await cw.runs(job.name, 50), cw.now(), base));\n }\n if (method === \"POST\" && path === \"/check\") {\n await cw.check();\n return redirectBack();\n }\n if (method === \"POST\" && parts[0] === \"jobs\" && parts.length === 3) {\n const name = jobName(parts[1]);\n const body = await readBody(request);\n if (parts[2] === \"silence\") await cw.silence(name, safeDuration(body.for, \"1h\"));\n else if (parts[2] === \"unsilence\") await cw.unsilence(name);\n else if (parts[2] === \"forget\") {\n await cw.forget(name);\n return new Response(null, { status: 303, headers: { location: `${base}/` } });\n } else return html(messagePage(\"Not found\", path, base), 404);\n return redirectBack();\n }\n\n // JSON API\n if (parts[0] === \"api\") {\n const rest = parts.slice(1);\n if (method === \"GET\" && rest[0] === \"jobs\" && rest.length === 1) {\n return json({ ok: true, jobs: await cw.jobs() });\n }\n if (rest[0] === \"jobs\" && rest.length === 2) {\n const name = jobName(rest[1]);\n if (method === \"GET\") {\n const job = await cw.jobSummary(name);\n if (!job) return json({ ok: false, error: \"No such job\" }, 404);\n const limit = Number(url.searchParams.get(\"runs\") ?? 20);\n return json({ ok: true, job, runs: await cw.runs(name, Number.isFinite(limit) ? limit : 20) });\n }\n if (method === \"DELETE\") {\n await cw.forget(name);\n return json({ ok: true });\n }\n }\n if (method === \"POST\" && rest[0] === \"jobs\" && rest.length === 3) {\n const name = jobName(rest[1]);\n if (!(await cw.jobSummary(name))) return json({ ok: false, error: \"No such job\" }, 404);\n const body = await readBody(request);\n if (rest[2] === \"silence\") return json({ ok: true, state: await cw.silence(name, safeDuration(body.for ?? url.searchParams.get(\"for\"), \"1h\")) });\n if (rest[2] === \"unsilence\") return json({ ok: true, state: await cw.unsilence(name) });\n }\n if ((method === \"GET\" || method === \"POST\") && rest[0] === \"check\" && rest.length === 1) {\n const result = await cw.check();\n return json({ ok: true, ...result });\n }\n if (method === \"GET\" && rest[0] === \"runs\" && rest.length === 2) {\n const run = await cw.getRun(rest[1]!);\n return run ? json({ ok: true, run }) : json({ ok: false, error: \"No such run\" }, 404);\n }\n return json({ ok: false, error: \"Not found\" }, 404);\n }\n\n return html(messagePage(\"Not found\", path, base), 404);\n };\n\n return { handler, GET: handler, POST: handler, DELETE: handler };\n}\n\nfunction safeDuration(value: string | null | undefined, fallback: string): string {\n if (!value) return fallback;\n try {\n parseDuration(value);\n return value;\n } catch {\n return fallback;\n }\n}\n\nfunction html(body: string, status = 200): Response {\n return new Response(body, {\n status,\n headers: { \"content-type\": \"text/html; charset=utf-8\", \"cache-control\": \"no-store\", \"x-robots-tag\": \"noindex\" },\n });\n}\n","import type { JobState, Run, Store, StoredJob, StoredJobDefinition } from \"../types.js\";\n\n/**\n * Keeps everything in process memory. The default when no store is given,\n * good for tests and for trying the library out. State is gone on restart,\n * so a missed run cannot be noticed across one.\n */\nexport function memory(): Store {\n const jobs = new Map<string, StoredJob>();\n const runs = new Map<string, Run>();\n const order = new Map<string, number>();\n const states = new Map<string, JobState>();\n let seq = 0;\n\n const clone = <T>(v: T): T => JSON.parse(JSON.stringify(v));\n\n return {\n async upsertJob(definition: StoredJobDefinition, now: number) {\n const existing = jobs.get(definition.name);\n jobs.set(definition.name, {\n name: definition.name,\n definition: clone(definition),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n });\n },\n async getJob(name) {\n const j = jobs.get(name);\n return j ? clone(j) : null;\n },\n async listJobs() {\n return [...jobs.values()].map(clone).sort((a, b) => a.name.localeCompare(b.name));\n },\n async deleteJob(name) {\n jobs.delete(name);\n states.delete(name);\n for (const [id, run] of runs) if (run.job === name) { runs.delete(id); order.delete(id); }\n },\n async insertRun(run) {\n runs.set(run.id, clone(run));\n order.set(run.id, ++seq);\n },\n async updateRun(run) {\n runs.set(run.id, clone(run));\n },\n async getRun(id) {\n const r = runs.get(id);\n return r ? clone(r) : null;\n },\n async listRuns(job, limit) {\n return [...runs.values()]\n .filter((r) => r.job === job)\n .sort((a, b) => b.startedAt - a.startedAt || order.get(b.id)! - order.get(a.id)!)\n .slice(0, limit)\n .map(clone);\n },\n async lastRun(job) {\n const list = await this.listRuns(job, 1);\n return list[0] ?? null;\n },\n async runningRuns() {\n return [...runs.values()].filter((r) => r.status === \"running\").map(clone);\n },\n async getState(job) {\n const s = states.get(job);\n return s ? clone(s) : null;\n },\n async setState(state) {\n states.set(state.job, clone(state));\n },\n async prune(before) {\n let n = 0;\n for (const [id, run] of runs) {\n if (run.status !== \"running\" && run.startedAt < before) {\n runs.delete(id);\n order.delete(id);\n n++;\n }\n }\n return n;\n },\n };\n}\n","import { parseDuration } from \"./duration.js\";\nimport {\n BASELINE_WINDOW,\n emptyState,\n isSilenced,\n isStuck,\n muteOpens,\n onCheck,\n onRunFinish,\n onRunStart,\n openConditions,\n timeoutMs,\n} from \"./evaluate.js\";\nimport type { AlertDraft, Evaluation } from \"./evaluate.js\";\nimport { composeAlert } from \"./format.js\";\nimport { json } from \"./http.js\";\nimport { createRecorder } from \"./job.js\";\nimport type { JobContext } from \"./job.js\";\nimport { errorMessage } from \"./output.js\";\nimport { parseSchedule } from \"./schedule.js\";\nimport { checkExpectation, toStored } from \"./serialize.js\";\nimport { percentile } from \"./stats.js\";\nimport { createRoutes } from \"./routes/index.js\";\nimport type { Routes, RoutesOptions } from \"./routes/index.js\";\nimport { memory } from \"./stores/memory.js\";\nimport type {\n Alert,\n AlertChannel,\n CheckResult,\n Condition,\n Duration,\n JobDefinition,\n JobOptions,\n JobState,\n JobSummary,\n Run,\n Store,\n StoredJob,\n StoredJobDefinition,\n TriageFn,\n} from \"./types.js\";\n\nexport type JobFn<T> = (job: JobContext) => Promise<T> | T;\nexport type HandlerFn<T> = (job: JobContext, request: Request) => Promise<T> | T;\n\nexport interface HandlerOptions {\n /**\n * Callers must send `Authorization: Bearer <secret>`. Defaults to the\n * client's cronSecret, which defaults to process.env.CRON_SECRET (what\n * Vercel sends its cron requests with). Pass null to allow anyone.\n */\n secret?: string | null;\n}\n\nexport interface JobHandle {\n readonly name: string;\n readonly definition: JobDefinition;\n /** Run the function now, recording the run. Rethrows whatever the function throws. */\n run<T>(fn: JobFn<T>, options?: { trigger?: string }): Promise<T>;\n /** A fetch-style request handler (Next.js route, Hono, Bun, Deno) that runs the function and records the run. */\n handler<T>(fn: HandlerFn<T>, options?: HandlerOptions): (request: Request) => Promise<Response>;\n}\n\nexport interface CronWatchOptions {\n /** Where jobs, runs and state live. Defaults to an in-memory store that forgets on restart. */\n store?: Store;\n /** Where alerts go. Defaults to the console. */\n alerts?: AlertChannel[];\n /** Adds a short diagnosis to failure alerts. See @cronwatch/sdk/anthropic. */\n triage?: TriageFn;\n /** Shared secret that handler() requests must carry. Defaults to process.env.CRON_SECRET. */\n cronSecret?: string | null;\n /** How long finished runs are kept. Default \"30d\". */\n retention?: Duration;\n /** Applied to every job unless the job sets its own. */\n defaults?: Pick<JobOptions, \"grace\" | \"timeout\" | \"timezone\" | \"failuresBeforeAlert\">;\n /** Called with anything that goes wrong outside a job: an alert channel failing, a triage timeout. */\n onError?: (error: unknown, where: string) => void;\n /** The clock. Tests use this. */\n now?: () => number;\n}\n\nexport interface ExecuteResult<T> {\n run: Run;\n result: T | undefined;\n error: unknown;\n threw: boolean;\n}\n\nconst NAME_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,119}$/;\nconst TRIAGE_TIMEOUT_MS = 25_000;\nconst PRUNE_INTERVAL_MS = 60 * 60_000;\n\nfunction constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n\nexport class CronWatch {\n readonly store: Store;\n readonly alerts: AlertChannel[];\n readonly triage: TriageFn | undefined;\n readonly cronSecret: string | null;\n readonly retentionMs: number;\n readonly now: () => number;\n readonly onError: (error: unknown, where: string) => void;\n private readonly defaults: NonNullable<CronWatchOptions[\"defaults\"]>;\n private readonly definitions = new Map<string, JobDefinition>();\n private readonly synced = new Set<string>();\n private ready: Promise<void> | null = null;\n private checking: Promise<CheckResult> | null = null;\n private lastPruneAt = 0;\n private timer: ReturnType<typeof setInterval> | null = null;\n private usingDefaultStore = false;\n\n constructor(options: CronWatchOptions = {}) {\n this.store = options.store ?? (this.usingDefaultStore = true, memory());\n this.alerts = options.alerts ?? [consoleChannel()];\n this.triage = options.triage;\n this.cronSecret = options.cronSecret === undefined ? (process.env.CRON_SECRET ?? null) : options.cronSecret;\n this.retentionMs = parseDuration(options.retention ?? \"30d\", \"retention\");\n this.defaults = options.defaults ?? {};\n this.now = options.now ?? (() => Date.now());\n this.onError = options.onError ?? ((error, where) => console.error(`[cronwatch] ${where}:`, error));\n }\n\n /** Declare a job. Call it once, at module level, and keep the handle. */\n job(name: string, options: JobOptions = {}): JobHandle {\n if (!NAME_RE.test(name)) {\n throw new Error(`job name \"${name}\" must be 1 to 120 characters of letters, digits, \".\", \"_\", \":\" or \"-\"`);\n }\n const definition: JobDefinition = { ...this.defaults, ...options, name };\n if (definition.schedule) parseSchedule(definition.schedule, definition.timezone);\n if (definition.grace !== undefined) parseDuration(definition.grace, \"grace\");\n if (definition.timeout !== undefined) parseDuration(definition.timeout, \"timeout\");\n if (definition.maxDuration !== undefined) parseDuration(definition.maxDuration, \"maxDuration\");\n this.definitions.set(name, definition);\n this.synced.delete(name);\n return this.handle(definition);\n }\n\n /** Run a job by name without keeping a handle. Defines it on first use. */\n run<T>(name: string, fn: JobFn<T>): Promise<T>;\n run<T>(name: string, options: JobOptions, fn: JobFn<T>): Promise<T>;\n run<T>(name: string, optionsOrFn: JobOptions | JobFn<T>, maybeFn?: JobFn<T>): Promise<T> {\n const fn = typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!;\n const options = typeof optionsOrFn === \"function\" ? undefined : optionsOrFn;\n const handle = options || !this.definitions.has(name) ? this.job(name, options) : this.handle(this.definitions.get(name)!);\n return handle.run(fn);\n }\n\n /** The definitions declared in this process. */\n definedJobs(): JobDefinition[] {\n return [...this.definitions.values()];\n }\n\n private handle(definition: JobDefinition): JobHandle {\n const self = this;\n return {\n name: definition.name,\n definition,\n async run<T>(fn: JobFn<T>, options?: { trigger?: string }): Promise<T> {\n const outcome = await self.execute(definition, fn, options?.trigger ?? \"run\");\n if (outcome.threw) throw outcome.error;\n return outcome.result as T;\n },\n handler<T>(fn: HandlerFn<T>, options?: HandlerOptions) {\n const secret = options?.secret === undefined ? self.cronSecret : options.secret;\n return async (request: Request): Promise<Response> => {\n if (secret) {\n const header = request.headers.get(\"authorization\") ?? \"\";\n if (!constantTimeEqual(header, `Bearer ${secret}`)) {\n return json({ ok: false, error: \"Unauthorized\" }, 401);\n }\n }\n const outcome = await self.execute(definition, (job) => fn(job, request), \"handler\");\n if (outcome.result instanceof Response) return outcome.result;\n const body = {\n ok: outcome.run.status === \"ok\",\n job: definition.name,\n run: outcome.run.id,\n status: outcome.run.status,\n durationMs: outcome.run.durationMs,\n ...(outcome.run.error ? { error: outcome.run.error.split(\"\\n\")[0] } : {}),\n };\n return json(body, outcome.run.status === \"ok\" ? 200 : 500);\n };\n },\n };\n }\n\n private async ensureReady(): Promise<void> {\n if (!this.ready) {\n this.ready = (async () => {\n if (this.store.init) await this.store.init();\n if (this.usingDefaultStore && process.env.NODE_ENV === \"production\") {\n console.warn(\"[cronwatch] using the in-memory store: runs and state are lost on restart. Pass a store from @cronwatch/sdk/sqlite or @cronwatch/sdk/postgres.\");\n }\n })();\n }\n await this.ready;\n }\n\n private async sync(definition: JobDefinition): Promise<void> {\n await this.ensureReady();\n if (this.synced.has(definition.name)) return;\n await this.store.upsertJob(toStored(definition), this.now());\n this.synced.add(definition.name);\n }\n\n /** Runs a function as a recorded run. Never throws for the job's own error; see `threw`. */\n async execute<T>(definition: JobDefinition, fn: JobFn<T>, trigger: string): Promise<ExecuteResult<T>> {\n await this.sync(definition);\n const startedAt = this.now();\n const run: Run = {\n id: crypto.randomUUID(),\n job: definition.name,\n status: \"running\",\n startedAt,\n finishedAt: null,\n durationMs: null,\n error: null,\n output: null,\n metrics: {},\n trigger,\n };\n await this.store.insertRun(run);\n\n const before = (await this.store.getState(definition.name)) ?? emptyState(definition.name);\n const started = onRunStart(before);\n if (openConditions(started.state).length !== openConditions(before).length) {\n await this.store.setState(started.state);\n }\n\n const recorder = createRecorder(run);\n const timer = setTimeout(() => recorder.abort(), timeoutMs(definition));\n if (typeof timer === \"object\" && \"unref\" in timer) timer.unref();\n\n let result: T | undefined;\n let error: unknown;\n let threw = false;\n try {\n result = await fn(recorder.context);\n } catch (e) {\n error = e;\n threw = true;\n } finally {\n clearTimeout(timer);\n }\n\n const finishedAt = this.now();\n run.finishedAt = finishedAt;\n run.durationMs = Math.max(0, finishedAt - startedAt);\n run.metrics = recorder.metrics();\n run.output = recorder.output() ?? (typeof result === \"string\" ? result : null);\n\n if (threw) {\n run.status = \"failed\";\n run.error = errorMessage(error);\n } else if (result instanceof Response && result.status >= 400) {\n run.status = \"failed\";\n run.error = `HTTP ${result.status}${result.statusText ? ` ${result.statusText}` : \"\"}`;\n } else {\n const unmet = checkExpectation(definition.expect, run.output);\n if (unmet) {\n run.status = \"failed\";\n run.error = unmet;\n } else {\n run.status = \"ok\";\n }\n }\n await this.store.updateRun(run);\n\n try {\n const history = (await this.store.listRuns(definition.name, BASELINE_WINDOW + 5)).filter((r) => r.id !== run.id);\n const state = (await this.store.getState(definition.name)) ?? emptyState(definition.name);\n const evaluation = onRunFinish(definition, run, state, history, started.openBefore, finishedAt);\n await this.settle(state, evaluation, toStored(definition), finishedAt);\n } catch (e) {\n this.onError(e, `evaluating ${definition.name}`);\n }\n\n return { run, result, error, threw };\n }\n\n /**\n * Look for missed and stuck runs across every job, send alerts, and prune\n * old runs. Call it from an interval (start()), a cron hitting the mounted\n * routes, or by hand. Concurrent calls share one check.\n */\n check(): Promise<CheckResult> {\n if (!this.checking) {\n this.checking = this.runCheck().finally(() => {\n this.checking = null;\n });\n }\n return this.checking;\n }\n\n private async runCheck(): Promise<CheckResult> {\n await this.ensureReady();\n for (const definition of this.definitions.values()) await this.sync(definition);\n const now = this.now();\n const alerts: Alert[] = [];\n\n // Runs that never reported back.\n for (const run of await this.store.runningRuns()) {\n const stored = await this.store.getJob(run.job);\n const declared = this.definitions.get(run.job);\n const definition = declared ? toStored(declared) : stored?.definition;\n if (!definition || !isStuck(definition, run, now)) continue;\n run.status = \"timeout\";\n run.finishedAt = now;\n run.durationMs = now - run.startedAt;\n run.error = `Still running after ${Math.round(timeoutMs(definition) / 60_000)} minutes; marked as timed out`;\n await this.store.updateRun(run);\n const history = (await this.store.listRuns(run.job, BASELINE_WINDOW + 5)).filter((r) => r.id !== run.id);\n const state = (await this.store.getState(run.job)) ?? emptyState(run.job);\n const evaluation = onRunFinish(definition, run, state, history, [], now);\n alerts.push(...(await this.settle(state, evaluation, definition, now)));\n }\n\n const jobs: JobSummary[] = [];\n for (const stored of await this.store.listJobs()) {\n const definition = stored.definition;\n const lastRun = await this.store.lastRun(stored.name);\n const state = (await this.store.getState(stored.name)) ?? emptyState(stored.name);\n const evaluation = onCheck(definition, stored, lastRun, state, now);\n alerts.push(...(await this.settle(state, evaluation, definition, now)));\n jobs.push(await this.summarize(stored, lastRun, evaluation.state, evaluation.nextExpectedAt, now));\n }\n\n let pruned = 0;\n if (now - this.lastPruneAt > PRUNE_INTERVAL_MS) {\n this.lastPruneAt = now;\n try {\n pruned = await this.store.prune(now - this.retentionMs);\n } catch (e) {\n this.onError(e, \"pruning\");\n }\n }\n\n return { checkedAt: now, jobs, alerts, pruned };\n }\n\n /** Every job the store knows about, with its health. Does not send alerts. */\n async jobs(): Promise<JobSummary[]> {\n await this.ensureReady();\n for (const definition of this.definitions.values()) await this.sync(definition);\n const now = this.now();\n const out: JobSummary[] = [];\n for (const stored of await this.store.listJobs()) {\n const lastRun = await this.store.lastRun(stored.name);\n const state = (await this.store.getState(stored.name)) ?? emptyState(stored.name);\n const { nextExpectedAt } = onCheck(stored.definition, stored, lastRun, state, now);\n out.push(await this.summarize(stored, lastRun, state, nextExpectedAt, now));\n }\n return out;\n }\n\n async jobSummary(name: string): Promise<JobSummary | null> {\n await this.ensureReady();\n const definition = this.definitions.get(name);\n if (definition) await this.sync(definition);\n const stored = await this.store.getJob(name);\n if (!stored) return null;\n const now = this.now();\n const lastRun = await this.store.lastRun(name);\n const state = (await this.store.getState(name)) ?? emptyState(name);\n const { nextExpectedAt } = onCheck(stored.definition, stored, lastRun, state, now);\n return this.summarize(stored, lastRun, state, nextExpectedAt, now);\n }\n\n async runs(name: string, limit = 50): Promise<Run[]> {\n await this.ensureReady();\n return this.store.listRuns(name, Math.min(500, Math.max(1, limit)));\n }\n\n async getRun(id: string): Promise<Run | null> {\n await this.ensureReady();\n return this.store.getRun(id);\n }\n\n /** Stop alerts for a job for a while. State keeps updating underneath. */\n async silence(name: string, duration: Duration): Promise<JobState> {\n await this.ensureReady();\n const state = (await this.store.getState(name)) ?? emptyState(name);\n state.silencedUntil = this.now() + parseDuration(duration, \"silence duration\");\n await this.store.setState(state);\n return state;\n }\n\n async unsilence(name: string): Promise<JobState> {\n await this.ensureReady();\n const state = (await this.store.getState(name)) ?? emptyState(name);\n state.silencedUntil = null;\n await this.store.setState(state);\n return state;\n }\n\n /** Remove a job and its runs from the store. A job still declared in code comes back on its next run. */\n async forget(name: string): Promise<void> {\n await this.ensureReady();\n this.definitions.delete(name);\n this.synced.delete(name);\n await this.store.deleteJob(name);\n }\n\n /** The dashboard and JSON API as fetch-style handlers. See createRoutes(). */\n routes(options?: RoutesOptions): Routes {\n return createRoutes(this, options);\n }\n\n /** Check on an interval, for long-running servers. Default every minute. */\n start(every: Duration = \"1m\"): void {\n if (this.timer) return;\n const ms = Math.max(5_000, parseDuration(every, \"check interval\"));\n const tick = () => this.check().catch((e) => this.onError(e, \"check\"));\n this.timer = setInterval(tick, ms);\n if (typeof this.timer === \"object\" && \"unref\" in this.timer) this.timer.unref();\n setTimeout(tick, 1_000).unref?.();\n }\n\n stop(): void {\n if (this.timer) clearInterval(this.timer);\n this.timer = null;\n }\n\n async close(): Promise<void> {\n this.stop();\n if (this.store.close) await this.store.close();\n }\n\n private async summarize(stored: StoredJob, lastRun: Run | null, state: JobState, nextExpectedAt: number | null, now: number): Promise<JobSummary> {\n const recent = await this.store.listRuns(stored.name, BASELINE_WINDOW);\n const finished = recent.filter((r) => r.status !== \"running\");\n const okDurations = recent.filter((r) => r.status === \"ok\" && r.durationMs !== null).map((r) => r.durationMs!);\n const open = openConditions(state);\n let health: JobSummary[\"health\"];\n if (state.silencedUntil !== null && state.silencedUntil > now) health = \"silenced\";\n else if (open.includes(\"stuck\") || (lastRun && isStuck(stored.definition, lastRun, now))) health = \"stuck\";\n else if (open.includes(\"failed\") || lastRun?.status === \"failed\" || lastRun?.status === \"timeout\") health = \"failing\";\n else if (open.includes(\"missed\")) health = \"late\";\n else if (!lastRun) health = \"never_ran\";\n else health = \"healthy\";\n return {\n name: stored.name,\n definition: stored.definition,\n health,\n open,\n lastRun,\n nextExpectedAt,\n consecutiveFailures: state.consecutiveFailures,\n silencedUntil: state.silencedUntil,\n stats: {\n runs: finished.length,\n okRate: finished.length === 0 ? 1 : finished.filter((r) => r.status === \"ok\").length / finished.length,\n p50Ms: percentile(okDurations, 50),\n p95Ms: percentile(okDurations, 95),\n },\n };\n }\n\n /** Save an evaluation's state, honouring silence, and send its alerts. */\n private async settle(previous: JobState, evaluation: Evaluation, definition: StoredJobDefinition, now: number): Promise<Alert[]> {\n if (isSilenced(previous, now)) {\n evaluation.state = muteOpens(previous, evaluation.state);\n evaluation.alerts = [];\n }\n if (JSON.stringify(evaluation.state) !== JSON.stringify(previous)) await this.store.setState(evaluation.state);\n return this.dispatch(evaluation.alerts, definition, evaluation.state, now);\n }\n\n private async dispatch(drafts: AlertDraft[], definition: StoredJobDefinition, state: JobState, now: number): Promise<Alert[]> {\n if (drafts.length === 0) return [];\n const sent: Alert[] = [];\n for (const draft of drafts) {\n const alert = composeAlert(draft, definition, now);\n if (this.triage && alert.type !== \"recovered\") {\n try {\n const recentRuns = await this.store.listRuns(alert.job, 5);\n const diagnosis = await withTimeout(this.triage({ alert, recentRuns }), TRIAGE_TIMEOUT_MS);\n if (diagnosis) alert.triage = diagnosis;\n } catch (e) {\n this.onError(e, `triage for ${alert.job}`);\n }\n }\n for (const channel of this.alerts) {\n try {\n await channel.send(alert);\n } catch (e) {\n this.onError(e, `alert channel ${channel.name}`);\n }\n }\n sent.push(alert);\n }\n state.lastAlertAt = now;\n await this.store.setState(state);\n return sent;\n }\n}\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const t = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);\n promise.then((v) => { clearTimeout(t); resolve(v); }, (e) => { clearTimeout(t); reject(e); });\n });\n}\n\n/** Writes alerts to the console. The default channel. */\nexport function consoleChannel(): AlertChannel {\n return {\n name: \"console\",\n async send(alert) {\n const line = `[cronwatch] ${alert.title}\\n${alert.message}${alert.triage ? `\\nTriage: ${alert.triage}` : \"\"}`;\n if (alert.type === \"recovered\") console.info(line);\n else console.error(line);\n },\n };\n}\n\n/** Wrap any function as an alert channel. */\nexport function custom(name: string, send: (alert: Alert) => Promise<void> | void): AlertChannel {\n return { name, send: async (alert) => { await send(alert); } };\n}\n\nexport type { Condition };\n","import { CronWatch } from \"./client.js\";\nimport type { CronWatchOptions } from \"./client.js\";\n\n/**\n * Create a CronWatch client. One per app, at module level:\n *\n * export const cw = cronwatch({ store: sqlite({ path: \"./data/cronwatch.db\" }), alerts: [slack({ webhookUrl })] });\n * export const nightly = cw.job(\"nightly-report\", { schedule: \"0 2 * * *\", grace: \"15m\" });\n */\nexport function cronwatch(options: CronWatchOptions = {}): CronWatch {\n return new CronWatch(options);\n}\n\nexport { CronWatch, consoleChannel, custom } from \"./client.js\";\nexport { json } from \"./http.js\";\nexport type { CronWatchOptions, HandlerFn, HandlerOptions, JobFn, JobHandle } from \"./client.js\";\nexport type { JobContext } from \"./job.js\";\nexport { memory } from \"./stores/memory.js\";\nexport { createRoutes } from \"./routes/index.js\";\nexport type { RoutesOptions, Routes } from \"./routes/index.js\";\nexport { parseDuration, formatDuration, formatRelative } from \"./duration.js\";\nexport { parseSchedule, previousFire, nextFire } from \"./schedule.js\";\nexport { composeAlert } from \"./format.js\";\nexport type {\n Alert,\n AlertChannel,\n AlertType,\n CheckResult,\n Condition,\n Duration,\n ExpectRule,\n JobDefinition,\n JobHealth,\n JobOptions,\n JobState,\n JobSummary,\n Run,\n RunStatus,\n Store,\n StoredJob,\n StoredJobDefinition,\n TriageContext,\n TriageFn,\n} from \"./types.js\";\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { S as Store, a as AlertChannel, T as TriageFn, D as Duration, J as JobOptions, b as JobDefinition, R as Run, C as CheckResult, c as JobSummary, d as JobState, A as Alert, e as Condition, f as StoredJobDefinition } from './types-BQ1P8z55.cjs';
|
|
2
|
+
export { g as AlertType, E as ExpectRule, h as JobHealth, i as RunStatus, j as StoredJob, k as TriageContext } from './types-BQ1P8z55.cjs';
|
|
3
|
+
import { Cron } from 'croner';
|
|
4
|
+
|
|
5
|
+
/** What a job function receives. */
|
|
6
|
+
interface JobContext {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly runId: string;
|
|
9
|
+
readonly startedAt: number;
|
|
10
|
+
/** Aborts when the job's timeout elapses. Honour it if the work can stop. */
|
|
11
|
+
readonly signal: AbortSignal;
|
|
12
|
+
/** Append a line of output. Kept with the run, capped at 16 KB, shown in alerts and the dashboard. */
|
|
13
|
+
log(...parts: unknown[]): void;
|
|
14
|
+
/** Report a number for this run: tokens, cost, rows, anything. Watched against budgets and baselines. */
|
|
15
|
+
metric(name: string, value: number): void;
|
|
16
|
+
metrics(values: Record<string, number>): void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface RoutesOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Required to reach anything. Send it as `Authorization: Bearer <token>`,
|
|
22
|
+
* or open the dashboard once with `?token=<token>` and a cookie is set.
|
|
23
|
+
* Defaults to process.env.CRONWATCH_TOKEN. With no token at all, the routes
|
|
24
|
+
* are open in development and refuse to serve in production.
|
|
25
|
+
*
|
|
26
|
+
* The check endpoint (/api/check) also accepts the client's cronSecret, so
|
|
27
|
+
* a platform cron that sends `Authorization: Bearer <CRON_SECRET>` can
|
|
28
|
+
* trigger checks without knowing the dashboard token.
|
|
29
|
+
*/
|
|
30
|
+
token?: string | null;
|
|
31
|
+
/** Where the routes are mounted, so links resolve. Default "/cronwatch". */
|
|
32
|
+
basePath?: string;
|
|
33
|
+
}
|
|
34
|
+
type FetchHandler = (request: Request) => Promise<Response>;
|
|
35
|
+
interface Routes {
|
|
36
|
+
handler: FetchHandler;
|
|
37
|
+
GET: FetchHandler;
|
|
38
|
+
POST: FetchHandler;
|
|
39
|
+
DELETE: FetchHandler;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A fetch-style handler serving the dashboard and a small JSON API. Mount it
|
|
43
|
+
* in a Next.js app at app/cronwatch/[[...path]]/route.ts:
|
|
44
|
+
*
|
|
45
|
+
* export const { GET, POST, DELETE } = cw.routes();
|
|
46
|
+
*/
|
|
47
|
+
declare function createRoutes(cw: CronWatch, options?: RoutesOptions): Routes;
|
|
48
|
+
|
|
49
|
+
type JobFn<T> = (job: JobContext) => Promise<T> | T;
|
|
50
|
+
type HandlerFn<T> = (job: JobContext, request: Request) => Promise<T> | T;
|
|
51
|
+
interface HandlerOptions {
|
|
52
|
+
/**
|
|
53
|
+
* Callers must send `Authorization: Bearer <secret>`. Defaults to the
|
|
54
|
+
* client's cronSecret, which defaults to process.env.CRON_SECRET (what
|
|
55
|
+
* Vercel sends its cron requests with). Pass null to allow anyone.
|
|
56
|
+
*/
|
|
57
|
+
secret?: string | null;
|
|
58
|
+
}
|
|
59
|
+
interface JobHandle {
|
|
60
|
+
readonly name: string;
|
|
61
|
+
readonly definition: JobDefinition;
|
|
62
|
+
/** Run the function now, recording the run. Rethrows whatever the function throws. */
|
|
63
|
+
run<T>(fn: JobFn<T>, options?: {
|
|
64
|
+
trigger?: string;
|
|
65
|
+
}): Promise<T>;
|
|
66
|
+
/** A fetch-style request handler (Next.js route, Hono, Bun, Deno) that runs the function and records the run. */
|
|
67
|
+
handler<T>(fn: HandlerFn<T>, options?: HandlerOptions): (request: Request) => Promise<Response>;
|
|
68
|
+
}
|
|
69
|
+
interface CronWatchOptions {
|
|
70
|
+
/** Where jobs, runs and state live. Defaults to an in-memory store that forgets on restart. */
|
|
71
|
+
store?: Store;
|
|
72
|
+
/** Where alerts go. Defaults to the console. */
|
|
73
|
+
alerts?: AlertChannel[];
|
|
74
|
+
/** Adds a short diagnosis to failure alerts. See @cronwatch/sdk/anthropic. */
|
|
75
|
+
triage?: TriageFn;
|
|
76
|
+
/** Shared secret that handler() requests must carry. Defaults to process.env.CRON_SECRET. */
|
|
77
|
+
cronSecret?: string | null;
|
|
78
|
+
/** How long finished runs are kept. Default "30d". */
|
|
79
|
+
retention?: Duration;
|
|
80
|
+
/** Applied to every job unless the job sets its own. */
|
|
81
|
+
defaults?: Pick<JobOptions, "grace" | "timeout" | "timezone" | "failuresBeforeAlert">;
|
|
82
|
+
/** Called with anything that goes wrong outside a job: an alert channel failing, a triage timeout. */
|
|
83
|
+
onError?: (error: unknown, where: string) => void;
|
|
84
|
+
/** The clock. Tests use this. */
|
|
85
|
+
now?: () => number;
|
|
86
|
+
}
|
|
87
|
+
interface ExecuteResult<T> {
|
|
88
|
+
run: Run;
|
|
89
|
+
result: T | undefined;
|
|
90
|
+
error: unknown;
|
|
91
|
+
threw: boolean;
|
|
92
|
+
}
|
|
93
|
+
declare class CronWatch {
|
|
94
|
+
readonly store: Store;
|
|
95
|
+
readonly alerts: AlertChannel[];
|
|
96
|
+
readonly triage: TriageFn | undefined;
|
|
97
|
+
readonly cronSecret: string | null;
|
|
98
|
+
readonly retentionMs: number;
|
|
99
|
+
readonly now: () => number;
|
|
100
|
+
readonly onError: (error: unknown, where: string) => void;
|
|
101
|
+
private readonly defaults;
|
|
102
|
+
private readonly definitions;
|
|
103
|
+
private readonly synced;
|
|
104
|
+
private ready;
|
|
105
|
+
private checking;
|
|
106
|
+
private lastPruneAt;
|
|
107
|
+
private timer;
|
|
108
|
+
private usingDefaultStore;
|
|
109
|
+
constructor(options?: CronWatchOptions);
|
|
110
|
+
/** Declare a job. Call it once, at module level, and keep the handle. */
|
|
111
|
+
job(name: string, options?: JobOptions): JobHandle;
|
|
112
|
+
/** Run a job by name without keeping a handle. Defines it on first use. */
|
|
113
|
+
run<T>(name: string, fn: JobFn<T>): Promise<T>;
|
|
114
|
+
run<T>(name: string, options: JobOptions, fn: JobFn<T>): Promise<T>;
|
|
115
|
+
/** The definitions declared in this process. */
|
|
116
|
+
definedJobs(): JobDefinition[];
|
|
117
|
+
private handle;
|
|
118
|
+
private ensureReady;
|
|
119
|
+
private sync;
|
|
120
|
+
/** Runs a function as a recorded run. Never throws for the job's own error; see `threw`. */
|
|
121
|
+
execute<T>(definition: JobDefinition, fn: JobFn<T>, trigger: string): Promise<ExecuteResult<T>>;
|
|
122
|
+
/**
|
|
123
|
+
* Look for missed and stuck runs across every job, send alerts, and prune
|
|
124
|
+
* old runs. Call it from an interval (start()), a cron hitting the mounted
|
|
125
|
+
* routes, or by hand. Concurrent calls share one check.
|
|
126
|
+
*/
|
|
127
|
+
check(): Promise<CheckResult>;
|
|
128
|
+
private runCheck;
|
|
129
|
+
/** Every job the store knows about, with its health. Does not send alerts. */
|
|
130
|
+
jobs(): Promise<JobSummary[]>;
|
|
131
|
+
jobSummary(name: string): Promise<JobSummary | null>;
|
|
132
|
+
runs(name: string, limit?: number): Promise<Run[]>;
|
|
133
|
+
getRun(id: string): Promise<Run | null>;
|
|
134
|
+
/** Stop alerts for a job for a while. State keeps updating underneath. */
|
|
135
|
+
silence(name: string, duration: Duration): Promise<JobState>;
|
|
136
|
+
unsilence(name: string): Promise<JobState>;
|
|
137
|
+
/** Remove a job and its runs from the store. A job still declared in code comes back on its next run. */
|
|
138
|
+
forget(name: string): Promise<void>;
|
|
139
|
+
/** The dashboard and JSON API as fetch-style handlers. See createRoutes(). */
|
|
140
|
+
routes(options?: RoutesOptions): Routes;
|
|
141
|
+
/** Check on an interval, for long-running servers. Default every minute. */
|
|
142
|
+
start(every?: Duration): void;
|
|
143
|
+
stop(): void;
|
|
144
|
+
close(): Promise<void>;
|
|
145
|
+
private summarize;
|
|
146
|
+
/** Save an evaluation's state, honouring silence, and send its alerts. */
|
|
147
|
+
private settle;
|
|
148
|
+
private dispatch;
|
|
149
|
+
}
|
|
150
|
+
/** Writes alerts to the console. The default channel. */
|
|
151
|
+
declare function consoleChannel(): AlertChannel;
|
|
152
|
+
/** Wrap any function as an alert channel. */
|
|
153
|
+
declare function custom(name: string, send: (alert: Alert) => Promise<void> | void): AlertChannel;
|
|
154
|
+
|
|
155
|
+
declare function json(body: unknown, status?: number, headers?: Record<string, string>): Response;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Keeps everything in process memory. The default when no store is given,
|
|
159
|
+
* good for tests and for trying the library out. State is gone on restart,
|
|
160
|
+
* so a missed run cannot be noticed across one.
|
|
161
|
+
*/
|
|
162
|
+
declare function memory(): Store;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* "15m" -> 900000. Accepts a plain number of milliseconds, and compound
|
|
166
|
+
* strings such as "1h30m". Whitespace between parts is fine.
|
|
167
|
+
*/
|
|
168
|
+
declare function parseDuration(value: Duration, label?: string): number;
|
|
169
|
+
/** 90000 -> "1m 30s". For messages, not for parsing back. */
|
|
170
|
+
declare function formatDuration(ms: number): string;
|
|
171
|
+
/** "5 minutes ago", "in 2h". Relative to `now`. */
|
|
172
|
+
declare function formatRelative(at: number, now: number): string;
|
|
173
|
+
|
|
174
|
+
interface ParsedSchedule {
|
|
175
|
+
kind: "cron" | "interval";
|
|
176
|
+
source: string;
|
|
177
|
+
/** For intervals, the period in milliseconds. */
|
|
178
|
+
everyMs?: number;
|
|
179
|
+
cron?: Cron;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* "0 2 * * *" (cron, five or six fields), "@hourly", or "every 5m".
|
|
183
|
+
* Parsed once per (schedule, timezone) pair and cached. The croner instance
|
|
184
|
+
* gets no callback, so it schedules nothing; it is only used to compute fire
|
|
185
|
+
* times. Without a timezone the expression is read in the process timezone,
|
|
186
|
+
* like crontab. Vercel and GitHub Actions run their crons in UTC, so pass
|
|
187
|
+
* timezone: "UTC" for those.
|
|
188
|
+
*/
|
|
189
|
+
declare function parseSchedule(schedule: string, timezone?: string): ParsedSchedule;
|
|
190
|
+
/** The next time the cron fires strictly after `from`. */
|
|
191
|
+
declare function nextFire(parsed: ParsedSchedule, from: number, lastRunAt: number | null): number | null;
|
|
192
|
+
/**
|
|
193
|
+
* The most recent time the cron fired at or before `now`, or null when the
|
|
194
|
+
* expression never fires in the year before `now`.
|
|
195
|
+
*
|
|
196
|
+
* croner only looks forward, so this searches: widen a window behind `now`
|
|
197
|
+
* until a fire time falls inside it, then bisect on the window's start for
|
|
198
|
+
* the latest start whose next fire is still at or before `now`.
|
|
199
|
+
*/
|
|
200
|
+
declare function previousFire(parsed: ParsedSchedule, now: number): number | null;
|
|
201
|
+
|
|
202
|
+
interface AlertDraft {
|
|
203
|
+
type: Condition | "recovered";
|
|
204
|
+
run: Run | null;
|
|
205
|
+
details: Record<string, unknown>;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** Turns a draft into the title and message every channel shows. */
|
|
209
|
+
declare function composeAlert(draft: AlertDraft, def: StoredJobDefinition, now: number): Alert;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Create a CronWatch client. One per app, at module level:
|
|
213
|
+
*
|
|
214
|
+
* export const cw = cronwatch({ store: sqlite({ path: "./data/cronwatch.db" }), alerts: [slack({ webhookUrl })] });
|
|
215
|
+
* export const nightly = cw.job("nightly-report", { schedule: "0 2 * * *", grace: "15m" });
|
|
216
|
+
*/
|
|
217
|
+
declare function cronwatch(options?: CronWatchOptions): CronWatch;
|
|
218
|
+
|
|
219
|
+
export { Alert, AlertChannel, CheckResult, Condition, CronWatch, type CronWatchOptions, Duration, type HandlerFn, type HandlerOptions, type JobContext, JobDefinition, type JobFn, type JobHandle, JobOptions, JobState, JobSummary, type Routes, type RoutesOptions, Run, Store, StoredJobDefinition, TriageFn, composeAlert, consoleChannel, createRoutes, cronwatch, custom, formatDuration, formatRelative, json, memory, nextFire, parseDuration, parseSchedule, previousFire };
|