@runium/core 0.0.8 → 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/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
- };