@yamanzyan/monitorx 1.0.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.
@@ -0,0 +1,408 @@
1
+ import { BufferList } from "bl";
2
+ import cluster from "node:cluster";
3
+ import { spawn } from "node:child_process";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { MAX_BUFFER, MessageType, MONITORX_PROCESS_STATE_FILE, } from "./protocol.js";
7
+ export class ProcessManager {
8
+ processes = new Map();
9
+ nameToId = new Map();
10
+ idCounter = 0;
11
+ constructor() {
12
+ // Auto-restart cluster workers that crash unexpectedly
13
+ cluster.on("exit", (worker, code, signal) => {
14
+ console.log(`Cluster worker ${worker.id} exited with code ${code} and signal ${signal}`);
15
+ for (const [id, state] of this.processes) {
16
+ if (state.mode === "cluster" && state.workerId === worker.id) {
17
+ if (state.status !== "stopped" && signal !== "SIGTERM" && code !== 0) {
18
+ console.log(`[cluster] worker ${worker.process.pid} crashed (code=${code}), restarting...`);
19
+ const newWorker = this._doFork(state.script, state.cwd);
20
+ if (newWorker) {
21
+ state.child = newWorker.process;
22
+ state.workerId = newWorker.id;
23
+ state.startTime = Date.now();
24
+ this._attachOutputHandlers(state, id);
25
+ this.sync();
26
+ }
27
+ }
28
+ break;
29
+ }
30
+ }
31
+ });
32
+ }
33
+ getIdsByName(name) {
34
+ return this.nameToId.get(name) || [];
35
+ }
36
+ start(proc, cwd, ids, byScript) {
37
+ if (ids && ids.length > 0) {
38
+ const existingProc = this.processes.get(ids[0]) ?? null;
39
+ if (existingProc?.status === "running") {
40
+ this._notify(existingProc, existingProc.id, `Process ${existingProc.id} is already running with PID ${existingProc.child.pid}`);
41
+ }
42
+ else if (existingProc) {
43
+ this.restart(ids);
44
+ }
45
+ else {
46
+ console.error(`No process found for ids: ${ids}`);
47
+ }
48
+ return;
49
+ }
50
+ // For non-byScript starts, check if processes with this name already running
51
+ if (!byScript) {
52
+ const nameIds = this.nameToId.get(proc.name) ?? [];
53
+ const running = nameIds.find((id) => this.processes.get(id)?.status === "running");
54
+ if (running !== undefined) {
55
+ const firstProc = this.processes.get(running);
56
+ this._notify(firstProc, firstProc.id, `"${proc.name}" already running`);
57
+ return;
58
+ }
59
+ }
60
+ const instances = proc.instances ?? 1;
61
+ if (instances > 1) {
62
+ const [, ...scriptArgs] = proc.script.split(" ");
63
+ const rawScript = scriptArgs.join(" ");
64
+ const userScript = path.isAbsolute(rawScript)
65
+ ? rawScript
66
+ : path.resolve(cwd, rawScript);
67
+ cluster.setupPrimary({ exec: userScript, silent: true });
68
+ for (let i = 0; i < instances; i++) {
69
+ this._forkWorker(proc, cwd);
70
+ }
71
+ }
72
+ else {
73
+ this._spawnProcess(proc, cwd);
74
+ }
75
+ }
76
+ _doFork(script, cwd) {
77
+ try {
78
+ const [, ...scriptArgs] = script.split(" ");
79
+ const rawScript = scriptArgs.join(" ");
80
+ const userScript = path.isAbsolute(rawScript)
81
+ ? rawScript
82
+ : path.resolve(cwd, rawScript);
83
+ cluster.setupPrimary({ exec: userScript, silent: true });
84
+ return cluster.fork();
85
+ }
86
+ catch (error) {
87
+ console.error("Failed to fork cluster worker:", error);
88
+ return null;
89
+ }
90
+ }
91
+ _forkWorker(proc, cwd) {
92
+ const worker = cluster.fork();
93
+ const id = ++this.idCounter;
94
+ const state = {
95
+ id,
96
+ child: worker.process,
97
+ buffer: new BufferList(),
98
+ subscribers: new Set(),
99
+ startTime: Date.now(),
100
+ status: "running",
101
+ name: proc.name,
102
+ script: proc.script,
103
+ cwd,
104
+ mode: "cluster",
105
+ instances: proc.instances,
106
+ workerId: worker.id,
107
+ };
108
+ this.processes.set(id, state);
109
+ this.nameToId.set(proc.name, [
110
+ ...(this.nameToId.get(proc.name) || []),
111
+ id,
112
+ ]);
113
+ this._attachOutputHandlers(state, id);
114
+ console.log(`Started cluster worker ${id} (workerId=${worker.id}) with PID ${worker.process.pid}`);
115
+ this.sync();
116
+ }
117
+ _spawnProcess(proc, cwd) {
118
+ const [command, ...args] = proc.script.split(" ");
119
+ let child;
120
+ try {
121
+ child = spawn(command, args, { cwd });
122
+ }
123
+ catch (error) {
124
+ console.error(`Failed to start process ${proc.name}:`, error);
125
+ return;
126
+ }
127
+ const id = ++this.idCounter;
128
+ const state = {
129
+ id,
130
+ child,
131
+ buffer: new BufferList(),
132
+ subscribers: new Set(),
133
+ startTime: Date.now(),
134
+ status: "running",
135
+ name: proc.name,
136
+ script: proc.script,
137
+ cwd,
138
+ mode: "fork",
139
+ };
140
+ this.processes.set(id, state);
141
+ this.nameToId.set(proc.name, [
142
+ ...(this.nameToId.get(proc.name) || []),
143
+ id,
144
+ ]);
145
+ this._attachOutputHandlers(state, id);
146
+ console.log(`Started process ${id} with PID ${child.pid}`);
147
+ this.sync();
148
+ }
149
+ stop(ids) {
150
+ console.log(`Stopping processes with ids: `, ids);
151
+ if (ids.length === 0) {
152
+ console.log("Stopping all processes...");
153
+ this.processes.forEach((state, id) => {
154
+ state.status = "stopped"; // set before kill so cluster exit handler won't restart
155
+ state.child.kill();
156
+ console.log(`Stopped process ${id} with PID ${state.child.pid}`);
157
+ });
158
+ return true;
159
+ }
160
+ for (const id of ids) {
161
+ const state = this.processes.get(id);
162
+ if (!state || state.status !== "running")
163
+ continue;
164
+ state.status = "stopped"; // set before kill
165
+ state.child.kill();
166
+ console.log(`Stopped process ${id} with PID ${state.child.pid}`);
167
+ }
168
+ this.sync();
169
+ return true;
170
+ }
171
+ restart(ids) {
172
+ if (ids.length === 0)
173
+ return false;
174
+ for (const id of ids) {
175
+ const state = this.processes.get(id);
176
+ if (!state)
177
+ continue;
178
+ if (state.status === "running") {
179
+ state.status = "stopped"; // prevent cluster exit handler from auto-restarting
180
+ state.child.kill();
181
+ }
182
+ this._notify(state, id, `Restarting process ${id}...`);
183
+ if (state.mode === "cluster") {
184
+ const worker = this._doFork(state.script, state.cwd);
185
+ if (!worker) {
186
+ state.status = "errored";
187
+ continue;
188
+ }
189
+ state.child = worker.process;
190
+ state.workerId = worker.id;
191
+ }
192
+ else {
193
+ const [command, ...args] = state.script.split(" ");
194
+ let child;
195
+ try {
196
+ child = spawn(command, args, { cwd: state.cwd });
197
+ }
198
+ catch (error) {
199
+ console.error(`Failed to restart process ${id}:`, error);
200
+ state.status = "errored";
201
+ continue;
202
+ }
203
+ state.child = child;
204
+ }
205
+ state.status = "running";
206
+ state.startTime = Date.now();
207
+ this._attachOutputHandlers(state, id);
208
+ console.log(`Restarted process ${id} with PID ${state.child.pid}`);
209
+ }
210
+ this.sync();
211
+ return ids.length > 0;
212
+ }
213
+ subscribe(ids, socket) {
214
+ if (ids.length === 0)
215
+ return null;
216
+ for (const id of ids) {
217
+ const state = this.processes.get(id);
218
+ if (!state)
219
+ return null;
220
+ const history = state.buffer.slice().toString();
221
+ if (history) {
222
+ socket.write(JSON.stringify({ type: MessageType.LOG, id, data: history }));
223
+ }
224
+ state.subscribers.add(socket);
225
+ socket.on("close", () => {
226
+ console.log(`Client disconnected from logs for process ${id}`);
227
+ state.subscribers.delete(socket);
228
+ });
229
+ console.log(`Subscribed to logs for process ${id}`);
230
+ return state;
231
+ }
232
+ }
233
+ list() {
234
+ const list = [];
235
+ this.processes.forEach((state) => {
236
+ const status = state.status === "running"
237
+ ? "Running"
238
+ : state.status === "stopped"
239
+ ? "Stopped"
240
+ : "Errored";
241
+ const { cpu, memory } = this._getProcessResourceUsage(state.child) || {};
242
+ list.push({
243
+ id: state.id,
244
+ name: state.name,
245
+ pid: state.child.pid,
246
+ startTime: state.startTime,
247
+ status,
248
+ mode: state.mode,
249
+ instances: state.instances,
250
+ usage: { cpu, memory },
251
+ });
252
+ });
253
+ return list;
254
+ }
255
+ has(ids) {
256
+ return ids.some((id) => this.processes.has(id));
257
+ }
258
+ killAll() {
259
+ this.processes.forEach((state, id) => {
260
+ console.log(`Killing process ${id} with PID ${state.child.pid}`);
261
+ state.status = "stopped";
262
+ state.child.kill();
263
+ });
264
+ }
265
+ delete(ids) {
266
+ if (ids.length === 0) {
267
+ this.processes.forEach((state) => {
268
+ if (state.status === "running") {
269
+ state.status = "stopped";
270
+ state.child.kill();
271
+ }
272
+ });
273
+ this.processes.clear();
274
+ this.nameToId.clear();
275
+ this.sync();
276
+ this.idCounter = 0;
277
+ return true;
278
+ }
279
+ for (const id of ids) {
280
+ const state = this.processes.get(id);
281
+ if (!state)
282
+ continue;
283
+ if (state.status === "running") {
284
+ state.status = "stopped";
285
+ state.child.kill();
286
+ }
287
+ this.processes.delete(id);
288
+ const nameIds = this.nameToId.get(state.name);
289
+ if (nameIds) {
290
+ const filtered = nameIds.filter((nid) => nid !== id);
291
+ if (filtered.length === 0) {
292
+ this.nameToId.delete(state.name);
293
+ }
294
+ else {
295
+ this.nameToId.set(state.name, filtered);
296
+ }
297
+ }
298
+ console.log(`Deleted process ${id} (${state.name})`);
299
+ this.idCounter = Math.max(this.idCounter - 1, 0);
300
+ }
301
+ this.sync();
302
+ return true;
303
+ }
304
+ sync() {
305
+ const state = Array.from(this.processes.values()).map((proc) => ({
306
+ id: proc.id,
307
+ name: proc.name,
308
+ script: proc.script,
309
+ cwd: proc.cwd,
310
+ status: proc.status,
311
+ startTime: proc.startTime,
312
+ mode: proc.mode,
313
+ instances: proc.instances,
314
+ }));
315
+ try {
316
+ fs.writeFileSync(MONITORX_PROCESS_STATE_FILE, JSON.stringify(state, null, 2));
317
+ }
318
+ catch (error) {
319
+ console.error("Failed to sync process state:", error);
320
+ }
321
+ }
322
+ restore() {
323
+ try {
324
+ if (!fs.existsSync(MONITORX_PROCESS_STATE_FILE))
325
+ return;
326
+ const raw = fs.readFileSync(MONITORX_PROCESS_STATE_FILE, "utf-8");
327
+ const saved = JSON.parse(raw);
328
+ for (const entry of saved) {
329
+ if (entry.status === "running") {
330
+ if (entry.mode === "cluster") {
331
+ const worker = this._doFork(entry.script, entry.cwd);
332
+ if (!worker)
333
+ continue;
334
+ const id = ++this.idCounter;
335
+ const state = {
336
+ id,
337
+ child: worker.process,
338
+ buffer: new BufferList(),
339
+ subscribers: new Set(),
340
+ startTime: Date.now(),
341
+ status: "running",
342
+ name: entry.name,
343
+ script: entry.script,
344
+ cwd: entry.cwd,
345
+ mode: "cluster",
346
+ instances: entry.instances,
347
+ workerId: worker.id,
348
+ };
349
+ this.processes.set(id, state);
350
+ this.nameToId.set(entry.name, [
351
+ ...(this.nameToId.get(entry.name) || []),
352
+ id,
353
+ ]);
354
+ this._attachOutputHandlers(state, id);
355
+ }
356
+ else {
357
+ this._spawnProcess({ name: entry.name, script: entry.script }, entry.cwd);
358
+ }
359
+ }
360
+ }
361
+ console.log(`Restored ${saved.filter((e) => e.status === "running").length} processes from state file`);
362
+ }
363
+ catch (error) {
364
+ console.error("Failed to restore process state:", error);
365
+ }
366
+ }
367
+ _notify(state, id, msg) {
368
+ const formatted = `[monitorx] ${msg}\n`;
369
+ state.buffer.append(Buffer.from(formatted));
370
+ for (const sub of state.subscribers) {
371
+ sub.write(JSON.stringify({ type: MessageType.LOG, id, data: formatted }));
372
+ }
373
+ console.log(msg);
374
+ }
375
+ _attachOutputHandlers(state, id) {
376
+ const handleOutput = (data) => {
377
+ state.buffer.append(data);
378
+ if (state.buffer.length > MAX_BUFFER) {
379
+ state.buffer.consume(state.buffer.length - MAX_BUFFER);
380
+ }
381
+ const line = data.toString();
382
+ for (const sub of state.subscribers) {
383
+ sub.write(JSON.stringify({ type: MessageType.LOG, id, data: line }));
384
+ }
385
+ };
386
+ state.child.stdout?.on("data", handleOutput);
387
+ state.child.stderr?.on("data", handleOutput);
388
+ }
389
+ _getProcessResourceUsage(child) {
390
+ if (typeof child.pid !== "number")
391
+ return null;
392
+ try {
393
+ const usage = process.resourceUsage();
394
+ const memory = usage
395
+ ? `${Math.round(usage.maxRSS / 1024 / 1024)} MB`
396
+ : undefined;
397
+ const cpu = usage
398
+ ? `${((usage.userCPUTime + usage.systemCPUTime) / 1000).toFixed(2).toString()}s`
399
+ : undefined;
400
+ return { cpu, memory };
401
+ }
402
+ catch (error) {
403
+ console.error(`Failed to get resource usage for PID ${child.pid}:`, error);
404
+ return null;
405
+ }
406
+ }
407
+ }
408
+ //# sourceMappingURL=process-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../src/process-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ export declare const MONITORX_PATH: string;
2
+ export declare const MONITORX_PROCESS_STATE_FILE: string;
3
+ export declare const SOCKET_PATH: string;
4
+ export declare const MAX_BUFFER: number;
5
+ export declare const SCRIPT_SERVER = "server";
6
+ export declare const MessageType: {
7
+ readonly START: "start";
8
+ readonly STOP: "stop";
9
+ readonly RESTART: "restart";
10
+ readonly DELETE: "delete";
11
+ readonly LOGS: "logs";
12
+ readonly LS: "ls";
13
+ readonly LIST: "list";
14
+ readonly LOG: "log";
15
+ readonly ERROR: "error";
16
+ };
17
+ export type MessageTypeValue = (typeof MessageType)[keyof typeof MessageType];
18
+ export interface ProcessConfig {
19
+ name: string;
20
+ script: string;
21
+ ids?: number[];
22
+ instances?: number;
23
+ }
24
+ export interface StartMessage {
25
+ type: typeof MessageType.START;
26
+ processes: ProcessConfig[];
27
+ cwd: string;
28
+ ids: number[];
29
+ byScript?: boolean;
30
+ name?: string;
31
+ }
32
+ export interface StopMessage {
33
+ type: typeof MessageType.STOP;
34
+ ids: number[];
35
+ }
36
+ export interface RestartMessage {
37
+ type: typeof MessageType.RESTART;
38
+ ids: number[];
39
+ }
40
+ export interface DeleteMessage {
41
+ type: typeof MessageType.DELETE;
42
+ ids: number[];
43
+ }
44
+ export interface LogsMessage {
45
+ type: typeof MessageType.LOGS;
46
+ ids: number[];
47
+ }
48
+ export interface LsMessage {
49
+ type: typeof MessageType.LS;
50
+ ids?: number[];
51
+ }
52
+ export interface LogMessage {
53
+ type: typeof MessageType.LOG;
54
+ name: string;
55
+ data: string;
56
+ }
57
+ export interface ErrorMessage {
58
+ type: typeof MessageType.ERROR;
59
+ message: string;
60
+ }
61
+ export interface LsResponseMessage {
62
+ type: typeof MessageType.LS;
63
+ data: LsMessageData[];
64
+ }
65
+ export type DaemonMessage = StartMessage | StopMessage | RestartMessage | DeleteMessage | LogsMessage | LsMessage;
66
+ export type ResponseMessage = LogMessage | ErrorMessage | LsResponseMessage;
67
+ export interface LsMessageData {
68
+ id: number;
69
+ name: string;
70
+ pid: number | undefined;
71
+ startTime?: number;
72
+ status: string;
73
+ mode: "fork" | "cluster";
74
+ instances?: number;
75
+ usage?: {
76
+ cpu: string | undefined;
77
+ memory: string | undefined;
78
+ };
79
+ }
@@ -0,0 +1,19 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ export const MONITORX_PATH = path.join(os.homedir(), ".monitorx");
4
+ export const MONITORX_PROCESS_STATE_FILE = `${MONITORX_PATH}/process_state.json`;
5
+ export const SOCKET_PATH = `${MONITORX_PATH}/daemon.sock`;
6
+ export const MAX_BUFFER = 64 * 1024; // 64 KB ring buffer per process
7
+ export const SCRIPT_SERVER = "server";
8
+ export const MessageType = {
9
+ START: "start",
10
+ STOP: "stop",
11
+ RESTART: "restart",
12
+ DELETE: "delete",
13
+ LOGS: "logs",
14
+ LS: "ls",
15
+ LIST: "list",
16
+ LOG: "log",
17
+ ERROR: "error",
18
+ };
19
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAElE,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,aAAa,qBAAqB,CAAC;AAEjF,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,aAAa,cAAc,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,gCAAgC;AAErE,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AACtC,MAAM,CAAC,MAAM,WAAW,GAAG;IAC1B,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,EAAE,EAAE,IAAI;IACR,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;CACL,CAAC"}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@yamanzyan/monitorx",
3
+ "version": "1.0.0",
4
+ "description": "A lightweight Node.js process manager with cluster support",
5
+ "main": "dist/cli.js",
6
+ "module": "dist/cli.js",
7
+ "types": "dist/cli.d.ts",
8
+ "type": "module",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "scripts": {
13
+ "build": "node scripts/clean-dist.mjs && tsc && chmod +x dist/cli.js dist/daemon.js",
14
+ "check-types": "tsc --noEmit",
15
+ "start": "node dist/cli.js",
16
+ "dev": "tsc --watch",
17
+ "daemon-dev": "nodemon dist/daemon.js",
18
+ "postinstall": "node scripts/postinstall.mjs",
19
+ "prepare": "npm run build",
20
+ "preuninstall": "monitorx stop",
21
+ "pub": "npm run build && npm publish",
22
+ "test": "npm run check-types",
23
+ "format": "prettier --write ."
24
+ },
25
+ "bin": {
26
+ "monitorx": "./dist/cli.js",
27
+ "monitorx-daemon": "./dist/daemon.js"
28
+ },
29
+ "keywords": [
30
+ "process manager",
31
+ "nodejs",
32
+ "cluster",
33
+ "daemon"
34
+ ],
35
+ "author": {
36
+ "name": "Yaman Jain",
37
+ "url": "https://github.com/yaman-694"
38
+ },
39
+ "license": "MIT",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/yaman-694/monitorx.git",
43
+ "directory": "."
44
+ },
45
+ "bugs": {
46
+ "url": "https://github.com/yaman-694/monitorx/issues"
47
+ },
48
+ "files": [
49
+ "dist/**/*",
50
+ "scripts/clean-dist.mjs",
51
+ "scripts/postinstall.mjs",
52
+ "README.md",
53
+ "package.json"
54
+ ],
55
+ "engines": {
56
+ "node": ">=18.0.0"
57
+ },
58
+ "dependencies": {
59
+ "bl": "^7.0.2",
60
+ "cli-table3": "^0.6.5",
61
+ "omnilogs": "^1.1.0"
62
+ },
63
+ "devDependencies": {
64
+ "@types/bl": "^5.1.0",
65
+ "@types/node": "^20.11.0",
66
+ "typescript": "^5.4.0",
67
+ "nodemon": "^3.1.14",
68
+ "prettier": "^3.6.2"
69
+ }
70
+ }
@@ -0,0 +1,7 @@
1
+ import { rmSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ const root = dirname(dirname(fileURLToPath(import.meta.url)));
6
+
7
+ rmSync(join(root, "dist"), { recursive: true, force: true });
@@ -0,0 +1,18 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const root = dirname(dirname(fileURLToPath(import.meta.url)));
7
+ const daemonEntry = join(root, "dist", "daemon.js");
8
+
9
+ if (!existsSync(daemonEntry)) {
10
+ process.exit(0);
11
+ }
12
+
13
+ const child = spawn(process.execPath, [daemonEntry, "--daemonize"], {
14
+ detached: true,
15
+ stdio: "ignore",
16
+ });
17
+
18
+ child.unref();