daimon 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/dist/cli.js +71 -67
- package/dist/dashboard/3rdpartylicenses.txt +4 -4
- package/dist/dashboard/browser/chunk-4VNZXWQZ.js +3 -0
- package/dist/dashboard/browser/chunk-4ZR4NTJW.js +1 -0
- package/dist/dashboard/browser/{chunk-HFJ25UTJ.js → chunk-7L4DWDGL.js} +4 -4
- package/dist/dashboard/browser/{chunk-C65CUT7O.js → chunk-BLNPJ4WD.js} +4 -4
- package/dist/dashboard/browser/chunk-E3HUMJ6S.js +6 -0
- package/dist/dashboard/browser/chunk-EBOHC6KX.js +1 -0
- package/dist/dashboard/browser/chunk-ESDYJ3BP.js +1 -0
- package/dist/dashboard/browser/chunk-JUZHAE4L.js +2 -0
- package/dist/dashboard/browser/chunk-K43KW4K2.js +4 -0
- package/dist/dashboard/browser/chunk-K46KCL6L.js +1 -0
- package/dist/dashboard/browser/chunk-KDCKLTCZ.js +1 -0
- package/dist/dashboard/browser/{chunk-JX3IOOXU.js → chunk-L63FHXGH.js} +1 -1
- package/dist/dashboard/browser/{chunk-Q7R63OUT.js → chunk-LBRCWYRN.js} +1 -1
- package/dist/dashboard/browser/chunk-MHOSWLRR.js +3 -0
- package/dist/dashboard/browser/{chunk-TSB6OOH2.js → chunk-N5GRSTMJ.js} +1 -1
- package/dist/dashboard/browser/{chunk-AEERNAF7.js → chunk-NDSAQ2HK.js} +1 -1
- package/dist/dashboard/browser/chunk-NN2YNLGP.js +3 -0
- package/dist/dashboard/browser/{chunk-3TYCIBMV.js → chunk-PJPGLT4T.js} +1 -1
- package/dist/dashboard/browser/chunk-R6J2WYUD.js +1 -0
- package/dist/dashboard/browser/chunk-T2YKGOEM.js +3 -0
- package/dist/dashboard/browser/chunk-U6AY7XZK.js +5 -0
- package/dist/dashboard/browser/{chunk-ZVU34B5S.js → chunk-UC3XMN2Y.js} +1 -1
- package/dist/dashboard/browser/chunk-UNT27XFJ.js +2 -0
- package/dist/dashboard/browser/chunk-V2CQL6W5.js +1 -0
- package/dist/dashboard/browser/chunk-VZ6E4VQY.js +2 -0
- package/dist/dashboard/browser/chunk-WJUGRIIZ.js +1 -0
- package/dist/dashboard/browser/{chunk-D4BFRQ63.js → chunk-WRBP4DQN.js} +4 -4
- package/dist/dashboard/browser/chunk-XUU4AY4M.js +2 -0
- package/dist/dashboard/browser/chunk-XYVF5I5T.js +1 -0
- package/dist/dashboard/browser/chunk-Y6B6X4Y6.js +2 -0
- package/dist/dashboard/browser/chunk-YNQPX5G6.js +1 -0
- package/dist/dashboard/browser/{chunk-SLQ2WBUA.js → chunk-YYAZGY5M.js} +1 -1
- package/dist/dashboard/browser/index.html +1 -1
- package/dist/dashboard/browser/main-ZADV4SOC.js +1 -0
- package/dist/main.js +48 -44
- package/dist/mcp.js +3 -2
- package/package.json +2 -2
- package/dist/dashboard/browser/chunk-5UAN6ETO.js +0 -1
- package/dist/dashboard/browser/chunk-AX3RJNG4.js +0 -1
- package/dist/dashboard/browser/chunk-BADBUP5C.js +0 -3
- package/dist/dashboard/browser/chunk-BF6RQFHS.js +0 -2
- package/dist/dashboard/browser/chunk-CNIZYK4A.js +0 -1
- package/dist/dashboard/browser/chunk-E235WGFQ.js +0 -3
- package/dist/dashboard/browser/chunk-F2EDJ6FT.js +0 -4
- package/dist/dashboard/browser/chunk-HFAARBWL.js +0 -1
- package/dist/dashboard/browser/chunk-LQNYSOSZ.js +0 -1
- package/dist/dashboard/browser/chunk-MBVVV35N.js +0 -1
- package/dist/dashboard/browser/chunk-NC2VPB4Y.js +0 -2
- package/dist/dashboard/browser/chunk-NXNVIINH.js +0 -1
- package/dist/dashboard/browser/chunk-QLKOKZDG.js +0 -9
- package/dist/dashboard/browser/chunk-QQSPJIPQ.js +0 -1
- package/dist/dashboard/browser/chunk-SCAIGUJL.js +0 -6
- package/dist/dashboard/browser/chunk-WWUKM5OG.js +0 -1
- package/dist/dashboard/browser/chunk-ZYE3XQS4.js +0 -2
- package/dist/dashboard/browser/main-Z6L5VPBT.js +0 -4
package/dist/main.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,"utf8"),{kind:"stub-created",path:t}}var
|
|
3
|
-
`);return[...e.values()].filter(
|
|
1
|
+
var Zr=Object.defineProperty;var tt=(n,t)=>()=>(n&&(t=n(n=0)),t);var Zt=(n,t)=>{for(var e in t)Zr(n,e,{get:t[e],enumerable:!0})};var Fe={};Zt(Fe,{configLookupPaths:()=>et,loadConfig:()=>W,validateConfig:()=>Rt});import z from"node:fs";import Y from"node:path";import gt from"node:os";import{fileURLToPath as Qr}from"node:url";function De(){return{searchRoots:[],portRange:[4200,4299],apiPort:4999,overrides:{},autoStart:[],profiles:{},tags:{},autoRestart:{enabled:!1,maxAttempts:5,windowMs:3e5},healthProbe:{enabled:!0,intervalMs:3e4,timeoutMs:2e3,path:"/",host:null,scheme:null,rejectUnauthorized:!1,fallbackHosts:["127.0.0.1","::1"]},logs:{enabled:!1,dir:Y.join(gt.homedir(),".daimon","logs"),maxFiles:5,maxBytesPerFile:1e7},depends:{},cascadeRestart:!1,history:{enabled:!0,path:Y.join(gt.homedir(),".daimon","history.db"),retentionDays:30},notifications:{enabled:!0,onError:!0,onUnhealthy:!0,tray:!1},staleDetect:{enabled:!0,silentMs:3e4},headless:!1,envFiles:{},requestLog:{enabled:!1,portOffset:1e3},metrics:{enabled:!1},editor:{scheme:"vscode"},apiToken:null,output:{format:"compact",ndjson:!1},doctor:{autoFix:{onInit:!1,permitted:["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","dead-search-root"]}},dashboard:{theme:"auto",density:"comfortable"}}}function Le(n){return n.startsWith("~/")||n.startsWith("~\\")?Y.join(gt.homedir(),n.slice(2)):n==="~"?gt.homedir():n}function Rt(n,t){return Qt(n,t)}function Qt(n,t){if(!n||typeof n!="object")throw new Error(`Config at ${t} is not a JSON object`);let e=n,r=De();if(e.searchRoots!==void 0){if(!Array.isArray(e.searchRoots)||!e.searchRoots.every(s=>typeof s=="string"||s&&typeof s=="object"&&typeof s.path=="string"))throw new Error(`Config "searchRoots" must be an array of strings or { path, viteSubfolders? } objects (${t})`);r.searchRoots=e.searchRoots}if(e.portRange!==void 0){if(!Array.isArray(e.portRange)||e.portRange.length!==2||typeof e.portRange[0]!="number"||typeof e.portRange[1]!="number"||e.portRange[0]>e.portRange[1])throw new Error(`Config "portRange" must be [min, max] numbers (${t})`);r.portRange=[e.portRange[0],e.portRange[1]]}if(e.apiPort!==void 0){if(typeof e.apiPort!="number")throw new Error(`Config "apiPort" must be a number (${t})`);r.apiPort=e.apiPort}if(e.overrides!==void 0){if(typeof e.overrides!="object"||e.overrides===null||Array.isArray(e.overrides))throw new Error(`Config "overrides" must be an object (${t})`);r.overrides=e.overrides}if(e.autoStart!==void 0){if(!Array.isArray(e.autoStart)||!e.autoStart.every(s=>typeof s=="string"))throw new Error(`Config "autoStart" must be an array of strings (${t})`);r.autoStart=e.autoStart}if(e.profiles!==void 0){if(typeof e.profiles!="object"||e.profiles===null||Array.isArray(e.profiles))throw new Error(`Config "profiles" must be an object (${t})`);for(let[s,o]of Object.entries(e.profiles))if(!Array.isArray(o)||!o.every(i=>typeof i=="string"))throw new Error(`Config "profiles.${s}" must be an array of strings (${t})`);r.profiles=e.profiles}if(e.tags!==void 0){if(typeof e.tags!="object"||e.tags===null||Array.isArray(e.tags))throw new Error(`Config "tags" must be an object (${t})`);r.tags=e.tags}if(e.autoRestart&&typeof e.autoRestart=="object"&&(r.autoRestart={...r.autoRestart,...e.autoRestart}),e.healthProbe&&typeof e.healthProbe=="object"&&(r.healthProbe={...r.healthProbe,...e.healthProbe}),e.logs&&typeof e.logs=="object"&&(r.logs={...r.logs,...e.logs},r.logs.dir=Le(r.logs.dir)),e.depends&&typeof e.depends=="object"&&!Array.isArray(e.depends)){for(let[s,o]of Object.entries(e.depends))if(!Array.isArray(o)||!o.every(i=>typeof i=="string"))throw new Error(`Config "depends.${s}" must be an array of strings (${t})`);r.depends=e.depends}if(typeof e.cascadeRestart=="boolean"&&(r.cascadeRestart=e.cascadeRestart),e.history&&typeof e.history=="object"&&(r.history={...r.history,...e.history},r.history.path=Le(r.history.path)),e.notifications&&typeof e.notifications=="object"&&(r.notifications={...r.notifications,...e.notifications}),e.staleDetect&&typeof e.staleDetect=="object"&&(r.staleDetect={...r.staleDetect,...e.staleDetect}),typeof e.headless=="boolean"&&(r.headless=e.headless),e.envFiles&&typeof e.envFiles=="object"&&!Array.isArray(e.envFiles)&&(r.envFiles=e.envFiles),e.requestLog&&typeof e.requestLog=="object"&&(r.requestLog={...r.requestLog,...e.requestLog}),e.metrics&&typeof e.metrics=="object"&&(r.metrics={...r.metrics,...e.metrics}),e.editor&&typeof e.editor=="object"){let s=e.editor.scheme;typeof s=="string"&&s.trim()&&(r.editor={scheme:s.trim()})}if((typeof e.apiToken=="string"||e.apiToken===null)&&(r.apiToken=e.apiToken),e.output&&typeof e.output=="object"){let s=e.output;(s.format==="compact"||s.format==="full")&&(r.output.format=s.format),typeof s.ndjson=="boolean"&&(r.output.ndjson=s.ndjson)}if(e.doctor&&typeof e.doctor=="object"){let s=e.doctor.autoFix;s&&typeof s=="object"&&(typeof s.onInit=="boolean"&&(r.doctor.autoFix.onInit=s.onInit),Array.isArray(s.permitted)&&(r.doctor.autoFix.permitted=s.permitted.filter(o=>typeof o=="string")))}if(e.dashboard&&typeof e.dashboard=="object"){let s=e.dashboard;(s.theme==="auto"||s.theme==="light"||s.theme==="dark")&&(r.dashboard.theme=s.theme),(s.density==="comfortable"||s.density==="compact")&&(r.dashboard.density=s.density)}return r}function et(){return{local:Y.join(process.cwd(),"daimon.config.json"),user:Y.join(gt.homedir(),".daimon","config.json")}}function W(){let{local:n,user:t}=et();if(z.existsSync(n)){let s=JSON.parse(z.readFileSync(n,"utf8"));return{kind:"loaded",config:Qt(s,n),path:n}}if(z.existsSync(t)){let s=JSON.parse(z.readFileSync(t,"utf8"));return{kind:"loaded",config:Qt(s,t),path:t}}let r=[Y.resolve(_e,"..","daimon.config.example.json"),Y.resolve(_e,"..","..","daimon.config.example.json")].find(s=>z.existsSync(s));return z.mkdirSync(Y.dirname(t),{recursive:!0}),r?z.copyFileSync(r,t):z.writeFileSync(t,JSON.stringify(De(),null,2)+`
|
|
2
|
+
`,"utf8"),{kind:"stub-created",path:t}}var tn,_e,yt=tt(()=>{"use strict";tn=Qr(import.meta.url),_e=Y.dirname(tn)});var re={};Zt(re,{discoverApps:()=>wt});import vt from"node:fs";import G from"node:path";import te from"fast-glob";function Ie(n){try{return JSON.parse(vt.readFileSync(n,"utf8"))}catch{return null}}function He(n){return!n||typeof n!="object"?!1:!!(n.targets?.serve||n.architect?.serve)}function Be(n){if(!n||typeof n!="object")return[];let t=n.targets??n.architect??{};return Object.keys(t).filter(e=>e!=="serve").sort()}function ee(n){return n.replace(/\\/g,"/")}function st(n,t){n&&(n.rejected[t]=(n.rejected[t]??0)+1)}function wt(n,t={}){let e=new Map,r=t.warnings??[],s=t.warnings===void 0;for(let o of n.searchRoots){let i=typeof o=="string"?o:o.path,a=typeof o=="string"?!1:!!o.viteSubfolders,u=typeof o=="string"?void 0:o.label,l=G.resolve(i);if(!vt.existsSync(l)){r.push(`searchRoot does not exist: ${l}`),st(t.stats,"searchRoot missing");continue}let h=G.join(l,"nx.json"),p=G.join(l,"angular.json");if(vt.existsSync(h)){let f=te.sync("**/project.json",{cwd:ee(l),ignore:["**/node_modules/**","**/dist/**","**/.nx/**","**/.git/**"],absolute:!0,dot:!1});for(let m of f){t.stats&&(t.stats.scanned+=1);let d=Ie(m);if(!d){st(t.stats,"unreadable project.json");continue}if(!He(d)){st(t.stats,"no serve target");continue}let g=d.name||G.basename(G.dirname(m));if(!g){st(t.stats,"project has no name");continue}if(e.has(g)){r.push(`duplicate project name "${g}" \u2014 keeping first`),st(t.stats,"duplicate name");continue}e.set(g,{name:g,workspaceRoot:l,workspaceType:"nx",command:`npx nx serve ${g}`,hidden:!1,tags:[],tasks:Be(d),workspaceLabel:u})}continue}if(vt.existsSync(p)){let m=Ie(p)?.projects||{};for(let[d,g]of Object.entries(m))if(He(g)){if(e.has(d)){r.push(`duplicate project name "${d}" \u2014 keeping first`);continue}e.set(d,{name:d,workspaceRoot:l,workspaceType:"angular",command:`npx ng serve ${d}`,hidden:!1,tags:[],tasks:Be(g),workspaceLabel:u})}continue}let x=te.sync("vite.config.{ts,js,mjs,cjs}",{cwd:ee(l),absolute:!0,deep:1}),S=vt.existsSync(G.join(l,".storybook")),c=!1;if(x.length>0){let f=G.basename(l);if(e.has(f)||e.set(f,{name:f,workspaceRoot:l,workspaceType:"vite",command:"npx vite",hidden:!1,tags:[],workspaceLabel:u}),c=!0,a){let m=te.sync("*/vite.config.{ts,js,mjs,cjs}",{cwd:ee(l),absolute:!0});for(let d of m){let g=G.dirname(d),R=G.basename(g);R===f||e.has(R)||e.set(R,{name:R,workspaceRoot:g,workspaceType:"vite",command:"npx vite",hidden:!1,tags:[],workspaceLabel:u})}}}if(S){let f=`${G.basename(l)}-storybook`;e.has(f)||e.set(f,{name:f,workspaceRoot:l,workspaceType:"storybook",command:"npx storybook dev --no-open",hidden:!1,tags:[],workspaceLabel:u}),c=!0}c||(r.push(`searchRoot has none of nx.json/angular.json/vite.config.*/.storybook: ${l}`),st(t.stats,"no project markers"))}for(let[o,i]of Object.entries(n.overrides||{})){let a=e.get(o);a?(i.command&&(a.command=i.command),typeof i.hidden=="boolean"&&(a.hidden=i.hidden),typeof i.port=="number"&&(a.pinnedPort=i.port),i.env&&(a.env=i.env)):i.command&&e.set(o,{name:o,workspaceRoot:process.cwd(),workspaceType:"nx",command:i.command,hidden:i.hidden??!1,pinnedPort:i.port,env:i.env,tags:[]})}for(let o of e.values())o.tags=n.tags?.[o.name]??[];if(s&&r.length)for(let o of r)process.stderr.write(`[daimon] warning: ${o}
|
|
3
|
+
`);return[...e.values()].filter(o=>!o.hidden)}var bt=tt(()=>{"use strict"});import On from"node:net";function it(n){return new Promise(t=>{let e=On.createServer();e.unref(),e.once("error",()=>t(!1)),e.listen({port:n,host:"127.0.0.1",exclusive:!0},()=>{e.close(()=>t(!0))})})}var ot,Ct=tt(()=>{"use strict";ot=class{assigned=new Map;min;max;onChange;constructor(t,e={}){if(this.min=t[0],this.max=t[1],this.onChange=e.onChange,e.initial){let r=new Set;for(let[s,o]of Object.entries(e.initial))typeof o=="number"&&(o<this.min||o>this.max||r.has(o)||(r.add(o),this.assigned.set(s,o)))}}snapshot(){return Object.fromEntries(this.assigned)}getAssigned(t){return this.assigned.get(t)}pin(t,e){this.assigned.set(t,e),this.onChange?.(this.snapshot())}async allocate(t,e){let r=this.assigned.get(t);if(e!==void 0)return this.assigned.set(t,e),this.onChange?.(this.snapshot()),e;if(r!==void 0)return r;let s=new Set(this.assigned.values());for(let o=this.min;o<=this.max;o++){if(s.has(o))continue;if(await it(o))return this.assigned.set(t,o),this.onChange?.(this.snapshot()),o}throw new Error(`No free ports in range ${this.min}-${this.max}`)}async isPortAvailableForUse(t){return it(t)}}});import Ln from"node:fs";import ie from"node:path";import{fileURLToPath as Dn}from"node:url";function Fn(){let n=[ie.resolve(ar,"..","package.json"),ie.resolve(ar,"..","..","package.json")];for(let t of n)try{return JSON.parse(Ln.readFileSync(t,"utf8"))}catch{}return{}}var ar,at,Ot=tt(()=>{"use strict";ar=ie.dirname(Dn(import.meta.url));at=Fn().version||"0.0.0"});import ct from"node:fs";import jt from"node:path";import In from"node:os";import{spawn as Hn}from"node:child_process";import{fileURLToPath as Bn}from"node:url";function V(){return ce}function Nt(){return lt}function ae(n){try{return process.kill(n,0),!0}catch(t){return t&&t.code==="EPERM"}}function ut(){try{let n=ct.readFileSync(lt,"utf8"),t=JSON.parse(n);if(!t||typeof t.pid!="number")return null;if(!ae(t.pid)){try{ct.unlinkSync(lt)}catch{}return null}return t}catch{return null}}function cr(n){ct.mkdirSync(ce,{recursive:!0});let t=lt+"."+process.pid+".tmp";ct.writeFileSync(t,JSON.stringify(n)),ct.renameSync(t,lt)}function St(){try{ct.unlinkSync(lt)}catch{}}function Un(){let n=jt.dirname(Bn(import.meta.url));return jt.join(n,"main.js")}async function le(n={}){let t={...process.env};n.port&&(t.DAIMON_PORT=String(n.port)),Hn(process.execPath,[Un(),"--headless"],{detached:!0,stdio:"ignore",env:t,windowsHide:!0}).unref();let r=Date.now();for(;Date.now()-r<5e3;){let s=ut();if(s&&(!n.port||s.apiPort===n.port))return s;await new Promise(o=>setTimeout(o,100))}throw new Error("daemon failed to start within 5s")}async function lr(n,t){let e=Date.now();for(;Date.now()-e<t;){if(!ae(n))return!0;await new Promise(r=>setTimeout(r,100))}return!ae(n)}function ur(n,t,e){return{pid:process.pid,apiPort:n,version:at,startedAt:Date.now(),headless:t,cwd:process.cwd(),configPath:e}}var ce,lt,rt=tt(()=>{"use strict";Ot();ce=jt.join(In.homedir(),".daimon"),lt=jt.join(ce,"daemon.lock")});import ls from"node:fs";import us from"node:path";import{createRequire as ps}from"node:module";var ds,fs,ms,hs,pt,ye=tt(()=>{"use strict";ds=ps(import.meta.url),fs=200,ms=360*60*1e3,hs=1e4,pt=class{constructor(t){this.cfg=t;if(t.enabled)try{ls.mkdirSync(us.dirname(t.path),{recursive:!0});let e=ds("better-sqlite3");this.db=new e(t.path),this.db.pragma("journal_mode = WAL"),this.migrate(),this.flushTimer=setInterval(()=>this.flush(),fs),this.retentionStart=setTimeout(()=>this.runRetention(),hs),this.retentionTimer=setInterval(()=>this.runRetention(),ms)}catch(e){this.warnOnce(`failed to open history db: ${e?.message||e}`),this.db=null}}cfg;db=null;queue=[];flushTimer=null;retentionTimer=null;retentionStart=null;warned=!1;warnOnce(t){this.warned||(this.warned=!0,process.stderr.write(`[daimon] history: ${t}
|
|
4
4
|
`))}migrate(){this.db&&this.db.exec(`
|
|
5
5
|
CREATE TABLE IF NOT EXISTS events (
|
|
6
6
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -29,52 +29,56 @@ var qr=Object.defineProperty;var tt=(n,t)=>()=>(n&&(t=n(n=0)),t);var je=(n,t)=>{
|
|
|
29
29
|
summary TEXT
|
|
30
30
|
);
|
|
31
31
|
CREATE INDEX IF NOT EXISTS task_runs_app_ts ON task_runs(app, ts);
|
|
32
|
-
`)}recordEvent(t){this.db&&this.queue.push({kind:"event",row:{ts:t.ts,app:t.app,type:t.type,from_state:t.from??null,to_state:t.to??null,message:t.message??null}})}recordCompile(t,e,r=Date.now()){this.db&&this.queue.push({kind:"compile",row:{ts:r,app:t,ms:e}})}recordTaskRun(t,e,r,s,i
|
|
33
|
-
`,"utf8");let
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
`);if(
|
|
32
|
+
`)}recordEvent(t){this.db&&this.queue.push({kind:"event",row:{ts:t.ts,app:t.app,type:t.type,from_state:t.from??null,to_state:t.to??null,message:t.message??null}})}recordCompile(t,e,r=Date.now()){this.db&&this.queue.push({kind:"compile",row:{ts:r,app:t,ms:e}})}recordTaskRun(t,e,r,s,o,i=Date.now()){this.db&&this.queue.push({kind:"task",row:{ts:i,app:t,task:e,exit_code:r,duration_ms:s,summary:o==null?null:JSON.stringify(o)}})}flush(){if(!this.db||this.queue.length===0)return;let t=this.queue;this.queue=[];try{let e=this.db.prepare("INSERT INTO events (ts,app,type,from_state,to_state,message) VALUES (?,?,?,?,?,?)"),r=this.db.prepare("INSERT INTO compile_times (ts,app,ms) VALUES (?,?,?)"),s=this.db.prepare("INSERT INTO task_runs (ts,app,task,exit_code,duration_ms,summary) VALUES (?,?,?,?,?,?)");this.db.transaction(i=>{for(let a of i)a.kind==="event"?e.run(a.row.ts,a.row.app,a.row.type,a.row.from_state,a.row.to_state,a.row.message):a.kind==="compile"?r.run(a.row.ts,a.row.app,a.row.ms):s.run(a.row.ts,a.row.app,a.row.task,a.row.exit_code,a.row.duration_ms,a.row.summary)})(t)}catch(e){this.warnOnce(`history write failed: ${e?.message||e}`)}}runRetention(){if(this.db)try{let t=Date.now()-this.cfg.retentionDays*864e5;this.db.prepare("DELETE FROM events WHERE ts < ?").run(t),this.db.prepare("DELETE FROM compile_times WHERE ts < ?").run(t),this.db.prepare("DELETE FROM task_runs WHERE ts < ?").run(t)}catch(t){this.warnOnce(`retention failed: ${t?.message||t}`)}}queryEvents(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since)),t.until!=null&&(e.push("ts <= ?"),r.push(t.until)),t.type&&(e.push("type = ?"),r.push(t.type));let s=`SELECT * FROM events ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??500),this.db.prepare(s).all(...r)}queryCompiles(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since)),t.until!=null&&(e.push("ts <= ?"),r.push(t.until));let s=`SELECT * FROM compile_times ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??1e3),this.db.prepare(s).all(...r)}queryTasks(t){if(!this.db)return[];let e=[],r=[];t.app&&(e.push("app = ?"),r.push(t.app)),t.task&&(e.push("task = ?"),r.push(t.task)),t.since!=null&&(e.push("ts >= ?"),r.push(t.since));let s=`SELECT * FROM task_runs ${e.length?"WHERE "+e.join(" AND "):""} ORDER BY ts DESC LIMIT ?`;return r.push(t.limit??200),this.db.prepare(s).all(...r)}summary(t){if(!this.db)return{uptimePct24h:0,restartCount24h:0,compileP50:null,compileP95:null,topErrors:[]};let e=Date.now()-24*3600*1e3,r=this.queryEvents({app:t,since:e,limit:5e3}),s=0,o=e,i=!1,a=null,u=[...r].sort((d,g)=>d.ts-g.ts);for(let d of u)d.type==="status"&&(d.to_state==="serving"&&!i?(i=!0,a=d.ts):i&&d.to_state!=="serving"&&a!=null&&(s+=d.ts-a,i=!1,a=null));i&&a!=null&&(s+=Date.now()-a);let l=Math.round(s/(24*3600*1e3)*1e3)/10,h=r.filter(d=>d.type==="status"&&d.to_state==="starting"&&(d.from_state==="serving"||d.from_state==="error"||d.from_state==="compiling")).length,p=this.queryCompiles({app:t,since:e,limit:1e3}).map(d=>d.ms).sort((d,g)=>d-g),x=(d,g)=>{if(d.length===0)return null;let R=Math.min(d.length-1,Math.floor((d.length-1)*g));return d[R]},S=x(p,.5),c=x(p,.95),f=new Map;for(let d of r)if(d.type==="error-new"||d.type==="error-recur"){let g=d.message??"";if(!g)continue;f.set(g,(f.get(g)??0)+1)}let m=[...f.entries()].sort((d,g)=>g[1]-d[1]).slice(0,5).map(([d,g])=>({message:d,count:g}));return{uptimePct24h:l,restartCount24h:h,compileP50:S,compileP95:c,topErrors:m}}why(t){let e=this.queryEvents({app:t,limit:200}),r=e.find(a=>a.type==="status"&&(a.to_state==="error"||a.from_state==="error"||a.to_state==="serving")),s=r?{ts:r.ts,app:r.app,type:r.type,from:r.from_state??void 0,to:r.to_state??void 0,message:r.message??void 0}:null,o=s?s.ts:Date.now(),i=e.filter(a=>a.ts<o).slice(0,5);return{trigger:s,preceding:i.map(a=>({ts:a.ts,app:a.app,type:a.type,from:a.from_state??void 0,to:a.to_state??void 0,message:a.message??void 0}))}}quickCheck(){if(!this.db)return!1;try{return this.db.prepare("PRAGMA quick_check").get()?.quick_check==="ok"}catch{return!1}}close(){if(this.flushTimer&&clearInterval(this.flushTimer),this.retentionTimer&&clearInterval(this.retentionTimer),this.retentionStart&&clearTimeout(this.retentionStart),this.flush(),this.db){try{this.db.close()}catch{}this.db=null}}}});var ve={};Zt(ve,{ALL_AUTO_FIX:()=>jr,runAutoFix:()=>Ns});import L from"node:fs";import H from"node:path";function gs(){let n=ut();if(!n)return{detected:!1,description:"no daemon running"};let t=process.cwd(),e=H.join(t,"daimon.config.json");if(!L.existsSync(e))return{detected:!1,description:"no local daimon.config.json in cwd"};let r=n.cwd,s=n.configPath,o=r&&H.resolve(r)===H.resolve(t),i=s&&H.resolve(s)===H.resolve(e);return o||i?{detected:!1,description:"daemon already running from this cwd/config"}:{detected:!0,description:`daemon (pid ${n.pid}) is running from ${r??"(unknown)"} but local daimon.config.json exists at ${t}`,lockCwd:r}}async function ys(){let n=ut();if(!n)return"no daemon running; nothing to do";try{await fetch(`http://127.0.0.1:${n.apiPort}/api/snapshot-state`,{method:"POST"})}catch{}try{await fetch(`http://127.0.0.1:${n.apiPort}/api/shutdown`,{method:"POST"})}catch{}return await lr(n.pid,5e3),St(),`respawned daemon at pid ${(await le({})).pid} from ${process.cwd()}; previous pid ${n.pid} (cwd ${n.cwd??"unknown"}) was shut down with state handoff. To undo: stop with 'daimon daemon stop' and start from the prior directory.`}function vs(){let n;try{n=L.readFileSync(Nt(),"utf8")}catch{return{detected:!1,description:"no lock file present"}}let t;try{t=JSON.parse(n)}catch{return{detected:!0,description:"lock file is malformed JSON"}}if(!t||typeof t.pid!="number")return{detected:!0,description:"lock file has no pid"};try{return process.kill(t.pid,0),{detected:!1,description:`lock file owner pid ${t.pid} is alive`}}catch(e){return e?.code==="EPERM"?{detected:!1,description:`lock file owner pid ${t.pid} alive (EPERM)`}:{detected:!0,description:`lock file claims pid ${t.pid} but the process is gone`}}}async function ws(){let n="(unknown)";try{let e=JSON.parse(L.readFileSync(Nt(),"utf8"));n=String(e?.pid??"?")}catch{}St();let t=await le({});return`removed stale ${Nt()} (prior pid ${n} was dead); spawned fresh daemon at pid ${t.pid}.`}function bs(){let n=process.cwd(),e=["nx.json","angular.json","vite.config.ts","vite.config.js","vite.config.mjs","vite.config.cjs",".storybook"].filter(i=>L.existsSync(H.join(n,i)));if(!e.length)return{detected:!1,description:"no nx.json/angular.json/vite.config.*/.storybook in cwd"};let r=W();return r.kind!=="loaded"?{detected:!0,description:`${e.join(", ")} present but no config is loaded`,markerFiles:e}:r.config.searchRoots.map(i=>H.resolve(typeof i=="string"?i:i.path)).some(i=>n.startsWith(i))?{detected:!1,description:`${e.join(", ")} present and a configured searchRoot covers ${n}`}:{detected:!0,description:`${e.join(", ")} present in ${n} but no searchRoot covers it`,markerFiles:e}}function Ss(){let n=process.cwd(),{local:t,user:e}=et(),r=L.existsSync(t)?t:e,s={};try{s=JSON.parse(L.readFileSync(r,"utf8"))}catch{}if(s.searchRoots=Array.isArray(s.searchRoots)?s.searchRoots:[],!s.searchRoots.some(i=>(typeof i=="string"?i:i?.path)===n)){let i;try{let a=JSON.parse(L.readFileSync(H.join(n,"package.json"),"utf8"));typeof a.name=="string"&&(i=a.name)}catch{}s.searchRoots.push(i?{path:n,label:i}:n)}L.mkdirSync(H.dirname(r),{recursive:!0}),L.writeFileSync(r,JSON.stringify(s,null,2)+`
|
|
33
|
+
`,"utf8");let o=ut();if(o)try{fetch(`http://127.0.0.1:${o.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`appended ${n} as a searchRoot in ${r}; triggered soft-reload of the running daemon.`}function ks(){let n=W();if(n.kind!=="loaded"||!n.config.history.enabled)return{detected:!1,description:"history disabled"};let t=n.config.history.path;if(!L.existsSync(t))return{detected:!1,description:"history db does not exist (will be created on next start)"};try{let e=new pt(n.config.history),r=e.quickCheck();return e.close(),r?{detected:!1,description:"history db quick_check passed"}:{detected:!0,description:`quick_check failed on ${t}`,dbPath:t}}catch(e){return{detected:!0,description:`cannot open ${t}: ${e?.message??String(e)}`,dbPath:t}}}function xs(){let n=W();if(n.kind!=="loaded")return"no config; cannot determine history path";let t=n.config.history.path,e=`${t}.corrupt-${Date.now()}`;for(let r of["","-wal","-shm"])try{L.renameSync(t+r,e+r)}catch{}return`rotated ${t} \u2192 ${e} (and -wal/-shm siblings). The daemon will rebuild an empty history db on next start.`}async function Es(){let n=W();if(n.kind!=="loaded")return{detected:!1,description:"no config loaded"};let[t,e]=n.config.portRange??[4200,4299],r=n.config.overrides??{},s=Object.values(r).map(a=>a.port).filter(a=>typeof a=="number"),o=Array.from(new Set([...s,t,e])),i=[];for(let a of o)if(!(!Number.isFinite(a)||a<=0))try{await it(a)||i.push(a)}catch{}return i.length?{detected:!0,description:`ports already LISTEN: ${i.join(", ")} (range ${t}-${e} + pinned overrides)`,conflicts:i}:{detected:!1,description:`all checked ports free (range ${t}-${e} + pinned)`}}function Ts(){return"no automated fix \u2014 predictive rule only. Run `daimon free-port <port>` to inspect the holder, or pick a different port in daimon.config.json. To undo: nothing was changed."}function Rs(){let n=process.cwd(),t=process.versions.node,e=H.join(n,".nvmrc");if(L.existsSync(e)){let s=L.readFileSync(e,"utf8").trim().replace(/^v/i,"");if(s&&!t.startsWith(s))return{detected:!0,description:`.nvmrc requires ${s}, running ${t}`,expected:s,actual:t}}let r=H.join(n,"package.json");if(L.existsSync(r))try{let o=JSON.parse(L.readFileSync(r,"utf8"))?.engines?.node;if(typeof o=="string"&&o.trim()){let i=o.match(/(\d+)(?:\.(\d+))?/);if(i){let a=Number(i[1]),u=Number(t.split(".")[0]);if(Number.isFinite(a)&&Number.isFinite(u)&&u<a)return{detected:!0,description:`package.json engines.node = "${o}" but running ${t}`,expected:o,actual:t}}}}catch{}return{detected:!1,description:`node ${t} satisfies .nvmrc / engines.node (or neither is present)`}}function As(){return"no automated fix \u2014 switching Node versions touches the user environment. Run `nvm use` (or your version manager equivalent) in this directory, then re-run daimon. To undo: nothing was changed."}function Cs(){let n=W();if(n.kind!=="loaded")return[];let t=[],e=new Set;for(let r of n.config.searchRoots){let s=typeof r=="string"?r:r.path;if(!s||!L.existsSync(s)||e.has(s))continue;e.add(s);let o=H.join(s,"package.json");if(!L.existsSync(o))continue;let i=null;for(let a of["package-lock.json","pnpm-lock.yaml","yarn.lock"]){let u=H.join(s,a);if(L.existsSync(u)){i=u;break}}t.push({name:H.basename(s),root:s,pkgPath:o,lockPath:i,nmPath:H.join(s,"node_modules")})}return t}function Nr(){let n=Cs();if(!n.length)return{detected:!1,description:"no searchRoots with package.json found"};let t=[];for(let r of n){if(!L.existsSync(r.nmPath)){t.push({root:r.root,reason:"missing"});continue}if(r.lockPath)try{let s=L.statSync(r.lockPath).mtimeMs,o=L.statSync(r.nmPath).mtimeMs;s>o+1e3&&t.push({root:r.root,reason:"stale"})}catch{}}return t.length?{detected:!0,description:`node_modules issues \u2014 ${t.map(r=>`${r.reason}: ${r.root}`).join(" \xB7 ")}`,entries:t}:{detected:!1,description:"every searchRoot package.json has a fresh node_modules"}}function Ps(){let n=Nr();return!n.detected||!n.entries?"nothing to suggest":`would suggest: ${n.entries.map(e=>`(cd "${e.root}" && npm install)`).join(" && ")}. Daimon does not run package managers on your behalf \u2014 run the command(s) yourself. To undo: nothing was changed.`}function $r(){let n=W();if(n.kind!=="loaded")return{detected:!1,description:"no config loaded"};let t=[];for(let e of n.config.searchRoots){let r=typeof e=="string"?e:e.path;r&&(L.existsSync(r)||t.push(r))}return t.length?{detected:!0,description:`searchRoots no longer on disk: ${t.join(", ")}`,dead:t}:{detected:!1,description:"every configured searchRoot resolves on disk"}}function Os(){let n=$r();if(!n.detected||!n.dead||!n.dead.length)return"nothing to remove";let{local:t,user:e}=et(),r=L.existsSync(t)?t:e,s={};try{s=JSON.parse(L.readFileSync(r,"utf8"))}catch{}if(!Array.isArray(s.searchRoots))return"config has no searchRoots array; nothing removed";let o=new Set(n.dead),i=s.searchRoots.length;s.searchRoots=s.searchRoots.filter(l=>{let h=typeof l=="string"?l:l?.path;return!o.has(h)});let a=i-s.searchRoots.length;L.writeFileSync(r,JSON.stringify(s,null,2)+`
|
|
34
|
+
`,"utf8");let u=ut();if(u)try{fetch(`http://127.0.0.1:${u.apiPort}/api/config/reload`,{method:"POST"})}catch{}return`removed ${a} dead searchRoot entr${a===1?"y":"ies"} from ${r} (${[...o].join(", ")}); triggered soft-reload. To undo: edit ${r} and re-add the path(s).`}async function Ns(n){let t={ran:[],skipped:[],errors:[]};for(let e of jr){if(!n.permitted.includes(e))continue;let r=js[e],s;try{s=await r.detect()}catch(o){t.errors.push({name:e,error:o?.message??String(o)});continue}if(!s.detected){t.skipped.push({name:e,detected:!1,description:s.description});continue}if(n.dryRun){t.ran.push({name:e,detected:!0,description:`(dry-run) would fix: ${s.description}`});continue}try{let o=await r.fix();t.ran.push({name:e,detected:!0,description:`${s.description} \u2014 ${o}`})}catch(o){t.errors.push({name:e,error:o?.message??String(o)})}}return t}var jr,js,we=tt(()=>{"use strict";rt();yt();ye();Ct();jr=["orphan-daemon","stale-lock","missing-search-root","corrupt-history-db","port-conflict-pred","node-version-mismatch","orphan-node-modules","dead-search-root"];js={"orphan-daemon":{detect:gs,fix:ys},"stale-lock":{detect:vs,fix:ws},"missing-search-root":{detect:bs,fix:Ss},"corrupt-history-db":{detect:ks,fix:xs},"port-conflict-pred":{detect:Es,fix:Ts},"node-version-mismatch":{detect:Rs,fix:As},"orphan-node-modules":{detect:Nr,fix:Ps},"dead-search-root":{detect:$r,fix:Os}}});yt();bt();import Co from"react";import{render as Po}from"ink";import{pathToFileURL as Oo}from"node:url";import{EventEmitter as Xn}from"node:events";import{spawn as Cn}from"node:child_process";import We from"tree-kill";import Pn from"strip-ansi";import en from"node:crypto";var rn=[/Local:\s+http/i,/Application bundle generation complete/i,/compiled successfully/i,/webpack compiled\s+(?:successfully|in\b)/i,/Angular Live Development Server is listening/i,/Storybook\s+[\d.]+\s+(?:for\s+\S+\s+)?started/i,/VITE\s+v[\d.]+\s+ready/i],nn=[/Building\.\.\./i,/Compilation started/i,/Initial chunk files/i,/Compiling/i],sn=[/^\s*ERROR\b/,/\berror TS\d+/,/✘/,/\[ERROR\]/,/Cannot find module/i,/^FAIL\s+\S+/,/^\s*●\s+/,/^\s*>\s+NX\s+.*failed/i,/\bModule not found:/,/\[vite\]\s+(?:Internal server error|Pre-transform error)/i,/\[plugin:[^\]]+\]/i,/^\s*ERR!\s+/,/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):\s+/],on=/\berror TS(\d+)/,an=/✘\s*\[ERROR\]\s*TS(\d+)/,cn=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+)/,Ue=/\(([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+)\)/,ln=/([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))\((\d+),(\d+)\)\s*:/,un=/^FAIL\s+(\S+\.(?:tsx?|jsx?|mjs|cjs))(?:\s|$)/,pn=/^ERROR in\s+(\S+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte))(?:[:\s](\d+):(\d+))?/,dn=/^\s+([A-Z]:[\\/][^\s:()]+|[^\s:()]+\.(?:tsx?|jsx?|mjs|cjs|vue|svelte)):(\d+):(\d+):?\s*$/,fn=[{tool:"vite",rx:/\[vite\]|\[plugin:vite:|transformWithEsbuild/i},{tool:"storybook",rx:/\bstorybook\b|^\s*ERR!\s|builder-vite/i},{tool:"jest",rx:/^FAIL\s|^\s*●\s+|\bjest\b/i},{tool:"nx",rx:/>\s+NX\s+|Failed tasks:|Nx errored/i},{tool:"webpack",rx:/\bModule not found:|webpack compiled|webpack-dev-server/i},{tool:"esbuild",rx:/✘\s*\[ERROR\]|esbuild/i},{tool:"typescript",rx:/\berror TS\d+/},{tool:"node",rx:/^\s*(?:Uncaught\s+)?(?:Error|TypeError|SyntaxError|ReferenceError|RangeError):/}];function mn(n){for(let{tool:t,rx:e}of fn)if(e.test(n))return t}var hn=/Local:\s+(https?:\/\/\S+)/i,gn=/Server running at\s+(https?:\/\/\S+)/i,yn=/listening on\s+(https?:\/\/\S+)/i,vn=/(?:listening|listen)\s+(https?:\/\/\S+)/i,wn=/Initial chunk files/i,bn=/Lazy chunk files/i,Sn=/(Initial total|Lazy total)\s*\|?\s*([\d.]+)\s*(kB|MB|B)\b/i,kn=/^\s*\|?\s*([^\s|][^|]*?)\s*\|\s*([^|]+?)\s*\|\s*([\d.]+)\s*(kB|MB|B)\b/i;function xn(n){return en.createHash("sha1").update(n).digest("hex").slice(0,16)}function En(n){let t={message:n},e=n.match(an)||n.match(on);e&&(t.code=`TS${e[1]}`);let r=n.match(ln)||n.match(Ue)||n.match(cn);if(r)t.file=r[1],t.line=Number(r[2]),t.col=Number(r[3]);else{let o=n.match(pn);if(o)t.file=o[1],o[2]&&(t.line=Number(o[2])),o[3]&&(t.col=Number(o[3]));else{let i=n.match(un);i&&(t.file=i[1])}}let s=mn(n);return s&&(t.tool=s),t}function Tn(n,t){try{let e=new URL(n);return e.hostname==="0.0.0.0"||e.hostname==="[::]"?(e.hostname=t.includes(":")?`[${t}]`:t,e.toString().replace(/\/$/,"")):n.replace(/\/$/,"")}catch{return n}}function Rn(n,t="127.0.0.1"){let e=n.match(hn)||n.match(gn)||n.match(yn)||n.match(vn);if(!e)return null;let r=e[1].replace(/[),.;]+$/,"");return Tn(r,t)}function An(n,t){if(wn.test(t))return n.bundle||(n.bundle={initialKB:0,lazyKB:0,files:[]}),n._bundleSection="initial",!1;if(bn.test(t))return n.bundle||(n.bundle={initialKB:0,lazyKB:0,files:[]}),n._bundleSection="lazy",!1;let e=t.match(Sn);if(e&&n.bundle){let s=parseFloat(e[2]),o=e[3].toUpperCase(),i=Math.round(o==="MB"?s*1024:o==="B"?s/1024:s);return/Initial/i.test(e[1])?n.bundle.initialKB=i:n.bundle.lazyKB=i,!0}let r=t.match(kn);if(r&&n.bundle){let s=r[1].trim();if(/^(Initial|Lazy)\s+(total|chunk)/i.test(s))return!1;let o=r[4].toUpperCase(),i=parseFloat(r[3]),a=o==="MB"?i*1024:o==="B"?i/1024:i;return n.bundle.files.push({name:s,sizeKB:Math.round(a*10)/10}),!1}return!1}function Je(n,t){let e=t.match(dn),r=e?null:t.match(Ue),s=e??r;if(s&&n.lastErrorHash){let S=n.errors.get(n.lastErrorHash);S&&!S.parsed?.file&&(S.parsed={...S.parsed??{message:S.message},file:s[1],line:Number(s[2]),col:Number(s[3])})}let o=t.trim();if(!o)return null;let i=n.status,a=!1,u,l=Rn(o);l&&!n.announcedUrl&&(n.announcedUrl=l,u=l);let h=An(n,o),p;if(rn.some(S=>S.test(o))){let S=n.status==="error"||!!n.recoveringFromError;if(n.status==="compiling"||n.status==="starting"||n.status==="error"){let c=Date.now();n.compileStartedAt!=null?(p=c-n.compileStartedAt,n.lastCompileMs=p,n.lastCompileAt=c,n.compileStartedAt=null,n.compileHistory.push(p),n.compileHistory.length>20&&n.compileHistory.splice(0,n.compileHistory.length-20)):n.lastCompileAt=c}n.status="serving",S&&(n.errors.clear(),n.recoveringFromError=!1)}else nn.some(S=>S.test(o))&&(n.status==="starting"||n.status==="serving"||n.status==="error")&&(n.status==="error"&&(n.recoveringFromError=!0),n.compileStartedAt=Date.now(),n.status="compiling");let x;if(sn.some(S=>S.test(o))){let S=xn(o),c=Date.now(),f=n.errors.get(S),m=!1,d;f?(f.count+=1,f.lastSeen=c,d=f):(d={message:o,count:1,firstSeen:c,lastSeen:c,parsed:En(o)},n.errors.set(S,d),m=!0),n.lastErrorHash=S,x={entry:d,isNew:m},n.status="error"}return a=n.status!==i,{statusChanged:a,error:x,announcedUrl:u,bundleUpdated:h,compileMs:p}}var Ge=500,At=class{child=null;stdoutBuf="";stderrBuf="";deps;stopping=!1;constructor(t){this.deps=t}isRunning(){return this.child!==null&&this.child.exitCode===null&&!this.stopping}start(){if(this.isRunning())return;let{app:t,port:e,state:r}=this.deps,s=Date.now();r.status="starting",r.startedAt=s,r.compileStartedAt=s,r.lastCompileMs=null,r.lastCompileAt=null,r.errors.clear(),r.logBuffer.length=0,r.lastStatusMessage=void 0;let i=`${this.deps.commandOverride||t.command} --port ${e}`,a={...process.env,...t.env||{},...this.deps.envOverride||{},PORT:String(e),FORCE_COLOR:"0"},u=Cn(i,[],{cwd:t.workspaceRoot,shell:!0,env:a,windowsHide:!0});this.child=u,r.pid=u.pid??null,r.port=e,u.stdout?.on("data",l=>this.handleChunk(l,"stdout")),u.stderr?.on("data",l=>this.handleChunk(l,"stderr")),u.on("exit",(l,h)=>{let p=r.status,x=this.stopping;x?(r.status="stopped",r.lastStatusMessage=`stopped (code=${l??"null"}${h?`, ${h}`:""})`):l!==0?(r.status="error",r.lastStatusMessage=`process exited with code ${l}${h?` (${h})`:""}`):r.status="stopped",r.pid=null,r.health="unknown",this.child=null,this.stopping=!1,p!==r.status&&this.deps.onStatusChange?.(p,r.status,r.lastStatusMessage),this.deps.onExit?.(l,h,x),this.deps.onStateChange()}),u.on("error",l=>{r.status="error",r.lastStatusMessage=`spawn error: ${l.message}`,this.deps.onStateChange()}),this.deps.onStateChange()}handleChunk(t,e){let r=t.toString("utf8"),s=this[e==="stdout"?"stdoutBuf":"stderrBuf"]+=r,o=s.lastIndexOf(`
|
|
35
|
+
`);if(o<0)return;let i=s.slice(0,o),a=s.slice(o+1);e==="stdout"?this.stdoutBuf=a:this.stderrBuf=a;let{state:u}=this.deps,l=!1;for(let h of i.split(/\r?\n/)){if(!h.length)continue;let p=Pn(h),x=Date.now();u.lastLogTs=x,u.stale&&(u.stale=!1),u.logBuffer.push({ts:x,line:p}),u.logBuffer.length>Ge&&u.logBuffer.splice(0,u.logBuffer.length-Ge),this.deps.onLogLine?.(p);let S=u.status,c=Je(u,p);c?.statusChanged&&(l=!0,this.deps.onStatusChange?.(S,u.status)),c?.error&&this.deps.onErrorRecorded?.(c.error.entry,c.error.isNew),c?.compileMs!=null&&this.deps.onCompile?.(c.compileMs),c?.bundleUpdated&&this.deps.onBundleUpdate?.()}(l||i.length>0)&&this.deps.onStateChange()}async stop(){if(!this.child||this.stopping)return;this.stopping=!0;let t=this.child.pid;if(!t){this.child=null,this.stopping=!1;return}await new Promise(e=>{let r=!1,s=()=>{r||(r=!0,e())},o=()=>s();this.child?.once("exit",o),We(t,"SIGTERM",()=>{});let i=setTimeout(()=>{We(t,"SIGKILL",()=>{})},2e3),a=setTimeout(()=>{clearTimeout(i),s()},3e3);this.child?.once("exit",()=>{clearTimeout(i),clearTimeout(a),s()})})}};Ct();import q from"node:fs";import jn from"node:path";var Pt=class{constructor(t,e){this.appName=t;this.cfg=e;this.filePath=jn.join(e.dir,`${t}.log`),this.open()}appName;cfg;fd=null;bytes=0;warned=!1;filePath;open(){try{q.mkdirSync(this.cfg.dir,{recursive:!0});try{this.bytes=q.statSync(this.filePath).size}catch{this.bytes=0}this.fd=q.openSync(this.filePath,"a")}catch(t){this.warn(`open failed: ${t.message}`),this.fd=null}}write(t){if(this.fd!=null)try{let e=`${new Date().toISOString()} ${t}
|
|
36
|
+
`,r=Buffer.from(e,"utf8");q.writeSync(this.fd,r),this.bytes+=r.length,this.bytes>=this.cfg.maxBytesPerFile&&this.rotate()}catch(e){this.warn(`write failed: ${e.message}`)}}close(){if(this.fd!=null){try{q.closeSync(this.fd)}catch{}this.fd=null}}rotate(){try{this.close();for(let t=this.cfg.maxFiles-1;t>=1;t--){let e=`${this.filePath}.${t}`,r=`${this.filePath}.${t+1}`;if(t+1>this.cfg.maxFiles-1){try{q.rmSync(e,{force:!0})}catch{}continue}try{q.existsSync(e)&&q.renameSync(e,r)}catch{}}try{let t=`${this.filePath}.1`;q.existsSync(this.filePath)&&q.renameSync(this.filePath,t)}catch{}this.open()}catch(t){this.warn(`rotate failed: ${t.message}`)}}warn(t){this.warned||(this.warned=!0,process.stderr.write(`[daimon] warning: diskLogger(${this.appName}) ${t}
|
|
37
|
+
`))}};function qe(n){let s=new Map,o=new Map,i=null,a=u=>{if(!i){s.set(u,1);for(let l of n[u]||[]){let h=s.get(l)??0;if(h===1){let p=[l,u],x=o.get(u);for(;x&&x!==l;)p.push(x),x=o.get(x);x===l&&p.push(l),i=p.reverse();return}if(h===0&&(o.set(l,u),a(l),i))return}s.set(u,2)}};for(let u of Object.keys(n))if((s.get(u)??0)===0&&(o.set(u,null),a(u),i))return i;return null}function Xe(n,t){let e=new Set,r=[t];for(;r.length;){let s=r.pop();if(!e.has(s)){e.add(s);for(let o of n[s]||[])r.push(o)}}return[...e]}function Ke(n,t){let e=new Set(t),r=new Map,s=new Map;for(let a of t)r.set(a,0),s.set(a,[]);for(let a of t)for(let u of n[a]||[])e.has(u)&&(s.get(u).push(a),r.set(a,(r.get(a)??0)+1));let o=[],i=t.filter(a=>(r.get(a)??0)===0);for(;i.length;){o.push([...i].sort());let a=[];for(let u of i)for(let l of s.get(u)??[])r.set(l,(r.get(l)??1)-1),r.get(l)===0&&a.push(l);i=a}return o}function Ye(n,t){let e=[];for(let[r,s]of Object.entries(n))s.includes(t)&&e.push(r);return e}import{spawn as Ve}from"node:child_process";import ze from"tree-kill";import Ze from"strip-ansi";var Nn=/Tests:\s+(?:(\d+)\s+failed,\s+)?(\d+)\s+passed(?:,\s+(\d+)\s+total)?/,$n=/Executed (\d+) of (\d+)(?:\s*\((\d+)\s*FAILED\))?/,Mn=/(\d+)\s+passed(?:.*?(\d+)\s+failed)?/i;function _n(n){let t=n.match(Nn);if(t){let s=t[1]?Number(t[1]):0,o=Number(t[2]),i=t[3]?Number(t[3]):o+s;return{passed:o,failed:s,total:i}}let e=n.match($n);if(e){let s=Number(e[1]),o=Number(e[2]),i=e[3]?Number(e[3]):0;return{passed:s-i,failed:i,total:o}}let r=n.match(Mn);if(r){let s=Number(r[1]),o=r[2]?Number(r[2]):0;return{passed:s,failed:o,total:s+o}}return null}function Qe(n,t,e){let r=e.length?" -- "+e.join(" "):"";return n.workspaceType==="nx"?`npx nx run ${n.name}:${t}${r}`:n.workspaceType==="angular"?`npx ng run ${n.name}:${t}${r}`:`npx ${t}${r}`}function tr(n,t,e=[]){return new Promise(r=>{let s=Date.now(),o=Qe(n,t,e),i=Ve(o,[],{cwd:n.workspaceRoot,shell:!0,env:{...process.env,...n.env||{},FORCE_COLOR:"0"},windowsHide:!0}),a=[],u="",l=h=>{u+=h.toString("utf8");let p=u.lastIndexOf(`
|
|
38
|
+
`);if(p<0)return;let x=u.slice(0,p);u=u.slice(p+1);for(let S of x.split(/\r?\n/)){if(!S.length)continue;let c=Ze(S);a.push(c),a.length>1e3&&a.splice(0,a.length-1e3)}};i.stdout?.on("data",l),i.stderr?.on("data",l),i.on("exit",h=>{let p=Date.now()-s,x=a.join(`
|
|
38
39
|
`)+(u?`
|
|
39
|
-
`+u:""),S=
|
|
40
|
-
`);if(h<0)return;let p=
|
|
41
|
-
`;try{ce.appendFileSync(this.file,e)}catch{}}};var lr=500,Ot=class extends Ln{entries=new Map;portAlloc;config;eventBuffer=[];history=null;watchTasks=new Map;sessionRecorder=new Pt;constructor(t,e,r){super(),this.config=t,this.portAlloc=r??new nt(t.portRange);for(let s of e)this.entries.set(s.name,{app:s,state:this.freshState(s.name,s.tags,s.workspaceLabel??null),proc:null})}getConfig(){return this.config}addDiscoveredApp(t){this.entries.has(t.name)||(this.entries.set(t.name,{app:t,state:this.freshState(t.name,t.tags,t.workspaceLabel??null),proc:null}),this.emit("change"))}updateDiscoveredApp(t){let e=this.entries.get(t.name);e&&(e.app=t,e.state.tags=t.tags,e.state.workspaceLabel=t.workspaceLabel??null,e.state.dependsOn=this.config.depends?.[t.name]??[],this.emit("change"))}getPortAllocator(){return this.portAlloc}setHistory(t){this.history=t}getHistory(){return this.history}freshState(t,e,r=null){return{name:t,status:"stopped",port:null,pid:null,startedAt:null,compileStartedAt:null,lastCompileMs:null,lastCompileAt:null,logBuffer:[],errors:new Map,compileHistory:[],health:"unknown",lastHealthAt:null,cpu:null,memMB:null,restartAttempts:0,restartWindowStart:null,nextRestartAt:null,tags:e,announcedUrl:null,lastHealthError:null,cachedProbeHost:null,lastLogTs:null,stale:!1,bundle:null,bundleRegressionPct:null,activeEnvFile:null,sessionOverrides:null,dependsOn:this.config.depends?.[t]??[],workspaceLabel:r}}names(){return[...this.entries.keys()]}list(){return this.names().map(t=>this.summary(t))}summary(t){let e=this.entries.get(t);if(!e)return null;let r=e.state,s=r.startedAt&&(r.status==="serving"||r.status==="compiling"||r.status==="starting")?Date.now()-r.startedAt:null,o=this.config.overrides?.[t]?.url||e.resolvedUrl||r.announcedUrl||(r.port?`http://127.0.0.1:${r.port}`:null),a;for(let u=this.eventBuffer.length-1;u>=0;u--){let c=this.eventBuffer[u];if(c.app===t&&c.type==="status"){a=Date.now()-c.ts;break}}return{name:r.name,status:r.status,port:r.port,url:o,errorCount:[...r.errors.values()].reduce((u,c)=>u+c.count,0),uptimeMs:s,lastCompileMs:r.lastCompileMs,health:r.health,lastHealthAt:r.lastHealthAt,cpu:r.cpu,memMB:r.memMB,compileHistoryMs:[...r.compileHistory],tags:[...r.tags],restartAttempts:r.restartAttempts,nextRestartAt:r.nextRestartAt,announcedUrl:r.announcedUrl,lastHealthError:r.lastHealthError,stale:r.stale,bundle:r.bundle,bundleRegressionPct:r.bundleRegressionPct,dependsOn:[...r.dependsOn],activeEnvFile:r.activeEnvFile,workspaceLabel:r.workspaceLabel,lastChangeMs:a}}getState(t){return this.entries.get(t)?.state??null}getApp(t){return this.entries.get(t)?.app??null}errors(t){let e=this.getState(t);return e?[...e.errors.values()].sort((r,s)=>s.lastSeen-r.lastSeen):null}errorsSince(t,e){let r=this.getState(t);return r?[...r.errors.values()].filter(s=>s.lastSeen>e).sort((s,i)=>i.lastSeen-s.lastSeen):null}logs(t,e={}){let r=this.getState(t);if(!r)return null;let s=r.logBuffer;if(e.sinceMs&&e.sinceMs>0){let i=Date.now()-e.sinceMs;s=s.filter(o=>o.ts>=i)}return e.tail&&e.tail>0&&(s=s.slice(-e.tail)),s.map(i=>i.line)}events(t={}){let e=t.sinceMs&&t.sinceMs>0?Date.now()-t.sinceMs:0;return this.eventBuffer.filter(r=>r.ts>=e&&(!t.app||r.app===t.app))}recordEvent(t){let e={ts:t.ts??Date.now(),...t};this.eventBuffer.push(e),this.emit("event",e),this.eventBuffer.length>lr&&this.eventBuffer.splice(0,this.eventBuffer.length-lr),this.history?.recordEvent(e),this.emit("event",e)}setHealth(t,e){let r=this.entries.get(t);if(!r)return;let s=r.state;if(s.lastHealthAt=Date.now(),s.health===e)return;let i=s.health;s.health=e,e==="healthy"&&(r.prevHealthyAt=Date.now(),r.cascadeArmed&&(r.cascadeArmed=!1,this.triggerCascadeRestart(t))),this.recordEvent({app:t,type:"health",from:i,to:e}),this.emit("change")}armCascade(t){let e=this.entries.get(t);e&&this.config.cascadeRestart&&e.prevHealthyAt!=null&&(e.cascadeArmed=!0)}setLastHealthError(t,e){let r=this.getState(t);r&&r.lastHealthError!==e&&(r.lastHealthError=e,this.emit("change"))}setResolvedUrl(t,e){let r=this.entries.get(t);r&&r.resolvedUrl!==e&&(r.resolvedUrl=e,this.emit("change"))}setCachedProbeHost(t,e){let r=this.getState(t);r&&(r.cachedProbeHost=e)}setStale(t,e){let r=this.getState(t);r&&r.stale!==e&&(r.stale=e,this.emit("change"))}setSessionOverride(t,e){let r=this.getState(t);r&&(r.sessionOverrides=e,this.emit("change"))}setActiveEnvFile(t,e){let r=this.getState(t);r&&(r.activeEnvFile=e,this.emit("change"))}async start(t){this.sessionRecorder.append({kind:"start",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(e.proc?.isRunning())return{ok:!0,status:e.state.status};let r=e.state.status,s;try{s=await this.portAlloc.allocate(t,e.app.pinnedPort)}catch(S){return e.state.status="error",e.state.lastStatusMessage=S.message,this.recordEvent({app:t,type:"status",from:r,to:"error",message:S.message}),this.emit("change"),{ok:!1,status:"error",error:S.message}}if(!await Et(s)){let S=Ve(s),l=Qe(s,S);return e.state.status="error",e.state.port=s,e.state.lastStatusMessage=l,this.recordEvent({app:t,type:"status",from:r,to:"error",message:l}),this.emit("change"),{ok:!1,status:"error",error:l}}e.state.health="unknown",e.state.lastHealthAt=null,e.state.announcedUrl=null,e.state.lastHealthError=null,e.state.cachedProbeHost=null,e.state.stale=!1,e.state.lastLogTs=null,e.resolvedUrl=void 0,!e.logger&&this.config.logs.enabled&&(e.logger=new Tt(t,this.config.logs));let o=e.state.sessionOverrides,a=this.config.envFiles?.[t]??[],u={};if(a.length){let S=e.state.activeEnvFile;(!S||!ne(e.app.workspaceRoot,[S]).length)&&(S=ne(e.app.workspaceRoot,a)[0]??null,S&&(e.state.activeEnvFile=S)),S&&(u=er(re(e.app.workspaceRoot,S)))}let c={...u,...this.config.overrides?.[t]?.env??{},...o?.env??{}},h=ir(),p=ar(c,h),b=new xt({state:e.state,app:e.app,port:s,envOverride:Object.keys(p).length?p:void 0,commandOverride:o?.command,onStateChange:()=>this.emit("change"),onStatusChange:(S,l,m)=>{this.recordEvent({app:t,type:"status",from:S,to:l,message:m}),(l==="stopped"||l==="error")&&(S==="serving"||S==="compiling")&&this.armCascade(t)},onErrorRecorded:(S,l)=>this.recordEvent({app:t,type:l?"error-new":"error-recur",message:S.message}),onExit:(S,l,m)=>this.emit("childExit",{name:t,code:S,signal:l,stopping:m}),onLogLine:S=>{e.logger?.write(S),this.emit("log",{name:t,ts:Date.now(),line:S})},onCompile:S=>{this.history?.recordCompile(t,S);let l=this.getState(t),m=e.lastBundleInitialKB;if(l.bundle&&l.bundle.initialKB>0){if(m&&m>0){let g=(l.bundle.initialKB-m)/m*100;l.bundleRegressionPct=Math.round(g*10)/10,g>10&&this.recordEvent({app:t,type:"bundle-regression",message:`initialKB +${l.bundleRegressionPct}% (${m}->${l.bundle.initialKB})`})}else l.bundleRegressionPct=null;e.lastBundleInitialKB=l.bundle.initialKB}this.checkCompileRegression(t,S),this.emit("compile",{name:t,ms:S})},onBundleUpdate:()=>this.emit("bundleUpdate",{name:t})});return e.proc=b,this.recordEvent({app:t,type:"status",from:r,to:"starting"}),b.start(),{ok:!0,status:e.state.status}}async stop(t){this.sessionRecorder.append({kind:"stop",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(this.emit("userStop",{name:t}),!e.proc||!e.proc.isRunning())return e.state.status!=="stopped"&&this.recordEvent({app:t,type:"status",from:e.state.status,to:"stopped"}),e.state.status="stopped",e.state.pid=null,e.state.health="unknown",this.emit("change"),{ok:!0,status:"stopped"};let r=e.state.status;return await e.proc.stop(),e.proc=null,e.state.status!==r&&this.recordEvent({app:t,type:"status",from:r,to:e.state.status}),{ok:!0,status:e.state.status}}async restart(t){return this.sessionRecorder.append({kind:"restart",app:t}),await this.stop(t),this.start(t)}async startWithDeps(t,e={}){if(!this.entries.has(t))return{ok:!1,results:[{name:t,status:"unknown",health:"unknown",error:"unknown app"}]};let r=Ue(this.config.depends??{},t).filter(a=>this.entries.has(a)),s=We(this.config.depends??{},r),i=[],o=e.waitMs??6e4;for(let a of s){let u=await Promise.all(a.map(h=>this.start(h)));for(let h=0;h<a.length;h++){let p=u[h];if(!p.ok)return i.push({name:a[h],status:p.status,health:"unknown",error:p.error}),{ok:!1,results:i}}let c=await Promise.all(a.map(h=>this.waitFor(h,"healthy",o)));for(let h=0;h<a.length;h++){let p=c[h],b=!p.timedOut&&p.status==="serving"&&p.health==="healthy";if(i.push({name:p.name,status:p.status,health:p.health,error:b?void 0:p.timedOut?"timeout waiting for healthy":"did not reach healthy"}),!b)return{ok:!1,results:i}}}return{ok:!0,results:i}}triggerCascadeRestart(t){if(!this.config.cascadeRestart)return;let e=Je(this.config.depends??{},t);for(let r of e){let s=this.getState(r);s&&(s.status==="serving"||s.status==="compiling"||s.status==="starting")&&this.restart(r)}}async stopAll(t=3e3){let e=[];for(let r of this.entries.values())r.proc?.isRunning()&&e.push(r.proc.stop());for(let r of this.watchTasks.values())e.push(r.stop());await Promise.race([Promise.all(e),new Promise(r=>setTimeout(r,t))]);for(let r of this.entries.values())r.logger?.close()}listTasks(t){let e=this.getApp(t);return e?[...e.tasks??[]]:null}async runTask(t,e,r=[]){this.sessionRecorder.append({kind:"run",app:t,task:e,args:r});let s=this.getApp(t);if(!s)return{error:"unknown app"};let i=await Ye(s,e,r);return this.history?.recordTaskRun(t,e,i.exitCode,i.durationMs,i.summary),this.recordEvent({app:t,type:"task-run",message:`${e} exit=${i.exitCode} duration=${i.durationMs}ms`}),this.emit("taskRun",{name:t,task:e,result:i}),i}startWatchTask(t,e,r=[]){let s=this.getApp(t);if(!s)return{ok:!1,error:"unknown app"};let i=`${t}::${e}`;if(this.watchTasks.has(i))return{ok:!0,pid:this.watchTasks.get(i).pid};let o=ze(s,e,r);return this.watchTasks.set(i,o),o.child.on("exit",()=>this.watchTasks.delete(i)),{ok:!0,pid:o.pid}}async stopWatchTask(t,e){let r=`${t}::${e}`,s=this.watchTasks.get(r);return s?(await s.stop(),this.watchTasks.delete(r),{ok:!0}):{ok:!0}}listWatchTasks(t){let e=[];for(let r of this.watchTasks.values())t&&r.app!==t||e.push({app:r.app,task:r.task,pid:r.pid,startedAt:r.startedAt});return e}checkCompileRegression(t,e){let r=this.history;if(!r)return;let i=r.queryCompiles({app:t,limit:31}).filter(u=>u.ms!==e).slice(0,30).map(u=>u.ms);if(i.length<10)return;let o=[...i].sort((u,c)=>u-c),a=o[Math.floor((o.length-1)*.5)];e>2*a&&this.recordEvent({app:t,type:"compile-regression",message:`${(e/1e3).toFixed(1)}s vs p50 ${(a/1e3).toFixed(1)}s`})}watchTaskLogs(t,e,r){let s=this.watchTasks.get(`${t}::${e}`);if(!s)return null;let i=s.logs;return r?i.slice(-r):[...i]}waitFor(t,e,r){return new Promise(s=>{let i=Date.now(),o=this.entries.get(t),a=()=>{if(!o)return!0;let p=o.state;return e==="serving"&&p.status==="serving"||e==="healthy"&&p.status==="serving"&&p.health==="healthy"||e==="stopped"&&p.status==="stopped"||e==="error"&&p.status==="error"},u=p=>{this.off("change",c),clearTimeout(h);let b=o?.state;s({name:t,status:b?.status??"unknown",health:b?.health??"unknown",timedOut:p,waitedMs:Date.now()-i})},c=()=>{a()&&u(!1)};if(a()){s({name:t,status:o.state.status,health:o.state.health,timedOut:!1,waitedMs:0});return}let h=setTimeout(()=>u(!0),r);this.on("change",c)})}};import hs from"node:http";import gs from"node:crypto";import It from"node:fs";import F from"node:path";import{fileURLToPath as ys}from"node:url";import pe from"node:fs";import ur from"node:path";import Dn from"node:os";var fe=ur.join(Dn.homedir(),".daimon","cursors.json");function Fn(){try{let n=pe.readFileSync(fe,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.errors&&typeof t.errors=="object")return{errors:t.errors}}catch{}return{errors:{}}}var le=null,ue=null;function In(n){ue=n,!le&&(le=setTimeout(()=>{le=null;let t=ue;if(ue=null,!!t)try{pe.mkdirSync(ur.dirname(fe),{recursive:!0}),pe.writeFileSync(fe,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: cursor write failed: ${e.message}
|
|
42
|
-
`)}},500))}var
|
|
40
|
+
`+u:""),S=_n(x);r({app:n.name,task:t,exitCode:h,durationMs:p,summary:S,outputTail:a.slice(-50)})}),i.on("error",()=>{r({app:n.name,task:t,exitCode:-1,durationMs:Date.now()-s,summary:null,outputTail:[...a,"[daimon] task spawn error"]})})})}function er(n,t,e=[]){let r=Qe(n,t,e),s=Ve(r,[],{cwd:n.workspaceRoot,shell:!0,env:{...process.env,...n.env||{},FORCE_COLOR:"0"},windowsHide:!0}),o=[],i="",a=l=>{i+=l.toString("utf8");let h=i.lastIndexOf(`
|
|
41
|
+
`);if(h<0)return;let p=i.slice(0,h);i=i.slice(h+1);for(let x of p.split(/\r?\n/))x.length&&(o.push(Ze(x)),o.length>500&&o.splice(0,o.length-500))};return s.stdout?.on("data",a),s.stderr?.on("data",a),{app:n.name,task:t,pid:s.pid??null,child:s,startedAt:Date.now(),logs:o,stop:()=>new Promise(l=>{if(!s.pid){l();return}let h=!1,p=()=>{h||(h=!0,l())};s.once("exit",p),ze(s.pid,"SIGTERM",()=>{}),setTimeout(()=>{s.pid&&ze(s.pid,"SIGKILL",()=>{})},2e3),setTimeout(p,3500)})}}import{spawnSync as ne}from"node:child_process";import ci from"tree-kill";function rr(n){if(process.platform==="win32"){let o=ne("powershell",["-NoProfile","-Command",`Get-NetTCPConnection -LocalPort ${n} -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty OwningProcess`],{encoding:"utf8",windowsHide:!0});if(o.status!==0)return null;let i=Number((o.stdout||"").trim().split(/\s+/)[0]);if(!Number.isFinite(i)||i<=0)return null;let a=ne("powershell",["-NoProfile","-Command",`Get-CimInstance Win32_Process -Filter "ProcessId=${i}" | Select-Object -Property Name,CommandLine | ConvertTo-Json -Compress`],{encoding:"utf8",windowsHide:!0}),u,l;try{let h=JSON.parse((a.stdout||"").trim()||"{}");u=typeof h.Name=="string"?h.Name:void 0,l=typeof h.CommandLine=="string"?h.CommandLine:void 0}catch{}return{pid:i,name:u,cmd:l}}let t=ne("lsof",["-nP","-iTCP:"+n,"-sTCP:LISTEN"],{encoding:"utf8"});if(t.status!==0)return null;let e=(t.stdout||"").split(/\r?\n/).filter(o=>o.trim()&&!o.startsWith("COMMAND"));if(!e.length)return null;let r=e[0].split(/\s+/);return{pid:Number(r[1]),name:r[0]}}function nr(n,t){if(!t)return`port ${n} already in use`;let e=[`port ${n} in use by`];return t.name&&e.push(t.name),e.push(`(pid ${t.pid}`),t.cmd&&(e[e.length-1]+=`, cmd: ${t.cmd.slice(0,120)}`),e[e.length-1]+=")",e.join(" ")}import or from"node:fs";import sr from"node:path";function ir(n){let t={},e;try{e=or.readFileSync(n,"utf8")}catch{return t}for(let r of e.split(/\r?\n/)){let s=r.trim();if(!s||s.startsWith("#"))continue;let o=s.indexOf("=");if(o<0)continue;let i=s.slice(0,o).trim(),a=s.slice(o+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),i&&(t[i]=a)}return t}function se(n,t){return sr.isAbsolute(t)?t:sr.join(n,t)}function oe(n,t){return t.filter(e=>or.existsSync(se(n,e)))}rt();import Jn from"node:fs";import Wn from"node:path";function Gn(){return Wn.join(V(),"secrets.json")}function pr(){try{let n=Jn.readFileSync(Gn(),"utf8");n.charCodeAt(0)===65279&&(n=n.slice(1));let t=JSON.parse(n);if(!t||typeof t!="object")return{};let e={};for(let[r,s]of Object.entries(t))typeof s=="string"&&(e[r]=s);return e}catch{return{}}}function dr(n,t){let e={};for(let[r,s]of Object.entries(n))e[r]=s.replace(/\$\{([A-Z_][A-Z0-9_]*)\}/gi,(o,i)=>t[i]??`\${${i}}`);return e}import ue from"node:fs";import qn from"node:os";import fr from"node:path";var $t=class{file=null;startTs=0;isRecording(){return this.file!=null}start(){if(this.file)return{path:this.file};let t=fr.join(qn.homedir(),".daimon","sessions");ue.mkdirSync(t,{recursive:!0});let e=fr.join(t,`${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`);return ue.writeFileSync(e,""),this.file=e,this.startTs=Date.now(),{path:e}}stop(){let t={path:this.file};return this.file=null,this.startTs=0,t}append(t){if(!this.file)return;let e=JSON.stringify({ts:Date.now()-this.startTs,...t})+`
|
|
42
|
+
`;try{ue.appendFileSync(this.file,e)}catch{}}};var mr=500,Mt=class extends Xn{entries=new Map;portAlloc;config;eventBuffer=[];history=null;watchTasks=new Map;sessionRecorder=new $t;constructor(t,e,r){super(),this.config=t,this.portAlloc=r??new ot(t.portRange);for(let s of e)this.entries.set(s.name,{app:s,state:this.freshState(s.name,s.tags,s.workspaceLabel??null),proc:null})}getConfig(){return this.config}addDiscoveredApp(t){this.entries.has(t.name)||(this.entries.set(t.name,{app:t,state:this.freshState(t.name,t.tags,t.workspaceLabel??null),proc:null}),this.emit("change"))}updateDiscoveredApp(t){let e=this.entries.get(t.name);e&&(e.app=t,e.state.tags=t.tags,e.state.workspaceLabel=t.workspaceLabel??null,e.state.dependsOn=this.config.depends?.[t.name]??[],this.emit("change"))}getPortAllocator(){return this.portAlloc}setHistory(t){this.history=t}getHistory(){return this.history}freshState(t,e,r=null){return{name:t,status:"stopped",port:null,pid:null,startedAt:null,compileStartedAt:null,lastCompileMs:null,lastCompileAt:null,logBuffer:[],errors:new Map,compileHistory:[],health:"unknown",lastHealthAt:null,cpu:null,memMB:null,restartAttempts:0,restartWindowStart:null,nextRestartAt:null,tags:e,announcedUrl:null,lastHealthError:null,cachedProbeHost:null,lastLogTs:null,stale:!1,bundle:null,bundleRegressionPct:null,activeEnvFile:null,sessionOverrides:null,dependsOn:this.config.depends?.[t]??[],workspaceLabel:r,discoveredHealthPath:null}}names(){return[...this.entries.keys()]}list(){return this.names().map(t=>this.summary(t))}summary(t){let e=this.entries.get(t);if(!e)return null;let r=e.state,s=r.startedAt&&(r.status==="serving"||r.status==="compiling"||r.status==="starting")?Date.now()-r.startedAt:null,i=this.config.overrides?.[t]?.url||e.resolvedUrl||r.announcedUrl||(r.port?`http://127.0.0.1:${r.port}`:null),a;for(let u=this.eventBuffer.length-1;u>=0;u--){let l=this.eventBuffer[u];if(l.app===t&&l.type==="status"){a=Date.now()-l.ts;break}}return{name:r.name,status:r.status,port:r.port,url:i,errorCount:[...r.errors.values()].reduce((u,l)=>u+l.count,0),uptimeMs:s,lastCompileMs:r.lastCompileMs,health:r.health,lastHealthAt:r.lastHealthAt,cpu:r.cpu,memMB:r.memMB,compileHistoryMs:[...r.compileHistory],tags:[...r.tags],restartAttempts:r.restartAttempts,nextRestartAt:r.nextRestartAt,announcedUrl:r.announcedUrl,lastHealthError:r.lastHealthError,stale:r.stale,bundle:r.bundle,bundleRegressionPct:r.bundleRegressionPct,dependsOn:[...r.dependsOn],activeEnvFile:r.activeEnvFile,workspaceLabel:r.workspaceLabel,lastChangeMs:a}}getState(t){return this.entries.get(t)?.state??null}getApp(t){return this.entries.get(t)?.app??null}errors(t){let e=this.getState(t);return e?[...e.errors.values()].sort((r,s)=>s.lastSeen-r.lastSeen):null}errorsSince(t,e){let r=this.getState(t);return r?[...r.errors.values()].filter(s=>s.lastSeen>e).sort((s,o)=>o.lastSeen-s.lastSeen):null}logs(t,e={}){let r=this.getState(t);if(!r)return null;let s=r.logBuffer;if(e.sinceMs&&e.sinceMs>0){let o=Date.now()-e.sinceMs;s=s.filter(i=>i.ts>=o)}return e.tail&&e.tail>0&&(s=s.slice(-e.tail)),s.map(o=>o.line)}events(t={}){let e=t.sinceMs&&t.sinceMs>0?Date.now()-t.sinceMs:0;return this.eventBuffer.filter(r=>r.ts>=e&&(!t.app||r.app===t.app))}recordEvent(t){let e={ts:t.ts??Date.now(),...t};this.eventBuffer.push(e),this.emit("event",e),this.eventBuffer.length>mr&&this.eventBuffer.splice(0,this.eventBuffer.length-mr),this.history?.recordEvent(e),this.emit("event",e)}setHealth(t,e){let r=this.entries.get(t);if(!r)return;let s=r.state;if(s.lastHealthAt=Date.now(),s.health===e)return;let o=s.health;s.health=e,e==="healthy"&&(r.prevHealthyAt=Date.now(),r.cascadeArmed&&(r.cascadeArmed=!1,this.triggerCascadeRestart(t))),this.recordEvent({app:t,type:"health",from:o,to:e}),this.emit("change")}armCascade(t){let e=this.entries.get(t);e&&this.config.cascadeRestart&&e.prevHealthyAt!=null&&(e.cascadeArmed=!0)}setLastHealthError(t,e){let r=this.getState(t);r&&r.lastHealthError!==e&&(r.lastHealthError=e,this.emit("change"))}setResolvedUrl(t,e){let r=this.entries.get(t);r&&r.resolvedUrl!==e&&(r.resolvedUrl=e,this.emit("change"))}setCachedProbeHost(t,e){let r=this.getState(t);r&&(r.cachedProbeHost=e)}setStale(t,e){let r=this.getState(t);r&&r.stale!==e&&(r.stale=e,this.emit("change"))}setSessionOverride(t,e){let r=this.getState(t);r&&(r.sessionOverrides=e,this.emit("change"))}setActiveEnvFile(t,e){let r=this.getState(t);r&&(r.activeEnvFile=e,this.emit("change"))}async start(t){this.sessionRecorder.append({kind:"start",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(e.proc?.isRunning())return{ok:!0,status:e.state.status};let r=e.state.status,s;try{s=await this.portAlloc.allocate(t,e.app.pinnedPort)}catch(S){return e.state.status="error",e.state.lastStatusMessage=S.message,this.recordEvent({app:t,type:"status",from:r,to:"error",message:S.message}),this.emit("change"),{ok:!1,status:"error",error:S.message}}if(!await it(s)){let S=rr(s),c=nr(s,S);return e.state.status="error",e.state.port=s,e.state.lastStatusMessage=c,this.recordEvent({app:t,type:"status",from:r,to:"error",message:c}),this.emit("change"),{ok:!1,status:"error",error:c}}e.state.health="unknown",e.state.lastHealthAt=null,e.state.announcedUrl=null,e.state.lastHealthError=null,e.state.cachedProbeHost=null,e.state.stale=!1,e.state.lastLogTs=null,e.resolvedUrl=void 0,!e.logger&&this.config.logs.enabled&&(e.logger=new Pt(t,this.config.logs));let i=e.state.sessionOverrides,a=this.config.envFiles?.[t]??[],u={};if(a.length){let S=e.state.activeEnvFile;(!S||!oe(e.app.workspaceRoot,[S]).length)&&(S=oe(e.app.workspaceRoot,a)[0]??null,S&&(e.state.activeEnvFile=S)),S&&(u=ir(se(e.app.workspaceRoot,S)))}let l={...u,...this.config.overrides?.[t]?.env??{},...i?.env??{}},h=pr(),p=dr(l,h),x=new At({state:e.state,app:e.app,port:s,envOverride:Object.keys(p).length?p:void 0,commandOverride:i?.command,onStateChange:()=>this.emit("change"),onStatusChange:(S,c,f)=>{this.recordEvent({app:t,type:"status",from:S,to:c,message:f}),(c==="stopped"||c==="error")&&(S==="serving"||S==="compiling")&&this.armCascade(t)},onErrorRecorded:(S,c)=>this.recordEvent({app:t,type:c?"error-new":"error-recur",message:S.message}),onExit:(S,c,f)=>this.emit("childExit",{name:t,code:S,signal:c,stopping:f}),onLogLine:S=>{e.logger?.write(S),this.emit("log",{name:t,ts:Date.now(),line:S})},onCompile:S=>{this.history?.recordCompile(t,S);let c=this.getState(t),f=e.lastBundleInitialKB;if(c.bundle&&c.bundle.initialKB>0){if(f&&f>0){let m=(c.bundle.initialKB-f)/f*100;c.bundleRegressionPct=Math.round(m*10)/10,m>10&&this.recordEvent({app:t,type:"bundle-regression",message:`initialKB +${c.bundleRegressionPct}% (${f}->${c.bundle.initialKB})`})}else c.bundleRegressionPct=null;e.lastBundleInitialKB=c.bundle.initialKB}this.checkCompileRegression(t,S),this.emit("compile",{name:t,ms:S})},onBundleUpdate:()=>this.emit("bundleUpdate",{name:t})});return e.proc=x,this.recordEvent({app:t,type:"status",from:r,to:"starting"}),x.start(),{ok:!0,status:e.state.status}}async stop(t){this.sessionRecorder.append({kind:"stop",app:t});let e=this.entries.get(t);if(!e)return{ok:!1,status:"unknown",error:"unknown app"};if(this.emit("userStop",{name:t}),!e.proc||!e.proc.isRunning())return e.state.status!=="stopped"&&this.recordEvent({app:t,type:"status",from:e.state.status,to:"stopped"}),e.state.status="stopped",e.state.pid=null,e.state.health="unknown",this.emit("change"),{ok:!0,status:"stopped"};let r=e.state.status;return await e.proc.stop(),e.proc=null,e.state.status!==r&&this.recordEvent({app:t,type:"status",from:r,to:e.state.status}),{ok:!0,status:e.state.status}}async restart(t){return this.sessionRecorder.append({kind:"restart",app:t}),await this.stop(t),this.start(t)}async startWithDeps(t,e={}){if(!this.entries.has(t))return{ok:!1,results:[{name:t,status:"unknown",health:"unknown",error:"unknown app"}]};let r=Xe(this.config.depends??{},t).filter(a=>this.entries.has(a)),s=Ke(this.config.depends??{},r),o=[],i=e.waitMs??6e4;for(let a of s){let u=await Promise.all(a.map(h=>this.start(h)));for(let h=0;h<a.length;h++){let p=u[h];if(!p.ok)return o.push({name:a[h],status:p.status,health:"unknown",error:p.error}),{ok:!1,results:o}}let l=await Promise.all(a.map(h=>this.waitFor(h,"healthy",i)));for(let h=0;h<a.length;h++){let p=l[h],x=!p.timedOut&&p.status==="serving"&&p.health==="healthy";if(o.push({name:p.name,status:p.status,health:p.health,error:x?void 0:p.timedOut?"timeout waiting for healthy":"did not reach healthy"}),!x)return{ok:!1,results:o}}}return{ok:!0,results:o}}triggerCascadeRestart(t){if(!this.config.cascadeRestart)return;let e=Ye(this.config.depends??{},t);for(let r of e){let s=this.getState(r);s&&(s.status==="serving"||s.status==="compiling"||s.status==="starting")&&this.restart(r)}}async stopAll(t=3e3){let e=[];for(let r of this.entries.values())r.proc?.isRunning()&&e.push(r.proc.stop());for(let r of this.watchTasks.values())e.push(r.stop());await Promise.race([Promise.all(e),new Promise(r=>setTimeout(r,t))]);for(let r of this.entries.values())r.logger?.close()}listTasks(t){let e=this.getApp(t);return e?[...e.tasks??[]]:null}async runTask(t,e,r=[]){this.sessionRecorder.append({kind:"run",app:t,task:e,args:r});let s=this.getApp(t);if(!s)return{error:"unknown app"};let o=await tr(s,e,r);return this.history?.recordTaskRun(t,e,o.exitCode,o.durationMs,o.summary),this.recordEvent({app:t,type:"task-run",message:`${e} exit=${o.exitCode} duration=${o.durationMs}ms`}),this.emit("taskRun",{name:t,task:e,result:o}),o}startWatchTask(t,e,r=[]){let s=this.getApp(t);if(!s)return{ok:!1,error:"unknown app"};let o=`${t}::${e}`;if(this.watchTasks.has(o))return{ok:!0,pid:this.watchTasks.get(o).pid};let i=er(s,e,r);return this.watchTasks.set(o,i),i.child.on("exit",()=>this.watchTasks.delete(o)),{ok:!0,pid:i.pid}}async stopWatchTask(t,e){let r=`${t}::${e}`,s=this.watchTasks.get(r);return s?(await s.stop(),this.watchTasks.delete(r),{ok:!0}):{ok:!0}}listWatchTasks(t){let e=[];for(let r of this.watchTasks.values())t&&r.app!==t||e.push({app:r.app,task:r.task,pid:r.pid,startedAt:r.startedAt});return e}checkCompileRegression(t,e){let r=this.history;if(!r)return;let o=r.queryCompiles({app:t,limit:31}).filter(u=>u.ms!==e).slice(0,30).map(u=>u.ms);if(o.length<10)return;let i=[...o].sort((u,l)=>u-l),a=i[Math.floor((i.length-1)*.5)];e>2*a&&this.recordEvent({app:t,type:"compile-regression",message:`${(e/1e3).toFixed(1)}s vs p50 ${(a/1e3).toFixed(1)}s`})}watchTaskLogs(t,e,r){let s=this.watchTasks.get(`${t}::${e}`);if(!s)return null;let o=s.logs;return r?o.slice(-r):[...o]}waitFor(t,e,r){return new Promise(s=>{let o=Date.now(),i=this.entries.get(t),a=()=>{if(!i)return!0;let p=i.state;return e==="serving"&&p.status==="serving"||e==="healthy"&&p.status==="serving"&&p.health==="healthy"||e==="stopped"&&p.status==="stopped"||e==="error"&&p.status==="error"},u=p=>{this.off("change",l),clearTimeout(h);let x=i?.state;s({name:t,status:x?.status??"unknown",health:x?.health??"unknown",timedOut:p,waitedMs:Date.now()-o})},l=()=>{a()&&u(!1)};if(a()){s({name:t,status:i.state.status,health:i.state.health,timedOut:!1,waitedMs:0});return}let h=setTimeout(()=>u(!0),r);this.on("change",l)})}};Ct();import $s from"node:http";import Ms from"node:crypto";import nt from"node:fs";import B from"node:path";import{fileURLToPath as _s}from"node:url";import fe from"node:fs";import hr from"node:path";import Kn from"node:os";var me=hr.join(Kn.homedir(),".daimon","cursors.json");function Yn(){try{let n=fe.readFileSync(me,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.errors&&typeof t.errors=="object")return{errors:t.errors}}catch{}return{errors:{}}}var pe=null,de=null;function zn(n){de=n,!pe&&(pe=setTimeout(()=>{pe=null;let t=de;if(de=null,!!t)try{fe.mkdirSync(hr.dirname(me),{recursive:!0}),fe.writeFileSync(me,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: cursor write failed: ${e.message}
|
|
43
|
+
`)}},500))}var _t=class{data=Yn();getErrorCursor(t,e){return this.data.errors[`${t}:${e}`]??0}setErrorCursor(t,e,r){this.data.errors[`${t}:${e}`]=r,zn(this.data)}};import gr from"node:fs";import Vn from"node:os";import yr from"node:path";var Zn=/key|secret|token|password|api[-_]?key/i;function Qn(n){let t={};for(let[e,r]of Object.entries(n))typeof r=="string"&&(t[e]=Zn.test(e)?"***":r);return t}function he(n,t){let e=n.summary(t);if(!e)return null;let r=n.getState(t),s=n.getApp(t),o=n.getConfig(),i=o.overrides?.[t]??{},a={...process.env,...s.env??{},...r.sessionOverrides?.env??{}},u=n.getHistory(),l=u?u.queryEvents({app:t,limit:50}):[];return{takenAt:new Date().toISOString(),summary:e,logs:r.logBuffer.slice(-500).map(h=>({ts:h.ts,line:h.line})),errors:[...r.errors.entries()].map(([h,p])=>({hash:h,message:p.message,count:p.count,firstSeen:p.firstSeen,lastSeen:p.lastSeen})),env:Qn(a),configSlice:{command:r.sessionOverrides?.command??i.command??s.command,port:r.sessionOverrides?.port??i.port??null,workspaceRoot:s.workspaceRoot,workspaceType:s.workspaceType,tags:s.tags,depends:o.depends?.[t]??[],envFiles:o.envFiles?.[t]??[]},events:l}}function vr(n,t){let e=he(n,t);if(!e)return null;let r=yr.join(Vn.homedir(),".daimon","snapshots");gr.mkdirSync(r,{recursive:!0});let s=e.takenAt.replace(/[:.]/g,"-"),o=yr.join(r,`${t}-${s}.json`);return gr.writeFileSync(o,JSON.stringify(e,null,2)),{path:o,payload:e}}import Lt from"node:fs";import wr from"node:path";var ts=["dist",".angular/cache","tmp","out-tsc"],es=["node_modules"];function br(n){let t=0;try{let e=Lt.readdirSync(n,{withFileTypes:!0});for(let r of e){let s=wr.join(n,r.name);try{r.isDirectory()?t+=br(s):r.isFile()&&(t+=Lt.statSync(s).size)}catch{}}}catch{}return t}function ge(n,t,e){let r=n.getApp(t);if(!r)return null;let s=n.getState(t),o=s?s.status==="serving"||s.status==="compiling"||s.status==="starting":!1,a=[...ts,...e?es:[]].map(u=>{let l=wr.join(r.workspaceRoot,u),h=Lt.existsSync(l);return{path:l,exists:h,sizeBytes:h?br(l):0}});return{app:t,workspace:r.workspaceRoot,targets:a,ranOnServing:o}}function Sr(n,t,e){let r=ge(n,t,e);if(!r)return{error:"unknown app"};if(r.ranOnServing)return{error:"app is currently running; stop it first"};let s=[],o=[];for(let i of r.targets)if(i.exists)try{Lt.rmSync(i.path,{recursive:!0,force:!0}),s.push(i.path)}catch(a){o.push({path:i.path,error:a?.message||String(a)})}return{ok:o.length===0,removed:s,failed:o}}function kt(n){return n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}var rs=["stopped","starting","compiling","serving","error"];function kr(n){let t=[];t.push("# HELP daimon_up daimon daemon up"),t.push("# TYPE daimon_up gauge"),t.push("daimon_up 1"),t.push("# HELP daimon_app_status app status one-hot"),t.push("# TYPE daimon_app_status gauge");let e=n.list();for(let r of e)for(let s of rs)t.push(`daimon_app_status{name="${kt(r.name)}",status="${s}"} ${r.status===s?1:0}`);t.push("# HELP daimon_compile_seconds last successful compile duration in seconds"),t.push("# TYPE daimon_compile_seconds gauge");for(let r of e)r.lastCompileMs!=null&&t.push(`daimon_compile_seconds{name="${kt(r.name)}"} ${(r.lastCompileMs/1e3).toFixed(3)}`);t.push("# HELP daimon_error_total cumulative deduped error count"),t.push("# TYPE daimon_error_total counter");for(let r of e)t.push(`daimon_error_total{name="${kt(r.name)}"} ${r.errorCount}`);t.push("# HELP daimon_cpu_percent app CPU percent"),t.push("# TYPE daimon_cpu_percent gauge");for(let r of e)r.cpu!=null&&t.push(`daimon_cpu_percent{name="${kt(r.name)}"} ${r.cpu}`);t.push("# HELP daimon_mem_mb app resident memory MB"),t.push("# TYPE daimon_mem_mb gauge");for(let r of e)r.memMB!=null&&t.push(`daimon_mem_mb{name="${kt(r.name)}"} ${r.memMB}`);return t.join(`
|
|
43
44
|
`)+`
|
|
44
|
-
`}
|
|
45
|
-
`;try{
|
|
46
|
-
`);let
|
|
47
|
-
`)};n.on("event",
|
|
48
|
-
`)}catch{}},3e4);
|
|
49
|
-
`);
|
|
45
|
+
`}rt();import xt from"node:fs";import ns from"node:crypto";import xr from"node:path";var ss=1e6;function os(){return xr.join(V(),"audit.log")}function is(n){try{if(xt.statSync(n).size>ss){let e=n+".1";try{xt.unlinkSync(e)}catch{}xt.renameSync(n,e)}}catch{}}function Er(n,t,e,r){let s=os();xt.mkdirSync(xr.dirname(s),{recursive:!0}),is(s);let o=JSON.stringify({prev:t,next:e}),i=ns.createHash("sha1").update(o).digest("hex").slice(0,12),a=`${new Date().toISOString()} ${n} ${i} ${r.join(",")}
|
|
46
|
+
`;try{xt.appendFileSync(s,a)}catch{}}import Dt from"node:fs";import Ft from"node:path";import{fileURLToPath as as}from"node:url";var Tr=Ft.dirname(as(import.meta.url));function cs(){let n=[Ft.resolve(Tr,"templates","presets"),Ft.resolve(Tr,"..","src","templates","presets")];for(let t of n)if(Dt.existsSync(t))return t;return n[0]}function Rr(){let n=cs();if(!Dt.existsSync(n))return[];let t=Dt.readdirSync(n).filter(r=>r.endsWith(".json")),e=[];for(let r of t)try{let s=Dt.readFileSync(Ft.join(n,r),"utf8");s.charCodeAt(0)===65279&&(s=s.slice(1)),e.push(JSON.parse(s))}catch{}return e}rt();import It from"node:fs";import Ar from"node:path";function Cr(){return Ar.join(V(),"state-handoff.json")}function Pr(n){let t=[];for(let s of n.names()){let o=n.getState(s);o&&(o.status==="serving"||o.status==="compiling"||o.status==="starting")&&o.port&&t.push({name:s,port:o.port})}let e={ts:Date.now(),apps:t},r=Cr();return It.mkdirSync(Ar.dirname(r),{recursive:!0}),It.writeFileSync(r,JSON.stringify(e)),r}function Or(n=6e4){let t=Cr();try{let e=It.readFileSync(t,"utf8"),r=JSON.parse(e);return It.unlinkSync(t),!r||typeof r.ts!="number"||Date.now()-r.ts>n?null:r}catch{return null}}Ot();var Ls=_s(import.meta.url),Ht=B.dirname(Ls);function be(){let n=[B.resolve(Ht,"dashboard","browser"),B.resolve(Ht,"dashboard"),B.resolve(Ht,"..","dist","dashboard","browser"),B.resolve(Ht,"..","dist","dashboard")];for(let t of n)if(nt.existsSync(B.join(t,"index.html")))return t;return null}var Ds={".html":"text/html; charset=utf-8",".js":"application/javascript; charset=utf-8",".mjs":"application/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".ico":"image/x-icon",".json":"application/json; charset=utf-8",".map":"application/json; charset=utf-8",".woff2":"font/woff2",".woff":"font/woff",".ttf":"font/ttf"};function Et(n,t){try{if(!nt.statSync(t).isFile())return!1;let r=B.extname(t).toLowerCase(),s=Ds[r]??"application/octet-stream",o=nt.readFileSync(t);return n.writeHead(200,{"content-type":s,"content-length":o.length,"cache-control":r===".html"?"no-cache":"public, max-age=3600"}),n.end(o),!0}catch{return!1}}function b(n,t,e){let r=JSON.stringify(e);n.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(r)}),n.end(r)}function ft(n){if(!n)return;let t=n.match(/^(\d+)(ms|s|m|h)?$/);if(!t)return;let e=Number(t[1]);switch(t[2]||"ms"){case"ms":return e;case"s":return e*1e3;case"m":return e*60*1e3;case"h":return e*60*60*1e3}}function Bt(n,t){let e=(n.searchParams.get("format")||"").toLowerCase();return e==="full"?"full":e==="compact"?"compact":t?.().output?.format==="full"?"full":"compact"}function Fs(n){return{name:n.name,status:n.status,port:n.port,health:n.health,errCount:n.errorCount,lastChangeMs:n.lastChangeMs??null}}function dt(n){return{name:n.name,status:n.status,port:n.port,url:n.url,health:n.health,errCount:n.errorCount,lastChangeMs:n.lastChangeMs??null,uptime:n.uptimeMs}}function Se(n){let t=n.parsed;return t&&(t.file||t.code)?{file:t.file??null,line:t.line??null,col:t.col??null,code:t.code??null,message:t.message??n.message}:{file:null,line:null,col:null,code:null,message:n.message}}function Is(n){if(!n)return{};if(/^\d{10,}$/.test(n))return{sinceTs:Number(n)};let t=ft(n);return t!=null?{sinceMs:t}:{}}var Hs=/key|secret|token|password|pass/i;function Bs(n){let t=JSON.parse(JSON.stringify(n));if(t.apiToken&&(t.apiToken="***"),t.overrides&&typeof t.overrides=="object")for(let e of Object.keys(t.overrides)){let r=t.overrides[e]?.env;if(r&&typeof r=="object")for(let s of Object.keys(r))Hs.test(s)&&(r[s]="***")}return t}function ke(n){if(!n)return"";try{let t=nt.readFileSync(n);return Ms.createHash("sha1").update(t).digest("hex")}catch{return""}}function Mr(n,t,e={}){let r=new _t,s=$s.createServer(async(o,i)=>{try{let a=new URL(o.url||"/","http://127.0.0.1"),u=o.method||"GET",l=a.pathname.replace(/\/$/,"").split("/").filter(Boolean),h=()=>{let f=(e.getConfig?e.getConfig():null)?.apiToken??null;if(!f)return!0;let m=o.headers.authorization;return typeof m=="string"&&m.toLowerCase().startsWith("bearer ")&&m.slice(7).trim()===f?!0:(b(i,401,{error:"unauthorized"}),!1)};if(u==="POST"&&a.pathname==="/api/shutdown"){if(!h())return;b(i,200,{ok:!0}),e.onShutdown&&setImmediate(()=>{try{e.onShutdown()}catch{}});return}if(a.pathname==="/api/config"&&e.getConfig){if(u==="GET"){let c=e.getConfig(),f=ke(e.configPath);i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:f}),i.end(JSON.stringify({etag:f,config:Bs(c)}));return}if(u==="PATCH"&&e.patchConfig){if(!h())return;let c=o.headers["if-match"]?.trim(),f=ke(e.configPath);if(!c||c!==f){b(i,412,{error:"etag mismatch",current:f});return}let m={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(R=>{let T=[];o.on("data",v=>T.push(v)),o.on("end",()=>{try{m=JSON.parse(Buffer.concat(T).toString("utf8"))}catch{}R()})});let d=e.patchConfig(m);if(!d.ok){b(i,400,{error:d.error});return}let g=ke(e.configPath);try{let R=o.socket.remoteAddress||"127.0.0.1";Er(R,m,m,d.applied)}catch{}i.writeHead(200,{"content-type":"application/json; charset=utf-8",etag:g}),i.end(JSON.stringify({etag:g,applied:d.applied,addedApps:d.addedApps,removedApps:d.removedApps,restartRequired:d.restartRequired}));return}b(i,405,{error:"method not allowed"});return}if(a.pathname==="/api/presets"&&u==="GET"){b(i,200,Rr());return}if(a.pathname==="/api/snapshot-state"&&u==="POST"){if(!h())return;let c=Pr(n);b(i,200,{ok:!0,path:c});return}if(a.pathname==="/api/config/reload"&&u==="POST"&&e.reloadConfig){if(!h())return;try{let c=await e.reloadConfig();b(i,200,c)}catch(c){b(i,400,{error:c?.message||String(c)})}return}if(u==="GET"&&a.pathname==="/metrics"&&e.metricsEnabled){let c=kr(n);i.writeHead(200,{"content-type":"text/plain; version=0.0.4","content-length":Buffer.byteLength(c)}),i.end(c);return}if(u!=="GET"&&a.pathname.startsWith("/api/")&&a.pathname!=="/api/shutdown"&&a.pathname!=="/api/config"&&a.pathname!=="/api/config/reload"&&!h())return;if(u==="GET"&&a.pathname==="/"){let c=be();if(c&&Et(i,B.join(c,"index.html")))return;i.writeHead(404).end('dashboard not found \u2014 run "npm run build:dashboard" in the daimon repo');return}if(l[0]==="api"&&l[1]==="events"&&l.length===2){if(u!=="GET"){b(i,405,{error:"method not allowed"});return}let c=ft(a.searchParams.get("since")),f=a.searchParams.get("app")||void 0;if(a.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});let g=n.events({sinceMs:c,app:f});for(let v of g)i.write(JSON.stringify(v)+`
|
|
47
|
+
`);let R=v=>{f&&v.app!==f||i.write(JSON.stringify(v)+`
|
|
48
|
+
`)};n.on("event",R);let T=setInterval(()=>{try{i.write(`
|
|
49
|
+
`)}catch{}},3e4);o.on("close",()=>{n.off("event",R),clearInterval(T);try{i.end()}catch{}});return}let m=n.events({sinceMs:c,app:f}),d=n.getHistory();if(d&&c&&m.length<500){let g=Date.now()-c,R=d.queryEvents({app:f,since:g,limit:1e3}),T=new Set(m.map(v=>`${v.ts}|${v.app}|${v.type}|${v.from??""}|${v.to??""}|${v.message??""}`));for(let v of R){let j=`${v.ts}|${v.app}|${v.type}|${v.from_state??""}|${v.to_state??""}|${v.message??""}`;T.has(j)||m.push({ts:v.ts,app:v.app,type:v.type,from:v.from_state??void 0,to:v.to_state??void 0,message:v.message??void 0})}m.sort((v,j)=>v.ts-j.ts)}b(i,200,m);return}if(l[0]==="api"&&l[1]==="session"){if(l[2]==="record"&&u==="POST"){let c=a.searchParams.get("action")||"toggle";if(c==="start"||c==="toggle"&&!n.sessionRecorder.isRecording()){let f=n.sessionRecorder.start();b(i,200,{recording:!0,path:f.path});return}if(c==="stop"||c==="toggle"&&n.sessionRecorder.isRecording()){let f=n.sessionRecorder.stop();b(i,200,{recording:!1,path:f.path});return}b(i,400,{error:"invalid action"});return}if(l[2]==="status"&&u==="GET"){b(i,200,{recording:n.sessionRecorder.isRecording()});return}b(i,404,{error:"not found"});return}if(l[0]==="api"&&l[1]==="history"){if(u!=="GET"){b(i,405,{error:"method not allowed"});return}let c=n.getHistory();if(!c){b(i,200,[]);return}let f=l[2],m=a.searchParams.get("app")||void 0,d=a.searchParams.get("since"),g=a.searchParams.get("until"),R=a.searchParams.get("limit"),T=d?/^\d{10,}$/.test(d)?Number(d):Date.now()-(ft(d)??0):void 0,v=g?/^\d{10,}$/.test(g)?Number(g):Date.now()-(ft(g)??0):void 0,j=R?Number(R):void 0;if(f==="events"){b(i,200,c.queryEvents({app:m,since:T,until:v,type:a.searchParams.get("type")||void 0,limit:j}));return}if(f==="compile-times"){b(i,200,c.queryCompiles({app:m,since:T,until:v,limit:j}));return}if(f==="tasks"){b(i,200,c.queryTasks({app:m,task:a.searchParams.get("task")||void 0,since:T,limit:j}));return}if(f==="summary"&&l.length>=4){let M=decodeURIComponent(l[3]);b(i,200,c.summary(M));return}if(f==="why"&&l.length>=4){let M=decodeURIComponent(l[3]);b(i,200,c.why(M));return}b(i,404,{error:"not found"});return}if(l[0]==="api"&&l[1]==="profiles"&&l[3]==="ensure-up"&&u==="POST"){let c=decodeURIComponent(l[2]),f=e.getConfig?.(),m=f?.profiles?.[c];if(!m){b(i,404,{error:"unknown profile"});return}let d=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(d)){b(i,400,{error:"until must be serving|healthy"});return}let g=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),R=g?Number(g):3e5;(!Number.isFinite(R)||R<=0)&&(R=3e5),R=Math.min(R,12e5);let T=f?.healthProbe?.enabled??!0,v=d==="healthy"&&!T?"serving":d,j=Date.now();for(let E of m){let y=n.summary(E);y&&y.status!=="serving"&&y.status!=="starting"&&y.status!=="compiling"&&await n.startWithDeps(E)}let M=await Promise.all(m.map(async E=>{let y=Math.max(1e3,R-(Date.now()-j));if(!n.summary(E))return{name:E,state:null,until:v,reachedTargetMs:null,timedOut:!1,error:"unknown"};let k=await n.waitFor(E,v,y),N=n.summary(E);return{name:E,state:N?dt(N):null,until:v,reachedTargetMs:k.timedOut?null:k.waitedMs,timedOut:k.timedOut}}));b(i,200,{profile:c,apps:M,_meta:{totalMs:Date.now()-j,until:v}});return}if(l[0]==="api"&&l[1]==="discovery"&&l[2]==="explain"&&u==="GET"){let c=e.getConfig?.();if(!c){b(i,200,{searchRoots:[],scanned:0,rejected:{},warnings:[],suggestion:"no config loaded"});return}let{discoverApps:f}=await Promise.resolve().then(()=>(bt(),re)),m={scanned:0,rejected:{}},d=[],g=f(c,{warnings:d,stats:m}),R=c.searchRoots.map(T=>typeof T=="string"?T:T.path);b(i,200,{searchRoots:R,scanned:m.scanned,rejected:m.rejected,warnings:d,appsFound:g.length,suggestion:g.length===0?R.length===0?"no searchRoots configured. Run 'daimon init --auto' from a workspace folder.":"discovery returned no apps. Check that searchRoots contain nx.json / angular.json / vite.config.* / .storybook.":`${g.length} apps discovered`});return}if(l[0]==="api"&&l[1]==="doctor"&&l[2]==="auto-fix"&&u==="POST"){if(!h())return;let c={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(T=>{let v=[];o.on("data",j=>v.push(j)),o.on("end",()=>{try{c=JSON.parse(Buffer.concat(v).toString("utf8"))}catch{}T()})});let{runAutoFix:f,ALL_AUTO_FIX:m}=await Promise.resolve().then(()=>(we(),ve)),g=e.getConfig?.()?.doctor?.autoFix?.permitted??m,R=Array.isArray(c.permitted)&&c.permitted.length?c.permitted:g;try{let T=await f({permitted:R,dryRun:!!c.dryRun});b(i,200,T)}catch(T){b(i,500,{error:T?.message??String(T)})}return}if(l[0]==="api"&&l[1]==="overview"&&u==="GET"){let c=e.getConfig?.(),f=n.list(),m=a.searchParams.get("workspace"),d=a.searchParams.get("profile"),g=f;if(m&&(g=g.filter(k=>k.workspaceLabel===m)),d){let k=c?.profiles?.[d]??null;k&&(g=g.filter(N=>k.includes(N.name)))}let R={apps:g.length,serving:g.filter(k=>k.status==="serving").length,errors:g.filter(k=>k.status==="error").length,stopped:g.filter(k=>k.status==="stopped").length,totalErrCount:g.reduce((k,N)=>k+N.errorCount,0),totalCpuPct:Math.round(g.reduce((k,N)=>k+(N.cpu??0),0)*10)/10,totalMemMb:Math.round(g.reduce((k,N)=>k+(N.memMB??0),0))},T={};for(let k of g)(T[k.status]??=[]).push(k.name);let v=g.filter(k=>k.status==="error"||k.errorCount>0).map(k=>{let N=n.errors(k.name)??[],D=N[N.length-1],w=D?.parsed;return{name:k.name,status:k.status,errCount:k.errorCount,firstError:w?{file:w.file??null,line:w.line??null,code:w.code??null,message:w.message??D?.message??""}:D?{file:null,line:null,code:null,message:D.message}:null}}),j=Date.now()-5*6e4,M=n.events({sinceMs:5*6e4}).filter(k=>k.type==="status"&&k.ts>=j).filter(k=>m?g.some(N=>N.name===k.app):!0).filter(k=>d?g.some(N=>N.name===k.app):!0).slice(-5).map(k=>({name:k.app,transition:`${k.from??"?"}\u2192${k.to??"?"}`,msAgo:Date.now()-k.ts})),E={ts:Date.now(),version:at,totals:R,byStatus:T,needsAttention:v,recentlyChanged:M};R.apps===0&&(E._meta={suggestion:"no apps registered. run 'daimon doctor' for recommended next step, or 'daimon init --auto' from a workspace folder."});let y=a.searchParams.get("budget"),P=y?Math.max(64,Number(y)|0):null;if(P){let k=P*4,N=0,D=0;for(;JSON.stringify(E).length>k&&(E.needsAttention.length||E.recentlyChanged.length);)if(E.needsAttention.length>1)E.needsAttention.pop(),N++;else if(E.recentlyChanged.length)E.recentlyChanged.pop(),D++;else if(E.needsAttention.length===1)E.needsAttention.pop(),N++;else break;N||D?E._meta={...E._meta??{},budget:P,omitted:{needsAttention:N,recentlyChanged:D}}:E._meta={...E._meta??{},budget:P}}b(i,200,E);return}if(l[0]!=="api"||l[1]!=="apps"){if(u==="GET"&&!a.pathname.startsWith("/metrics")){let c=be();if(c){let f=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(f){let m=B.resolve(c,f);if(m.startsWith(c)&&Et(i,m))return}if(!B.extname(f||"")&&Et(i,B.join(c,"index.html")))return}}b(i,404,{error:"not found"});return}if(l.length===2){if(u!=="GET"){b(i,405,{error:"method not allowed"});return}let c=Bt(a,e.getConfig),f=n.list(),m=c==="full"?f:f.map(Fs);if(a.searchParams.get("stream")==="ndjson"){i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8"});for(let d of m)i.write(JSON.stringify(d)+`
|
|
50
|
+
`);i.end();return}if(a.searchParams.get("explain")==="1"){let d=e.getConfig?.(),g={format:c};if(d){let{discoverApps:R}=await Promise.resolve().then(()=>(bt(),re)),T={scanned:0,rejected:{}},v=[];R(d,{warnings:v,stats:T});let j=d.searchRoots.map(M=>typeof M=="string"?M:M.path);g={format:c,searchRoots:j,scanned:T.scanned,rejected:T.rejected,warnings:v,suggestion:m.length===0?j.length===0?"no searchRoots configured. Run 'daimon init --auto' from a workspace folder to add the current cwd.":"discovery returned no apps. Check that searchRoots contain nx.json / angular.json / vite.config.* / .storybook, then run 'daimon doctor'.":"apps discovered; _meta is informational."}}b(i,200,{apps:m,_meta:g});return}b(i,200,m);return}let p=decodeURIComponent(l[2]),x=l[3],S=l[4];if(!x){if(u!=="GET"){b(i,405,{error:"method not allowed"});return}let c=n.summary(p);if(!c){b(i,404,{error:"unknown app"});return}Bt(a,e.getConfig)==="full"?b(i,200,{...c,_meta:{format:"full"}}):b(i,200,{...dt(c),_meta:{format:"compact"}});return}if(x==="errors"&&S==="since-last"&&u==="GET"){let c=a.searchParams.get("client")||"default",f=r.getErrorCursor(c,p),m=n.errorsSince(p,f);if(m==null){b(i,404,{error:"unknown app"});return}let d=m.reduce((R,T)=>Math.max(R,T.lastSeen),f);d>f&&r.setErrorCursor(c,p,d);let g=Bt(a,e.getConfig);b(i,200,g==="full"?m:m.map(Se));return}if(x==="errors"&&!S&&u==="GET"){let c=a.searchParams.get("since"),f=Bt(a,e.getConfig);if(c){let{sinceMs:d,sinceTs:g}=Is(c),R=g??(d!=null?Date.now()-d:0),T=n.errorsSince(p,R);if(T==null){b(i,404,{error:"unknown app"});return}b(i,200,f==="full"?T:T.map(Se));return}let m=n.errors(p);if(m==null){b(i,404,{error:"unknown app"});return}b(i,200,f==="full"?m:m.map(Se));return}if(x==="logs"&&l[4]==="stream"&&u==="GET"){if(!n.summary(p)){b(i,404,{error:"unknown app"});return}i.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"});let c=n.logs(p,{tail:50})??[];for(let T of c)i.write(`data: ${JSON.stringify({ts:Date.now(),line:T})}
|
|
50
51
|
|
|
51
|
-
`);let
|
|
52
|
+
`);let f=[],m=0,d=()=>{for(;f.length&&i.write(f.shift()););},g=T=>{T.name===p&&(f.length>=200&&(m++,f.shift()),f.push(`data: ${JSON.stringify({ts:T.ts,line:T.line})}
|
|
52
53
|
|
|
53
|
-
`),d())};n.on("log",
|
|
54
|
+
`),d())};n.on("log",g);let R=setInterval(()=>i.write(`: ping
|
|
54
55
|
|
|
55
|
-
`),3e4);i.on("close",()=>{n.off("log",y),clearInterval(k)});return}if(b==="logs"&&u==="GET"){let l=a.searchParams.get("tail"),m=a.searchParams.get("since"),g=n.logs(p,{tail:l?Number(l):void 0,sinceMs:ct(m)});if(g==null){w(o,404,{error:"unknown app"});return}w(o,200,{lines:g});return}if(b==="wait"&&u==="GET"){if(!n.summary(p)){w(o,404,{error:"unknown app"});return}let l=(a.searchParams.get("until")||"serving").toLowerCase();if(!["serving","healthy","stopped","error"].includes(l)){w(o,400,{error:"until must be one of serving|healthy|stopped|error"});return}let m=a.searchParams.get("timeout"),g=m?Number(m):120;(!Number.isFinite(g)||g<=0)&&(g=120),g=Math.min(g,600);let d=await n.waitFor(p,l,g*1e3);w(o,200,d);return}if(b==="ensure"&&u==="POST"){let l=n.summary(p);if(!l){w(o,404,{error:"unknown app"});return}let m=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(m)){w(o,400,{error:"until must be serving|healthy"});return}let g=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),d=g?Number(g):18e4;(!Number.isFinite(d)||d<=0)&&(d=18e4),d=Math.min(d,6e5);let y=e.getConfig?.().healthProbe?.enabled??!0,k=m,E;if(k==="healthy"&&!y&&(k="serving",E="no health probe; treated serving as terminal"),k==="serving"&&l.status==="serving"||k==="healthy"&&l.status==="serving"&&l.health==="healthy"){w(o,200,{...Ft(l),_meta:{format:"compact",startedFromState:null,warning:E,waitedMs:0}});return}let O=l.status;l.status!=="starting"&&l.status!=="compiling"&&await n.start(p);let _=await n.waitFor(p,k,d),T=n.summary(p),f=T?Ft(T):{name:p,status:_.status,port:null,url:null,health:_.health,errCount:0,lastChangeMs:null,uptime:null};if(_.timedOut){w(o,200,{error:"timeout",state:f,_meta:{format:"compact",startedFromState:O,warning:E,waitedMs:_.waitedMs,timedOut:!0}});return}w(o,200,{...f,_meta:{format:"compact",startedFromState:O,warning:E,waitedMs:_.waitedMs}});return}if(b==="start"&&u==="POST"){if(a.searchParams.get("withDeps")==="1"){let g=await n.startWithDeps(p);w(o,g.ok?200:400,g);return}let m=await n.start(p);w(o,m.ok?200:400,m);return}if(b==="start-with-deps"&&u==="POST"){let l=await n.startWithDeps(p);w(o,l.ok?200:400,l);return}if(b==="tasks"&&u==="GET"&&!S){let l=n.listTasks(p);if(l==null){w(o,404,{error:"unknown app"});return}w(o,200,{tasks:l,watching:n.listWatchTasks(p)});return}if(b==="run"&&S&&u==="POST"){let l={};i.headers["content-length"]&&i.headers["content-length"]!=="0"&&await new Promise(d=>{let y=[];i.on("data",k=>y.push(k)),i.on("end",()=>{try{l=JSON.parse(Buffer.concat(y).toString("utf8"))}catch{}d()})});let m=Array.isArray(l.args)?l.args.map(String):[];if(l.watch){let d=n.startWatchTask(p,S,m);w(o,d.ok?200:400,d);return}let g=await n.runTask(p,S,m);if("error"in g){w(o,404,g);return}w(o,200,g);return}if(b==="run-stop"&&S&&u==="POST"){let l=await n.stopWatchTask(p,S);w(o,200,l);return}if(b==="env"&&u==="GET"){let m=n.getConfig().envFiles?.[p]??[],g=n.getState(p);w(o,200,{candidates:m,active:g?.activeEnvFile??null});return}if(b==="env"&&u==="POST"){let l={};i.headers["content-length"]&&i.headers["content-length"]!=="0"&&await new Promise(g=>{let d=[];i.on("data",y=>d.push(y)),i.on("end",()=>{try{l=JSON.parse(Buffer.concat(d).toString("utf8"))}catch{}g()})}),n.setActiveEnvFile(p,l.use??null);let m=n.getState(p);w(o,200,{active:m?.activeEnvFile??null});return}if(b==="requests"&&u==="GET"){if(!e.requestLog){w(o,200,[]);return}let l=ct(a.searchParams.get("since"));w(o,200,e.requestLog.requests(p,l));return}if(b==="clean"&&u==="POST"){let l=a.searchParams.get("deep")==="1",m=a.searchParams.get("yes")==="1",g=me(n,p,l);if(!g){w(o,404,{error:"unknown app"});return}if(g.ranOnServing){w(o,409,{error:"refusing: app is currently running",plan:g});return}if(!m){w(o,200,{plan:g,hint:"pass --yes to delete"});return}let d=gr(n,p,l);w(o,200,d);return}if(b==="snapshot"&&u==="POST"){if(a.searchParams.get("write")==="1"){let g=dr(n,p);if(!g){w(o,404,{error:"unknown app"});return}w(o,200,{snapshot:g.path});return}let m=de(n,p);if(!m){w(o,404,{error:"unknown app"});return}w(o,200,m);return}if(b==="stop"&&u==="POST"){let l=await n.stop(p);w(o,l.ok?200:400,l);return}if(b==="restart"&&u==="POST"){let l=await n.restart(p);w(o,l.ok?200:400,l);return}if(u==="GET"&&!a.pathname.startsWith("/api/")&&!a.pathname.startsWith("/metrics")){let l=ge();if(l){let m=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(m){let g=F.resolve(l,m);if(g.startsWith(l)&&bt(o,g))return}if(!F.extname(m||"")&&bt(o,F.join(l,"index.html")))return}}w(o,404,{error:"not found"})}catch(a){w(o,500,{error:a?.message||String(a)})}});return s.listen(t,"127.0.0.1"),s}import Es from"node:http";import Ts from"node:https";var As=1e3,Cs=500;function Rs(n,t,e,r,s){if(t)return[t];let i=n.path||"/",o=n.fallbackHosts&&n.fallbackHosts.length?n.fallbackHosts:["127.0.0.1"];if(n.host||n.scheme){let u=e?Bt(e):null,c=n.scheme||u?.protocol?.replace(":","")||"http",h=n.host||u?.hostname||(r?o[0]:"127.0.0.1"),p=r??(u?.port?Number(u.port):null);return[Or(c,h,p,i)]}if(e){let u=Bt(e);if(u)return u.pathname=i,[u.toString()]}let a=[];s&&a.push(s);for(let u of o)a.includes(u)||a.push(u);return a.map(u=>Or("http",u,r,i))}function Bt(n){try{return new URL(n)}catch{return null}}function Or(n,t,e,r){let s=t.includes(":")&&!t.startsWith("[")?`[${t}]`:t,i=e?`:${e}`:"";return`${n}://${s}${i}${r.startsWith("/")?r:"/"+r}`}var Ht=class{constructor(t,e,r){this.registry=t;this.cfg=e;this.fullConfig=r;if(e.enabled){t.on("change",this.onChange);for(let s of t.names())this.evaluate(s)}}registry;cfg;fullConfig;timers=new Map;starting=new Map;freshness=new Map;stopped=!1;stop(){this.stopped=!0,this.registry.off("change",this.onChange);for(let t of this.timers.values())clearInterval(t);for(let t of this.starting.values())clearTimeout(t);this.timers.clear(),this.starting.clear()}onChange=()=>{if(!this.stopped)for(let t of this.registry.names())this.evaluate(t)};evaluate(t){let e=this.registry.getState(t);if(e)if(e.status==="serving"){if(this.timers.has(t)||this.starting.has(t))return;this.freshness.set(t,{retried:!1});let r=setTimeout(()=>{this.starting.delete(t),this.probe(t);let s=setInterval(()=>{this.probe(t)},this.cfg.intervalMs);this.timers.set(t,s)},Cs);this.starting.set(t,r)}else{let r=this.timers.get(t);r&&(clearInterval(r),this.timers.delete(t));let s=this.starting.get(t);s&&(clearTimeout(s),this.starting.delete(t)),this.freshness.delete(t),e.health!=="unknown"&&(e.status==="stopped"||e.status==="error")&&this.registry.setHealth(t,"unknown")}}async probe(t){let e=this.registry.getState(t);if(!e||e.status!=="serving")return;let r=this.fullConfig?.overrides?.[t]?.url,s=Rs(this.cfg,r,e.announcedUrl,e.port,e.cachedProbeHost);if(s.length===0){this.registry.setLastHealthError(t,"no probe URL available"),this.registry.setHealth(t,"unhealthy");return}let i=null;for(let a of s){let u=await this.tryProbe(a);if(u.ok){let c=Bt(a);c&&this.registry.setCachedProbeHost(t,c.hostname.replace(/^\[|\]$/g,"")),this.registry.setResolvedUrl(t,a),this.registry.setLastHealthError(t,null),this.registry.setHealth(t,"healthy");return}i||(i=`${u.error} ${a}`)}let o=this.freshness.get(t);if(o&&!o.retried){o.retried=!0,setTimeout(()=>{this.probe(t)},As);return}this.registry.setLastHealthError(t,i||"unknown probe failure"),this.registry.setHealth(t,"unhealthy")}tryProbe(t){return new Promise(e=>{let r=!1,s=u=>{r||(r=!0,e(u))},i=t.startsWith("https://"),o=i?Ts:Es,a={timeout:this.cfg.timeoutMs};if(i){let c=Bt(t)?.hostname?.replace(/^\[|\]$/g,"")??"",h=c==="127.0.0.1"||c==="::1"||c==="localhost";a.rejectUnauthorized=h?!1:!!this.cfg.rejectUnauthorized}try{let u=o.get(t,a,c=>{let h=c.statusCode??0;c.resume(),h>=200&&h<500?s({ok:!0}):s({ok:!1,error:`http ${h}`})});u.on("timeout",()=>u.destroy(new Error("timeout"))),u.on("error",c=>s({ok:!1,error:c?.code||c?.message||"error"}))}catch(u){s({ok:!1,error:u?.message||"throw"})}})}};import Ps from"pidusage";var Ut=class{constructor(t,e=2e3){this.registry=t;this.intervalMs=e;this.timer=setInterval(()=>this.tick(),e)}registry;intervalMs;timer=null;stopped=!1;stop(){this.stopped=!0,this.timer&&(clearInterval(this.timer),this.timer=null)}async tick(){if(this.stopped)return;let t=[];for(let r of this.registry.names()){let s=this.registry.getState(r);s?.pid&&t.push({name:r,pid:s.pid})}if(!t.length)return;let e=!1;await Promise.all(t.map(async({name:r,pid:s})=>{try{let i=await Ps(s),o=this.registry.getState(r);if(!o)return;let a=Math.round(i.cpu*10)/10,u=Math.round(i.memory/(1024*1024));(o.cpu!==a||o.memMB!==u)&&(o.cpu=a,o.memMB=u,e=!0)}catch{let i=this.registry.getState(r);i&&(i.cpu!=null||i.memMB!=null)&&(i.cpu=null,i.memMB=null,e=!0)}})),e&&this.registry.emit("change")}};var Wt=class{constructor(t,e){this.registry=t;this.cfg=e}registry;cfg;timers=new Map;stopped=!1;stop(){this.stopped=!0;for(let t of this.timers.values())clearTimeout(t);this.timers.clear()}onExit(t,e,r,s){if(this.stopped||s||!this.cfg.enabled||e===0&&!r)return;let i=this.registry.getState(t);if(!i)return;let o=Date.now();if((i.restartWindowStart==null||o-i.restartWindowStart>this.cfg.windowMs)&&(i.restartWindowStart=o,i.restartAttempts=0),i.restartAttempts+=1,i.restartAttempts>this.cfg.maxAttempts){i.lastStatusMessage=`auto-restart aborted (${i.restartAttempts-1}/${this.cfg.maxAttempts} within window)`,i.nextRestartAt=null,this.registry.recordEvent({app:t,type:"restart-scheduled",message:i.lastStatusMessage}),this.registry.emit("change");return}let a=Math.min(2**(i.restartAttempts-1)*1e3,3e4);i.nextRestartAt=o+a,i.lastStatusMessage=`restarting in ${Math.round(a/1e3)}s (attempt ${i.restartAttempts}/${this.cfg.maxAttempts})`,this.registry.recordEvent({app:t,type:"restart-scheduled",message:i.lastStatusMessage}),this.registry.emit("change");let u=setTimeout(()=>{this.timers.delete(t);let c=this.registry.getState(t);c&&(c.nextRestartAt=null),this.registry.start(t)},a);this.timers.set(t,u)}onUserStop(t){let e=this.timers.get(t);e&&(clearTimeout(e),this.timers.delete(t));let r=this.registry.getState(t);r&&(r.restartAttempts=0,r.restartWindowStart=null,r.nextRestartAt=null)}};import Se from"node:fs";import jr from"node:path";import Os from"node:os";var ke=jr.join(Os.homedir(),".daimon","state.json");function $r(){try{let n=Se.readFileSync(ke,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.ports&&typeof t.ports=="object")return{ports:t.ports}}catch{}return{ports:{}}}var we=null,be=null;function Nr(n){be=n,!we&&(we=setTimeout(()=>{we=null;let t=be;if(be=null,!!t)try{Se.mkdirSync(jr.dirname(ke),{recursive:!0}),Se.writeFileSync(ke,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: state write failed: ${e.message}
|
|
56
|
-
`)}}
|
|
57
|
-
|
|
58
|
-
`))}stop(){this.registry.off("event",this.onEvent)}onEvent=t=>{this.notifier&&(t.type==="status"&&t.to==="error"&&this.cfg.onError?this.fire(t.app,"error",`${t.app} \u2192 error`,t.message||"app entered error state"):t.type==="health"&&t.to==="unhealthy"&&this.cfg.onUnhealthy?this.fire(t.app,"unhealthy",`${t.app} unhealthy`,"health probe failing"):t.type==="stale"?this.fire(t.app,"stale",`${t.app} stale`,t.message||"no output despite source changes"):t.type==="compile-regression"?this.fire(t.app,"compile-regression",`${t.app} slow compile`,t.message||"compile time regression"):t.type==="bundle-regression"?this.fire(t.app,"bundle-regression",`${t.app} bundle grew`,t.message||"bundle size regression"):t.type==="task-run"&&/exit=[1-9]/.test(t.message||"")&&this.fire(t.app,"task-fail",`${t.app} task failed`,t.message||""))};fire(t,e,r,s){if(!this.notifier)return;let i=`${t}::${e}`,o=this.lastSent.get(i)??0,a=Date.now();if(a-o<Ms){this.audit("throttled",`${i}`);return}this.lastSent.set(i,a);let u={title:`daimon: ${r}`,message:s,wait:!1,appID:"daimon"},c=(h,p)=>{h?(this.audit("fail",`${i} :: ${h?.message||h}`),this.warnOnce(`notify failed: ${h?.message||h}`)):this.audit("ok",`${i} :: ${r} :: ${p??"(no response)"}`)};try{this.audit("attempt",`${i} :: ${r}`),(this.toaster??this.notifier).notify(u,c)}catch(h){this.audit("throw",`${i} :: ${h?.message||h}`),this.warnOnce(`notify threw: ${h?.message||h}`)}}};import Lr from"node:fs";import xe from"node:path";var _s=5e3,Ls=3e4,Ds=new Set(["node_modules","dist",".angular",".nx",".git","tmp","out-tsc","coverage"]),Fs=new Set([".ts",".tsx",".html",".scss",".css",".js",".jsx",".json"]),Gt=class{constructor(t,e){this.registry=t;this.cfg=e;e.enabled&&(this.timer=setInterval(()=>this.tick(),_s),t.on("compile",this.onCompile))}registry;cfg;timer=null;caches=new Map;stop(){this.timer&&clearInterval(this.timer),this.registry.off("compile",this.onCompile)}onCompile=t=>{let e=this.registry.getApp(t.name);e&&this.caches.delete(e.workspaceRoot)};tick(){for(let t of this.registry.names())this.evaluate(t)}evaluate(t){let e=this.registry.getState(t),r=this.registry.getApp(t);if(!e||!r)return;if(e.status!=="serving"){e.stale&&this.registry.setStale(t,!1);return}if(e.startedAt==null)return;let s=e.lastLogTs??e.startedAt,i=Date.now()-s;if(i<this.cfg.silentMs){e.stale&&this.registry.setStale(t,!1);return}let o=e.lastCompileAt??e.startedAt;this.hasSourceChange(r.workspaceRoot,o,e.lastCompileAt)&&(e.stale||(this.registry.setStale(t,!0),this.registry.recordEvent({app:t,type:"stale",message:`no output in ${Math.round(i/1e3)}s despite source changes`})))}hasSourceChange(t,e,r){let s=this.caches.get(t);if(!s||Date.now()-s.ts>Ls||r!=null&&s.ts<r){let a=this.scan(t);this.caches.set(t,{ts:Date.now(),files:a})}return this.caches.get(t).files.some(a=>a.mtime>e)}scan(t){let e=[],r=(s,i)=>{if(i>8||e.length>4e3)return;let o;try{o=Lr.readdirSync(s,{withFileTypes:!0})}catch{return}for(let a of o)if(!a.name.startsWith(".git")){if(a.isDirectory()){if(Ds.has(a.name))continue;r(xe.join(s,a.name),i+1)}else if(a.isFile()){let u=xe.extname(a.name);if(!Fs.has(u))continue;try{let c=xe.join(s,a.name),h=Lr.statSync(c);e.push({path:c,mtime:h.mtimeMs})}catch{}}}};return r(t,0),e}};import Dr from"node:http";var qt=200,Xt=class{constructor(t,e){this.registry=t;this.cfg=e;e.enabled&&(t.on("change",this.onChange),this.tick())}registry;cfg;proxies=new Map;stopped=!1;stop(){this.stopped=!0,this.registry.off("change",this.onChange);for(let t of this.proxies.values())try{t.server.close()}catch{}this.proxies.clear()}onChange=()=>{this.stopped||this.tick()};tick(){for(let t of this.registry.names()){let e=this.registry.getState(t);if(!e)continue;let r=this.proxies.has(t);e.status==="serving"&&e.port&&!r?this.startProxy(t,e.port):e.status!=="serving"&&r&&this.stopProxy(t)}}stopProxy(t){let e=this.proxies.get(t);if(e){try{e.server.close()}catch{}this.proxies.delete(t)}}startProxy(t,e){let r=e+this.cfg.portOffset,s=[],i=Dr.createServer((o,a)=>{let u=Date.now(),c={hostname:"127.0.0.1",port:e,method:o.method,path:o.url,headers:{...o.headers,host:`127.0.0.1:${e}`}},h=Dr.request(c,p=>{a.writeHead(p.statusCode||502,p.headers),p.pipe(a);let b=()=>{s.push({ts:Date.now(),method:o.method||"GET",path:o.url||"/",status:p.statusCode||0,durationMs:Date.now()-u}),s.length>qt&&s.splice(0,s.length-qt)};p.on("end",b),p.on("error",b)});h.on("error",()=>{a.writeHead(502).end("upstream error"),s.push({ts:Date.now(),method:o.method||"GET",path:o.url||"/",status:502,durationMs:Date.now()-u}),s.length>qt&&s.splice(0,s.length-qt)}),o.pipe(h)});i.on("error",o=>{o?.code==="EADDRINUSE"&&process.stderr.write(`[daimon] requestLog: port ${r} in use for ${t}; disabling proxy
|
|
59
|
-
`)
|
|
60
|
-
|
|
61
|
-
`))}catch{}return s}
|
|
56
|
+
`),3e4);o.on("close",()=>{n.off("log",g),clearInterval(R)});return}if(x==="logs"&&u==="GET"){let c=a.searchParams.get("tail"),f=a.searchParams.get("since"),m=n.logs(p,{tail:c?Number(c):void 0,sinceMs:ft(f)});if(m==null){b(i,404,{error:"unknown app"});return}b(i,200,{lines:m});return}if(x==="focus"&&u==="POST"){let c=n.summary(p);if(!c){b(i,404,{error:"unknown app"});return}let f=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy","stable"].includes(f)){b(i,400,{error:"until must be one of serving|healthy|stable"});return}let m=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),d=m?Number(m):18e4;(!Number.isFinite(d)||d<=0)&&(d=18e4),d=Math.min(d,6e5);let g=a.searchParams.get("stableMs"),R=g&&Number.isFinite(Number(g))?Math.max(1e3,Number(g)):5e3;i.writeHead(200,{"content-type":"application/x-ndjson; charset=utf-8","cache-control":"no-cache",connection:"keep-alive"});let T=w=>{try{i.write(JSON.stringify(w)+`
|
|
57
|
+
`)}catch{}};T({kind:"subscribed",app:p,until:f,ts:Date.now(),state:dt(c)});let v=Date.now(),j=Date.now(),M=!1,E=w=>{if(M)return;M=!0,n.off("event",P),clearInterval(k),clearInterval(N),clearTimeout(D);let $=n.summary(p);T({kind:"done",reason:w,ts:Date.now(),state:$?dt($):null,waitedMs:Date.now()-v});try{i.end()}catch{}},y=()=>{let w=n.summary(p);if(!w)return!1;if(f==="serving")return w.status==="serving";if(f==="healthy")return w.status==="serving"&&w.health==="healthy";if(f==="stable"){let $=Date.now()-j;return w.status==="serving"&&w.health==="healthy"&&$>=R}return!1},P=w=>{if(w.app===p)if(j=Date.now(),w.type==="status")T({kind:"status",from:w.from,to:w.to,ts:w.ts}),f!=="stable"&&y()&&E("reached");else if(w.type==="error-new"||w.type==="error-recur"){let C=(n.errors(p)??[])[0];C&&T({kind:"error",message:C.message,parsed:C.parsed??null,ts:w.ts})}else w.type==="health"&&(T({kind:"health",from:w.from,to:w.to,ts:w.ts}),f!=="stable"&&y()&&E("reached"))};n.on("event",P);let k=setInterval(()=>{y()&&E("reached")},1e3),N=setInterval(()=>{try{i.write(`
|
|
58
|
+
`)}catch{}},3e4),D=setTimeout(()=>E("timeout"),d);o.on("close",()=>E("closed")),y()&&E("reached");return}if(x==="health"&&S==="pin"&&u==="POST"){let c=n.getState(p);if(!c){b(i,404,{error:"unknown app"});return}let f={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(M=>{let E=[];o.on("data",y=>E.push(y)),o.on("end",()=>{try{f=JSON.parse(Buffer.concat(E).toString("utf8"))}catch{}M()})});let m=typeof f.path=="string"&&f.path?f.path:c.discoveredHealthPath??null;if(!m){b(i,400,{error:"no path supplied and no discoveredHealthPath on app"});return}let{configLookupPaths:d}=await Promise.resolve().then(()=>(yt(),Fe)),{local:g,user:R}=d(),T=nt.existsSync(g)?g:R,v={};try{v=JSON.parse(nt.readFileSync(T,"utf8"))}catch{}(!v.overrides||typeof v.overrides!="object")&&(v.overrides={}),(!v.overrides[p]||typeof v.overrides[p]!="object")&&(v.overrides[p]={});let j=v.overrides[p].healthProbePath??null;if(v.overrides[p].healthProbePath=m,nt.writeFileSync(T,JSON.stringify(v,null,2)+`
|
|
59
|
+
`,"utf8"),e.reloadConfig)try{await e.reloadConfig()}catch{}b(i,200,{pinned:m,app:p,configPath:T,previous:j});return}if(x==="try-fix"&&u==="POST"){let c=n.summary(p);if(!c){b(i,404,{error:"unknown app"});return}let f=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(f)){b(i,400,{error:"until must be serving|healthy"});return}let m=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),d=m?Number(m):18e4;(!Number.isFinite(d)||d<=0)&&(d=18e4),d=Math.min(d,6e5);let g={status:c.status,health:c.health,errCount:c.errorCount,firstError:(n.errors(p)??[])[0]?.parsed??null},{runAutoFix:R,ALL_AUTO_FIX:T}=await Promise.resolve().then(()=>(we(),ve)),j=e.getConfig?.()?.doctor?.autoFix?.permitted??T,M={ran:[],skipped:[],errors:[]};try{M=await R({permitted:j,dryRun:!1})}catch(C){M.errors.push({name:"auto-fix",error:C?.message??String(C)})}let E=(M.ran??[]).map(C=>C.name),y=null;try{let C=await n.restart(p);C?.ok||(y=C?.error??"restart failed")}catch(C){y=C?.message??String(C)}let P=await n.waitFor(p,f,d),k=n.summary(p),D=(n.errors(p)??[]).slice(0,5).map(C=>({file:C.parsed?.file??null,line:C.parsed?.line??null,code:C.parsed?.code??null,tool:C.parsed?.tool??null,message:C.parsed?.message??C.message})),w=k?{status:k.status,health:k.health,errCount:k.errorCount}:{status:P.status,health:P.health,errCount:0},$=f==="serving"&&w.status==="serving"||f==="healthy"&&w.status==="serving"&&w.health==="healthy";b(i,200,{before:g,after:w,fixed:E,stillFailing:D,reached:$,waitedMs:P.waitedMs,_meta:{autoFix:M,restartErr:y,timedOut:P.timedOut}});return}if(x==="wait"&&u==="GET"){if(!n.summary(p)){b(i,404,{error:"unknown app"});return}let c=(a.searchParams.get("until")||"serving").toLowerCase();if(!["serving","healthy","stopped","error"].includes(c)){b(i,400,{error:"until must be one of serving|healthy|stopped|error"});return}let f=a.searchParams.get("timeout"),m=f?Number(f):120;(!Number.isFinite(m)||m<=0)&&(m=120),m=Math.min(m,600);let d=await n.waitFor(p,c,m*1e3);b(i,200,d);return}if(x==="ensure"&&u==="POST"){let c=n.summary(p);if(!c){b(i,404,{error:"unknown app"});return}let f=(a.searchParams.get("until")||"healthy").toLowerCase();if(!["serving","healthy"].includes(f)){b(i,400,{error:"until must be serving|healthy"});return}let m=a.searchParams.get("timeoutMs")||a.searchParams.get("timeout"),d=m?Number(m):18e4;(!Number.isFinite(d)||d<=0)&&(d=18e4),d=Math.min(d,6e5);let g=e.getConfig?.().healthProbe?.enabled??!0,R=f,T;if(R==="healthy"&&!g&&(R="serving",T="no health probe; treated serving as terminal"),R==="serving"&&c.status==="serving"||R==="healthy"&&c.status==="serving"&&c.health==="healthy"){b(i,200,{...dt(c),_meta:{format:"compact",startedFromState:null,warning:T,waitedMs:0}});return}let j=c.status;c.status!=="starting"&&c.status!=="compiling"&&await n.start(p);let M=await n.waitFor(p,R,d),E=n.summary(p),y=E?dt(E):{name:p,status:M.status,port:null,url:null,health:M.health,errCount:0,lastChangeMs:null,uptime:null};if(M.timedOut){b(i,200,{error:"timeout",state:y,_meta:{format:"compact",startedFromState:j,warning:T,waitedMs:M.waitedMs,timedOut:!0}});return}b(i,200,{...y,_meta:{format:"compact",startedFromState:j,warning:T,waitedMs:M.waitedMs}});return}if(x==="start"&&u==="POST"){if(a.searchParams.get("withDeps")==="1"){let m=await n.startWithDeps(p);b(i,m.ok?200:400,m);return}let f=await n.start(p);b(i,f.ok?200:400,f);return}if(x==="start-with-deps"&&u==="POST"){let c=await n.startWithDeps(p);b(i,c.ok?200:400,c);return}if(x==="tasks"&&u==="GET"&&!S){let c=n.listTasks(p);if(c==null){b(i,404,{error:"unknown app"});return}b(i,200,{tasks:c,watching:n.listWatchTasks(p)});return}if(x==="run"&&S&&u==="POST"){let c={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(d=>{let g=[];o.on("data",R=>g.push(R)),o.on("end",()=>{try{c=JSON.parse(Buffer.concat(g).toString("utf8"))}catch{}d()})});let f=Array.isArray(c.args)?c.args.map(String):[];if(c.watch){let d=n.startWatchTask(p,S,f);b(i,d.ok?200:400,d);return}let m=await n.runTask(p,S,f);if("error"in m){b(i,404,m);return}b(i,200,m);return}if(x==="run-stop"&&S&&u==="POST"){let c=await n.stopWatchTask(p,S);b(i,200,c);return}if(x==="env"&&u==="GET"){let f=n.getConfig().envFiles?.[p]??[],m=n.getState(p);b(i,200,{candidates:f,active:m?.activeEnvFile??null});return}if(x==="env"&&u==="POST"){let c={};o.headers["content-length"]&&o.headers["content-length"]!=="0"&&await new Promise(m=>{let d=[];o.on("data",g=>d.push(g)),o.on("end",()=>{try{c=JSON.parse(Buffer.concat(d).toString("utf8"))}catch{}m()})}),n.setActiveEnvFile(p,c.use??null);let f=n.getState(p);b(i,200,{active:f?.activeEnvFile??null});return}if(x==="requests"&&u==="GET"){if(!e.requestLog){b(i,200,[]);return}let c=ft(a.searchParams.get("since"));b(i,200,e.requestLog.requests(p,c));return}if(x==="clean"&&u==="POST"){let c=a.searchParams.get("deep")==="1",f=a.searchParams.get("yes")==="1",m=ge(n,p,c);if(!m){b(i,404,{error:"unknown app"});return}if(m.ranOnServing){b(i,409,{error:"refusing: app is currently running",plan:m});return}if(!f){b(i,200,{plan:m,hint:"pass --yes to delete"});return}let d=Sr(n,p,c);b(i,200,d);return}if(x==="snapshot"&&u==="POST"){if(a.searchParams.get("write")==="1"){let m=vr(n,p);if(!m){b(i,404,{error:"unknown app"});return}b(i,200,{snapshot:m.path});return}let f=he(n,p);if(!f){b(i,404,{error:"unknown app"});return}b(i,200,f);return}if(x==="stop"&&u==="POST"){let c=await n.stop(p);b(i,c.ok?200:400,c);return}if(x==="restart"&&u==="POST"){let c=await n.restart(p);b(i,c.ok?200:400,c);return}if(u==="GET"&&!a.pathname.startsWith("/api/")&&!a.pathname.startsWith("/metrics")){let c=be();if(c){let f=a.pathname.replace(/^\/dashboard\//,"/").replace(/^\//,"");if(f){let m=B.resolve(c,f);if(m.startsWith(c)&&Et(i,m))return}if(!B.extname(f||"")&&Et(i,B.join(c,"index.html")))return}}b(i,404,{error:"not found"})}catch(a){b(i,500,{error:a?.message||String(a)})}});return s.listen(t,"127.0.0.1"),s}import Us from"node:http";import Js from"node:https";var Ws=1e3,Gs=500,qs=["/","/health","/-/health","/api/health","/ready","/healthz"];function _r(n,t,e,r,s){if(t)return[t];let o=n.path||"/",i=n.fallbackHosts&&n.fallbackHosts.length?n.fallbackHosts:["127.0.0.1"];if(n.host||n.scheme){let u=e?Ut(e):null,l=n.scheme||u?.protocol?.replace(":","")||"http",h=n.host||u?.hostname||(r?i[0]:"127.0.0.1"),p=r??(u?.port?Number(u.port):null);return[Lr(l,h,p,o)]}if(e){let u=Ut(e);if(u)return u.pathname=o,[u.toString()]}let a=[];s&&a.push(s);for(let u of i)a.includes(u)||a.push(u);return a.map(u=>Lr("http",u,r,o))}function Ut(n){try{return new URL(n)}catch{return null}}function Lr(n,t,e,r){let s=t.includes(":")&&!t.startsWith("[")?`[${t}]`:t,o=e?`:${e}`:"";return`${n}://${s}${o}${r.startsWith("/")?r:"/"+r}`}var Jt=class{constructor(t,e,r){this.registry=t;this.cfg=e;this.fullConfig=r;if(e.enabled){t.on("change",this.onChange);for(let s of t.names())this.evaluate(s)}}registry;cfg;fullConfig;timers=new Map;starting=new Map;freshness=new Map;stopped=!1;stop(){this.stopped=!0,this.registry.off("change",this.onChange);for(let t of this.timers.values())clearInterval(t);for(let t of this.starting.values())clearTimeout(t);this.timers.clear(),this.starting.clear()}onChange=()=>{if(!this.stopped)for(let t of this.registry.names())this.evaluate(t)};evaluate(t){let e=this.registry.getState(t);if(e)if(e.status==="serving"){if(this.timers.has(t)||this.starting.has(t))return;this.freshness.set(t,{retried:!1});let r=setTimeout(()=>{this.starting.delete(t),this.probe(t);let s=setInterval(()=>{this.probe(t)},this.cfg.intervalMs);this.timers.set(t,s)},Gs);this.starting.set(t,r)}else{let r=this.timers.get(t);r&&(clearInterval(r),this.timers.delete(t));let s=this.starting.get(t);s&&(clearTimeout(s),this.starting.delete(t)),this.freshness.delete(t),e.health!=="unknown"&&(e.status==="stopped"||e.status==="error")&&this.registry.setHealth(t,"unknown")}}async probe(t){let e=this.registry.getState(t);if(!e||e.status!=="serving")return;let r=this.fullConfig?.overrides?.[t]?.url,s=this.fullConfig?.overrides?.[t]?.healthProbePath,o=this.cfg;s?o={...this.cfg,path:s}:e.discoveredHealthPath&&(o={...this.cfg,path:e.discoveredHealthPath});let i=_r(o,r,e.announcedUrl,e.port,e.cachedProbeHost);if(!r&&!s&&!e.discoveredHealthPath&&(this.cfg.path==="/"||!this.cfg.path)&&e.health!=="healthy"&&this.discoverPath(t),i.length===0){this.registry.setLastHealthError(t,"no probe URL available"),this.registry.setHealth(t,"unhealthy");return}let a=null;for(let l of i){let h=await this.tryProbe(l);if(h.ok){let p=Ut(l);p&&this.registry.setCachedProbeHost(t,p.hostname.replace(/^\[|\]$/g,"")),this.registry.setResolvedUrl(t,l),this.registry.setLastHealthError(t,null),this.registry.setHealth(t,"healthy");return}a||(a=`${h.error} ${l}`)}let u=this.freshness.get(t);if(u&&!u.retried){u.retried=!0,setTimeout(()=>{this.probe(t)},Ws);return}this.registry.setLastHealthError(t,a||"unknown probe failure"),this.registry.setHealth(t,"unhealthy")}async discoverPath(t){let e=this.registry.getState(t);if(!(!e||e.status!=="serving")&&!e.discoveredHealthPath)for(let r of qs){let s={...this.cfg,path:r},o=_r(s,void 0,e.announcedUrl,e.port,e.cachedProbeHost);for(let i of o)if((await this.tryProbe(i,{strict2xx:!0})).ok){e.discoveredHealthPath=r,this.registry.recordEvent({app:t,type:"health",message:`discovered probe path: ${r} (pin via POST /api/apps/${encodeURIComponent(t)}/health/pin or daimon pin-health ${t} --accept)`});return}}}tryProbe(t,e={}){return new Promise(r=>{let s=!1,o=h=>{s||(s=!0,r(h))},i=t.startsWith("https://"),a=i?Js:Us,u={timeout:this.cfg.timeoutMs};if(i){let p=Ut(t)?.hostname?.replace(/^\[|\]$/g,"")??"",x=p==="127.0.0.1"||p==="::1"||p==="localhost";u.rejectUnauthorized=x?!1:!!this.cfg.rejectUnauthorized}let l=e.strict2xx?300:500;try{let h=a.get(t,u,p=>{let x=p.statusCode??0;p.resume(),x>=200&&x<l?o({ok:!0}):o({ok:!1,error:`http ${x}`})});h.on("timeout",()=>h.destroy(new Error("timeout"))),h.on("error",p=>o({ok:!1,error:p?.code||p?.message||"error"}))}catch(h){o({ok:!1,error:h?.message||"throw"})}})}};import Xs from"pidusage";var Wt=class{constructor(t,e=2e3){this.registry=t;this.intervalMs=e;this.timer=setInterval(()=>this.tick(),e)}registry;intervalMs;timer=null;stopped=!1;stop(){this.stopped=!0,this.timer&&(clearInterval(this.timer),this.timer=null)}async tick(){if(this.stopped)return;let t=[];for(let r of this.registry.names()){let s=this.registry.getState(r);s?.pid&&t.push({name:r,pid:s.pid})}if(!t.length)return;let e=!1;await Promise.all(t.map(async({name:r,pid:s})=>{try{let o=await Xs(s),i=this.registry.getState(r);if(!i)return;let a=Math.round(o.cpu*10)/10,u=Math.round(o.memory/(1024*1024));(i.cpu!==a||i.memMB!==u)&&(i.cpu=a,i.memMB=u,e=!0)}catch{let o=this.registry.getState(r);o&&(o.cpu!=null||o.memMB!=null)&&(o.cpu=null,o.memMB=null,e=!0)}})),e&&this.registry.emit("change")}};var Gt=class{constructor(t,e){this.registry=t;this.cfg=e}registry;cfg;timers=new Map;stopped=!1;stop(){this.stopped=!0;for(let t of this.timers.values())clearTimeout(t);this.timers.clear()}onExit(t,e,r,s){if(this.stopped||s||!this.cfg.enabled||e===0&&!r)return;let o=this.registry.getState(t);if(!o)return;let i=Date.now();if((o.restartWindowStart==null||i-o.restartWindowStart>this.cfg.windowMs)&&(o.restartWindowStart=i,o.restartAttempts=0),o.restartAttempts+=1,o.restartAttempts>this.cfg.maxAttempts){o.lastStatusMessage=`auto-restart aborted (${o.restartAttempts-1}/${this.cfg.maxAttempts} within window)`,o.nextRestartAt=null,this.registry.recordEvent({app:t,type:"restart-scheduled",message:o.lastStatusMessage}),this.registry.emit("change");return}let a=Math.min(2**(o.restartAttempts-1)*1e3,3e4);o.nextRestartAt=i+a,o.lastStatusMessage=`restarting in ${Math.round(a/1e3)}s (attempt ${o.restartAttempts}/${this.cfg.maxAttempts})`,this.registry.recordEvent({app:t,type:"restart-scheduled",message:o.lastStatusMessage}),this.registry.emit("change");let u=setTimeout(()=>{this.timers.delete(t);let l=this.registry.getState(t);l&&(l.nextRestartAt=null),this.registry.start(t)},a);this.timers.set(t,u)}onUserStop(t){let e=this.timers.get(t);e&&(clearTimeout(e),this.timers.delete(t));let r=this.registry.getState(t);r&&(r.restartAttempts=0,r.restartWindowStart=null,r.nextRestartAt=null)}};import Te from"node:fs";import Dr from"node:path";import Ks from"node:os";var Re=Dr.join(Ks.homedir(),".daimon","state.json");function Fr(){try{let n=Te.readFileSync(Re,"utf8"),t=JSON.parse(n);if(t&&typeof t=="object"&&t.ports&&typeof t.ports=="object")return{ports:t.ports}}catch{}return{ports:{}}}var xe=null,Ee=null;function Ir(n){Ee=n,!xe&&(xe=setTimeout(()=>{xe=null;let t=Ee;if(Ee=null,!!t)try{Te.mkdirSync(Dr.dirname(Re),{recursive:!0}),Te.writeFileSync(Re,JSON.stringify(t),"utf8")}catch(e){process.stderr.write(`[daimon] warning: state write failed: ${e.message}
|
|
60
|
+
`)}},500))}ye();import Hr from"node:fs";import Ys from"node:os";import Br from"node:path";import{createRequire as zs}from"node:module";var Vs=zs(import.meta.url),Zs=6e4,qt=class{constructor(t,e){this.registry=t;this.cfg=e;this.logFile=Br.join(Ys.homedir(),".daimon","notifications.log");try{Hr.mkdirSync(Br.dirname(this.logFile),{recursive:!0})}catch{}if(!e.enabled){this.audit("init","disabled by config");return}try{let r=Vs("node-notifier");if(this.notifier=r,process.platform==="win32")try{let s=r.WindowsToaster;s&&(this.toaster=new s({withFallback:!0}))}catch(s){this.audit("init",`WindowsToaster unavailable: ${s?.message||s}`)}this.audit("init",`node-notifier loaded${this.toaster?" (+WindowsToaster fallback)":""}`)}catch(r){this.warnOnce(`node-notifier unavailable: ${r?.message||r}`),this.audit("init",`node-notifier load failed: ${r?.message||r}`);return}t.on("event",this.onEvent)}registry;cfg;notifier=null;toaster=null;lastSent=new Map;warned=!1;logFile;audit(t,e){let r=`${new Date().toISOString()} ${t} ${e}
|
|
61
|
+
`;try{Hr.appendFileSync(this.logFile,r)}catch{}}warnOnce(t){this.warned||(this.warned=!0,process.stderr.write(`[daimon] notifier: ${t}
|
|
62
|
+
`))}stop(){this.registry.off("event",this.onEvent)}onEvent=t=>{this.notifier&&(t.type==="status"&&t.to==="error"&&this.cfg.onError?this.fire(t.app,"error",`${t.app} \u2192 error`,t.message||"app entered error state"):t.type==="health"&&t.to==="unhealthy"&&this.cfg.onUnhealthy?this.fire(t.app,"unhealthy",`${t.app} unhealthy`,"health probe failing"):t.type==="stale"?this.fire(t.app,"stale",`${t.app} stale`,t.message||"no output despite source changes"):t.type==="compile-regression"?this.fire(t.app,"compile-regression",`${t.app} slow compile`,t.message||"compile time regression"):t.type==="bundle-regression"?this.fire(t.app,"bundle-regression",`${t.app} bundle grew`,t.message||"bundle size regression"):t.type==="task-run"&&/exit=[1-9]/.test(t.message||"")&&this.fire(t.app,"task-fail",`${t.app} task failed`,t.message||""))};fire(t,e,r,s){if(!this.notifier)return;let o=`${t}::${e}`,i=this.lastSent.get(o)??0,a=Date.now();if(a-i<Zs){this.audit("throttled",`${o}`);return}this.lastSent.set(o,a);let u={title:`daimon: ${r}`,message:s,wait:!1,appID:"daimon"},l=(h,p)=>{h?(this.audit("fail",`${o} :: ${h?.message||h}`),this.warnOnce(`notify failed: ${h?.message||h}`)):this.audit("ok",`${o} :: ${r} :: ${p??"(no response)"}`)};try{this.audit("attempt",`${o} :: ${r}`),(this.toaster??this.notifier).notify(u,l)}catch(h){this.audit("throw",`${o} :: ${h?.message||h}`),this.warnOnce(`notify threw: ${h?.message||h}`)}}};import Ur from"node:fs";import Ae from"node:path";var Qs=5e3,to=3e4,eo=new Set(["node_modules","dist",".angular",".nx",".git","tmp","out-tsc","coverage"]),ro=new Set([".ts",".tsx",".html",".scss",".css",".js",".jsx",".json"]),Xt=class{constructor(t,e){this.registry=t;this.cfg=e;e.enabled&&(this.timer=setInterval(()=>this.tick(),Qs),t.on("compile",this.onCompile))}registry;cfg;timer=null;caches=new Map;stop(){this.timer&&clearInterval(this.timer),this.registry.off("compile",this.onCompile)}onCompile=t=>{let e=this.registry.getApp(t.name);e&&this.caches.delete(e.workspaceRoot)};tick(){for(let t of this.registry.names())this.evaluate(t)}evaluate(t){let e=this.registry.getState(t),r=this.registry.getApp(t);if(!e||!r)return;if(e.status!=="serving"){e.stale&&this.registry.setStale(t,!1);return}if(e.startedAt==null)return;let s=e.lastLogTs??e.startedAt,o=Date.now()-s;if(o<this.cfg.silentMs){e.stale&&this.registry.setStale(t,!1);return}let i=e.lastCompileAt??e.startedAt;this.hasSourceChange(r.workspaceRoot,i,e.lastCompileAt)&&(e.stale||(this.registry.setStale(t,!0),this.registry.recordEvent({app:t,type:"stale",message:`no output in ${Math.round(o/1e3)}s despite source changes`})))}hasSourceChange(t,e,r){let s=this.caches.get(t);if(!s||Date.now()-s.ts>to||r!=null&&s.ts<r){let a=this.scan(t);this.caches.set(t,{ts:Date.now(),files:a})}return this.caches.get(t).files.some(a=>a.mtime>e)}scan(t){let e=[],r=(s,o)=>{if(o>8||e.length>4e3)return;let i;try{i=Ur.readdirSync(s,{withFileTypes:!0})}catch{return}for(let a of i)if(!a.name.startsWith(".git")){if(a.isDirectory()){if(eo.has(a.name))continue;r(Ae.join(s,a.name),o+1)}else if(a.isFile()){let u=Ae.extname(a.name);if(!ro.has(u))continue;try{let l=Ae.join(s,a.name),h=Ur.statSync(l);e.push({path:l,mtime:h.mtimeMs})}catch{}}}};return r(t,0),e}};import Jr from"node:http";var Kt=200,Yt=class{constructor(t,e){this.registry=t;this.cfg=e;e.enabled&&(t.on("change",this.onChange),this.tick())}registry;cfg;proxies=new Map;stopped=!1;stop(){this.stopped=!0,this.registry.off("change",this.onChange);for(let t of this.proxies.values())try{t.server.close()}catch{}this.proxies.clear()}onChange=()=>{this.stopped||this.tick()};tick(){for(let t of this.registry.names()){let e=this.registry.getState(t);if(!e)continue;let r=this.proxies.has(t);e.status==="serving"&&e.port&&!r?this.startProxy(t,e.port):e.status!=="serving"&&r&&this.stopProxy(t)}}stopProxy(t){let e=this.proxies.get(t);if(e){try{e.server.close()}catch{}this.proxies.delete(t)}}startProxy(t,e){let r=e+this.cfg.portOffset,s=[],o=Jr.createServer((i,a)=>{let u=Date.now(),l={hostname:"127.0.0.1",port:e,method:i.method,path:i.url,headers:{...i.headers,host:`127.0.0.1:${e}`}},h=Jr.request(l,p=>{a.writeHead(p.statusCode||502,p.headers),p.pipe(a);let x=()=>{s.push({ts:Date.now(),method:i.method||"GET",path:i.url||"/",status:p.statusCode||0,durationMs:Date.now()-u}),s.length>Kt&&s.splice(0,s.length-Kt)};p.on("end",x),p.on("error",x)});h.on("error",()=>{a.writeHead(502).end("upstream error"),s.push({ts:Date.now(),method:i.method||"GET",path:i.url||"/",status:502,durationMs:Date.now()-u}),s.length>Kt&&s.splice(0,s.length-Kt)}),i.pipe(h)});o.on("error",i=>{i?.code==="EADDRINUSE"&&process.stderr.write(`[daimon] requestLog: port ${r} in use for ${t}; disabling proxy
|
|
63
|
+
`),this.proxies.delete(t)}),o.listen(r,"127.0.0.1",()=>{this.proxies.set(t,{app:t,proxyPort:r,server:o,buffer:s})})}requests(t,e){let r=this.proxies.get(t);if(!r)return[];if(e){let s=Date.now()-e;return r.buffer.filter(o=>o.ts>=s)}return[...r.buffer]}proxyPortFor(t){return this.proxies.get(t)?.proxyPort??null}};rt();yt();bt();import Ce from"node:fs";var no=new Set(["command","port","env","url"]);function Wr(n){let t=Ce.readFileSync(n,"utf8");t.charCodeAt(0)===65279&&(t=t.slice(1));let e=JSON.parse(t);if(!e||typeof e!="object"||Array.isArray(e))throw new Error("config must be a JSON object");return e}function Gr(n,t){if(t===null)return null;if(typeof t!="object"||Array.isArray(t))return t;let e=n&&typeof n=="object"&&!Array.isArray(n)?{...n}:{};for(let[r,s]of Object.entries(t))s===null?delete e[r]:e[r]=Gr(e[r],s);return e}function so(n,t){let e=n+"."+process.pid+".tmp";Ce.writeFileSync(e,t,"utf8"),Ce.renameSync(e,n)}function oo(n,t){let e=new Set;for(let r of Object.keys(t))JSON.stringify(n?.[r])!==JSON.stringify(t[r])&&e.add(r);for(let r of Object.keys(n||{}))r in t||e.add(r);return[...e]}function qr(n){let t=Wr(n.configPath),e=Gr(t,n.patch);if(!e||typeof e!="object")throw new Error("patch produced non-object config");let r=Rt(e,n.configPath);return so(n.configPath,JSON.stringify(e,null,2)+`
|
|
64
|
+
`),{config:r,raw:e,applied:oo(t,e),prevRaw:t}}function Pe(n){let t=Wr(n.configPath),e=Rt(t,n.configPath);return io(n.registry,e)}function io(n,t){let e=n.getConfig();for(let l of Object.keys(e))e[l]=void 0;Object.assign(e,t);let r=new Set(n.names()),s=wt(e),o=new Set(s.map(l=>l.name)),i=[],a=[];for(let l of s)r.has(l.name)?n.updateDiscoveredApp(l):(n.addDiscoveredApp(l),i.push(l.name));for(let l of r)o.has(l)||a.push(l);let u=[];for(let l of n.names()){let h=n.getState(l);if(h&&(h.status==="serving"||h.status==="compiling")){let p=e.overrides?.[l];if(!p)continue;for(let x of no)if(x in p){u.push(l);break}}}return{addedApps:i,removedApps:a,restartRequired:u,config:e}}Ot();rt();import Xr from"node:fs";import ao from"node:os";import Kr from"node:path";var co=/key|secret|token|password|pass/i;function lo(n){if(!n)return null;let t=JSON.parse(JSON.stringify(n));if(t.apiToken&&(t.apiToken="***"),t.overrides)for(let e of Object.keys(t.overrides)){let r=t.overrides[e]?.env;if(r)for(let s of Object.keys(r))co.test(s)&&(r[s]="***")}return t}function uo(n,t=200){if(!n)return[];let e=[];for(let r of n.names()){let s=n.getState(r);if(s)for(let o of s.logBuffer)e.push({ts:o.ts,line:`[${r}] ${o.line}`})}return e.sort((r,s)=>r.ts-s.ts),e.slice(-t).map(r=>r.line)}function po(){let n=Kr.join(V(),"crashes");return Xr.mkdirSync(n,{recursive:!0}),n}function fo(n,t,e){let r=new Date().toISOString().replace(/[:.]/g,"-"),s=Kr.join(po(),`${r}.txt`),o=n,i=[`daimon crash dump @ ${new Date().toISOString()}`,`version: ${at}`,`node: ${process.version}`,`platform: ${process.platform} ${ao.release()}`,`cwd: ${process.cwd()}`,`pid: ${process.pid}`,"","ERROR:",o?.stack||String(o),"","CONFIG (redacted):",JSON.stringify(lo(e),null,2),"","RECENT LOG (last 200 lines across apps):",...uo(t,200)];try{Xr.writeFileSync(s,i.join(`
|
|
65
|
+
`))}catch{}return s}function Yr(n){let t=e=>{let r=null;try{r=fo(e,n.getRegistry(),n.getConfig())}catch{}try{process.stderr.write(`[daimon] fatal: ${e?.stack||e}
|
|
62
66
|
`)}catch{}if(r)try{process.stderr.write(`[daimon] crash dump: ${r}
|
|
63
|
-
`)}catch{}process.exit(1)};process.on("uncaughtException",t),process.on("unhandledRejection",t)}import
|
|
64
|
-
`);
|
|
65
|
-
`)}),onSubmit:()=>{let
|
|
66
|
-
`),process.exit(1)}if(r.kind==="stub-created"){let
|
|
67
|
+
`)}catch{}process.exit(1)};process.on("uncaughtException",t),process.on("unhandledRejection",t)}import A,{useEffect as wo,useState as X}from"react";import je from"node:fs";import bo from"node:os";import So from"node:path";import{Box as J,Text as O,useApp as ko,useInput as xo,useStdout as Eo}from"ink";import Ne from"ink-text-input";import{spawn as $e,spawnSync as To}from"node:child_process";import F,{useEffect as mo,useMemo as ho,useState as mt}from"react";import{Box as Tt,Text as U,useInput as go,useStdout as yo}from"ink";import vo from"ink-text-input";function Oe({registry:n,appName:t,onExit:e}){let{stdout:r}=yo(),[s,o]=mt(0),[i,a]=mt(!1),[u,l]=mt(""),[h,p]=mt(""),[x,S]=mt(0),[c,f]=mt(0);mo(()=>{let y=()=>o(k=>k+1);n.on("change",y);let P=setInterval(()=>o(k=>k+1),500);return()=>{n.off("change",y),clearInterval(P)}},[n]);let d=n.getState(t)?.logBuffer.map(y=>y.line)??[],g=(r.rows||30)-4,R=ho(()=>{if(!h)return[];let y=h.toLowerCase();return d.reduce((P,k,N)=>(k.toLowerCase().includes(y)&&P.push(N),P),[])},[d,h,s]);go((y,P)=>{if(i){if(P.escape){a(!1),l("");return}return}if(y==="q"||P.escape){e();return}if(y==="/"){a(!0);return}if(y==="g"){S(Math.max(0,d.length-g));return}if(y==="G"){S(0);return}if(P.pageUp){S(k=>Math.min(Math.max(0,d.length-g),k+g));return}if(P.pageDown){S(k=>Math.max(0,k-g));return}if(P.upArrow){S(k=>Math.min(Math.max(0,d.length-g),k+1));return}if(P.downArrow){S(k=>Math.max(0,k-1));return}if((y==="n"||y==="N")&&R.length){let k=y==="n"?(c+1)%R.length:(c-1+R.length)%R.length;f(k);let N=R[k],D=d.length-x,w=D-g;(N<w||N>=D)&&S(Math.max(0,d.length-N-Math.floor(g/2)));return}});let T=y=>{p(y),a(!1),l(""),f(0)},v=d.length-x,j=Math.max(0,v-g),M=d.slice(j,v),E=(y,P)=>{if(!h)return F.createElement(U,{key:P},F.createElement(U,{dimColor:!0},String(P+1).padStart(5)," "),y);let k=h,N=y.toLowerCase(),D=k.toLowerCase(),w=[],$=0,C=0;for(;$<y.length;){let I=N.indexOf(D,$);if(I<0){w.push(F.createElement(U,{key:C++},y.slice($)));break}I>$&&w.push(F.createElement(U,{key:C++},y.slice($,I))),w.push(F.createElement(U,{key:C++,backgroundColor:"yellow",color:"black"},y.slice(I,I+k.length))),$=I+k.length}let _=R[c]===P;return F.createElement(U,{key:P},F.createElement(U,{color:_?"cyan":void 0,dimColor:!_},String(P+1).padStart(5)," "),w)};return F.createElement(Tt,{flexDirection:"column"},F.createElement(Tt,null,F.createElement(U,{bold:!0},"full log: ",F.createElement(U,{color:"cyan"},t)),F.createElement(U,{dimColor:!0}," (",d.length," lines",h?`, ${R.length} matches for "${h}"`:"",", scroll=",x,")")),F.createElement(Tt,{flexDirection:"column"},M.length===0?F.createElement(U,{dimColor:!0},"(no log yet)"):M.map((y,P)=>E(y,j+P))),F.createElement(Tt,null,i?F.createElement(Tt,null,F.createElement(U,null,"/"),F.createElement(vo,{value:u,onChange:l,onSubmit:T})):F.createElement(U,{dimColor:!0},"[/] search [n/N] next/prev [g/G] bottom/top [PgUp/PgDn] [\u2191\u2193] [q/Esc] back")))}function Ro(n){try{process.platform==="win32"?$e("cmd",["/c","start","",n],{detached:!0,stdio:"ignore",windowsHide:!0}).unref():process.platform==="darwin"?$e("open",[n],{detached:!0,stdio:"ignore"}).unref():$e("xdg-open",[n],{detached:!0,stdio:"ignore"}).unref()}catch{}}var zr={stopped:"gray",starting:"yellow",compiling:"yellow",serving:"green",error:"red"},Vr={healthy:"green",unhealthy:"red",unknown:"gray"};function Ao(n){if(n==null)return"";let t=Math.floor(n/1e3);if(t<60)return`${t}s`;let e=Math.floor(t/60);return e<60?`${e}m ${t%60}s`:`${Math.floor(e/60)}h ${e%60}m`}function Me({registry:n,apiPort:t,onQuit:e}){let{exit:r}=ko(),{stdout:s}=Eo(),[o,i]=X(n.list()),[a,u]=X(0),[l,h]=X(!1),[p,x]=X(0),[S,c]=X(!1),[f,m]=X([]),[d,g]=X(!1),[R,T]=X(""),[v,j]=X(null),[,M]=X(0);wo(()=>{let w=()=>i(n.list());n.on("change",w);let $=setInterval(()=>{i(n.list()),M(C=>C+1)},1e3);return()=>{n.off("change",w),clearInterval($)}},[n]),xo((w,$)=>{if(S)return;if(v){if($.escape){j(null);return}if($.tab){let _=v.field==="command"?"port":v.field==="port"?"env":"command";j({...v,field:_});return}return}if(d){if($.escape){g(!1),T("");return}if($.return){let _=R.trim();m(_?_.split(/[\s,]+/).filter(Boolean):[]),g(!1),T("");return}if($.backspace||$.delete){T(_=>_.slice(0,-1));return}w&&!$.ctrl&&T(_=>_+w);return}if(w==="q"||$.ctrl&&w==="c"){e(),r();return}if(o.length===0)return;if($.upArrow){u(_=>Math.max(0,_-1)),x(0);return}if($.downArrow){u(_=>Math.min(o.length-1,_+1)),x(0);return}let C=o[a];if(C)if(w==="s")n.start(C.name);else if(w==="x")n.stop(C.name);else if(w==="r")n.restart(C.name);else if(w==="L")c(!0);else if(w==="t")g(!0),T(f.join(" "));else if(w==="e"){let _=n.getConfig(),I=n.getApp(C.name),K=n.getState(C.name)?.sessionOverrides??null,ht=K?.env??_.overrides?.[C.name]?.env??{},Z=Object.entries(ht).map(([zt,Vt])=>`${zt}=${Vt}`).join(`
|
|
68
|
+
`);j({name:C.name,field:"command",cmd:K?.command??I?.command??"",port:String(K?.port??_.overrides?.[C.name]?.port??C.port??""),env:Z})}else if(w==="E"){let I=n.getConfig().envFiles?.[C.name]??[];if(!I.length)return;let K=n.getState(C.name)?.activeEnvFile??null,ht=K?I.indexOf(K):-1,Z=I[(ht+1)%I.length];n.setActiveEnvFile(C.name,Z)}else if(w==="V"){let _=process.env.EDITOR||(process.platform==="win32"?"notepad":"vi"),I=So.join(bo.tmpdir(),`daimon-${C.name}-${Date.now()}.json`),K=n.getConfig(),ht=n.getApp(C.name),Z=n.getState(C.name)?.sessionOverrides??null,zt={command:Z?.command??ht?.command,port:Z?.port??K.overrides?.[C.name]?.port??null,env:Z?.env??K.overrides?.[C.name]?.env??{}};try{je.writeFileSync(I,JSON.stringify(zt,null,2)),To(_,[I],{stdio:"inherit",shell:!0});let Vt=je.readFileSync(I,"utf8"),Q=JSON.parse(Vt);n.setSessionOverride(C.name,{command:typeof Q.command=="string"?Q.command:void 0,port:typeof Q.port=="number"?Q.port:void 0,env:Q.env&&typeof Q.env=="object"?Q.env:void 0}),je.unlinkSync(I)}catch{}}else w==="l"?h(_=>!_):w==="o"?C.url&&Ro(C.url):$.pageUp?x(_=>_+5):$.pageDown&&x(_=>Math.max(0,_-5))});let E=f.length===0?o:o.filter(w=>f.every($=>w.tags.includes($))),y=E[Math.min(a,Math.max(0,E.length-1))],P=y?n.getState(y.name):null,k=P?P.logBuffer.slice(Math.max(0,P.logBuffer.length-12-p),P.logBuffer.length-p).map(w=>w.line):[],N=s.columns||100,D=Math.min(36,Math.floor(N*.4));return S&&y?A.createElement(Oe,{registry:n,appName:y.name,onExit:()=>c(!1)}):A.createElement(J,{flexDirection:"column",width:N},A.createElement(J,{borderStyle:"round",borderColor:"cyan",paddingX:1},A.createElement(O,{bold:!0,color:"cyan"},"daimon"),A.createElement(O,{dimColor:!0}," \u2022 api http://127.0.0.1:",t)),A.createElement(J,{flexDirection:"row"},A.createElement(J,{flexDirection:"column",width:D,borderStyle:"single",borderColor:"gray",paddingX:1},A.createElement(O,{bold:!0},"Apps ",f.length?A.createElement(O,{dimColor:!0},"(tags: ",f.join(", "),")"):null),E.length===0?A.createElement(O,{dimColor:!0},o.length===0?"(no apps discovered)":"(no apps match tag filter)"):E.map((w,$)=>{let C=$===a;return A.createElement(J,{key:w.name},A.createElement(O,{color:C?"cyan":void 0},C?"\u25B8 ":" "),A.createElement(O,{color:C?"cyan":void 0},((n.getState(w.name)?.sessionOverrides?"*":"")+w.name).padEnd(20).slice(0,20)),A.createElement(O,{color:zr[w.status]}," ",w.status.padEnd(9)),A.createElement(O,{color:Vr[w.health]},w.status==="serving"?"\u25CF":" "),A.createElement(O,{dimColor:!0},w.port?` :${w.port}`:""),N>=100&&w.cpu!=null?A.createElement(O,{dimColor:!0}," ",String(w.cpu).padStart(5),"% ",String(w.memMB??0).padStart(5),"MB"):null)})),A.createElement(J,{flexDirection:"column",flexGrow:1,borderStyle:"single",borderColor:"gray",paddingX:1},y&&P?A.createElement(A.Fragment,null,A.createElement(O,null,"Selected: ",A.createElement(O,{bold:!0},y.name)),A.createElement(O,null,"Status: ",A.createElement(O,{color:zr[y.status]},y.status)," ",A.createElement(O,{color:Vr[y.health]},"\u25CF")," ",A.createElement(O,{dimColor:!0},y.health)),A.createElement(O,null,"Port: ",y.port??"-"),A.createElement(O,null,"URL: ",y.url??"-"),y.announcedUrl&&y.announcedUrl!==y.url?A.createElement(O,{dimColor:!0},"Announced: ",y.announcedUrl):null,y.lastHealthError?A.createElement(O,{color:"red"},"HealthErr: ",y.lastHealthError):null,y.stale?A.createElement(O,{color:"yellow"},"\u26A0 stale (best guess)"):null,A.createElement(O,null,"Errors: ",A.createElement(O,{color:y.errorCount?"red":void 0},y.errorCount)),A.createElement(O,null,"Uptime: ",Ao(y.uptimeMs)),y.cpu!=null||y.memMB!=null?A.createElement(O,null,"Usage: ",y.cpu??"-","% ",y.memMB??"-"," MB"):null,y.compileHistoryMs.length>0?A.createElement(O,null,"Recent compile: ",y.compileHistoryMs.slice(-5).map(w=>(w/1e3).toFixed(1)+"s").join(" \xB7 ")):null,y.bundle?A.createElement(O,null,"Bundle: ",y.bundle.initialKB,"KB initial \xB7 ",y.bundle.lazyKB,"KB lazy",y.bundleRegressionPct!=null&&y.bundleRegressionPct>10?A.createElement(O,{color:"red"}," (+",y.bundleRegressionPct,"% \u26A0)"):null):null,P.lastStatusMessage?A.createElement(O,{dimColor:!0},"Note: ",P.lastStatusMessage):null,A.createElement(O,null,"\u2500\u2500\u2500\u2500 recent log ",l?"(focused)":""," \u2500\u2500\u2500\u2500"),k.length===0?A.createElement(O,{dimColor:!0},"(no output yet)"):k.map((w,$)=>A.createElement(O,{key:$,wrap:"truncate-end"},w))):A.createElement(O,{dimColor:!0},"No app selected."))),A.createElement(J,{flexDirection:"column"},d?A.createElement(O,null,"tag filter (space-separated, Enter to apply, Esc to cancel): ",A.createElement(O,{color:"cyan"},R)):null,v?A.createElement(J,{flexDirection:"column",borderStyle:"round",borderColor:"yellow",paddingX:1},A.createElement(O,{bold:!0,color:"yellow"},"edit ",v.name," (session-only) Tab=next field Enter=save Esc=cancel"),A.createElement(J,null,A.createElement(O,null,v.field==="command"?"> ":" ","command: "),v.field==="command"?A.createElement(Ne,{value:v.cmd,onChange:w=>j({...v,cmd:w}),onSubmit:()=>j({...v,field:"port"})}):A.createElement(O,{dimColor:!0},v.cmd)),A.createElement(J,null,A.createElement(O,null,v.field==="port"?"> ":" ","port: "),v.field==="port"?A.createElement(Ne,{value:v.port,onChange:w=>j({...v,port:w}),onSubmit:()=>j({...v,field:"env"})}):A.createElement(O,{dimColor:!0},v.port)),A.createElement(J,null,A.createElement(O,null,v.field==="env"?"> ":" ","env (k=v;): "),v.field==="env"?A.createElement(Ne,{value:v.env.replace(/\n/g,";"),onChange:w=>j({...v,env:w.replace(/;/g,`
|
|
69
|
+
`)}),onSubmit:()=>{let w=Number(v.port),$={};for(let C of v.env.split(/\n/)){let _=C.match(/^\s*([^=]+)=(.*)$/);_&&($[_[1].trim()]=_[2])}n.setSessionOverride(v.name,{command:v.cmd||void 0,port:Number.isFinite(w)&&w>0?w:void 0,env:Object.keys($).length?$:void 0}),j(null)}}):A.createElement(O,{dimColor:!0},v.env))):null,A.createElement(O,{dimColor:!0},"[s] start [x] stop [r] restart [o] open URL [t] tag filter [e] edit [E] cycle env [V] $EDITOR [l] log focus [Shift+L] full log [PgUp/PgDn] scroll [q] quit")))}async function jo(n={}){let t=null,e=null;Yr({getRegistry:()=>t,getConfig:()=>e});let r;try{r=W()}catch(E){process.stderr.write(`[daimon] config error: ${E.message}
|
|
70
|
+
`),process.exit(1)}if(r.kind==="stub-created"){let E=et();process.stdout.write(`[daimon] no config found. Created stub at:
|
|
67
71
|
${r.path}
|
|
68
72
|
`),process.stdout.write(`[daimon] Edit it to add "searchRoots" pointing at your Nx/Angular workspace, then run again.
|
|
69
|
-
`),process.stdout.write(`[daimon] (Local override path: ${
|
|
70
|
-
`),process.exit(0)}let{config:s,path:
|
|
71
|
-
`),s.depends&&Object.keys(s.depends).length){let
|
|
72
|
-
`),process.exit(1))}let
|
|
73
|
-
`);let a
|
|
74
|
-
`);for(let
|
|
75
|
-
`);continue}s.depends&&s.depends[
|
|
76
|
-
`);try{
|
|
77
|
-
`)}if(process.on("SIGINT",()=>{v()}),process.on("SIGTERM",()=>{v()}),process.on("beforeExit",()=>{v()}),
|
|
78
|
-
`);let
|
|
79
|
-
`),
|
|
80
|
-
`),process.exit(1)});export{
|
|
73
|
+
`),process.stdout.write(`[daimon] (Local override path: ${E.local})
|
|
74
|
+
`),process.exit(0)}let{config:s,path:o}=r;if(process.stdout.write(`[daimon] config: ${o}
|
|
75
|
+
`),s.depends&&Object.keys(s.depends).length){let E=qe(s.depends);E&&(process.stderr.write(`[daimon] config error: depends graph has a cycle: ${E.join(" -> ")}
|
|
76
|
+
`),process.exit(1))}let i=wt(s);i.length===0&&process.stdout.write(`[daimon] no serveable projects discovered in: ${s.searchRoots.join(", ")||"(none)"}
|
|
77
|
+
`);let a=Fr(),u=new ot(s.portRange,{initial:a.ports,onChange:E=>Ir({ports:E})}),l=new Mt(s,i,u);t=l,e=s;let h=new pt(s.history);l.setHistory(h);let p=new Jt(l,s.healthProbe,s),x=new Wt(l),S=new Gt(l,s.autoRestart),c=new qt(l,s.notifications),f=new Xt(l,s.staleDetect),m=new Yt(l,s.requestLog);l.on("childExit",({name:E,code:y,signal:P,stopping:k})=>S.onExit(E,y,P,k)),l.on("userStop",({name:E})=>S.onUserStop(E));let d=Or();if(d&&d.apps.length){process.stdout.write(`[daimon] state-handoff: restoring ${d.apps.map(E=>E.name).join(", ")}
|
|
78
|
+
`);for(let E of d.apps)u.pin(E.name,E.port);for(let E of d.apps)l.names().includes(E.name)&&l.start(E.name)}if(s.autoStart&&s.autoStart.length){let E=new Set(l.names());for(let y of s.autoStart){if(!E.has(y)){process.stderr.write(`[daimon] warning: autoStart references unknown app "${y}"
|
|
79
|
+
`);continue}s.depends&&s.depends[y]&&s.depends[y].length?l.startWithDeps(y):l.start(y)}}let g=process.env.DAIMON_PORT?Number(process.env.DAIMON_PORT):s.apiPort,R=!!n.headless||!!s.headless||process.argv.includes("--headless"),T=!1,v=async()=>{if(!T){T=!0;try{p.stop()}catch{}try{x.stop()}catch{}try{S.stop()}catch{}try{c.stop()}catch{}try{f.stop()}catch{}try{m.stop()}catch{}try{h.close()}catch{}try{await l.stopAll(3e3)}catch{}try{j.close()}catch{}try{St()}catch{}process.exit(0)}},j=Mr(l,g,{metricsEnabled:s.metrics.enabled,requestLog:m,onShutdown:()=>{v()},configPath:o,getConfig:()=>l.getConfig(),patchConfig:E=>{try{let y=qr({configPath:o,patch:E}),P=Pe({configPath:o,registry:l});return{ok:!0,applied:y.applied,addedApps:P.addedApps,removedApps:P.removedApps,restartRequired:P.restartRequired}}catch(y){return{ok:!1,error:y?.message||String(y)}}},reloadConfig:async()=>{let E=Pe({configPath:o,registry:l});return{ok:!0,addedApps:E.addedApps,removedApps:E.removedApps,restartRequired:E.restartRequired}}});process.stdout.write(`[daimon] api: http://127.0.0.1:${g}
|
|
80
|
+
`);try{cr(ur(g,R,o))}catch(E){process.stderr.write(`[daimon] warning: could not write daemon.lock: ${E?.message||E}
|
|
81
|
+
`)}if(process.on("SIGINT",()=>{v()}),process.on("SIGTERM",()=>{v()}),process.on("beforeExit",()=>{v()}),R){process.stdout.write(`[daimon] headless mode \u2014 TUI suppressed. Dashboard: http://127.0.0.1:${g}
|
|
82
|
+
`);let E="",y=setInterval(()=>{let P=l.list().map(N=>({name:N.name,status:N.status,health:N.health,port:N.port})),k=JSON.stringify(P);k!==E&&(process.stderr.write(k+`
|
|
83
|
+
`),E=k)},6e4);await new Promise(()=>{}),clearInterval(y);return}await Po(Co.createElement(Me,{registry:l,apiPort:g,onQuit:()=>{v()}})).waitUntilExit(),await v()}var No=(()=>{try{return import.meta.url===Oo(process.argv[1]||"").href}catch{return!1}})();No&&jo().catch(n=>{process.stderr.write(`[daimon] fatal: ${n?.stack||n}
|
|
84
|
+
`),process.exit(1)});export{jo as startInProcess};
|