@cronwatch/sdk 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +31 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +31 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -157,15 +157,15 @@ function runCovers(startedAt, dueAt, followingAt = null) {
|
|
|
157
157
|
}
|
|
158
158
|
function inSpringForwardGap(parsed, startedAt, fireAt) {
|
|
159
159
|
const LOOKBACK = 3 * 36e5;
|
|
160
|
-
const
|
|
160
|
+
const after2 = utcOffset(fireAt, parsed.timezone);
|
|
161
161
|
const before = utcOffset(fireAt - LOOKBACK, parsed.timezone);
|
|
162
|
-
const gap =
|
|
162
|
+
const gap = after2 - before;
|
|
163
163
|
if (gap <= 0) return false;
|
|
164
164
|
let lo = fireAt - LOOKBACK;
|
|
165
165
|
let hi = fireAt;
|
|
166
166
|
while (hi - lo > 6e4) {
|
|
167
167
|
const mid = lo + Math.floor((hi - lo) / 2);
|
|
168
|
-
if (utcOffset(mid, parsed.timezone) ===
|
|
168
|
+
if (utcOffset(mid, parsed.timezone) === after2) hi = mid;
|
|
169
169
|
else lo = mid;
|
|
170
170
|
}
|
|
171
171
|
const jumpAt = Math.floor(hi / 6e4) * 6e4;
|
|
@@ -503,8 +503,8 @@ ${out}`);
|
|
|
503
503
|
break;
|
|
504
504
|
}
|
|
505
505
|
title = `${name} recovered`;
|
|
506
|
-
const
|
|
507
|
-
lines.push(`A run ${run ? when(run.startedAt, now) : "just now"} succeeded${
|
|
506
|
+
const after2 = draft.details.after.map((c) => c.replace("_", " ")).join(", ");
|
|
507
|
+
lines.push(`A run ${run ? when(run.startedAt, now) : "just now"} succeeded${after2 ? ` after: ${after2}` : ""}.`);
|
|
508
508
|
if (run?.durationMs !== null && run?.durationMs !== void 0) lines.push(`Ran ${formatDuration(run.durationMs)}.`);
|
|
509
509
|
break;
|
|
510
510
|
}
|
|
@@ -691,6 +691,9 @@ function checkExpectation(expect, output) {
|
|
|
691
691
|
function escapeHtml(value) {
|
|
692
692
|
return String(value ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
693
693
|
}
|
|
694
|
+
function escapeName(value) {
|
|
695
|
+
return escapeHtml(value).replace(/([_:./-]+)(?=[^_:./-])/g, "$1<wbr>");
|
|
696
|
+
}
|
|
694
697
|
|
|
695
698
|
// src/routes/icons.ts
|
|
696
699
|
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>';
|
|
@@ -1037,7 +1040,7 @@ function dayTimeline(lanes, span, base, total) {
|
|
|
1037
1040
|
const { job } = input;
|
|
1038
1041
|
const parts = lane(input, span, { nowInLane: false, label: job.name });
|
|
1039
1042
|
return {
|
|
1040
|
-
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)}">${
|
|
1043
|
+
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>`,
|
|
1041
1044
|
words: `<li>${escapeHtml(`${job.name} (${job.definition.schedule ?? "no schedule"}): ${parts.words}.`)}</li>`
|
|
1042
1045
|
};
|
|
1043
1046
|
});
|
|
@@ -1277,7 +1280,7 @@ ${options.refresh ? `<meta http-equiv="refresh" content="${options.refresh}">` :
|
|
|
1277
1280
|
}
|
|
1278
1281
|
function brand(base, crumb) {
|
|
1279
1282
|
const home = `<a href="${h(base)}/">${MARK}<span>CronWatch</span></a>`;
|
|
1280
|
-
return crumb === void 0 ? `<p class="brand">${home}</p>` : `<p class="brand">${home}<span class="slash" aria-hidden="true">/</span><span class="crumb">${
|
|
1283
|
+
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>`;
|
|
1281
1284
|
}
|
|
1282
1285
|
var HEALTH = {
|
|
1283
1286
|
failing: ["bad", "failing"],
|
|
@@ -1330,7 +1333,7 @@ function dashboardPage(jobs, runsByJob, now, base, checkedAt, lanes = jobs.slice
|
|
|
1330
1333
|
const last = job.lastRun;
|
|
1331
1334
|
const d = job.definition;
|
|
1332
1335
|
return `<tr>
|
|
1333
|
-
<td class="job"><a class="name" href="${h(base)}/jobs/${encodeURIComponent(job.name)}">${
|
|
1336
|
+
<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>
|
|
1334
1337
|
<td class="health">${healthState(job)}</td>
|
|
1335
1338
|
<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>
|
|
1336
1339
|
<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>
|
|
@@ -1402,7 +1405,7 @@ function jobPage(job, runs, now, base, complete = true) {
|
|
|
1402
1405
|
<section class="sec intro" aria-label="Job">
|
|
1403
1406
|
<h2>Job</h2>
|
|
1404
1407
|
<div>
|
|
1405
|
-
<h1 class="jobname">${
|
|
1408
|
+
<h1 class="jobname">${escapeName(job.name)}</h1>
|
|
1406
1409
|
${d.description ? `<p class="desc">${h(d.description)}</p>` : ""}
|
|
1407
1410
|
<p class="stateline">${healthState(job)}${why ? `<span class="why">${h(why)}</span>` : ""}</p>
|
|
1408
1411
|
<div class="actions">
|
|
@@ -2148,8 +2151,7 @@ var CronWatch = class {
|
|
|
2148
2151
|
const started = recorded ? this.updateState(name, (before) => ({ state: onRunStart(before), result: void 0 })).then(() => {
|
|
2149
2152
|
}, (e) => this.onError(e, `starting ${name}`)) : Promise.resolve();
|
|
2150
2153
|
const recorder = createRecorder(run);
|
|
2151
|
-
const
|
|
2152
|
-
if (typeof timer === "object" && "unref" in timer) timer.unref();
|
|
2154
|
+
const clearTimer = after(timeoutMs(definition), () => recorder.abort());
|
|
2153
2155
|
let result;
|
|
2154
2156
|
let error;
|
|
2155
2157
|
let threw = false;
|
|
@@ -2159,7 +2161,7 @@ var CronWatch = class {
|
|
|
2159
2161
|
error = e;
|
|
2160
2162
|
threw = true;
|
|
2161
2163
|
} finally {
|
|
2162
|
-
|
|
2164
|
+
clearTimer();
|
|
2163
2165
|
}
|
|
2164
2166
|
const finishedAt = this.now();
|
|
2165
2167
|
run.finishedAt = finishedAt;
|
|
@@ -2714,7 +2716,7 @@ ${id}`;
|
|
|
2714
2716
|
*/
|
|
2715
2717
|
start(every = "1m") {
|
|
2716
2718
|
if (this.timer) return;
|
|
2717
|
-
const ms = Math.max(5e3, parseDuration(every, "check interval"));
|
|
2719
|
+
const ms = Math.min(TIMER_MAX_MS, Math.max(5e3, parseDuration(every, "check interval")));
|
|
2718
2720
|
if (this.deferDelivery && !this.warnedDeferredStart) {
|
|
2719
2721
|
this.warnedDeferredStart = true;
|
|
2720
2722
|
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.');
|
|
@@ -2853,20 +2855,30 @@ function checkRunId(job, id, method) {
|
|
|
2853
2855
|
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`);
|
|
2854
2856
|
}
|
|
2855
2857
|
}
|
|
2856
|
-
function joinLines(before,
|
|
2857
|
-
if (before === null || before === "") return
|
|
2858
|
-
if (
|
|
2858
|
+
function joinLines(before, after2) {
|
|
2859
|
+
if (before === null || before === "") return after2;
|
|
2860
|
+
if (after2 === null) return before;
|
|
2859
2861
|
return `${before}
|
|
2860
|
-
${
|
|
2862
|
+
${after2}`;
|
|
2861
2863
|
}
|
|
2862
|
-
function joinOutput(before,
|
|
2863
|
-
const joined = joinLines(before,
|
|
2864
|
+
function joinOutput(before, after2) {
|
|
2865
|
+
const joined = joinLines(before, after2);
|
|
2864
2866
|
return joined === null ? null : capOutput(joined);
|
|
2865
2867
|
}
|
|
2866
2868
|
function clampLimit(limit, fallback, min) {
|
|
2867
2869
|
const n = typeof limit === "number" && Number.isFinite(limit) ? Math.trunc(limit) : fallback;
|
|
2868
2870
|
return Math.min(500, Math.max(min, n));
|
|
2869
2871
|
}
|
|
2872
|
+
var TIMER_MAX_MS = 2 ** 31 - 1;
|
|
2873
|
+
function after(ms, fn) {
|
|
2874
|
+
let timer;
|
|
2875
|
+
const arm = (left) => {
|
|
2876
|
+
timer = left > TIMER_MAX_MS ? setTimeout(() => arm(left - TIMER_MAX_MS), TIMER_MAX_MS) : setTimeout(fn, left);
|
|
2877
|
+
if (typeof timer === "object" && "unref" in timer) timer.unref();
|
|
2878
|
+
};
|
|
2879
|
+
arm(ms);
|
|
2880
|
+
return () => clearTimeout(timer);
|
|
2881
|
+
}
|
|
2870
2882
|
function withTimeout(promise, ms) {
|
|
2871
2883
|
return new Promise((resolve, reject) => {
|
|
2872
2884
|
const t = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);
|