infra-kit 0.3.2 → 0.3.4

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.
@@ -1,42 +1,42 @@
1
- import{b as Q,e as Z,i as Te,m as Ce,n as $e,o as Le,r as Ne}from"./chunk-7F5YKMWK.js";import"./chunk-A7FAXZGI.js";import{b as F,c as Ie}from"./chunk-NLOLELZ5.js";import{A as ye,B as T,C as be,D as Se,E as Pe,G as De,H as Ae,K as xe,Q as Y,v as E,w as k,x as _,y as we,z as U}from"./chunk-KHEUED4B.js";import{d as Re,e as Ee,m as ke}from"./chunk-CHETBZ6M.js";import{Command as In}from"commander";import R from"node:process";import{pathToFileURL as On}from"node:url";import*as Ve from"node:path";import Yt from"node:process";var $t=r=>({pane:{surfaces:[{type:"terminal",command:r}]}}),ee=(r,e)=>{if(r.length===1)return $t(r[0]);let t=Math.ceil(r.length/2),n=r.slice(0,t),i=r.slice(t);return{direction:e%2===0?"horizontal":"vertical",split:Math.round(t/r.length*100)/100,children:[ee(n,e+1),ee(i,e+1)]}},Oe=r=>{if(r.length===0)throw new Error("buildCmuxLayout: at least one command is required");return ee(r,0)};import{constants as jt}from"node:os";import oe from"node:process";import{execFile as Lt,execFileSync as Nt}from"node:child_process";import P from"node:process";var It=5e3,Ot=100,_t=2e3,Fe="/bin/ps",Ut=1e3,Me=["-eo","pid=,ppid=,pgid=,lstart="],He=8<<20,We=r=>r.split(`
2
- `).flatMap(e=>{let[t,n,i,...o]=e.trim().split(/\s+/);if(t==null||n==null||i==null)return[];let s=Number(t),a=Number(n),l=Number(i);return!Number.isInteger(s)||!Number.isInteger(a)||!Number.isInteger(l)?[]:[{pid:s,ppid:a,pgid:l,lstart:o.join(" ")}]}),je=r=>{let e=new Map;for(let t of r)t.pid===t.pgid&&e.set(t.pgid,t.lstart);return e},Ft=(r,e,t)=>{let n=je(e);return Be(r,e,t).flatMap(i=>{let o=n.get(i);return o==null||o===""?[]:[{pgid:i,leaderStart:o}]})},_e=(r,e)=>{let t=je(e);return r.flatMap(({pgid:n,leaderStart:i})=>{if(t.get(n)!==i)return[];try{P.kill(-n,"SIGKILL")}catch{return[]}return[n]})},Be=(r,e,t)=>{let n=new Map;for(let a of e){let l=n.get(a.ppid);l?l.push(a):n.set(a.ppid,[a])}let i=new Set([r]),o=new Set([r]),s=[r];for(let a=0;a<s.length;a+=1)for(let l of n.get(s[a]??-1)??[])o.has(l.pid)||(o.add(l.pid),i.add(l.pgid),s.push(l.pid));return[...i].filter(a=>a>1&&a!==t)},C=()=>{try{return We(Nt(Fe,[...Me],{encoding:"utf8",maxBuffer:He}))}catch{return[]}},Mt=async()=>new Promise(r=>{Lt(Fe,[...Me],{encoding:"utf8",maxBuffer:He},(e,t)=>{r(e?[]:We(t))})}),Ht=(r,e,t)=>t.some(n=>n.pid===r&&n.ppid===e),te=(r,e)=>{let t=e.find(n=>n.pid===P.pid)?.pgid;return Be(r,e,t)},Ge=r=>{try{return P.kill(-r,0),!0}catch{return!1}},re=(r,e)=>{for(let t of r)try{P.kill(-t,e)}catch{}},A=()=>{re(te(P.pid,C()),"SIGKILL")},Wt=async r=>new Promise(e=>{setTimeout(e,r)}),Ue=async(r,e)=>{let t=Date.now()+e,n=r;for(;n.length>0&&Date.now()<t&&(n=n.filter(Ge),n.length!==0);)await Wt(Ot);return n};function M(r,e=It,t){r.unref();let n=!1,i=!1,o=[],s=null,a=()=>{s&&clearInterval(s),s=null},l=async()=>{let u=r.pid;if(u==null||i||n)return;let c=await Mt();if(c.length===0||i||n)return;let g=c.find(v=>v.pid===P.pid)?.pgid,p=Ft(u,c,g);p.length>0&&(o=p)};l(),s=setInterval(()=>{l()},Ut),s.unref();let d=u=>{n||t?.(u)};return r.on("exit",(u,c)=>{i=!0,a(),n||_e(o,C()),d(`exited unexpectedly (code=${u??"null"}, signal=${c??"null"})`)}),r.on("error",u=>{d(`failed to spawn: ${u.message}`)}),{kill:async()=>{n=!0,a();let u=r.pid;if(u==null)return;if(r.exitCode!==null||r.signalCode!==null){_e(o,C());return}let c=C();if(c.length>0&&!Ht(u,P.pid,c))return;let g=te(u,c);re(g,"SIGTERM");let p=await Ue(g,e);if(p.length===0)return;let v=te(u,C()),y=[...new Set([...p,...v])].filter(Ge);re(y,"SIGKILL"),await Ue(y,_t)}}}var Bt=["SIGINT","SIGTERM","SIGHUP"],Gt=jt.signals,Vt=2,ne=r=>128+(Gt[r]??Vt),Jt=2e4,Kt=r=>{oe.exit(r)},qt=(r,e)=>{oe.on(r,e)},zt=(r,e)=>{let t=setTimeout(r,e);return t.unref(),()=>{clearTimeout(t)}},ie=r=>{try{oe.stderr.write(r)}catch{}},Xt=(r,e)=>{let t=e instanceof Error?`${e.message}
3
- ${e.stack??"(no stack)"}`:String(e);ie(`
1
+ import{b as Z,e as ee,i as Te,m as Ce,n as $e,o as Le,r as Ne}from"./chunk-S45AAYXO.js";import"./chunk-A7FAXZGI.js";import{b as C,c as Ie}from"./chunk-RVTI3AL2.js";import{A as T,B as Se,C as Pe,D as De,F as xe,G as Ae,J as Re,P as Y,u as k,v as E,w as U,x as ye,y as F,z as be}from"./chunk-IVWPZEMC.js";import{d as ke,e as Q,m as Ee}from"./chunk-CHETBZ6M.js";import{Command as _n}from"commander";import R from"node:process";import{pathToFileURL as Un}from"node:url";import*as Ve from"node:path";import er from"node:process";var It=r=>({pane:{surfaces:[{type:"terminal",command:r}]}}),te=(r,e)=>{if(r.length===1)return It(r[0]);let t=Math.ceil(r.length/2),n=r.slice(0,t),i=r.slice(t);return{direction:e%2===0?"horizontal":"vertical",split:Math.round(t/r.length*100)/100,children:[te(n,e+1),te(i,e+1)]}},Oe=r=>{if(r.length===0)throw new Error("buildCmuxLayout: at least one command is required");return te(r,0)};import{constants as Vt}from"node:os";import se from"node:process";import{execFile as Ot,execFileSync as _t}from"node:child_process";import P from"node:process";var Ut=5e3,Ft=100,Mt=2e3,Fe="/bin/ps",Ht=1e3,Me=["-eo","pid=,ppid=,pgid=,lstart="],He=8<<20,je=r=>r.split(`
2
+ `).flatMap(e=>{let[t,n,i,...o]=e.trim().split(/\s+/);if(t==null||n==null||i==null)return[];let s=Number(t),a=Number(n),l=Number(i);return!Number.isInteger(s)||!Number.isInteger(a)||!Number.isInteger(l)?[]:[{pid:s,ppid:a,pgid:l,lstart:o.join(" ")}]}),We=r=>{let e=new Map;for(let t of r)t.pid===t.pgid&&e.set(t.pgid,t.lstart);return e},jt=(r,e,t)=>{let n=We(e);return Be(r,e,t).flatMap(i=>{let o=n.get(i);return o==null||o===""?[]:[{pgid:i,leaderStart:o}]})},_e=(r,e)=>{let t=We(e);return r.flatMap(({pgid:n,leaderStart:i})=>{if(t.get(n)!==i)return[];try{P.kill(-n,"SIGKILL")}catch{return[]}return[n]})},Be=(r,e,t)=>{let n=new Map;for(let a of e){let l=n.get(a.ppid);l?l.push(a):n.set(a.ppid,[a])}let i=new Set([r]),o=new Set([r]),s=[r];for(let a=0;a<s.length;a+=1)for(let l of n.get(s[a]??-1)??[])o.has(l.pid)||(o.add(l.pid),i.add(l.pgid),s.push(l.pid));return[...i].filter(a=>a>1&&a!==t)},$=()=>{try{return je(_t(Fe,[...Me],{encoding:"utf8",maxBuffer:He}))}catch{return[]}},Wt=async()=>new Promise(r=>{Ot(Fe,[...Me],{encoding:"utf8",maxBuffer:He},(e,t)=>{r(e?[]:je(t))})}),Bt=(r,e,t)=>t.some(n=>n.pid===r&&n.ppid===e),re=(r,e)=>{let t=e.find(n=>n.pid===P.pid)?.pgid;return Be(r,e,t)},Ge=r=>{try{return P.kill(-r,0),!0}catch{return!1}},ne=(r,e)=>{for(let t of r)try{P.kill(-t,e)}catch{}},x=()=>{ne(re(P.pid,$()),"SIGKILL")},Gt=async r=>new Promise(e=>{setTimeout(e,r)}),Ue=async(r,e)=>{let t=Date.now()+e,n=r;for(;n.length>0&&Date.now()<t&&(n=n.filter(Ge),n.length!==0);)await Gt(Ft);return n};function M(r,e=Ut,t){r.unref();let n=!1,i=!1,o=[],s=null,a=()=>{s&&clearInterval(s),s=null},l=async()=>{let p=r.pid;if(p==null||i||n)return;let d=await Wt();if(d.length===0||i||n)return;let g=d.find(m=>m.pid===P.pid)?.pgid,u=jt(p,d,g);u.length>0&&(o=u)};l(),s=setInterval(()=>{l()},Ht),s.unref();let c=p=>{n||t?.(p)};return r.on("exit",(p,d)=>{i=!0,a(),n||_e(o,$()),c(`exited unexpectedly (code=${p??"null"}, signal=${d??"null"})`)}),r.on("error",p=>{c(`failed to spawn: ${p.message}`)}),{kill:async()=>{n=!0,a();let p=r.pid;if(p==null)return;if(r.exitCode!==null||r.signalCode!==null){_e(o,$());return}let d=$();if(d.length>0&&!Bt(p,P.pid,d))return;let g=re(p,d);ne(g,"SIGTERM");let u=await Ue(g,e);if(u.length===0)return;let m=re(p,$()),w=[...new Set([...u,...m])].filter(Ge);ne(w,"SIGKILL"),await Ue(w,Mt)}}}var Jt=["SIGINT","SIGTERM","SIGHUP"],Kt=Vt.signals,qt=2,ie=r=>128+(Kt[r]??qt),zt=2e4,Xt=r=>{se.exit(r)},Yt=(r,e)=>{se.on(r,e)},Qt=(r,e)=>{let t=setTimeout(r,e);return t.unref(),()=>{clearTimeout(t)}},oe=r=>{try{se.stderr.write(r)}catch{}},Zt=(r,e)=>{let t=e instanceof Error?`${e.message}
3
+ ${e.stack??"(no stack)"}`:String(e);oe(`
4
4
  \u2717 Teardown failed while handling ${r}: ${t}
5
- `)},H=({onSignal:r,exit:e=Kt,register:t=qt,forceReap:n=A,teardownDeadlineMs:i=Jt,setTimer:o=zt,describeStall:s=()=>"unknown",fileReport:a=()=>{}})=>{let l=null,d=null,u=c=>{if(l!==null){if(c!==l)return;ie(`
6
- \u26A0 Received ${c} again \u2014 force-quitting.
7
- `),d?.(),n(),e(ne(c));return}l=c,d=o(()=>{let g=`
5
+ `)},H=({onSignal:r,exit:e=Xt,register:t=Yt,forceReap:n=x,teardownDeadlineMs:i=zt,setTimer:o=Qt,describeStall:s=()=>"unknown",fileReport:a=()=>{}})=>{let l=null,c=null,p=d=>{if(l!==null){if(d!==l)return;oe(`
6
+ \u26A0 Received ${d} again \u2014 force-quitting.
7
+ `),c?.(),n(),e(ie(d));return}l=d,c=o(()=>{let g=`
8
8
  \u26A0 Teardown deadline exceeded at stage=${s()} after ${i}ms \u2014 force-quitting.
9
- `;ie(g),a(g),n(),e(ne(c))},i),(async()=>{try{await r(c)}catch(g){Xt(c,g)}finally{d?.(),e(ne(c))}})()};for(let c of Bt)t(c,()=>u(c))};var Qt=(r,e)=>r.map(({app:t,targets:n})=>`pnpm exec infra-kit dev ${n&&n.length>0?`--target=${n.join(",")}`:`--app=${t}`}${e?" --watch":""}`),Zt=r=>{let e=new Map;for(let t of Object.keys(r?.apps??{})){let n=t.split("/")[0];n===void 0||n==="*"||e.set(n,[...e.get(n)??[],t])}return e},er=(r,e)=>{let t=_(r);return e?t.filter(n=>e.includes(n.name)):t},tr=(r,e)=>{E.info(`\u{1F9E9} Opened cmux dev workspace ${e} with ${r.length} pane(s):`);for(let t of r)E.info(` \u2022 ${t.name} (infra-kit dev --app=${t.name})`)},rr=r=>{H({onSignal:async e=>{E.info(`
10
- Received ${e}, closing cmux dev workspace ${r}...`),await Le(r)}})},Je=async r=>{let e=k(Yt.cwd()),t=er(e,U(r.include));if(t.length===0){E.warn("No API apps found to run");return}let n=Zt(r.presetDef),i=Qt(t.map(d=>({app:d.name,targets:n.get(d.name)})),r.watch??!1),o=Oe(i),s=`${Ve.basename(e)} dev`,a=await $e({cwd:e,title:s,layout:o});tr(t,a),rr(a);let l=setInterval(()=>{l.refresh()},2**30);await new Promise(()=>{})};import se from"node:process";var ae=r=>{try{se.stderr.write(r)}catch{}},$=(r,e,t=!0)=>{let n=e instanceof Error?`${e.message}
9
+ `;oe(g),a(g),n(),e(ie(d))},i),(async()=>{try{await r(d)}catch(g){Zt(d,g)}finally{c?.(),e(ie(d))}})()};for(let d of Jt)t(d,()=>p(d))};var tr=(r,e)=>r.map(({app:t,targets:n})=>`pnpm exec infra-kit dev ${n&&n.length>0?`--target=${n.join(",")}`:`--app=${t}`}${e?" --watch":""}`),rr=r=>{let e=new Map;for(let t of Object.keys(r?.apps??{})){let n=t.split("/")[0];n===void 0||n==="*"||e.set(n,[...e.get(n)??[],t])}return e},nr=(r,e)=>{let t=U(r);return e?t.filter(n=>e.includes(n.name)):t},ir=(r,e)=>{k.info(`\u{1F9E9} Opened cmux dev workspace ${e} with ${r.length} pane(s):`);for(let t of r)k.info(` \u2022 ${t.name} (infra-kit dev --app=${t.name})`)},or=r=>{H({onSignal:async e=>{k.info(`
10
+ Received ${e}, closing cmux dev workspace ${r}...`),await Le(r)}})},Je=async r=>{let e=E(er.cwd()),t=nr(e,F(r.include));if(t.length===0){k.warn("No API apps found to run");return}let n=rr(r.presetDef),i=tr(t.map(c=>({app:c.name,targets:n.get(c.name)})),r.watch??!1),o=Oe(i),s=`${Ve.basename(e)} dev`,a=await $e({cwd:e,title:s,layout:o});ir(t,a),or(a);let l=setInterval(()=>{l.refresh()},2**30);await new Promise(()=>{})};import ae from"node:process";var le=r=>{try{ae.stderr.write(r)}catch{}},L=(r,e,t=!0)=>{let n=e instanceof Error?`${e.message}
11
11
  ${e.stack??"(no stack)"}`:String(e);return`
12
12
  \u26A0\uFE0F ${r}: ${n}
13
13
  ${t?` dev-server kept alive (likely a bug in a handler's async path); restart if it misbehaves.
14
14
  `:` dev-server is shutting down: its stdio is unwritable, so reporting this fault would loop forever.
15
- `}`},nr=(r,e)=>{ae($(r,e))},ir=(r,e)=>{ae($(r,e,!1))},or=r=>{ae(`
15
+ `}`},sr=(r,e)=>{le(L(r,e))},ar=(r,e)=>{le(L(r,e,!1))},lr=r=>{le(`
16
16
  \u2717 dev-server exiting: ${r}
17
- `),A(),se.exit(1)},sr=(r,e)=>{se.on(r,e)},Ke=({onFault:r=nr,register:e=sr,isTerminalDead:t=()=>!1,fileFault:n=ir,onFatal:i=or}={})=>{let o=s=>a=>{if(t()){n(s,a),i(`${s} while stdio is unwritable`);return}r(s,a)};e("uncaughtException",o("uncaughtException")),e("unhandledRejection",o("unhandledRejection"))};import{DEFAULT_RELEASE_SLUG as St,DEV_CONTEXT_WIRE_VERSION as Zr,loadDev as en,slugifyHostLabel as tn,slugifyRelease as rn}from"@slip-stream-kit/config/internal";import nn from"chokidar";import{exec as on,execFileSync as sn}from"node:child_process";import*as h from"node:fs";import an from"node:net";import ln from"node:os";import*as m from"node:path";import f from"node:process";import un from"node:util";import{execFile as ar}from"node:child_process";import*as qe from"node:fs";import*as W from"node:path";import{promisify as lr}from"node:util";var ur=lr(ar),pr=r=>{try{let e=JSON.parse(qe.readFileSync(W.join(r,"package.json"),"utf-8"));return typeof e.name=="string"?e.name:void 0}catch{return}},cr=r=>async e=>{let{stdout:t}=await ur("pnpm",["exec","turbo","run","build","--dry=json",`--filter=...${e}`],{cwd:r,maxBuffer:33554432}),i=(JSON.parse(t).tasks??[]).map(o=>o.package).filter(o=>typeof o=="string");return[...new Set(i)]},dr=r=>{let e=new Map,t=new Map;for(let n of T(r)){let i=pr(W.dirname(n));i!==void 0&&(e.set(n,i),t.set(i,n))}return{packageNameByDir:e,dirByName:t}},ze=async(r,e,t=cr(r))=>{let{packageNameByDir:n,dirByName:i}=dr(r),o=new Map,s=await Promise.all(e.map(async a=>({app:a,closure:await t(a.packageName)})));for(let{app:a,closure:l}of s)for(let d of l){let u=i.get(d);if(u===void 0)continue;let c=o.get(u)??new Set;c.add(a.name),o.set(u,c)}return{dependentsByPackageDir:o,packageNameByDir:n}},Xe=r=>`__pkg__:${r}`,Ye=(r,e,t)=>{if(e===null||t===void 0)return null;let n=e.dependentsByPackageDir.get(t)??new Set;return r.filter(i=>i.watchDeps&&n.has(i.name))};var gr="this run never launched it",hr=(r,e,t)=>{if(!(!t&&r.includes("<env>")))return r.replaceAll("<packageName>",e).replaceAll("<env>",t??"")},fr=r=>r.default??r.from[0]??"cloud",Qe=r=>r.uis.flatMap(e=>Object.entries(e.routes).flatMap(([t,n])=>{let i=mr(e,t,n,r);return i?[i]:[]})),mr=(r,e,t,{wanted:n,running:i,reasons:o,env:s})=>{let{packageName:a}=t,l=n.has(a)||t.pinnedLocal===!0;if(!t.from.includes("local")||!l||i.has(a))return null;let d=fr(t),u=o.get(a),c=d==="cloud"&&r.cloudTemplate!=null?hr(r.cloudTemplate,a,s):void 0;return{uiApp:r.app,route:e,packageName:a,fallback:d,apiApp:u?.app,reason:u?.reason??gr,cloudTarget:c}},vr=r=>{if(r.fallback==="local")return`would proxy ${r.route} at the local alias for "${r.packageName}", which nothing is serving \u2014 every request will fail`;let e=r.cloudTarget??"the cloud backend";return`would proxy ${r.route} to ${e} instead of your local backend`},Ze=r=>r.apiApp!=null,wr=r=>Ze(r)?`fix ${r.apiApp}/api and re-run (or use --watch to retry it on the next save)`:`this run never launched "${r.packageName}" \u2014 drop the --app/--self narrowing, add its api to the preset, or set "${r.route}" to "cloud" if you meant to develop against cloud`,et=(r,e)=>{let t=r.map(n=>{let i=Ze(n)?`${n.apiApp}/api`:`"${n.packageName}"`;return` ${n.uiApp}/ui ${n.route} \u2192 ${n.packageName}: ${n.uiApp}/ui ${vr(n)}.
17
+ `),x(),ae.exit(1)},ur=(r,e)=>{ae.on(r,e)},Ke=({onFault:r=sr,register:e=ur,isTerminalDead:t=()=>!1,fileFault:n=ar,onFatal:i=lr}={})=>{let o=s=>a=>{if(t()){n(s,a),i(`${s} while stdio is unwritable`);return}r(s,a)};e("uncaughtException",o("uncaughtException")),e("unhandledRejection",o("unhandledRejection"))};import{DEFAULT_RELEASE_SLUG as xt,DEV_CONTEXT_WIRE_VERSION as tn,loadDev as rn,slugifyHostLabel as nn,slugifyRelease as on}from"@slip-stream-kit/config/internal";import sn from"chokidar";import{exec as an,execFileSync as ln}from"node:child_process";import*as h from"node:fs";import un from"node:net";import pn from"node:os";import*as v from"node:path";import f from"node:process";import cn from"node:util";import{execFile as pr}from"node:child_process";import*as qe from"node:fs";import*as j from"node:path";import{promisify as cr}from"node:util";var dr=cr(pr),gr=r=>{try{let e=JSON.parse(qe.readFileSync(j.join(r,"package.json"),"utf-8"));return typeof e.name=="string"?e.name:void 0}catch{return}},hr=r=>async e=>{let{stdout:t}=await dr("pnpm",["exec","turbo","run","build","--dry=json",`--filter=...${e}`],{cwd:r,maxBuffer:33554432}),i=(JSON.parse(t).tasks??[]).map(o=>o.package).filter(o=>typeof o=="string");return[...new Set(i)]},fr=r=>{let e=new Map,t=new Map;for(let n of T(r)){let i=gr(j.dirname(n));i!==void 0&&(e.set(n,i),t.set(i,n))}return{packageNameByDir:e,dirByName:t}},ze=async(r,e,t=hr(r))=>{let{packageNameByDir:n,dirByName:i}=fr(r),o=new Map,s=await Promise.all(e.map(async a=>({app:a,closure:await t(a.packageName)})));for(let{app:a,closure:l}of s)for(let c of l){let p=i.get(c);if(p===void 0)continue;let d=o.get(p)??new Set;d.add(a.name),o.set(p,d)}return{dependentsByPackageDir:o,packageNameByDir:n}},Xe=r=>`__pkg__:${r}`,Ye=(r,e,t)=>{if(e===null||t===void 0)return null;let n=e.dependentsByPackageDir.get(t)??new Set;return r.filter(i=>i.watchDeps&&n.has(i.name))};var mr="this run never launched it",Qe=(r,e,t)=>{if(!(!t&&r.includes("<env>")))return r.replaceAll("<packageName>",e).replaceAll("<env>",t??"")},Ze=r=>r.default??r.from[0]??"cloud",vr=(r,e,t)=>r==null?void 0:Qe(r,e,t),et=r=>r.uis.flatMap(e=>Object.entries(e.routes).flatMap(([t,n])=>{let i=wr(e,t,n,r);return i?[i]:[]})),wr=(r,e,t,{wanted:n,running:i,reasons:o,env:s})=>{let{packageName:a}=t,l=n.has(a)||t.pinnedLocal===!0;if(!t.from.includes("local")||!l||i.has(a))return null;let c=Ze(t),p=o.get(a),d=c==="cloud"&&r.cloudTemplate!=null?Qe(r.cloudTemplate,a,s):void 0;return{uiApp:r.app,route:e,packageName:a,fallback:c,apiApp:p?.app,reason:p?.reason??mr,cloudTarget:d}},tt=r=>{let{uis:e,running:t,localOrigin:n,env:i}=r;return e.flatMap(o=>Object.entries(o.routes).sort(([s],[a])=>s.localeCompare(a)).map(([s,a])=>{let l=a.from.includes("local")&&t.has(a.packageName)?"local":Ze(a),c=l==="local"?n(a.packageName):vr(o.cloudTemplate,a.packageName,i);return{uiApp:o.app,route:s,packageName:a.packageName,source:l,target:c}}))},yr=r=>{if(r.fallback==="local")return`would proxy ${r.route} at the local alias for "${r.packageName}", which nothing is serving \u2014 every request will fail`;let e=r.cloudTarget??"the cloud backend";return`would proxy ${r.route} to ${e} instead of your local backend`},rt=r=>r.apiApp!=null,br=r=>rt(r)?`fix ${r.apiApp}/api and re-run (or use --watch to retry it on the next save)`:`this run never launched "${r.packageName}" \u2014 drop the --app/--self narrowing, add its api to the preset, or set "${r.route}" to "cloud" if you meant to develop against cloud`,nt=(r,e)=>{let t=r.map(n=>{let i=rt(n)?`${n.apiApp}/api`:`"${n.packageName}"`;return` ${n.uiApp}/ui ${n.route} \u2192 ${n.packageName}: ${n.uiApp}/ui ${yr(n)}.
18
18
  ${i}: ${n.reason}
19
- \u2192 ${wr(n)}`});return`infra-kit dev: "${e}" is supposed to serve a backend locally, but it is not running \u2014 refusing to bring the frontend up silently pointed somewhere else.
19
+ \u2192 ${br(n)}`});return`infra-kit dev: "${e}" is supposed to serve a backend locally, but it is not running \u2014 refusing to bring the frontend up silently pointed somewhere else.
20
20
 
21
21
  ${t.join(`
22
22
 
23
- `)}`};import{AsyncLocalStorage as yr}from"node:async_hooks";var le=new yr,tt=(r,e)=>le.run(r,e),rt=r=>{le.enterWith(r)},j=()=>le.getStore();import{Buffer as ot}from"node:buffer";import w from"node:fs";import x from"node:path";import D from"node:process";import G from"node:process";var br=new Set(["EAGAIN","EINTR"]),B=!1,nt=()=>B,Sr=(r,e)=>r===G.stdout?"stdout":r===G.stderr||e===1?"stderr":"stdout",it=({streams:r=[G.stdout,G.stderr],onDeath:e}={})=>{let t=!1,n=[];for(let[i,o]of r.entries()){let s=Sr(o,i),a=l=>{let d=l??new Error("stdio error");d.code!=null&&br.has(d.code)||(B=!0,!t&&(t=!0,e?.(s,d)))};o.on("error",a),n.push({stream:o,listener:a})}return{isDead:()=>B,uninstall:()=>{for(let{stream:i,listener:o}of n)i.removeListener("error",o);n.length=0,B=!1,t=!1}}};var Pr=()=>Object.getPrototypeOf(D.stdout).write,ue=r=>nt()?!0:Pr().call(D.stdout,r);var lt=()=>new Proxy(D.stdout,{get(r,e,t){if(e==="write")return i=>ue(String(i));let n=Reflect.get(r,e,t);return typeof n=="function"?n.bind(r):n}}),st=()=>({errors:0,warns:0,lastErrorAt:null}),ut=r=>{let e=r.split(/\W+/).filter(t=>t!=="").join("-");return e===""?null:e},Dr=()=>{let r=D.env[Re]??"",e=ut(r)??"no-session";return x.join(ke(),e,"dev",String(D.pid))},at=r=>`${ut(r)??"unnamed"}.log`,Ar=10080*60*1e3,xr=r=>{let e=Number(r);if(!Number.isInteger(e)||e<=0)return!1;try{return D.kill(e,0),!0}catch(t){return t.code==="EPERM"}},Rr=(r,e)=>{let t;try{t=w.readdirSync(r,{withFileTypes:!0})}catch{return}for(let n of t){if(!n.isDirectory()||xr(n.name))continue;let i=x.join(r,n.name);try{e-w.statSync(i).mtimeMs>Ar&&w.rmSync(i,{recursive:!0,force:!0})}catch{}}},Er=256*1024*1024,kr="INFRA_KIT_DEV_LOG_MAX_BYTES",Tr=()=>{let r=Number(D.env[kr]);return Number.isInteger(r)&&r>0?r:Er},V=class{dir;fds=new Map;counters=new Map;bytes=new Map;capped=new Set;maxBytes;closed=!1;constructor(e=Dr(),t=Tr()){this.dir=e,this.maxBytes=t,w.mkdirSync(this.dir,{recursive:!0}),Rr(x.dirname(this.dir),Date.now()),this.linkLatest()}linkLatest(){let e=x.join(x.dirname(this.dir),"latest");try{w.rmSync(e,{force:!0}),w.symlinkSync(this.dir,e,"dir")}catch{}}pathFor(e){return x.join(this.dir,at(e))}fdFor(e){let t=this.fds.get(e);if(t!=null)return t;try{let n=w.openSync(this.pathFor(e),"a");this.fds.set(e,n);try{this.bytes.set(e,w.fstatSync(n).size)}catch{this.bytes.set(e,0)}return n}catch{return null}}write(e,t,n={}){if(this.closed)return;let i=this.counters.get(e)??st();if(n.level==="error"?(i.errors+=1,i.lastErrorAt=Date.now()):n.level==="warn"&&(i.warns+=1),this.counters.set(e,i),this.capped.has(e))return;let o=this.fdFor(e);if(o==null)return;let s=t.endsWith(`
23
+ `)}`};import{AsyncLocalStorage as Sr}from"node:async_hooks";var ue=new Sr,it=(r,e)=>ue.run(r,e),ot=r=>{ue.enterWith(r)},W=()=>ue.getStore();import{Buffer as lt}from"node:buffer";import y from"node:fs";import A from"node:path";import D from"node:process";import G from"node:process";var Pr=new Set(["EAGAIN","EINTR"]),B=!1,st=()=>B,Dr=(r,e)=>r===G.stdout?"stdout":r===G.stderr||e===1?"stderr":"stdout",at=({streams:r=[G.stdout,G.stderr],onDeath:e}={})=>{let t=!1,n=[];for(let[i,o]of r.entries()){let s=Dr(o,i),a=l=>{let c=l??new Error("stdio error");c.code!=null&&Pr.has(c.code)||(B=!0,!t&&(t=!0,e?.(s,c)))};o.on("error",a),n.push({stream:o,listener:a})}return{isDead:()=>B,uninstall:()=>{for(let{stream:i,listener:o}of n)i.removeListener("error",o);n.length=0,B=!1,t=!1}}};var xr=()=>Object.getPrototypeOf(D.stdout).write,pe=r=>st()?!0:xr().call(D.stdout,r);var ct=()=>new Proxy(D.stdout,{get(r,e,t){if(e==="write")return i=>pe(String(i));let n=Reflect.get(r,e,t);return typeof n=="function"?n.bind(r):n}}),ut=()=>({errors:0,warns:0,lastErrorAt:null}),dt=r=>{let e=r.split(/\W+/).filter(t=>t!=="").join("-");return e===""?null:e},Ar=()=>{let r=D.env[ke]??"",e=dt(r)??"no-session";return A.join(Ee(),e,"dev",String(D.pid))},pt=r=>`${dt(r)??"unnamed"}.log`,Rr=10080*60*1e3,kr=r=>{let e=Number(r);if(!Number.isInteger(e)||e<=0)return!1;try{return D.kill(e,0),!0}catch(t){return t.code==="EPERM"}},Er=(r,e)=>{let t;try{t=y.readdirSync(r,{withFileTypes:!0})}catch{return}for(let n of t){if(!n.isDirectory()||kr(n.name))continue;let i=A.join(r,n.name);try{e-y.statSync(i).mtimeMs>Rr&&y.rmSync(i,{recursive:!0,force:!0})}catch{}}},Tr=256*1024*1024,Cr="INFRA_KIT_DEV_LOG_MAX_BYTES",$r=()=>{let r=Number(D.env[Cr]);return Number.isInteger(r)&&r>0?r:Tr},V=class{dir;fds=new Map;counters=new Map;bytes=new Map;capped=new Set;maxBytes;closed=!1;constructor(e=Ar(),t=$r()){this.dir=e,this.maxBytes=t,y.mkdirSync(this.dir,{recursive:!0}),Er(A.dirname(this.dir),Date.now()),this.linkLatest()}linkLatest(){let e=A.join(A.dirname(this.dir),"latest");try{y.rmSync(e,{force:!0}),y.symlinkSync(this.dir,e,"dir")}catch{}}pathFor(e){return A.join(this.dir,pt(e))}fdFor(e){let t=this.fds.get(e);if(t!=null)return t;try{let n=y.openSync(this.pathFor(e),"a");this.fds.set(e,n);try{this.bytes.set(e,y.fstatSync(n).size)}catch{this.bytes.set(e,0)}return n}catch{return null}}write(e,t,n={}){if(this.closed)return;let i=this.counters.get(e)??ut();if(n.level==="error"?(i.errors+=1,i.lastErrorAt=Date.now()):n.level==="warn"&&(i.warns+=1),this.counters.set(e,i),this.capped.has(e))return;let o=this.fdFor(e);if(o==null)return;let s=t.endsWith(`
24
24
  `)?t:`${t}
25
- `,a=ot.byteLength(s);if((this.bytes.get(e)??0)+a>this.maxBytes){this.capped.add(e),this.writeRaw(o,e,`[capped] ${at(e)} hit ${this.maxBytes} bytes; further lines dropped (likely a logging loop)
26
- `);return}this.writeRaw(o,e,s)}writeRaw(e,t,n){try{w.writeSync(e,n),this.bytes.set(t,(this.bytes.get(t)??0)+ot.byteLength(n))}catch{}}statsFor(e){return this.counters.get(e)??st()}services(){return[...this.fds.keys()]}close(){if(!this.closed){this.closed=!0;for(let e of this.fds.values())try{w.closeSync(e)}catch{}this.fds.clear()}}};import pe from"node:process";import Cr from"node:util";var ce={log:"info",info:"info",debug:"debug",trace:"debug",warn:"warn",error:"error"},pt=({sink:r,fallbackService:e,currentService:t})=>{let n=!0,i=()=>t()??e,o=(u,c)=>{r.write(i(),u,{level:c})},s={};for(let u of Object.keys(ce))s[u]=console[u],console[u]=(...c)=>{if(!n){s[u](...c);return}o(Cr.format(...c),ce[u])};let a=(u,c)=>{let g=u.write.bind(u),p="",v=()=>{p!==""&&(r.write(i(),p,{level:c}),p="")};return u.write=((y,...N)=>{if(!n||typeof y!="string")return g(y,...N);p+=y;let I=p.split(`
27
- `);p=I.pop()??"";for(let S of I)S!==""&&r.write(i(),S,{level:c});p.length>8192&&v();let b=N.find(S=>typeof S=="function");return typeof b=="function"&&pe.nextTick(b),!0}),()=>{v(),Reflect.deleteProperty(u,"write")}},l=a(pe.stdout,"info"),d=a(pe.stderr,"warn");return{uninstall:()=>{if(n){n=!1,l(),d();for(let u of Object.keys(ce))console[u]=s[u]}}}};var $r="/api/v1";function ct(r){if(r==null||r==="")return;let e=parseInt(r.trim().replace(/^["']|["']$/g,""),10);return Number.isNaN(e)?void 0:e}function dt(r,e,t){let i=`${r.replace(/-/g,"_").toUpperCase()}_PORT`,o=ct(e[i]);if(o!=null)return o;let s=ct(e.PORT);return s??t[r]?.port??void 0}function gt(r,e){return e[r]?.prefixUrl??$r}function ht(r){let e=r.map(i=>i.port),t=e.filter((i,o)=>e.indexOf(i)!==o),n=r.filter(i=>t.includes(i.port));return{duplicatePorts:t,conflictingApps:n}}import{Logger as Lr}from"@aws-lambda-powertools/logger";import Nr from"fastify";import*as mt from"node:fs";import*as L from"node:path";import de from"node:process";import{pathToFileURL as Ir}from"node:url";import{parse as Or}from"yaml";var _r=r=>r?.code==="EADDRINUSE",Ur=3e4,Fr=()=>{let r=Number.parseInt(de.env.DEV_SERVER_TIMEOUT_MS??"",10);return Number.isNaN(r)?Ur:r},ft=()=>de.env.DEV_SERVER_REQUEST_LOG==="1",J=class{constructor(e){this.serverConfig=e;this.importCacheBust=`${Date.now()}`,this.logger=new Lr({serviceName:"LocalServer",logLevel:"DEBUG"}),this.serverConfig.prefixUrl=this.serverConfig.prefixUrl??"",this.server=Nr({logger:!1}),this.server.addHook("onRequest",async(n,i)=>{let o=this.serverConfig.serviceTag;o!=null&&rt(o),i.header("Access-Control-Allow-Origin","*"),i.header("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),i.header("Access-Control-Allow-Headers","Content-Type, Authorization, X-Requested-With"),n.method==="OPTIONS"&&i.status(204).send()});let t=this.serverConfig.onRequestLog;(ft()||t)&&this.server.addHook("onResponse",async(n,i)=>{let o=Math.round(i.elapsedTime),s=n.url.split("?")[0]??n.url;t?.({method:n.method,path:s,status:i.statusCode,ms:o}),ft()&&de.stdout.write(`${n.method} ${n.url} \u2192 ${i.statusCode} ${o}ms
28
- `)})}serverConfig;importCacheBust;logger;server;controllers={};registeredRouteKeys=new Set;getRegisteredRoutes(){return[...this.registeredRouteKeys].sort()}async start(){this.registerHealthRoute(),await Promise.all(this.loadRoutes());let e=await this.listenWithFallback();return this.serverConfig.port=e,this.logger.info(`Server listening on http://127.0.0.1:${e}`,{address:`http://127.0.0.1:${e}`}),e}async listenWithFallback(){let e=this.serverConfig.port;if(e!=null)try{return await this.server.listen({port:e,host:"127.0.0.1"}),this.readBoundPort()}catch(t){if(!_r(t))throw t}return await this.server.listen({port:0,host:"127.0.0.1"}),this.readBoundPort()}readBoundPort(){let e=this.server.server.address();if(e==null||typeof e=="string")throw new Error("Server address unavailable after listen()");return e.port}async close(){let e=this.server.server;typeof e.closeAllConnections=="function"&&e.closeAllConnections(),await this.server.close()}registerHealthRoute(){this.server.route({method:"GET",url:"/__health",handler:(e,t)=>t.code(200).send({status:"ok",app:this.serverConfig.appName??null,port:this.serverConfig.port})})}loadRoutes(){let e=L.join(this.serverConfig.controllersPath,"serverless.yml"),t=mt.readFileSync(e,"utf8"),n=Or(t),i=[];if(!n?.functions)return i;for(let o of Object.values(n.functions))if(o?.events?.length)for(let s of o.events){let a=s?.http;a&&i.push(this.defineRoute(a,o))}return i}async defineRoute(e,t){let n=e.path.toString();n=n.replaceAll("{",":").replaceAll("}","");let i=L.posix.join(this.serverConfig.prefixUrl??"",n);i=i[0]==="/"?i:`/${i}`;let o=["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS"],s=String(e.method).toUpperCase();if(!o.includes(s))throw new Error(`Invalid HTTP method: "${e.method}" for URL: ${i}`);let a=`${s} ${i}`;if(this.registeredRouteKeys.has(a))throw new Error(`Duplicate route: ${a}`);this.registeredRouteKeys.add(a);let d=(t.handler??"").split("."),u=d[0]??"",c=d[1]??"",g=L.join(this.serverConfig.controllersPath,`${u}.js`),p=Ir(g);p.searchParams.set("v",this.importCacheBust);let v=this.serverConfig.serviceTag,y=async()=>await import(p.href),N=v==null?await y():await tt(v,y);this.controllers[a]={action:N,handler:c};let I=this.logger.createChild({serviceName:"RequestLogger"});this.server.route({method:s,url:i,handler:async(b,S)=>{let O=this.controllers[a];if(!O)throw new Error(`No controller for ${a}`);let ve=O.action[O.handler];if(!ve)throw new Error(`No handler ${O.handler} for ${i}`);let X=await ve(this.getEventObj(b.body,b.query,b.params,b.headers,s,i),this.getContext(),I),Ct=JSON.parse(X.body);return S.headers(X.headers??{}),S.code(X?.statusCode??500).send(Ct)}})}getEventObj(e,t,n,i,o="",s=""){let a={body:e?JSON.stringify(e):null,headers:i??{},multiValueHeaders:{},httpMethod:o,isBase64Encoded:!1,path:s,pathParameters:n??null,queryStringParameters:t??null,multiValueQueryStringParameters:null,stageVariables:null,requestContext:{accountId:"",apiId:"",authorizer:void 0,protocol:"",httpMethod:o,identity:{accessKey:null,accountId:null,apiKey:null,apiKeyId:null,caller:null,clientCert:null,cognitoAuthenticationProvider:null,cognitoAuthenticationType:null,cognitoIdentityId:null,cognitoIdentityPoolId:null,principalOrgId:null,sourceIp:"devIp",user:null,userAgent:null,userArn:null},path:s,stage:"",requestId:"",requestTimeEpoch:0,resourceId:"",resourcePath:s},resource:s};return a.source="aws.events",a}getContext(){let e=Date.now(),t=Fr(),n=new Date().toISOString().split("T")[0]??"";return{callbackWaitsForEmptyEventLoop:!1,functionName:"local-dev",functionVersion:"1.0.0",invokedFunctionArn:"arn:aws:lambda:local:000000000000:function:local-dev",memoryLimitInMB:"1024",awsRequestId:`local-${Date.now()}`,logGroupName:"/aws/lambda/local-dev",logStreamName:`${n}/local`,getRemainingTimeInMillis:()=>Math.max(0,t-(Date.now()-e)),done:(i,o)=>{},fail:i=>{},succeed:i=>{}}}};import{spawn as Mr}from"node:child_process";import*as vt from"node:fs";var Hr=(r,e)=>[...r.map(t=>`--filter=...${t}`),...e.map(t=>`--filter=${t}^...`)],wt=({depInclusive:r,depClosure:e,cwd:t,logFile:n,onUnexpectedExit:i})=>{let o=Hr(r,e),s=vt.openSync(n,"a"),a=Mr("pnpm",["exec","turbo","watch","build",...o,"--continue=dependencies-successful","--env-mode=loose"],{cwd:t,detached:!0,stdio:["ignore",s,s]});return M(a,void 0,i)};import{spawn as Wr}from"node:child_process";import jr from"node:process";var Br=[/^error\b/i,/^[✘✖×]/,/^\[vite\][^\n]*\berror\b/i,/^\w*Error: /,/\berror TS\d+\b/,/^Failed to (?:resolve|load url|parse|compile)\b/i,/^(?:ENOENT|EADDRINUSE|ECONNREFUSED)\b/,/pre-transform error/i,/\b(?:build|transform|compilation) failed\b/i],Gr=r=>Br.some(e=>e.test(r))?"error":"info",Vr=/\u001B\][\s\S]*?(?:\u0007|\u001B\\)/g,Jr=/\u001B\[[0-9;?]*[\u0020-\u002F]*[\u0040-\u007E]/g,Kr=/[\u0000-\u0008\u000B-\u001F\u007F]/g,qr=r=>r.replace(Vr,"").replace(Jr,"").replace(Kr,""),zr=/^([^\s:]+):dev:[ \t]?/,Xr=r=>/^cache (?:bypass|hit|miss)/.test(r)||r.startsWith("$ "),Yr=r=>{let e=qr(r).trimEnd(),t=zr.exec(e);if(t==null)return null;let n=e.slice(t[0].length);return n.trim()===""||Xr(n.trim())?null:{pkg:t[1],text:n,level:Gr(n)}},Qr=64*1024,yt=(r,e)=>{if(r==null)return;let t="",n=i=>{let o=Yr(i);o!=null&&e.onLine?.(o)};r.setEncoding("utf-8"),r.on("data",i=>{e.appendLog?.(i),t+=i;let o=t.split(`
29
- `);t=o.pop()??"";for(let s of o)n(s);t.length>Qr&&(n(t),t="")}),r.on("end",()=>{t!==""&&(n(t),t="")}),r.on("error",i=>{e.appendLog?.(`[infra-kit] ui dev stream error: ${i.message}
30
- `)})},bt=({packageNames:r,cwd:e,concurrency:t,env:n,appendLog:i,onLine:o,onUnexpectedExit:s})=>{let a=r.map(d=>`--filter=${d}`),l=Wr("pnpm",["exec","turbo","run","dev",...a,`--concurrency=${t}`,"--env-mode=loose","--only","--output-logs=new-only","--no-update-notifier","--ui=stream"],{cwd:e,detached:!0,stdio:["ignore","pipe","pipe"],env:{...jr.env,...n}});return yt(l.stdout,{appendLog:i,onLine:o}),yt(l.stderr,{appendLog:i,onLine:o}),M(l,void 0,s)};var q="runner",pn="turbo",cn="watch";function K(r){let e=ln.homedir();return r===e||r.startsWith(`${e}${m.sep}`)?`~${r.slice(e.length)}`:r}function Pt(r){return r.map(e=>e.packageName).join(", ")}var dn=un.promisify(on),gn=async(r,e)=>{try{let{stderr:t}=await dn(r);t&&e&&e(` (build) ${t.trim()}`,"debug"),t&&!e&&console.error("stderr:",t)}catch(t){let n=t;throw e&&(n.stdout||n.stderr)&&(n.stdout&&e(` stdout: ${n.stdout.trim()}`,"error"),n.stderr&&e(` stderr: ${n.stderr.trim()}`,"error")),t}},At=null;function xt(r){At?.write(q,r)}var hn=()=>new Promise((r,e)=>{let t=an.createServer();t.unref(),t.on("error",e),t.listen(0,"127.0.0.1",()=>{let n=t.address(),i=typeof n=="object"&&n!==null?n.port:0;t.close(()=>r(i))})}),fn=r=>typeof r=="object",z=async r=>(await r.body?.cancel(),{kind:"foreign",status:r.status,contentType:r.headers.get("content-type")}),mn=(r,e)=>{let t=e.contentType?.split(";")[0]?.trim(),n=t==null||t===""?`${e.status}`:`${e.status} ${t}`;return`port ${r} answered ${n}, not vite's ping \u2014 liveness cannot be verified`},vn=1500,Dt={accept:"text/x-vite-ping"},wn=r=>r.kind==="api"?`http://127.0.0.1:${r.port}/__health`:`http://127.0.0.1:${r.port}/`,yn=(r,e)=>{try{return new URL(r,e)}catch{return null}},bn=async(r,e)=>{let t=await fetch(r,{signal:e});return t.ok?(await t.body?.cancel(),"ok"):z(t)},Sn=async(r,e)=>{let t=await fetch(r,{headers:Dt,redirect:"manual",signal:e});if(t.status===204)return"ok";if(t.status<300||t.status>=400)return z(t);let n=t.headers.get("location"),i=n==null?null:yn(n,r);if(i==null||i.origin!==new URL(r).origin)return z(t);await t.body?.cancel();let o=await fetch(i,{headers:Dt,redirect:"manual",signal:e});return o.status!==204?z(o):(await o.body?.cancel(),"ok")},Pn=async r=>{let e=wn(r),t=AbortSignal.timeout(vn);try{return r.kind==="api"?await bn(e,t):await Sn(e,t)}catch{return"refused"}},Dn=[{name:"@slip-stream-kit/vite",floor:"0.1.134"},{name:"@slip-stream-kit/config",floor:"0.1.134"},{name:"infra-kit",floor:"0.1.132"}],An=(r,e)=>{let t=o=>o.split(".").map(s=>Number.parseInt(s,10)||0),n=t(r),i=t(e);for(let o=0;o<Math.max(n.length,i.length);o+=1){let s=n[o]??0,a=i[o]??0;if(s!==a)return s<a}return!1},xn=r=>{let e=[r];try{for(let t of h.readdirSync(m.join(r,"apps"),{withFileTypes:!0}))if(t.isDirectory())for(let n of["api","ui"])e.push(m.join(r,"apps",t.name,n))}catch{}return e},Rn=(r,e)=>{try{let t=JSON.parse(h.readFileSync(m.join(r,"package.json"),"utf-8"));return["dependencies","devDependencies"].some(n=>t[n]?.[e]!=null)}catch{return!1}},En=(r,e,t)=>{let n=t.split("/"),i=e;for(;;){let o=m.join(i,"node_modules",...n);if(h.existsSync(o))return o;let s=m.dirname(i);if(i===r||s===i)return;i=s}},kn=(r,e)=>{try{let t=h.realpathSync(e),n=h.realpathSync(r);return t.startsWith(n+m.sep)&&!t.includes(`${m.sep}node_modules${m.sep}`)}catch{return!1}},Tn=r=>{try{return h.realpathSync(r)}catch{return r}},Cn=(r,e,t,n)=>{if(kn(r,n))return;let i;try{let o=JSON.parse(h.readFileSync(m.join(n,"package.json"),"utf-8"));if(typeof o.version!="string")throw new Error("no version field");i=o.version}catch{throw new Error(`infra-kit dev: could not read the version of the pinned \`${e}\` helper (${n}). Refusing to start rather than risk proxying plain HTTP at a TLS listener. Run \`pnpm install\`.`)}if(An(i,t))throw new Error(`infra-kit dev: this repo pins ${e} ${i}, but dev URLs are now HTTPS and the \`infraKitDev\` helper only understands them from ${t}. An older helper would proxy plain HTTP at a TLS listener \u2014 silently. Bump the dependency:
31
- pnpm add -D ${e}@^${t}`)},$n=r=>{let e=xn(r);for(let{name:t,floor:n}of Dn){let i=e.filter(s=>Rn(s,t)),o=new Map;for(let s of[...i,r]){let a=En(r,s,t);a&&o.set(Tn(a),a)}if(o.size===0){if(i.length===0)continue;throw new Error(`infra-kit dev: ${i[0]}/package.json depends on ${t} but it does not resolve from there, so the \`infraKitDev\` helper version cannot be verified. Run \`pnpm install\`.`)}for(let s of o.values())Cn(r,t,n,s)}},ge=r=>{try{let e=sn("git",["rev-parse","--abbrev-ref","HEAD"],{cwd:r,encoding:"utf-8"}).trim(),t=rn(e);return t===""?St:t}catch{return St}},Ln=r=>{let t=(r instanceof Error?r.message:String(r)).split(`
32
- `)[0]?.trim()??"";return t===""?"unknown error (see the log)":t},he=class r{monorepoRoot;devContextDir;appServers=[];reqTimes=new Map;lastSummary=null;readyAt=0;watchDebounceTimers=new Map;watcher=null;static WATCH_DEBOUNCE_MS=400;restartWorkChain=Promise.resolve();static PORT_RELEASE_DELAY_MS=200;livenessTimer=null;health=new Map;firstErrorLogged=new Set;uiTagByPackage=new Map;static LIVENESS_INTERVAL_MS=5e3;static LIVENESS_FAILURE_THRESHOLD=2;static NEVER_UP_DOWN_THRESHOLD=6;options;runBuild;turboWatchFactory;turboWatch=null;uiDevFactory;uiDev=null;sink;intercept;dryRunner;failedApps=[];degradedRoutes=[];renderer;healthProbe;proxy;proxyPort=xe;registeredAliases=new Set;uiPortMap={};shuttingDown=!1;closureMap=null;closureBuild=Promise.resolve();teardown=null;stage="idle";constructor(e={},t=gn,n=wt,i=bt,o,s,a=Pn,l=Te(),d){this.options=e,this.runBuild=t,this.turboWatchFactory=n,this.uiDevFactory=i,this.dryRunner=o,this.proxy=l,this.sink=d??new V,At=this.sink,this.intercept=Rt(this.options)?pt({sink:this.sink,fallbackService:q,currentService:j}):null,this.renderer=s??new Ie({appendLog:xt,verbose:this.options.verbose??!1}),this.healthProbe=a,this.devContextDir=m.join(f.cwd(),".infra-kit","dev-context"),this.monorepoRoot=k(f.cwd()),(f.env.DOPPLER_PROJECT!=null||f.env.DOPPLER_ENVIRONMENT!=null)&&this.renderer.log("\u{1F510} Doppler env detected (DOPPLER_PROJECT / DOPPLER_ENVIRONMENT)","debug")}discoverApiApps(e){return _(this.monorepoRoot).map(t=>({...t,preferredPort:this.resolvePreferredPort(t.name,e),prefixUrl:this.resolvePrefixUrl(t.name,e),watchDeps:!0}))}async loadDevConfig(){try{return(await Y()).dev??{}}catch{return{}}}normalizeAppInclude(){return U(this.options.include)}resolvePreferredPort(e,t){return dt(e,f.env,t)}resolvePrefixUrl(e,t){return gt(e,t)}async loadDevPresets(){try{return(await Y()).devServersPresets??{}}catch{return{}}}resolvePresetDef(e){if(this.options.presetDef!=null)return this.options.presetDef;let t=this.options.preset;if(t==null)return{};let n=e[t];if(!n){let i=Object.keys(e);throw new Error(`Unknown dev preset "${t}". Available: ${i.length>0?i.join(", "):"(none defined in devServersPresets)"}`)}return n}async start(){let e=Date.now(),t=this.normalizeAppInclude(),n=this.options.watch??!1,i=await this.loadDevConfig();f.env.POWERTOOLS_DEV??="true",f.env.LOG_LEVEL??="DEBUG",this.renderer.narrate("\u{1F680} Starting Development Server Runner"),n&&this.renderer.narrate("\u{1F440} Watch mode: will rebuild and restart on file save");let{apps:o,uiApps:s,apiAppsAll:a,uiAppsAll:l,wantedLocalPkgs:d,presetProxy:u}=await this.resolveRunPlan(i,t);if(o.length===0&&s.length===0){this.renderer.log("\u26A0\uFE0F No API or UI apps to run for this preset","warn");return}await this.bringUpProxy(o),await this.buildAll(o,s,n),o.length>0&&(this.renderer.bootStep("starting servers"),await this.startAllApps(o),this.renderer.narrate(this.failedApps.length===0?"\u{1F389} All servers started!":`\u26A0\uFE0F ${this.appServers.length}/${o.length} servers started \u2014 ${this.failedApps.length} failed`),this.renderer.narrate(`\u{1F4DD} Logs \u2192 ${K(this.sink.dir)} (one file per service)`));let c=Ae({preset:this.options.preset,running:[...o.map(g=>`${g.name}/api`),...s.map(g=>`${g.name}/ui`)],discovered:[...a.map(g=>`${g.name}/api`),...l.map(g=>`${g.name}/ui`)]});if(this.degradedRoutes=await this.collectDegradedRoutes(s,d,u),this.degradedRoutes.length>0&&!n)throw new Error(et(this.degradedRoutes,c));if(await this.printReady(o,s,e,c),this.options.routes&&this.printRouteDump(),this.appServers.length===0&&s.length===0&&this.failedApps.length>0)throw new Error(`infra-kit dev: no app started (${this.failedApps.length} of ${o.length} failed). First failure: ${this.failedApps[0]?.reason??"unknown"}`);this.armWatch(o,s,n),s.length>0&&this.startUiDev(s),this.startLivenessMonitor()}async resolveRunPlan(e,t){let n=this.discoverApiApps(e),i=we(this.monorepoRoot),o=De(this.resolvePresetDef(await this.loadDevPresets()),{api:n.map(p=>p.name),ui:i.map(p=>p.name)});o.unmatched.length>0&&this.renderer.log(`\u26A0\uFE0F Preset targets not found (skipped): ${o.unmatched.join(", ")}`,"warn");let s=new Set(o.targets.filter(p=>p.part==="api").map(p=>p.app)),a=new Set(o.targets.filter(p=>p.part==="ui").map(p=>p.app)),l=p=>!t||t.includes(p),d=new Map(o.targets.filter(p=>p.part==="api").map(p=>[p.app,p.watchDeps])),u=n.filter(p=>s.has(p.name)&&l(p.name)).map(p=>({...p,watchDeps:d.get(p.name)??p.watchDeps})),c=i.filter(p=>a.has(p.name)&&l(p.name)),g=new Set(n.filter(p=>s.has(p.name)).map(p=>p.packageName));return{apps:u,uiApps:c,apiAppsAll:n,uiAppsAll:i,wantedLocalPkgs:g,presetProxy:o.proxy}}async collectDegradedRoutes(e,t,n){if(e.length===0)return[];let i=[];for(let o of e){let s=await en(o.path).catch(()=>{});if(!s?.proxy)continue;let a=n[o.name]??{},l=Object.fromEntries(Object.entries(s.proxy.routes).map(([d,u])=>[d,{...u,pinnedLocal:a[d]==="local"}]));i.push({app:o.name,routes:l,cloudTemplate:s.proxy.templates.cloud})}return Qe({uis:i,wanted:t,running:new Set(this.appServers.map(({app:o})=>o.packageName)),reasons:new Map(this.failedApps.map(({app:o,reason:s})=>[o.packageName,{app:o.name,reason:s}])),env:f.env[Ee]})}async bringUpProxy(e){$n(k(f.cwd())),await this.ensureProxy(),e.length>0&&this.assertNoPortConflicts(e)}async buildAll(e,t,n){let i=[e.length>0?`building ${Pt(e)}`:"",t.length>0?`warming ${Pt(t)}`:""].filter(Boolean).join(" \xB7 ");this.renderer.bootStep(i),e.length>0&&await this.buildApps(e,n),t.length>0&&await this.buildUiApps(t)}armWatch(e,t,n){n&&(this.appServers.length>0||t.length>0)&&(this.setupWatch(e,t),this.closureBuild=this.buildClosureMapSafe(e).then(i=>{this.closureMap=i}))}async buildUiApps(e){let t=e.map(n=>`--filter=${n.packageName}^...`).join(" ");try{await this.runBuild(`pnpm exec turbo run build ${t} --env-mode=loose --output-logs=errors-only --no-update-notifier`,this.renderer.logFn),this.renderer.narrate("\u2705 UI deps built")}catch(n){this.renderer.log(`\u26A0\uFE0F UI dep build failed (continuing; vite will report unresolved deps): ${String(n)}`,"warn")}}startUiDev(e){let t=e.map(s=>s.name).join(", ");this.renderer.narrate(`\u{1F3A8} Starting ${e.length} UI dev server(s) via \`turbo run dev\`: ${t}`),this.renderer.narrate(" (framework output is routed into the live tail; full detail in the runner log)");let n=Object.keys(this.uiPortMap).length>0?{INFRA_KIT_UI_PORTS:JSON.stringify(this.uiPortMap)}:void 0,i=f.env.NODE_EXTRA_CA_CERTS==null&&h.existsSync(Z())?{NODE_EXTRA_CA_CERTS:Z()}:void 0,o=new Map(e.map(s=>[s.packageName,`${s.name}/ui`]));this.uiDev=this.uiDevFactory({packageNames:e.map(s=>s.packageName),cwd:f.cwd(),concurrency:Math.max(e.length+4,12),env:n||i?{...n,...i}:void 0,appendLog:s=>{this.sink.write(pn,s)},onLine:({pkg:s,text:a,level:l})=>{let d=o.get(s)??`${s}/ui`;this.sink.write(d,a,{level:l})},onUnexpectedExit:s=>{this.markUiEngineDead(),this.reportEngineDeath("UI dev engine (`turbo run dev`)","frontends stopped reloading",s)}})}formatAppList(e){return e.map(t=>`${t.name}:${t.port}`).join(", ")}assertNoPortConflicts(e){let t=e.filter(o=>o.preferredPort!=null).map(o=>({name:o.name,port:o.preferredPort})),{duplicatePorts:n,conflictingApps:i}=ht(t);if(n.length!==0)throw this.renderer.log(`\u26A0\uFE0F Port conflict detected! ${n.join(", ")}`,"error"),this.renderer.log(`Conflicting apps: ${this.formatAppList(i)}`,"error"),this.renderer.log("\n\u{1F4A1} Tip: give each app a distinct port via `{APP}_PORT` env (e.g. `CLIENT_PORT=`,","error"),this.renderer.log(" `SEARCH_ENGINE_PORT=`) or `dev.<app>.port` in infra-kit.json; or run a subset with","error"),this.renderer.log(" `--app=<name>,<name>`.\n","error"),new Error(`Port conflict detected: ${n.join(", ")}`)}async buildApps(e,t){let i=`pnpm exec turbo run build ${e.map(o=>`--filter=${o.packageName}`).join(" ")} --env-mode=loose --output-logs=errors-only --no-update-notifier${t?" --force":""}`;try{await this.runBuild(i,this.renderer.logFn),this.renderer.narrate("\u2705 Build complete")}catch(o){this.renderer.log(`\u274C Build failed: ${String(o)}`,"error"),o instanceof Error&&o.message&&this.renderer.log(` ${o.message}`,"error");let s=o;throw s.stdout&&this.renderer.log(` stdout: ${s.stdout.trim()}`,"error"),s.stderr&&this.renderer.log(` stderr: ${s.stderr.trim()}`,"error"),o}}async startAllApps(e){await Promise.all(e.map(async t=>{try{let n=await this.startOneApp(t);n&&this.appServers.push({app:t,...n,startedAt:Date.now(),restarts:0})}catch(n){this.renderer.log(`\u274C Failed to start ${t.name}: ${String(n)}`,"error"),this.failedApps.push({app:t,reason:Ln(n)})}}))}async ensureProxy(){let e=this.proxy.binPath();if(e==null||!await this.proxy.isAvailable())throw new Error("infra-kit dev: portless is not installed, so no dev URL can resolve. It ships as a dependency of infra-kit \u2014 reinstall with `pnpm install`.");if(!await this.proxy.isProxyServing(this.proxyPort,!0))throw new Error(`infra-kit dev: no portless daemon is serving HTTPS on :${this.proxyPort}, so no dev URL can resolve. Install it once (this is the only step that needs root):
33
- ${Q(["service","install"],{sudo:!0,bin:e})}
25
+ `,a=lt.byteLength(s);if((this.bytes.get(e)??0)+a>this.maxBytes){this.capped.add(e),this.writeRaw(o,e,`[capped] ${pt(e)} hit ${this.maxBytes} bytes; further lines dropped (likely a logging loop)
26
+ `);return}this.writeRaw(o,e,s)}writeRaw(e,t,n){try{y.writeSync(e,n),this.bytes.set(t,(this.bytes.get(t)??0)+lt.byteLength(n))}catch{}}statsFor(e){return this.counters.get(e)??ut()}services(){return[...this.fds.keys()]}close(){if(!this.closed){this.closed=!0;for(let e of this.fds.values())try{y.closeSync(e)}catch{}this.fds.clear()}}};import ce from"node:process";import Lr from"node:util";var de={log:"info",info:"info",debug:"debug",trace:"debug",warn:"warn",error:"error"},gt=({sink:r,fallbackService:e,currentService:t})=>{let n=!0,i=()=>t()??e,o=(p,d)=>{r.write(i(),p,{level:d})},s={};for(let p of Object.keys(de))s[p]=console[p],console[p]=(...d)=>{if(!n){s[p](...d);return}o(Lr.format(...d),de[p])};let a=(p,d)=>{let g=p.write.bind(p),u="",m=()=>{u!==""&&(r.write(i(),u,{level:d}),u="")};return p.write=((w,...I)=>{if(!n||typeof w!="string")return g(w,...I);u+=w;let O=u.split(`
27
+ `);u=O.pop()??"";for(let S of O)S!==""&&r.write(i(),S,{level:d});u.length>8192&&m();let b=I.find(S=>typeof S=="function");return typeof b=="function"&&ce.nextTick(b),!0}),()=>{m(),Reflect.deleteProperty(p,"write")}},l=a(ce.stdout,"info"),c=a(ce.stderr,"warn");return{uninstall:()=>{if(n){n=!1,l(),c();for(let p of Object.keys(de))console[p]=s[p]}}}};var Nr="/api/v1";function ht(r){if(r==null||r==="")return;let e=parseInt(r.trim().replace(/^["']|["']$/g,""),10);return Number.isNaN(e)?void 0:e}function ft(r,e,t){let i=`${r.replace(/-/g,"_").toUpperCase()}_PORT`,o=ht(e[i]);if(o!=null)return o;let s=ht(e.PORT);return s??t[r]?.port??void 0}function mt(r,e){return e[r]?.prefixUrl??Nr}function vt(r){let e=r.map(i=>i.port),t=e.filter((i,o)=>e.indexOf(i)!==o),n=r.filter(i=>t.includes(i.port));return{duplicatePorts:t,conflictingApps:n}}import{Logger as Ir}from"@aws-lambda-powertools/logger";import Or from"fastify";import*as yt from"node:fs";import*as N from"node:path";import ge from"node:process";import{pathToFileURL as _r}from"node:url";import{parse as Ur}from"yaml";var Fr=r=>r?.code==="EADDRINUSE",Mr=3e4,Hr=()=>{let r=Number.parseInt(ge.env.DEV_SERVER_TIMEOUT_MS??"",10);return Number.isNaN(r)?Mr:r},wt=()=>ge.env.DEV_SERVER_REQUEST_LOG==="1",J=class{constructor(e){this.serverConfig=e;this.importCacheBust=`${Date.now()}`,this.logger=new Ir({serviceName:"LocalServer",logLevel:"DEBUG"}),this.serverConfig.prefixUrl=this.serverConfig.prefixUrl??"",this.server=Or({logger:!1}),this.server.addHook("onRequest",async(n,i)=>{let o=this.serverConfig.serviceTag;o!=null&&ot(o),i.header("Access-Control-Allow-Origin","*"),i.header("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),i.header("Access-Control-Allow-Headers","Content-Type, Authorization, X-Requested-With"),n.method==="OPTIONS"&&i.status(204).send()});let t=this.serverConfig.onRequestLog;(wt()||t)&&this.server.addHook("onResponse",async(n,i)=>{let o=Math.round(i.elapsedTime),s=n.url.split("?")[0]??n.url;t?.({method:n.method,path:s,status:i.statusCode,ms:o}),wt()&&ge.stdout.write(`${n.method} ${n.url} \u2192 ${i.statusCode} ${o}ms
28
+ `)})}serverConfig;importCacheBust;logger;server;controllers={};registeredRouteKeys=new Set;getRegisteredRoutes(){return[...this.registeredRouteKeys].sort()}async start(){this.registerHealthRoute(),await Promise.all(this.loadRoutes());let e=await this.listenWithFallback();return this.serverConfig.port=e,this.logger.info(`Server listening on http://127.0.0.1:${e}`,{address:`http://127.0.0.1:${e}`}),e}async listenWithFallback(){let e=this.serverConfig.port;if(e!=null)try{return await this.server.listen({port:e,host:"127.0.0.1"}),this.readBoundPort()}catch(t){if(!Fr(t))throw t}return await this.server.listen({port:0,host:"127.0.0.1"}),this.readBoundPort()}readBoundPort(){let e=this.server.server.address();if(e==null||typeof e=="string")throw new Error("Server address unavailable after listen()");return e.port}async close(){let e=this.server.server;typeof e.closeAllConnections=="function"&&e.closeAllConnections(),await this.server.close()}registerHealthRoute(){this.server.route({method:"GET",url:"/__health",handler:(e,t)=>t.code(200).send({status:"ok",app:this.serverConfig.appName??null,port:this.serverConfig.port})})}loadRoutes(){let e=N.join(this.serverConfig.controllersPath,"serverless.yml"),t=yt.readFileSync(e,"utf8"),n=Ur(t),i=[];if(!n?.functions)return i;for(let o of Object.values(n.functions))if(o?.events?.length)for(let s of o.events){let a=s?.http;a&&i.push(this.defineRoute(a,o))}return i}async defineRoute(e,t){let n=e.path.toString();n=n.replaceAll("{",":").replaceAll("}","");let i=N.posix.join(this.serverConfig.prefixUrl??"",n);i=i[0]==="/"?i:`/${i}`;let o=["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS"],s=String(e.method).toUpperCase();if(!o.includes(s))throw new Error(`Invalid HTTP method: "${e.method}" for URL: ${i}`);let a=`${s} ${i}`;if(this.registeredRouteKeys.has(a))throw new Error(`Duplicate route: ${a}`);this.registeredRouteKeys.add(a);let c=(t.handler??"").split("."),p=c[0]??"",d=c[1]??"",g=N.join(this.serverConfig.controllersPath,`${p}.js`),u=_r(g);u.searchParams.set("v",this.importCacheBust);let m=this.serverConfig.serviceTag,w=async()=>await import(u.href),I=m==null?await w():await it(m,w);this.controllers[a]={action:I,handler:d};let O=this.logger.createChild({serviceName:"RequestLogger"});this.server.route({method:s,url:i,handler:async(b,S)=>{let _=this.controllers[a];if(!_)throw new Error(`No controller for ${a}`);let we=_.action[_.handler];if(!we)throw new Error(`No handler ${_.handler} for ${i}`);let X=await we(this.getEventObj(b.body,b.query,b.params,b.headers,s,i),this.getContext(),O),Nt=JSON.parse(X.body);return S.headers(X.headers??{}),S.code(X?.statusCode??500).send(Nt)}})}getEventObj(e,t,n,i,o="",s=""){let a={body:e?JSON.stringify(e):null,headers:i??{},multiValueHeaders:{},httpMethod:o,isBase64Encoded:!1,path:s,pathParameters:n??null,queryStringParameters:t??null,multiValueQueryStringParameters:null,stageVariables:null,requestContext:{accountId:"",apiId:"",authorizer:void 0,protocol:"",httpMethod:o,identity:{accessKey:null,accountId:null,apiKey:null,apiKeyId:null,caller:null,clientCert:null,cognitoAuthenticationProvider:null,cognitoAuthenticationType:null,cognitoIdentityId:null,cognitoIdentityPoolId:null,principalOrgId:null,sourceIp:"devIp",user:null,userAgent:null,userArn:null},path:s,stage:"",requestId:"",requestTimeEpoch:0,resourceId:"",resourcePath:s},resource:s};return a.source="aws.events",a}getContext(){let e=Date.now(),t=Hr(),n=new Date().toISOString().split("T")[0]??"";return{callbackWaitsForEmptyEventLoop:!1,functionName:"local-dev",functionVersion:"1.0.0",invokedFunctionArn:"arn:aws:lambda:local:000000000000:function:local-dev",memoryLimitInMB:"1024",awsRequestId:`local-${Date.now()}`,logGroupName:"/aws/lambda/local-dev",logStreamName:`${n}/local`,getRemainingTimeInMillis:()=>Math.max(0,t-(Date.now()-e)),done:(i,o)=>{},fail:i=>{},succeed:i=>{}}}};import{spawn as jr}from"node:child_process";import*as bt from"node:fs";var Wr=(r,e)=>[...r.map(t=>`--filter=...${t}`),...e.map(t=>`--filter=${t}^...`)],St=({depInclusive:r,depClosure:e,cwd:t,logFile:n,onUnexpectedExit:i})=>{let o=Wr(r,e),s=bt.openSync(n,"a"),a=jr("pnpm",["exec","turbo","watch","build",...o,"--continue=dependencies-successful","--env-mode=loose"],{cwd:t,detached:!0,stdio:["ignore",s,s]});return M(a,void 0,i)};import{spawn as Br}from"node:child_process";import Gr from"node:process";var Vr=[/^error\b/i,/^[✘✖×]/,/^\[vite\][^\n]*\berror\b/i,/^\w*Error: /,/\berror TS\d+\b/,/^Failed to (?:resolve|load url|parse|compile)\b/i,/^(?:ENOENT|EADDRINUSE|ECONNREFUSED)\b/,/pre-transform error/i,/\b(?:build|transform|compilation) failed\b/i],Jr=r=>Vr.some(e=>e.test(r))?"error":"info",Kr=/\u001B\][\s\S]*?(?:\u0007|\u001B\\)/g,qr=/\u001B\[[0-9;?]*[\u0020-\u002F]*[\u0040-\u007E]/g,zr=/[\u0000-\u0008\u000B-\u001F\u007F]/g,Xr=r=>r.replace(Kr,"").replace(qr,"").replace(zr,""),Yr=/^([^\s:]+):dev:[ \t]?/,Qr=r=>/^cache (?:bypass|hit|miss)/.test(r)||r.startsWith("$ "),Zr=r=>{let e=Xr(r).trimEnd(),t=Yr.exec(e);if(t==null)return null;let n=e.slice(t[0].length);return n.trim()===""||Qr(n.trim())?null:{pkg:t[1],text:n,level:Jr(n)}},en=64*1024,Pt=(r,e)=>{if(r==null)return;let t="",n=i=>{let o=Zr(i);o!=null&&e.onLine?.(o)};r.setEncoding("utf-8"),r.on("data",i=>{e.appendLog?.(i),t+=i;let o=t.split(`
29
+ `);t=o.pop()??"";for(let s of o)n(s);t.length>en&&(n(t),t="")}),r.on("end",()=>{t!==""&&(n(t),t="")}),r.on("error",i=>{e.appendLog?.(`[infra-kit] ui dev stream error: ${i.message}
30
+ `)})},Dt=({packageNames:r,cwd:e,concurrency:t,env:n,appendLog:i,onLine:o,onUnexpectedExit:s})=>{let a=r.map(c=>`--filter=${c}`),l=Br("pnpm",["exec","turbo","run","dev",...a,`--concurrency=${t}`,"--env-mode=loose","--only","--output-logs=new-only","--no-update-notifier","--ui=stream"],{cwd:e,detached:!0,stdio:["ignore","pipe","pipe"],env:{...Gr.env,...n}});return Pt(l.stdout,{appendLog:i,onLine:o}),Pt(l.stderr,{appendLog:i,onLine:o}),M(l,void 0,s)};var q="runner",dn="turbo",gn="watch";function K(r){let e=pn.homedir();return r===e||r.startsWith(`${e}${v.sep}`)?`~${r.slice(e.length)}`:r}function At(r){return r.map(e=>e.packageName).join(", ")}var hn=cn.promisify(an),fn=async(r,e)=>{try{let{stderr:t}=await hn(r);t&&e&&e(` (build) ${t.trim()}`,"debug"),t&&!e&&console.error("stderr:",t)}catch(t){let n=t;throw e&&(n.stdout||n.stderr)&&(n.stdout&&e(` stdout: ${n.stdout.trim()}`,"error"),n.stderr&&e(` stderr: ${n.stderr.trim()}`,"error")),t}},kt=null;function Et(r){kt?.write(q,r)}var mn=()=>new Promise((r,e)=>{let t=un.createServer();t.unref(),t.on("error",e),t.listen(0,"127.0.0.1",()=>{let n=t.address(),i=typeof n=="object"&&n!==null?n.port:0;t.close(()=>r(i))})}),vn=r=>typeof r=="object",z=async r=>(await r.body?.cancel(),{kind:"foreign",status:r.status,contentType:r.headers.get("content-type")}),wn=(r,e)=>{let t=e.contentType?.split(";")[0]?.trim(),n=t==null||t===""?`${e.status}`:`${e.status} ${t}`;return`port ${r} answered ${n}, not vite's ping \u2014 liveness cannot be verified`},yn=1500,Rt={accept:"text/x-vite-ping"},bn=r=>r.kind==="api"?`http://127.0.0.1:${r.port}/__health`:`http://127.0.0.1:${r.port}/`,Sn=(r,e)=>{try{return new URL(r,e)}catch{return null}},Pn=async(r,e)=>{let t=await fetch(r,{signal:e});return t.ok?(await t.body?.cancel(),"ok"):z(t)},Dn=async(r,e)=>{let t=await fetch(r,{headers:Rt,redirect:"manual",signal:e});if(t.status===204)return"ok";if(t.status<300||t.status>=400)return z(t);let n=t.headers.get("location"),i=n==null?null:Sn(n,r);if(i==null||i.origin!==new URL(r).origin)return z(t);await t.body?.cancel();let o=await fetch(i,{headers:Rt,redirect:"manual",signal:e});return o.status!==204?z(o):(await o.body?.cancel(),"ok")},xn=async r=>{let e=bn(r),t=AbortSignal.timeout(yn);try{return r.kind==="api"?await Pn(e,t):await Dn(e,t)}catch{return"refused"}},An=[{name:"@slip-stream-kit/vite",floor:"0.1.134"},{name:"@slip-stream-kit/config",floor:"0.1.134"},{name:"infra-kit",floor:"0.1.132"}],Rn=(r,e)=>{let t=o=>o.split(".").map(s=>Number.parseInt(s,10)||0),n=t(r),i=t(e);for(let o=0;o<Math.max(n.length,i.length);o+=1){let s=n[o]??0,a=i[o]??0;if(s!==a)return s<a}return!1},kn=r=>{let e=[r];try{for(let t of h.readdirSync(v.join(r,"apps"),{withFileTypes:!0}))if(t.isDirectory())for(let n of["api","ui"])e.push(v.join(r,"apps",t.name,n))}catch{}return e},En=(r,e)=>{try{let t=JSON.parse(h.readFileSync(v.join(r,"package.json"),"utf-8"));return["dependencies","devDependencies"].some(n=>t[n]?.[e]!=null)}catch{return!1}},Tn=(r,e,t)=>{let n=t.split("/"),i=e;for(;;){let o=v.join(i,"node_modules",...n);if(h.existsSync(o))return o;let s=v.dirname(i);if(i===r||s===i)return;i=s}},Cn=(r,e)=>{try{let t=h.realpathSync(e),n=h.realpathSync(r);return t.startsWith(n+v.sep)&&!t.includes(`${v.sep}node_modules${v.sep}`)}catch{return!1}},$n=r=>{try{return h.realpathSync(r)}catch{return r}},Ln=(r,e,t,n)=>{if(Cn(r,n))return;let i;try{let o=JSON.parse(h.readFileSync(v.join(n,"package.json"),"utf-8"));if(typeof o.version!="string")throw new Error("no version field");i=o.version}catch{throw new Error(`infra-kit dev: could not read the version of the pinned \`${e}\` helper (${n}). Refusing to start rather than risk proxying plain HTTP at a TLS listener. Run \`pnpm install\`.`)}if(Rn(i,t))throw new Error(`infra-kit dev: this repo pins ${e} ${i}, but dev URLs are now HTTPS and the \`infraKitDev\` helper only understands them from ${t}. An older helper would proxy plain HTTP at a TLS listener \u2014 silently. Bump the dependency:
31
+ pnpm add -D ${e}@^${t}`)},Nn=r=>{let e=kn(r);for(let{name:t,floor:n}of An){let i=e.filter(s=>En(s,t)),o=new Map;for(let s of[...i,r]){let a=Tn(r,s,t);a&&o.set($n(a),a)}if(o.size===0){if(i.length===0)continue;throw new Error(`infra-kit dev: ${i[0]}/package.json depends on ${t} but it does not resolve from there, so the \`infraKitDev\` helper version cannot be verified. Run \`pnpm install\`.`)}for(let s of o.values())Ln(r,t,n,s)}},he=r=>{try{let e=ln("git",["rev-parse","--abbrev-ref","HEAD"],{cwd:r,encoding:"utf-8"}).trim(),t=on(e);return t===""?xt:t}catch{return xt}},In=r=>{let t=(r instanceof Error?r.message:String(r)).split(`
32
+ `)[0]?.trim()??"";return t===""?"unknown error (see the log)":t},fe=class r{monorepoRoot;devContextDir;appServers=[];reqTimes=new Map;lastSummary=null;readyAt=0;watchDebounceTimers=new Map;watcher=null;static WATCH_DEBOUNCE_MS=400;restartWorkChain=Promise.resolve();static PORT_RELEASE_DELAY_MS=200;livenessTimer=null;health=new Map;firstErrorLogged=new Set;uiTagByPackage=new Map;static LIVENESS_INTERVAL_MS=5e3;static LIVENESS_FAILURE_THRESHOLD=2;static NEVER_UP_DOWN_THRESHOLD=6;options;runBuild;turboWatchFactory;turboWatch=null;uiDevFactory;uiDev=null;sink;intercept;dryRunner;failedApps=[];degradedRoutes=[];launchedUis=[];proxyRoutes=[];renderer;healthProbe;proxy;proxyPort=Re;registeredAliases=new Set;uiPortMap={};shuttingDown=!1;closureMap=null;closureBuild=Promise.resolve();teardown=null;stage="idle";constructor(e={},t=fn,n=St,i=Dt,o,s,a=xn,l=Te(),c){this.options=e,this.runBuild=t,this.turboWatchFactory=n,this.uiDevFactory=i,this.dryRunner=o,this.proxy=l,this.sink=c??new V,kt=this.sink,this.intercept=Tt(this.options)?gt({sink:this.sink,fallbackService:q,currentService:W}):null,this.renderer=s??new Ie({appendLog:Et,verbose:this.options.verbose??!1}),this.healthProbe=a,this.devContextDir=v.join(f.cwd(),".infra-kit","dev-context"),this.monorepoRoot=E(f.cwd()),(f.env.DOPPLER_PROJECT!=null||f.env.DOPPLER_ENVIRONMENT!=null)&&this.renderer.log("\u{1F510} Doppler env detected (DOPPLER_PROJECT / DOPPLER_ENVIRONMENT)","debug")}discoverApiApps(e){return U(this.monorepoRoot).map(t=>({...t,preferredPort:this.resolvePreferredPort(t.name,e),prefixUrl:this.resolvePrefixUrl(t.name,e),watchDeps:!0}))}async loadDevConfig(){try{return(await Y()).dev??{}}catch{return{}}}normalizeAppInclude(){return F(this.options.include)}resolvePreferredPort(e,t){return ft(e,f.env,t)}resolvePrefixUrl(e,t){return mt(e,t)}async loadDevPresets(){try{return(await Y()).devServersPresets??{}}catch{return{}}}resolvePresetDef(e){if(this.options.presetDef!=null)return this.options.presetDef;let t=this.options.preset;if(t==null)return{};let n=e[t];if(!n){let i=Object.keys(e);throw new Error(`Unknown dev preset "${t}". Available: ${i.length>0?i.join(", "):"(none defined in devServersPresets)"}`)}return n}async start(){let e=Date.now(),t=this.normalizeAppInclude(),n=this.options.watch??!1,i=await this.loadDevConfig();f.env.POWERTOOLS_DEV??="true",f.env.LOG_LEVEL??="DEBUG",this.renderer.narrate("\u{1F680} Starting Development Server Runner"),n&&this.renderer.narrate("\u{1F440} Watch mode: will rebuild and restart on file save");let{apps:o,uiApps:s,apiAppsAll:a,uiAppsAll:l,wantedLocalPkgs:c,presetProxy:p}=await this.resolveRunPlan(i,t);if(o.length===0&&s.length===0){this.renderer.log("\u26A0\uFE0F No API or UI apps to run for this preset","warn");return}await this.bringUpProxy(o),await this.buildAll(o,s,n),o.length>0&&(this.renderer.bootStep("starting servers"),await this.startAllApps(o),this.renderer.narrate(this.failedApps.length===0?"\u{1F389} All servers started!":`\u26A0\uFE0F ${this.appServers.length}/${o.length} servers started \u2014 ${this.failedApps.length} failed`),this.renderer.narrate(`\u{1F4DD} Logs \u2192 ${K(this.sink.dir)} (one file per service)`));let d=Ae({preset:this.options.preset,running:[...o.map(g=>`${g.name}/api`),...s.map(g=>`${g.name}/ui`)],discovered:[...a.map(g=>`${g.name}/api`),...l.map(g=>`${g.name}/ui`)]});if(this.degradedRoutes=await this.collectDegradedRoutes(s,c,p),this.degradedRoutes.length>0&&!n)throw new Error(nt(this.degradedRoutes,d));if(await this.printReady(o,s,e,d),this.options.routes&&this.printRouteDump(),this.appServers.length===0&&s.length===0&&this.failedApps.length>0)throw new Error(`infra-kit dev: no app started (${this.failedApps.length} of ${o.length} failed). First failure: ${this.failedApps[0]?.reason??"unknown"}`);this.armWatch(o,s,n),s.length>0&&this.startUiDev(s),this.startLivenessMonitor()}async resolveRunPlan(e,t){let n=this.discoverApiApps(e),i=ye(this.monorepoRoot),o=xe(this.resolvePresetDef(await this.loadDevPresets()),{api:n.map(u=>u.name),ui:i.map(u=>u.name)});o.unmatched.length>0&&this.renderer.log(`\u26A0\uFE0F Preset targets not found (skipped): ${o.unmatched.join(", ")}`,"warn");let s=new Set(o.targets.filter(u=>u.part==="api").map(u=>u.app)),a=new Set(o.targets.filter(u=>u.part==="ui").map(u=>u.app)),l=u=>!t||t.includes(u),c=new Map(o.targets.filter(u=>u.part==="api").map(u=>[u.app,u.watchDeps])),p=n.filter(u=>s.has(u.name)&&l(u.name)).map(u=>({...u,watchDeps:c.get(u.name)??u.watchDeps})),d=i.filter(u=>a.has(u.name)&&l(u.name)),g=new Set(n.filter(u=>s.has(u.name)).map(u=>u.packageName));return{apps:p,uiApps:d,apiAppsAll:n,uiAppsAll:i,wantedLocalPkgs:g,presetProxy:o.proxy}}async collectDegradedRoutes(e,t,n){if(e.length===0)return[];let i=[];for(let o of e){let s=await rn(o.path).catch(()=>{});if(!s?.proxy)continue;let a=n[o.name]??{},l=Object.fromEntries(Object.entries(s.proxy.routes).map(([c,p])=>[c,{...p,pinnedLocal:a[c]==="local"}]));i.push({app:o.name,routes:l,cloudTemplate:s.proxy.templates.cloud})}return this.launchedUis=i,et({uis:i,wanted:t,running:new Set(this.appServers.map(({app:o})=>o.packageName)),reasons:new Map(this.failedApps.map(({app:o,reason:s})=>[o.packageName,{app:o.name,reason:s}])),env:f.env[Q]})}proxiesFor(e){let t=this.proxyRoutes.filter(n=>n.uiApp===e).map(n=>({route:n.route,source:n.source,target:n.target}));return t.length>0?t:void 0}async bringUpProxy(e){Nn(E(f.cwd())),await this.ensureProxy(),e.length>0&&this.assertNoPortConflicts(e)}async buildAll(e,t,n){let i=[e.length>0?`building ${At(e)}`:"",t.length>0?`warming ${At(t)}`:""].filter(Boolean).join(" \xB7 ");this.renderer.bootStep(i),e.length>0&&await this.buildApps(e,n),t.length>0&&await this.buildUiApps(t)}armWatch(e,t,n){n&&(this.appServers.length>0||t.length>0)&&(this.setupWatch(e,t),this.closureBuild=this.buildClosureMapSafe(e).then(i=>{this.closureMap=i}))}async buildUiApps(e){let t=e.map(n=>`--filter=${n.packageName}^...`).join(" ");try{await this.runBuild(`pnpm exec turbo run build ${t} --env-mode=loose --output-logs=errors-only --no-update-notifier`,this.renderer.logFn),this.renderer.narrate("\u2705 UI deps built")}catch(n){this.renderer.log(`\u26A0\uFE0F UI dep build failed (continuing; vite will report unresolved deps): ${String(n)}`,"warn")}}startUiDev(e){let t=e.map(s=>s.name).join(", ");this.renderer.narrate(`\u{1F3A8} Starting ${e.length} UI dev server(s) via \`turbo run dev\`: ${t}`),this.renderer.narrate(" (framework output is routed into the live tail; full detail in the runner log)");let n=Object.keys(this.uiPortMap).length>0?{INFRA_KIT_UI_PORTS:JSON.stringify(this.uiPortMap)}:void 0,i=f.env.NODE_EXTRA_CA_CERTS==null&&h.existsSync(ee())?{NODE_EXTRA_CA_CERTS:ee()}:void 0,o=new Map(e.map(s=>[s.packageName,`${s.name}/ui`]));this.uiDev=this.uiDevFactory({packageNames:e.map(s=>s.packageName),cwd:f.cwd(),concurrency:Math.max(e.length+4,12),env:n||i?{...n,...i}:void 0,appendLog:s=>{this.sink.write(dn,s)},onLine:({pkg:s,text:a,level:l})=>{let c=o.get(s)??`${s}/ui`;this.sink.write(c,a,{level:l})},onUnexpectedExit:s=>{this.markUiEngineDead(),this.reportEngineDeath("UI dev engine (`turbo run dev`)","frontends stopped reloading",s)}})}formatAppList(e){return e.map(t=>`${t.name}:${t.port}`).join(", ")}assertNoPortConflicts(e){let t=e.filter(o=>o.preferredPort!=null).map(o=>({name:o.name,port:o.preferredPort})),{duplicatePorts:n,conflictingApps:i}=vt(t);if(n.length!==0)throw this.renderer.log(`\u26A0\uFE0F Port conflict detected! ${n.join(", ")}`,"error"),this.renderer.log(`Conflicting apps: ${this.formatAppList(i)}`,"error"),this.renderer.log("\n\u{1F4A1} Tip: give each app a distinct port via `{APP}_PORT` env (e.g. `CLIENT_PORT=`,","error"),this.renderer.log(" `SEARCH_ENGINE_PORT=`) or `dev.<app>.port` in infra-kit.json; or run a subset with","error"),this.renderer.log(" `--app=<name>,<name>`.\n","error"),new Error(`Port conflict detected: ${n.join(", ")}`)}async buildApps(e,t){let i=`pnpm exec turbo run build ${e.map(o=>`--filter=${o.packageName}`).join(" ")} --env-mode=loose --output-logs=errors-only --no-update-notifier${t?" --force":""}`;try{await this.runBuild(i,this.renderer.logFn),this.renderer.narrate("\u2705 Build complete")}catch(o){this.renderer.log(`\u274C Build failed: ${String(o)}`,"error"),o instanceof Error&&o.message&&this.renderer.log(` ${o.message}`,"error");let s=o;throw s.stdout&&this.renderer.log(` stdout: ${s.stdout.trim()}`,"error"),s.stderr&&this.renderer.log(` stderr: ${s.stderr.trim()}`,"error"),o}}async startAllApps(e){await Promise.all(e.map(async t=>{try{let n=await this.startOneApp(t);n&&this.appServers.push({app:t,...n,startedAt:Date.now(),restarts:0})}catch(n){this.renderer.log(`\u274C Failed to start ${t.name}: ${String(n)}`,"error"),this.failedApps.push({app:t,reason:In(n)})}}))}async ensureProxy(){let e=this.proxy.binPath();if(e==null||!await this.proxy.isAvailable())throw new Error("infra-kit dev: portless is not installed, so no dev URL can resolve. It ships as a dependency of infra-kit \u2014 reinstall with `pnpm install`.");if(!await this.proxy.isProxyServing(this.proxyPort,!0))throw new Error(`infra-kit dev: no portless daemon is serving HTTPS on :${this.proxyPort}, so no dev URL can resolve. Install it once (this is the only step that needs root):
33
+ ${Z(["service","install"],{sudo:!0,bin:e})}
34
34
  Then trust its local CA (no sudo needed):
35
- ${Q(["trust"],{bin:e})}
36
- \`infra-kit doctor\` checks both.`)}async registerAppAlias(e,t,n){let i=ge(t),o=tn(e);if(o==="")throw new Error(`infra-kit dev: package name "${e}" has no letters or digits to build a hostname from.`);let s=`${i}.${o}`;if(!await this.proxy.registerAlias(s,n))throw new Error(`infra-kit dev: portless refused the alias "${s}" \u2192 127.0.0.1:${n}.`);return this.registeredAliases.add(s),`${s}.localhost`}async startOneApp(e){this.renderer.narrate(`\u{1F504} Starting ${e.name}...`);let t=new J({controllersPath:e.path,prefixUrl:e.prefixUrl,port:e.preferredPort,appName:e.name,serviceTag:`${e.name}/api`,onRequestLog:({method:o,path:s,status:a,ms:l})=>{if(s==="/__health")return;let d=`${e.name}/api`,u=`${o} ${s} ${a} ${l}ms`;this.sink.write(d,u,{level:a>=500?"error":"info"});let c=this.reqTimes.get(d);c?c.push(Date.now()):this.reqTimes.set(d,[Date.now()])}}),n=await t.start(),i;try{i=await this.registerAppAlias(e.packageName,e.path,n)}catch(o){throw await t.close().catch(()=>{}),o}try{this.writeDevContextFragment(e,n,i)}catch(o){this.renderer.log(`\u26A0\uFE0F Failed to write dev-context fragment for ${e.name}: ${String(o)}`,"warn")}return this.renderer.narrate(`\u2705 ${e.name} started on port ${n}`),{server:t,boundPort:n,alias:i}}writeDevContextFragment(e,t,n){let i={v:Zr,package:e.packageName,port:t,pid:f.pid,writtenAt:Date.now(),release:ge(e.path),alias:n,origin:`https://${n}`},o=m.join(this.devContextDir,`${e.name}.json`),s=m.join(this.devContextDir,`${e.name}.json.${f.pid}.tmp`);h.mkdirSync(this.devContextDir,{recursive:!0}),h.writeFileSync(s,JSON.stringify(i,null,2)),h.renameSync(s,o)}removeDevContextFragment(e){h.rmSync(m.join(this.devContextDir,`${e.name}.json`),{force:!0})}scheduleRestartWork(e){let t=this.restartWorkChain.then(()=>e(),()=>e());return this.restartWorkChain=t.catch(()=>{}),t}async delayPortRelease(){await new Promise(e=>setTimeout(e,r.PORT_RELEASE_DELAY_MS))}restart(e){return this.shuttingDown?Promise.resolve():this.scheduleRestartWork(()=>this.shuttingDown?Promise.resolve():this.runRestart(e))}resolveRestartTargets(e){return e.map(t=>({idx:this.appServers.findIndex(n=>n.app.name===t.name),app:t})).filter(t=>t.idx>=0||this.isFailedApp(t.app.name))}isFailedApp(e){return this.failedApps.some(t=>t.app.name===e)}promoteRecoveredApp(e,t){let n={app:e,...t,startedAt:Date.now(),restarts:0},i=`${e.name}/api`;this.healthEntry(i,"api"),this.appServers.push(n);let o=this.failedApps.findIndex(s=>s.app.name===e.name);return o>=0&&this.failedApps.splice(o,1),this.lastSummary&&(this.lastSummary={...this.lastSummary,endpoints:[...this.lastSummary.endpoints,{tag:i,url:F({prefixUrl:e.prefixUrl,alias:t.alias}),health:this.healthOf(i)}],failed:(this.lastSummary.failed??[]).filter(s=>s.tag!==i)}),n}async runRestart(e){let t=this.resolveRestartTargets(e);if(t.length===0)return;let n=t.length===1?t[0].app.name:`${t.length} apps`;this.renderer.log(`\u{1F504} Restarting ${n}...`),await Promise.all(t.map(async({idx:a})=>{if(!(a<0))try{await this.appServers[a].server.close()}catch(l){this.renderer.log(` Close warning: ${String(l)}`,"debug")}})),await this.delayPortRelease();let i=await Promise.all(t.map(async({idx:a,app:l})=>{try{let d=await this.startOneApp(l);if(d){if(a<0){let g=this.promoteRecoveredApp(l,d);return this.renderer.log(`\u2705 ${l.name} recovered \u2014 its routes are served locally again`,"info"),{app:l,entry:g}}let u=this.appServers[a],c={app:l,...d,startedAt:Date.now(),restarts:(u?.restarts??0)+1};return this.appServers[a]=c,{app:l,entry:c}}return{app:l,entry:null}}catch(d){return this.renderer.log(`\u274C Failed to ${a<0?"start":"restart"} ${l.name}: ${String(d)}`,"error"),{app:l,entry:null}}})),o=await Promise.all(i.map(async({app:a,entry:l})=>{let d=`${a.name}/api`;if(l==null)return this.markDown(d,"api"),this.refreshStatus(),{label:`${a.name} \u25CF down`,healthy:!1};let u={tag:d,port:l.boundPort,kind:"api"},c=await this.healthProbe(u);this.recordProbe(u,c),this.refreshStatus();let g=c==="ok";return{label:`${a.name}:${l.boundPort} ${g?"\u25CF up":"\u25CF down"}`,healthy:g}})),s=o.every(a=>a.healthy);this.renderer.log(`${s?"\u2705":"\u26A0\uFE0F "} Restarted ${o.map(a=>a.label).join(", ")}`)}async buildClosureMapSafe(e){try{return await ze(this.monorepoRoot,e,this.dryRunner)}catch(t){return this.renderer.log(`\u26A0\uFE0F Dependency-closure map unavailable (${String(t)}); package changes restart all apps`,"warn"),null}}reportEngineDeath(e,t,n){this.shuttingDown||this.renderer.log(`\u26A0\uFE0F ${e} ${n} \u2014 ${t}. Restart \`infra-kit dev\`.`,"warn")}markUiEngineDead(){if(!this.shuttingDown){for(let{tag:e,kind:t}of this.uiTargets())this.healthEntry(e,t).dead=!0;this.refreshStatus()}}setupWatch(e,t){this.turboWatch=this.turboWatchFactory({depInclusive:e.map(l=>l.packageName),depClosure:t.map(l=>l.packageName),cwd:f.cwd(),logFile:this.sink.pathFor(cn),onUnexpectedExit:l=>{this.reportEngineDeath("Watch engine (`turbo watch build`)","file saves no longer rebuild",l)}}),this.renderer.narrate("\u{1F440} Watch mode: started `turbo watch build` engine; watching dist output");let n=be(e),i=T(this.monorepoRoot),o=[...n,...i];if(o.length===0){this.renderer.log("\u26A0\uFE0F No app or package dist directories found to watch (were they built?)","warn");return}let s=f.env.DEV_SERVER_CHOKIDAR_POLL==="1",a=nn.watch(o,{ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:200,pollInterval:100},ignored:l=>l.endsWith(".tsbuildinfo")||l.endsWith(".map"),...s?{usePolling:!0,interval:400}:{}});this.watcher=a,s&&this.renderer.log("\u{1F440} chokidar: usePolling enabled (DEV_SERVER_CHOKIDAR_POLL=1)","debug"),a.on("change",l=>{this.handleDistChange(l,e,n,i)}),this.renderer.narrate(`\u{1F440} Watching ${n.length} app dist + ${i.length} package dist dir(s) for changes...`)}handleDistChange(e,t,n,i){this.renderer.log(`\u{1F440} dist change detected: ${e}`,"debug");let o=Se(e,n,i);if(o.kind==="package"){let a=Ye(t,this.closureMap,o.packageDir);if(a===null){this.scheduleDebounced("__packages__",()=>this.restart(t));return}a.length>0&&o.packageDir!==void 0&&this.scheduleDebounced(Xe(o.packageDir),()=>this.restart(a));return}let s=t.find(a=>m.join(a.path,"dist")===o.app);s&&this.scheduleDebounced(s.name,()=>this.restart([s]))}scheduleDebounced(e,t){if(this.shuttingDown)return;let n=this.watchDebounceTimers.get(e);n&&clearTimeout(n);let i=setTimeout(()=>{this.watchDebounceTimers.delete(e),!this.shuttingDown&&t().catch(o=>{this.renderer.log(`Restart error (${e}): ${String(o)}`,"error")})},r.WATCH_DEBOUNCE_MS);this.watchDebounceTimers.set(e,i)}uiHealthEnabled(){return(this.options.uiHealth??!0)&&f.env.INFRA_KIT_NO_UI_HEALTH!=="1"}apiTargets(){return this.appServers.map(({app:e,boundPort:t})=>({tag:`${e.name}/api`,port:t,kind:"api"}))}uiTargets(){return this.uiHealthEnabled()?Object.entries(this.uiPortMap).map(([e,{port:t}])=>({tag:this.uiTagByPackage.get(e)??`${e}/ui`,port:t,kind:"ui"})):[]}healthEntry(e,t){let n=this.health.get(e);if(n)return n;let i={kind:t,failures:0,foreignStreak:0,everUp:!1,dead:!1,unverified:!1};return this.health.set(e,i),i}recordProbe(e,t){let n=this.healthEntry(e.tag,e.kind),i=r.LIVENESS_FAILURE_THRESHOLD;if(t==="ok"){let o=n.failures>=i;n.everUp=!0,n.failures=0,n.foreignStreak=0,n.unverified=!1,o&&this.renderer.log(`\u2705 ${e.tag} recovered`);return}if(fn(t)&&e.kind==="ui"){n.foreignStreak+=1,n.unverified=n.foreignStreak>=i,n.foreignStreak===i&&this.renderer.log(`\u26A0\uFE0F ${e.tag}: ${mn(e.port,t)}`,"warn");return}if(n.foreignStreak=0,n.failures+=1,e.kind==="ui"&&n.failures>=i&&(n.unverified=!1),n.failures===i){let o=e.kind==="api"?"/__health not responding":"not answering vite's ping";this.renderer.log(`\u26A0\uFE0F ${e.tag} unhealthy (${o})`,"warn")}}markDown(e,t){let n=this.healthEntry(e,t);n.dead=!0,n.failures=r.LIVENESS_FAILURE_THRESHOLD,n.foreignStreak=0,n.unverified=!1}healthOf(e){let t=this.health.get(e);return t==null?"unknown":t.unverified?"unverified":t.everUp?t.failures>=r.LIVENESS_FAILURE_THRESHOLD?"down":"ok":this.neverUpState(t)}neverUpState(e){return e.kind==="api"||e.dead||e.failures>=r.NEVER_UP_DOWN_THRESHOLD?"down":"starting"}startLivenessMonitor(){this.scheduleLivenessTick()}scheduleLivenessTick(){let e=this.options.livenessIntervalMs??r.LIVENESS_INTERVAL_MS;this.livenessTimer=setTimeout(()=>{this.livenessTick().finally(()=>{this.shuttingDown||this.scheduleLivenessTick()}).catch(()=>{})},e),this.livenessTimer.unref()}refreshStatus(){let e=this.lastSummary;if(e==null)return;let t=Date.now(),n=new Map(this.appServers.map(i=>[`${i.app.name}/api`,i]));this.pruneRequestWindow(t),this.renderer.refresh?.({...e,sessionUptimeMs:t-this.readyAt,degraded:this.degradedRows(),uiRefs:e.uiRefs.map(i=>({...i,errors:this.announceFirstError(i.tag)})),endpoints:e.endpoints.map(i=>{let o=n.get(i.tag);return{...i,health:this.healthOf(i.tag),uptimeMs:o?t-o.startedAt:void 0,restarts:o?.restarts,rpm:(this.reqTimes.get(i.tag)??[]).length,errors:this.announceFirstError(i.tag)}})})}announceFirstError(e){let{errors:t}=this.sink.statsFor(e);return t>0&&!this.firstErrorLogged.has(e)&&(this.firstErrorLogged.add(e),this.renderer.log(`\u26A0\uFE0F ${e} reported its first error \u2192 ${K(this.sink.pathFor(e))}`,"warn")),t}degradedRows(){if(this.degradedRoutes.length===0)return[];let e=new Set(this.appServers.map(({app:t})=>t.packageName));return this.degradedRoutes.filter(t=>!e.has(t.packageName)).map(t=>({route:t.route,tag:`${t.uiApp}/ui`,fallback:t.fallback,target:t.cloudTarget}))}pruneRequestWindow(e){let t=e-6e4;for(let[n,i]of this.reqTimes)this.reqTimes.set(n,i.filter(o=>o>t))}async livenessTick(){this.shuttingDown||(await Promise.all([...this.apiTargets(),...this.uiTargets()].map(e=>this.probeOne(e))),this.refreshStatus())}async probeOne(e){let t=await this.healthProbe(e);this.shuttingDown||this.recordProbe(e,t)}async printReady(e,t,n,i){let o=Date.now()-n;await Promise.all(this.apiTargets().map(g=>this.probeOne(g)));let s=this.appServers.map(({app:g,alias:p})=>({tag:`${g.name}/api`,url:F({prefixUrl:g.prefixUrl,alias:p}),health:this.healthOf(`${g.name}/api`)}));this.uiPortMap={};let a=[],l=[];for(let g of t){let p=await this.assignUiPort(g),v=`${g.name}/ui`;p!=null?a.push({tag:v,url:F({prefixUrl:"",alias:p.alias}),health:this.seedUiHealth(v)}):l.push({tag:v})}let d=this.options.watch??!1,u=e.length+t.length,c=T(this.monorepoRoot).length;this.lastSummary={target:i,watch:d,release:ge(f.cwd()),elapsedMs:o,endpoints:[...s,...a],uiRefs:l,failed:this.failedApps.map(({app:g,reason:p})=>({tag:`${g.name}/api`,reason:p})),degraded:this.degradedRows(),watchSummary:`${u} app${u===1?"":"s"} \xB7 ${c} package${c===1?"":"s"}`,logPath:K(this.sink.dir),logHref:this.sink.dir},this.readyAt=Date.now(),this.renderer.ready(this.lastSummary),this.refreshStatus()}async assignUiPort(e){if(!e.managedPort)return null;let t;try{t=await hn()}catch{return null}let n=await this.registerAppAlias(e.packageName,e.path,t);return this.uiPortMap[e.packageName]={port:t,alias:n},this.uiTagByPackage.set(e.packageName,`${e.name}/ui`),{port:t,alias:n}}seedUiHealth(e){return this.uiHealthEnabled()?(this.healthEntry(e,"ui"),this.healthOf(e)):"unknown"}printRouteDump(){if(this.appServers.length!==0){this.renderer.log("\u{1F5FA}\uFE0F Registered routes:");for(let{app:e,server:t}of this.appServers){let n=t.getRegisteredRoutes();this.renderer.log(` ${e.name} (${n.length}): ${n.length>0?n.join(", "):"(none)"}`)}}}reportFault(e){this.sink.write(j()??q,e,{level:"error"}),this.renderer.log(e,"error",{tee:!1})}fileFault(e){this.sink.write(j()??q,e,{level:"error"})}get shutdownStage(){return this.stage}shutdown(){return this.teardown!=null?this.teardown:(this.teardown=this.doShutdown(),this.teardown.catch(()=>{}),this.teardown)}async doShutdown(){this.shuttingDown=!0,this.stage="starting",this.renderer.dispose(),this.intercept?.uninstall(),this.renderer.log("\u{1F6D1} Shutting down all servers...");for(let e of this.watchDebounceTimers.values())clearTimeout(e);this.watchDebounceTimers.clear(),this.livenessTimer&&(clearTimeout(this.livenessTimer),this.livenessTimer=null),this.watcher&&(this.stage="watcher.close",await this.watcher.close(),this.watcher=null),this.stage="restartWorkChain",await this.restartWorkChain,this.stage="closureBuild",await this.closureBuild,this.stage="removeAlias",await Promise.all([...this.registeredAliases].map(e=>this.proxy.removeAlias(e))),this.registeredAliases.clear(),this.turboWatch&&(this.stage="turboWatch.kill",await this.turboWatch.kill(),this.turboWatch=null),this.uiDev&&(this.stage="uiDev.kill",await this.uiDev.kill(),this.uiDev=null);for(let{app:e,server:t}of this.appServers){this.stage=`server.close(${e.name})`;try{await t.close()}catch{}this.removeDevContextFragment(e)}this.intercept?.uninstall(),this.renderer.log(`\u2713 dev stopped \xB7 logs \u2192 ${K(this.sink.dir)}`),this.sink.close(),this.stage="done"}},Rt=r=>(r.tty??!!f.stdout.isTTY)&&!r.json,Nn=async r=>{if(!Rt(r))return;let{PersistentInkDevUi:e}=await import("./persistent-ink-dev-ui-TLUJJC2D.js"),{createSafeStream:t}=await import("./safe-stderr-HXDR2DNJ.js");return new e({appendLog:xt,verbose:r.verbose??!1,stdout:t(lt())})};async function Et(r={}){let e=await Nn(r),t=new he(r,void 0,void 0,void 0,void 0,e);try{await t.start()}catch(n){throw await t.shutdown().catch(()=>{}),n}return t}var fe=1,_n=2e4,Un=r=>{if(r!=null){for(let e of r)if(Pe(e)!==null)throw new Error(`infra-kit dev: invalid --target "${e}" (expected "<app>/api" or "<app>/ui").`);return{apps:Object.fromEntries(r.map(e=>[e,{}]))}}},kt=r=>{if(r==null)return null;let e=r.split(",").map(t=>t.trim()).filter(Boolean);return e.length>0?e:null},Tt=r=>({watch:r.watch??!1,include:kt(r.app),preset:r.preset,presetDef:Un(kt(r.target)),cmux:r.cmux??!1,self:r.self??!1,verbose:r.verbose??!1,routes:r.routes??!1,uiHealth:r.uiHealth??!0}),Fn=r=>!r.self||r.include?r:{...r,include:[ye(R.cwd())]},Mn=(r,e)=>{let t=setTimeout(r,e);return t.unref(),()=>{clearTimeout(t)}},Hn=({getRunner:r,forceReap:e=A,exit:t=o=>{R.exit(o)},setTimer:n=Mn,deadlineMs:i=_n})=>{let o=!1;return s=>{if(o)return;o=!0;let a=r();if(a==null){e(),t(fe);return}a.fileFault(`
35
+ ${Z(["trust"],{bin:e})}
36
+ \`infra-kit doctor\` checks both.`)}async registerAppAlias(e,t,n){let i=he(t),o=nn(e);if(o==="")throw new Error(`infra-kit dev: package name "${e}" has no letters or digits to build a hostname from.`);let s=`${i}.${o}`;if(!await this.proxy.registerAlias(s,n))throw new Error(`infra-kit dev: portless refused the alias "${s}" \u2192 127.0.0.1:${n}.`);return this.registeredAliases.add(s),`${s}.localhost`}async startOneApp(e){this.renderer.narrate(`\u{1F504} Starting ${e.name}...`);let t=new J({controllersPath:e.path,prefixUrl:e.prefixUrl,port:e.preferredPort,appName:e.name,serviceTag:`${e.name}/api`,onRequestLog:({method:o,path:s,status:a,ms:l})=>{if(s==="/__health")return;let c=`${e.name}/api`,p=`${o} ${s} ${a} ${l}ms`;this.sink.write(c,p,{level:a>=500?"error":"info"});let d=this.reqTimes.get(c);d?d.push(Date.now()):this.reqTimes.set(c,[Date.now()])}}),n=await t.start(),i;try{i=await this.registerAppAlias(e.packageName,e.path,n)}catch(o){throw await t.close().catch(()=>{}),o}try{this.writeDevContextFragment(e,n,i)}catch(o){this.renderer.log(`\u26A0\uFE0F Failed to write dev-context fragment for ${e.name}: ${String(o)}`,"warn")}return this.renderer.narrate(`\u2705 ${e.name} started on port ${n}`),{server:t,boundPort:n,alias:i}}writeDevContextFragment(e,t,n){let i={v:tn,package:e.packageName,port:t,pid:f.pid,writtenAt:Date.now(),release:he(e.path),alias:n,origin:`https://${n}`},o=v.join(this.devContextDir,`${e.name}.json`),s=v.join(this.devContextDir,`${e.name}.json.${f.pid}.tmp`);h.mkdirSync(this.devContextDir,{recursive:!0}),h.writeFileSync(s,JSON.stringify(i,null,2)),h.renameSync(s,o)}removeDevContextFragment(e){h.rmSync(v.join(this.devContextDir,`${e.name}.json`),{force:!0})}scheduleRestartWork(e){let t=this.restartWorkChain.then(()=>e(),()=>e());return this.restartWorkChain=t.catch(()=>{}),t}async delayPortRelease(){await new Promise(e=>setTimeout(e,r.PORT_RELEASE_DELAY_MS))}restart(e){return this.shuttingDown?Promise.resolve():this.scheduleRestartWork(()=>this.shuttingDown?Promise.resolve():this.runRestart(e))}resolveRestartTargets(e){return e.map(t=>({idx:this.appServers.findIndex(n=>n.app.name===t.name),app:t})).filter(t=>t.idx>=0||this.isFailedApp(t.app.name))}isFailedApp(e){return this.failedApps.some(t=>t.app.name===e)}promoteRecoveredApp(e,t){let n={app:e,...t,startedAt:Date.now(),restarts:0},i=`${e.name}/api`;this.healthEntry(i,"api"),this.appServers.push(n);let o=this.failedApps.findIndex(s=>s.app.name===e.name);return o>=0&&this.failedApps.splice(o,1),this.lastSummary&&(this.lastSummary={...this.lastSummary,endpoints:[...this.lastSummary.endpoints,{tag:i,url:C({prefixUrl:e.prefixUrl,alias:t.alias}),health:this.healthOf(i)}],failed:(this.lastSummary.failed??[]).filter(s=>s.tag!==i)}),n}async runRestart(e){let t=this.resolveRestartTargets(e);if(t.length===0)return;let n=t.length===1?t[0].app.name:`${t.length} apps`;this.renderer.log(`\u{1F504} Restarting ${n}...`),await Promise.all(t.map(async({idx:a})=>{if(!(a<0))try{await this.appServers[a].server.close()}catch(l){this.renderer.log(` Close warning: ${String(l)}`,"debug")}})),await this.delayPortRelease();let i=await Promise.all(t.map(async({idx:a,app:l})=>{try{let c=await this.startOneApp(l);if(c){if(a<0){let g=this.promoteRecoveredApp(l,c);return this.renderer.log(`\u2705 ${l.name} recovered \u2014 its routes are served locally again`,"info"),{app:l,entry:g}}let p=this.appServers[a],d={app:l,...c,startedAt:Date.now(),restarts:(p?.restarts??0)+1};return this.appServers[a]=d,{app:l,entry:d}}return{app:l,entry:null}}catch(c){return this.renderer.log(`\u274C Failed to ${a<0?"start":"restart"} ${l.name}: ${String(c)}`,"error"),{app:l,entry:null}}})),o=await Promise.all(i.map(async({app:a,entry:l})=>{let c=`${a.name}/api`;if(l==null)return this.markDown(c,"api"),this.refreshStatus(),{label:`${a.name} \u25CF down`,healthy:!1};let p={tag:c,port:l.boundPort,kind:"api"},d=await this.healthProbe(p);this.recordProbe(p,d),this.refreshStatus();let g=d==="ok";return{label:`${a.name}:${l.boundPort} ${g?"\u25CF up":"\u25CF down"}`,healthy:g}})),s=o.every(a=>a.healthy);this.renderer.log(`${s?"\u2705":"\u26A0\uFE0F "} Restarted ${o.map(a=>a.label).join(", ")}`)}async buildClosureMapSafe(e){try{return await ze(this.monorepoRoot,e,this.dryRunner)}catch(t){return this.renderer.log(`\u26A0\uFE0F Dependency-closure map unavailable (${String(t)}); package changes restart all apps`,"warn"),null}}reportEngineDeath(e,t,n){this.shuttingDown||this.renderer.log(`\u26A0\uFE0F ${e} ${n} \u2014 ${t}. Restart \`infra-kit dev\`.`,"warn")}markUiEngineDead(){if(!this.shuttingDown){for(let{tag:e,kind:t}of this.uiTargets())this.healthEntry(e,t).dead=!0;this.refreshStatus()}}setupWatch(e,t){this.turboWatch=this.turboWatchFactory({depInclusive:e.map(l=>l.packageName),depClosure:t.map(l=>l.packageName),cwd:f.cwd(),logFile:this.sink.pathFor(gn),onUnexpectedExit:l=>{this.reportEngineDeath("Watch engine (`turbo watch build`)","file saves no longer rebuild",l)}}),this.renderer.narrate("\u{1F440} Watch mode: started `turbo watch build` engine; watching dist output");let n=Se(e),i=T(this.monorepoRoot),o=[...n,...i];if(o.length===0){this.renderer.log("\u26A0\uFE0F No app or package dist directories found to watch (were they built?)","warn");return}let s=f.env.DEV_SERVER_CHOKIDAR_POLL==="1",a=sn.watch(o,{ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:200,pollInterval:100},ignored:l=>l.endsWith(".tsbuildinfo")||l.endsWith(".map"),...s?{usePolling:!0,interval:400}:{}});this.watcher=a,s&&this.renderer.log("\u{1F440} chokidar: usePolling enabled (DEV_SERVER_CHOKIDAR_POLL=1)","debug"),a.on("change",l=>{this.handleDistChange(l,e,n,i)}),this.renderer.narrate(`\u{1F440} Watching ${n.length} app dist + ${i.length} package dist dir(s) for changes...`)}handleDistChange(e,t,n,i){this.renderer.log(`\u{1F440} dist change detected: ${e}`,"debug");let o=Pe(e,n,i);if(o.kind==="package"){let a=Ye(t,this.closureMap,o.packageDir);if(a===null){this.scheduleDebounced("__packages__",()=>this.restart(t));return}a.length>0&&o.packageDir!==void 0&&this.scheduleDebounced(Xe(o.packageDir),()=>this.restart(a));return}let s=t.find(a=>v.join(a.path,"dist")===o.app);s&&this.scheduleDebounced(s.name,()=>this.restart([s]))}scheduleDebounced(e,t){if(this.shuttingDown)return;let n=this.watchDebounceTimers.get(e);n&&clearTimeout(n);let i=setTimeout(()=>{this.watchDebounceTimers.delete(e),!this.shuttingDown&&t().catch(o=>{this.renderer.log(`Restart error (${e}): ${String(o)}`,"error")})},r.WATCH_DEBOUNCE_MS);this.watchDebounceTimers.set(e,i)}uiHealthEnabled(){return(this.options.uiHealth??!0)&&f.env.INFRA_KIT_NO_UI_HEALTH!=="1"}apiTargets(){return this.appServers.map(({app:e,boundPort:t})=>({tag:`${e.name}/api`,port:t,kind:"api"}))}uiTargets(){return this.uiHealthEnabled()?Object.entries(this.uiPortMap).map(([e,{port:t}])=>({tag:this.uiTagByPackage.get(e)??`${e}/ui`,port:t,kind:"ui"})):[]}healthEntry(e,t){let n=this.health.get(e);if(n)return n;let i={kind:t,failures:0,foreignStreak:0,everUp:!1,dead:!1,unverified:!1};return this.health.set(e,i),i}recordProbe(e,t){let n=this.healthEntry(e.tag,e.kind),i=r.LIVENESS_FAILURE_THRESHOLD;if(t==="ok"){let o=n.failures>=i;n.everUp=!0,n.failures=0,n.foreignStreak=0,n.unverified=!1,o&&this.renderer.log(`\u2705 ${e.tag} recovered`);return}if(vn(t)&&e.kind==="ui"){n.foreignStreak+=1,n.unverified=n.foreignStreak>=i,n.foreignStreak===i&&this.renderer.log(`\u26A0\uFE0F ${e.tag}: ${wn(e.port,t)}`,"warn");return}if(n.foreignStreak=0,n.failures+=1,e.kind==="ui"&&n.failures>=i&&(n.unverified=!1),n.failures===i){let o=e.kind==="api"?"/__health not responding":"not answering vite's ping";this.renderer.log(`\u26A0\uFE0F ${e.tag} unhealthy (${o})`,"warn")}}markDown(e,t){let n=this.healthEntry(e,t);n.dead=!0,n.failures=r.LIVENESS_FAILURE_THRESHOLD,n.foreignStreak=0,n.unverified=!1}healthOf(e){let t=this.health.get(e);return t==null?"unknown":t.unverified?"unverified":t.everUp?t.failures>=r.LIVENESS_FAILURE_THRESHOLD?"down":"ok":this.neverUpState(t)}neverUpState(e){return e.kind==="api"||e.dead||e.failures>=r.NEVER_UP_DOWN_THRESHOLD?"down":"starting"}startLivenessMonitor(){this.scheduleLivenessTick()}scheduleLivenessTick(){let e=this.options.livenessIntervalMs??r.LIVENESS_INTERVAL_MS;this.livenessTimer=setTimeout(()=>{this.livenessTick().finally(()=>{this.shuttingDown||this.scheduleLivenessTick()}).catch(()=>{})},e),this.livenessTimer.unref()}refreshStatus(){let e=this.lastSummary;if(e==null)return;let t=Date.now(),n=new Map(this.appServers.map(i=>[`${i.app.name}/api`,i]));this.pruneRequestWindow(t),this.renderer.refresh?.({...e,sessionUptimeMs:t-this.readyAt,degraded:this.degradedRows(),uiRefs:e.uiRefs.map(i=>({...i,errors:this.announceFirstError(i.tag)})),endpoints:e.endpoints.map(i=>{let o=n.get(i.tag);return{...i,health:this.healthOf(i.tag),uptimeMs:o?t-o.startedAt:void 0,restarts:o?.restarts,rpm:(this.reqTimes.get(i.tag)??[]).length,errors:this.announceFirstError(i.tag)}})})}announceFirstError(e){let{errors:t}=this.sink.statsFor(e);return t>0&&!this.firstErrorLogged.has(e)&&(this.firstErrorLogged.add(e),this.renderer.log(`\u26A0\uFE0F ${e} reported its first error \u2192 ${K(this.sink.pathFor(e))}`,"warn")),t}degradedRows(){if(this.degradedRoutes.length===0)return[];let e=new Set(this.appServers.map(({app:t})=>t.packageName));return this.degradedRoutes.filter(t=>!e.has(t.packageName)).map(t=>({route:t.route,tag:`${t.uiApp}/ui`,fallback:t.fallback,target:t.cloudTarget}))}pruneRequestWindow(e){let t=e-6e4;for(let[n,i]of this.reqTimes)this.reqTimes.set(n,i.filter(o=>o>t))}async livenessTick(){this.shuttingDown||(await Promise.all([...this.apiTargets(),...this.uiTargets()].map(e=>this.probeOne(e))),this.refreshStatus())}async probeOne(e){let t=await this.healthProbe(e);this.shuttingDown||this.recordProbe(e,t)}async printReady(e,t,n,i){let o=Date.now()-n;await Promise.all(this.apiTargets().map(u=>this.probeOne(u)));let s=this.appServers.map(({app:u,alias:m})=>({tag:`${u.name}/api`,url:C({prefixUrl:u.prefixUrl,alias:m}),health:this.healthOf(`${u.name}/api`)})),a=new Map(this.appServers.map(({app:u,alias:m})=>[u.packageName,C({prefixUrl:u.prefixUrl,alias:m})]));this.proxyRoutes=tt({uis:this.launchedUis,running:new Set(this.appServers.map(({app:u})=>u.packageName)),localOrigin:u=>a.get(u),env:f.env[Q]}),this.uiPortMap={};let l=[],c=[];for(let u of t){let m=await this.assignUiPort(u),w=`${u.name}/ui`;m!=null?l.push({tag:w,url:C({prefixUrl:"",alias:m.alias}),health:this.seedUiHealth(w),proxies:this.proxiesFor(u.name)}):c.push({tag:w,proxies:this.proxiesFor(u.name)})}let p=this.options.watch??!1,d=e.length+t.length,g=T(this.monorepoRoot).length;this.lastSummary={target:i,watch:p,release:he(f.cwd()),elapsedMs:o,endpoints:[...s,...l],uiRefs:c,failed:this.failedApps.map(({app:u,reason:m})=>({tag:`${u.name}/api`,reason:m})),degraded:this.degradedRows(),watchSummary:`${d} app${d===1?"":"s"} \xB7 ${g} package${g===1?"":"s"}`,logPath:K(this.sink.dir),logHref:this.sink.dir},this.readyAt=Date.now(),this.renderer.ready(this.lastSummary),this.refreshStatus()}async assignUiPort(e){if(!e.managedPort)return null;let t;try{t=await mn()}catch{return null}let n=await this.registerAppAlias(e.packageName,e.path,t);return this.uiPortMap[e.packageName]={port:t,alias:n},this.uiTagByPackage.set(e.packageName,`${e.name}/ui`),{port:t,alias:n}}seedUiHealth(e){return this.uiHealthEnabled()?(this.healthEntry(e,"ui"),this.healthOf(e)):"unknown"}printRouteDump(){if(this.appServers.length!==0){this.renderer.log("\u{1F5FA}\uFE0F Registered routes:");for(let{app:e,server:t}of this.appServers){let n=t.getRegisteredRoutes();this.renderer.log(` ${e.name} (${n.length}): ${n.length>0?n.join(", "):"(none)"}`)}}}reportFault(e){this.sink.write(W()??q,e,{level:"error"}),this.renderer.log(e,"error",{tee:!1})}fileFault(e){this.sink.write(W()??q,e,{level:"error"})}get shutdownStage(){return this.stage}shutdown(){return this.teardown!=null?this.teardown:(this.teardown=this.doShutdown(),this.teardown.catch(()=>{}),this.teardown)}async doShutdown(){this.shuttingDown=!0,this.stage="starting",this.renderer.dispose(),this.intercept?.uninstall(),this.renderer.log("\u{1F6D1} Shutting down all servers...");for(let e of this.watchDebounceTimers.values())clearTimeout(e);this.watchDebounceTimers.clear(),this.livenessTimer&&(clearTimeout(this.livenessTimer),this.livenessTimer=null),this.watcher&&(this.stage="watcher.close",await this.watcher.close(),this.watcher=null),this.stage="restartWorkChain",await this.restartWorkChain,this.stage="closureBuild",await this.closureBuild,this.stage="removeAlias",await Promise.all([...this.registeredAliases].map(e=>this.proxy.removeAlias(e))),this.registeredAliases.clear(),this.turboWatch&&(this.stage="turboWatch.kill",await this.turboWatch.kill(),this.turboWatch=null),this.uiDev&&(this.stage="uiDev.kill",await this.uiDev.kill(),this.uiDev=null);for(let{app:e,server:t}of this.appServers){this.stage=`server.close(${e.name})`;try{await t.close()}catch{}this.removeDevContextFragment(e)}this.intercept?.uninstall(),this.renderer.log(`\u2713 dev stopped \xB7 logs \u2192 ${K(this.sink.dir)}`),this.sink.close(),this.stage="done"}},Tt=r=>(r.tty??!!f.stdout.isTTY)&&!r.json,On=async r=>{if(!Tt(r))return;let{PersistentInkDevUi:e}=await import("./persistent-ink-dev-ui-PLLSRSGL.js"),{createSafeStream:t}=await import("./safe-stderr-HXDR2DNJ.js");return new e({appendLog:Et,verbose:r.verbose??!1,stdout:t(ct())})};async function Ct(r={}){let e=await On(r),t=new fe(r,void 0,void 0,void 0,void 0,e);try{await t.start()}catch(n){throw await t.shutdown().catch(()=>{}),n}return t}var me=1,Fn=2e4,Mn=r=>{if(r!=null){for(let e of r)if(De(e)!==null)throw new Error(`infra-kit dev: invalid --target "${e}" (expected "<app>/api" or "<app>/ui").`);return{apps:Object.fromEntries(r.map(e=>[e,{}]))}}},$t=r=>{if(r==null)return null;let e=r.split(",").map(t=>t.trim()).filter(Boolean);return e.length>0?e:null},Lt=r=>({watch:r.watch??!1,include:$t(r.app),preset:r.preset,presetDef:Mn($t(r.target)),cmux:r.cmux??!1,self:r.self??!1,verbose:r.verbose??!1,routes:r.routes??!1,uiHealth:r.uiHealth??!0}),Hn=r=>!r.self||r.include?r:{...r,include:[be(R.cwd())]},jn=(r,e)=>{let t=setTimeout(r,e);return t.unref(),()=>{clearTimeout(t)}},Wn=({getRunner:r,forceReap:e=x,exit:t=o=>{R.exit(o)},setTimer:n=jn,deadlineMs:i=Fn})=>{let o=!1;return s=>{if(o)return;o=!0;let a=r();if(a==null){e(),t(me);return}a.fileFault(`
37
37
  \u2717 dev-server exiting: ${s}
38
- `);let l=n(()=>{e(),t(fe)},i);a.shutdown().finally(()=>{l(),t(fe)}).catch(()=>{})}},me=async r=>{let e=Fn(r);if(e.cmux){if(await Ce()){await Je(e);return}R.stdout.write(`cmux not available; falling back to single-terminal dev
39
- `)}let t=null,n=Hn({getRunner:()=>t}),i=it({onDeath:(s,a)=>{n(`stdio unwritable: ${s} ${a.code}`)}});t=await Et(e);let o=t;Ke({onFault:(s,a)=>{o.reportFault($(s,a))},isTerminalDead:i.isDead,fileFault:(s,a)=>{o.fileFault($(s,a,!1))},onFatal:n}),H({onSignal:async s=>{ue(`
38
+ `);let l=n(()=>{e(),t(me)},i);a.shutdown().finally(()=>{l(),t(me)}).catch(()=>{})}},ve=async r=>{let e=Hn(r);if(e.cmux){if(await Ce()){await Je(e);return}R.stdout.write(`cmux not available; falling back to single-terminal dev
39
+ `)}let t=null,n=Wn({getRunner:()=>t}),i=at({onDeath:(s,a)=>{n(`stdio unwritable: ${s} ${a.code}`)}});t=await Ct(e);let o=t;Ke({onFault:(s,a)=>{o.reportFault(L(s,a))},isTerminalDead:i.isDead,fileFault:(s,a)=>{o.fileFault(L(s,a,!1))},onFatal:n}),H({onSignal:async s=>{pe(`
40
40
  Received ${s}, shutting down dev-server...
41
- `),await o.shutdown()},describeStall:()=>o.shutdownStage,fileReport:s=>{o.fileFault(s)}})},Wn=(r,e,t)=>!r.preset&&!r.app&&!r.self&&!r.cmux&&!r.watch&&!r.verbose&&!r.routes&&e&&!t,jn=(r,e)=>({watch:r.watch,cmux:r.cmux,include:r.include??null,preset:r.preset,presetDef:r.presetDef,self:!1,verbose:!1,routes:!1,uiHealth:e.uiHealth??!0}),Ro=async(r,e,t)=>{if(Wn(r,e,t)){let{runDevWizard:n}=await import("./dev-wizard-run-5NOQIMR5.js"),i=Promise.all([import("./persistent-ink-dev-ui-TLUJJC2D.js"),import("./safe-stderr-HXDR2DNJ.js")]).catch(()=>{}),o;try{o=await n()}catch(s){if(Ne(s))return;throw s}if(o==null)return;await i,await me({...jn(o,r),tty:e,json:t});return}await me({...Tt(r),tty:e,json:t})},Bn=async r=>{let e=new In;e.name("infra-kit-dev-server").description("Run local dev servers for the apps in a named devServersPresets preset (or all apps)").argument("[preset]","Named preset from devServersPresets (omit to run every app)").option("-w, --watch","Rebuild and restart on file save").option("--app <names>","Further narrow to these app folder names (comma-separated)").option("--cmux","Run each app in its own cmux pane (one workspace, N panes; falls back to single terminal if cmux is unavailable)").option("--self","Run only the app of the current directory (infer from cwd; use inside apps/<app>/\u2026)").option("-V, --verbose","Print full boot narration (default: quiet; full detail always in the session log)").option("--routes","Print each app\u2019s registered METHOD /path routes at startup (default: off)"),e.parse(r),await me(Tt({...e.opts(),preset:e.args[0]}))};import.meta.url===On(R.argv[1]??"").href&&Bn(R.argv).catch(r=>{console.error(r instanceof Error?r.message:String(r)),R.exit(1)});export{Hn as createFatalHandler,me as runDevServer,Ro as runDevServerCli,Wn as shouldRunWizard,Tt as toDevServerOptions};
41
+ `),await o.shutdown()},describeStall:()=>o.shutdownStage,fileReport:s=>{o.fileFault(s)}})},Bn=(r,e,t)=>!r.preset&&!r.app&&!r.self&&!r.cmux&&!r.watch&&!r.verbose&&!r.routes&&e&&!t,Gn=(r,e)=>({watch:r.watch,cmux:r.cmux,include:r.include??null,preset:r.preset,presetDef:r.presetDef,self:!1,verbose:!1,routes:!1,uiHealth:e.uiHealth??!0}),Eo=async(r,e,t)=>{if(Bn(r,e,t)){let{runDevWizard:n}=await import("./dev-wizard-run-5ST3BJ4L.js"),i=Promise.all([import("./persistent-ink-dev-ui-PLLSRSGL.js"),import("./safe-stderr-HXDR2DNJ.js")]).catch(()=>{}),o;try{o=await n()}catch(s){if(Ne(s))return;throw s}if(o==null)return;await i,await ve({...Gn(o,r),tty:e,json:t});return}await ve({...Lt(r),tty:e,json:t})},Vn=async r=>{let e=new _n;e.name("infra-kit-dev-server").description("Run local dev servers for the apps in a named devServersPresets preset (or all apps)").argument("[preset]","Named preset from devServersPresets (omit to run every app)").option("-w, --watch","Rebuild and restart on file save").option("--app <names>","Further narrow to these app folder names (comma-separated)").option("--cmux","Run each app in its own cmux pane (one workspace, N panes; falls back to single terminal if cmux is unavailable)").option("--self","Run only the app of the current directory (infer from cwd; use inside apps/<app>/\u2026)").option("-V, --verbose","Print full boot narration (default: quiet; full detail always in the session log)").option("--routes","Print each app\u2019s registered METHOD /path routes at startup (default: off)"),e.parse(r),await ve(Lt({...e.opts(),preset:e.args[0]}))};import.meta.url===Un(R.argv[1]??"").href&&Vn(R.argv).catch(r=>{console.error(r instanceof Error?r.message:String(r)),R.exit(1)});export{Wn as createFatalHandler,ve as runDevServer,Eo as runDevServerCli,Bn as shouldRunWizard,Lt as toDevServerOptions};
42
42
  //# sourceMappingURL=dev-server.js.map