@cronwatch/sdk 0.6.0 → 0.7.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 +2 -0
- package/dist/anthropic.cjs.map +1 -1
- package/dist/anthropic.d.cts +1 -1
- package/dist/anthropic.d.ts +1 -1
- package/dist/anthropic.js.map +1 -1
- package/dist/bugsnag.d.cts +1 -1
- package/dist/bugsnag.d.ts +1 -1
- package/dist/{client-B7bqnkI5.d.cts → client-B5hM4l-D.d.ts} +5 -2
- package/dist/{client-pmqH3apS.d.ts → client-Di5HAWQz.d.cts} +5 -2
- package/dist/d1.d.cts +1 -1
- package/dist/d1.d.ts +1 -1
- package/dist/datadog.d.cts +1 -1
- package/dist/datadog.d.ts +1 -1
- package/dist/discord.d.cts +1 -1
- package/dist/discord.d.ts +1 -1
- package/dist/{email-_H0faCh3.d.ts → email-Ciq7GRn4.d.ts} +1 -1
- package/dist/{email-BJ-z_epD.d.cts → email-DX6gkd5H.d.cts} +1 -1
- package/dist/honeybadger.d.cts +1 -1
- package/dist/honeybadger.d.ts +1 -1
- package/dist/index.cjs +60 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +60 -21
- package/dist/index.js.map +1 -1
- package/dist/mailgun.d.cts +2 -2
- package/dist/mailgun.d.ts +2 -2
- package/dist/newrelic.d.cts +1 -1
- package/dist/newrelic.d.ts +1 -1
- package/dist/pg-cron.d.cts +2 -2
- package/dist/pg-cron.d.ts +2 -2
- package/dist/postgres.d.cts +1 -1
- package/dist/postgres.d.ts +1 -1
- package/dist/postmark.d.cts +2 -2
- package/dist/postmark.d.ts +2 -2
- package/dist/resend.d.cts +2 -2
- package/dist/resend.d.ts +2 -2
- package/dist/rollbar.d.cts +1 -1
- package/dist/rollbar.d.ts +1 -1
- package/dist/sendgrid.d.cts +2 -2
- package/dist/sendgrid.d.ts +2 -2
- package/dist/sentry.d.cts +1 -1
- package/dist/sentry.d.ts +1 -1
- package/dist/ses.d.cts +2 -2
- package/dist/ses.d.ts +2 -2
- package/dist/slack.d.cts +1 -1
- package/dist/slack.d.ts +1 -1
- package/dist/sqlite.d.cts +1 -1
- package/dist/sqlite.d.ts +1 -1
- package/dist/twilio.d.cts +1 -1
- package/dist/twilio.d.ts +1 -1
- package/dist/{types-Ddq1MUPL.d.cts → types-BjBbCGeJ.d.cts} +4 -1
- package/dist/{types-Ddq1MUPL.d.ts → types-BjBbCGeJ.d.ts} +4 -1
- package/dist/webhook.d.cts +1 -1
- package/dist/webhook.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { C as CronWatchOptions, a as CronWatch } from './client-
|
|
2
|
-
export { F as FetchHandler, H as HandlerFn, b as HandlerOptions, J as JobContext, c as JobFn, d as JobHandle, R as RecordRunOptions, e as Routes, f as RoutesOptions, g as RunHandle, h as RunOutcome, S as Source, i as SourceHost, j as StartOptions, k as consoleChannel, l as createRoutes, m as custom } from './client-
|
|
3
|
-
import { S as Store, D as Duration, b as AlertDraft, c as StoredJobDefinition, A as Alert } from './types-
|
|
4
|
-
export { a as AlertChannel, d as AlertDetails, e as AlertType, B as BudgetBreach, C as ChannelContext, f as CheckResult, g as Condition, E as ExpectRule, J as JobDefinition, h as JobHealth, i as JobOptions, j as JobState, k as JobSummary, R as Run, l as RunStatus, m as StoredJob, T as TriageContext, n as TriageFn } from './types-
|
|
1
|
+
import { C as CronWatchOptions, a as CronWatch } from './client-Di5HAWQz.cjs';
|
|
2
|
+
export { F as FetchHandler, H as HandlerFn, b as HandlerOptions, J as JobContext, c as JobFn, d as JobHandle, R as RecordRunOptions, e as Routes, f as RoutesOptions, g as RunHandle, h as RunOutcome, S as Source, i as SourceHost, j as StartOptions, k as consoleChannel, l as createRoutes, m as custom } from './client-Di5HAWQz.cjs';
|
|
3
|
+
import { S as Store, D as Duration, b as AlertDraft, c as StoredJobDefinition, A as Alert } from './types-BjBbCGeJ.cjs';
|
|
4
|
+
export { a as AlertChannel, d as AlertDetails, e as AlertType, B as BudgetBreach, C as ChannelContext, f as CheckResult, g as Condition, E as ExpectRule, J as JobDefinition, h as JobHealth, i as JobOptions, j as JobState, k as JobSummary, R as Run, l as RunStatus, m as StoredJob, T as TriageContext, n as TriageFn } from './types-BjBbCGeJ.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Keeps everything in process memory. The default when no store is given,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { C as CronWatchOptions, a as CronWatch } from './client-
|
|
2
|
-
export { F as FetchHandler, H as HandlerFn, b as HandlerOptions, J as JobContext, c as JobFn, d as JobHandle, R as RecordRunOptions, e as Routes, f as RoutesOptions, g as RunHandle, h as RunOutcome, S as Source, i as SourceHost, j as StartOptions, k as consoleChannel, l as createRoutes, m as custom } from './client-
|
|
3
|
-
import { S as Store, D as Duration, b as AlertDraft, c as StoredJobDefinition, A as Alert } from './types-
|
|
4
|
-
export { a as AlertChannel, d as AlertDetails, e as AlertType, B as BudgetBreach, C as ChannelContext, f as CheckResult, g as Condition, E as ExpectRule, J as JobDefinition, h as JobHealth, i as JobOptions, j as JobState, k as JobSummary, R as Run, l as RunStatus, m as StoredJob, T as TriageContext, n as TriageFn } from './types-
|
|
1
|
+
import { C as CronWatchOptions, a as CronWatch } from './client-B5hM4l-D.js';
|
|
2
|
+
export { F as FetchHandler, H as HandlerFn, b as HandlerOptions, J as JobContext, c as JobFn, d as JobHandle, R as RecordRunOptions, e as Routes, f as RoutesOptions, g as RunHandle, h as RunOutcome, S as Source, i as SourceHost, j as StartOptions, k as consoleChannel, l as createRoutes, m as custom } from './client-B5hM4l-D.js';
|
|
3
|
+
import { S as Store, D as Duration, b as AlertDraft, c as StoredJobDefinition, A as Alert } from './types-BjBbCGeJ.js';
|
|
4
|
+
export { a as AlertChannel, d as AlertDetails, e as AlertType, B as BudgetBreach, C as ChannelContext, f as CheckResult, g as Condition, E as ExpectRule, J as JobDefinition, h as JobHealth, i as JobOptions, j as JobState, k as JobSummary, R as Run, l as RunStatus, m as StoredJob, T as TriageContext, n as TriageFn } from './types-BjBbCGeJ.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Keeps everything in process memory. The default when no store is given,
|
package/dist/index.js
CHANGED
|
@@ -9,11 +9,14 @@ var UNIT_MS = {
|
|
|
9
9
|
d: 864e5,
|
|
10
10
|
w: 6048e5
|
|
11
11
|
};
|
|
12
|
+
var MAX_LENGTH = 64;
|
|
13
|
+
var QUOTED = 32;
|
|
12
14
|
function parseDuration(value, label = "duration") {
|
|
13
15
|
if (typeof value === "number") {
|
|
14
16
|
if (!Number.isFinite(value) || value < 0) throw new Error(`${label} must be a non-negative number of milliseconds`);
|
|
15
17
|
return value;
|
|
16
18
|
}
|
|
19
|
+
if (value.length > MAX_LENGTH) tooLong(value, label);
|
|
17
20
|
const text = value.trim().toLowerCase();
|
|
18
21
|
if (text === "") throw new Error(`${label} is empty`);
|
|
19
22
|
const re = /(\d+(?:\.\d+)?)\s*(ms|s|m|h|d|w)/g;
|
|
@@ -29,6 +32,16 @@ function parseDuration(value, label = "duration") {
|
|
|
29
32
|
}
|
|
30
33
|
return Math.round(total);
|
|
31
34
|
}
|
|
35
|
+
function tooLong(value, label) {
|
|
36
|
+
let count = 0;
|
|
37
|
+
let head = "";
|
|
38
|
+
for (const char of value) {
|
|
39
|
+
if (count < QUOTED) head += char;
|
|
40
|
+
if (++count > MAX_LENGTH) {
|
|
41
|
+
throw new Error(`${label} "${head}..." is too long for a duration (more than ${MAX_LENGTH} characters)`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
32
45
|
function formatDuration(ms) {
|
|
33
46
|
if (!Number.isFinite(ms)) return "?";
|
|
34
47
|
if (ms < 1e3) return `${Math.round(ms)}ms`;
|
|
@@ -155,15 +168,15 @@ function runCovers(startedAt, dueAt, followingAt = null) {
|
|
|
155
168
|
}
|
|
156
169
|
function inSpringForwardGap(parsed, startedAt, fireAt) {
|
|
157
170
|
const LOOKBACK = 3 * 36e5;
|
|
158
|
-
const
|
|
171
|
+
const after2 = utcOffset(fireAt, parsed.timezone);
|
|
159
172
|
const before = utcOffset(fireAt - LOOKBACK, parsed.timezone);
|
|
160
|
-
const gap =
|
|
173
|
+
const gap = after2 - before;
|
|
161
174
|
if (gap <= 0) return false;
|
|
162
175
|
let lo = fireAt - LOOKBACK;
|
|
163
176
|
let hi = fireAt;
|
|
164
177
|
while (hi - lo > 6e4) {
|
|
165
178
|
const mid = lo + Math.floor((hi - lo) / 2);
|
|
166
|
-
if (utcOffset(mid, parsed.timezone) ===
|
|
179
|
+
if (utcOffset(mid, parsed.timezone) === after2) hi = mid;
|
|
167
180
|
else lo = mid;
|
|
168
181
|
}
|
|
169
182
|
const jumpAt = Math.floor(hi / 6e4) * 6e4;
|
|
@@ -501,8 +514,8 @@ ${out}`);
|
|
|
501
514
|
break;
|
|
502
515
|
}
|
|
503
516
|
title = `${name} recovered`;
|
|
504
|
-
const
|
|
505
|
-
lines.push(`A run ${run ? when(run.startedAt, now) : "just now"} succeeded${
|
|
517
|
+
const after2 = draft.details.after.map((c) => c.replace("_", " ")).join(", ");
|
|
518
|
+
lines.push(`A run ${run ? when(run.startedAt, now) : "just now"} succeeded${after2 ? ` after: ${after2}` : ""}.`);
|
|
506
519
|
if (run?.durationMs !== null && run?.durationMs !== void 0) lines.push(`Ran ${formatDuration(run.durationMs)}.`);
|
|
507
520
|
break;
|
|
508
521
|
}
|
|
@@ -689,6 +702,9 @@ function checkExpectation(expect, output) {
|
|
|
689
702
|
function escapeHtml(value) {
|
|
690
703
|
return String(value ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
691
704
|
}
|
|
705
|
+
function escapeName(value) {
|
|
706
|
+
return escapeHtml(value).replace(/([_:./-]+)(?=[^_:./-])/g, "$1<wbr>");
|
|
707
|
+
}
|
|
692
708
|
|
|
693
709
|
// src/routes/icons.ts
|
|
694
710
|
var ICON_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><rect width="40" height="40" rx="10" fill="#141417"/><rect x="0.5" y="0.5" width="39" height="39" rx="9.5" fill="none" stroke="#2a2a2f"/><circle cx="20" cy="20" r="10.5" fill="none" stroke="#f3f3f1" stroke-width="2"/><path d="M20 12.5V20h6" fill="none" stroke="#f3f3f1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
|
@@ -1035,7 +1051,7 @@ function dayTimeline(lanes, span, base, total) {
|
|
|
1035
1051
|
const { job } = input;
|
|
1036
1052
|
const parts = lane(input, span, { nowInLane: false, label: job.name });
|
|
1037
1053
|
return {
|
|
1038
|
-
html: `<li class="lane"><div class="who"><i class="sq ${stateClass(job)}" aria-hidden="true"></i><a class="name" href="${escapeHtml(base)}/jobs/${encodeURIComponent(job.name)}">${
|
|
1054
|
+
html: `<li class="lane"><div class="who"><i class="sq ${stateClass(job)}" aria-hidden="true"></i><a class="name" href="${escapeHtml(base)}/jobs/${encodeURIComponent(job.name)}">${escapeName(job.name)}</a><span class="sched">${escapeHtml(job.definition.schedule ?? "no schedule")}</span></div><div class="track">${parts.svg}${parts.note}</div></li>`,
|
|
1039
1055
|
words: `<li>${escapeHtml(`${job.name} (${job.definition.schedule ?? "no schedule"}): ${parts.words}.`)}</li>`
|
|
1040
1056
|
};
|
|
1041
1057
|
});
|
|
@@ -1275,7 +1291,7 @@ ${options.refresh ? `<meta http-equiv="refresh" content="${options.refresh}">` :
|
|
|
1275
1291
|
}
|
|
1276
1292
|
function brand(base, crumb) {
|
|
1277
1293
|
const home = `<a href="${h(base)}/">${MARK}<span>CronWatch</span></a>`;
|
|
1278
|
-
return crumb === void 0 ? `<p class="brand">${home}</p>` : `<p class="brand">${home}<span class="slash" aria-hidden="true">/</span><span class="crumb">${
|
|
1294
|
+
return crumb === void 0 ? `<p class="brand">${home}</p>` : `<p class="brand">${home}<span class="slash" aria-hidden="true">/</span><span class="crumb">${escapeName(crumb)}</span></p>`;
|
|
1279
1295
|
}
|
|
1280
1296
|
var HEALTH = {
|
|
1281
1297
|
failing: ["bad", "failing"],
|
|
@@ -1328,7 +1344,7 @@ function dashboardPage(jobs, runsByJob, now, base, checkedAt, lanes = jobs.slice
|
|
|
1328
1344
|
const last = job.lastRun;
|
|
1329
1345
|
const d = job.definition;
|
|
1330
1346
|
return `<tr>
|
|
1331
|
-
<td class="job"><a class="name" href="${h(base)}/jobs/${encodeURIComponent(job.name)}">${
|
|
1347
|
+
<td class="job"><a class="name" href="${h(base)}/jobs/${encodeURIComponent(job.name)}">${escapeName(job.name)}</a>${d.description ? `<span class="desc">${h(d.description)}</span>` : ""}</td>
|
|
1332
1348
|
<td class="health">${healthState(job)}</td>
|
|
1333
1349
|
<td class="nowrap hide-sm">${d.schedule ? `${h(d.schedule)}${d.timezone ? `<span class="tz">${h(d.timezone)}</span>` : ""}` : `<span class="muted">no schedule</span>`}</td>
|
|
1334
1350
|
<td class="nowrap last">${last ? `${runState(last)} ${stamp(last.startedAt, now)}${last.durationMs !== null ? `<span class="sub">took ${h(formatDuration(last.durationMs))}</span>` : ""}` : `<span class="muted">never</span>`}</td>
|
|
@@ -1400,7 +1416,7 @@ function jobPage(job, runs, now, base, complete = true) {
|
|
|
1400
1416
|
<section class="sec intro" aria-label="Job">
|
|
1401
1417
|
<h2>Job</h2>
|
|
1402
1418
|
<div>
|
|
1403
|
-
<h1 class="jobname">${
|
|
1419
|
+
<h1 class="jobname">${escapeName(job.name)}</h1>
|
|
1404
1420
|
${d.description ? `<p class="desc">${h(d.description)}</p>` : ""}
|
|
1405
1421
|
<p class="stateline">${healthState(job)}${why ? `<span class="why">${h(why)}</span>` : ""}</p>
|
|
1406
1422
|
<div class="actions">
|
|
@@ -1477,7 +1493,20 @@ function developmentToken() {
|
|
|
1477
1493
|
return btoa(String.fromCharCode(...bytes)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1478
1494
|
}
|
|
1479
1495
|
function developmentSignInLine(origin, base, token) {
|
|
1480
|
-
|
|
1496
|
+
const intro = "[cronwatch] CRONWATCH_TOKEN is not set, so this development server made a token for the dashboard. Sign in: ";
|
|
1497
|
+
return origin === null ? `${intro}${base}/?token=${token} on this server (the first request's host is not local, so the link leaves it out)` : `${intro}${origin}${base}/?token=${token}`;
|
|
1498
|
+
}
|
|
1499
|
+
function isLoopbackOrigin(origin) {
|
|
1500
|
+
let host;
|
|
1501
|
+
try {
|
|
1502
|
+
host = new URL(origin).hostname.toLowerCase();
|
|
1503
|
+
} catch {
|
|
1504
|
+
return false;
|
|
1505
|
+
}
|
|
1506
|
+
if (host === "localhost" || host.endsWith(".localhost")) return true;
|
|
1507
|
+
if (host === "[::1]") return true;
|
|
1508
|
+
const octets = /^127\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(host);
|
|
1509
|
+
return octets !== null && octets.slice(1).every((o) => Number(o) <= 255);
|
|
1481
1510
|
}
|
|
1482
1511
|
function safeDecode(value) {
|
|
1483
1512
|
try {
|
|
@@ -1582,7 +1611,8 @@ function createRoutes(cw, options = {}) {
|
|
|
1582
1611
|
const publicOrigin = originOf(request, url);
|
|
1583
1612
|
if (generated && !announced) {
|
|
1584
1613
|
announced = true;
|
|
1585
|
-
|
|
1614
|
+
const shown = fixedOrigin ?? (isLoopbackOrigin(publicOrigin) ? publicOrigin : null);
|
|
1615
|
+
console.info(developmentSignInLine(shown, base, token));
|
|
1586
1616
|
}
|
|
1587
1617
|
if (method === "GET" || method === "HEAD") {
|
|
1588
1618
|
if (path === "/offline") {
|
|
@@ -2146,8 +2176,7 @@ var CronWatch = class {
|
|
|
2146
2176
|
const started = recorded ? this.updateState(name, (before) => ({ state: onRunStart(before), result: void 0 })).then(() => {
|
|
2147
2177
|
}, (e) => this.onError(e, `starting ${name}`)) : Promise.resolve();
|
|
2148
2178
|
const recorder = createRecorder(run);
|
|
2149
|
-
const
|
|
2150
|
-
if (typeof timer === "object" && "unref" in timer) timer.unref();
|
|
2179
|
+
const clearTimer = after(timeoutMs(definition), () => recorder.abort());
|
|
2151
2180
|
let result;
|
|
2152
2181
|
let error;
|
|
2153
2182
|
let threw = false;
|
|
@@ -2157,7 +2186,7 @@ var CronWatch = class {
|
|
|
2157
2186
|
error = e;
|
|
2158
2187
|
threw = true;
|
|
2159
2188
|
} finally {
|
|
2160
|
-
|
|
2189
|
+
clearTimer();
|
|
2161
2190
|
}
|
|
2162
2191
|
const finishedAt = this.now();
|
|
2163
2192
|
run.finishedAt = finishedAt;
|
|
@@ -2712,7 +2741,7 @@ ${id}`;
|
|
|
2712
2741
|
*/
|
|
2713
2742
|
start(every = "1m") {
|
|
2714
2743
|
if (this.timer) return;
|
|
2715
|
-
const ms = Math.max(5e3, parseDuration(every, "check interval"));
|
|
2744
|
+
const ms = Math.min(TIMER_MAX_MS, Math.max(5e3, parseDuration(every, "check interval")));
|
|
2716
2745
|
if (this.deferDelivery && !this.warnedDeferredStart) {
|
|
2717
2746
|
this.warnedDeferredStart = true;
|
|
2718
2747
|
console.warn('[cronwatch] start() was called with deliver: "check", so these checks send no alerts. Another process must run checks with deliver: "now" (the default) to send them.');
|
|
@@ -2851,20 +2880,30 @@ function checkRunId(job, id, method) {
|
|
|
2851
2880
|
throw new Error(`job "${job}": ${method}() cannot take a run id starting with "${RESERVED_RUN_ID_PREFIX}", which the pg_cron source uses for its runs`);
|
|
2852
2881
|
}
|
|
2853
2882
|
}
|
|
2854
|
-
function joinLines(before,
|
|
2855
|
-
if (before === null || before === "") return
|
|
2856
|
-
if (
|
|
2883
|
+
function joinLines(before, after2) {
|
|
2884
|
+
if (before === null || before === "") return after2;
|
|
2885
|
+
if (after2 === null) return before;
|
|
2857
2886
|
return `${before}
|
|
2858
|
-
${
|
|
2887
|
+
${after2}`;
|
|
2859
2888
|
}
|
|
2860
|
-
function joinOutput(before,
|
|
2861
|
-
const joined = joinLines(before,
|
|
2889
|
+
function joinOutput(before, after2) {
|
|
2890
|
+
const joined = joinLines(before, after2);
|
|
2862
2891
|
return joined === null ? null : capOutput(joined);
|
|
2863
2892
|
}
|
|
2864
2893
|
function clampLimit(limit, fallback, min) {
|
|
2865
2894
|
const n = typeof limit === "number" && Number.isFinite(limit) ? Math.trunc(limit) : fallback;
|
|
2866
2895
|
return Math.min(500, Math.max(min, n));
|
|
2867
2896
|
}
|
|
2897
|
+
var TIMER_MAX_MS = 2 ** 31 - 1;
|
|
2898
|
+
function after(ms, fn) {
|
|
2899
|
+
let timer;
|
|
2900
|
+
const arm = (left) => {
|
|
2901
|
+
timer = left > TIMER_MAX_MS ? setTimeout(() => arm(left - TIMER_MAX_MS), TIMER_MAX_MS) : setTimeout(fn, left);
|
|
2902
|
+
if (typeof timer === "object" && "unref" in timer) timer.unref();
|
|
2903
|
+
};
|
|
2904
|
+
arm(ms);
|
|
2905
|
+
return () => clearTimeout(timer);
|
|
2906
|
+
}
|
|
2868
2907
|
function withTimeout(promise, ms) {
|
|
2869
2908
|
return new Promise((resolve, reject) => {
|
|
2870
2909
|
const t = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);
|