@zuzjs/pm 0.0.26 → 0.0.27

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,6 @@
1
+ import C from'path';import {fileURLToPath}from'url';import y from'os';import g from'picocolors';import c from'winston';import D from'events';import w from'fs';import W from'net';var I=()=>fileURLToPath(import.meta.url),N=()=>C.dirname(I()),p=N();var R=(s=>(s.Fork="fork",s.Cluster="cluster",s))(R||{}),L=(o=>(o.Stopped="stopped",o.Starting="starting",o.Running="running",o.Stopping="stopping",o.Crashed="crashed",o.Errored="errored",o))(L||{});var F=C.join(y.homedir(),".zpm","logs"),J=c.format.combine(c.format.timestamp({format:"YYYY/MM/DD HH:mm:ss"}),c.format.splat(),c.format.printf(({timestamp:e,level:r,message:s,tag:t})=>{let n=g.gray(`[${e}]`),m=g.bold(`[ZPM/${(t||"SYS").toUpperCase()}]`);return `${n} [${r=="info"?g.cyan(r):r=="warn"?g.yellow(r):r=="error"?g.red(r):r=="success"?g.green(r):r=="debug"?g.gray(r):"debug"}] ${m} \u2192 ${s}`})),u=c.createLogger({levels:{error:0,warn:1,info:2,success:2,debug:3},transports:[new c.transports.Console({level:"debug",format:J}),new c.transports.File({filename:C.join(F,"daemon.log"),format:c.format.combine(c.format.timestamp(),c.format.json())})]}),l={info:(e,...r)=>u.info(r.join(" "),{tag:e}),warn:(e,...r)=>u.warn(r.join(" "),{tag:e}),error:(e,...r)=>u.error(r.join(" "),{tag:e}),debug:(e,...r)=>u.debug(r.join(" "),{tag:e}),success:(e,...r)=>u.log("success",r.join(" "),{tag:e})};var k=class extends D{map=new Map;set(r,s){this.map.set(r,s),this.emit("change",r,s);}get(r){return this.map.get(r)}has(r){return this.map.has(r)}delete(r){this.map.delete(r),this.emit("delete",r);}all(){return new Map(this.map)}onchange(r){return this.on("change",r)}offchange(r){return this.off("change",r)}},P=new k;function O(e="zuz-pm"){return y.platform()==="win32"?C.join("\\\\.\\pipe",e):C.join(y.tmpdir(),`${e}.sock`)}function ar(e){let r=O();w.existsSync(r)&&w.unlinkSync(r);let s=W.createServer(t=>{let n="";t.on("data",m=>{n+=m.toString();let o=n.split(`
2
+ `);n=o.pop()??"";for(let d of o)d.trim()&&E(e,t,d);}),t.on("error",m=>{l.error("IPC","Socket error:",m.message);});});return s.listen(r,()=>{if(y.platform()!=="win32")try{w.chmodSync(r,"777");}catch(t){console.error("Failed to set socket permissions:",t);}l.success("IPC",`Listening on ${r}`);}),s.on("error",t=>{l.error("IPC","Server error:",t);}),s}async function E(e,r,s){let t;try{t=JSON.parse(s);}catch{S(r,{ok:false,error:"Invalid JSON"});return}try{let n=null;switch(t.cmd){case "ping":n="pong";break;case "start":await e.start(t.config),n=`Started "${t.name}"`;break;case "stop":await e.stop(t.name),n=`Stopped "${t.name}"`;break;case "restart":await e.restart(t.name),n=`Restarted "${t.name}"`;break;case "delete":await e.delete(t.name),n=`Deleted "${t.name}"`;break;case "stats":n=await e.getStats(t.name);break;case "list":n=e.list();break;case "add-worker":await e.addWorker(t.config,t.autoStart),n=`Added "${t.config.name}"`;break;case "find-worker":n=e.getWorker(t.name);break;case "get-store":{n=Array.from(P.all()).map(([i,a])=>({name:i,status:a.status,childrenCount:a.children.length,restartCount:a.restartCount,backoffTime:a.backoffTime,isRestarting:a.isRestarting,probeFailures:a.probeFailures}));break}case "logs":let m=t.name,o=[];if(m){let i=e.getWorker(m);if(!i){r.write(JSON.stringify({ok:!1,error:`Worker "${m}" not found`})+`
3
+ `);return}o.push(i);}else {let i=e.list();for(let a of i){let f=e.getWorker(a);f&&o.push(f);}}if(o.length===0){r.write(JSON.stringify({ok:!1,error:"No active workers to stream logs from"})+`
4
+ `);return}let d=[];for(let i of o){let a=i.mp();for(let f of a.children){let b=x=>{let $=m?"":`[${i.name}] `;r.write(JSON.stringify({ok:!0,data:`${$}${x.toString()}`})+`
5
+ `);};f.stdout?.on("data",b),f.stderr?.on("data",b),d.push({child:f,onData:b});}}r.on("close",()=>{for(let{child:i,onData:a}of d)i.stdout?.off("data",a),i.stderr?.off("data",a);});break;default:l.error("ZPM",`Unknown command: ${t.cmd}`);}S(r,{ok:!0,data:n});}catch(n){S(r,{ok:false,error:String(n.message??n)});}}function S(e,r){e.writable&&e.write(JSON.stringify(r)+`
6
+ `);}export{p as a,R as b,L as c,l as d,P as e,O as f,ar as g};
@@ -0,0 +1,2 @@
1
+ import {d,e}from'./chunk-5NYRGZXX.js';import {execSync,spawn,exec}from'child_process';import E from'http';import _ from'https';import I from'net';import L from'chokidar';import f from'fs';import C from'os';import c from'path';import g from'picocolors';import T from'ws';import B from'pidusage';function R(a,t){return new Promise(e=>{let i=(a.startsWith("https")?_:E).get(a,{timeout:t},o=>{e((o.statusCode??500)<500);});i.on("error",()=>e(false)),i.on("timeout",()=>{i.destroy(),e(false);});})}function M(a,t){let[e,s]=a.split(":"),i=Number(s);return new Promise(o=>{let n=I.createConnection({host:e,port:i},()=>{n.destroy(),o(true);});n.setTimeout(t),n.on("timeout",()=>{n.destroy(),o(false);}),n.on("error",()=>o(false));})}function N(a,t){return new Promise(e=>{let s=setTimeout(()=>e(false),t);exec(a,i=>{clearTimeout(s),e(!i);});})}async function k(a){let t=(a.timeoutSeconds??5)*1e3;switch(a.type){case "http":return R(a.target,t);case "tcp":return M(a.target,t);case "exec":return N(a.target,t);default:return false}}var j=5e3,H=16e3,w=1e3,q=5e3;async function K(a){return new Promise(t=>{I.createServer().once("error",()=>t(false)).once("listening",function(){this.close(()=>t(true));}).listen(a);})}async function U(a){if(await K(a))return;let t=C.platform()==="darwin"?`lsof -ti :${a} | xargs kill -9 2>/dev/null || true`:`fuser -k -9 ${a}/tcp 2>/dev/null; true`;await new Promise(e=>exec(t,()=>e())),await new Promise(e=>setTimeout(e,800));}async function J(a,t){let e=a.process?.pid??a.pid;if(e)return new Promise(s=>{let i=false,o=()=>{i||(i=true,clearTimeout(n),s());};a.once?.("exit",o),a.once?.("exit",o);try{process.kill(e,"SIGTERM");}catch{return o()}let n=setTimeout(()=>{try{process.kill(e,"SIGKILL"),setTimeout(o,100);}catch{o();}},t),l=setInterval(()=>{try{process.kill(e,0);}catch{clearInterval(l),o();}},500);})}var p=class{cfg;name;watcher=null;isBuilding=false;constructor(t){this.cfg={mode:"fork",instances:1,...t},this.name=t.name,this.initStore();}getConfig(){return this.cfg}async start(){let t=this.mp();if(t.status==="running"||t.status==="starting"){d.warn(this.name,"Already running \u2013 ignoring start()");return}this.patch({status:"starting",isRestarting:false,children:[],restartCount:0,backoffTime:w,probeFailures:0,startTime:null}),this.clearTimers(),this.stopProbe(),d.info(this.name,"Initializing fresh start...");try{await this.spawnAll(),this.cfg.devMode&&this.watchFiles();}catch(e){this.patch({status:"errored"}),d.error(this.name,`Start failed: ${e.message}`);}}async stop(){let t=this.mp();if(t.status==="stopping"){d.info(this.name,"Already stopping...");return}this.patch({status:"stopping",isRestarting:false}),d.info(this.name,`Stopping ${t.children.length} instances...`),this.clearTimers(),this.stopProbe(),this.stopWatcher();try{await Promise.race([Promise.all(t.children.map(e=>J(e,this.cfg.killTimeout??j))),new Promise((e,s)=>setTimeout(()=>s(new Error("Termination timeout")),1e4))]);}catch(e){d.error(this.name,`Stop timed out, forcing state reset: ${e.message||"UNKNOWN"}`);}this.patch({children:[],status:"stopped",startTime:null}),this.stopWatcher(),d.success(this.name,"Stopped.");}async restart(){await this.stop(),await this.start();}async getStats(){let t=this.mp(),e=t.children[0]?.pid??null,s=null,i=null,o=null;if(e&&t.status==="running")try{let n=await B(e);s=n.cpu,i=n.memory;}catch{}return {name:this.name,status:t.status,pid:e,uptime:t.startTime?Date.now()-t.startTime:null,restartCount:t.restartCount,cpu:s,memoryRss:i,memoryHeap:o,mode:this.cfg.mode??"fork",instances:t.children.length}}async spawnAll(){if(!f.existsSync(this.cfg.scriptPath)){d.error(this.name,`Script not found: ${this.cfg.scriptPath}. Waiting for build...`),this.patch({status:"errored"});return}this.cfg.port&&await U(this.cfg.port);let t=this.cfg.mode??"fork",e=t==="cluster"?this.cfg.instances??C.cpus().length:1,s=[];for(let o=0;o<e;o++){let n=this.forkChild();n&&s.push(n);}if(s.length===0){d.error(this.name,"Failed to spawn any instances."),this.patch({status:"stopped"});return}this.patch({children:s,startTime:Date.now(),status:"running"}),d.success(this.name,`Started ${s.length} instance(s) [${t}]`);let i=setTimeout(()=>{this.mp().status==="running"&&(this.patch({backoffTime:w,restartCount:0}),d.success(this.name,"Process is stable."));},q);this.patch({stabilityTimer:i}),this.cfg.probe&&this.startProbe();}forkChild(){try{let t=this.cfg.scriptPath.endsWith(".js"),e=c.isAbsolute(this.cfg.scriptPath),s,i,o;t?(s=process.execPath,i=[this.cfg.scriptPath,...this.cfg.args??[]],o=c.dirname(c.resolve(this.cfg.scriptPath,".."))):(s=this.cfg.scriptPath,i=[...this.cfg.args??[]],o=e?c.dirname(this.cfg.scriptPath):process.cwd());let n={cwd:o,stdio:["ignore","pipe","pipe"],env:{...process.env,...this.cfg.env??{},NODE_ENV:this.cfg.devMode?"development":"production",PATH:`${c.resolve(process.cwd(),"node_modules/.bin")}${c.delimiter}${process.env.PATH}`},detached:!1,shell:!t};if(process.getuid&&process.getuid()===0&&this.cfg.user)try{let m=parseInt(execSync(`id -u ${this.cfg.user}`).toString().trim()),d$1=parseInt(execSync(`id -g ${this.cfg.user}`).toString().trim());n.uid=m,n.gid=d$1,d.info(this.name,`Setting privileges to user: ${this.cfg.user} (uid: ${m})`);}catch{d.error(this.name,`Failed to resolve user "${this.cfg.user}". Running as root!`);}let l=spawn(s,i,n);this.setupLogging(l);let h=Date.now();return l.on("error",m=>{d.error(this.name,`Spawn error (${s}):`,m.message);}),l.on("exit",(m,d)=>{let x=Date.now()-h;this.onChildExit(l,m,d,x);}),l}catch(t){return d.error(this.name,"Failed to fork child:",t.message),null}}_forkChild(){try{let t=this.cfg.scriptPath.endsWith(".js")?"node":this.cfg.scriptPath,e=this.cfg.scriptPath.endsWith(".js")?[this.cfg.scriptPath,...this.cfg.args??[]]:[...this.cfg.args??[]],s=spawn(t,e,{cwd:c.dirname(c.resolve(this.cfg.scriptPath,"..")),stdio:["ignore","pipe","pipe"],env:{...process.env,...this.cfg.env??{},NODE_ENV:this.cfg.devMode?"development":"production"},detached:!1,shell:!1});this.setupLogging(s);let i=Date.now();return s.on("error",o=>{d.error(this.name,"Spawn error:",o);}),s.on("exit",(o,n)=>{let l=Date.now()-i;this.onChildExit(s,o,n,l);}),s}catch(t){return d.error(this.name,"Failed to fork child:",t),null}}onChildExit(t,e,s,i){let o=this.mp(),n=o.children.filter(l=>l!==t);if(this.patch({children:n}),o.isRestarting){n.length===0?(d.info(this.name,"All instances stopped. Spawning new ones..."),this.patch({isRestarting:false}),this.spawnAll()):d.info(this.name,`Restart in progress... waiting for ${n.length} instance(s) to stop.`);return}if(o.status==="stopping"){n.length===0?(d.info(this.name,"All instances dead. Spawning new ones..."),this.patch({isRestarting:false}),this.spawnAll()):d.info(this.name,`Stop in progress... waiting for ${n.length} instance(s) to stop.`);return}d.warn(this.name,`Process exited (code=${e}, signal=${s}, uptime=${i}ms)`),e!==0&&e!==null&&(this.patch({status:"crashed"}),i<1500&&d.error(this.name,`Immediate crash (${i}ms) \u2013 likely a syntax/build error. Waiting for next file change.`),this.scheduleRestart());}scheduleRestart(){let t=this.mp(),e=t.backoffTime,s=this.cfg.maxBackoff??H;d.warn(this.name,`Scheduling restart in ${e}ms (attempt #${t.restartCount+1})`);let i=setTimeout(async()=>{this.patch({restartCount:t.restartCount+1,backoffTime:Math.min(e*2,s)}),await this.spawnAll();},e);this.patch({restartTimer:i});}startProbe(){let t=this.cfg.probe,e=(t.intervalSeconds??10)*1e3,s=t.failureThreshold??3,o=setInterval(async()=>{let n=this.mp();if(n.status!=="running")return;if(await k(t)){n.probeFailures>0&&this.patch({probeFailures:0});return}let h=n.probeFailures+1;this.patch({probeFailures:h}),d.warn(this.name,`Liveness probe failed (${h}/${s})`),h>=s&&(d.error(this.name,"Liveness probe threshold exceeded \u2013 restarting."),this.patch({probeFailures:0}),await this.restart());},e);this.patch({probeTimer:o});}stopProbe(){let{probeTimer:t}=this.mp();t&&(clearInterval(t),this.patch({probeTimer:null,probeFailures:0}));}findProjectRoot(t){let e=c.resolve(t);for(f.existsSync(e)&&f.statSync(e).isFile()&&(e=c.dirname(e));e!==c.parse(e).root;){if(f.existsSync(c.join(e,"package.json")))return e;e=c.dirname(e);}return process.cwd()}watchFiles(){this.stopWatcher();let t=this.findProjectRoot(this.cfg.scriptPath),e=c.resolve(t,"src");d.info(this.name,g.gray(`Watcher active on: ${e}`)),this.watcher=L.watch(e,{ignored:[/node_modules/,/\.pid$/],persistent:true,ignoreInitial:true,awaitWriteFinish:{stabilityThreshold:1500,pollInterval:500}}),this.watcher.on("all",async(s,i)=>{if(!this.isBuilding&&(s==="change"||s==="add"))if(d.info(this.name,g.yellow(`File ${s}: ${c.basename(i)} \u2013 restarting`)),this.cfg.reloadCommand){this.isBuilding=true,d.info(this.name,g.blue(`Executing: ${this.cfg.reloadCommand}`));let{exec:o}=await import('child_process');o(this.cfg.reloadCommand,{cwd:t,env:{...process.env,PATH:`${c.resolve(t,"node_modules/.bin")}${c.delimiter}${process.env.PATH}`}},(n,l,h)=>{if(this.isBuilding=false,n){d.error(this.name,`Build Failed:
2
+ ${h||l||n.message}`);return}d.success(this.name,"Build successful. Triggering restart..."),this.restart();});}else this.restart();}),this.watcher.on("error",s=>d.error(this.name,"Watcher error:",s)),this.watcher.on("ready",()=>d.info(this.name,`Watching ${t}`));}stopWatcher(){this.watcher&&(this.watcher.close(),this.watcher=null);}initStore(){e.set(this.name,{config:this.cfg,children:[],status:"stopped",startTime:null,restartCount:0,backoffTime:w,restartTimer:null,stabilityTimer:null,probeTimer:null,probeFailures:0,isRestarting:false});}mp(){return e.get(this.name)}_patch(t){e.set(this.name,{...this.mp(),...t});}patch(t){let e$1=this.mp();t.status&&t.status!==e$1.status&&d.info(this.name,`[STATE] ${e$1.status} \u2794 ${t.status}${t.isRestarting?" (Restarting)":""}`),t.lastError&&d.error(this.name,`[REASON] ${t.lastError}`),e.set(this.name,{...e$1,...t});}clearTimers(){let{restartTimer:t,stabilityTimer:e}=this.mp();t&&clearTimeout(t),e&&clearTimeout(e),this.patch({restartTimer:null,stabilityTimer:null});}setupLogging(t){let e=this.cfg.logs?.wsUrl,s=null;e&&(s=new T(e),s.on("open",()=>d.debug(this.name,"Connected to log collector")),s.on("error",o=>d.error(this.name,"Log Collector WS Error",o.message)));let i=o=>{let n=o.toString();this.cfg.devMode&&process.stdout.write(`[${this.name}] ${n}`),s&&s.readyState===T.OPEN&&s.send(JSON.stringify({app:this.name,timestamp:Date.now(),log:n}));};t.stdout?.on("data",i),t.stderr?.on("data",i);}};var F=class{workers=new Map;SNAPSHOT_FILE=c.join(C.homedir(),".zpm","snapshot.json");async start(t){let e$1=this.workers.get(t.name);if(e$1){let i=e.get(t.name);if(i?.status==="stopped"||i?.status==="crashed"||i?.status==="errored"){d.info("ZPM",`Resuming existing worker "${t.name}"`),await e$1.start();return}d.warn("ZPM",`Worker "${g.cyan(t.name)}" is ${g.cyan(i?.status)} - use restart()`);return}let s=new p(t);this.workers.set(t.name,s),await s.start(),this.saveSnapshot();}async stop(t){let e=this.require(t);e&&(await e.stop(),this.saveSnapshot());}async restart(t){let e=this.require(t);e&&(await e.restart(),this.saveSnapshot());}async delete(t){let e$1=this.require(t);e$1&&(await e$1.stop(),this.workers.delete(t),e.delete(t),this.saveSnapshot(),d.info("PM",`Deleted worker "${t}"`));}async getStats(t){if(t){let s=this.require(t);return s?[await s.getStats()]:[]}return await Promise.all([...this.workers.values()].map(s=>s.getStats()))}list(){return [...this.workers.keys()]}getAllConfigs(){return Array.from(this.workers.values()).map(t=>t.getConfig())}async stopAll(){d.info("PM","Stopping all workers..."),await Promise.all([...this.workers.values()].map(t=>t.stop())),d.info("PM","All workers stopped."),this.saveSnapshot();}getWorker(t){let e=this.workers.get(t);return e||(d.error(t,"Worker Not Found"),null)}async addWorker(t,e){let s=new p(t);this.workers.set(t.name,s),e&&await s.start(),this.saveSnapshot();}require(t){let e=this.workers.get(t);return e||(d.error(t,"Worker Not Found"),null)}saveSnapshot(){try{let t=c.dirname(this.SNAPSHOT_FILE);f.existsSync(t)||f.mkdirSync(t,{recursive:!0});let e=this.getAllConfigs();f.writeFileSync(this.SNAPSHOT_FILE,JSON.stringify(e,null,2)),d.info("daemon",`Saved snapshot of ${e.length} workers.`);}catch(t){d.error("daemon","Failed to save snapshot:",t.message);}}};export{k as a,p as b,F as c};
@@ -0,0 +1,3 @@
1
+ 'use strict';var chunkWPWZGJN5_cjs=require('./chunk-WPWZGJN5.cjs'),child_process=require('child_process'),A=require('http'),E=require('https'),_=require('net'),N=require('chokidar'),f=require('fs'),T=require('os'),c=require('path'),g=require('picocolors'),y=require('ws'),O=require('pidusage');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var A__default=/*#__PURE__*/_interopDefault(A);var E__default=/*#__PURE__*/_interopDefault(E);var ___default=/*#__PURE__*/_interopDefault(_);var N__default=/*#__PURE__*/_interopDefault(N);var f__default=/*#__PURE__*/_interopDefault(f);var T__default=/*#__PURE__*/_interopDefault(T);var c__default=/*#__PURE__*/_interopDefault(c);var g__default=/*#__PURE__*/_interopDefault(g);var y__default=/*#__PURE__*/_interopDefault(y);var O__default=/*#__PURE__*/_interopDefault(O);/* ZuzJS Process Manager */
2
+ function I(a,t){return new Promise(e=>{let i=(a.startsWith("https")?E__default.default:A__default.default).get(a,{timeout:t},o=>{e((o.statusCode??500)<500);});i.on("error",()=>e(false)),i.on("timeout",()=>{i.destroy(),e(false);});})}function R(a,t){let[e,s]=a.split(":"),i=Number(s);return new Promise(o=>{let n=___default.default.createConnection({host:e,port:i},()=>{n.destroy(),o(true);});n.setTimeout(t),n.on("timeout",()=>{n.destroy(),o(false);}),n.on("error",()=>o(false));})}function M(a,t){return new Promise(e=>{let s=setTimeout(()=>e(false),t);child_process.exec(a,i=>{clearTimeout(s),e(!i);});})}async function P(a){let t=(a.timeoutSeconds??5)*1e3;switch(a.type){case "http":return I(a.target,t);case "tcp":return R(a.target,t);case "exec":return M(a.target,t);default:return false}}var B=5e3,j=16e3,w=1e3,H=5e3;async function q(a){return new Promise(t=>{___default.default.createServer().once("error",()=>t(false)).once("listening",function(){this.close(()=>t(true));}).listen(a);})}async function K(a){if(await q(a))return;let t=T__default.default.platform()==="darwin"?`lsof -ti :${a} | xargs kill -9 2>/dev/null || true`:`fuser -k -9 ${a}/tcp 2>/dev/null; true`;await new Promise(e=>child_process.exec(t,()=>e())),await new Promise(e=>setTimeout(e,800));}async function U(a,t){let e=a.process?.pid??a.pid;if(e)return new Promise(s=>{let i=false,o=()=>{i||(i=true,clearTimeout(n),s());};a.once?.("exit",o),a.once?.("exit",o);try{process.kill(e,"SIGTERM");}catch{return o()}let n=setTimeout(()=>{try{process.kill(e,"SIGKILL"),setTimeout(o,100);}catch{o();}},t),l=setInterval(()=>{try{process.kill(e,0);}catch{clearInterval(l),o();}},500);})}var p=class{cfg;name;watcher=null;isBuilding=false;constructor(t){this.cfg={mode:"fork",instances:1,...t},this.name=t.name,this.initStore();}getConfig(){return this.cfg}async start(){let t=this.mp();if(t.status==="running"||t.status==="starting"){chunkWPWZGJN5_cjs.d.warn(this.name,"Already running \u2013 ignoring start()");return}this.patch({status:"starting",isRestarting:false,children:[],restartCount:0,backoffTime:w,probeFailures:0,startTime:null}),this.clearTimers(),this.stopProbe(),chunkWPWZGJN5_cjs.d.info(this.name,"Initializing fresh start...");try{await this.spawnAll(),this.cfg.devMode&&this.watchFiles();}catch(e){this.patch({status:"errored"}),chunkWPWZGJN5_cjs.d.error(this.name,`Start failed: ${e.message}`);}}async stop(){let t=this.mp();if(t.status==="stopping"){chunkWPWZGJN5_cjs.d.info(this.name,"Already stopping...");return}this.patch({status:"stopping",isRestarting:false}),chunkWPWZGJN5_cjs.d.info(this.name,`Stopping ${t.children.length} instances...`),this.clearTimers(),this.stopProbe(),this.stopWatcher();try{await Promise.race([Promise.all(t.children.map(e=>U(e,this.cfg.killTimeout??B))),new Promise((e,s)=>setTimeout(()=>s(new Error("Termination timeout")),1e4))]);}catch(e){chunkWPWZGJN5_cjs.d.error(this.name,`Stop timed out, forcing state reset: ${e.message||"UNKNOWN"}`);}this.patch({children:[],status:"stopped",startTime:null}),this.stopWatcher(),chunkWPWZGJN5_cjs.d.success(this.name,"Stopped.");}async restart(){await this.stop(),await this.start();}async getStats(){let t=this.mp(),e=t.children[0]?.pid??null,s=null,i=null,o=null;if(e&&t.status==="running")try{let n=await O__default.default(e);s=n.cpu,i=n.memory;}catch{}return {name:this.name,status:t.status,pid:e,uptime:t.startTime?Date.now()-t.startTime:null,restartCount:t.restartCount,cpu:s,memoryRss:i,memoryHeap:o,mode:this.cfg.mode??"fork",instances:t.children.length}}async spawnAll(){if(!f__default.default.existsSync(this.cfg.scriptPath)){chunkWPWZGJN5_cjs.d.error(this.name,`Script not found: ${this.cfg.scriptPath}. Waiting for build...`),this.patch({status:"errored"});return}this.cfg.port&&await K(this.cfg.port);let t=this.cfg.mode??"fork",e=t==="cluster"?this.cfg.instances??T__default.default.cpus().length:1,s=[];for(let o=0;o<e;o++){let n=this.forkChild();n&&s.push(n);}if(s.length===0){chunkWPWZGJN5_cjs.d.error(this.name,"Failed to spawn any instances."),this.patch({status:"stopped"});return}this.patch({children:s,startTime:Date.now(),status:"running"}),chunkWPWZGJN5_cjs.d.success(this.name,`Started ${s.length} instance(s) [${t}]`);let i=setTimeout(()=>{this.mp().status==="running"&&(this.patch({backoffTime:w,restartCount:0}),chunkWPWZGJN5_cjs.d.success(this.name,"Process is stable."));},H);this.patch({stabilityTimer:i}),this.cfg.probe&&this.startProbe();}forkChild(){try{let t=this.cfg.scriptPath.endsWith(".js"),e=c__default.default.isAbsolute(this.cfg.scriptPath),s,i,o;t?(s=process.execPath,i=[this.cfg.scriptPath,...this.cfg.args??[]],o=c__default.default.dirname(c__default.default.resolve(this.cfg.scriptPath,".."))):(s=this.cfg.scriptPath,i=[...this.cfg.args??[]],o=e?c__default.default.dirname(this.cfg.scriptPath):process.cwd());let n={cwd:o,stdio:["ignore","pipe","pipe"],env:{...process.env,...this.cfg.env??{},NODE_ENV:this.cfg.devMode?"development":"production",PATH:`${c__default.default.resolve(process.cwd(),"node_modules/.bin")}${c__default.default.delimiter}${process.env.PATH}`},detached:!1,shell:!t};if(process.getuid&&process.getuid()===0&&this.cfg.user)try{let m=parseInt(child_process.execSync(`id -u ${this.cfg.user}`).toString().trim()),d=parseInt(child_process.execSync(`id -g ${this.cfg.user}`).toString().trim());n.uid=m,n.gid=d,chunkWPWZGJN5_cjs.d.info(this.name,`Setting privileges to user: ${this.cfg.user} (uid: ${m})`);}catch{chunkWPWZGJN5_cjs.d.error(this.name,`Failed to resolve user "${this.cfg.user}". Running as root!`);}let l=child_process.spawn(s,i,n);this.setupLogging(l);let h=Date.now();return l.on("error",m=>{chunkWPWZGJN5_cjs.d.error(this.name,`Spawn error (${s}):`,m.message);}),l.on("exit",(m,d)=>{let F=Date.now()-h;this.onChildExit(l,m,d,F);}),l}catch(t){return chunkWPWZGJN5_cjs.d.error(this.name,"Failed to fork child:",t.message),null}}_forkChild(){try{let t=this.cfg.scriptPath.endsWith(".js")?"node":this.cfg.scriptPath,e=this.cfg.scriptPath.endsWith(".js")?[this.cfg.scriptPath,...this.cfg.args??[]]:[...this.cfg.args??[]],s=child_process.spawn(t,e,{cwd:c__default.default.dirname(c__default.default.resolve(this.cfg.scriptPath,"..")),stdio:["ignore","pipe","pipe"],env:{...process.env,...this.cfg.env??{},NODE_ENV:this.cfg.devMode?"development":"production"},detached:!1,shell:!1});this.setupLogging(s);let i=Date.now();return s.on("error",o=>{chunkWPWZGJN5_cjs.d.error(this.name,"Spawn error:",o);}),s.on("exit",(o,n)=>{let l=Date.now()-i;this.onChildExit(s,o,n,l);}),s}catch(t){return chunkWPWZGJN5_cjs.d.error(this.name,"Failed to fork child:",t),null}}onChildExit(t,e,s,i){let o=this.mp(),n=o.children.filter(l=>l!==t);if(this.patch({children:n}),o.isRestarting){n.length===0?(chunkWPWZGJN5_cjs.d.info(this.name,"All instances stopped. Spawning new ones..."),this.patch({isRestarting:false}),this.spawnAll()):chunkWPWZGJN5_cjs.d.info(this.name,`Restart in progress... waiting for ${n.length} instance(s) to stop.`);return}if(o.status==="stopping"){n.length===0?(chunkWPWZGJN5_cjs.d.info(this.name,"All instances dead. Spawning new ones..."),this.patch({isRestarting:false}),this.spawnAll()):chunkWPWZGJN5_cjs.d.info(this.name,`Stop in progress... waiting for ${n.length} instance(s) to stop.`);return}chunkWPWZGJN5_cjs.d.warn(this.name,`Process exited (code=${e}, signal=${s}, uptime=${i}ms)`),e!==0&&e!==null&&(this.patch({status:"crashed"}),i<1500&&chunkWPWZGJN5_cjs.d.error(this.name,`Immediate crash (${i}ms) \u2013 likely a syntax/build error. Waiting for next file change.`),this.scheduleRestart());}scheduleRestart(){let t=this.mp(),e=t.backoffTime,s=this.cfg.maxBackoff??j;chunkWPWZGJN5_cjs.d.warn(this.name,`Scheduling restart in ${e}ms (attempt #${t.restartCount+1})`);let i=setTimeout(async()=>{this.patch({restartCount:t.restartCount+1,backoffTime:Math.min(e*2,s)}),await this.spawnAll();},e);this.patch({restartTimer:i});}startProbe(){let t=this.cfg.probe,e=(t.intervalSeconds??10)*1e3,s=t.failureThreshold??3,o=setInterval(async()=>{let n=this.mp();if(n.status!=="running")return;if(await P(t)){n.probeFailures>0&&this.patch({probeFailures:0});return}let h=n.probeFailures+1;this.patch({probeFailures:h}),chunkWPWZGJN5_cjs.d.warn(this.name,`Liveness probe failed (${h}/${s})`),h>=s&&(chunkWPWZGJN5_cjs.d.error(this.name,"Liveness probe threshold exceeded \u2013 restarting."),this.patch({probeFailures:0}),await this.restart());},e);this.patch({probeTimer:o});}stopProbe(){let{probeTimer:t}=this.mp();t&&(clearInterval(t),this.patch({probeTimer:null,probeFailures:0}));}findProjectRoot(t){let e=c__default.default.resolve(t);for(f__default.default.existsSync(e)&&f__default.default.statSync(e).isFile()&&(e=c__default.default.dirname(e));e!==c__default.default.parse(e).root;){if(f__default.default.existsSync(c__default.default.join(e,"package.json")))return e;e=c__default.default.dirname(e);}return process.cwd()}watchFiles(){this.stopWatcher();let t=this.findProjectRoot(this.cfg.scriptPath),e=c__default.default.resolve(t,"src");chunkWPWZGJN5_cjs.d.info(this.name,g__default.default.gray(`Watcher active on: ${e}`)),this.watcher=N__default.default.watch(e,{ignored:[/node_modules/,/\.pid$/],persistent:true,ignoreInitial:true,awaitWriteFinish:{stabilityThreshold:1500,pollInterval:500}}),this.watcher.on("all",async(s,i)=>{if(!this.isBuilding&&(s==="change"||s==="add"))if(chunkWPWZGJN5_cjs.d.info(this.name,g__default.default.yellow(`File ${s}: ${c__default.default.basename(i)} \u2013 restarting`)),this.cfg.reloadCommand){this.isBuilding=true,chunkWPWZGJN5_cjs.d.info(this.name,g__default.default.blue(`Executing: ${this.cfg.reloadCommand}`));let{exec:o}=await import('child_process');o(this.cfg.reloadCommand,{cwd:t,env:{...process.env,PATH:`${c__default.default.resolve(t,"node_modules/.bin")}${c__default.default.delimiter}${process.env.PATH}`}},(n,l,h)=>{if(this.isBuilding=false,n){chunkWPWZGJN5_cjs.d.error(this.name,`Build Failed:
3
+ ${h||l||n.message}`);return}chunkWPWZGJN5_cjs.d.success(this.name,"Build successful. Triggering restart..."),this.restart();});}else this.restart();}),this.watcher.on("error",s=>chunkWPWZGJN5_cjs.d.error(this.name,"Watcher error:",s)),this.watcher.on("ready",()=>chunkWPWZGJN5_cjs.d.info(this.name,`Watching ${t}`));}stopWatcher(){this.watcher&&(this.watcher.close(),this.watcher=null);}initStore(){chunkWPWZGJN5_cjs.e.set(this.name,{config:this.cfg,children:[],status:"stopped",startTime:null,restartCount:0,backoffTime:w,restartTimer:null,stabilityTimer:null,probeTimer:null,probeFailures:0,isRestarting:false});}mp(){return chunkWPWZGJN5_cjs.e.get(this.name)}_patch(t){chunkWPWZGJN5_cjs.e.set(this.name,{...this.mp(),...t});}patch(t){let e=this.mp();t.status&&t.status!==e.status&&chunkWPWZGJN5_cjs.d.info(this.name,`[STATE] ${e.status} \u2794 ${t.status}${t.isRestarting?" (Restarting)":""}`),t.lastError&&chunkWPWZGJN5_cjs.d.error(this.name,`[REASON] ${t.lastError}`),chunkWPWZGJN5_cjs.e.set(this.name,{...e,...t});}clearTimers(){let{restartTimer:t,stabilityTimer:e}=this.mp();t&&clearTimeout(t),e&&clearTimeout(e),this.patch({restartTimer:null,stabilityTimer:null});}setupLogging(t){let e=this.cfg.logs?.wsUrl,s=null;e&&(s=new y__default.default(e),s.on("open",()=>chunkWPWZGJN5_cjs.d.debug(this.name,"Connected to log collector")),s.on("error",o=>chunkWPWZGJN5_cjs.d.error(this.name,"Log Collector WS Error",o.message)));let i=o=>{let n=o.toString();this.cfg.devMode&&process.stdout.write(`[${this.name}] ${n}`),s&&s.readyState===y__default.default.OPEN&&s.send(JSON.stringify({app:this.name,timestamp:Date.now(),log:n}));};t.stdout?.on("data",i),t.stderr?.on("data",i);}};var W=class{workers=new Map;SNAPSHOT_FILE=c__default.default.join(T__default.default.homedir(),".zpm","snapshot.json");async start(t){let e=this.workers.get(t.name);if(e){let i=chunkWPWZGJN5_cjs.e.get(t.name);if(i?.status==="stopped"||i?.status==="crashed"||i?.status==="errored"){chunkWPWZGJN5_cjs.d.info("ZPM",`Resuming existing worker "${t.name}"`),await e.start();return}chunkWPWZGJN5_cjs.d.warn("ZPM",`Worker "${g__default.default.cyan(t.name)}" is ${g__default.default.cyan(i?.status)} - use restart()`);return}let s=new p(t);this.workers.set(t.name,s),await s.start(),this.saveSnapshot();}async stop(t){let e=this.require(t);e&&(await e.stop(),this.saveSnapshot());}async restart(t){let e=this.require(t);e&&(await e.restart(),this.saveSnapshot());}async delete(t){let e=this.require(t);e&&(await e.stop(),this.workers.delete(t),chunkWPWZGJN5_cjs.e.delete(t),this.saveSnapshot(),chunkWPWZGJN5_cjs.d.info("PM",`Deleted worker "${t}"`));}async getStats(t){if(t){let s=this.require(t);return s?[await s.getStats()]:[]}return await Promise.all([...this.workers.values()].map(s=>s.getStats()))}list(){return [...this.workers.keys()]}getAllConfigs(){return Array.from(this.workers.values()).map(t=>t.getConfig())}async stopAll(){chunkWPWZGJN5_cjs.d.info("PM","Stopping all workers..."),await Promise.all([...this.workers.values()].map(t=>t.stop())),chunkWPWZGJN5_cjs.d.info("PM","All workers stopped."),this.saveSnapshot();}getWorker(t){let e=this.workers.get(t);return e||(chunkWPWZGJN5_cjs.d.error(t,"Worker Not Found"),null)}async addWorker(t,e){let s=new p(t);this.workers.set(t.name,s),e&&await s.start(),this.saveSnapshot();}require(t){let e=this.workers.get(t);return e||(chunkWPWZGJN5_cjs.d.error(t,"Worker Not Found"),null)}saveSnapshot(){try{let t=c__default.default.dirname(this.SNAPSHOT_FILE);f__default.default.existsSync(t)||f__default.default.mkdirSync(t,{recursive:!0});let e=this.getAllConfigs();f__default.default.writeFileSync(this.SNAPSHOT_FILE,JSON.stringify(e,null,2)),chunkWPWZGJN5_cjs.d.info("daemon",`Saved snapshot of ${e.length} workers.`);}catch(t){chunkWPWZGJN5_cjs.d.error("daemon","Failed to save snapshot:",t.message);}}};exports.a=P;exports.b=p;exports.c=W;
@@ -1,3 +1,3 @@
1
- import {a,d,f}from'./chunk-FXEDN7ZZ.js';import {spawn}from'child_process';import p from'fs';import w from'net';import k from'os';import P from'path';function s(d,e="zuz-pm"){return new Promise((r,n)=>{let t=w.createConnection(f(e)),i="";t.on("connect",()=>{t.write(JSON.stringify(d)+`
1
+ import {a,d,f}from'./chunk-5NYRGZXX.js';import {spawn}from'child_process';import p from'fs';import w from'net';import k from'os';import P from'path';function s(d,e="zuz-pm"){return new Promise((r,n)=>{let t=w.createConnection(f(e)),i="";t.on("connect",()=>{t.write(JSON.stringify(d)+`
2
2
  `);}),t.on("data",o=>{i+=o.toString();let c=i.split(`
3
3
  `);i=c.pop()??"";for(let g of c)if(g.trim())try{let a=JSON.parse(g);t.destroy(),a.ok?r(a.data):n(new Error(a.error));}catch(a){t.destroy(),n(a);}}),t.on("error",o=>n(o)),t.setTimeout(1e4,()=>{t.destroy(),n(new Error("IPC timeout"));});})}var u=class{daemonScript;namespace;constructor(e){this.namespace=e?.namespace??"zuz-pm",this.daemonScript=e?.daemonScript??P.join(a,"daemon.js");}async isDaemonRunning(){try{return d.info("[ZPM]","Daemon is Running :?"),await s({cmd:"ping"},this.namespace),!0}catch{return d.info("[ZPM]","Daemon is not running."),false}}async ensureDaemon(){if(await this.isDaemonRunning())return;d.info("Starting ZPM daemon...");let r=process.env.NODE_ENV!=="production";spawn(process.execPath,[this.daemonScript],{detached:true,stdio:r?"inherit":"ignore"}).unref(),await this.waitForDaemon(8e3);}async killDaemon(){let e=P.join(k.tmpdir(),"zuz-pm.pid");if(!p.existsSync(e))throw new Error("Daemon PID file not found \u2013 is the daemon running?");let r=Number(p.readFileSync(e,"utf8").trim());try{process.kill(r,"SIGTERM"),console.log(`[ZPM] Sent SIGTERM to daemon (PID ${r})`);}catch(n){throw new Error(`Failed to kill daemon: ${n.message}`)}finally{p.unlinkSync(e);}}async getStore(){let e=await s({cmd:"get-store"},this.namespace);return e.ok==true?e.data:null}async getProcessByName(e){let r=await s({cmd:"get-store"},this.namespace);return (r.ok==true?r.data:[]).find(t=>t.name==e)}async startWorker(e){let r=await this.getWorkerByName(e);return r?this.start(r.getConfig()):(d.info(e,`Worker ${e} not found`),`Worker ${e} not found`)}async start(e){let r=await this.getWorkerByName(e.name);return console.log(r),r&&(e={...r.getConfig(),...e}),s({cmd:"start",name:e.name,config:e},this.namespace)}async stop(e){return s({cmd:"stop",name:e},this.namespace)}async restart(e){return s({cmd:"restart",name:e},this.namespace)}async delete(e){return s({cmd:"delete",name:e},this.namespace)}async replaceWorker(e,r,n){let t=await this.getWorkerByName(e);if(t)return await this.stop(e),await this.delete(e),await s({cmd:"add-worker",config:{...t.getConfig(),name:r},autoStart:n})}async getWorkerByName(e){return await s({cmd:"find-worker",name:e},this.namespace)}async stats(e){return s({cmd:"stats",name:e},this.namespace)}async list(){return s({cmd:"list"},this.namespace)}waitForDaemon(e){let r=Date.now(),n=200;return new Promise((t,i)=>{let o=()=>{this.isDaemonRunning().then(c=>{if(c)return t();if(Date.now()-r>e)return i(new Error("Daemon did not start in time"));setTimeout(o,n);});};setTimeout(o,n);})}},E=new u;export{u as a,E as b};
package/dist/cli.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  var r=new commander.Command;r.option("-s, --namespace <name>","Internal daemon namespace","zuz-pm");r.parseOptions(process.argv);var S=r.opts(),u=S.namespace,a=new chunkOVDI4B7H_cjs.a(u),v=l__default.default.dirname(url.fileURLToPath(chunkWPWZGJN5_cjs.a)),P=l__default.default.resolve(v,"../package.json"),k=JSON.parse(w__default.default.readFileSync(P,"utf8"));async function $(o,e){if(!await a.isDaemonRunning())return;let c=e?`"${e}"`:"all workers";console.log(s__default.default.cyan("[ZPM]"),s__default.default.gray(`Attaching stream for ${c}...`));let n=h__default.default.createConnection(chunkWPWZGJN5_cjs.f(o));n.write(JSON.stringify({cmd:"logs",name:e})+`
4
4
  `),n.on("data",m=>{let p=m.toString().split(`
5
5
  `);for(let i of p)if(i.trim())try{let d=JSON.parse(i);d.ok&&process.stdout.write(d.data);}catch{}}),n.on("error",m=>{console.error(s__default.default.red(`[IPC Error] ${m.message}`));}),process.on("SIGINT",()=>{n.destroy(),console.log(s__default.default.gray(`
6
- Disconnected from logs.`)),process.exit();});}r.name("zpm").description("Production grade process manager for the @zuzjs ecosystem").version(k.version,"-v, --version","output the current version");r.command("start <script>").description("Start a new process").option("-n, --name <name>","Unique name for the process").option("-p, --port <port>","Port the app listens on",parseInt).option("-i, --instances <number>","Number of instances (cluster mode)",parseInt,1).option("-d, --dev","Enable development mode (auto-restart)",false).option("--reload-cmd <command>","Command to run before restarting in dev mode").option("-c, --cluster","Use cluster mode instead of fork",false).option("--ws <url>","WebSocket URL to stream logs (e.g. for ZPanel)","http://127.0.0.1:2082/_/wss/zpm").option("--save-logs","Save logs to a local file",false).option("--args <string>",'Arguments to pass to the script (e.g. "dev -p 3000")').option("--probe-type <type>","Type of probe: http, tcp, or exec").option("--probe-target <target>","URL, host:port, or command").option("--probe-interval <sec>","Seconds between probes",parseInt,30).option("--probe-threshold <count>","Failures before restart",parseInt,3).action(async(o,e)=>{try{await a.ensureDaemon();let t=l__default.default.resolve(process.cwd(),o),c=e.name??l__default.default.basename(o),n=await a.start({name:e.name??l__default.default.basename(o),scriptPath:t,port:e.port,instances:e.instances,devMode:e.dev,mode:e.cluster?"cluster":"fork",args:e.args?e.args.split(" "):[],reloadCommand:e.reloadCmd,probe:e.probeTarget?{type:e.probeType,target:e.probeTarget||(e.probeType==="http"?"http://localhost:3000":"localhost:3000"),intervalSeconds:e.probeInterval,failureThreshold:e.probeThreshold,timeoutSeconds:5}:void 0,logs:{wsUrl:e.ws,saveToFile:e.saveLogs}});console.log(s__default.default.cyan("[ZPM]"),n),e.dev?await $(u,c):process.exit(0);}catch(t){console.log(s__default.default.cyan("[ZPM]"),s__default.default.red("[ERROR]"),t.message);}});r.command("logs [name]").description("Stream real-time logs (omit name for all logs)").action(async o=>{try{if(!await a.isDaemonRunning())throw new Error("Daemon is not running.");let t=o?`"${o}"`:"all workers";console.log(s__default.default.cyan("[ZPM]"),`Streaming logs for "${s__default.default.green(t)}" (Ctrl+C to stop)`);let c=h__default.default.createConnection(chunkWPWZGJN5_cjs.f(u));c.write(JSON.stringify({cmd:"logs",name:o})+`
6
+ Disconnected from logs.`)),process.exit();});}r.name("zpm").description("Production grade process manager for the @zuzjs ecosystem").version(k.version,"-v, --version","output the current version");r.command("start <script>").description("Start a new process").option("-n, --name <name>","Unique name for the process").option("-p, --port <port>","Port the app listens on",parseInt).option("-i, --instances <number>","Number of instances (cluster mode)",parseInt,1).option("-d, --dev","Enable development mode (auto-restart)",false).option("--reload-cmd <command>","Command to run before restarting in dev mode").option("-u, --user <username>","User to run the process as").option("-c, --cluster","Use cluster mode instead of fork",false).option("--ws <url>","WebSocket URL to stream logs (e.g. for ZPanel)","http://127.0.0.1:2082/_/wss/zpm").option("--save-logs","Save logs to a local file",false).option("--args <string>",'Arguments to pass to the script (e.g. "dev -p 3000")').option("--probe-type <type>","Type of probe: http, tcp, or exec").option("--probe-target <target>","URL, host:port, or command").option("--probe-interval <sec>","Seconds between probes",parseInt,30).option("--probe-threshold <count>","Failures before restart",parseInt,3).action(async(o,e)=>{try{await a.ensureDaemon();let t=l__default.default.resolve(process.cwd(),o),c=e.name??l__default.default.basename(o),n=await a.start({name:e.name??l__default.default.basename(o),scriptPath:t,port:e.port,instances:e.instances,devMode:e.dev,mode:e.cluster?"cluster":"fork",args:e.args?e.args.split(" "):[],reloadCommand:e.reloadCmd,user:e.user,probe:e.probeTarget?{type:e.probeType,target:e.probeTarget||(e.probeType==="http"?"http://localhost:3000":"localhost:3000"),intervalSeconds:e.probeInterval,failureThreshold:e.probeThreshold,timeoutSeconds:5}:void 0,logs:{wsUrl:e.ws,saveToFile:e.saveLogs}});console.log(s__default.default.cyan("[ZPM]"),n),e.dev?await $(u,c):process.exit(0);}catch(t){console.log(s__default.default.cyan("[ZPM]"),s__default.default.red("[ERROR]"),t.message);}});r.command("logs [name]").description("Stream real-time logs (omit name for all logs)").action(async o=>{try{if(!await a.isDaemonRunning())throw new Error("Daemon is not running.");let t=o?`"${o}"`:"all workers";console.log(s__default.default.cyan("[ZPM]"),`Streaming logs for "${s__default.default.green(t)}" (Ctrl+C to stop)`);let c=h__default.default.createConnection(chunkWPWZGJN5_cjs.f(u));c.write(JSON.stringify({cmd:"logs",name:o})+`
7
7
  `),c.on("data",n=>{let m=n.toString().split(`
8
8
  `);for(let p of m)if(p.trim())try{let i=JSON.parse(p);i.ok?process.stdout.write(i.data):(console.error(`\x1B[31m${i.error}\x1B[0m`),process.exit(1));}catch{}}),c.on("error",n=>{console.error(`\x1B[31m[IPC Error]\x1B[0m ${n.message}`),process.exit(1);}),process.on("SIGINT",()=>{c.destroy(),console.log(`
9
9
  \x1B[90mDisconnected from logs.\x1B[0m`),process.exit();});}catch(e){console.error(`\x1B[31m[Error]\x1B[0m ${e.message}`);}});r.command("list").description("List all managed processes").action(async()=>{let o=await a.list();if(o.length===0){console.log("No workers registered.");return}console.log("\x1B[1mManaged Processes:\x1B[0m"),o.forEach(e=>console.log(` \u2022 ${e}`));});r.command("stats [name]").description("Show telemetry for processes").action(async o=>{let e=await a.stats(o);if(e.length===0){console.log("No stats available.");return}e.forEach(t=>{let c=t.uptime?`${Math.round(t.uptime/1e3)}s`:"0s",n=t.status==="running"?"\x1B[32m":"\x1B[31m";console.log(`${n}[${t.status.toUpperCase()}]\x1B[0m \x1B[1m${t.name.padEnd(15)}\x1B[0m PID: ${String(t.pid??"N/A").padEnd(6)} CPU: ${String(t.cpu??0).padStart(3)}% MEM: ${Math.round((t.memoryRss??0)/1024/1024)}MB Uptime: ${c}`);});});["stop","restart","delete"].forEach(o=>{r.command(`${o} <name>`).description(`${o.charAt(0).toUpperCase()+o.slice(1)} a process`).action(async e=>{try{let t=await a[o](e);console.log(`\x1B[32m[ZPM]\x1B[0m ${t}`);}catch(t){console.error(`\x1B[31m[Error]\x1B[0m ${t.message}`);}});});r.command("start-daemon").description("Start the background ZPM daemon").action(async()=>{await a.ensureDaemon(),console.log("\x1B[32m[ZPM]\x1B[0m Daemon started.");});r.command("restart-daemon").description("Restart the background ZPM daemon").action(async()=>{await a.killDaemon(),await a.ensureDaemon(),console.log("\x1B[32m[ZPM]\x1B[0m Daemon started.");});r.command("kill-daemon").description("Stop the background ZPM daemon").action(async()=>{await a.killDaemon(),console.log("\x1B[33mDaemon killed.\x1B[0m");});r.command("store").description("Show raw internal store state for debugging").action(async()=>{let o=await a.getStore();if(o){let e=o;if(e.length===0){console.log(s__default.default.yellow("Store is empty."));return}console.log(s__default.default.magenta(`
package/dist/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import {a as a$1}from'./chunk-SHBIDNZL.js';import {f as f$1}from'./chunk-FXEDN7ZZ.js';import {Command}from'commander';import y from'fs';import f from'net';import l from'path';import {fileURLToPath}from'url';import s from'picocolors';var r=new Command;r.option("-s, --namespace <name>","Internal daemon namespace","zuz-pm");r.parseOptions(process.argv);var x=r.opts(),u=x.namespace,a=new a$1(u),S=l.dirname(fileURLToPath(import.meta.url)),v=l.resolve(S,"../package.json"),P=JSON.parse(y.readFileSync(v,"utf8"));async function k(o,e){if(!await a.isDaemonRunning())return;let c=e?`"${e}"`:"all workers";console.log(s.cyan("[ZPM]"),s.gray(`Attaching stream for ${c}...`));let n=f.createConnection(f$1(o));n.write(JSON.stringify({cmd:"logs",name:e})+`
2
+ import {a as a$1}from'./chunk-IFYJLMCJ.js';import {f as f$1}from'./chunk-5NYRGZXX.js';import {Command}from'commander';import y from'fs';import f from'net';import l from'path';import {fileURLToPath}from'url';import s from'picocolors';var r=new Command;r.option("-s, --namespace <name>","Internal daemon namespace","zuz-pm");r.parseOptions(process.argv);var x=r.opts(),u=x.namespace,a=new a$1(u),S=l.dirname(fileURLToPath(import.meta.url)),v=l.resolve(S,"../package.json"),P=JSON.parse(y.readFileSync(v,"utf8"));async function k(o,e){if(!await a.isDaemonRunning())return;let c=e?`"${e}"`:"all workers";console.log(s.cyan("[ZPM]"),s.gray(`Attaching stream for ${c}...`));let n=f.createConnection(f$1(o));n.write(JSON.stringify({cmd:"logs",name:e})+`
3
3
  `),n.on("data",m=>{let p=m.toString().split(`
4
4
  `);for(let i of p)if(i.trim())try{let d=JSON.parse(i);d.ok&&process.stdout.write(d.data);}catch{}}),n.on("error",m=>{console.error(s.red(`[IPC Error] ${m.message}`));}),process.on("SIGINT",()=>{n.destroy(),console.log(s.gray(`
5
- Disconnected from logs.`)),process.exit();});}r.name("zpm").description("Production grade process manager for the @zuzjs ecosystem").version(P.version,"-v, --version","output the current version");r.command("start <script>").description("Start a new process").option("-n, --name <name>","Unique name for the process").option("-p, --port <port>","Port the app listens on",parseInt).option("-i, --instances <number>","Number of instances (cluster mode)",parseInt,1).option("-d, --dev","Enable development mode (auto-restart)",false).option("--reload-cmd <command>","Command to run before restarting in dev mode").option("-c, --cluster","Use cluster mode instead of fork",false).option("--ws <url>","WebSocket URL to stream logs (e.g. for ZPanel)","http://127.0.0.1:2082/_/wss/zpm").option("--save-logs","Save logs to a local file",false).option("--args <string>",'Arguments to pass to the script (e.g. "dev -p 3000")').option("--probe-type <type>","Type of probe: http, tcp, or exec").option("--probe-target <target>","URL, host:port, or command").option("--probe-interval <sec>","Seconds between probes",parseInt,30).option("--probe-threshold <count>","Failures before restart",parseInt,3).action(async(o,e)=>{try{await a.ensureDaemon();let t=l.resolve(process.cwd(),o),c=e.name??l.basename(o),n=await a.start({name:e.name??l.basename(o),scriptPath:t,port:e.port,instances:e.instances,devMode:e.dev,mode:e.cluster?"cluster":"fork",args:e.args?e.args.split(" "):[],reloadCommand:e.reloadCmd,probe:e.probeTarget?{type:e.probeType,target:e.probeTarget||(e.probeType==="http"?"http://localhost:3000":"localhost:3000"),intervalSeconds:e.probeInterval,failureThreshold:e.probeThreshold,timeoutSeconds:5}:void 0,logs:{wsUrl:e.ws,saveToFile:e.saveLogs}});console.log(s.cyan("[ZPM]"),n),e.dev?await k(u,c):process.exit(0);}catch(t){console.log(s.cyan("[ZPM]"),s.red("[ERROR]"),t.message);}});r.command("logs [name]").description("Stream real-time logs (omit name for all logs)").action(async o=>{try{if(!await a.isDaemonRunning())throw new Error("Daemon is not running.");let t=o?`"${o}"`:"all workers";console.log(s.cyan("[ZPM]"),`Streaming logs for "${s.green(t)}" (Ctrl+C to stop)`);let c=f.createConnection(f$1(u));c.write(JSON.stringify({cmd:"logs",name:o})+`
5
+ Disconnected from logs.`)),process.exit();});}r.name("zpm").description("Production grade process manager for the @zuzjs ecosystem").version(P.version,"-v, --version","output the current version");r.command("start <script>").description("Start a new process").option("-n, --name <name>","Unique name for the process").option("-p, --port <port>","Port the app listens on",parseInt).option("-i, --instances <number>","Number of instances (cluster mode)",parseInt,1).option("-d, --dev","Enable development mode (auto-restart)",false).option("--reload-cmd <command>","Command to run before restarting in dev mode").option("-u, --user <username>","User to run the process as").option("-c, --cluster","Use cluster mode instead of fork",false).option("--ws <url>","WebSocket URL to stream logs (e.g. for ZPanel)","http://127.0.0.1:2082/_/wss/zpm").option("--save-logs","Save logs to a local file",false).option("--args <string>",'Arguments to pass to the script (e.g. "dev -p 3000")').option("--probe-type <type>","Type of probe: http, tcp, or exec").option("--probe-target <target>","URL, host:port, or command").option("--probe-interval <sec>","Seconds between probes",parseInt,30).option("--probe-threshold <count>","Failures before restart",parseInt,3).action(async(o,e)=>{try{await a.ensureDaemon();let t=l.resolve(process.cwd(),o),c=e.name??l.basename(o),n=await a.start({name:e.name??l.basename(o),scriptPath:t,port:e.port,instances:e.instances,devMode:e.dev,mode:e.cluster?"cluster":"fork",args:e.args?e.args.split(" "):[],reloadCommand:e.reloadCmd,user:e.user,probe:e.probeTarget?{type:e.probeType,target:e.probeTarget||(e.probeType==="http"?"http://localhost:3000":"localhost:3000"),intervalSeconds:e.probeInterval,failureThreshold:e.probeThreshold,timeoutSeconds:5}:void 0,logs:{wsUrl:e.ws,saveToFile:e.saveLogs}});console.log(s.cyan("[ZPM]"),n),e.dev?await k(u,c):process.exit(0);}catch(t){console.log(s.cyan("[ZPM]"),s.red("[ERROR]"),t.message);}});r.command("logs [name]").description("Stream real-time logs (omit name for all logs)").action(async o=>{try{if(!await a.isDaemonRunning())throw new Error("Daemon is not running.");let t=o?`"${o}"`:"all workers";console.log(s.cyan("[ZPM]"),`Streaming logs for "${s.green(t)}" (Ctrl+C to stop)`);let c=f.createConnection(f$1(u));c.write(JSON.stringify({cmd:"logs",name:o})+`
6
6
  `),c.on("data",n=>{let m=n.toString().split(`
7
7
  `);for(let p of m)if(p.trim())try{let i=JSON.parse(p);i.ok?process.stdout.write(i.data):(console.error(`\x1B[31m${i.error}\x1B[0m`),process.exit(1));}catch{}}),c.on("error",n=>{console.error(`\x1B[31m[IPC Error]\x1B[0m ${n.message}`),process.exit(1);}),process.on("SIGINT",()=>{c.destroy(),console.log(`
8
8
  \x1B[90mDisconnected from logs.\x1B[0m`),process.exit();});}catch(e){console.error(`\x1B[31m[Error]\x1B[0m ${e.message}`);}});r.command("list").description("List all managed processes").action(async()=>{let o=await a.list();if(o.length===0){console.log("No workers registered.");return}console.log("\x1B[1mManaged Processes:\x1B[0m"),o.forEach(e=>console.log(` \u2022 ${e}`));});r.command("stats [name]").description("Show telemetry for processes").action(async o=>{let e=await a.stats(o);if(e.length===0){console.log("No stats available.");return}e.forEach(t=>{let c=t.uptime?`${Math.round(t.uptime/1e3)}s`:"0s",n=t.status==="running"?"\x1B[32m":"\x1B[31m";console.log(`${n}[${t.status.toUpperCase()}]\x1B[0m \x1B[1m${t.name.padEnd(15)}\x1B[0m PID: ${String(t.pid??"N/A").padEnd(6)} CPU: ${String(t.cpu??0).padStart(3)}% MEM: ${Math.round((t.memoryRss??0)/1024/1024)}MB Uptime: ${c}`);});});["stop","restart","delete"].forEach(o=>{r.command(`${o} <name>`).description(`${o.charAt(0).toUpperCase()+o.slice(1)} a process`).action(async e=>{try{let t=await a[o](e);console.log(`\x1B[32m[ZPM]\x1B[0m ${t}`);}catch(t){console.error(`\x1B[31m[Error]\x1B[0m ${t.message}`);}});});r.command("start-daemon").description("Start the background ZPM daemon").action(async()=>{await a.ensureDaemon(),console.log("\x1B[32m[ZPM]\x1B[0m Daemon started.");});r.command("restart-daemon").description("Restart the background ZPM daemon").action(async()=>{await a.killDaemon(),await a.ensureDaemon(),console.log("\x1B[32m[ZPM]\x1B[0m Daemon started.");});r.command("kill-daemon").description("Stop the background ZPM daemon").action(async()=>{await a.killDaemon(),console.log("\x1B[33mDaemon killed.\x1B[0m");});r.command("store").description("Show raw internal store state for debugging").action(async()=>{let o=await a.getStore();if(o){let e=o;if(e.length===0){console.log(s.yellow("Store is empty."));return}console.log(s.magenta(`
package/dist/daemon.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var chunkMR272QVA_cjs=require('./chunk-MR272QVA.cjs'),chunkWPWZGJN5_cjs=require('./chunk-WPWZGJN5.cjs'),n=require('fs'),f=require('os'),S=require('path');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var n__default=/*#__PURE__*/_interopDefault(n);var f__default=/*#__PURE__*/_interopDefault(f);var S__default=/*#__PURE__*/_interopDefault(S);/* ZuzJS Process Manager */
2
- var t=S__default.default.join(f__default.default.tmpdir(),"zuz-pm.pid");function g(){n__default.default.writeFileSync(t,String(process.pid));}function u(){n__default.default.existsSync(t)&&n__default.default.unlinkSync(t);}async function h(){chunkWPWZGJN5_cjs.d.success("daemon",`Booting ZPM daemon (PID ${process.pid})`),g();let r=new chunkMR272QVA_cjs.c,d=chunkWPWZGJN5_cjs.g(r);if(n__default.default.existsSync(r.SNAPSHOT_FILE))try{let e=n__default.default.readFileSync(r.SNAPSHOT_FILE,"utf-8"),s=JSON.parse(e);if(Array.isArray(s)&&s.length>0){chunkWPWZGJN5_cjs.d.info("daemon",`Restoring ${s.length} workers from snapshot...`);for(let a of s)r.start(a).catch(p=>{chunkWPWZGJN5_cjs.d.error("daemon",`Failed to restore worker "${a.name}":`,p.message);});}}catch(e){chunkWPWZGJN5_cjs.d.error("daemon","Snapshot restoration failed:",e.message);}async function i(e){chunkWPWZGJN5_cjs.d.info("daemon",`Received ${e} \u2013 shutting down\u2026`),r.saveSnapshot(),d.close(),await r.stopAll(),u(),process.exit(0);}process.on("SIGINT",()=>i("SIGINT")),process.on("SIGTERM",()=>i("SIGTERM")),process.on("uncaughtException",e=>chunkWPWZGJN5_cjs.d.error("daemon","Uncaught exception:",e)),process.on("unhandledRejection",e=>chunkWPWZGJN5_cjs.d.error("daemon","Unhandled rejection:",e)),chunkWPWZGJN5_cjs.d.success("daemon","Ready \u2013 waiting for IPC commands.");}h().catch(r=>{chunkWPWZGJN5_cjs.d.error("daemon","Fatal startup error:",r),process.exit(1);});
1
+ 'use strict';var chunkD2LT5GYB_cjs=require('./chunk-D2LT5GYB.cjs'),chunkWPWZGJN5_cjs=require('./chunk-WPWZGJN5.cjs'),n=require('fs'),f=require('os'),S=require('path');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var n__default=/*#__PURE__*/_interopDefault(n);var f__default=/*#__PURE__*/_interopDefault(f);var S__default=/*#__PURE__*/_interopDefault(S);/* ZuzJS Process Manager */
2
+ var t=S__default.default.join(f__default.default.tmpdir(),"zuz-pm.pid");function g(){n__default.default.writeFileSync(t,String(process.pid));}function u(){n__default.default.existsSync(t)&&n__default.default.unlinkSync(t);}async function h(){chunkWPWZGJN5_cjs.d.success("daemon",`Booting ZPM daemon (PID ${process.pid})`),g();let r=new chunkD2LT5GYB_cjs.c,d=chunkWPWZGJN5_cjs.g(r);if(n__default.default.existsSync(r.SNAPSHOT_FILE))try{let e=n__default.default.readFileSync(r.SNAPSHOT_FILE,"utf-8"),s=JSON.parse(e);if(Array.isArray(s)&&s.length>0){chunkWPWZGJN5_cjs.d.info("daemon",`Restoring ${s.length} workers from snapshot...`);for(let a of s)r.start(a).catch(p=>{chunkWPWZGJN5_cjs.d.error("daemon",`Failed to restore worker "${a.name}":`,p.message);});}}catch(e){chunkWPWZGJN5_cjs.d.error("daemon","Snapshot restoration failed:",e.message);}async function i(e){chunkWPWZGJN5_cjs.d.info("daemon",`Received ${e} \u2013 shutting down\u2026`),r.saveSnapshot(),d.close(),await r.stopAll(),u(),process.exit(0);}process.on("SIGINT",()=>i("SIGINT")),process.on("SIGTERM",()=>i("SIGTERM")),process.on("uncaughtException",e=>chunkWPWZGJN5_cjs.d.error("daemon","Uncaught exception:",e)),process.on("unhandledRejection",e=>chunkWPWZGJN5_cjs.d.error("daemon","Unhandled rejection:",e)),chunkWPWZGJN5_cjs.d.success("daemon","Ready \u2013 waiting for IPC commands.");}h().catch(r=>{chunkWPWZGJN5_cjs.d.error("daemon","Fatal startup error:",r),process.exit(1);});
package/dist/daemon.js CHANGED
@@ -1 +1 @@
1
- import {c}from'./chunk-MB2FUF4P.js';import {d,g as g$1}from'./chunk-FXEDN7ZZ.js';import n from'fs';import f from'os';import S from'path';var t=S.join(f.tmpdir(),"zuz-pm.pid");function g(){n.writeFileSync(t,String(process.pid));}function u(){n.existsSync(t)&&n.unlinkSync(t);}async function h(){d.success("daemon",`Booting ZPM daemon (PID ${process.pid})`),g();let r=new c,d$1=g$1(r);if(n.existsSync(r.SNAPSHOT_FILE))try{let e=n.readFileSync(r.SNAPSHOT_FILE,"utf-8"),s=JSON.parse(e);if(Array.isArray(s)&&s.length>0){d.info("daemon",`Restoring ${s.length} workers from snapshot...`);for(let a of s)r.start(a).catch(p=>{d.error("daemon",`Failed to restore worker "${a.name}":`,p.message);});}}catch(e){d.error("daemon","Snapshot restoration failed:",e.message);}async function i(e){d.info("daemon",`Received ${e} \u2013 shutting down\u2026`),r.saveSnapshot(),d$1.close(),await r.stopAll(),u(),process.exit(0);}process.on("SIGINT",()=>i("SIGINT")),process.on("SIGTERM",()=>i("SIGTERM")),process.on("uncaughtException",e=>d.error("daemon","Uncaught exception:",e)),process.on("unhandledRejection",e=>d.error("daemon","Unhandled rejection:",e)),d.success("daemon","Ready \u2013 waiting for IPC commands.");}h().catch(r=>{d.error("daemon","Fatal startup error:",r),process.exit(1);});
1
+ import {c}from'./chunk-6S5I354M.js';import {d,g as g$1}from'./chunk-5NYRGZXX.js';import n from'fs';import f from'os';import S from'path';var t=S.join(f.tmpdir(),"zuz-pm.pid");function g(){n.writeFileSync(t,String(process.pid));}function u(){n.existsSync(t)&&n.unlinkSync(t);}async function h(){d.success("daemon",`Booting ZPM daemon (PID ${process.pid})`),g();let r=new c,d$1=g$1(r);if(n.existsSync(r.SNAPSHOT_FILE))try{let e=n.readFileSync(r.SNAPSHOT_FILE,"utf-8"),s=JSON.parse(e);if(Array.isArray(s)&&s.length>0){d.info("daemon",`Restoring ${s.length} workers from snapshot...`);for(let a of s)r.start(a).catch(p=>{d.error("daemon",`Failed to restore worker "${a.name}":`,p.message);});}}catch(e){d.error("daemon","Snapshot restoration failed:",e.message);}async function i(e){d.info("daemon",`Received ${e} \u2013 shutting down\u2026`),r.saveSnapshot(),d$1.close(),await r.stopAll(),u(),process.exit(0);}process.on("SIGINT",()=>i("SIGINT")),process.on("SIGTERM",()=>i("SIGTERM")),process.on("uncaughtException",e=>d.error("daemon","Uncaught exception:",e)),process.on("unhandledRejection",e=>d.error("daemon","Unhandled rejection:",e)),d.success("daemon","Ready \u2013 waiting for IPC commands.");}h().catch(r=>{d.error("daemon","Fatal startup error:",r),process.exit(1);});
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- 'use strict';var chunkOVDI4B7H_cjs=require('./chunk-OVDI4B7H.cjs'),chunkMR272QVA_cjs=require('./chunk-MR272QVA.cjs'),chunkWPWZGJN5_cjs=require('./chunk-WPWZGJN5.cjs');Object.defineProperty(exports,"ZPMClient",{enumerable:true,get:function(){return chunkOVDI4B7H_cjs.a}});Object.defineProperty(exports,"zpm",{enumerable:true,get:function(){return chunkOVDI4B7H_cjs.b}});Object.defineProperty(exports,"ProcessManager",{enumerable:true,get:function(){return chunkMR272QVA_cjs.c}});Object.defineProperty(exports,"Worker",{enumerable:true,get:function(){return chunkMR272QVA_cjs.b}});Object.defineProperty(exports,"runProbe",{enumerable:true,get:function(){return chunkMR272QVA_cjs.a}});Object.defineProperty(exports,"WorkerMode",{enumerable:true,get:function(){return chunkWPWZGJN5_cjs.b}});Object.defineProperty(exports,"WorkerStatus",{enumerable:true,get:function(){return chunkWPWZGJN5_cjs.c}});Object.defineProperty(exports,"getSocketPath",{enumerable:true,get:function(){return chunkWPWZGJN5_cjs.f}});Object.defineProperty(exports,"logger",{enumerable:true,get:function(){return chunkWPWZGJN5_cjs.d}});Object.defineProperty(exports,"processStore",{enumerable:true,get:function(){return chunkWPWZGJN5_cjs.e}});
1
+ 'use strict';var chunkOVDI4B7H_cjs=require('./chunk-OVDI4B7H.cjs'),chunkD2LT5GYB_cjs=require('./chunk-D2LT5GYB.cjs'),chunkWPWZGJN5_cjs=require('./chunk-WPWZGJN5.cjs');Object.defineProperty(exports,"ZPMClient",{enumerable:true,get:function(){return chunkOVDI4B7H_cjs.a}});Object.defineProperty(exports,"zpm",{enumerable:true,get:function(){return chunkOVDI4B7H_cjs.b}});Object.defineProperty(exports,"ProcessManager",{enumerable:true,get:function(){return chunkD2LT5GYB_cjs.c}});Object.defineProperty(exports,"Worker",{enumerable:true,get:function(){return chunkD2LT5GYB_cjs.b}});Object.defineProperty(exports,"runProbe",{enumerable:true,get:function(){return chunkD2LT5GYB_cjs.a}});Object.defineProperty(exports,"WorkerMode",{enumerable:true,get:function(){return chunkWPWZGJN5_cjs.b}});Object.defineProperty(exports,"WorkerStatus",{enumerable:true,get:function(){return chunkWPWZGJN5_cjs.c}});Object.defineProperty(exports,"getSocketPath",{enumerable:true,get:function(){return chunkWPWZGJN5_cjs.f}});Object.defineProperty(exports,"logger",{enumerable:true,get:function(){return chunkWPWZGJN5_cjs.d}});Object.defineProperty(exports,"processStore",{enumerable:true,get:function(){return chunkWPWZGJN5_cjs.e}});
package/dist/index.d.cts CHANGED
@@ -19,6 +19,10 @@ interface WorkerConfig {
19
19
  name: string;
20
20
  /** Absolute path to the entry script */
21
21
  scriptPath: string;
22
+ /** User */
23
+ user?: string;
24
+ uid?: number;
25
+ gid?: number;
22
26
  /** CLI arguments forwarded to the child */
23
27
  args?: string[];
24
28
  /** Extra environment variables merged on top of process.env */
package/dist/index.d.ts CHANGED
@@ -19,6 +19,10 @@ interface WorkerConfig {
19
19
  name: string;
20
20
  /** Absolute path to the entry script */
21
21
  scriptPath: string;
22
+ /** User */
23
+ user?: string;
24
+ uid?: number;
25
+ gid?: number;
22
26
  /** CLI arguments forwarded to the child */
23
27
  args?: string[];
24
28
  /** Extra environment variables merged on top of process.env */
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export{a as ZPMClient,b as zpm}from'./chunk-SHBIDNZL.js';export{c as ProcessManager,b as Worker,a as runProbe}from'./chunk-MB2FUF4P.js';export{b as WorkerMode,c as WorkerStatus,f as getSocketPath,d as logger,e as processStore}from'./chunk-FXEDN7ZZ.js';
1
+ export{a as ZPMClient,b as zpm}from'./chunk-IFYJLMCJ.js';export{c as ProcessManager,b as Worker,a as runProbe}from'./chunk-6S5I354M.js';export{b as WorkerMode,c as WorkerStatus,f as getSocketPath,d as logger,e as processStore}from'./chunk-5NYRGZXX.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuzjs/pm",
3
- "version": "0.0.26",
3
+ "version": "0.0.27",
4
4
  "keywords": [
5
5
  "core",
6
6
  "zuz",
@@ -1,6 +0,0 @@
1
- import C from'path';import {fileURLToPath}from'url';import y from'os';import g from'picocolors';import c from'winston';import D from'events';import w from'fs';import W from'net';var I=()=>fileURLToPath(import.meta.url),N=()=>C.dirname(I()),u=N();var R=(s=>(s.Fork="fork",s.Cluster="cluster",s))(R||{}),L=(n=>(n.Stopped="stopped",n.Starting="starting",n.Running="running",n.Stopping="stopping",n.Crashed="crashed",n.Errored="errored",n))(L||{});var F=C.join(y.homedir(),".zpm","logs"),J=c.format.combine(c.format.timestamp({format:"YYYY/MM/DD HH:mm:ss"}),c.format.splat(),c.format.printf(({timestamp:e,level:r,message:s,tag:t})=>{let o=g.gray(`[${e}]`),m=g.bold(`[ZPM/${(t||"SYS").toUpperCase()}]`);return `${o} [${r=="info"?g.cyan(r):r=="warn"?g.yellow(r):r=="error"?g.red(r):r=="success"?g.green(r):r=="debug"?g.gray(r):"debug"}] ${m} \u2192 ${s}`})),l=c.createLogger({levels:{error:0,warn:1,info:2,success:2,debug:3},transports:[new c.transports.Console({level:"debug",format:J}),new c.transports.File({filename:C.join(F,"daemon.log"),format:c.format.combine(c.format.timestamp(),c.format.json())})]}),p={info:(e,...r)=>l.info(r.join(" "),{tag:e}),warn:(e,...r)=>l.warn(r.join(" "),{tag:e}),error:(e,...r)=>l.error(r.join(" "),{tag:e}),debug:(e,...r)=>l.debug(r.join(" "),{tag:e}),success:(e,...r)=>l.log("success",r.join(" "),{tag:e})};var k=class extends D{map=new Map;set(r,s){this.map.set(r,s),this.emit("change",r,s);}get(r){return this.map.get(r)}has(r){return this.map.has(r)}delete(r){this.map.delete(r),this.emit("delete",r);}all(){return new Map(this.map)}onchange(r){return this.on("change",r)}offchange(r){return this.off("change",r)}},P=new k;function O(e="zuz-pm"){return y.platform()==="win32"?C.join("\\\\.\\pipe",e):C.join(y.tmpdir(),`${e}.sock`)}function ar(e){let r=O();w.existsSync(r)&&w.unlinkSync(r);let s=W.createServer(t=>{let o="";t.on("data",m=>{o+=m.toString();let n=o.split(`
2
- `);o=n.pop()??"";for(let d of n)d.trim()&&E(e,t,d);}),t.on("error",m=>{p.error("IPC","Socket error:",m.message);});});return s.listen(r,()=>{if(y.platform()!=="win32")try{w.chmodSync(r,"777");}catch(t){console.error("Failed to set socket permissions:",t);}p.success("IPC",`Listening on ${r}`);}),s.on("error",t=>{p.error("IPC","Server error:",t);}),s}async function E(e,r,s){let t;try{t=JSON.parse(s);}catch{S(r,{ok:false,error:"Invalid JSON"});return}try{let o=null;switch(t.cmd){case "ping":o="pong";break;case "start":await e.start(t.config),o=`Started "${t.name}"`;break;case "stop":await e.stop(t.name),o=`Stopped "${t.name}"`;break;case "restart":await e.restart(t.name),o=`Restarted "${t.name}"`;break;case "delete":await e.delete(t.name),o=`Deleted "${t.name}"`;break;case "stats":o=await e.getStats(t.name);break;case "list":o=e.list();break;case "add-worker":await e.addWorker(t.config,t.autoStart),o=`Added "${t.config.name}"`;break;case "find-worker":o=e.getWorker(t.name);break;case "get-store":{o=Array.from(P.all()).map(([i,a])=>({name:i,status:a.status,childrenCount:a.children.length,restartCount:a.restartCount,backoffTime:a.backoffTime,isRestarting:a.isRestarting,probeFailures:a.probeFailures}));break}case "logs":let m=t.name,n=[];if(m){let i=e.getWorker(m);if(!i){r.write(JSON.stringify({ok:!1,error:`Worker "${m}" not found`})+`
3
- `);return}n.push(i);}else {let i=e.list();for(let a of i){let f=e.getWorker(a);f&&n.push(f);}}if(n.length===0){r.write(JSON.stringify({ok:!1,error:"No active workers to stream logs from"})+`
4
- `);return}let d=[];for(let i of n){let a=i.mp();for(let f of a.children){let b=x=>{let $=m?"":`[${i.name}] `;r.write(JSON.stringify({ok:!0,data:`${$}${x.toString()}`})+`
5
- `);};f.stdout?.on("data",b),f.stderr?.on("data",b),d.push({child:f,onData:b});}}r.on("close",()=>{for(let{child:i,onData:a}of d)i.stdout?.off("data",a),i.stderr?.off("data",a);});break;default:p.error("ZPM",`Unknown command: ${t.cmd}`);}S(r,{ok:!0,data:o});}catch(o){S(r,{ok:false,error:String(o.message??o)});}}function S(e,r){e.writable&&e.write(JSON.stringify(r)+`
6
- `);}export{u as a,R as b,L as c,p as d,P as e,O as f,ar as g};
@@ -1,2 +0,0 @@
1
- import {d as d$1,e}from'./chunk-FXEDN7ZZ.js';import {spawn,exec}from'child_process';import x from'http';import A from'https';import E from'net';import M from'chokidar';import u from'fs';import S from'os';import c from'path';import f from'picocolors';import k from'ws';import D from'pidusage';function _(a,t){return new Promise(e=>{let i=(a.startsWith("https")?A:x).get(a,{timeout:t},o=>{e((o.statusCode??500)<500);});i.on("error",()=>e(false)),i.on("timeout",()=>{i.destroy(),e(false);});})}function R(a,t){let[e,s]=a.split(":"),i=Number(s);return new Promise(o=>{let n=E.createConnection({host:e,port:i},()=>{n.destroy(),o(true);});n.setTimeout(t),n.on("timeout",()=>{n.destroy(),o(false);}),n.on("error",()=>o(false));})}function I(a,t){return new Promise(e=>{let s=setTimeout(()=>e(false),t);exec(a,i=>{clearTimeout(s),e(!i);});})}async function v(a){let t=(a.timeoutSeconds??5)*1e3;switch(a.type){case "http":return _(a.target,t);case "tcp":return R(a.target,t);case "exec":return I(a.target,t);default:return false}}var O=5e3,B=16e3,d=1e3,j=5e3;async function H(a){return new Promise(t=>{E.createServer().once("error",()=>t(false)).once("listening",function(){this.close(()=>t(true));}).listen(a);})}async function q(a){if(await H(a))return;let t=S.platform()==="darwin"?`lsof -ti :${a} | xargs kill -9 2>/dev/null || true`:`fuser -k -9 ${a}/tcp 2>/dev/null; true`;await new Promise(e=>exec(t,()=>e())),await new Promise(e=>setTimeout(e,800));}async function K(a,t){let e=a.process?.pid??a.pid;if(e)return new Promise(s=>{let i=false,o=()=>{i||(i=true,clearTimeout(n),s());};a.once?.("exit",o),a.once?.("exit",o);try{process.kill(e,"SIGTERM");}catch{return o()}let n=setTimeout(()=>{try{process.kill(e,"SIGKILL"),setTimeout(o,100);}catch{o();}},t),h=setInterval(()=>{try{process.kill(e,0);}catch{clearInterval(h),o();}},500);})}var p=class{cfg;name;watcher=null;isBuilding=false;constructor(t){this.cfg={mode:"fork",instances:1,...t},this.name=t.name,this.initStore();}getConfig(){return this.cfg}async start(){let t=this.mp();if(t.status==="running"||t.status==="starting"){d$1.warn(this.name,"Already running \u2013 ignoring start()");return}this.patch({status:"starting",isRestarting:false,children:[],restartCount:0,backoffTime:d,probeFailures:0,startTime:null}),this.clearTimers(),this.stopProbe(),d$1.info(this.name,"Initializing fresh start...");try{await this.spawnAll(),this.cfg.devMode&&this.watchFiles();}catch(e){this.patch({status:"errored"}),d$1.error(this.name,`Start failed: ${e.message}`);}}async stop(){let t=this.mp();if(t.status==="stopping"){d$1.info(this.name,"Already stopping...");return}this.patch({status:"stopping",isRestarting:false}),d$1.info(this.name,`Stopping ${t.children.length} instances...`),this.clearTimers(),this.stopProbe(),this.stopWatcher();try{await Promise.race([Promise.all(t.children.map(e=>K(e,this.cfg.killTimeout??O))),new Promise((e,s)=>setTimeout(()=>s(new Error("Termination timeout")),1e4))]);}catch(e){d$1.error(this.name,`Stop timed out, forcing state reset: ${e.message||"UNKNOWN"}`);}this.patch({children:[],status:"stopped",startTime:null}),this.stopWatcher(),d$1.success(this.name,"Stopped.");}async restart(){await this.stop(),await this.start();}async getStats(){let t=this.mp(),e=t.children[0]?.pid??null,s=null,i=null,o=null;if(e&&t.status==="running")try{let n=await D(e);s=n.cpu,i=n.memory;}catch{}return {name:this.name,status:t.status,pid:e,uptime:t.startTime?Date.now()-t.startTime:null,restartCount:t.restartCount,cpu:s,memoryRss:i,memoryHeap:o,mode:this.cfg.mode??"fork",instances:t.children.length}}async spawnAll(){if(!u.existsSync(this.cfg.scriptPath)){d$1.error(this.name,`Script not found: ${this.cfg.scriptPath}. Waiting for build...`),this.patch({status:"errored"});return}this.cfg.port&&await q(this.cfg.port);let t=this.cfg.mode??"fork",e=t==="cluster"?this.cfg.instances??S.cpus().length:1,s=[];for(let o=0;o<e;o++){let n=this.forkChild();n&&s.push(n);}if(s.length===0){d$1.error(this.name,"Failed to spawn any instances."),this.patch({status:"stopped"});return}this.patch({children:s,startTime:Date.now(),status:"running"}),d$1.success(this.name,`Started ${s.length} instance(s) [${t}]`);let i=setTimeout(()=>{this.mp().status==="running"&&(this.patch({backoffTime:d,restartCount:0}),d$1.success(this.name,"Process is stable."));},j);this.patch({stabilityTimer:i}),this.cfg.probe&&this.startProbe();}forkChild(){try{let t=this.cfg.scriptPath.endsWith(".js"),e=c.isAbsolute(this.cfg.scriptPath),s,i,o;t?(s=process.execPath,i=[this.cfg.scriptPath,...this.cfg.args??[]],o=c.dirname(c.resolve(this.cfg.scriptPath,".."))):(s=this.cfg.scriptPath,i=[...this.cfg.args??[]],o=e?c.dirname(this.cfg.scriptPath):process.cwd());let n=spawn(s,i,{cwd:o,stdio:["ignore","pipe","pipe"],env:{...process.env,...this.cfg.env??{},NODE_ENV:this.cfg.devMode?"development":"production",PATH:`${c.resolve(process.cwd(),"node_modules/.bin")}${c.delimiter}${process.env.PATH}`},detached:!1,shell:!t});this.setupLogging(n);let h=Date.now();return n.on("error",l=>{d$1.error(this.name,`Spawn error (${s}):`,l.message);}),n.on("exit",(l,W)=>{let $=Date.now()-h;this.onChildExit(n,l,W,$);}),n}catch(t){return d$1.error(this.name,"Failed to fork child:",t.message),null}}_forkChild(){try{let t=this.cfg.scriptPath.endsWith(".js")?"node":this.cfg.scriptPath,e=this.cfg.scriptPath.endsWith(".js")?[this.cfg.scriptPath,...this.cfg.args??[]]:[...this.cfg.args??[]],s=spawn(t,e,{cwd:c.dirname(c.resolve(this.cfg.scriptPath,"..")),stdio:["ignore","pipe","pipe"],env:{...process.env,...this.cfg.env??{},NODE_ENV:this.cfg.devMode?"development":"production"},detached:!1,shell:!1});this.setupLogging(s);let i=Date.now();return s.on("error",o=>{d$1.error(this.name,"Spawn error:",o);}),s.on("exit",(o,n)=>{let h=Date.now()-i;this.onChildExit(s,o,n,h);}),s}catch(t){return d$1.error(this.name,"Failed to fork child:",t),null}}onChildExit(t,e,s,i){let o=this.mp(),n=o.children.filter(h=>h!==t);if(this.patch({children:n}),o.isRestarting){n.length===0?(d$1.info(this.name,"All instances stopped. Spawning new ones..."),this.patch({isRestarting:false}),this.spawnAll()):d$1.info(this.name,`Restart in progress... waiting for ${n.length} instance(s) to stop.`);return}if(o.status==="stopping"){n.length===0?(d$1.info(this.name,"All instances dead. Spawning new ones..."),this.patch({isRestarting:false}),this.spawnAll()):d$1.info(this.name,`Stop in progress... waiting for ${n.length} instance(s) to stop.`);return}d$1.warn(this.name,`Process exited (code=${e}, signal=${s}, uptime=${i}ms)`),e!==0&&e!==null&&(this.patch({status:"crashed"}),i<1500&&d$1.error(this.name,`Immediate crash (${i}ms) \u2013 likely a syntax/build error. Waiting for next file change.`),this.scheduleRestart());}scheduleRestart(){let t=this.mp(),e=t.backoffTime,s=this.cfg.maxBackoff??B;d$1.warn(this.name,`Scheduling restart in ${e}ms (attempt #${t.restartCount+1})`);let i=setTimeout(async()=>{this.patch({restartCount:t.restartCount+1,backoffTime:Math.min(e*2,s)}),await this.spawnAll();},e);this.patch({restartTimer:i});}startProbe(){let t=this.cfg.probe,e=(t.intervalSeconds??10)*1e3,s=t.failureThreshold??3,o=setInterval(async()=>{let n=this.mp();if(n.status!=="running")return;if(await v(t)){n.probeFailures>0&&this.patch({probeFailures:0});return}let l=n.probeFailures+1;this.patch({probeFailures:l}),d$1.warn(this.name,`Liveness probe failed (${l}/${s})`),l>=s&&(d$1.error(this.name,"Liveness probe threshold exceeded \u2013 restarting."),this.patch({probeFailures:0}),await this.restart());},e);this.patch({probeTimer:o});}stopProbe(){let{probeTimer:t}=this.mp();t&&(clearInterval(t),this.patch({probeTimer:null,probeFailures:0}));}findProjectRoot(t){let e=c.resolve(t);for(u.existsSync(e)&&u.statSync(e).isFile()&&(e=c.dirname(e));e!==c.parse(e).root;){if(u.existsSync(c.join(e,"package.json")))return e;e=c.dirname(e);}return process.cwd()}watchFiles(){this.stopWatcher();let t=this.findProjectRoot(this.cfg.scriptPath),e=c.resolve(t,"src");d$1.info(this.name,f.gray(`Watcher active on: ${e}`)),this.watcher=M.watch(e,{ignored:[/node_modules/,/\.pid$/],persistent:true,ignoreInitial:true,awaitWriteFinish:{stabilityThreshold:1500,pollInterval:500}}),this.watcher.on("all",async(s,i)=>{if(!this.isBuilding&&(s==="change"||s==="add"))if(d$1.info(this.name,f.yellow(`File ${s}: ${c.basename(i)} \u2013 restarting`)),this.cfg.reloadCommand){this.isBuilding=true,d$1.info(this.name,f.blue(`Executing: ${this.cfg.reloadCommand}`));let{exec:o}=await import('child_process');o(this.cfg.reloadCommand,{cwd:t,env:{...process.env,PATH:`${c.resolve(t,"node_modules/.bin")}${c.delimiter}${process.env.PATH}`}},(n,h,l)=>{if(this.isBuilding=false,n){d$1.error(this.name,`Build Failed:
2
- ${l||h||n.message}`);return}d$1.success(this.name,"Build successful. Triggering restart..."),this.restart();});}else this.restart();}),this.watcher.on("error",s=>d$1.error(this.name,"Watcher error:",s)),this.watcher.on("ready",()=>d$1.info(this.name,`Watching ${t}`));}stopWatcher(){this.watcher&&(this.watcher.close(),this.watcher=null);}initStore(){e.set(this.name,{config:this.cfg,children:[],status:"stopped",startTime:null,restartCount:0,backoffTime:d,restartTimer:null,stabilityTimer:null,probeTimer:null,probeFailures:0,isRestarting:false});}mp(){return e.get(this.name)}_patch(t){e.set(this.name,{...this.mp(),...t});}patch(t){let e$1=this.mp();t.status&&t.status!==e$1.status&&d$1.info(this.name,`[STATE] ${e$1.status} \u2794 ${t.status}${t.isRestarting?" (Restarting)":""}`),t.lastError&&d$1.error(this.name,`[REASON] ${t.lastError}`),e.set(this.name,{...e$1,...t});}clearTimers(){let{restartTimer:t,stabilityTimer:e}=this.mp();t&&clearTimeout(t),e&&clearTimeout(e),this.patch({restartTimer:null,stabilityTimer:null});}setupLogging(t){let e=this.cfg.logs?.wsUrl,s=null;e&&(s=new k(e),s.on("open",()=>d$1.debug(this.name,"Connected to log collector")),s.on("error",o=>d$1.error(this.name,"Log Collector WS Error",o.message)));let i=o=>{let n=o.toString();this.cfg.devMode&&process.stdout.write(`[${this.name}] ${n}`),s&&s.readyState===k.OPEN&&s.send(JSON.stringify({app:this.name,timestamp:Date.now(),log:n}));};t.stdout?.on("data",i),t.stderr?.on("data",i);}};var C=class{workers=new Map;SNAPSHOT_FILE=c.join(S.homedir(),".zpm","snapshot.json");async start(t){let e$1=this.workers.get(t.name);if(e$1){let i=e.get(t.name);if(i?.status==="stopped"||i?.status==="crashed"||i?.status==="errored"){d$1.info("ZPM",`Resuming existing worker "${t.name}"`),await e$1.start();return}d$1.warn("ZPM",`Worker "${f.cyan(t.name)}" is ${f.cyan(i?.status)} - use restart()`);return}let s=new p(t);this.workers.set(t.name,s),await s.start(),this.saveSnapshot();}async stop(t){let e=this.require(t);e&&(await e.stop(),this.saveSnapshot());}async restart(t){let e=this.require(t);e&&(await e.restart(),this.saveSnapshot());}async delete(t){let e$1=this.require(t);e$1&&(await e$1.stop(),this.workers.delete(t),e.delete(t),this.saveSnapshot(),d$1.info("PM",`Deleted worker "${t}"`));}async getStats(t){if(t){let s=this.require(t);return s?[await s.getStats()]:[]}return await Promise.all([...this.workers.values()].map(s=>s.getStats()))}list(){return [...this.workers.keys()]}getAllConfigs(){return Array.from(this.workers.values()).map(t=>t.getConfig())}async stopAll(){d$1.info("PM","Stopping all workers..."),await Promise.all([...this.workers.values()].map(t=>t.stop())),d$1.info("PM","All workers stopped."),this.saveSnapshot();}getWorker(t){let e=this.workers.get(t);return e||(d$1.error(t,"Worker Not Found"),null)}async addWorker(t,e){let s=new p(t);this.workers.set(t.name,s),e&&await s.start(),this.saveSnapshot();}require(t){let e=this.workers.get(t);return e||(d$1.error(t,"Worker Not Found"),null)}saveSnapshot(){try{let t=c.dirname(this.SNAPSHOT_FILE);u.existsSync(t)||u.mkdirSync(t,{recursive:!0});let e=this.getAllConfigs();u.writeFileSync(this.SNAPSHOT_FILE,JSON.stringify(e,null,2)),d$1.info("daemon",`Saved snapshot of ${e.length} workers.`);}catch(t){d$1.error("daemon","Failed to save snapshot:",t.message);}}};export{v as a,p as b,C as c};
@@ -1,3 +0,0 @@
1
- 'use strict';var chunkWPWZGJN5_cjs=require('./chunk-WPWZGJN5.cjs'),child_process=require('child_process'),F=require('http'),x=require('https'),A=require('net'),I=require('chokidar'),u=require('fs'),k=require('os'),c=require('path'),f=require('picocolors'),P=require('ws'),L=require('pidusage');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var F__default=/*#__PURE__*/_interopDefault(F);var x__default=/*#__PURE__*/_interopDefault(x);var A__default=/*#__PURE__*/_interopDefault(A);var I__default=/*#__PURE__*/_interopDefault(I);var u__default=/*#__PURE__*/_interopDefault(u);var k__default=/*#__PURE__*/_interopDefault(k);var c__default=/*#__PURE__*/_interopDefault(c);var f__default=/*#__PURE__*/_interopDefault(f);var P__default=/*#__PURE__*/_interopDefault(P);var L__default=/*#__PURE__*/_interopDefault(L);/* ZuzJS Process Manager */
2
- function E(a,t){return new Promise(e=>{let i=(a.startsWith("https")?x__default.default:F__default.default).get(a,{timeout:t},o=>{e((o.statusCode??500)<500);});i.on("error",()=>e(false)),i.on("timeout",()=>{i.destroy(),e(false);});})}function _(a,t){let[e,s]=a.split(":"),i=Number(s);return new Promise(o=>{let n=A__default.default.createConnection({host:e,port:i},()=>{n.destroy(),o(true);});n.setTimeout(t),n.on("timeout",()=>{n.destroy(),o(false);}),n.on("error",()=>o(false));})}function R(a,t){return new Promise(e=>{let s=setTimeout(()=>e(false),t);child_process.exec(a,i=>{clearTimeout(s),e(!i);});})}async function b(a){let t=(a.timeoutSeconds??5)*1e3;switch(a.type){case "http":return E(a.target,t);case "tcp":return _(a.target,t);case "exec":return R(a.target,t);default:return false}}var D=5e3,O=16e3,d=1e3,B=5e3;async function j(a){return new Promise(t=>{A__default.default.createServer().once("error",()=>t(false)).once("listening",function(){this.close(()=>t(true));}).listen(a);})}async function H(a){if(await j(a))return;let t=k__default.default.platform()==="darwin"?`lsof -ti :${a} | xargs kill -9 2>/dev/null || true`:`fuser -k -9 ${a}/tcp 2>/dev/null; true`;await new Promise(e=>child_process.exec(t,()=>e())),await new Promise(e=>setTimeout(e,800));}async function q(a,t){let e=a.process?.pid??a.pid;if(e)return new Promise(s=>{let i=false,o=()=>{i||(i=true,clearTimeout(n),s());};a.once?.("exit",o),a.once?.("exit",o);try{process.kill(e,"SIGTERM");}catch{return o()}let n=setTimeout(()=>{try{process.kill(e,"SIGKILL"),setTimeout(o,100);}catch{o();}},t),h=setInterval(()=>{try{process.kill(e,0);}catch{clearInterval(h),o();}},500);})}var p=class{cfg;name;watcher=null;isBuilding=false;constructor(t){this.cfg={mode:"fork",instances:1,...t},this.name=t.name,this.initStore();}getConfig(){return this.cfg}async start(){let t=this.mp();if(t.status==="running"||t.status==="starting"){chunkWPWZGJN5_cjs.d.warn(this.name,"Already running \u2013 ignoring start()");return}this.patch({status:"starting",isRestarting:false,children:[],restartCount:0,backoffTime:d,probeFailures:0,startTime:null}),this.clearTimers(),this.stopProbe(),chunkWPWZGJN5_cjs.d.info(this.name,"Initializing fresh start...");try{await this.spawnAll(),this.cfg.devMode&&this.watchFiles();}catch(e){this.patch({status:"errored"}),chunkWPWZGJN5_cjs.d.error(this.name,`Start failed: ${e.message}`);}}async stop(){let t=this.mp();if(t.status==="stopping"){chunkWPWZGJN5_cjs.d.info(this.name,"Already stopping...");return}this.patch({status:"stopping",isRestarting:false}),chunkWPWZGJN5_cjs.d.info(this.name,`Stopping ${t.children.length} instances...`),this.clearTimers(),this.stopProbe(),this.stopWatcher();try{await Promise.race([Promise.all(t.children.map(e=>q(e,this.cfg.killTimeout??D))),new Promise((e,s)=>setTimeout(()=>s(new Error("Termination timeout")),1e4))]);}catch(e){chunkWPWZGJN5_cjs.d.error(this.name,`Stop timed out, forcing state reset: ${e.message||"UNKNOWN"}`);}this.patch({children:[],status:"stopped",startTime:null}),this.stopWatcher(),chunkWPWZGJN5_cjs.d.success(this.name,"Stopped.");}async restart(){await this.stop(),await this.start();}async getStats(){let t=this.mp(),e=t.children[0]?.pid??null,s=null,i=null,o=null;if(e&&t.status==="running")try{let n=await L__default.default(e);s=n.cpu,i=n.memory;}catch{}return {name:this.name,status:t.status,pid:e,uptime:t.startTime?Date.now()-t.startTime:null,restartCount:t.restartCount,cpu:s,memoryRss:i,memoryHeap:o,mode:this.cfg.mode??"fork",instances:t.children.length}}async spawnAll(){if(!u__default.default.existsSync(this.cfg.scriptPath)){chunkWPWZGJN5_cjs.d.error(this.name,`Script not found: ${this.cfg.scriptPath}. Waiting for build...`),this.patch({status:"errored"});return}this.cfg.port&&await H(this.cfg.port);let t=this.cfg.mode??"fork",e=t==="cluster"?this.cfg.instances??k__default.default.cpus().length:1,s=[];for(let o=0;o<e;o++){let n=this.forkChild();n&&s.push(n);}if(s.length===0){chunkWPWZGJN5_cjs.d.error(this.name,"Failed to spawn any instances."),this.patch({status:"stopped"});return}this.patch({children:s,startTime:Date.now(),status:"running"}),chunkWPWZGJN5_cjs.d.success(this.name,`Started ${s.length} instance(s) [${t}]`);let i=setTimeout(()=>{this.mp().status==="running"&&(this.patch({backoffTime:d,restartCount:0}),chunkWPWZGJN5_cjs.d.success(this.name,"Process is stable."));},B);this.patch({stabilityTimer:i}),this.cfg.probe&&this.startProbe();}forkChild(){try{let t=this.cfg.scriptPath.endsWith(".js"),e=c__default.default.isAbsolute(this.cfg.scriptPath),s,i,o;t?(s=process.execPath,i=[this.cfg.scriptPath,...this.cfg.args??[]],o=c__default.default.dirname(c__default.default.resolve(this.cfg.scriptPath,".."))):(s=this.cfg.scriptPath,i=[...this.cfg.args??[]],o=e?c__default.default.dirname(this.cfg.scriptPath):process.cwd());let n=child_process.spawn(s,i,{cwd:o,stdio:["ignore","pipe","pipe"],env:{...process.env,...this.cfg.env??{},NODE_ENV:this.cfg.devMode?"development":"production",PATH:`${c__default.default.resolve(process.cwd(),"node_modules/.bin")}${c__default.default.delimiter}${process.env.PATH}`},detached:!1,shell:!t});this.setupLogging(n);let h=Date.now();return n.on("error",l=>{chunkWPWZGJN5_cjs.d.error(this.name,`Spawn error (${s}):`,l.message);}),n.on("exit",(l,C)=>{let W=Date.now()-h;this.onChildExit(n,l,C,W);}),n}catch(t){return chunkWPWZGJN5_cjs.d.error(this.name,"Failed to fork child:",t.message),null}}_forkChild(){try{let t=this.cfg.scriptPath.endsWith(".js")?"node":this.cfg.scriptPath,e=this.cfg.scriptPath.endsWith(".js")?[this.cfg.scriptPath,...this.cfg.args??[]]:[...this.cfg.args??[]],s=child_process.spawn(t,e,{cwd:c__default.default.dirname(c__default.default.resolve(this.cfg.scriptPath,"..")),stdio:["ignore","pipe","pipe"],env:{...process.env,...this.cfg.env??{},NODE_ENV:this.cfg.devMode?"development":"production"},detached:!1,shell:!1});this.setupLogging(s);let i=Date.now();return s.on("error",o=>{chunkWPWZGJN5_cjs.d.error(this.name,"Spawn error:",o);}),s.on("exit",(o,n)=>{let h=Date.now()-i;this.onChildExit(s,o,n,h);}),s}catch(t){return chunkWPWZGJN5_cjs.d.error(this.name,"Failed to fork child:",t),null}}onChildExit(t,e,s,i){let o=this.mp(),n=o.children.filter(h=>h!==t);if(this.patch({children:n}),o.isRestarting){n.length===0?(chunkWPWZGJN5_cjs.d.info(this.name,"All instances stopped. Spawning new ones..."),this.patch({isRestarting:false}),this.spawnAll()):chunkWPWZGJN5_cjs.d.info(this.name,`Restart in progress... waiting for ${n.length} instance(s) to stop.`);return}if(o.status==="stopping"){n.length===0?(chunkWPWZGJN5_cjs.d.info(this.name,"All instances dead. Spawning new ones..."),this.patch({isRestarting:false}),this.spawnAll()):chunkWPWZGJN5_cjs.d.info(this.name,`Stop in progress... waiting for ${n.length} instance(s) to stop.`);return}chunkWPWZGJN5_cjs.d.warn(this.name,`Process exited (code=${e}, signal=${s}, uptime=${i}ms)`),e!==0&&e!==null&&(this.patch({status:"crashed"}),i<1500&&chunkWPWZGJN5_cjs.d.error(this.name,`Immediate crash (${i}ms) \u2013 likely a syntax/build error. Waiting for next file change.`),this.scheduleRestart());}scheduleRestart(){let t=this.mp(),e=t.backoffTime,s=this.cfg.maxBackoff??O;chunkWPWZGJN5_cjs.d.warn(this.name,`Scheduling restart in ${e}ms (attempt #${t.restartCount+1})`);let i=setTimeout(async()=>{this.patch({restartCount:t.restartCount+1,backoffTime:Math.min(e*2,s)}),await this.spawnAll();},e);this.patch({restartTimer:i});}startProbe(){let t=this.cfg.probe,e=(t.intervalSeconds??10)*1e3,s=t.failureThreshold??3,o=setInterval(async()=>{let n=this.mp();if(n.status!=="running")return;if(await b(t)){n.probeFailures>0&&this.patch({probeFailures:0});return}let l=n.probeFailures+1;this.patch({probeFailures:l}),chunkWPWZGJN5_cjs.d.warn(this.name,`Liveness probe failed (${l}/${s})`),l>=s&&(chunkWPWZGJN5_cjs.d.error(this.name,"Liveness probe threshold exceeded \u2013 restarting."),this.patch({probeFailures:0}),await this.restart());},e);this.patch({probeTimer:o});}stopProbe(){let{probeTimer:t}=this.mp();t&&(clearInterval(t),this.patch({probeTimer:null,probeFailures:0}));}findProjectRoot(t){let e=c__default.default.resolve(t);for(u__default.default.existsSync(e)&&u__default.default.statSync(e).isFile()&&(e=c__default.default.dirname(e));e!==c__default.default.parse(e).root;){if(u__default.default.existsSync(c__default.default.join(e,"package.json")))return e;e=c__default.default.dirname(e);}return process.cwd()}watchFiles(){this.stopWatcher();let t=this.findProjectRoot(this.cfg.scriptPath),e=c__default.default.resolve(t,"src");chunkWPWZGJN5_cjs.d.info(this.name,f__default.default.gray(`Watcher active on: ${e}`)),this.watcher=I__default.default.watch(e,{ignored:[/node_modules/,/\.pid$/],persistent:true,ignoreInitial:true,awaitWriteFinish:{stabilityThreshold:1500,pollInterval:500}}),this.watcher.on("all",async(s,i)=>{if(!this.isBuilding&&(s==="change"||s==="add"))if(chunkWPWZGJN5_cjs.d.info(this.name,f__default.default.yellow(`File ${s}: ${c__default.default.basename(i)} \u2013 restarting`)),this.cfg.reloadCommand){this.isBuilding=true,chunkWPWZGJN5_cjs.d.info(this.name,f__default.default.blue(`Executing: ${this.cfg.reloadCommand}`));let{exec:o}=await import('child_process');o(this.cfg.reloadCommand,{cwd:t,env:{...process.env,PATH:`${c__default.default.resolve(t,"node_modules/.bin")}${c__default.default.delimiter}${process.env.PATH}`}},(n,h,l)=>{if(this.isBuilding=false,n){chunkWPWZGJN5_cjs.d.error(this.name,`Build Failed:
3
- ${l||h||n.message}`);return}chunkWPWZGJN5_cjs.d.success(this.name,"Build successful. Triggering restart..."),this.restart();});}else this.restart();}),this.watcher.on("error",s=>chunkWPWZGJN5_cjs.d.error(this.name,"Watcher error:",s)),this.watcher.on("ready",()=>chunkWPWZGJN5_cjs.d.info(this.name,`Watching ${t}`));}stopWatcher(){this.watcher&&(this.watcher.close(),this.watcher=null);}initStore(){chunkWPWZGJN5_cjs.e.set(this.name,{config:this.cfg,children:[],status:"stopped",startTime:null,restartCount:0,backoffTime:d,restartTimer:null,stabilityTimer:null,probeTimer:null,probeFailures:0,isRestarting:false});}mp(){return chunkWPWZGJN5_cjs.e.get(this.name)}_patch(t){chunkWPWZGJN5_cjs.e.set(this.name,{...this.mp(),...t});}patch(t){let e=this.mp();t.status&&t.status!==e.status&&chunkWPWZGJN5_cjs.d.info(this.name,`[STATE] ${e.status} \u2794 ${t.status}${t.isRestarting?" (Restarting)":""}`),t.lastError&&chunkWPWZGJN5_cjs.d.error(this.name,`[REASON] ${t.lastError}`),chunkWPWZGJN5_cjs.e.set(this.name,{...e,...t});}clearTimers(){let{restartTimer:t,stabilityTimer:e}=this.mp();t&&clearTimeout(t),e&&clearTimeout(e),this.patch({restartTimer:null,stabilityTimer:null});}setupLogging(t){let e=this.cfg.logs?.wsUrl,s=null;e&&(s=new P__default.default(e),s.on("open",()=>chunkWPWZGJN5_cjs.d.debug(this.name,"Connected to log collector")),s.on("error",o=>chunkWPWZGJN5_cjs.d.error(this.name,"Log Collector WS Error",o.message)));let i=o=>{let n=o.toString();this.cfg.devMode&&process.stdout.write(`[${this.name}] ${n}`),s&&s.readyState===P__default.default.OPEN&&s.send(JSON.stringify({app:this.name,timestamp:Date.now(),log:n}));};t.stdout?.on("data",i),t.stderr?.on("data",i);}};var T=class{workers=new Map;SNAPSHOT_FILE=c__default.default.join(k__default.default.homedir(),".zpm","snapshot.json");async start(t){let e=this.workers.get(t.name);if(e){let i=chunkWPWZGJN5_cjs.e.get(t.name);if(i?.status==="stopped"||i?.status==="crashed"||i?.status==="errored"){chunkWPWZGJN5_cjs.d.info("ZPM",`Resuming existing worker "${t.name}"`),await e.start();return}chunkWPWZGJN5_cjs.d.warn("ZPM",`Worker "${f__default.default.cyan(t.name)}" is ${f__default.default.cyan(i?.status)} - use restart()`);return}let s=new p(t);this.workers.set(t.name,s),await s.start(),this.saveSnapshot();}async stop(t){let e=this.require(t);e&&(await e.stop(),this.saveSnapshot());}async restart(t){let e=this.require(t);e&&(await e.restart(),this.saveSnapshot());}async delete(t){let e=this.require(t);e&&(await e.stop(),this.workers.delete(t),chunkWPWZGJN5_cjs.e.delete(t),this.saveSnapshot(),chunkWPWZGJN5_cjs.d.info("PM",`Deleted worker "${t}"`));}async getStats(t){if(t){let s=this.require(t);return s?[await s.getStats()]:[]}return await Promise.all([...this.workers.values()].map(s=>s.getStats()))}list(){return [...this.workers.keys()]}getAllConfigs(){return Array.from(this.workers.values()).map(t=>t.getConfig())}async stopAll(){chunkWPWZGJN5_cjs.d.info("PM","Stopping all workers..."),await Promise.all([...this.workers.values()].map(t=>t.stop())),chunkWPWZGJN5_cjs.d.info("PM","All workers stopped."),this.saveSnapshot();}getWorker(t){let e=this.workers.get(t);return e||(chunkWPWZGJN5_cjs.d.error(t,"Worker Not Found"),null)}async addWorker(t,e){let s=new p(t);this.workers.set(t.name,s),e&&await s.start(),this.saveSnapshot();}require(t){let e=this.workers.get(t);return e||(chunkWPWZGJN5_cjs.d.error(t,"Worker Not Found"),null)}saveSnapshot(){try{let t=c__default.default.dirname(this.SNAPSHOT_FILE);u__default.default.existsSync(t)||u__default.default.mkdirSync(t,{recursive:!0});let e=this.getAllConfigs();u__default.default.writeFileSync(this.SNAPSHOT_FILE,JSON.stringify(e,null,2)),chunkWPWZGJN5_cjs.d.info("daemon",`Saved snapshot of ${e.length} workers.`);}catch(t){chunkWPWZGJN5_cjs.d.error("daemon","Failed to save snapshot:",t.message);}}};exports.a=b;exports.b=p;exports.c=T;