@runium/core 0.0.7 → 0.0.9
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/.eslintrc.json +30 -0
- package/.prettierrc.json +10 -0
- package/README.md +1 -0
- package/package.json +23 -11
- package/src/error.ts +22 -0
- package/src/file.ts +53 -0
- package/src/index.ts +8 -0
- package/src/macros.ts +91 -0
- package/src/project-config.ts +483 -0
- package/src/project-schema.ts +767 -0
- package/src/project.ts +748 -0
- package/src/task.ts +381 -0
- package/src/trigger.ts +170 -0
- package/tsconfig.json +29 -0
- package/types/index.d.ts +510 -0
- package/types/package.json +22 -0
- package/vite.config.ts +123 -0
- package/index.js +0 -586
package/index.js
DELETED
|
@@ -1,586 +0,0 @@
|
|
|
1
|
-
import { readFile as x, writeFile as M, mkdir as j } from "node:fs/promises";
|
|
2
|
-
import { EventEmitter as v } from "node:events";
|
|
3
|
-
import q from "bcx-expression-evaluator";
|
|
4
|
-
import K from "ajv/dist/2020.js";
|
|
5
|
-
import U from "ajv-keywords";
|
|
6
|
-
import { spawn as F } from "node:child_process";
|
|
7
|
-
import { createWriteStream as w } from "node:fs";
|
|
8
|
-
import { resolve as I, dirname as P } from "node:path";
|
|
9
|
-
class p extends Error {
|
|
10
|
-
code;
|
|
11
|
-
payload;
|
|
12
|
-
constructor(t, s, r = null) {
|
|
13
|
-
super(t), this.code = s, this.payload = r;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function At(e) {
|
|
17
|
-
return !!e && e instanceof p;
|
|
18
|
-
}
|
|
19
|
-
var Y = ((e) => (e.READ_JSON = "file-read-json", e.WRITE_JSON = "file-write-json", e))(Y || {});
|
|
20
|
-
async function _t(e) {
|
|
21
|
-
try {
|
|
22
|
-
const t = await x(e, { encoding: "utf-8" });
|
|
23
|
-
return JSON.parse(t);
|
|
24
|
-
} catch (t) {
|
|
25
|
-
throw new p(`Can not read JSON file ${e}`, "file-read-json", { path: e, original: t });
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
async function It(e, t) {
|
|
29
|
-
try {
|
|
30
|
-
await M(e, JSON.stringify(t, null, 2), { encoding: "utf-8" });
|
|
31
|
-
} catch (s) {
|
|
32
|
-
throw new p(`Can not write JSON file ${e}`, "file-write-json", { path: e, data: t, original: s });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
const V = String.raw`"\$unwrap\((.*)\)"`;
|
|
36
|
-
var J = ((e) => (e.MACRO_APPLY_ERROR = "macro-apply-error", e))(J || {});
|
|
37
|
-
function $t(e, t) {
|
|
38
|
-
const s = Object.keys(t), r = String.raw`\$(${s.join("|")})\(([^()]*(?:\([^()]*\)[^()]*)*)\)`, i = (o) => {
|
|
39
|
-
const a = new RegExp(r, "g");
|
|
40
|
-
let c = o, n = !0;
|
|
41
|
-
for (; n; ) n = !1, c = c.replace(a, (u, A, N) => {
|
|
42
|
-
n = !0;
|
|
43
|
-
const y = [];
|
|
44
|
-
let _ = 0, S = "";
|
|
45
|
-
for (const g of N) g === "," && _ === 0 ? (y.push(S.trim()), S = "") : (g === "(" && _++, g === ")" && _--, S += g);
|
|
46
|
-
y.push(S.trim());
|
|
47
|
-
const G = y.map((g) => g ? i(g) : "");
|
|
48
|
-
try {
|
|
49
|
-
return t[A](...G);
|
|
50
|
-
} catch (g) {
|
|
51
|
-
throw new p(`Can not apply macro "${A}"`, "macro-apply-error", { type: A, args: y, original: g });
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
return c;
|
|
55
|
-
};
|
|
56
|
-
return (function(o) {
|
|
57
|
-
const a = new RegExp(V, "g");
|
|
58
|
-
return o.replace(a, (c, n) => n.trim());
|
|
59
|
-
})(s.length ? i(e) : e);
|
|
60
|
-
}
|
|
61
|
-
var f = ((e) => (e.IMMEDIATE = "immediate", e.DEFERRED = "deferred", e.IGNORE = "ignore", e))(f || {}), 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 || {}), T = ((e) => (e.DEFAULT = "default", e))(T || {}), l = ((e) => (e.EVENT = "event", e.TIMEOUT = "timeout", e.INTERVAL = "interval", e))(l || {}), m = ((e) => (e.ALWAYS = "always", e.ON_FAILURE = "on-failure", e))(m || {}), B = ((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))(B || {});
|
|
62
|
-
const H = /* @__PURE__ */ new Set(["start-task", "restart-task", "stop-task"]), W = /* @__PURE__ */ new Set(["enable-trigger", "disable-trigger"]), X = new Set(Object.values(d)), z = new Set(Object.values(l));
|
|
63
|
-
function b(e) {
|
|
64
|
-
return H.has(e.type);
|
|
65
|
-
}
|
|
66
|
-
function O(e) {
|
|
67
|
-
return W.has(e.type);
|
|
68
|
-
}
|
|
69
|
-
function Z(e) {
|
|
70
|
-
return !X.has(e.type);
|
|
71
|
-
}
|
|
72
|
-
function Q(e) {
|
|
73
|
-
return !z.has(e.type);
|
|
74
|
-
}
|
|
75
|
-
const C = new K({ allowUnionTypes: !0, allErrors: !0, verbose: !0 });
|
|
76
|
-
function tt(e) {
|
|
77
|
-
const t = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Set();
|
|
78
|
-
for (const i of e.tasks) s.add(i.id), t.set(i.id, []);
|
|
79
|
-
const r = new Set(e.triggers?.map((i) => i.id) || []);
|
|
80
|
-
for (const i of e.tasks) {
|
|
81
|
-
for (const o of i.dependencies || []) {
|
|
82
|
-
if (!s.has(o.taskId)) throw new p(`Task "${i.id}" depends on not existing task "${o.taskId}"`, "project-config-task-not-exists", { taskId: i.id, dependency: { ...o }, scope: "dependencies" });
|
|
83
|
-
t.get(o.taskId).push(i.id);
|
|
84
|
-
}
|
|
85
|
-
for (const o of i.handlers || []) {
|
|
86
|
-
if (b(o.action) && !s.has(o.action.taskId)) throw new p(`Task "${i.id}" handler action uses not existing task "${o.action.taskId}"`, "project-config-task-not-exists", { taskId: i.id, handler: { ...o }, scope: "handlers" });
|
|
87
|
-
if (O(o.action) && !r.has(o.action.triggerId)) throw new p(`Task "${i.id}" handler action uses not existing trigger "${o.action.triggerId}"`, "project-config-trigger-not-exists", { taskId: i.id, handler: { ...o }, scope: "handlers" });
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
for (const i of e.triggers || []) {
|
|
91
|
-
if (b(i.action) && !s.has(i.action.taskId)) throw new p(`Trigger "${i.id}" action uses not existing task "${i.action.taskId}"`, "project-config-task-not-exists", { trigger: { ...i }, scope: "triggers" });
|
|
92
|
-
if (O(i.action) && !r.has(i.action.triggerId)) throw new p(`Trigger "${i.id}" action uses not existing trigger "${i.action.triggerId}"`, "project-config-trigger-not-exists", { trigger: { ...i }, scope: "triggers" });
|
|
93
|
-
}
|
|
94
|
-
(function(i) {
|
|
95
|
-
const o = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), c = (n) => {
|
|
96
|
-
if (a.has(n)) {
|
|
97
|
-
const u = [...a, n].join(" -> ");
|
|
98
|
-
throw new p(`Project config tasks circular dependency detected ${u}`, "project-config-tasks-circular-dependency", { task: n, dependencies: [...a] });
|
|
99
|
-
}
|
|
100
|
-
if (!o.has(n)) {
|
|
101
|
-
a.add(n);
|
|
102
|
-
for (const u of i.get(n) || []) c(u);
|
|
103
|
-
a.delete(n), o.add(n);
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
for (const n of i.keys()) o.has(n) || c(n);
|
|
107
|
-
})(t);
|
|
108
|
-
}
|
|
109
|
-
function et(e, t) {
|
|
110
|
-
(function(s, r) {
|
|
111
|
-
const i = C.compile(r || {});
|
|
112
|
-
if (!i(s)) throw new p("Incorrect project config data", "project-config-incorrect-data", { errors: i.errors });
|
|
113
|
-
})(e, t), tt(e);
|
|
114
|
-
}
|
|
115
|
-
U(C, ["uniqueItemProperties"]);
|
|
116
|
-
var h = ((e) => (e.IDLE = "idle", e.STARTING = "starting", e.STARTED = "started", e.COMPLETED = "completed", e.FAILED = "failed", e.STOPPING = "stopping", e.STOPPED = "stopped", e))(h || {}), E = ((e) => (e.STATE_CHANGE = "state-change", e.STDOUT = "stdout", e.STDERR = "stderr", e))(E || {});
|
|
117
|
-
const jt = -1;
|
|
118
|
-
class D extends v {
|
|
119
|
-
constructor(t) {
|
|
120
|
-
super(), this.options = t;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
class st extends D {
|
|
124
|
-
constructor(t) {
|
|
125
|
-
super(t), this.options = t, this.setMaxListeners(50), this.options.env = { ...process.env, ...t.env || {} }, this.options.cwd = I(process.cwd(), t.cwd || "");
|
|
126
|
-
}
|
|
127
|
-
state = { status: "idle", pid: -1, timestamp: Date.now(), iteration: 0 };
|
|
128
|
-
process = null;
|
|
129
|
-
stdoutStream = null;
|
|
130
|
-
stderrStream = null;
|
|
131
|
-
ttlTimer = null;
|
|
132
|
-
getState() {
|
|
133
|
-
return { ...this.state };
|
|
134
|
-
}
|
|
135
|
-
getOptions() {
|
|
136
|
-
return { ...this.options };
|
|
137
|
-
}
|
|
138
|
-
canStart() {
|
|
139
|
-
const { status: t } = this.state;
|
|
140
|
-
return t !== "started" && t !== "starting" && t !== "stopping";
|
|
141
|
-
}
|
|
142
|
-
async start() {
|
|
143
|
-
if (this.canStart()) {
|
|
144
|
-
this.updateState({ status: "starting", iteration: this.state.iteration + 1, pid: -1, exitCode: void 0, error: void 0 });
|
|
145
|
-
try {
|
|
146
|
-
await this.initLogStreams();
|
|
147
|
-
const { cwd: t, command: s, arguments: r = [], env: i, shell: o = !0 } = this.options;
|
|
148
|
-
this.process = F(s, r, { cwd: t, env: i, shell: o, stdio: ["ignore", "pipe", "pipe"] }), this.addProcessListeners(), this.setTTLTimer(), this.updateState({ status: "started", pid: this.process.pid });
|
|
149
|
-
} catch (t) {
|
|
150
|
-
this.onError(t);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
canStop() {
|
|
155
|
-
const { status: t } = this.state;
|
|
156
|
-
return !!this.process && t === "started";
|
|
157
|
-
}
|
|
158
|
-
async stop(t = "") {
|
|
159
|
-
if (this.canStop()) return this.updateState({ status: "stopping", reason: t }), new Promise((s) => {
|
|
160
|
-
const r = this.options.stopSignal || "SIGTERM";
|
|
161
|
-
this.process.kill(r), this.process.on("exit", () => {
|
|
162
|
-
s();
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
async restart() {
|
|
167
|
-
await this.stop("restart"), this.start();
|
|
168
|
-
}
|
|
169
|
-
updateState(t) {
|
|
170
|
-
const s = { ...this.state, ...t, timestamp: Date.now() };
|
|
171
|
-
this.state = Object.fromEntries(Object.entries(s).filter(([r, i]) => i !== void 0)), this.emit("state-change", this.getState()), this.emit(this.state.status, this.getState());
|
|
172
|
-
}
|
|
173
|
-
async initLogStreams() {
|
|
174
|
-
const { stdout: t = null, stderr: s = null } = this.options.log || {};
|
|
175
|
-
if (t) {
|
|
176
|
-
const r = I(t);
|
|
177
|
-
await j(P(r), { recursive: !0 }), this.stdoutStream = w(t, { flags: "w" });
|
|
178
|
-
}
|
|
179
|
-
if (s) {
|
|
180
|
-
const r = I(s);
|
|
181
|
-
await j(P(r), { recursive: !0 }), this.stderrStream = w(s, { flags: "w" });
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
setTTLTimer() {
|
|
185
|
-
const { ttl: t } = this.options;
|
|
186
|
-
t && this.process && (this.ttlTimer = setTimeout(() => {
|
|
187
|
-
this.stop("ttl");
|
|
188
|
-
}, t));
|
|
189
|
-
}
|
|
190
|
-
addProcessListeners() {
|
|
191
|
-
this.process && (this.process.stdout?.on("data", (t) => this.onStdOutData(t)), this.process.stderr?.on("data", (t) => this.onStdErrData(t)), this.process.on("exit", (t) => this.onExit(t)), this.process.on("error", (t) => this.onError(t)));
|
|
192
|
-
}
|
|
193
|
-
onStdOutData(t) {
|
|
194
|
-
const s = t.toString();
|
|
195
|
-
this.emit("stdout", s), this.stdoutStream && this.stdoutStream.write(s);
|
|
196
|
-
}
|
|
197
|
-
onStdErrData(t) {
|
|
198
|
-
const s = t.toString();
|
|
199
|
-
this.emit("stderr", s), this.stderrStream && this.stderrStream.write(s);
|
|
200
|
-
}
|
|
201
|
-
onExit(t) {
|
|
202
|
-
const s = t !== null ? t : -1;
|
|
203
|
-
this.updateState({ status: s === 0 ? "completed" : s === -1 ? "stopped" : "failed", exitCode: s }), this.cleanup();
|
|
204
|
-
}
|
|
205
|
-
onError(t) {
|
|
206
|
-
this.updateState({ status: "failed", error: t }), this.cleanup();
|
|
207
|
-
}
|
|
208
|
-
cleanup() {
|
|
209
|
-
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);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
var rt = ((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))(rt || {});
|
|
213
|
-
const $ = /^[a-zA-Z0-9_-]+$/, it = { id: { type: "string", pattern: $.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" } }, R = { id: { type: "string", pattern: $.source }, action: { $ref: "#/$defs/Runium_Action" }, disabled: { type: "boolean" } };
|
|
214
|
-
function L(e, t) {
|
|
215
|
-
return { type: "object", properties: { ...structuredClone(it), type: { const: e }, options: { ...structuredClone(t) } }, required: ["id", "options"], additionalProperties: !1 };
|
|
216
|
-
}
|
|
217
|
-
function ot(e, t) {
|
|
218
|
-
return { type: "object", properties: { type: { type: "string", const: e }, ...t ? { payload: t } : {} }, required: ["type", ...t ? ["payload"] : []], additionalProperties: !1 };
|
|
219
|
-
}
|
|
220
|
-
function nt(e, t) {
|
|
221
|
-
const s = t ? { payload: t } : {}, r = t ? ["payload"] : [];
|
|
222
|
-
return { type: "object", properties: { ...structuredClone(R), type: { type: "string", const: e }, ...s }, required: ["id", "type", "action", ...r], additionalProperties: !1 };
|
|
223
|
-
}
|
|
224
|
-
function at() {
|
|
225
|
-
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: $.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(f) }, 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(h) }, 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: { type: "object", properties: { ...structuredClone(R), type: { const: l.EVENT }, event: { type: "string" } }, required: ["id", "type", "event", "action"], additionalProperties: !1 }, Runium_TriggerInterval: { type: "object", properties: { ...structuredClone(R), type: { const: l.INTERVAL }, interval: { type: "number", minimum: 0 } }, required: ["id", "type", "interval", "action"], additionalProperties: !1 }, Runium_TriggerTimeout: { type: "object", properties: { ...structuredClone(R), type: { const: l.TIMEOUT }, timeout: { type: "number", minimum: 0 } }, required: ["id", "type", "timeout", "action"], additionalProperties: !1 }, Runium_Action: { oneOf: [{ $ref: "#/$defs/Runium_ActionEmitEvent" }, { $ref: "#/$defs/Runium_ActionProcessTask" }, { $ref: "#/$defs/Runium_ActionStopProject" }, { $ref: "#/$defs/Runium_ActionToggleTrigger" }] }, Runium_ActionEmitEvent: { type: "object", properties: { type: { type: "string", const: d.EMIT_EVENT }, event: { type: "string" } }, required: ["type", "event"], additionalProperties: !1 }, Runium_ActionProcessTask: { type: "object", properties: { type: { type: "string", enum: [d.START_TASK, d.RESTART_TASK, d.STOP_TASK] }, taskId: { type: "string" } }, required: ["type", "taskId"], additionalProperties: !1 }, Runium_ActionStopProject: { type: "object", properties: { type: { type: "string", const: d.STOP_PROJECT } }, required: ["type"], additionalProperties: !1 }, Runium_ActionToggleTrigger: { type: "object", properties: { type: { type: "string", enum: [d.ENABLE_TRIGGER, d.DISABLE_TRIGGER] }, triggerId: { type: "string" } }, required: ["type", "triggerId"], additionalProperties: !1 }, Runium_TaskConfig: { ...L(T.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: m.ALWAYS }, delay: { type: "number" } }, additionalProperties: !1 }, Runium_TaskRestartPolicyOnFailure: { type: "object", required: ["policy"], properties: { policy: { const: m.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 } } };
|
|
226
|
-
return Object.freeze(e);
|
|
227
|
-
}
|
|
228
|
-
function ct(e, t) {
|
|
229
|
-
let s = structuredClone(e);
|
|
230
|
-
return t.project && (s = (function(r, i) {
|
|
231
|
-
return i && (r.properties = { ...i.properties || {}, ...r.properties }, r.required = Array.from(/* @__PURE__ */ new Set([...r.required ?? [], ...i.required ?? []]))), r;
|
|
232
|
-
})(s, t.project)), t.definitions && (s = (function(r, i) {
|
|
233
|
-
return i && (r.$defs = { ...i, ...r.$defs }), r;
|
|
234
|
-
})(s, t.definitions)), t.tasks && (s = (function(r, i) {
|
|
235
|
-
if (i) {
|
|
236
|
-
const o = new Set(r.properties.tasks.items.oneOf.map((c) => {
|
|
237
|
-
const n = c.$ref.split("/").pop() || "";
|
|
238
|
-
return r.$defs[n]?.properties?.type?.const || T.DEFAULT;
|
|
239
|
-
})), a = {};
|
|
240
|
-
for (const [c, n] of Object.entries(i)) {
|
|
241
|
-
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 });
|
|
242
|
-
a[c] = L(n.type, n.options), r.properties.tasks.items.oneOf.push({ $ref: `#/$defs/${c}` }), o.add(n.type);
|
|
243
|
-
}
|
|
244
|
-
r.$defs = { ...a, ...r.$defs };
|
|
245
|
-
}
|
|
246
|
-
return r;
|
|
247
|
-
})(s, t.tasks)), t.actions && (s = (function(r, i) {
|
|
248
|
-
if (i) {
|
|
249
|
-
const o = new Set(r.$defs.Runium_Action.oneOf.map((c) => {
|
|
250
|
-
const n = c.$ref.split("/").pop() || "", u = r.$defs[n]?.properties?.type;
|
|
251
|
-
return u?.enum || [u?.const];
|
|
252
|
-
}).flat()), a = {};
|
|
253
|
-
for (const [c, n] of Object.entries(i)) {
|
|
254
|
-
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 });
|
|
255
|
-
a[c] = ot(n.type, n.payload), r.$defs.Runium_Action.oneOf.push({ $ref: `#/$defs/${c}` }), o.add(n.type);
|
|
256
|
-
}
|
|
257
|
-
r.$defs = { ...a, ...r.$defs };
|
|
258
|
-
}
|
|
259
|
-
return r;
|
|
260
|
-
})(s, t.actions)), t.triggers && (s = (function(r, i) {
|
|
261
|
-
if (i) {
|
|
262
|
-
const o = new Set(r.$defs.Runium_Trigger.oneOf.map((c) => {
|
|
263
|
-
const n = c.$ref.split("/").pop() || "";
|
|
264
|
-
return r.$defs[n]?.properties?.type?.const;
|
|
265
|
-
})), a = {};
|
|
266
|
-
for (const [c, n] of Object.entries(i)) {
|
|
267
|
-
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 });
|
|
268
|
-
a[c] = nt(n.type, n.payload), r.$defs.Runium_Trigger.oneOf.push({ $ref: `#/$defs/${c}` }), o.add(n.type);
|
|
269
|
-
}
|
|
270
|
-
r.$defs = { ...a, ...r.$defs };
|
|
271
|
-
}
|
|
272
|
-
return r;
|
|
273
|
-
})(s, t.triggers)), Object.freeze(s);
|
|
274
|
-
}
|
|
275
|
-
class k {
|
|
276
|
-
project;
|
|
277
|
-
id;
|
|
278
|
-
action;
|
|
279
|
-
disabled;
|
|
280
|
-
constructor(t, s) {
|
|
281
|
-
this.id = t.id, this.action = t.action, this.disabled = t.disabled ?? !1, this.project = s;
|
|
282
|
-
}
|
|
283
|
-
getId() {
|
|
284
|
-
return this.id;
|
|
285
|
-
}
|
|
286
|
-
isDisabled() {
|
|
287
|
-
return this.disabled;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
class pt extends k {
|
|
291
|
-
event;
|
|
292
|
-
constructor(t, s) {
|
|
293
|
-
super(t, s), this.event = t.event;
|
|
294
|
-
}
|
|
295
|
-
enable() {
|
|
296
|
-
this.project.on(this.event, this.handler), this.disabled = !1;
|
|
297
|
-
}
|
|
298
|
-
disable() {
|
|
299
|
-
this.project.off(this.event, this.handler), this.disabled = !0;
|
|
300
|
-
}
|
|
301
|
-
handler = () => {
|
|
302
|
-
this.project.processAction(this.action);
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
class dt extends k {
|
|
306
|
-
interval;
|
|
307
|
-
intervalId = null;
|
|
308
|
-
constructor(t, s) {
|
|
309
|
-
super(t, s), this.interval = t.interval;
|
|
310
|
-
}
|
|
311
|
-
enable() {
|
|
312
|
-
this.intervalId = setInterval(() => {
|
|
313
|
-
this.project.processAction(this.action);
|
|
314
|
-
}, this.interval), this.disabled = !1;
|
|
315
|
-
}
|
|
316
|
-
disable() {
|
|
317
|
-
this.intervalId && clearInterval(this.intervalId), this.disabled = !0, this.intervalId = null;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
class ut extends k {
|
|
321
|
-
timeout;
|
|
322
|
-
timeoutId = null;
|
|
323
|
-
constructor(t, s) {
|
|
324
|
-
super(t, s), this.timeout = t.timeout;
|
|
325
|
-
}
|
|
326
|
-
enable() {
|
|
327
|
-
this.timeoutId = setTimeout(() => {
|
|
328
|
-
this.project.processAction(this.action);
|
|
329
|
-
}, this.timeout), this.disabled = !1;
|
|
330
|
-
}
|
|
331
|
-
disable() {
|
|
332
|
-
this.timeoutId && clearTimeout(this.timeoutId), this.disabled = !0, this.timeoutId = null;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
var gt = ((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))(gt || {}), ht = ((e) => (e.IDLE = "idle", e.STARTING = "starting", e.STARTED = "started", e.STOPPING = "stopping", e.STOPPED = "stopped", e))(ht || {}), lt = ((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))(lt || {});
|
|
336
|
-
class wt extends v {
|
|
337
|
-
constructor(t) {
|
|
338
|
-
super(), this.config = t;
|
|
339
|
-
}
|
|
340
|
-
schema = at();
|
|
341
|
-
taskProcessors = /* @__PURE__ */ new Map([[T.DEFAULT, st]]);
|
|
342
|
-
actionProcessors = /* @__PURE__ */ new Map();
|
|
343
|
-
triggerProcessors = /* @__PURE__ */ new Map();
|
|
344
|
-
tasks = /* @__PURE__ */ new Map();
|
|
345
|
-
triggers = /* @__PURE__ */ new Map();
|
|
346
|
-
state = { timestamp: Date.now(), status: "idle" };
|
|
347
|
-
validate() {
|
|
348
|
-
et(this.config, this.schema);
|
|
349
|
-
}
|
|
350
|
-
getConfig() {
|
|
351
|
-
return { ...this.config };
|
|
352
|
-
}
|
|
353
|
-
setConfig(t) {
|
|
354
|
-
this.config = { ...t };
|
|
355
|
-
}
|
|
356
|
-
getState() {
|
|
357
|
-
return { ...this.state };
|
|
358
|
-
}
|
|
359
|
-
async start() {
|
|
360
|
-
if (this.state.status !== "idle" && this.state.status !== "stopped") return;
|
|
361
|
-
this.validate(), this.initTasks(), this.initTriggers(), this.updateState({ status: "starting" });
|
|
362
|
-
const t = this.getTasksStartOrder();
|
|
363
|
-
for (const s of t) if (this.tasks.has(s)) {
|
|
364
|
-
const { instance: r, config: i } = this.tasks.get(s), { mode: o = f.IMMEDIATE, dependencies: a = [] } = i;
|
|
365
|
-
o === f.IMMEDIATE && a.length === 0 && r.start();
|
|
366
|
-
}
|
|
367
|
-
this.updateState({ status: "started" });
|
|
368
|
-
}
|
|
369
|
-
async stop(t = "") {
|
|
370
|
-
if (this.state.status !== "started" && this.state.status !== "starting") return;
|
|
371
|
-
this.updateState({ status: "stopping", reason: t }), this.cleanupTriggers();
|
|
372
|
-
const s = this.getTasksStartOrder().reverse(), r = [];
|
|
373
|
-
for (const i of s) if (this.tasks.has(i)) {
|
|
374
|
-
const { instance: o } = this.tasks.get(i), { status: a } = o.getState();
|
|
375
|
-
a === h.STARTED && r.push(o.stop("project-stop"));
|
|
376
|
-
}
|
|
377
|
-
await Promise.allSettled(r), this.updateState({ status: "stopped" });
|
|
378
|
-
}
|
|
379
|
-
extendValidationSchema(t) {
|
|
380
|
-
this.schema = ct(this.schema, t);
|
|
381
|
-
}
|
|
382
|
-
registerAction(t, s) {
|
|
383
|
-
if (this.actionProcessors.has(t)) throw new p(`Action processor for type "${t}" already registered`, "project-action-processor-already-registered", { type: t });
|
|
384
|
-
if (typeof s != "function") throw new p(`Action processor for type "${t}" must be a function`, "project-action-processor-incorrect", { type: t });
|
|
385
|
-
this.actionProcessors.set(t, s);
|
|
386
|
-
}
|
|
387
|
-
registerTask(t, s) {
|
|
388
|
-
if (this.taskProcessors.has(t)) throw new p(`Task processor for type "${t}" already registered`, "project-task-processor-already-registered", { type: t });
|
|
389
|
-
if (!(s.prototype instanceof D)) throw new p(`Task processor for type "${t}" must be a subclass of "RuniumTask"`, "project-task-processor-incorrect", { type: t });
|
|
390
|
-
this.taskProcessors.set(t, s);
|
|
391
|
-
}
|
|
392
|
-
registerTrigger(t, s) {
|
|
393
|
-
if (this.triggerProcessors.has(t)) throw new p(`Trigger processor for type "${t}" already registered`, "project-trigger-processor-already-registered", { type: t });
|
|
394
|
-
if (!(s.prototype instanceof k)) throw new p(`Trigger processor for type "${t}" must be a subclass of "RuniumTrigger"`, "project-trigger-processor-incorrect", { type: t });
|
|
395
|
-
this.triggerProcessors.set(t, s);
|
|
396
|
-
}
|
|
397
|
-
updateState(t) {
|
|
398
|
-
this.state = { ...this.state, ...t, timestamp: Date.now() }, this.emit("state-change", this.getState()), this.emit(this.state.status, this.getState());
|
|
399
|
-
}
|
|
400
|
-
initTasks() {
|
|
401
|
-
this.tasks.clear();
|
|
402
|
-
for (const t of this.config.tasks) {
|
|
403
|
-
const s = t.type || T.DEFAULT, r = this.taskProcessors.get(s);
|
|
404
|
-
if (!r) throw new p(`Task processor for type "${s}" not found`, "project-task-processor-not-found", { type: s });
|
|
405
|
-
const i = new r(t.options);
|
|
406
|
-
i.on(E.STATE_CHANGE, (o) => {
|
|
407
|
-
this.emit("task-state-change", t.id, o), this.onTaskStateChange(t.id, o);
|
|
408
|
-
}), i.on(E.STDOUT, (o) => {
|
|
409
|
-
this.emit("task-stdout", t.id, o);
|
|
410
|
-
}), i.on(E.STDERR, (o) => {
|
|
411
|
-
this.emit("task-stderr", t.id, o);
|
|
412
|
-
}), this.tasks.set(t.id, { instance: i, config: t, dependencies: [...t.dependencies || []], dependents: null });
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
getTasksStartOrder() {
|
|
416
|
-
const t = [], s = /* @__PURE__ */ new Set(), r = (i) => {
|
|
417
|
-
if (s.has(i)) return;
|
|
418
|
-
s.add(i);
|
|
419
|
-
const { dependencies: o = [] } = this.tasks.get(i) || {};
|
|
420
|
-
for (const a of o) this.tasks.has(a.taskId) && r(a.taskId);
|
|
421
|
-
t.push(i);
|
|
422
|
-
};
|
|
423
|
-
for (const i of this.tasks.keys()) r(i);
|
|
424
|
-
return t;
|
|
425
|
-
}
|
|
426
|
-
onTaskStateChange(t, s) {
|
|
427
|
-
const { config: r, instance: i } = this.tasks.get(t), o = this.getDependentTasks(t);
|
|
428
|
-
for (const a of o) this.isDependentTaskReady(a) && this.startTask(a);
|
|
429
|
-
if (s.status === h.COMPLETED || s.status === h.FAILED) {
|
|
430
|
-
const { restart: a } = r;
|
|
431
|
-
if (a && s.exitCode !== -1) {
|
|
432
|
-
const { policy: c } = a;
|
|
433
|
-
if (c === m.ALWAYS || c === m.ON_FAILURE && s.exitCode !== 0) {
|
|
434
|
-
const { maxRetries: n = 1 / 0, delay: u = 0 } = a;
|
|
435
|
-
s.iteration <= n && setTimeout(i.restart.bind(i), u);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
(r.handlers || []).forEach((a) => {
|
|
440
|
-
this.checkTaskStateCondition(a.condition, s) && this.processAction(a.action);
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
checkTaskStateCondition(t, s) {
|
|
444
|
-
return typeof t == "string" ? q.evaluate(t, s) === !0 : typeof t == "object" ? Object.entries(t).every(([r, i]) => s[r] === i) : typeof t == "boolean" && t;
|
|
445
|
-
}
|
|
446
|
-
async startTask(t) {
|
|
447
|
-
if (this.tasks.has(t)) {
|
|
448
|
-
const { instance: s } = this.tasks.get(t), { status: r } = s.getState();
|
|
449
|
-
if (r !== h.STARTED && r !== h.STARTING && r !== h.STOPPING) return this.emit("start-task", t), s.start();
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
async stopTask(t) {
|
|
453
|
-
if (this.tasks.has(t)) {
|
|
454
|
-
const { instance: s } = this.tasks.get(t), { status: r } = s.getState();
|
|
455
|
-
if (r === h.STARTED) return this.emit("stop-task", t), s.stop("action-stop");
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
async restartTask(t) {
|
|
459
|
-
if (this.tasks.has(t)) {
|
|
460
|
-
const { instance: s } = this.tasks.get(t);
|
|
461
|
-
return this.emit("restart-task", t), s.restart();
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
isDependentTaskReady(t) {
|
|
465
|
-
if (this.tasks.has(t)) {
|
|
466
|
-
const { dependencies: s = [], config: r } = this.tasks.get(t);
|
|
467
|
-
if (r.mode === f.IGNORE) return !1;
|
|
468
|
-
for (const { taskId: i, condition: o } of s) {
|
|
469
|
-
const { instance: a } = this.tasks.get(i);
|
|
470
|
-
if (!this.checkTaskStateCondition(o, a.getState())) return !1;
|
|
471
|
-
}
|
|
472
|
-
return !0;
|
|
473
|
-
}
|
|
474
|
-
return !1;
|
|
475
|
-
}
|
|
476
|
-
getDependentTasks(t) {
|
|
477
|
-
let s = [];
|
|
478
|
-
if (this.tasks.has(t)) {
|
|
479
|
-
const { dependents: r } = this.tasks.get(t);
|
|
480
|
-
if (r) s = r;
|
|
481
|
-
else {
|
|
482
|
-
for (const [i, { dependencies: o }] of this.tasks) for (const a of o) a.taskId === t && s.push(i);
|
|
483
|
-
this.tasks.get(t).dependents = s;
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
return s;
|
|
487
|
-
}
|
|
488
|
-
processAction(t) {
|
|
489
|
-
if (this.emit("process-action", t), Z(t)) {
|
|
490
|
-
const s = this.actionProcessors.get(t.type);
|
|
491
|
-
s && s(t.payload || {});
|
|
492
|
-
} else switch (t.type) {
|
|
493
|
-
case d.START_TASK:
|
|
494
|
-
this.startTask(t.taskId);
|
|
495
|
-
break;
|
|
496
|
-
case d.RESTART_TASK:
|
|
497
|
-
this.restartTask(t.taskId);
|
|
498
|
-
break;
|
|
499
|
-
case d.STOP_TASK:
|
|
500
|
-
this.stopTask(t.taskId);
|
|
501
|
-
break;
|
|
502
|
-
case d.EMIT_EVENT:
|
|
503
|
-
this.emit(t.event);
|
|
504
|
-
break;
|
|
505
|
-
case d.STOP_PROJECT:
|
|
506
|
-
break;
|
|
507
|
-
case d.ENABLE_TRIGGER:
|
|
508
|
-
this.enableTrigger(t.triggerId);
|
|
509
|
-
break;
|
|
510
|
-
case d.DISABLE_TRIGGER:
|
|
511
|
-
this.disableTrigger(t.triggerId);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
initTriggers() {
|
|
515
|
-
const t = { processAction: this.processAction.bind(this), on: this.on.bind(this), off: this.off.bind(this) };
|
|
516
|
-
let s = null;
|
|
517
|
-
for (const r of this.config.triggers || []) {
|
|
518
|
-
if (Q(r)) {
|
|
519
|
-
const i = this.triggerProcessors.get(r.type);
|
|
520
|
-
i && (s = new i(r, t));
|
|
521
|
-
} else switch (r.type) {
|
|
522
|
-
case l.EVENT:
|
|
523
|
-
s = new pt(r, t);
|
|
524
|
-
break;
|
|
525
|
-
case l.INTERVAL:
|
|
526
|
-
s = new dt(r, t);
|
|
527
|
-
break;
|
|
528
|
-
case l.TIMEOUT:
|
|
529
|
-
s = new ut(r, t);
|
|
530
|
-
}
|
|
531
|
-
s && (this.triggers.set(r.id, s), r.disabled !== !0 && s.enable());
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
cleanupTriggers() {
|
|
535
|
-
for (const t in this.triggers) {
|
|
536
|
-
const s = this.triggers.get(t);
|
|
537
|
-
s && s.disable();
|
|
538
|
-
}
|
|
539
|
-
this.triggers.clear();
|
|
540
|
-
}
|
|
541
|
-
enableTrigger(t) {
|
|
542
|
-
const s = this.triggers.get(t);
|
|
543
|
-
s && (this.emit("enable-trigger", t), s.enable());
|
|
544
|
-
}
|
|
545
|
-
disableTrigger(t) {
|
|
546
|
-
const s = this.triggers.get(t);
|
|
547
|
-
s && (this.emit("disable-trigger", t), s.disable());
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
export {
|
|
551
|
-
pt as EventTrigger,
|
|
552
|
-
Y as FileErrorCode,
|
|
553
|
-
$ as ID_REGEX,
|
|
554
|
-
dt as IntervalTrigger,
|
|
555
|
-
J as MacrosErrorCode,
|
|
556
|
-
wt as Project,
|
|
557
|
-
d as ProjectActionType,
|
|
558
|
-
B as ProjectConfigErrorCode,
|
|
559
|
-
lt as ProjectErrorCode,
|
|
560
|
-
gt as ProjectEvent,
|
|
561
|
-
rt as ProjectSchemaErrorCode,
|
|
562
|
-
ht as ProjectStatus,
|
|
563
|
-
m as ProjectTaskRestartPolicyType,
|
|
564
|
-
f as ProjectTaskStartMode,
|
|
565
|
-
T as ProjectTaskType,
|
|
566
|
-
l as ProjectTriggerType,
|
|
567
|
-
p as RuniumError,
|
|
568
|
-
D as RuniumTask,
|
|
569
|
-
k as RuniumTrigger,
|
|
570
|
-
jt as SILENT_EXIT_CODE,
|
|
571
|
-
st as Task,
|
|
572
|
-
E as TaskEvent,
|
|
573
|
-
h as TaskStatus,
|
|
574
|
-
ut as TimeoutTrigger,
|
|
575
|
-
$t as applyMacros,
|
|
576
|
-
ct as extendProjectSchema,
|
|
577
|
-
at as getProjectSchema,
|
|
578
|
-
Z as isCustomAction,
|
|
579
|
-
Q as isCustomTrigger,
|
|
580
|
-
b as isProcessTaskAction,
|
|
581
|
-
At as isRuniumError,
|
|
582
|
-
O as isToggleTriggerAction,
|
|
583
|
-
_t as readJsonFile,
|
|
584
|
-
et as validateProject,
|
|
585
|
-
It as writeJsonFile
|
|
586
|
-
};
|