@cronwatch/sdk 0.3.0 → 0.4.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.
Files changed (136) hide show
  1. package/README.md +8 -7
  2. package/dist/anthropic.d.cts +1 -1
  3. package/dist/anthropic.d.ts +1 -1
  4. package/dist/bugsnag.cjs +108 -0
  5. package/dist/bugsnag.cjs.map +1 -0
  6. package/dist/bugsnag.d.cts +26 -0
  7. package/dist/bugsnag.d.ts +26 -0
  8. package/dist/bugsnag.js +106 -0
  9. package/dist/bugsnag.js.map +1 -0
  10. package/dist/client-B7bqnkI5.d.cts +450 -0
  11. package/dist/client-pmqH3apS.d.ts +450 -0
  12. package/dist/d1.cjs +214 -0
  13. package/dist/d1.cjs.map +1 -0
  14. package/dist/d1.d.cts +42 -0
  15. package/dist/d1.d.ts +42 -0
  16. package/dist/d1.js +212 -0
  17. package/dist/d1.js.map +1 -0
  18. package/dist/datadog.cjs +95 -0
  19. package/dist/datadog.cjs.map +1 -0
  20. package/dist/datadog.d.cts +24 -0
  21. package/dist/datadog.d.ts +24 -0
  22. package/dist/datadog.js +93 -0
  23. package/dist/datadog.js.map +1 -0
  24. package/dist/discord.cjs +2 -0
  25. package/dist/discord.cjs.map +1 -1
  26. package/dist/discord.d.cts +1 -1
  27. package/dist/discord.d.ts +1 -1
  28. package/dist/discord.js +2 -0
  29. package/dist/discord.js.map +1 -1
  30. package/dist/email-BJ-z_epD.d.cts +21 -0
  31. package/dist/email-_H0faCh3.d.ts +21 -0
  32. package/dist/honeybadger.cjs +101 -0
  33. package/dist/honeybadger.cjs.map +1 -0
  34. package/dist/honeybadger.d.cts +23 -0
  35. package/dist/honeybadger.d.ts +23 -0
  36. package/dist/honeybadger.js +99 -0
  37. package/dist/honeybadger.js.map +1 -0
  38. package/dist/index.cjs +692 -124
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +5 -228
  41. package/dist/index.d.ts +5 -228
  42. package/dist/index.js +692 -124
  43. package/dist/index.js.map +1 -1
  44. package/dist/mailgun.cjs +115 -0
  45. package/dist/mailgun.cjs.map +1 -0
  46. package/dist/mailgun.d.cts +21 -0
  47. package/dist/mailgun.d.ts +21 -0
  48. package/dist/mailgun.js +113 -0
  49. package/dist/mailgun.js.map +1 -0
  50. package/dist/newrelic.cjs +88 -0
  51. package/dist/newrelic.cjs.map +1 -0
  52. package/dist/newrelic.d.cts +25 -0
  53. package/dist/newrelic.d.ts +25 -0
  54. package/dist/newrelic.js +86 -0
  55. package/dist/newrelic.js.map +1 -0
  56. package/dist/node.cjs +191 -0
  57. package/dist/node.cjs.map +1 -0
  58. package/dist/node.d.cts +97 -0
  59. package/dist/node.d.ts +97 -0
  60. package/dist/node.js +186 -0
  61. package/dist/node.js.map +1 -0
  62. package/dist/pg-cron.cjs +286 -0
  63. package/dist/pg-cron.cjs.map +1 -0
  64. package/dist/pg-cron.d.cts +93 -0
  65. package/dist/pg-cron.d.ts +93 -0
  66. package/dist/pg-cron.js +280 -0
  67. package/dist/pg-cron.js.map +1 -0
  68. package/dist/postgres.cjs +33 -1
  69. package/dist/postgres.cjs.map +1 -1
  70. package/dist/postgres.d.cts +1 -1
  71. package/dist/postgres.d.ts +1 -1
  72. package/dist/postgres.js +33 -1
  73. package/dist/postgres.js.map +1 -1
  74. package/dist/postmark.cjs +106 -0
  75. package/dist/postmark.cjs.map +1 -0
  76. package/dist/postmark.d.cts +18 -0
  77. package/dist/postmark.d.ts +18 -0
  78. package/dist/postmark.js +104 -0
  79. package/dist/postmark.js.map +1 -0
  80. package/dist/resend.cjs +114 -0
  81. package/dist/resend.cjs.map +1 -0
  82. package/dist/resend.d.cts +16 -0
  83. package/dist/resend.d.ts +16 -0
  84. package/dist/resend.js +112 -0
  85. package/dist/resend.js.map +1 -0
  86. package/dist/rollbar.cjs +108 -0
  87. package/dist/rollbar.cjs.map +1 -0
  88. package/dist/rollbar.d.cts +20 -0
  89. package/dist/rollbar.d.ts +20 -0
  90. package/dist/rollbar.js +106 -0
  91. package/dist/rollbar.js.map +1 -0
  92. package/dist/sendgrid.cjs +114 -0
  93. package/dist/sendgrid.cjs.map +1 -0
  94. package/dist/sendgrid.d.cts +19 -0
  95. package/dist/sendgrid.d.ts +19 -0
  96. package/dist/sendgrid.js +112 -0
  97. package/dist/sendgrid.js.map +1 -0
  98. package/dist/sentry.cjs +130 -0
  99. package/dist/sentry.cjs.map +1 -0
  100. package/dist/sentry.d.cts +28 -0
  101. package/dist/sentry.d.ts +28 -0
  102. package/dist/sentry.js +127 -0
  103. package/dist/sentry.js.map +1 -0
  104. package/dist/ses.cjs +170 -0
  105. package/dist/ses.cjs.map +1 -0
  106. package/dist/ses.d.cts +25 -0
  107. package/dist/ses.d.ts +25 -0
  108. package/dist/ses.js +168 -0
  109. package/dist/ses.js.map +1 -0
  110. package/dist/slack.cjs +2 -0
  111. package/dist/slack.cjs.map +1 -1
  112. package/dist/slack.d.cts +1 -1
  113. package/dist/slack.d.ts +1 -1
  114. package/dist/slack.js +2 -0
  115. package/dist/slack.js.map +1 -1
  116. package/dist/sqlite.cjs +62 -5
  117. package/dist/sqlite.cjs.map +1 -1
  118. package/dist/sqlite.d.cts +1 -1
  119. package/dist/sqlite.d.ts +1 -1
  120. package/dist/sqlite.js +62 -5
  121. package/dist/sqlite.js.map +1 -1
  122. package/dist/twilio.cjs +168 -0
  123. package/dist/twilio.cjs.map +1 -0
  124. package/dist/twilio.d.cts +52 -0
  125. package/dist/twilio.d.ts +52 -0
  126. package/dist/twilio.js +162 -0
  127. package/dist/twilio.js.map +1 -0
  128. package/dist/{types-C1PyRjI5.d.cts → types-Ddq1MUPL.d.cts} +50 -4
  129. package/dist/{types-C1PyRjI5.d.ts → types-Ddq1MUPL.d.ts} +50 -4
  130. package/dist/webhook.cjs +11 -5
  131. package/dist/webhook.cjs.map +1 -1
  132. package/dist/webhook.d.cts +6 -3
  133. package/dist/webhook.d.ts +6 -3
  134. package/dist/webhook.js +11 -6
  135. package/dist/webhook.js.map +1 -1
  136. package/package.json +211 -5
@@ -0,0 +1,450 @@
1
+ import { S as Store, a as AlertChannel, n as TriageFn, i as JobOptions, R as Run, A as Alert, D as Duration, J as JobDefinition, f as CheckResult, k as JobSummary, j as JobState } from './types-Ddq1MUPL.cjs';
2
+
3
+ /** What a job function receives. */
4
+ interface JobContext {
5
+ readonly name: string;
6
+ readonly runId: string;
7
+ readonly startedAt: number;
8
+ /** Aborts when the job's timeout elapses. Honour it if the work can stop. */
9
+ readonly signal: AbortSignal;
10
+ /** Append a line of output. Kept with the run, capped at 16 KB, shown in alerts and the dashboard. */
11
+ log(...parts: unknown[]): void;
12
+ /** Report a number for this run: tokens, cost, rows, anything. Watched against budgets and baselines. */
13
+ metric(name: string, value: number): void;
14
+ metrics(values: Record<string, number>): void;
15
+ }
16
+
17
+ interface RoutesOptions {
18
+ /**
19
+ * Required to reach anything. Send it as `Authorization: Bearer <token>`,
20
+ * or open the dashboard once with `?token=<token>` and a cookie is set.
21
+ * Defaults to process.env.CRONWATCH_TOKEN (on Cloudflare Workers, which
22
+ * have no process, pass env.CRONWATCH_TOKEN); an empty string counts as unset.
23
+ * With no token while NODE_ENV is "development" or "test", the routes make
24
+ * a random one and print a sign-in link to the server log on their first
25
+ * request; with no token otherwise they answer 503. Pass `null` to opt out
26
+ * and serve them open everywhere, for example behind your own auth.
27
+ *
28
+ * The check endpoint (/api/check) also accepts the client's cronSecret, so
29
+ * a platform cron that sends `Authorization: Bearer <CRON_SECRET>` can
30
+ * trigger checks without knowing the dashboard token.
31
+ */
32
+ token?: string | null;
33
+ /** Where the routes are mounted, so links resolve. Default "/cronwatch". */
34
+ basePath?: string;
35
+ /**
36
+ * The public origin the dashboard is served from, such as
37
+ * "https://app.example.com", for an app behind a proxy whose request URLs
38
+ * carry an internal host or scheme. Used in place of the request URL's
39
+ * origin for the cross-site check on writes, the sign-in redirect (its
40
+ * cookie is Secure when this is https, and the redirect back after a form
41
+ * follows a Referer on this origin) and the development sign-in line.
42
+ * Takes precedence over trustProxy.
43
+ */
44
+ origin?: string;
45
+ /**
46
+ * Take the public origin from X-Forwarded-Proto and X-Forwarded-Host (the
47
+ * first value of each, falling back to the request URL's scheme or host
48
+ * for whichever is missing) when a request carries either. Only for an app
49
+ * whose proxy sets or overwrites both headers: a client can send them too.
50
+ * Default false, which ignores them.
51
+ */
52
+ trustProxy?: boolean;
53
+ }
54
+ type FetchHandler = (request: Request) => Promise<Response>;
55
+ interface Routes {
56
+ handler: FetchHandler;
57
+ GET: FetchHandler;
58
+ POST: FetchHandler;
59
+ DELETE: FetchHandler;
60
+ }
61
+ /**
62
+ * A fetch-style handler serving the dashboard and a small JSON API. Mount it
63
+ * in a Next.js app at app/cronwatch/[[...path]]/route.ts:
64
+ *
65
+ * export const { GET, POST, DELETE } = cw.routes();
66
+ */
67
+ declare function createRoutes(cw: CronWatch, options?: RoutesOptions): Routes;
68
+
69
+ type JobFn<T> = (job: JobContext) => Promise<T> | T;
70
+ type HandlerFn<T> = (job: JobContext, request: Request) => Promise<T> | T;
71
+ interface HandlerOptions {
72
+ /**
73
+ * Callers must send `Authorization: Bearer <secret>`. Defaults to the
74
+ * client's cronSecret, which defaults to process.env.CRON_SECRET (what
75
+ * Vercel sends its cron requests with). An empty string counts as unset.
76
+ * With no secret at all the handler answers 503 unless NODE_ENV is
77
+ * "development" or "test". Pass null to allow anyone.
78
+ */
79
+ secret?: string | null;
80
+ }
81
+ interface JobHandle {
82
+ readonly name: string;
83
+ readonly definition: JobDefinition;
84
+ /** Run the function now, recording the run. Rethrows whatever the function throws. */
85
+ run<T>(fn: JobFn<T>, options?: {
86
+ trigger?: string;
87
+ }): Promise<T>;
88
+ /** A fetch-style request handler (Next.js route, Hono, Bun, Deno) that runs the function and records the run. */
89
+ handler<T>(fn: HandlerFn<T>, options?: HandlerOptions): (request: Request) => Promise<Response>;
90
+ /**
91
+ * Record a running run now and finish it later, perhaps from another
92
+ * process (see resume()). Store failures go to onError; it never throws for
93
+ * them. A run that is never finished is marked stuck by the first check
94
+ * after the job's timeout.
95
+ */
96
+ start(options?: StartOptions): Promise<RunHandle>;
97
+ /** A handle on a run this job started elsewhere, by its id, so this process can log to it and finish it. */
98
+ resume(runId: string): Promise<RunHandle>;
99
+ }
100
+ interface StartOptions {
101
+ /** What started the run, as with run(). Default "start". */
102
+ trigger?: string;
103
+ /**
104
+ * Your own stable id for the run, such as an Inngest run id, 1 to 200
105
+ * characters, not starting with "pgcron:" (the pg_cron source's). A start
106
+ * with an id already recorded for this job records nothing and returns a
107
+ * handle on that run instead; an id recorded for another job throws,
108
+ * whether that job's start is still in flight or long done.
109
+ */
110
+ id?: string;
111
+ }
112
+ /**
113
+ * How a started run ended. `{ error }` is a failure, recorded like an error
114
+ * run() caught. Otherwise the run succeeded, and `result` (or a string
115
+ * passed on its own) is treated like the value run()'s function returns:
116
+ * a string is the output when nothing was logged, `expect` is checked, and
117
+ * a Response with status 400 or above is a failure.
118
+ */
119
+ type RunOutcome = {
120
+ status?: "ok";
121
+ result?: unknown;
122
+ } | {
123
+ error: unknown;
124
+ };
125
+ /** A run recorded by job.start() or found by job.resume(), to finish later. */
126
+ interface RunHandle {
127
+ readonly id: string;
128
+ readonly job: string;
129
+ /** When the run started; null when a resumed run could not be read. */
130
+ readonly startedAt: number | null;
131
+ /** False once finished, and from the start for a resumed run that already finished or does not exist. */
132
+ readonly active: boolean;
133
+ /** Add a line of output. Kept in the handle until flush() or finish(). */
134
+ log(...parts: unknown[]): void;
135
+ /** Report a number for this run. A later value for the same name replaces an earlier one. */
136
+ metric(name: string, value: number): void;
137
+ metrics(values: Record<string, number>): void;
138
+ /**
139
+ * Append the lines and metrics added so far to the stored run, which must
140
+ * still be running and belong to this job. A read, change and write of the
141
+ * run's row, written only while it is still running: two processes
142
+ * appending to one run at the same moment can lose one's lines, but a flush
143
+ * never undoes a finish. The first 16 KB of everything flushed stay in the
144
+ * handle, so an expect rule at finish() sees an early line as run() would.
145
+ */
146
+ flush(): Promise<void>;
147
+ /**
148
+ * Finish the run, judge it like any other and send what that produces.
149
+ * Resolves to the run as recorded, or null when nothing was recorded: the
150
+ * run was already finished (here or elsewhere), was not found, or belongs
151
+ * to another job, which is reported to onError. When several processes
152
+ * finish one run, only the one whose write lands judges it. Never throws
153
+ * for the store: a store that fails is reported, nothing is recorded, and
154
+ * the handle stays active so finish() can be called again.
155
+ */
156
+ finish(outcome?: RunOutcome | string): Promise<Run | null>;
157
+ /** finish({ error }). */
158
+ fail(error: unknown): Promise<Run | null>;
159
+ }
160
+ /**
161
+ * What a Source may use of the client: declare jobs, read the store, and
162
+ * record runs it found elsewhere. A CronWatch is one.
163
+ */
164
+ interface SourceHost {
165
+ /** Declare a job, as CronWatch.job(). Throws for an invalid name or option. */
166
+ job(name: string, options?: JobOptions): unknown;
167
+ /** See CronWatch.recordRun(). */
168
+ recordRun(run: Run, options?: RecordRunOptions): Promise<Alert[]>;
169
+ readonly store: Store;
170
+ readonly now: () => number;
171
+ readonly onError: (error: unknown, where: string) => void;
172
+ }
173
+ /**
174
+ * Runs that happen somewhere CronWatch cannot wrap, such as inside the
175
+ * database (see @cronwatch/sdk/pg-cron). check() calls sync() on each source
176
+ * first, so what it records is evaluated in the same check.
177
+ */
178
+ interface Source {
179
+ name: string;
180
+ /** Declare the jobs and record their new runs. Returns the alerts recording them sent. */
181
+ sync(host: SourceHost): Promise<Alert[] | void>;
182
+ }
183
+ interface RecordRunOptions {
184
+ /** False stores the run without evaluating it, for history imported on first sight. Default true. */
185
+ evaluate?: boolean;
186
+ }
187
+ interface CronWatchOptions {
188
+ /** Where jobs, runs and state live. Defaults to an in-memory store that forgets on restart. */
189
+ store?: Store;
190
+ /**
191
+ * Where runs this process does not wrap come from, such as pg_cron jobs.
192
+ * Each is synced at the start of every check(); one that throws is
193
+ * reported to onError and the check carries on.
194
+ */
195
+ sources?: Source[];
196
+ /** Where alerts go. Defaults to the console. */
197
+ alerts?: AlertChannel[];
198
+ /** Adds a short diagnosis to every alert except recoveries. See @cronwatch/sdk/anthropic. */
199
+ triage?: TriageFn;
200
+ /**
201
+ * Shared secret that handler() requests must carry. Defaults to
202
+ * process.env.CRON_SECRET (on Cloudflare Workers, which have no process,
203
+ * pass env.CRON_SECRET); an empty string counts as unset. Pass null to
204
+ * let handlers run without one.
205
+ */
206
+ cronSecret?: string | null;
207
+ /** How long finished runs are kept. Default "30d". */
208
+ retention?: Duration;
209
+ /** Applied to every job unless the job sets its own. */
210
+ defaults?: Pick<JobOptions, "grace" | "timeout" | "timezone" | "failuresBeforeAlert">;
211
+ /**
212
+ * Applied to every run's output and error before it is stored, shown or
213
+ * sent to an alert channel or triage. The default blanks values that look
214
+ * like secrets (password=..., Authorization headers, URL credentials, bearer
215
+ * tokens, JWTs, PEM private keys, webhook URLs, AWS, GitHub, Slack, Stripe,
216
+ * Google and API key formats). Pass your own function, or false to keep
217
+ * output exactly as logged. A function that throws or returns something
218
+ * other than a string is reported to onError and the default is used.
219
+ */
220
+ redact?: ((text: string) => string) | false;
221
+ /**
222
+ * "now" (the default) sends alerts from this process. "check" sends nothing
223
+ * from here: each alert is queued in the store and the next check, in a
224
+ * process that delivers now, sends it (with triage). For a process that
225
+ * records runs but cannot reach the network, such as a sandboxed backup job.
226
+ * Its `alerts` and `triage` are not used.
227
+ */
228
+ deliver?: "now" | "check";
229
+ /** Called with anything that goes wrong outside a job: the store failing, an alert channel failing, a triage timeout. */
230
+ onError?: (error: unknown, where: string) => void;
231
+ /** The clock. Tests use this. */
232
+ now?: () => number;
233
+ }
234
+ declare class CronWatch {
235
+ readonly store: Store;
236
+ readonly alerts: AlertChannel[];
237
+ readonly triage: TriageFn | undefined;
238
+ readonly sources: Source[];
239
+ /** The secret handler() requests must carry, or null when none is set. */
240
+ readonly cronSecret: string | null;
241
+ readonly retentionMs: number;
242
+ readonly now: () => number;
243
+ readonly onError: (error: unknown, where: string) => void;
244
+ /** cronSecret was passed as null: handlers may run without a secret. */
245
+ private readonly secretOptOut;
246
+ private readonly redact;
247
+ /** "check": queue alerts for another process's check instead of sending them. See CronWatchOptions.deliver. */
248
+ private readonly deferDelivery;
249
+ private readonly defaults;
250
+ private readonly definitions;
251
+ private readonly synced;
252
+ /** The tail of each job's queue of state updates. See serial(). */
253
+ private readonly queues;
254
+ /** start() calls with an id still in flight, so two at once in this process record one run. */
255
+ private readonly starting;
256
+ private ready;
257
+ private checking;
258
+ private lastPruneAt;
259
+ private timer;
260
+ private firstTick;
261
+ private usingDefaultStore;
262
+ private warnedNoSecret;
263
+ private warnedDeferredStart;
264
+ constructor(options?: CronWatchOptions);
265
+ /** Declare a job. Call it once, at module level, and keep the handle. */
266
+ job(name: string, options?: JobOptions): JobHandle;
267
+ /** Run a job by name without keeping a handle. Defines it on first use. */
268
+ run<T>(name: string, fn: JobFn<T>): Promise<T>;
269
+ run<T>(name: string, options: JobOptions, fn: JobFn<T>): Promise<T>;
270
+ /** The definitions declared in this process. */
271
+ definedJobs(): JobDefinition[];
272
+ /** A handle on a run started elsewhere, as job(name).resume(runId). The job must be declared in this process. */
273
+ resumeRun(name: string, runId: string): Promise<RunHandle>;
274
+ private handle;
275
+ private warnNoSecret;
276
+ /** onError, for places that must carry on even when onError itself throws. */
277
+ private report;
278
+ private ensureReady;
279
+ private sync;
280
+ /**
281
+ * Runs `fn` after every earlier state update for the same job has settled,
282
+ * so two runs (or a run and a check) in this process never read and write
283
+ * the job's state over each other. Other processes are coordinated by
284
+ * updateState() instead.
285
+ */
286
+ private serial;
287
+ private readState;
288
+ /**
289
+ * Every read-modify-write of a job's state goes through here. In turn with
290
+ * this process's other updates to the job (serial()), it reads the state,
291
+ * asks `change` for the next one, and writes it with the version one
292
+ * higher, only if the stored version is still the one read. When another
293
+ * process wrote in between, the write is refused and it starts again from
294
+ * a fresh read, up to STATE_ATTEMPTS times. So `change` may run more than
295
+ * once and must only compute: whatever it returns from the attempt that
296
+ * was written is the result. Nothing is written when the state is
297
+ * unchanged. Returns the state as stored.
298
+ */
299
+ private updateState;
300
+ /** A conditional write, or for a store without compareAndSetState, a plain one that always succeeds. */
301
+ private writeState;
302
+ /**
303
+ * Runs a function as a recorded run. The function always runs, whatever
304
+ * the store is doing: store errors go to onError, and the result is the
305
+ * function's own outcome. Never throws for the job's own error; see `threw`.
306
+ */
307
+ private execute;
308
+ /**
309
+ * Sets a finished run's status and error from how it ended, then redacts
310
+ * its output and error. Shared by execute() and RunHandle.finish().
311
+ */
312
+ private conclude;
313
+ /**
314
+ * Writes a finished run and evaluates it. `recorded` says whether its
315
+ * start was written; if not, it is inserted now. Returns why nothing was
316
+ * recorded (another process finished the run first, say), or null. Throws
317
+ * when the store does, so a handle can be finished again. Shared by
318
+ * execute() and RunHandle.finish().
319
+ */
320
+ private recordFinish;
321
+ /** A conditional write (Store.updateRunIf), or for a store without one, a read then a plain write. */
322
+ private writeRunIf;
323
+ /**
324
+ * Writes a finished run over its stored row, only while that row is still
325
+ * running, or else still marked timeout by a check. Only the process whose
326
+ * write lands goes on to evaluate the run; for the others it returns why
327
+ * nothing was written. `lateAfterTimeout` means a check already counted
328
+ * the run as a stuck failure: a late failure must not count twice, while
329
+ * a late success still closes stuck and recovers. Throws when the store does.
330
+ */
331
+ private claimFinish;
332
+ /** job.start(): records a running run and returns a handle to finish it. See JobHandle.start. */
333
+ private startRun;
334
+ /**
335
+ * The start of execute() without the function: the run is inserted and
336
+ * missed and stuck close (onRunStart). A store that fails is reported and
337
+ * the handle inserts the finished run instead, as execute() does.
338
+ */
339
+ private recordStart;
340
+ /** job.resume() and cw.resumeRun(). A store that cannot be read is reported, and finish() reads it again. */
341
+ private resumeHandle;
342
+ /** A handle on a stored run. One still running, or marked timeout by a check, can be finished. */
343
+ private existingHandle;
344
+ /**
345
+ * The handle itself. `base` is the run as last known here, `recorded`
346
+ * whether its start is in the store, and `inactive` why finish() has
347
+ * nothing to do, or null. Lines and metrics wait in the handle until
348
+ * flush() or finish() merges them onto a fresh read of the stored run.
349
+ */
350
+ private runHandle;
351
+ /**
352
+ * Record a run that happened outside this process, for a Source. Its job
353
+ * must be declared with job() first. Runs are keyed by id: a new one is
354
+ * inserted, a stored one still running (or marked timeout by a check) is
355
+ * finished when this one is not running, and anything else is left alone,
356
+ * so recording the same run twice changes nothing. Finishing is
357
+ * conditional (see Store.updateRunIf): when two processes record the same
358
+ * finish, only the one whose write lands evaluates it, and the other
359
+ * reports it as already finished. A stored run of another job is left
360
+ * alone and reported. A finished run is judged as if it had been wrapped
361
+ * here (expect, failures, duration, budgets) and its output and error are
362
+ * redacted the same way; one finishing after a check marked it timeout is
363
+ * judged only when it succeeded, as RunHandle.finish() does. Returns the
364
+ * alerts it sent.
365
+ */
366
+ recordRun(input: Run, options?: RecordRunOptions): Promise<Alert[]>;
367
+ /** recordRun() for a run already stored. */
368
+ private recordOver;
369
+ /**
370
+ * Evaluate a finished run (ok, failed, or timed out by a check), already
371
+ * written, against the job's state and send what that produces. Never throws.
372
+ */
373
+ private finishRun;
374
+ /**
375
+ * The runs before `run`, newest first, with up to BASELINE_WINDOW
376
+ * successful ones when the store has them. One small read normally; a
377
+ * larger one only when failures crowd the successes out of it.
378
+ */
379
+ private history;
380
+ /**
381
+ * Look for missed and stuck runs across every job, send alerts, retry
382
+ * alerts no channel accepted, and prune old runs. Call it from an interval
383
+ * (start()), a cron hitting the mounted routes, or by hand. Concurrent
384
+ * calls share one check.
385
+ */
386
+ check(): Promise<CheckResult>;
387
+ private runCheck;
388
+ /** A job's summary and its newest runs, without alerting. A job that cannot be evaluated is reported and shown as failing. */
389
+ private snapshot;
390
+ /** The summary of a job whose evaluation failed, from whatever can still be read. */
391
+ private unevaluable;
392
+ /** Every job the store knows about, with its health. Does not send alerts. */
393
+ jobs(): Promise<JobSummary[]>;
394
+ /** Every job's summary with its newest `limit` runs, read together. What the dashboard shows. */
395
+ jobsWithRuns(limit?: number): Promise<{
396
+ job: JobSummary;
397
+ runs: Run[];
398
+ }[]>;
399
+ jobSummary(name: string): Promise<JobSummary | null>;
400
+ /** A job's runs, newest first. `limit` is a whole number from 1 to 500. */
401
+ runs(name: string, limit?: number): Promise<Run[]>;
402
+ getRun(id: string): Promise<Run | null>;
403
+ /** Stop alerts for a job for a while. State keeps updating underneath. */
404
+ silence(name: string, duration: Duration): Promise<JobState>;
405
+ unsilence(name: string): Promise<JobState>;
406
+ /** Read, change and write one job's state, in turn with every other update to it. */
407
+ private patchState;
408
+ /** Remove a job and its runs from the store. A job still declared in code comes back on its next run. */
409
+ forget(name: string): Promise<void>;
410
+ /** The dashboard and JSON API as fetch-style handlers. See createRoutes(). */
411
+ routes(options?: RoutesOptions): Routes;
412
+ /**
413
+ * Check on an interval, for long-running servers. Default every minute.
414
+ * Not for serverless functions or Cloudflare Workers, where nothing runs
415
+ * between requests: call check() from a cron there instead.
416
+ */
417
+ start(every?: Duration): void;
418
+ stop(): void;
419
+ close(): Promise<void>;
420
+ /**
421
+ * Compose, triage and send each draft. The state was saved before this
422
+ * (updateState), so a slow channel holds up nothing else; afterwards only
423
+ * the delivery fields are written back, onto a fresh read of the state.
424
+ */
425
+ private dispatch;
426
+ /**
427
+ * Send the alerts that no channel accepted last time, once each, oldest
428
+ * first. `state` is the job's state as this check left it: an alert that
429
+ * no longer describes it (staleAlert) is dropped instead. Retries across a
430
+ * check share RETRY_BUDGET_MS of wall-clock time; once it is spent the rest
431
+ * stay queued for the next check.
432
+ */
433
+ private retryUndelivered;
434
+ /**
435
+ * Mark delivered alerts done, drop stale ones, and keep failed ones for the
436
+ * next check. A failed alert replaces its stored copy, so a triage made on
437
+ * this attempt is kept. lastAlertAt moves only on a delivery.
438
+ */
439
+ private recordDelivery;
440
+ /** Send to every channel at once. True when at least one accepted it, or there are none. */
441
+ private deliver;
442
+ /** Sets alert.triage to the diagnosis, or to null when there is none, so it is tried once per alert. */
443
+ private addTriage;
444
+ }
445
+ /** Writes alerts to the console. The default channel. */
446
+ declare function consoleChannel(): AlertChannel;
447
+ /** Wrap any function as an alert channel. */
448
+ declare function custom(name: string, send: (alert: Alert) => Promise<void> | void): AlertChannel;
449
+
450
+ export { type CronWatchOptions as C, type FetchHandler as F, type HandlerFn as H, type JobContext as J, type RecordRunOptions as R, type Source as S, CronWatch as a, type HandlerOptions as b, type JobFn as c, type JobHandle as d, type Routes as e, type RoutesOptions as f, type RunHandle as g, type RunOutcome as h, type SourceHost as i, type StartOptions as j, consoleChannel as k, createRoutes as l, custom as m };