@connextar/house 0.11.0 → 0.13.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 +581 -19
- package/dist/auth/index.d.ts +3 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +3 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/second-factor-index.d.ts +7 -0
- package/dist/auth/second-factor-index.d.ts.map +1 -0
- package/dist/auth/second-factor-index.js +7 -0
- package/dist/auth/second-factor-index.js.map +1 -0
- package/dist/auth/second-factor-next.d.ts +39 -0
- package/dist/auth/second-factor-next.d.ts.map +1 -0
- package/dist/auth/second-factor-next.js +131 -0
- package/dist/auth/second-factor-next.js.map +1 -0
- package/dist/auth/second-factor-routes.d.ts +29 -0
- package/dist/auth/second-factor-routes.d.ts.map +1 -0
- package/dist/auth/second-factor-routes.js +35 -0
- package/dist/auth/second-factor-routes.js.map +1 -0
- package/dist/auth/second-factor.d.ts +117 -0
- package/dist/auth/second-factor.d.ts.map +1 -0
- package/dist/auth/second-factor.js +127 -0
- package/dist/auth/second-factor.js.map +1 -0
- package/dist/auth/two-factor-policy.d.ts +30 -1
- package/dist/auth/two-factor-policy.d.ts.map +1 -1
- package/dist/auth/two-factor-policy.js +39 -1
- package/dist/auth/two-factor-policy.js.map +1 -1
- package/dist/jobs/health.d.ts +17 -4
- package/dist/jobs/health.d.ts.map +1 -1
- package/dist/jobs/health.js +10 -7
- package/dist/jobs/health.js.map +1 -1
- package/dist/jobs/index.d.ts +4 -3
- package/dist/jobs/index.d.ts.map +1 -1
- package/dist/jobs/index.js +3 -2
- package/dist/jobs/index.js.map +1 -1
- package/dist/jobs/job-health-list.d.ts +15 -3
- package/dist/jobs/job-health-list.d.ts.map +1 -1
- package/dist/jobs/job-health-list.js +11 -7
- package/dist/jobs/job-health-list.js.map +1 -1
- package/dist/jobs/prune.d.ts +45 -0
- package/dist/jobs/prune.d.ts.map +1 -0
- package/dist/jobs/prune.js +58 -0
- package/dist/jobs/prune.js.map +1 -0
- package/dist/jobs/registry.d.ts +19 -4
- package/dist/jobs/registry.d.ts.map +1 -1
- package/dist/jobs/registry.js +16 -1
- package/dist/jobs/registry.js.map +1 -1
- package/dist/jobs/scheduler.d.ts +12 -1
- package/dist/jobs/scheduler.d.ts.map +1 -1
- package/dist/jobs/scheduler.js +24 -9
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/jobs/store.d.ts +26 -1
- package/dist/jobs/store.d.ts.map +1 -1
- package/dist/jobs/store.js +35 -4
- package/dist/jobs/store.js.map +1 -1
- package/dist/password/common.d.ts +2 -0
- package/dist/password/common.d.ts.map +1 -0
- package/dist/password/common.js +58 -0
- package/dist/password/common.js.map +1 -0
- package/dist/password/estimate-index.d.ts +10 -0
- package/dist/password/estimate-index.d.ts.map +1 -0
- package/dist/password/estimate-index.js +10 -0
- package/dist/password/estimate-index.js.map +1 -0
- package/dist/password/estimate.d.ts +65 -0
- package/dist/password/estimate.d.ts.map +1 -0
- package/dist/password/estimate.js +612 -0
- package/dist/password/estimate.js.map +1 -0
- package/dist/password/index.d.ts +22 -0
- package/dist/password/index.d.ts.map +1 -0
- package/dist/password/index.js +22 -0
- package/dist/password/index.js.map +1 -0
- package/dist/password/password-input.d.ts +55 -0
- package/dist/password/password-input.d.ts.map +1 -0
- package/dist/password/password-input.js +54 -0
- package/dist/password/password-input.js.map +1 -0
- package/dist/password/password-strength.d.ts +59 -0
- package/dist/password/password-strength.d.ts.map +1 -0
- package/dist/password/password-strength.js +74 -0
- package/dist/password/password-strength.js.map +1 -0
- package/dist/password/reveal.d.ts +56 -0
- package/dist/password/reveal.d.ts.map +1 -0
- package/dist/password/reveal.js +109 -0
- package/dist/password/reveal.js.map +1 -0
- package/package.json +19 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SECOND_FACTOR_EVERYWHERE_ID } from "./second-factor-routes.js";
|
|
1
2
|
/**
|
|
2
3
|
* Which sign-in routes need the second factor enforced by hand.
|
|
3
4
|
*
|
|
@@ -18,6 +19,12 @@
|
|
|
18
19
|
* This lives in the package rather than in each app because it is a security
|
|
19
20
|
* decision that has to be the same everywhere, and because getting it wrong is
|
|
20
21
|
* silent: two-factor keeps *looking* enabled while doing nothing.
|
|
22
|
+
*
|
|
23
|
+
* **Superseded by `secondFactorEverywhere()`** (`@connextar/house/auth/second-factor`),
|
|
24
|
+
* which instead puts the code screen after a magic link *and* after a social
|
|
25
|
+
* sign-in, so neither needs refusing. Pass the hook's `ctx.context` to
|
|
26
|
+
* {@link shouldBlockForTwoFactor} and the refusal retires itself while that plugin
|
|
27
|
+
* is live — see {@link magicLinkRefusalRetired}.
|
|
21
28
|
*/
|
|
22
29
|
export const TWO_FACTOR_BLOCKED_PATHS = ["/sign-in/magic-link"];
|
|
23
30
|
export const TWO_FACTOR_BLOCKED_MESSAGE = "This account uses two-factor authentication. Sign in with your email and password, " +
|
|
@@ -37,11 +44,42 @@ export function isTwoFactorBlockedPath(path) {
|
|
|
37
44
|
* answering "does this account exist, and does it have two-factor on?" for
|
|
38
45
|
* anyone with an email address and a spare minute.
|
|
39
46
|
*/
|
|
40
|
-
export async function shouldBlockForTwoFactor(path, email, lookup
|
|
47
|
+
export async function shouldBlockForTwoFactor(path, email, lookup,
|
|
48
|
+
/**
|
|
49
|
+
* The hook's `ctx.context`. Passing it retires the refusal once `secondFactorEverywhere()` is installed and
|
|
50
|
+
* challenging magic links — see {@link magicLinkRefusalRetired}.
|
|
51
|
+
*/
|
|
52
|
+
authContext) {
|
|
41
53
|
if (!isTwoFactorBlockedPath(path) || !email)
|
|
42
54
|
return false;
|
|
55
|
+
if (authContext && magicLinkRefusalRetired(authContext))
|
|
56
|
+
return false;
|
|
43
57
|
return lookup(email.toLowerCase());
|
|
44
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* True when refusing magic links for two-factor accounts is no longer needed, because
|
|
61
|
+
* `secondFactorEverywhere()` from `@connextar/house/auth/second-factor` is installed, enabled, and puts the code
|
|
62
|
+
* screen behind `/magic-link/verify`.
|
|
63
|
+
*
|
|
64
|
+
* This is how an app retires its old before-hook refusal *safely*: the refusal steps aside exactly while its
|
|
65
|
+
* replacement is live, and comes back on its own if the replacement is ever switched off (`enabled: false`) or
|
|
66
|
+
* removed — so turning the challenge off can never quietly reopen the magic-link hole. Pass `ctx.context` from a
|
|
67
|
+
* hook, or `auth.options`.
|
|
68
|
+
*/
|
|
69
|
+
export function magicLinkRefusalRetired(authContext) {
|
|
70
|
+
const plugins = authContext.options?.plugins ?? authContext.plugins ?? [];
|
|
71
|
+
return plugins.some((plugin) => {
|
|
72
|
+
if (!plugin || typeof plugin !== "object")
|
|
73
|
+
return false;
|
|
74
|
+
const { id, options } = plugin;
|
|
75
|
+
if (id !== SECOND_FACTOR_EVERYWHERE_ID)
|
|
76
|
+
return false;
|
|
77
|
+
if (options?.enabled === false)
|
|
78
|
+
return false;
|
|
79
|
+
const routes = options?.routes;
|
|
80
|
+
return !Array.isArray(routes) || routes.includes("/magic-link/verify");
|
|
81
|
+
});
|
|
82
|
+
}
|
|
45
83
|
/**
|
|
46
84
|
* Pull the shared secret out of an `otpauth://` URI, for the "can't scan it?"
|
|
47
85
|
* manual-entry path during enrolment.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"two-factor-policy.js","sourceRoot":"","sources":["../../src/auth/two-factor-policy.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"two-factor-policy.js","sourceRoot":"","sources":["../../src/auth/two-factor-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,qBAAqB,CAAU,CAAC;AAIzE,MAAM,CAAC,MAAM,0BAA0B,GACrC,qFAAqF;IACrF,kDAAkD,CAAC;AAErD,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,OAAQ,wBAA8C,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxE,CAAC;AAKD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,IAAY,EACZ,KAAgC,EAChC,MAAuB;AACvB;;;GAGG;AACH,WAAoC;IAEpC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAC1D,IAAI,WAAW,IAAI,uBAAuB,CAAC,WAAW,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,OAAO,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;AACrC,CAAC;AAQD;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CAAC,WAA4B;IAClE,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,OAAO,IAAI,WAAW,CAAC,OAAO,IAAI,EAAE,CAAC;IAC1E,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;QAC7B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACxD,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,MAA6E,CAAC;QACtG,IAAI,EAAE,KAAK,2BAA2B;YAAE,OAAO,KAAK,CAAC;QACrD,IAAI,OAAO,EAAE,OAAO,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QAC7C,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAClD,CAAC"}
|
package/dist/jobs/health.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CountFormatOptions, type CountLine } from "./counts.js";
|
|
2
|
-
import type
|
|
2
|
+
import { type AnyJob, type RunNowScope } from "./registry.js";
|
|
3
3
|
import type { JobRunRecord, JobSwitchState } from "./store.js";
|
|
4
4
|
/**
|
|
5
5
|
* A job's health — derived every time it is shown, never stored.
|
|
@@ -22,7 +22,9 @@ import type { JobRunRecord, JobSwitchState } from "./store.js";
|
|
|
22
22
|
* run exactly at the threshold is still healthy). A tenant's own Run now
|
|
23
23
|
* sweeps one tenant, so it proves nothing about the schedule and does not
|
|
24
24
|
* reset the clock — in Quickie it did, so one owner's click made a job look
|
|
25
|
-
* healthy to everyone.
|
|
25
|
+
* healthy to everyone. A platform Run now sweeps every tenant, as the
|
|
26
|
+
* schedule does, so it counts: an operator re-running a failed sweep puts
|
|
27
|
+
* the job right for everyone.
|
|
26
28
|
* 6. **healthy**.
|
|
27
29
|
*/
|
|
28
30
|
export type JobHealthState = "paused" | "never-run" | "running" | "failed" | "stale" | "healthy";
|
|
@@ -108,8 +110,17 @@ export interface JobView {
|
|
|
108
110
|
switchedBy: string | null;
|
|
109
111
|
/** This viewer may switch it. */
|
|
110
112
|
canSwitch: boolean;
|
|
111
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* This viewer may press Run now, and what it would sweep — the first of
|
|
115
|
+
* `runNowScopes`, or `null` when there are none.
|
|
116
|
+
*/
|
|
112
117
|
runNow: RunNowScope | null;
|
|
118
|
+
/**
|
|
119
|
+
* Every Run now this viewer may press, narrowest first. One scope for almost
|
|
120
|
+
* everyone: on a job that offers both, an operator (platform, no tenant) gets
|
|
121
|
+
* `["platform"]` and an owner `["tenant"]`; only a viewer holding both gets two.
|
|
122
|
+
*/
|
|
123
|
+
runNowScopes: RunNowScope[];
|
|
113
124
|
lastRun: JobRunView | null;
|
|
114
125
|
lastSuccess: JobRunView | null;
|
|
115
126
|
}
|
|
@@ -124,7 +135,9 @@ export interface JobViewOptions extends CountFormatOptions {
|
|
|
124
135
|
now: Date;
|
|
125
136
|
}
|
|
126
137
|
export declare function effectiveTimeout(job: AnyJob, fallback: number): number;
|
|
127
|
-
/**
|
|
138
|
+
/** Every Run now this viewer may press on this job, narrowest first: a tenant run needs a tenant, a platform run platform authority. */
|
|
139
|
+
export declare function runNowScopesFor(job: AnyJob, audience: JobAudience): RunNowScope[];
|
|
140
|
+
/** Whether this viewer may press Run now on this job, and over whom — the narrowest scope they hold. */
|
|
128
141
|
export declare function runNowFor(job: AnyJob, audience: JobAudience): RunNowScope | null;
|
|
129
142
|
export declare function buildJobView(job: AnyJob, facts: JobFacts, audience: JobAudience, options: JobViewOptions & {
|
|
130
143
|
timeoutMs: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/jobs/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/jobs/health.ts"],"names":[],"mappings":"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"}
|
package/dist/jobs/health.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { countLines, describeSpan } from "./counts.js";
|
|
2
|
+
import { runNowScopes } from "./registry.js";
|
|
2
3
|
import { isManualKey } from "./windows.js";
|
|
3
4
|
export function deriveHealth(input) {
|
|
4
5
|
const { latest, lastWholeSuccess, now } = input;
|
|
@@ -29,13 +30,13 @@ export function deriveHealth(input) {
|
|
|
29
30
|
export function effectiveTimeout(job, fallback) {
|
|
30
31
|
return job.timeoutMs ?? fallback;
|
|
31
32
|
}
|
|
32
|
-
/**
|
|
33
|
+
/** Every Run now this viewer may press on this job, narrowest first: a tenant run needs a tenant, a platform run platform authority. */
|
|
34
|
+
export function runNowScopesFor(job, audience) {
|
|
35
|
+
return runNowScopes(job.runNow).filter((scope) => scope === "tenant" ? Boolean(audience.tenantId) : audience.platform);
|
|
36
|
+
}
|
|
37
|
+
/** Whether this viewer may press Run now on this job, and over whom — the narrowest scope they hold. */
|
|
33
38
|
export function runNowFor(job, audience) {
|
|
34
|
-
|
|
35
|
-
return null;
|
|
36
|
-
if (job.runNow.scope === "tenant")
|
|
37
|
-
return audience.tenantId ? "tenant" : null;
|
|
38
|
-
return audience.platform ? "platform" : null;
|
|
39
|
+
return runNowScopesFor(job, audience)[0] ?? null;
|
|
39
40
|
}
|
|
40
41
|
function runView(job, run, audience, options) {
|
|
41
42
|
const withheld = !audience.platform && run.tenantId === null;
|
|
@@ -54,6 +55,7 @@ function runView(job, run, audience, options) {
|
|
|
54
55
|
export function buildJobView(job, facts, audience, options) {
|
|
55
56
|
const switchable = job.switchable ?? true;
|
|
56
57
|
const paused = switchable && Boolean(facts.switch?.paused);
|
|
58
|
+
const runNowScopes = runNowScopesFor(job, audience);
|
|
57
59
|
const lastRun = facts.latest ? runView(job, facts.latest, audience, options) : null;
|
|
58
60
|
const input = {
|
|
59
61
|
latest: facts.latest,
|
|
@@ -77,7 +79,8 @@ export function buildJobView(job, facts, audience, options) {
|
|
|
77
79
|
switchedAt: switchable ? (facts.switch?.at?.toISOString() ?? null) : null,
|
|
78
80
|
switchedBy: switchable ? (facts.switch?.by ?? null) : null,
|
|
79
81
|
canSwitch: switchable && audience.platform,
|
|
80
|
-
runNow:
|
|
82
|
+
runNow: runNowScopes[0] ?? null,
|
|
83
|
+
runNowScopes,
|
|
81
84
|
lastRun,
|
|
82
85
|
lastSuccess: facts.lastVisibleSuccess ? runView(job, facts.lastVisibleSuccess, audience, options) : null,
|
|
83
86
|
};
|
package/dist/jobs/health.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/jobs/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAA2C,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/jobs/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAA2C,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,YAAY,EAAiC,MAAM,eAAe,CAAC;AAE5E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAyD3C,MAAM,UAAU,YAAY,CAAC,KAAkB;IAC7C,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAChD,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IAC7C,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB;QAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IAChE,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACjC,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAClE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QACrE,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IAChG,CAAC;IACD,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACzG,CAAC;IACD,IACE,KAAK,CAAC,YAAY,KAAK,IAAI;QAC3B,CAAC,CAAC,gBAAgB,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,gBAAgB,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,YAAY,CAAC,EAChG,CAAC;QACD,OAAO;YACL,KAAK,EAAE,OAAO;YACd,aAAa,EAAE,gBAAgB,EAAE,SAAS,CAAC,WAAW,EAAE,IAAI,IAAI;YAChE,WAAW,EAAE,KAAK,CAAC,YAAY;SAChC,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,gBAAgB,IAAI,MAAO,CAAC;IAC5C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;AAC9E,CAAC;AA2ED,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,QAAgB;IAC5D,OAAO,GAAG,CAAC,SAAS,IAAI,QAAQ,CAAC;AACnC,CAAC;AAED,wIAAwI;AACxI,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,QAAqB;IAChE,OAAO,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAC/C,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CACpE,CAAC;AACJ,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,QAAqB;IAC1D,OAAO,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACnD,CAAC;AAED,SAAS,OAAO,CAAC,GAAW,EAAE,GAAiB,EAAE,QAAqB,EAAE,OAA2B;IACjG,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC;IAC7D,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE;QACtC,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,IAAI,IAAI;QACjD,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU;QAC3D,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,YAAY,EAAE,GAAG,CAAC,QAAQ,KAAK,IAAI;QACnC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;QACnE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK;QAClC,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,GAAW,EACX,KAAe,EACf,QAAqB,EACrB,OAA+C;IAE/C,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC;IAC1C,MAAM,MAAM,GAAG,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpF,MAAM,KAAK,GAAG;QACZ,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,SAAS,EAAE,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC;QACnD,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC;IACF,MAAM,UAAU,GAAG,YAAY,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,0DAA0D;IAC1D,MAAM,MAAM,GAAG,CAAC,MAAiB,EAAa,EAAE,CAC9C,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACvF,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,MAAM;QAChC,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;QACzD,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;QAC9B,MAAM;QACN,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QACzE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QAC1D,SAAS,EAAE,UAAU,IAAI,QAAQ,CAAC,QAAQ;QAC1C,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI;QAC/B,YAAY;QACZ,OAAO;QACP,WAAW,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,kBAAkB,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;KACzG,CAAC;AACJ,CAAC;AAYD,6BAA6B;AAC7B,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,UAAuB,EAAE;IAC/D,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,EAAE;QACxD,GAAG,EAAE,SAAS;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,eAAe;KAC9C,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,sBAAsB;AACtB,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,UAAuB,EAAE;IAC9D,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,EAAE;QACxD,GAAG,EAAE,SAAS;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,eAAe;KAC9C,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3B,CAAC;AASD,2CAA2C;AAC3C,MAAM,UAAU,cAAc,CAAC,MAAiB,EAAE,UAAuB,EAAE;IACzE,QAAQ,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC5D,KAAK,WAAW;YACd,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,uBAAuB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAClF,KAAK,SAAS;YACZ,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACxG,KAAK,QAAQ;YACX,OAAO;gBACL,KAAK,EAAE,QAAQ;gBACf,MAAM,EAAE,MAAM,CAAC,UAAU;oBACvB,CAAC,CAAC,WAAW,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,gDAAgD;oBAC3F,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,sBAAsB,CAAC;gBAC5C,IAAI,EAAE,KAAK;aACZ,CAAC;QACJ,KAAK,OAAO;YACV,OAAO;gBACL,KAAK,EAAE,OAAO;gBACd,MAAM,EAAE,MAAM,CAAC,aAAa;oBAC1B,CAAC,CAAC,6BAA6B,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,mBAAmB,UAAU,CAAC,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG;oBAC9H,CAAC,CAAC,gEAAgE,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG;gBACvG,IAAI,EAAE,SAAS;aAChB,CAAC;QACJ,KAAK,SAAS;YACZ,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC5D,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,cAAc,CAC5B,IAA2D,EAC3D,UAAuB,EAAE;IAEzB,IAAI,CAAC,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3D,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3D,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB,IAAI,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;AACpG,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,WAAW,CAAC,GAAe,EAAE,MAAc,EAAE,UAAuB,EAAE;IACpF,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;IAC/D,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/F,CAAC"}
|
package/dist/jobs/index.d.ts
CHANGED
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
*/
|
|
19
19
|
export { checkCronRequest, type CronAuthOptions, type CronAuthResult } from "./cron-auth.js";
|
|
20
20
|
export { countLines, countsSummary, declaredCounts, describeSpan, formatCount, formatDuration, formatMoney, type CountDeclaration, type CountDeclarations, type CountFormatOptions, type CountKind, type CountLabel, type CountLine, type CountValues, } from "./counts.js";
|
|
21
|
-
export { buildJobView, deriveHealth, describeHealth, describeRun, describeSwitch, formatDay, formatWhen, runNowFor, type HealthInput, type HealthWords, type JobAudience, type JobFacts, type JobHealth, type JobHealthState, type JobRunView, type JobView, type RunFacts, type WhenOptions, } from "./health.js";
|
|
22
|
-
export { DEFAULT_COOLDOWN_MS, DEFAULT_TIMEOUT_MS, MAX_JOB_ID, MAX_WINDOW_KEY, defineJob, defineJobs, jobDefinitionProblems, type AnyJob, type JobActor, type JobContext, type JobDefinition, type RunNowRule, type RunNowScope, } from "./registry.js";
|
|
21
|
+
export { buildJobView, deriveHealth, describeHealth, describeRun, describeSwitch, formatDay, formatWhen, runNowFor, runNowScopesFor, type HealthInput, type HealthWords, type JobAudience, type JobFacts, type JobHealth, type JobHealthState, type JobRunView, type JobView, type RunFacts, type WhenOptions, } from "./health.js";
|
|
22
|
+
export { DEFAULT_COOLDOWN_MS, DEFAULT_TIMEOUT_MS, MAX_JOB_ID, MAX_WINDOW_KEY, defineJob, defineJobs, jobDefinitionProblems, runNowScopes, type AnyJob, type JobActor, type JobContext, type JobDefinition, type RunNowRule, type RunNowScope, } from "./registry.js";
|
|
23
|
+
export { DEFAULT_JOB_RUN_PRUNE_BATCH, DEFAULT_JOB_RUN_RETENTION_DAYS, JOB_RUN_PRUNE_COUNTS, pruneJobRuns, type JobRunPruneCounts, type PruneJobRunsOptions, } from "./prune.js";
|
|
23
24
|
export { createScheduler, refusalStatus, summariseTick, type RunNowCaller, type RunNowOutcome, type RunNowRefusal, type Scheduler, type SchedulerOptions, type SwitchCaller, type SwitchOutcome, type SwitchRefusal, type TickResult, type TickStatus, } from "./scheduler.js";
|
|
24
|
-
export { createMemoryJobStore, pausedFromStored, type JobRunClaim, type JobRunOutcome, type JobRunQuery, type JobRunRecord, type JobStore, type JobSwitchChange, type JobSwitchState, } from "./store.js";
|
|
25
|
+
export { createMemoryJobStore, pausedFromStored, type JobRunClaim, type JobRunOutcome, type JobRunPrune, type JobRunQuery, type JobRunRecord, type JobStore, type JobSwitchChange, type JobSwitchState, } from "./store.js";
|
|
25
26
|
export { MANUAL_KEY_PREFIX, daily, everyHours, hourly, isManualKey, monthly, weekly, type CalendarWindowOptions, type JobWindow, } from "./windows.js";
|
|
26
27
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/jobs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,WAAW,EACX,cAAc,EACd,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,EACd,SAAS,EACT,UAAU,EACV,SAAS,EACT,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,aAAa,EACb,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,KAAK,EACL,UAAU,EACV,MAAM,EACN,WAAW,EACX,OAAO,EACP,MAAM,EACN,KAAK,qBAAqB,EAC1B,KAAK,SAAS,GACf,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,WAAW,EACX,cAAc,EACd,WAAW,EACX,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,EACd,SAAS,EACT,UAAU,EACV,SAAS,EACT,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,YAAY,EACZ,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,EAC9B,oBAAoB,EACpB,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,eAAe,EACf,aAAa,EACb,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,KAAK,EACL,UAAU,EACV,MAAM,EACN,WAAW,EACX,OAAO,EACP,MAAM,EACN,KAAK,qBAAqB,EAC1B,KAAK,SAAS,GACf,MAAM,cAAc,CAAC"}
|
package/dist/jobs/index.js
CHANGED
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
*/
|
|
19
19
|
export { checkCronRequest } from "./cron-auth.js";
|
|
20
20
|
export { countLines, countsSummary, declaredCounts, describeSpan, formatCount, formatDuration, formatMoney, } from "./counts.js";
|
|
21
|
-
export { buildJobView, deriveHealth, describeHealth, describeRun, describeSwitch, formatDay, formatWhen, runNowFor, } from "./health.js";
|
|
22
|
-
export { DEFAULT_COOLDOWN_MS, DEFAULT_TIMEOUT_MS, MAX_JOB_ID, MAX_WINDOW_KEY, defineJob, defineJobs, jobDefinitionProblems, } from "./registry.js";
|
|
21
|
+
export { buildJobView, deriveHealth, describeHealth, describeRun, describeSwitch, formatDay, formatWhen, runNowFor, runNowScopesFor, } from "./health.js";
|
|
22
|
+
export { DEFAULT_COOLDOWN_MS, DEFAULT_TIMEOUT_MS, MAX_JOB_ID, MAX_WINDOW_KEY, defineJob, defineJobs, jobDefinitionProblems, runNowScopes, } from "./registry.js";
|
|
23
|
+
export { DEFAULT_JOB_RUN_PRUNE_BATCH, DEFAULT_JOB_RUN_RETENTION_DAYS, JOB_RUN_PRUNE_COUNTS, pruneJobRuns, } from "./prune.js";
|
|
23
24
|
export { createScheduler, refusalStatus, summariseTick, } from "./scheduler.js";
|
|
24
25
|
export { createMemoryJobStore, pausedFromStored, } from "./store.js";
|
|
25
26
|
export { MANUAL_KEY_PREFIX, daily, everyHours, hourly, isManualKey, monthly, weekly, } from "./windows.js";
|
package/dist/jobs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,gBAAgB,EAA6C,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,WAAW,EACX,cAAc,EACd,WAAW,GAQZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,EACd,SAAS,EACT,UAAU,EACV,SAAS,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,gBAAgB,EAA6C,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,WAAW,EACX,cAAc,EACd,WAAW,GAQZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,EACd,SAAS,EACT,UAAU,EACV,SAAS,EACT,eAAe,GAWhB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,YAAY,GAOb,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,EAC9B,oBAAoB,EACpB,YAAY,GAGb,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,eAAe,EACf,aAAa,EACb,aAAa,GAWd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,GASjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,KAAK,EACL,UAAU,EACV,MAAM,EACN,WAAW,EACX,OAAO,EACP,MAAM,GAGP,MAAM,cAAc,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type JobView, type WhenOptions } from "./health.js";
|
|
3
|
+
import type { RunNowScope } from "./registry.js";
|
|
3
4
|
/** Every element the list draws. Each value replaces the default for that part. */
|
|
4
5
|
export interface JobHealthClassNames {
|
|
5
6
|
list: string;
|
|
@@ -38,10 +39,21 @@ export interface JobHealthListProps extends WhenOptions {
|
|
|
38
39
|
* `ActionFeedbackProvider`. Without it no switch is drawn.
|
|
39
40
|
*/
|
|
40
41
|
onSwitch?: (jobId: string, on: boolean) => Promise<void>;
|
|
41
|
-
/**
|
|
42
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Run a job now, over `scope` — the button pressed. Resolve with the route's
|
|
44
|
+
* `message` to have it said; throw to refuse. Send the scope to the route and
|
|
45
|
+
* on to `scheduler.runNow` as the caller's `scope`: on a job that offers both,
|
|
46
|
+
* it is what tells the two buttons apart.
|
|
47
|
+
*/
|
|
48
|
+
onRunNow?: (jobId: string, scope: RunNowScope) => Promise<{
|
|
43
49
|
message?: string;
|
|
44
50
|
} | void>;
|
|
51
|
+
/**
|
|
52
|
+
* What each Run now sweeps, in the app's words, for a row that offers this
|
|
53
|
+
* viewer both — "Run for every organisation", "Run for yours". A row with one
|
|
54
|
+
* says only "Run now". Default "every account" and "your account".
|
|
55
|
+
*/
|
|
56
|
+
runNowWords?: Partial<Record<RunNowScope, string>>;
|
|
45
57
|
/** After a switch lands or a run finishes — usually `router.refresh()`. */
|
|
46
58
|
onSettled?: () => void;
|
|
47
59
|
/** Anything of the app's own under a row: AltEd's link to the harvest's screen. */
|
|
@@ -62,5 +74,5 @@ export interface JobHealthListProps extends WhenOptions {
|
|
|
62
74
|
* Draws plain elements on the theme tokens, like the wizard; there is still no
|
|
63
75
|
* `Button` in this package. The app wraps it in its own card and heading.
|
|
64
76
|
*/
|
|
65
|
-
export declare function JobHealthList({ jobs, onSwitch, onRunNow, onSettled, extra, emptyText, className, classNames, locale, timeZone, }: JobHealthListProps): React.JSX.Element;
|
|
77
|
+
export declare function JobHealthList({ jobs, onSwitch, onRunNow, onSettled, runNowWords, extra, emptyText, className, classNames, locale, timeZone, }: JobHealthListProps): React.JSX.Element;
|
|
66
78
|
//# sourceMappingURL=job-health-list.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-health-list.d.ts","sourceRoot":"","sources":["../../src/jobs/job-health-list.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,EAML,KAAK,OAAO,EACZ,KAAK,WAAW,EACjB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"job-health-list.d.ts","sourceRoot":"","sources":["../../src/jobs/job-health-list.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,EAML,KAAK,OAAO,EACZ,KAAK,WAAW,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,mFAAmF;AACnF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,kDAAkD;AAClD,eAAO,MAAM,sBAAsB,EAAE,mBA2BpC,CAAC;AAWF,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,sDAAsD;IACtD,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACvF;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,mFAAmF;IACnF,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1C,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC3C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,WAAW,EACX,KAAK,EACL,SAAgC,EAChC,SAAS,EACT,UAAU,EACV,MAAM,EACN,QAAQ,GACT,EAAE,kBAAkB,qBAsBpB"}
|
|
@@ -54,13 +54,14 @@ const ICONS = {
|
|
|
54
54
|
* Draws plain elements on the theme tokens, like the wizard; there is still no
|
|
55
55
|
* `Button` in this package. The app wraps it in its own card and heading.
|
|
56
56
|
*/
|
|
57
|
-
export function JobHealthList({ jobs, onSwitch, onRunNow, onSettled, extra, emptyText = "No scheduled jobs.", className, classNames, locale, timeZone, }) {
|
|
57
|
+
export function JobHealthList({ jobs, onSwitch, onRunNow, onSettled, runNowWords, extra, emptyText = "No scheduled jobs.", className, classNames, locale, timeZone, }) {
|
|
58
58
|
const c = { ...JOB_HEALTH_CLASS_NAMES, ...classNames };
|
|
59
59
|
const actions = useKeyedAction();
|
|
60
60
|
if (jobs.length === 0)
|
|
61
61
|
return _jsx("p", { className: c.empty, children: emptyText });
|
|
62
|
-
return (_jsx("ul", { className: cx(c.list, className), children: jobs.map((job) => (_jsx(JobRow, { job: job, c: c, actions: actions, onSwitch: onSwitch, onRunNow: onRunNow, onSettled: onSettled, extra: extra, when: { locale, timeZone } }, job.id))) }));
|
|
62
|
+
return (_jsx("ul", { className: cx(c.list, className), children: jobs.map((job) => (_jsx(JobRow, { job: job, c: c, actions: actions, onSwitch: onSwitch, onRunNow: onRunNow, onSettled: onSettled, scopeWords: { ...RUN_NOW_WORDS, ...runNowWords }, extra: extra, when: { locale, timeZone } }, job.id))) }));
|
|
63
63
|
}
|
|
64
|
+
const RUN_NOW_WORDS = { tenant: "your account", platform: "every account" };
|
|
64
65
|
function toneClass(c, words) {
|
|
65
66
|
switch (words.tone) {
|
|
66
67
|
case "good":
|
|
@@ -73,7 +74,7 @@ function toneClass(c, words) {
|
|
|
73
74
|
return c.badgeNeutral;
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
|
-
function JobRow({ job, c, actions, onSwitch, onRunNow, onSettled, extra, when, }) {
|
|
77
|
+
function JobRow({ job, c, actions, onSwitch, onRunNow, onSettled, scopeWords, extra, when, }) {
|
|
77
78
|
const on = useOptimisticValue(!job.paused, { onSettled });
|
|
78
79
|
// Health with the switch as the screen shows it, not as the server last said.
|
|
79
80
|
const health = on.value ? job.healthIfOn : { state: "paused" };
|
|
@@ -96,10 +97,11 @@ function JobRow({ job, c, actions, onSwitch, onRunNow, onSettled, extra, when, }
|
|
|
96
97
|
await onSwitch(job.id, next);
|
|
97
98
|
}, { error: next ? `Couldn't turn ${job.label} back on` : `Couldn't pause ${job.label}` });
|
|
98
99
|
};
|
|
99
|
-
const runNow = () => {
|
|
100
|
+
const runNow = (scope) => {
|
|
100
101
|
if (!onRunNow)
|
|
101
102
|
return;
|
|
102
|
-
|
|
103
|
+
// Keyed on the job, not the scope: while one of its runs is under way, neither button starts another.
|
|
104
|
+
void actions.run(job.id, () => onRunNow(job.id, scope), {
|
|
103
105
|
success: (result) => (result && result.message) || `Ran ${job.label}.`,
|
|
104
106
|
error: `Couldn't run ${job.label}`,
|
|
105
107
|
// A failed run is on the ledger too, so the screen has something new to show either way.
|
|
@@ -109,7 +111,9 @@ function JobRow({ job, c, actions, onSwitch, onRunNow, onSettled, extra, when, }
|
|
|
109
111
|
};
|
|
110
112
|
const running = actions.isPending(job.id);
|
|
111
113
|
const showSwitch = job.canSwitch && Boolean(onSwitch);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
// `runNow` null is the last word: a view an app narrowed by hand offers nothing.
|
|
115
|
+
const scopes = !onRunNow || job.runNow === null ? [] : job.runNowScopes.length ? job.runNowScopes : [job.runNow];
|
|
116
|
+
const showRunNow = scopes.length > 0;
|
|
117
|
+
return (_jsxs("li", { className: c.row, "data-job": job.id, "data-health": health.state, children: [_jsxs("div", { className: c.body, children: [_jsxs("div", { className: c.heading, children: [_jsx("span", { className: c.label, children: job.label }), _jsxs("span", { className: cx(c.badge, toneClass(c, words)), children: [_jsx(Icon, { "aria-hidden": "true" }), words.label] })] }), _jsxs("p", { className: c.meta, children: [job.cadence, run ? ` · ${describeRun(run, "Last run", when)}` : ""] }), detail ? _jsx("p", { className: health.state === "failed" ? c.error : c.detail, children: detail }) : null, countsLine ? _jsx("p", { className: c.counts, children: countsLine }) : null, switchLine ? _jsx("p", { className: c.switched, children: switchLine }) : null, extra?.(job)] }), showSwitch || showRunNow ? (_jsxs("div", { className: c.actions, children: [scopes.map((scope) => (_jsxs("button", { type: "button", className: c.runNow, onClick: () => runNow(scope), disabled: running || !on.value, title: on.value ? undefined : "Switched off — turn it back on to run it", "data-busy": running ? "true" : undefined, "data-scope": scope, "aria-label": scopes.length > 1 ? `Run ${job.label} now for ${scopeWords[scope]}` : `Run ${job.label} now`, children: [_jsx(Play, { "aria-hidden": "true" }), scopes.length > 1 ? `Run for ${scopeWords[scope]}` : "Run now"] }, scope))), showSwitch ? (_jsx("button", { type: "button", role: "switch", "aria-checked": on.value, "aria-label": job.label, "aria-busy": on.pending || undefined, className: cx(c.switch, on.value ? c.switchOn : c.switchOff), onClick: toggle, children: _jsx("span", { className: cx(c.thumb, on.value ? c.thumbOn : c.thumbOff) }) })) : null] })) : null] }));
|
|
114
118
|
}
|
|
115
119
|
//# sourceMappingURL=job-health-list.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-health-list.js","sourceRoot":"","sources":["../../src/jobs/job-health-list.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EACL,WAAW,EACX,WAAW,EACX,OAAO,EACP,KAAK,EACL,YAAY,EACZ,IAAI,EACJ,aAAa,GAEd,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AACvC,OAAO,EAAE,cAAc,EAAoB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,cAAc,EACd,WAAW,EACX,cAAc,GAKf,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"job-health-list.js","sourceRoot":"","sources":["../../src/jobs/job-health-list.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EACL,WAAW,EACX,WAAW,EACX,OAAO,EACP,KAAK,EACL,YAAY,EACZ,IAAI,EACJ,aAAa,GAEd,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AACvC,OAAO,EAAE,cAAc,EAAoB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,cAAc,EACd,WAAW,EACX,cAAc,GAKf,MAAM,aAAa,CAAC;AA+BrB,kDAAkD;AAClD,MAAM,CAAC,MAAM,sBAAsB,GAAwB;IACzD,IAAI,EAAE,sCAAsC;IAC5C,KAAK,EAAE,+BAA+B;IACtC,GAAG,EAAE,4EAA4E;IACjF,IAAI,EAAE,oCAAoC;IAC1C,OAAO,EAAE,mCAAmC;IAC5C,KAAK,EAAE,qCAAqC;IAC5C,KAAK,EAAE,mGAAmG;IAC1G,SAAS,EAAE,8CAA8C;IACzD,YAAY,EAAE,qCAAqC;IACnD,YAAY,EAAE,wCAAwC;IACtD,QAAQ,EAAE,0DAA0D;IACpE,IAAI,EAAE,+BAA+B;IACrC,MAAM,EAAE,+BAA+B;IACvC,KAAK,EAAE,0BAA0B;IACjC,MAAM,EAAE,4CAA4C;IACpD,QAAQ,EAAE,+BAA+B;IACzC,OAAO,EAAE,kCAAkC;IAC3C,MAAM,EACJ,6RAA6R;IAC/R,MAAM,EACJ,sMAAsM;IACxM,QAAQ,EAAE,YAAY;IACtB,SAAS,EAAE,wBAAwB;IACnC,KAAK,EAAE,mFAAmF;IAC1F,OAAO,EAAE,eAAe;IACxB,QAAQ,EAAE,eAAe;CAC1B,CAAC;AAEF,MAAM,KAAK,GAA2C;IACpD,MAAM,EAAE,WAAW;IACnB,WAAW,EAAE,KAAK;IAClB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,OAAO;IACf,KAAK,EAAE,aAAa;IACpB,OAAO,EAAE,WAAW;CACrB,CAAC;AAiCF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,WAAW,EACX,KAAK,EACL,SAAS,GAAG,oBAAoB,EAChC,SAAS,EACT,UAAU,EACV,MAAM,EACN,QAAQ,GACW;IACnB,MAAM,CAAC,GAAwB,EAAE,GAAG,sBAAsB,EAAE,GAAG,UAAU,EAAE,CAAC;IAC5E,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;IACjC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,YAAG,SAAS,EAAE,CAAC,CAAC,KAAK,YAAG,SAAS,GAAK,CAAC;IACrE,OAAO,CACL,aAAI,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,YACjC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,KAAC,MAAM,IAEL,GAAG,EAAE,GAAG,EACR,CAAC,EAAE,CAAC,EACJ,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,WAAW,EAAE,EAChD,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IATrB,GAAG,CAAC,EAAE,CAUX,CACH,CAAC,GACC,CACN,CAAC;AACJ,CAAC;AAED,MAAM,aAAa,GAAgC,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;AAEzG,SAAS,SAAS,CAAC,CAAsB,EAAE,KAAkB;IAC3D,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM;YACT,OAAO,CAAC,CAAC,SAAS,CAAC;QACrB,KAAK,SAAS;YACZ,OAAO,CAAC,CAAC,YAAY,CAAC;QACxB,KAAK,KAAK;YACR,OAAO,CAAC,CAAC,QAAQ,CAAC;QACpB;YACE,OAAO,CAAC,CAAC,YAAY,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,SAAS,MAAM,CAAC,EACd,GAAG,EACH,CAAC,EACD,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,UAAU,EACV,KAAK,EACL,IAAI,GAWL;IACC,MAAM,EAAE,GAAG,kBAAkB,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAE1D,8EAA8E;IAC9E,MAAM,MAAM,GAAc,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IAC1E,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEjC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC;IACxB,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,CAAC;IAChC,MAAM,UAAU,GACd,GAAG,EAAE,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM;QAC1B,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC;QAC3B,CAAC,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE;YACnB,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YACxG,CAAC,CAAC,IAAI,CAAC;IAEb,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IAChE,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAEzG,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC;QACvB,KAAK,EAAE,CAAC,GAAG,CACT,IAAI,EACJ,KAAK,IAAI,EAAE;YACT,MAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC,EACD,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,iBAAiB,GAAG,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,kBAAkB,GAAG,CAAC,KAAK,EAAE,EAAE,CACvF,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,CAAC,KAAkB,EAAE,EAAE;QACpC,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,sGAAsG;QACtG,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE;YACtD,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,KAAK,GAAG;YACtE,KAAK,EAAE,gBAAgB,GAAG,CAAC,KAAK,EAAE;YAClC,yFAAyF;YACzF,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,EAAE;YAC9B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,EAAE;SAC7B,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtD,iFAAiF;IACjF,MAAM,MAAM,GACV,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpG,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAErC,OAAO,CACL,cAAI,SAAS,EAAE,CAAC,CAAC,GAAG,cAAY,GAAG,CAAC,EAAE,iBAAe,MAAM,CAAC,KAAK,aAC/D,eAAK,SAAS,EAAE,CAAC,CAAC,IAAI,aACpB,eAAK,SAAS,EAAE,CAAC,CAAC,OAAO,aACvB,eAAM,SAAS,EAAE,CAAC,CAAC,KAAK,YAAG,GAAG,CAAC,KAAK,GAAQ,EAC5C,gBAAM,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,aAC/C,KAAC,IAAI,mBAAa,MAAM,GAAG,EAC1B,KAAK,CAAC,KAAK,IACP,IACH,EACN,aAAG,SAAS,EAAE,CAAC,CAAC,IAAI,aACjB,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IACpD,EACH,MAAM,CAAC,CAAC,CAAC,YAAG,SAAS,EAAE,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,YAAG,MAAM,GAAK,CAAC,CAAC,CAAC,IAAI,EAC1F,UAAU,CAAC,CAAC,CAAC,YAAG,SAAS,EAAE,CAAC,CAAC,MAAM,YAAG,UAAU,GAAK,CAAC,CAAC,CAAC,IAAI,EAC5D,UAAU,CAAC,CAAC,CAAC,YAAG,SAAS,EAAE,CAAC,CAAC,QAAQ,YAAG,UAAU,GAAK,CAAC,CAAC,CAAC,IAAI,EAC9D,KAAK,EAAE,CAAC,GAAG,CAAC,IACT,EACL,UAAU,IAAI,UAAU,CAAC,CAAC,CAAC,CAC1B,eAAK,SAAS,EAAE,CAAC,CAAC,OAAO,aACtB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACrB,kBAEE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,CAAC,CAAC,MAAM,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAC5B,QAAQ,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC,KAAK,EAC9B,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,0CAA0C,eAC7D,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,gBAC3B,KAAK,gBACL,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,KAAK,YAAY,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,KAAK,MAAM,aAExG,KAAC,IAAI,mBAAa,MAAM,GAAG,EAC1B,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAX1D,KAAK,CAYH,CACV,CAAC,EACD,UAAU,CAAC,CAAC,CAAC,CACZ,iBACE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,QAAQ,kBACC,EAAE,CAAC,KAAK,gBACV,GAAG,CAAC,KAAK,eACV,EAAE,CAAC,OAAO,IAAI,SAAS,EAClC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,EAC5D,OAAO,EAAE,MAAM,YAEf,eAAM,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAI,GAC5D,CACV,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC,CAAC,CAAC,IAAI,IACL,CACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { CountValues } from "./counts.js";
|
|
2
|
+
import type { JobStore } from "./store.js";
|
|
3
|
+
/** How long a run is kept, unless it is one health reads. */
|
|
4
|
+
export declare const DEFAULT_JOB_RUN_RETENTION_DAYS = 90;
|
|
5
|
+
/** At most this many rows a call, so one housekeeping run never holds the table for long. */
|
|
6
|
+
export declare const DEFAULT_JOB_RUN_PRUNE_BATCH = 1000;
|
|
7
|
+
/**
|
|
8
|
+
* What `pruneJobRuns` reports, declared so it reads "12 old job runs removed".
|
|
9
|
+
* Spread it into the housekeeping job's `counts`, and the result into what its
|
|
10
|
+
* `run` returns.
|
|
11
|
+
*/
|
|
12
|
+
export declare const JOB_RUN_PRUNE_COUNTS: {
|
|
13
|
+
readonly jobRunsPruned: {
|
|
14
|
+
readonly label: {
|
|
15
|
+
readonly one: "old job run removed";
|
|
16
|
+
readonly other: "old job runs removed";
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export type JobRunPruneCounts = CountValues<typeof JOB_RUN_PRUNE_COUNTS>;
|
|
21
|
+
export interface PruneJobRunsOptions {
|
|
22
|
+
/** The clock. The housekeeping job passes its `now`. */
|
|
23
|
+
now?: Date;
|
|
24
|
+
/**
|
|
25
|
+
* Keep every run for this many days. Default 90. At least 1 — a day, not a
|
|
26
|
+
* millisecond count, so `90` cannot be mistaken for 90 ms and empty the ledger.
|
|
27
|
+
*/
|
|
28
|
+
retentionDays?: number;
|
|
29
|
+
/** Delete at most this many rows in the call. Default 1000. Whatever is left goes next time. */
|
|
30
|
+
batchLimit?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Delete runs older than the retention period — never the latest run or the
|
|
34
|
+
* latest successful run of a job (per tenant, for tenants' own runs, and once
|
|
35
|
+
* for the runs over every tenant), and never one that has not finished — at
|
|
36
|
+
* most `batchLimit` of them, oldest first. Running it again straight away
|
|
37
|
+
* deletes only what the first call's limit left.
|
|
38
|
+
*
|
|
39
|
+
* ```ts
|
|
40
|
+
* counts: { windowsPruned: { label: "…" }, ...JOB_RUN_PRUNE_COUNTS },
|
|
41
|
+
* run: async ({ now }) => ({ windowsPruned: await pruneRateLimits(), ...(await pruneJobRuns(jobStore, { now })) }),
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function pruneJobRuns(store: JobStore, options?: PruneJobRunsOptions): Promise<JobRunPruneCounts>;
|
|
45
|
+
//# sourceMappingURL=prune.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../../src/jobs/prune.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,WAAW,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAkB3C,6DAA6D;AAC7D,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,6FAA6F;AAC7F,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAEhD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;CAEK,CAAC;AAEvC,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEzE,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,GAAG,CAAC,EAAE,IAAI,CAAC;IACX;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gGAAgG;IAChG,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAkBjH"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pruning the ledger — from the app's own housekeeping job, a bounded batch a
|
|
3
|
+
* day.
|
|
4
|
+
*
|
|
5
|
+
* The ledger grows without end (AltEd writes about 150 rows a day), and a Run
|
|
6
|
+
* now row keeps the name of whoever pressed it. Old rows are history, not
|
|
7
|
+
* state — with two exceptions, which are the whole of the care here. Health is
|
|
8
|
+
* read from the latest run and the latest successful run of each job (and, for
|
|
9
|
+
* a tenant's own Run now, of each job for that tenant). Delete those and a
|
|
10
|
+
* monthly job that last ran 120 days ago reads **Never run**; delete an
|
|
11
|
+
* unfinished one and a run under way loses its row. So those are never
|
|
12
|
+
* deleted, however old, and everything else past the retention period is.
|
|
13
|
+
*/
|
|
14
|
+
const DAY = 24 * 60 * 60 * 1000;
|
|
15
|
+
/** How long a run is kept, unless it is one health reads. */
|
|
16
|
+
export const DEFAULT_JOB_RUN_RETENTION_DAYS = 90;
|
|
17
|
+
/** At most this many rows a call, so one housekeeping run never holds the table for long. */
|
|
18
|
+
export const DEFAULT_JOB_RUN_PRUNE_BATCH = 1000;
|
|
19
|
+
/**
|
|
20
|
+
* What `pruneJobRuns` reports, declared so it reads "12 old job runs removed".
|
|
21
|
+
* Spread it into the housekeeping job's `counts`, and the result into what its
|
|
22
|
+
* `run` returns.
|
|
23
|
+
*/
|
|
24
|
+
export const JOB_RUN_PRUNE_COUNTS = {
|
|
25
|
+
jobRunsPruned: { label: { one: "old job run removed", other: "old job runs removed" } },
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Delete runs older than the retention period — never the latest run or the
|
|
29
|
+
* latest successful run of a job (per tenant, for tenants' own runs, and once
|
|
30
|
+
* for the runs over every tenant), and never one that has not finished — at
|
|
31
|
+
* most `batchLimit` of them, oldest first. Running it again straight away
|
|
32
|
+
* deletes only what the first call's limit left.
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* counts: { windowsPruned: { label: "…" }, ...JOB_RUN_PRUNE_COUNTS },
|
|
36
|
+
* run: async ({ now }) => ({ windowsPruned: await pruneRateLimits(), ...(await pruneJobRuns(jobStore, { now })) }),
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export async function pruneJobRuns(store, options = {}) {
|
|
40
|
+
const retentionDays = options.retentionDays ?? DEFAULT_JOB_RUN_RETENTION_DAYS;
|
|
41
|
+
const limit = options.batchLimit ?? DEFAULT_JOB_RUN_PRUNE_BATCH;
|
|
42
|
+
if (!(Number.isFinite(retentionDays) && retentionDays >= 1)) {
|
|
43
|
+
throw new RangeError(`The job run retention is a number of days, at least 1 (got ${retentionDays}).`);
|
|
44
|
+
}
|
|
45
|
+
if (!(Number.isInteger(limit) && limit >= 1)) {
|
|
46
|
+
throw new RangeError(`The job run prune batch is a whole number of rows, at least 1 (got ${limit}).`);
|
|
47
|
+
}
|
|
48
|
+
if (typeof store.pruneRuns !== "function") {
|
|
49
|
+
throw new Error("This JobStore can't prune old runs: add pruneRuns to the adapter (the README has it).");
|
|
50
|
+
}
|
|
51
|
+
const now = options.now ?? new Date();
|
|
52
|
+
const deleted = await store.pruneRuns({ startedBefore: new Date(now.getTime() - retentionDays * DAY), limit });
|
|
53
|
+
if (!(Number.isInteger(deleted) && deleted >= 0)) {
|
|
54
|
+
throw new Error(`The JobStore's pruneRuns didn't say how many runs it deleted (got ${String(deleted)}).`);
|
|
55
|
+
}
|
|
56
|
+
return { jobRunsPruned: deleted };
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=prune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../src/jobs/prune.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AAEH,MAAM,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhC,6DAA6D;AAC7D,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,CAAC;AAEjD,6FAA6F;AAC7F,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,CAAC;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,aAAa,EAAE,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,qBAAqB,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE;CACnD,CAAC;AAgBvC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAe,EAAE,UAA+B,EAAE;IACnF,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,8BAA8B,CAAC;IAC9E,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,IAAI,2BAA2B,CAAC;IAChE,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,IAAI,CAAC,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,UAAU,CAAC,8DAA8D,aAAa,IAAI,CAAC,CAAC;IACxG,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,UAAU,CAAC,sEAAsE,KAAK,IAAI,CAAC,CAAC;IACxG,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,uFAAuF,CAAC,CAAC;IAC3G,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,aAAa,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/G,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,qEAAqE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5G,CAAC;IACD,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC"}
|
package/dist/jobs/registry.d.ts
CHANGED
|
@@ -17,14 +17,29 @@ export interface JobActor {
|
|
|
17
17
|
*/
|
|
18
18
|
export type RunNowScope = "tenant" | "platform";
|
|
19
19
|
export interface RunNowRule {
|
|
20
|
-
scope: RunNowScope;
|
|
21
20
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
21
|
+
* Over whom Run now may sweep: one scope, or both.
|
|
22
|
+
*
|
|
23
|
+
* `["tenant", "platform"]` — Quickie's per-organisation jobs: an owner re-runs
|
|
24
|
+
* their own organisation, and an operator re-runs the sweep over every
|
|
25
|
+
* organisation when the overnight one failed. The two are fenced from each
|
|
26
|
+
* other: each has its own cool-down (a tenant's per tenant), neither starts
|
|
27
|
+
* while the other is in flight, and only the platform run counts for the
|
|
28
|
+
* job's health. Offering both needs `JobStore.latestUnfinishedRun`.
|
|
29
|
+
*/
|
|
30
|
+
scope: RunNowScope | readonly RunNowScope[];
|
|
31
|
+
/**
|
|
32
|
+
* How soon the same scope may run it again — per tenant for a tenant run.
|
|
33
|
+
* Default ten minutes. A manual run skips the job's hour gates, so without
|
|
34
|
+
* this a second press sends the whole batch again. `0` turns it off.
|
|
25
35
|
*/
|
|
26
36
|
cooldownMs?: number;
|
|
27
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* The scopes a rule offers, narrowest first, each once: `["tenant"]`,
|
|
40
|
+
* `["platform"]` or `["tenant", "platform"]`. Nothing when Run now is off.
|
|
41
|
+
*/
|
|
42
|
+
export declare function runNowScopes(rule: false | RunNowRule | undefined): RunNowScope[];
|
|
28
43
|
/** What a run is handed. */
|
|
29
44
|
export interface JobContext {
|
|
30
45
|
now: Date;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/jobs/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,gGAAgG;AAChG,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/jobs/registry.ts"],"names":[],"mappings":"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"}
|
package/dist/jobs/registry.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
const SCOPE_ORDER = ["tenant", "platform"];
|
|
2
|
+
/**
|
|
3
|
+
* The scopes a rule offers, narrowest first, each once: `["tenant"]`,
|
|
4
|
+
* `["platform"]` or `["tenant", "platform"]`. Nothing when Run now is off.
|
|
5
|
+
*/
|
|
6
|
+
export function runNowScopes(rule) {
|
|
7
|
+
if (!rule)
|
|
8
|
+
return [];
|
|
9
|
+
const declared = Array.isArray(rule.scope) ? rule.scope : [rule.scope];
|
|
10
|
+
return SCOPE_ORDER.filter((scope) => declared.includes(scope));
|
|
11
|
+
}
|
|
1
12
|
/**
|
|
2
13
|
* A job's definition, checked against its own counts at compile time: `run`
|
|
3
14
|
* must report every count `counts` declares, and nothing it does not — a
|
|
@@ -43,9 +54,13 @@ export function jobDefinitionProblems(jobs) {
|
|
|
43
54
|
if (job.timeoutMs !== undefined && !positive(job.timeoutMs))
|
|
44
55
|
problems.push(`"${name}" has a timeout that is not positive.`);
|
|
45
56
|
if (job.runNow) {
|
|
46
|
-
|
|
57
|
+
const declared = Array.isArray(job.runNow.scope) ? job.runNow.scope : [job.runNow.scope];
|
|
58
|
+
if (declared.length === 0 || declared.some((scope) => scope !== "tenant" && scope !== "platform")) {
|
|
47
59
|
problems.push(`"${name}" offers Run now without saying over whom — "tenant" or "platform".`);
|
|
48
60
|
}
|
|
61
|
+
else if (new Set(declared).size !== declared.length) {
|
|
62
|
+
problems.push(`"${name}" offers Run now over the same scope twice.`);
|
|
63
|
+
}
|
|
49
64
|
const cooldown = job.runNow.cooldownMs;
|
|
50
65
|
if (cooldown !== undefined && !(Number.isFinite(cooldown) && cooldown >= 0)) {
|
|
51
66
|
problems.push(`"${name}" has a Run now cool-down that is not zero or more.`);
|