@runium/core 0.2.0 → 0.3.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/index.js +172 -157
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { readFile as
|
|
2
|
-
import { exec as
|
|
3
|
-
import { setTimeout as
|
|
4
|
-
import { promisify as
|
|
5
|
-
import { EventEmitter as
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import { createWriteStream as
|
|
10
|
-
import { constants as
|
|
11
|
-
import { resolve as
|
|
1
|
+
import { readFile as J, writeFile as B, mkdir as O } from "node:fs/promises";
|
|
2
|
+
import { exec as H, spawn as W } from "node:child_process";
|
|
3
|
+
import { setTimeout as X } from "node:timers/promises";
|
|
4
|
+
import { promisify as z } from "node:util";
|
|
5
|
+
import { EventEmitter as N } from "node:events";
|
|
6
|
+
import Z from "bcx-expression-evaluator";
|
|
7
|
+
import Q from "ajv/dist/2020.js";
|
|
8
|
+
import tt from "ajv-keywords";
|
|
9
|
+
import { createWriteStream as v } from "node:fs";
|
|
10
|
+
import { constants as et } from "node:os";
|
|
11
|
+
import { resolve as $, dirname as D } from "node:path";
|
|
12
12
|
class p extends Error {
|
|
13
13
|
code;
|
|
14
14
|
payload;
|
|
@@ -19,10 +19,10 @@ class p extends Error {
|
|
|
19
19
|
function xt(e) {
|
|
20
20
|
return !!e && e instanceof p;
|
|
21
21
|
}
|
|
22
|
-
var
|
|
22
|
+
var st = ((e) => (e.READ_JSON = "file-read-json", e.WRITE_JSON = "file-write-json", e))(st || {});
|
|
23
23
|
async function Mt(e) {
|
|
24
24
|
try {
|
|
25
|
-
const t = await
|
|
25
|
+
const t = await J(e, { encoding: "utf-8" });
|
|
26
26
|
return JSON.parse(t);
|
|
27
27
|
} catch (t) {
|
|
28
28
|
throw new p(`Can not read JSON file ${e}`, "file-read-json", { path: e, original: t });
|
|
@@ -30,42 +30,42 @@ async function Mt(e) {
|
|
|
30
30
|
}
|
|
31
31
|
async function Kt(e, t) {
|
|
32
32
|
try {
|
|
33
|
-
await
|
|
33
|
+
await B(e, JSON.stringify(t, null, 2), { encoding: "utf-8" });
|
|
34
34
|
} catch (s) {
|
|
35
35
|
throw new p(`Can not write JSON file ${e}`, "file-write-json", { path: e, data: t, original: s });
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
const
|
|
39
|
-
var
|
|
38
|
+
const rt = String.raw`"\$unwrap\((.*)\)"`;
|
|
39
|
+
var it = ((e) => (e.MACRO_APPLY_ERROR = "macro-apply-error", e))(it || {});
|
|
40
40
|
function qt(e, t) {
|
|
41
41
|
const s = Object.keys(t), i = String.raw`\$(${s.join("|")})\(([^()]*(?:\([^()]*\)[^()]*)*)\)`, r = (o) => {
|
|
42
42
|
const a = new RegExp(i, "g");
|
|
43
43
|
let c = o, n = !0;
|
|
44
|
-
for (; n; ) n = !1, c = c.replace(a, (u,
|
|
44
|
+
for (; n; ) n = !1, c = c.replace(a, (u, l, Y) => {
|
|
45
45
|
n = !0;
|
|
46
|
-
const
|
|
47
|
-
let
|
|
48
|
-
for (const h of
|
|
49
|
-
|
|
50
|
-
const
|
|
46
|
+
const R = [];
|
|
47
|
+
let w = 0, k = "";
|
|
48
|
+
for (const h of Y) h === "," && w === 0 ? (R.push(k.trim()), k = "") : (h === "(" && w++, h === ")" && w--, k += h);
|
|
49
|
+
R.push(k.trim());
|
|
50
|
+
const V = R.map((h) => h ? r(h) : "");
|
|
51
51
|
try {
|
|
52
|
-
return t[
|
|
52
|
+
return t[l](...V);
|
|
53
53
|
} catch (h) {
|
|
54
|
-
throw new p(`Can not apply macro "${
|
|
54
|
+
throw new p(`Can not apply macro "${l}"`, "macro-apply-error", { type: l, args: R, original: h });
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
return c;
|
|
58
58
|
};
|
|
59
59
|
return (function(o) {
|
|
60
|
-
const a = new RegExp(
|
|
60
|
+
const a = new RegExp(rt, "g");
|
|
61
61
|
return o.replace(a, (c, n) => n.trim());
|
|
62
62
|
})(s.length ? r(e) : e);
|
|
63
63
|
}
|
|
64
|
-
const
|
|
65
|
-
async function
|
|
66
|
-
return process.platform === "win32" ?
|
|
64
|
+
const L = z(H);
|
|
65
|
+
async function G(e) {
|
|
66
|
+
return process.platform === "win32" ? x(e) : (async function(t) {
|
|
67
67
|
try {
|
|
68
|
-
const { stdout: s } = await
|
|
68
|
+
const { stdout: s } = await L("ps -eo pid,ppid"), i = s.split(`
|
|
69
69
|
`).slice(1), r = /* @__PURE__ */ new Map();
|
|
70
70
|
for (const o of i) {
|
|
71
71
|
const a = o.trim().split(/\s+/);
|
|
@@ -74,18 +74,18 @@ async function L(e) {
|
|
|
74
74
|
isNaN(c) || isNaN(n) || (r.has(n) || r.set(n, []), r.get(n).push(c));
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
return
|
|
77
|
+
return M(t, r);
|
|
78
78
|
} catch {
|
|
79
79
|
return { pid: t, children: [], depth: 0 };
|
|
80
80
|
}
|
|
81
81
|
})(e);
|
|
82
82
|
}
|
|
83
|
-
async function
|
|
83
|
+
async function x(e) {
|
|
84
84
|
try {
|
|
85
|
-
const { stdout: t } = await
|
|
85
|
+
const { stdout: t } = await L(`wmic process where (ParentProcessId=${e}) get ProcessId`, { windowsHide: !0 }), s = t.split(`
|
|
86
86
|
`).map((r) => r.trim()).filter(Boolean).slice(1).map((r) => parseInt(r, 10)).filter((r) => !isNaN(r)), i = [];
|
|
87
87
|
for (const r of s) {
|
|
88
|
-
const o = await
|
|
88
|
+
const o = await x(r);
|
|
89
89
|
i.push(o);
|
|
90
90
|
}
|
|
91
91
|
return { pid: e, children: i, depth: 0 };
|
|
@@ -93,14 +93,14 @@ async function G(e) {
|
|
|
93
93
|
return { pid: e, children: [], depth: 0 };
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
-
function
|
|
97
|
-
return { pid: e, children: (t.get(e) || []).map((s) =>
|
|
96
|
+
function M(e, t) {
|
|
97
|
+
return { pid: e, children: (t.get(e) || []).map((s) => M(s, t)), depth: 0 };
|
|
98
98
|
}
|
|
99
|
-
function
|
|
99
|
+
function K(e, t = 0) {
|
|
100
100
|
e.depth = t;
|
|
101
|
-
for (const s of e.children)
|
|
101
|
+
for (const s of e.children) K(s, t + 1);
|
|
102
102
|
}
|
|
103
|
-
function
|
|
103
|
+
function m(e) {
|
|
104
104
|
try {
|
|
105
105
|
return process.kill(e, 0), !0;
|
|
106
106
|
} catch (t) {
|
|
@@ -108,8 +108,8 @@ function T(e) {
|
|
|
108
108
|
return s.code !== "ESRCH" && s.code === "EPERM";
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
async function
|
|
112
|
-
if (!
|
|
111
|
+
async function C(e, t = "SIGTERM", s = 1e3) {
|
|
112
|
+
if (!m(e)) return !0;
|
|
113
113
|
try {
|
|
114
114
|
process.kill(e, t);
|
|
115
115
|
} catch (r) {
|
|
@@ -119,47 +119,47 @@ async function O(e, t = "SIGTERM", s = 1e3) {
|
|
|
119
119
|
}
|
|
120
120
|
const i = Date.now();
|
|
121
121
|
for (; Date.now() - i < s; ) {
|
|
122
|
-
if (!
|
|
123
|
-
await
|
|
122
|
+
if (!m(e)) return !0;
|
|
123
|
+
await X(50);
|
|
124
124
|
}
|
|
125
|
-
return !
|
|
125
|
+
return !m(e);
|
|
126
126
|
}
|
|
127
|
-
async function
|
|
128
|
-
const r = await
|
|
129
|
-
|
|
127
|
+
async function ot(e, t = "SIGTERM", s = "SIGKILL", i = 1e3) {
|
|
128
|
+
const r = await G(e);
|
|
129
|
+
K(r);
|
|
130
130
|
const o = (function(a) {
|
|
131
131
|
const c = [], n = (u) => {
|
|
132
132
|
c.push(u);
|
|
133
|
-
for (const
|
|
133
|
+
for (const l of u.children) n(l);
|
|
134
134
|
};
|
|
135
|
-
return n(a), c.sort((u,
|
|
135
|
+
return n(a), c.sort((u, l) => l.depth - u.depth);
|
|
136
136
|
})(r);
|
|
137
137
|
for (const a of o)
|
|
138
|
-
|
|
138
|
+
m(a.pid) && !await C(a.pid, t, i) && m(a.pid) && await C(a.pid, s, i);
|
|
139
139
|
}
|
|
140
140
|
async function Ut(e) {
|
|
141
|
-
const t = await
|
|
141
|
+
const t = await G(e), s = [], i = (r) => {
|
|
142
142
|
s.push(r.pid);
|
|
143
143
|
for (const o of r.children) i(o);
|
|
144
144
|
};
|
|
145
145
|
return i(t), s;
|
|
146
146
|
}
|
|
147
|
-
var
|
|
148
|
-
const
|
|
149
|
-
function
|
|
150
|
-
return nt.has(e.type);
|
|
151
|
-
}
|
|
152
|
-
function C(e) {
|
|
147
|
+
var y = ((e) => (e.IMMEDIATE = "immediate", e.DEFERRED = "deferred", e.IGNORE = "ignore", e))(y || {}), d = ((e) => (e.EMIT_EVENT = "emit-event", e.START_TASK = "start-task", e.RESTART_TASK = "restart-task", e.STOP_TASK = "stop-task", e.STOP_PROJECT = "stop-project", e.ENABLE_TRIGGER = "enable-trigger", e.DISABLE_TRIGGER = "disable-trigger", e))(d || {}), S = ((e) => (e.DEFAULT = "default", e))(S || {}), f = ((e) => (e.EVENT = "event", e.TIMEOUT = "timeout", e.INTERVAL = "interval", e))(f || {}), E = ((e) => (e.ALWAYS = "always", e.ON_FAILURE = "on-failure", e))(E || {}), nt = ((e) => (e.INCORRECT_DATA = "project-config-incorrect-data", e.TASKS_CIRCULAR_DEPENDENCY = "project-config-tasks-circular-dependency", e.TASK_NOT_EXISTS = "project-config-task-not-exists", e.TRIGGER_NOT_EXISTS = "project-config-trigger-not-exists", e))(nt || {});
|
|
148
|
+
const at = /* @__PURE__ */ new Set(["start-task", "restart-task", "stop-task"]), ct = /* @__PURE__ */ new Set(["enable-trigger", "disable-trigger"]), pt = new Set(Object.values(d)), dt = new Set(Object.values(f));
|
|
149
|
+
function P(e) {
|
|
153
150
|
return at.has(e.type);
|
|
154
151
|
}
|
|
155
|
-
function
|
|
156
|
-
return
|
|
152
|
+
function j(e) {
|
|
153
|
+
return ct.has(e.type);
|
|
157
154
|
}
|
|
158
155
|
function ut(e) {
|
|
159
156
|
return !pt.has(e.type);
|
|
160
157
|
}
|
|
161
|
-
const K = new Z({ allowUnionTypes: !0, allErrors: !0, verbose: !0 });
|
|
162
158
|
function ht(e) {
|
|
159
|
+
return !dt.has(e.type);
|
|
160
|
+
}
|
|
161
|
+
const q = new Q({ allowUnionTypes: !0, allErrors: !0, verbose: !0 });
|
|
162
|
+
function gt(e) {
|
|
163
163
|
const t = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Set();
|
|
164
164
|
for (const r of e.tasks) s.add(r.id), t.set(r.id, []);
|
|
165
165
|
const i = new Set(e.triggers?.map((r) => r.id) || []);
|
|
@@ -169,13 +169,13 @@ function ht(e) {
|
|
|
169
169
|
t.get(o.taskId).push(r.id);
|
|
170
170
|
}
|
|
171
171
|
for (const o of r.handlers || []) {
|
|
172
|
-
if (
|
|
173
|
-
if (
|
|
172
|
+
if (P(o.action) && !s.has(o.action.options.taskId)) throw new p(`Task "${r.id}" handler action uses not existing task "${o.action.options.taskId}"`, "project-config-task-not-exists", { taskId: r.id, handler: { ...o }, scope: "handlers" });
|
|
173
|
+
if (j(o.action) && !i.has(o.action.options.triggerId)) throw new p(`Task "${r.id}" handler action uses not existing trigger "${o.action.options.triggerId}"`, "project-config-trigger-not-exists", { taskId: r.id, handler: { ...o }, scope: "handlers" });
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
for (const r of e.triggers || []) {
|
|
177
|
-
if (
|
|
178
|
-
if (
|
|
177
|
+
if (P(r.action) && !s.has(r.action.options.taskId)) throw new p(`Trigger "${r.id}" action uses not existing task "${r.action.options.taskId}"`, "project-config-task-not-exists", { trigger: { ...r }, scope: "triggers" });
|
|
178
|
+
if (j(r.action) && !i.has(r.action.options.triggerId)) throw new p(`Trigger "${r.id}" action uses not existing trigger "${r.action.options.triggerId}"`, "project-config-trigger-not-exists", { trigger: { ...r }, scope: "triggers" });
|
|
179
179
|
}
|
|
180
180
|
(function(r) {
|
|
181
181
|
const o = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), c = (n) => {
|
|
@@ -192,23 +192,23 @@ function ht(e) {
|
|
|
192
192
|
for (const n of r.keys()) o.has(n) || c(n);
|
|
193
193
|
})(t);
|
|
194
194
|
}
|
|
195
|
-
function
|
|
195
|
+
function ft(e, t) {
|
|
196
196
|
(function(s, i) {
|
|
197
|
-
const r =
|
|
197
|
+
const r = q.compile(i || {});
|
|
198
198
|
if (!r(s)) throw new p("Incorrect project config data", "project-config-incorrect-data", { errors: r.errors });
|
|
199
|
-
})(e, t),
|
|
199
|
+
})(e, t), gt(e);
|
|
200
200
|
}
|
|
201
|
-
|
|
202
|
-
var g = ((e) => (e.IDLE = "idle", e.STARTING = "starting", e.STARTED = "started", e.COMPLETED = "completed", e.FAILED = "failed", e.STOPPING = "stopping", e.STOPPED = "stopped", e))(g || {}),
|
|
201
|
+
tt(q, ["uniqueItemProperties"]);
|
|
202
|
+
var g = ((e) => (e.IDLE = "idle", e.STARTING = "starting", e.STARTED = "started", e.COMPLETED = "completed", e.FAILED = "failed", e.STOPPING = "stopping", e.STOPPED = "stopped", e))(g || {}), A = ((e) => (e.STATE_CHANGE = "state-change", e.STDOUT = "stdout", e.STDERR = "stderr", e))(A || {});
|
|
203
203
|
const Ft = -1;
|
|
204
|
-
class
|
|
204
|
+
class U extends N {
|
|
205
205
|
constructor(t) {
|
|
206
206
|
super(), this.options = t;
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
|
-
class lt extends
|
|
209
|
+
class lt extends U {
|
|
210
210
|
constructor(t) {
|
|
211
|
-
super(t), this.options = t, this.setMaxListeners(50), this.options.env = { ...process.env, ...t.env || {} }, this.options.cwd =
|
|
211
|
+
super(t), this.options = t, this.setMaxListeners(50), this.options.env = { ...process.env, ...t.env || {} }, this.options.cwd = $(process.cwd(), t.cwd || "");
|
|
212
212
|
}
|
|
213
213
|
state = { status: "idle", pid: -1, timestamp: Date.now(), iteration: 0 };
|
|
214
214
|
process = null;
|
|
@@ -231,7 +231,7 @@ class lt extends q {
|
|
|
231
231
|
try {
|
|
232
232
|
await this.initLogStreams();
|
|
233
233
|
const { cwd: t, command: s, arguments: i = [], env: r, shell: o = !0 } = this.options;
|
|
234
|
-
this.process =
|
|
234
|
+
this.process = W(s, i, { cwd: t, env: r, shell: o, stdio: ["ignore", "pipe", "pipe"] }), this.addProcessListeners(), this.setTTLTimer(), this.updateState({ status: "started", pid: this.process.pid });
|
|
235
235
|
} catch (t) {
|
|
236
236
|
this.onError(t);
|
|
237
237
|
}
|
|
@@ -245,7 +245,7 @@ class lt extends q {
|
|
|
245
245
|
if (!this.canStop()) return;
|
|
246
246
|
this.updateState({ status: "stopping", reason: t });
|
|
247
247
|
const s = this.options.stopSignal || "SIGTERM";
|
|
248
|
-
await
|
|
248
|
+
await ot(Number(this.process.pid), s, "SIGKILL", 3e4);
|
|
249
249
|
}
|
|
250
250
|
async restart() {
|
|
251
251
|
await this.stop("restart"), this.start();
|
|
@@ -257,12 +257,12 @@ class lt extends q {
|
|
|
257
257
|
async initLogStreams() {
|
|
258
258
|
const { stdout: t = null, stderr: s = null } = this.options.log || {};
|
|
259
259
|
if (t) {
|
|
260
|
-
const i =
|
|
261
|
-
await
|
|
260
|
+
const i = $(t);
|
|
261
|
+
await O(D(i), { recursive: !0 }), this.stdoutStream = v(t, { flags: this.state.iteration === 1 ? "w" : "a" });
|
|
262
262
|
}
|
|
263
263
|
if (s) {
|
|
264
|
-
const i =
|
|
265
|
-
await
|
|
264
|
+
const i = $(s);
|
|
265
|
+
await O(D(i), { recursive: !0 }), this.stderrStream = v(s, { flags: this.state.iteration === 1 ? "w" : "a" });
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
268
|
setTTLTimer() {
|
|
@@ -284,7 +284,7 @@ class lt extends q {
|
|
|
284
284
|
}
|
|
285
285
|
onExit(t) {
|
|
286
286
|
let s = -1;
|
|
287
|
-
t !== null && (s = t === 128 +
|
|
287
|
+
t !== null && (s = t === 128 + et.signals[this.options.stopSignal || "SIGTERM"] ? -1 : t), this.updateState({ status: s === 0 ? "completed" : s === -1 ? "stopped" : "failed", exitCode: s }), this.cleanup();
|
|
288
288
|
}
|
|
289
289
|
onError(t) {
|
|
290
290
|
this.updateState({ status: "failed", error: t }), this.cleanup();
|
|
@@ -293,20 +293,21 @@ class lt extends q {
|
|
|
293
293
|
this.ttlTimer && (clearTimeout(this.ttlTimer), this.ttlTimer = null), this.process && (this.process.removeAllListeners(), this.process.stdout?.removeAllListeners(), this.process.stderr?.removeAllListeners(), this.process = null), this.stdoutStream && (this.stdoutStream.end(), this.stdoutStream = null), this.stderrStream && (this.stderrStream.end(), this.stderrStream = null);
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
|
-
var
|
|
297
|
-
const
|
|
298
|
-
function
|
|
299
|
-
return { type: "object", properties: { ...structuredClone(
|
|
296
|
+
var Tt = ((e) => (e.ACTION_TYPE_ALREADY_USED = "project-schema-action-type-already-used", e.TASK_TYPE_ALREADY_USED = "project-schema-task-type-already-used", e.TRIGGER_TYPE_ALREADY_USED = "project-schema-trigger-type-already-used", e))(Tt || {});
|
|
297
|
+
const b = /^[a-zA-Z0-9_-]+$/, mt = { id: { type: "string", pattern: b.source }, name: { type: "string" }, type: { type: "string" }, mode: { $ref: "#/$defs/Runium_TaskStartMode" }, dependencies: { type: "array", items: { $ref: "#/$defs/Runium_TaskDependency" } }, handlers: { type: "array", items: { $ref: "#/$defs/Runium_TaskHandler" } }, restart: { $ref: "#/$defs/Runium_TaskRestartPolicy" } }, yt = { id: { type: "string", pattern: b.source }, action: { $ref: "#/$defs/Runium_Action" }, disabled: { type: "boolean" } };
|
|
298
|
+
function F(e, t) {
|
|
299
|
+
return { type: "object", properties: { ...structuredClone(mt), type: { const: e }, options: { ...structuredClone(t) } }, required: ["id", "options"], additionalProperties: !1 };
|
|
300
300
|
}
|
|
301
|
-
function
|
|
302
|
-
|
|
301
|
+
function T(e, t) {
|
|
302
|
+
const s = t ? { options: t } : {}, i = t ? ["options"] : [];
|
|
303
|
+
return { type: "object", properties: { type: Array.isArray(e) ? { type: "string", enum: e } : { type: "string", const: e }, ...s }, required: ["type", ...i], additionalProperties: !1 };
|
|
303
304
|
}
|
|
304
|
-
function
|
|
305
|
-
const s = t ? {
|
|
306
|
-
return { type: "object", properties: { ...structuredClone(
|
|
305
|
+
function _(e, t) {
|
|
306
|
+
const s = t ? { options: t } : {}, i = t ? ["options"] : [];
|
|
307
|
+
return { type: "object", properties: { ...structuredClone(yt), type: { type: "string", const: e }, ...s }, required: ["id", "type", "action", ...i], additionalProperties: !1 };
|
|
307
308
|
}
|
|
308
309
|
function St() {
|
|
309
|
-
const e = { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "https://example.com/schemas/project.json", title: "Project", type: "object", properties: { id: { type: "string", pattern:
|
|
310
|
+
const e = { $schema: "https://json-schema.org/draft/2020-12/schema", $id: "https://example.com/schemas/project.json", title: "Project", type: "object", properties: { id: { type: "string", pattern: b.source }, name: { type: "string" }, tasks: { type: "array", items: { oneOf: [{ $ref: "#/$defs/Runium_TaskConfig" }] }, minItems: 1, uniqueItemProperties: ["id"] }, triggers: { type: "array", items: { $ref: "#/$defs/Runium_Trigger" }, uniqueItemProperties: ["id"] } }, required: ["id", "tasks"], additionalProperties: !1, $defs: { Runium_EnvValue: { type: ["string", "number", "boolean"] }, Runium_Env: { type: "object", additionalProperties: { $ref: "#/$defs/Runium_EnvValue" } }, Runium_TaskStartMode: { type: "string", enum: Object.values(y) }, Runium_TaskHandler: { type: "object", properties: { action: { $ref: "#/$defs/Runium_Action" }, condition: { $ref: "#/$defs/Runium_TaskStateCondition" } }, required: ["action", "condition"], additionalProperties: !1 }, Runium_TaskStateCondition: { oneOf: [{ type: "string" }, { type: "boolean" }, { $ref: "#/$defs/Runium_TaskState" }] }, Runium_TaskState: { type: "object", properties: { status: { $ref: "#/$defs/Runium_TaskStatus" }, iteration: { type: "number", minimum: 0 }, exitCode: { type: "number", minimum: 0 }, reason: { type: "string" } }, additionalProperties: !1 }, Runium_TaskStatus: { type: "string", enum: Object.values(g) }, Runium_TaskDependency: { type: "object", properties: { taskId: { type: "string" }, condition: { $ref: "#/$defs/Runium_TaskStateCondition" } }, required: ["taskId", "condition"], additionalProperties: !1 }, Runium_Trigger: { oneOf: [{ $ref: "#/$defs/Runium_TriggerEvent" }, { $ref: "#/$defs/Runium_TriggerInterval" }, { $ref: "#/$defs/Runium_TriggerTimeout" }] }, Runium_TriggerEvent: _(f.EVENT, { type: "object", properties: { event: { type: "string" } }, required: ["event"], additionalProperties: !1 }), Runium_TriggerInterval: _(f.INTERVAL, { type: "object", properties: { interval: { type: "number", minimum: 0 } }, required: ["interval"], additionalProperties: !1 }), Runium_TriggerTimeout: _(f.TIMEOUT, { type: "object", properties: { timeout: { type: "number", minimum: 0 } }, required: ["timeout"], additionalProperties: !1 }), Runium_Action: { oneOf: [{ $ref: "#/$defs/Runium_ActionEmitEvent" }, { $ref: "#/$defs/Runium_ActionProcessTask" }, { $ref: "#/$defs/Runium_ActionStopProject" }, { $ref: "#/$defs/Runium_ActionToggleTrigger" }] }, Runium_ActionEmitEvent: T(d.EMIT_EVENT, { type: "object", properties: { event: { type: "string" } }, required: ["event"], additionalProperties: !1 }), Runium_ActionProcessTask: T([d.START_TASK, d.RESTART_TASK, d.STOP_TASK], { type: "object", properties: { taskId: { type: "string" } }, required: ["taskId"], additionalProperties: !1 }), Runium_ActionStopProject: T(d.STOP_PROJECT), Runium_ActionToggleTrigger: T([d.ENABLE_TRIGGER, d.DISABLE_TRIGGER], { type: "object", properties: { triggerId: { type: "string" } }, required: ["triggerId"], additionalProperties: !1 }), Runium_TaskConfig: { ...F(S.DEFAULT, { $ref: "#/$defs/Runium_TaskOptions" }) }, Runium_TaskOptions: { type: "object", properties: { command: { type: "string" }, arguments: { type: "array", items: { type: "string" } }, shell: { type: "boolean" }, cwd: { type: "string" }, env: { $ref: "#/$defs/Runium_Env" }, ttl: { type: "number" }, log: { $ref: "#/$defs/Runium_TaskLog" }, stopSignal: { type: "string" } }, required: ["command"], additionalProperties: !1 }, Runium_TaskRestartPolicy: { oneOf: [{ $ref: "#/$defs/Runium_TaskRestartPolicyAlways" }, { $ref: "#/$defs/Runium_TaskRestartPolicyOnFailure" }] }, Runium_TaskRestartPolicyAlways: { type: "object", required: ["policy"], properties: { policy: { const: E.ALWAYS }, delay: { type: "number" } }, additionalProperties: !1 }, Runium_TaskRestartPolicyOnFailure: { type: "object", required: ["policy"], properties: { policy: { const: E.ON_FAILURE }, delay: { type: "number" }, maxRetries: { type: "number" } }, additionalProperties: !1 }, Runium_TaskLog: { type: "object", properties: { stdout: { type: ["string", "null"] }, stderr: { type: ["string", "null"] } }, additionalProperties: !1 } } };
|
|
310
311
|
return Object.freeze(e);
|
|
311
312
|
}
|
|
312
313
|
function Et(e, t) {
|
|
@@ -319,11 +320,11 @@ function Et(e, t) {
|
|
|
319
320
|
if (r) {
|
|
320
321
|
const o = new Set(i.properties.tasks.items.oneOf.map((c) => {
|
|
321
322
|
const n = c.$ref.split("/").pop() || "";
|
|
322
|
-
return i.$defs[n]?.properties?.type?.const ||
|
|
323
|
+
return i.$defs[n]?.properties?.type?.const || S.DEFAULT;
|
|
323
324
|
})), a = {};
|
|
324
325
|
for (const [c, n] of Object.entries(r)) {
|
|
325
326
|
if (o.has(n.type)) throw new p(`Task type "${n.type}" already used in project schema`, "project-schema-task-type-already-used", { type: n.type });
|
|
326
|
-
a[c] =
|
|
327
|
+
a[c] = F(n.type, n.options), i.properties.tasks.items.oneOf.push({ $ref: `#/$defs/${c}` }), o.add(n.type);
|
|
327
328
|
}
|
|
328
329
|
i.$defs = { ...a, ...i.$defs };
|
|
329
330
|
}
|
|
@@ -336,7 +337,7 @@ function Et(e, t) {
|
|
|
336
337
|
}).flat()), a = {};
|
|
337
338
|
for (const [c, n] of Object.entries(r)) {
|
|
338
339
|
if (o.has(n.type)) throw new p(`Action type "${n.type}" already used in project schema`, "project-schema-action-type-already-used", { type: n.type });
|
|
339
|
-
a[c] =
|
|
340
|
+
a[c] = T(n.type, n.options), i.$defs.Runium_Action.oneOf.push({ $ref: `#/$defs/${c}` }), o.add(n.type);
|
|
340
341
|
}
|
|
341
342
|
i.$defs = { ...a, ...i.$defs };
|
|
342
343
|
}
|
|
@@ -349,14 +350,14 @@ function Et(e, t) {
|
|
|
349
350
|
})), a = {};
|
|
350
351
|
for (const [c, n] of Object.entries(r)) {
|
|
351
352
|
if (o.has(n.type)) throw new p(`Trigger type "${n.type}" already used in project schema`, "project-schema-trigger-type-already-used", { type: n.type });
|
|
352
|
-
a[c] =
|
|
353
|
+
a[c] = _(n.type, n.options), i.$defs.Runium_Trigger.oneOf.push({ $ref: `#/$defs/${c}` }), o.add(n.type);
|
|
353
354
|
}
|
|
354
355
|
i.$defs = { ...a, ...i.$defs };
|
|
355
356
|
}
|
|
356
357
|
return i;
|
|
357
358
|
})(s, t.triggers)), Object.freeze(s);
|
|
358
359
|
}
|
|
359
|
-
class
|
|
360
|
+
class I {
|
|
360
361
|
project;
|
|
361
362
|
id;
|
|
362
363
|
action;
|
|
@@ -370,11 +371,14 @@ class _ {
|
|
|
370
371
|
isDisabled() {
|
|
371
372
|
return this.disabled;
|
|
372
373
|
}
|
|
374
|
+
processAction() {
|
|
375
|
+
this.project.processAction(this.action);
|
|
376
|
+
}
|
|
373
377
|
}
|
|
374
|
-
class Rt extends
|
|
378
|
+
class Rt extends I {
|
|
375
379
|
event;
|
|
376
380
|
constructor(t, s) {
|
|
377
|
-
super(t, s), this.event = t.event;
|
|
381
|
+
super(t, s), this.event = t.options.event;
|
|
378
382
|
}
|
|
379
383
|
enable() {
|
|
380
384
|
this.project.on(this.event, this.handler), this.disabled = !1;
|
|
@@ -383,33 +387,33 @@ class Rt extends _ {
|
|
|
383
387
|
this.project.off(this.event, this.handler), this.disabled = !0;
|
|
384
388
|
}
|
|
385
389
|
handler = () => {
|
|
386
|
-
this.
|
|
390
|
+
this.processAction();
|
|
387
391
|
};
|
|
388
392
|
}
|
|
389
|
-
class kt extends
|
|
393
|
+
class kt extends I {
|
|
390
394
|
interval;
|
|
391
395
|
intervalId = null;
|
|
392
396
|
constructor(t, s) {
|
|
393
|
-
super(t, s), this.interval = t.interval;
|
|
397
|
+
super(t, s), this.interval = t.options.interval;
|
|
394
398
|
}
|
|
395
399
|
enable() {
|
|
396
400
|
this.intervalId = setInterval(() => {
|
|
397
|
-
this.
|
|
401
|
+
this.processAction();
|
|
398
402
|
}, this.interval), this.disabled = !1;
|
|
399
403
|
}
|
|
400
404
|
disable() {
|
|
401
405
|
this.intervalId && clearInterval(this.intervalId), this.disabled = !0, this.intervalId = null;
|
|
402
406
|
}
|
|
403
407
|
}
|
|
404
|
-
class At extends
|
|
408
|
+
class At extends I {
|
|
405
409
|
timeout;
|
|
406
410
|
timeoutId = null;
|
|
407
411
|
constructor(t, s) {
|
|
408
|
-
super(t, s), this.timeout = t.timeout;
|
|
412
|
+
super(t, s), this.timeout = t.options.timeout;
|
|
409
413
|
}
|
|
410
414
|
enable() {
|
|
411
415
|
this.timeoutId = setTimeout(() => {
|
|
412
|
-
this.
|
|
416
|
+
this.processAction();
|
|
413
417
|
}, this.timeout), this.disabled = !1;
|
|
414
418
|
}
|
|
415
419
|
disable() {
|
|
@@ -417,19 +421,19 @@ class At extends _ {
|
|
|
417
421
|
}
|
|
418
422
|
}
|
|
419
423
|
var _t = ((e) => (e.STATE_CHANGE = "state-change", e.START_TASK = "start-task", e.RESTART_TASK = "restart-task", e.STOP_TASK = "stop-task", e.PROCESS_ACTION = "process-action", e.ENABLE_TRIGGER = "enable-trigger", e.DISABLE_TRIGGER = "disable-trigger", e.TASK_STATE_CHANGE = "task-state-change", e.TASK_STDOUT = "task-stdout", e.TASK_STDERR = "task-stderr", e))(_t || {}), It = ((e) => (e.IDLE = "idle", e.STARTING = "starting", e.STARTED = "started", e.STOPPING = "stopping", e.STOPPED = "stopped", e))(It || {}), wt = ((e) => (e.ACTION_PROCESSOR_ALREADY_REGISTERED = "project-action-processor-already-registered", e.ACTION_PROCESSOR_INCORRECT = "project-action-processor-incorrect", e.TASK_PROCESSOR_NOT_FOUND = "project-task-processor-not-found", e.TASK_PROCESSOR_ALREADY_REGISTERED = "project-task-processor-already-registered", e.TASK_PROCESSOR_INCORRECT = "project-task-processor-incorrect", e.TRIGGER_PROCESSOR_ALREADY_REGISTERED = "project-trigger-processor-already-registered", e.TRIGGER_PROCESSOR_INCORRECT = "project-trigger-processor-incorrect", e))(wt || {});
|
|
420
|
-
class Yt extends
|
|
424
|
+
class Yt extends N {
|
|
421
425
|
constructor(t) {
|
|
422
426
|
super(), this.config = t;
|
|
423
427
|
}
|
|
424
428
|
schema = St();
|
|
425
|
-
taskProcessors = /* @__PURE__ */ new Map([[
|
|
429
|
+
taskProcessors = /* @__PURE__ */ new Map([[S.DEFAULT, lt]]);
|
|
426
430
|
actionProcessors = /* @__PURE__ */ new Map();
|
|
427
431
|
triggerProcessors = /* @__PURE__ */ new Map();
|
|
428
432
|
tasks = /* @__PURE__ */ new Map();
|
|
429
433
|
triggers = /* @__PURE__ */ new Map();
|
|
430
434
|
state = { timestamp: Date.now(), status: "idle" };
|
|
431
435
|
validate() {
|
|
432
|
-
|
|
436
|
+
ft(this.config, this.schema);
|
|
433
437
|
}
|
|
434
438
|
getConfig() {
|
|
435
439
|
return { ...this.config };
|
|
@@ -445,8 +449,8 @@ class Yt extends D {
|
|
|
445
449
|
this.validate(), this.initTasks(), this.initTriggers(), this.updateState({ status: "starting" });
|
|
446
450
|
const t = this.getTasksStartOrder();
|
|
447
451
|
for (const s of t) if (this.tasks.has(s)) {
|
|
448
|
-
const { instance: i, config: r } = this.tasks.get(s), { mode: o =
|
|
449
|
-
o ===
|
|
452
|
+
const { instance: i, config: r } = this.tasks.get(s), { mode: o = y.IMMEDIATE, dependencies: a = [] } = r;
|
|
453
|
+
o === y.IMMEDIATE && a.length === 0 && i.start();
|
|
450
454
|
}
|
|
451
455
|
this.updateState({ status: "started" });
|
|
452
456
|
}
|
|
@@ -470,12 +474,12 @@ class Yt extends D {
|
|
|
470
474
|
}
|
|
471
475
|
registerTask(t, s) {
|
|
472
476
|
if (this.taskProcessors.has(t)) throw new p(`Task processor for type "${t}" already registered`, "project-task-processor-already-registered", { type: t });
|
|
473
|
-
if (!(s.prototype instanceof
|
|
477
|
+
if (!(s.prototype instanceof U)) throw new p(`Task processor for type "${t}" must be a subclass of "RuniumTask"`, "project-task-processor-incorrect", { type: t });
|
|
474
478
|
this.taskProcessors.set(t, s);
|
|
475
479
|
}
|
|
476
480
|
registerTrigger(t, s) {
|
|
477
481
|
if (this.triggerProcessors.has(t)) throw new p(`Trigger processor for type "${t}" already registered`, "project-trigger-processor-already-registered", { type: t });
|
|
478
|
-
if (!(s.prototype instanceof
|
|
482
|
+
if (!(s.prototype instanceof I)) throw new p(`Trigger processor for type "${t}" must be a subclass of "RuniumTrigger"`, "project-trigger-processor-incorrect", { type: t });
|
|
479
483
|
this.triggerProcessors.set(t, s);
|
|
480
484
|
}
|
|
481
485
|
updateState(t) {
|
|
@@ -484,14 +488,14 @@ class Yt extends D {
|
|
|
484
488
|
initTasks() {
|
|
485
489
|
this.tasks.clear();
|
|
486
490
|
for (const t of this.config.tasks) {
|
|
487
|
-
const s = t.type ||
|
|
491
|
+
const s = t.type || S.DEFAULT, i = this.taskProcessors.get(s);
|
|
488
492
|
if (!i) throw new p(`Task processor for type "${s}" not found`, "project-task-processor-not-found", { type: s });
|
|
489
493
|
const r = new i(t.options);
|
|
490
|
-
r.on(
|
|
494
|
+
r.on(A.STATE_CHANGE, (o) => {
|
|
491
495
|
this.emit("task-state-change", t.id, o), this.onTaskStateChange(t.id, o);
|
|
492
|
-
}), r.on(
|
|
496
|
+
}), r.on(A.STDOUT, (o) => {
|
|
493
497
|
this.emit("task-stdout", t.id, o);
|
|
494
|
-
}), r.on(
|
|
498
|
+
}), r.on(A.STDERR, (o) => {
|
|
495
499
|
this.emit("task-stderr", t.id, o);
|
|
496
500
|
}), this.tasks.set(t.id, { instance: r, config: t, dependencies: [...t.dependencies || []], dependents: null });
|
|
497
501
|
}
|
|
@@ -514,7 +518,7 @@ class Yt extends D {
|
|
|
514
518
|
const { restart: a } = i;
|
|
515
519
|
if (a && s.exitCode !== -1) {
|
|
516
520
|
const { policy: c } = a;
|
|
517
|
-
if (c ===
|
|
521
|
+
if (c === E.ALWAYS || c === E.ON_FAILURE && s.exitCode !== 0) {
|
|
518
522
|
const { maxRetries: n = 1 / 0, delay: u = 0 } = a;
|
|
519
523
|
s.iteration <= n && setTimeout(r.restart.bind(r), u);
|
|
520
524
|
}
|
|
@@ -525,7 +529,7 @@ class Yt extends D {
|
|
|
525
529
|
});
|
|
526
530
|
}
|
|
527
531
|
checkTaskStateCondition(t, s) {
|
|
528
|
-
return typeof t == "string" ?
|
|
532
|
+
return typeof t == "string" ? Z.evaluate(t, s) === !0 : typeof t == "object" ? Object.entries(t).every(([i, r]) => s[i] === r) : typeof t == "boolean" && t;
|
|
529
533
|
}
|
|
530
534
|
async startTask(t) {
|
|
531
535
|
if (this.tasks.has(t)) {
|
|
@@ -555,7 +559,7 @@ class Yt extends D {
|
|
|
555
559
|
isDependentTaskReady(t) {
|
|
556
560
|
if (this.tasks.has(t)) {
|
|
557
561
|
const { dependencies: s = [], config: i } = this.tasks.get(t);
|
|
558
|
-
if (i.mode ===
|
|
562
|
+
if (i.mode === y.IGNORE) return !1;
|
|
559
563
|
for (const { taskId: r, condition: o } of s) {
|
|
560
564
|
const { instance: a } = this.tasks.get(r);
|
|
561
565
|
if (!this.checkTaskStateCondition(o, a.getState())) return !1;
|
|
@@ -577,47 +581,58 @@ class Yt extends D {
|
|
|
577
581
|
return s;
|
|
578
582
|
}
|
|
579
583
|
processAction(t) {
|
|
580
|
-
if (this.emit("process-action", t),
|
|
584
|
+
if (this.emit("process-action", t), P(t)) {
|
|
585
|
+
const s = t.options.taskId;
|
|
586
|
+
switch (t.type) {
|
|
587
|
+
case d.START_TASK:
|
|
588
|
+
this.startTask(s);
|
|
589
|
+
break;
|
|
590
|
+
case d.RESTART_TASK:
|
|
591
|
+
this.restartTask(s);
|
|
592
|
+
break;
|
|
593
|
+
case d.STOP_TASK:
|
|
594
|
+
this.stopTask(s);
|
|
595
|
+
}
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
if (j(t)) {
|
|
599
|
+
const s = t.options.triggerId;
|
|
600
|
+
switch (t.type) {
|
|
601
|
+
case d.ENABLE_TRIGGER:
|
|
602
|
+
this.enableTrigger(s);
|
|
603
|
+
break;
|
|
604
|
+
case d.DISABLE_TRIGGER:
|
|
605
|
+
this.disableTrigger(s);
|
|
606
|
+
}
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
if (ut(t)) {
|
|
581
610
|
const s = this.actionProcessors.get(t.type);
|
|
582
|
-
s && s(t.
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
this.startTask(t.taskId);
|
|
586
|
-
break;
|
|
587
|
-
case d.RESTART_TASK:
|
|
588
|
-
this.restartTask(t.taskId);
|
|
589
|
-
break;
|
|
590
|
-
case d.STOP_TASK:
|
|
591
|
-
this.stopTask(t.taskId);
|
|
592
|
-
break;
|
|
611
|
+
return void (s && s(t.options || {}));
|
|
612
|
+
}
|
|
613
|
+
switch (t.type) {
|
|
593
614
|
case d.EMIT_EVENT:
|
|
594
|
-
this.emit(t.event);
|
|
615
|
+
this.emit(t.options.event);
|
|
595
616
|
break;
|
|
596
617
|
case d.STOP_PROJECT:
|
|
597
618
|
this.stop("action");
|
|
598
|
-
break;
|
|
599
|
-
case d.ENABLE_TRIGGER:
|
|
600
|
-
this.enableTrigger(t.triggerId);
|
|
601
|
-
break;
|
|
602
|
-
case d.DISABLE_TRIGGER:
|
|
603
|
-
this.disableTrigger(t.triggerId);
|
|
604
619
|
}
|
|
605
620
|
}
|
|
606
621
|
initTriggers() {
|
|
607
622
|
const t = { processAction: this.processAction.bind(this), on: this.on.bind(this), off: this.off.bind(this) };
|
|
608
623
|
let s = null;
|
|
609
624
|
for (const i of this.config.triggers || []) {
|
|
610
|
-
if (
|
|
625
|
+
if (ht(i)) {
|
|
611
626
|
const r = this.triggerProcessors.get(i.type);
|
|
612
627
|
r && (s = new r(i, t));
|
|
613
628
|
} else switch (i.type) {
|
|
614
|
-
case
|
|
629
|
+
case f.EVENT:
|
|
615
630
|
s = new Rt(i, t);
|
|
616
631
|
break;
|
|
617
|
-
case
|
|
632
|
+
case f.INTERVAL:
|
|
618
633
|
s = new kt(i, t);
|
|
619
634
|
break;
|
|
620
|
-
case
|
|
635
|
+
case f.TIMEOUT:
|
|
621
636
|
s = new At(i, t);
|
|
622
637
|
}
|
|
623
638
|
s && (this.triggers.set(i.id, s), i.disabled !== !0 && s.enable());
|
|
@@ -641,40 +656,40 @@ class Yt extends D {
|
|
|
641
656
|
}
|
|
642
657
|
export {
|
|
643
658
|
Rt as EventTrigger,
|
|
644
|
-
|
|
645
|
-
|
|
659
|
+
st as FileErrorCode,
|
|
660
|
+
b as ID_REGEX,
|
|
646
661
|
kt as IntervalTrigger,
|
|
647
|
-
|
|
662
|
+
it as MacrosErrorCode,
|
|
648
663
|
Yt as Project,
|
|
649
664
|
d as ProjectActionType,
|
|
650
|
-
|
|
665
|
+
nt as ProjectConfigErrorCode,
|
|
651
666
|
wt as ProjectErrorCode,
|
|
652
667
|
_t as ProjectEvent,
|
|
653
|
-
|
|
668
|
+
Tt as ProjectSchemaErrorCode,
|
|
654
669
|
It as ProjectStatus,
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
670
|
+
E as ProjectTaskRestartPolicyType,
|
|
671
|
+
y as ProjectTaskStartMode,
|
|
672
|
+
S as ProjectTaskType,
|
|
673
|
+
f as ProjectTriggerType,
|
|
659
674
|
p as RuniumError,
|
|
660
|
-
|
|
661
|
-
|
|
675
|
+
U as RuniumTask,
|
|
676
|
+
I as RuniumTrigger,
|
|
662
677
|
Ft as SILENT_EXIT_CODE,
|
|
663
678
|
lt as Task,
|
|
664
|
-
|
|
679
|
+
A as TaskEvent,
|
|
665
680
|
g as TaskStatus,
|
|
666
681
|
At as TimeoutTrigger,
|
|
667
682
|
qt as applyMacros,
|
|
668
683
|
Et as extendProjectSchema,
|
|
669
684
|
Ut as getProcessTreePids,
|
|
670
685
|
St as getProjectSchema,
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
686
|
+
ut as isCustomAction,
|
|
687
|
+
ht as isCustomTrigger,
|
|
688
|
+
P as isProcessTaskAction,
|
|
674
689
|
xt as isRuniumError,
|
|
675
|
-
|
|
676
|
-
|
|
690
|
+
j as isToggleTriggerAction,
|
|
691
|
+
ot as killProcessTree,
|
|
677
692
|
Mt as readJsonFile,
|
|
678
|
-
|
|
693
|
+
ft as validateProject,
|
|
679
694
|
Kt as writeJsonFile
|
|
680
695
|
};
|