@tdk-landscape/tdk-cli-core 1.3.175 → 1.3.177

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,32 +1,32 @@
1
1
  import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
- import{c as Ke,e as sr}from"./chunk-42IVF3YT.js";import{a as wt}from"./chunk-6EA4DGCY.js";import{execFileSync as ai}from"node:child_process";import{readFileSync as Bd}from"node:fs";import{join as Hd}from"node:path";import{execFileSync as od,execSync as Zo}from"node:child_process";import{existsSync as H,readdirSync as id,readFileSync as Se}from"node:fs";import{join as D,normalize as qn,relative as zn}from"node:path";function or(e,t,n){let r=e.indexOf(t);if(r===-1)return e;let s=t.length,o=0,i="";do i+=e.slice(o,r)+t+n,o=r+s,r=e.indexOf(t,o);while(r!==-1);return i+=e.slice(o),i}function ir(e,t,n,r){let s=0,o="";do{let i=e[r-1]==="\r";o+=e.slice(s,i?r-1:r)+t+(i?`\r
2
+ import{c as Ge,e as sr}from"./chunk-42IVF3YT.js";import{a as wt}from"./chunk-6EA4DGCY.js";import{execFileSync as ci}from"node:child_process";import{readFileSync as Gu}from"node:fs";import{join as Ku}from"node:path";import{execFileSync as au,execSync as ei}from"node:child_process";import{existsSync as H,readdirSync as cu,readFileSync as Se}from"node:fs";import{join as D,normalize as qn,relative as zn}from"node:path";function or(e,t,n){let r=e.indexOf(t);if(r===-1)return e;let s=t.length,o=0,i="";do i+=e.slice(o,r)+t+n,o=r+s,r=e.indexOf(t,o);while(r!==-1);return i+=e.slice(o),i}function ir(e,t,n,r){let s=0,o="";do{let i=e[r-1]==="\r";o+=e.slice(s,i?r-1:r)+t+(i?`\r
3
3
  `:`
4
4
  `)+n,s=r+1,r=e.indexOf(`
5
- `,s)}while(r!==-1);return o+=e.slice(s),o}var ar=(e=0)=>t=>`\x1B[${t+e}m`,Et=(e=0)=>t=>`\x1B[${38+e};5;${t}m`,vt=(e=0)=>(t,n,r)=>`\x1B[${38+e};2;${t};${n};${r}m`,ui=e=>`\x1B[58;5;${e<90?e-30:e-90+8}m`,E={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],underlineDouble:["4:2",24],underlineCurly:["4:3",24],underlineDotted:["4:4",24],underlineDashed:["4:5",24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]},underlineColor:{underlineBlack:["58;5;0",59],underlineRed:["58;5;1",59],underlineGreen:["58;5;2",59],underlineYellow:["58;5;3",59],underlineBlue:["58;5;4",59],underlineMagenta:["58;5;5",59],underlineCyan:["58;5;6",59],underlineWhite:["58;5;7",59],underlineBlackBright:["58;5;8",59],underlineGray:["58;5;8",59],underlineGrey:["58;5;8",59],underlineRedBright:["58;5;9",59],underlineGreenBright:["58;5;10",59],underlineYellowBright:["58;5;11",59],underlineBlueBright:["58;5;12",59],underlineMagentaBright:["58;5;13",59],underlineCyanBright:["58;5;14",59],underlineWhiteBright:["58;5;15",59]}},cr=Object.keys(E.modifier),Pt=Object.keys(E.color),$t=Object.keys(E.bgColor),li=Object.keys(E.underlineColor),ur=[...Pt,...$t];function di(){let e=new Map;for(let[t,n]of Object.entries(E)){for(let[r,s]of Object.entries(n))E[r]={open:`\x1B[${s[0]}m`,close:`\x1B[${s[1]}m`},n[r]=E[r],e.set(Number.parseInt(s[0],10),s[1]);Object.defineProperty(E,t,{value:n,enumerable:!1})}return Object.defineProperty(E,"codes",{value:e,enumerable:!1}),E.color.close="\x1B[39m",E.bgColor.close="\x1B[49m",E.underlineColor.close="\x1B[59m",E.color.ansi=ar(),E.color.ansi256=Et(),E.color.ansi16m=vt(),E.bgColor.ansi=ar(10),E.bgColor.ansi256=Et(10),E.bgColor.ansi16m=vt(10),E.underlineColor.ansi=ui,E.underlineColor.ansi256=Et(20),E.underlineColor.ansi16m=vt(20),Object.defineProperties(E,{rgbToAnsi256:{value(t,n,r){return t===n&&n===r?t<8?16:t>248?231:Math.round((t-8)/247*24)+232:16+36*Math.round(t/255*5)+6*Math.round(n/255*5)+Math.round(r/255*5)},enumerable:!1},hexToRgb:{value(t){let n=/[\da-f]{6}|[\da-f]{3}/i.exec(t.toString(16));if(!n)return[0,0,0];let[r]=n;r.length===3&&(r=[...r].map(o=>o+o).join(""));let s=Number.parseInt(r,16);return[s>>16&255,s>>8&255,s&255]},enumerable:!1},hexToAnsi256:{value:t=>E.rgbToAnsi256(...E.hexToRgb(t)),enumerable:!1},ansi256ToAnsi:{value(t){if(t<8)return 30+t;if(t<16)return 90+(t-8);let n,r,s;if(t>=232)n=((t-232)*10+8)/255,r=n,s=n;else{t-=16;let a=t%36;n=Math.floor(t/36)/5,r=Math.floor(a/6)/5,s=a%6/5}let o=Math.max(n,r,s)*2;if(o===0)return 30;let i=30+(Math.round(s)<<2|Math.round(r)<<1|Math.round(n));return o===2&&(i+=60),i},enumerable:!1},rgbToAnsi:{value:(t,n,r)=>E.ansi256ToAnsi(E.rgbToAnsi256(t,n,r)),enumerable:!1},hexToAnsi:{value:t=>E.ansi256ToAnsi(E.hexToAnsi256(t)),enumerable:!1}}),E}var pi=di(),W=pi;import _t from"node:process";import fi from"node:os";import lr from"node:tty";function K(e,t=globalThis.Deno?globalThis.Deno.args:_t.argv){let n=e.startsWith("-")?"":e.length===1?"-":"--",r=t.indexOf(n+e),s=t.indexOf("--");return r!==-1&&(s===-1||r<s)}var{env:v}=_t,Ge;K("no-color")||K("no-colors")||K("color=false")||K("color=never")?Ge=0:(K("color")||K("colors")||K("color=true")||K("color=always"))&&(Ge=1);function pr(){return/^\d+$/.test(v.FORCE_COLOR)}function mi(){if("FORCE_COLOR"in v){if(v.FORCE_COLOR==="false")return 0;if(v.FORCE_COLOR==="true"||v.FORCE_COLOR.length===0)return 1;if(pr())return Math.min(Number.parseInt(v.FORCE_COLOR,10),3)}}function hi(e){return e===0?!1:{level:e,hasBasic:!0,has256:e>=2,has16m:e>=3}}function gi(e,{streamIsTTY:t,sniffFlags:n=!0}={}){let r=mi();r!==void 0&&(Ge=r);let s=n?Ge:r;if(s===0)return 0;if(n){if(K("color=16m")||K("color=full")||K("color=truecolor"))return 3;if(K("color=256"))return 2}if(s!==void 0&&pr())return s;if("TF_BUILD"in v&&"AGENT_NAME"in v)return 1;if(e&&!t&&s===void 0)return 0;let o=s||0;if(v.TERM==="dumb")return o;if(_t.platform==="win32"){let i=fi.release().split(".");return Number(i[0])>=10&&Number(i[2])>=10586?Number(i[2])>=14931?3:2:1}if("CI"in v)return["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(i=>i in v)?3:["TRAVIS","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(i=>i in v)||v.CI_NAME==="codeship"?1:o;if("TEAMCITY_VERSION"in v)return/^(?:9\.0*[1-9]\d*\.|\d{2,}\.)/.test(v.TEAMCITY_VERSION)?1:0;if(v.COLORTERM==="truecolor"||v.TERM==="xterm-kitty"||v.TERM==="xterm-ghostty"||v.TERM==="wezterm")return 3;if("TERM_PROGRAM"in v){let i=Number.parseInt((v.TERM_PROGRAM_VERSION||"").split(".",1)[0],10);switch(v.TERM_PROGRAM){case"iTerm.app":return i>=3?3:2;case"Apple_Terminal":return 2}}return/-256(?:color)?$/i.test(v.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(v.TERM)||"COLORTERM"in v?1:o}function dr(e,t={}){let n=gi(e,{streamIsTTY:e&&e.isTTY,...t});return hi(n)}var ki={stdout:dr({isTTY:lr.isatty(1)}),stderr:dr({isTTY:lr.isatty(2)})},fr=ki;var{stdout:mr,stderr:hr}=fr,xe=Symbol("GENERATOR"),we=Symbol("STYLER"),We=Symbol("IS_EMPTY"),Ve=Symbol("LEVEL"),Ee=Object.create(null),gr=e=>{if(!Number.isSafeInteger(e)||e<0||e>3)throw new Error("The `level` should be an integer from 0 to 3")},yi={enumerable:!0,get(){return this[Ve]},set(e){gr(e),this[Ve]=e}},Si=(e,t={})=>{t.level!==void 0&&gr(t.level);let n=mr?mr.level:0;e[Ve]=t.level===void 0?n:t.level};var bi=e=>{let t=(...n)=>n.join(" ");return Si(t,e),Object.setPrototypeOf(t,ve.prototype),t};function ve(e){return bi(e)}Object.setPrototypeOf(ve.prototype,Function.prototype);for(let[e,t]of Object.entries(W))Ee[e]={get(){let n=At(this,kr(t.open,t.close,this[we]),this[We]);return Object.defineProperty(this,e,{value:n}),n}};Ee.visible={get(){let e=At(this,this[we],!0);return Object.defineProperty(this,"visible",{value:e}),e}};var Ti=(e,t)=>{let n=W[t];if(e==="rgb"){let s=(i,a,c)=>n.ansi(W.rgbToAnsi(i,a,c));return[s,s,(i,a,c)=>n.ansi256(W.rgbToAnsi256(i,a,c)),n.ansi16m]}if(e==="hex"){let s=i=>n.ansi(W.hexToAnsi(i));return[s,s,i=>n.ansi256(W.hexToAnsi256(i)),i=>n.ansi16m(...W.hexToRgb(i))]}let r=s=>n.ansi(W.ansi256ToAnsi(s));return[r,r,n.ansi256,n.ansi256]},xi=["rgb","hex","ansi256"];for(let e of xi){let t=e[0].toUpperCase()+e.slice(1);for(let[n,r]of[[e,"color"],["bg"+t,"bgColor"],["underline"+t,"underlineColor"]]){let{close:s}=W[r],o=Ti(e,r);Ee[n]={get(){let i=function(a,c,u){let d=o[this.level](a,c,u);return At(this,kr(d,s,this[we]),this[We])};return Object.defineProperty(this,n,{value:i}),i}}}}var wi=Object.defineProperties(()=>{},{...Ee,level:{enumerable:!0,get(){return this[xe].level},set(e){this[xe].level=e}}}),kr=(e,t,n)=>{let r,s;return n===void 0?(r=e,s=t):(r=n.openAll+e,s=t+n.closeAll),{open:e,close:t,openAll:r,closeAll:s,parent:n}},At=(e,t,n)=>{let r=(...s)=>s.length===1?Rt(r,""+s[0]):s.length===2?Rt(r,`${s[0]??""} ${s[1]??""}`):Rt(r,s.join(" "));return Object.setPrototypeOf(r,wi),r[xe]=e[xe]??e,r[we]=t,r[We]=n,r},Rt=(e,t)=>{if(e[xe][Ve]<=0||!t)return e[We]?"":t;let n=e[we];if(n===void 0)return t;let{openAll:r,closeAll:s}=n;if(t.includes("\x1B"))for(;n!==void 0;)t=or(t,n.close,n.open),n=n.parent;let o=t.indexOf(`
6
- `);return o!==-1&&(t=ir(t,s,r,o)),r+t+s};Object.defineProperties(ve.prototype,{...Ee,level:yi});var Ei=ve(),rp=ve({level:hr?hr.level:0});var m=Ei;import{Command as ad}from"commander";import*as S from"node:fs";import*as k from"node:path";import{fileURLToPath as dc}from"node:url";import ie from"handlebars";var B="Container Runtime",J="bring-your-own";var j="database-management",q=".tiltignore",yr="service.json",se="docker-compose.yml",C=".autogenerated",Je="TILT_TECH_STACK.star",qe="TILT_RESOURCE_DEFAULTS.star",_="project.json",A="package.json",Dt=[Je,qe,"spec.master"],ip=["backend","frontend","library","sdk","worker","migrator","mcp","agent",J],Ot={backend:["dev","build","start"],worker:["dev","build","start"],migrator:["dev","build","start"],mcp:["dev","build","start"],agent:["dev","build","start"],frontend:["dev","build"],library:["dev","build"],sdk:["dev","build"],[J]:[]};var Nt=["monitoring","elk","debezium","golden_image","verdaccio"],P={frontend:{base:3e3,min:3e3,max:3999,range:"3000-3999"},backend:{base:4e3,min:4e3,max:4999,range:"4000-4999"},mcp:{base:4e3,min:4e3,max:5999,range:"4000-5999"},agent:{base:4e3,min:4e3,max:5999,range:"4000-5999"},[J]:{base:4e3,min:4e3,max:5999,range:"4000-5999"},worker:{base:6e3,min:6e3,max:6999,range:"6000-6999"},health:{base:5e3,min:5e3,max:5999,range:"5000-5999"},migrator:{base:7e3,min:7e3,max:7999,range:"7000-7999"}},Pe={tiltUi:10350,traefik:8080},Ct="https://tdk-landscape.github.io/tdk-website/docs/quickstart/";var Sr=["node_modules",".git",".tilt",".tilt-engine","dist","build",".prisma",".turbo","coverage","tmp","temp","__tests__","test","tests",".github",".vscode","docs"],br=["Dockerfile",se,"docker-compose.yaml","Tiltfile","vite.config.ts","tsconfig.json","tsconfig.build.json"],vi={infra:"\u{1F3D7}\uFE0F",core:"\u{1F527}",api:"\u26A1",app:"\u{1F3A8}",orchestrator:"\u2699\uFE0F"};function ap(e){let t=e.toLowerCase();for(let[n,r]of Object.entries(vi))if(t.includes(n))return r;return"\u{1F4E6}"}var Pi="1.0.0",$i={runtime:"bun",bundler:"vite",language:"typescript",framework:"hono",database:"postgresql",orm:"prisma",messaging:"nats",linting:"biome",testing:"vitest"},_i={frontend:{base:P.frontend.base,range:P.frontend.range,start:P.frontend.min,end:P.frontend.max},backend:{base:P.backend.base,range:P.backend.range,start:P.backend.min,end:P.backend.max},health:{base:P.health.base,range:P.health.range,start:P.health.min,end:P.health.max},worker:{base:P.worker.base,range:P.worker.range,start:P.worker.min,end:P.worker.max},migrator:{base:P.migrator.base,range:P.migrator.range,start:P.migrator.min,end:P.migrator.max},tiltUi:Pe.tiltUi,traefik:Pe.traefik},Ri={path:"/health",live:"/health/live",ready:"/health/ready",timeout:30,interval:5},Ai={frontend:"-frontend",backend:"-backend",worker:"-worker",migrator:"-migrator",library:"-lib",sdk:"-sdk",validSeparators:["-","_"],maxLength:63,minLength:3},Di={entrypoint:"web",network:"traefik-public",defaultHost:"localhost",appHost:"app.localhost",apiHost:"api.localhost",appSubdomainPrefix:"app",apiSubdomainPrefix:"api",defaultPort:8080,tlsEnabled:!1,entrypoints:["web"],middlewares:[],tls:{enabled:!1},healthcheckPath:"/health",healthcheckInterval:"10s",healthcheckTimeout:"5s",frontendPriorityBase:100},Oi=["node_modules","dist","build",".git",".prisma",".turbo","coverage","tmp","temp","__tests__","test","tests"],Ni={frontend:{suffix:"-frontend",portRange:"3000-3999"},backend:{suffix:"-backend",portRange:"4000-4999"},library:{suffix:"-library",portRange:null},sdk:{suffix:"-sdk",portRange:"3000-9999"},migrator:{suffix:"-migrator",portRange:"7000-7999"},worker:{suffix:"-worker",portRange:"6000-6999"}},Ci={prisma:"Database ORM with migrations",nats:"Event streaming via NATS",redis:"Caching layer",infisical:"Secrets management",vitest:"Testing framework",traefik:"HTTP routing",websocket:"Real-time connections",graphql:"GraphQL support",grpc:"gRPC support",viteNode:"Vite Node runtime",maintenance:"Maintenance mode"},ji={services:"services/product",sharedPlatform:"shared-platform-engineering",sharedProduct:"shared-product-engineering",sharedDdd:"shared-ddd-layers"},Ii={scanIntervalSeconds:5,maxManifestsPerRoot:50,servicePatterns:["services/product/*","services/platform/*"]},Fi={dockerfile:"Dockerfile",context:"."},Li={backend:{command:"bun",args:["run","dev"],env:{NODE_ENV:"development"}},frontend:{command:"bun",args:["run","dev"],env:{NODE_ENV:"development"}}},L={version:Pi,tech:$i,ports:_i,health:Ri,naming:Ai,traefik:Di,filewatchIgnores:Oi,serviceTypes:Ni,features:Ci,paths:ji,discovery:Ii,docker:Fi,runtime:Li};import{randomBytes as Mi}from"node:crypto";import{closeSync as Ui,fchmodSync as Bi,fsyncSync as Hi,openSync as Ki,renameSync as Gi,rmSync as Vi,statSync as Wi,writeFileSync as Ji}from"node:fs";import{basename as qi,dirname as zi,join as Yi}from"node:path";function $e(e,t){let n=Yi(zi(e),`.${qi(e)}.${process.pid}.${Mi(4).toString("hex")}.tmp`),r;try{r=Wi(e).mode&511}catch{r=void 0}try{let s=Ki(n,"wx");try{r!==void 0&&Bi(s,r),Ji(s,t,"utf-8"),Hi(s)}finally{Ui(s)}Gi(n,e)}catch(s){throw Vi(n,{force:!0}),s}}import{appendFileSync as Xi,existsSync as Tr,mkdirSync as Qi,readFileSync as Zi,writeFileSync as xr}from"node:fs";import{resolve as jt}from"node:path";function yp(e,t,n){for(let[r,s]of t.entries())console.log(m.blue(`${s.emoji} ${s.description}...`)),s.type==="json"?ta(e,s.filename,s.content):na(e,s.filename,String(s.content)),n&&n(s,r,t.length)}function ea(e,t,n=2){let r=`${JSON.stringify(t,null,n)}
7
- `;xr(e,r,"utf-8")}function ta(e,t,n,r=2){let s=jt(e,t);ea(s,n,r)}function It(e,t){xr(e,t,"utf-8")}function na(e,t,n){let r=jt(e,t);It(r,n)}function Sp(e){Tr(e)||Qi(e,{recursive:!0})}var ra=[".env",".tdk/.tdk-out/",".tdk/.project-id",".tdk/smoke/","node_modules/"];function bp(e){let t=jt(e,".gitignore"),n=Tr(t)?Zi(t,"utf-8"):"",r=new Set(n.split(`
8
- `).map(a=>a.trim().replace(/\/$/,""))),s=ra.filter(a=>!r.has(a.replace(/\/$/,"")));if(s.length===0)return[];let o=n&&!n.endsWith(`
5
+ `,s)}while(r!==-1);return o+=e.slice(s),o}var ar=(e=0)=>t=>`\x1B[${t+e}m`,Et=(e=0)=>t=>`\x1B[${38+e};5;${t}m`,vt=(e=0)=>(t,n,r)=>`\x1B[${38+e};2;${t};${n};${r}m`,di=e=>`\x1B[58;5;${e<90?e-30:e-90+8}m`,E={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],underlineDouble:["4:2",24],underlineCurly:["4:3",24],underlineDotted:["4:4",24],underlineDashed:["4:5",24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]},underlineColor:{underlineBlack:["58;5;0",59],underlineRed:["58;5;1",59],underlineGreen:["58;5;2",59],underlineYellow:["58;5;3",59],underlineBlue:["58;5;4",59],underlineMagenta:["58;5;5",59],underlineCyan:["58;5;6",59],underlineWhite:["58;5;7",59],underlineBlackBright:["58;5;8",59],underlineGray:["58;5;8",59],underlineGrey:["58;5;8",59],underlineRedBright:["58;5;9",59],underlineGreenBright:["58;5;10",59],underlineYellowBright:["58;5;11",59],underlineBlueBright:["58;5;12",59],underlineMagentaBright:["58;5;13",59],underlineCyanBright:["58;5;14",59],underlineWhiteBright:["58;5;15",59]}},cr=Object.keys(E.modifier),Pt=Object.keys(E.color),$t=Object.keys(E.bgColor),ui=Object.keys(E.underlineColor),lr=[...Pt,...$t];function pi(){let e=new Map;for(let[t,n]of Object.entries(E)){for(let[r,s]of Object.entries(n))E[r]={open:`\x1B[${s[0]}m`,close:`\x1B[${s[1]}m`},n[r]=E[r],e.set(Number.parseInt(s[0],10),s[1]);Object.defineProperty(E,t,{value:n,enumerable:!1})}return Object.defineProperty(E,"codes",{value:e,enumerable:!1}),E.color.close="\x1B[39m",E.bgColor.close="\x1B[49m",E.underlineColor.close="\x1B[59m",E.color.ansi=ar(),E.color.ansi256=Et(),E.color.ansi16m=vt(),E.bgColor.ansi=ar(10),E.bgColor.ansi256=Et(10),E.bgColor.ansi16m=vt(10),E.underlineColor.ansi=di,E.underlineColor.ansi256=Et(20),E.underlineColor.ansi16m=vt(20),Object.defineProperties(E,{rgbToAnsi256:{value(t,n,r){return t===n&&n===r?t<8?16:t>248?231:Math.round((t-8)/247*24)+232:16+36*Math.round(t/255*5)+6*Math.round(n/255*5)+Math.round(r/255*5)},enumerable:!1},hexToRgb:{value(t){let n=/[\da-f]{6}|[\da-f]{3}/i.exec(t.toString(16));if(!n)return[0,0,0];let[r]=n;r.length===3&&(r=[...r].map(o=>o+o).join(""));let s=Number.parseInt(r,16);return[s>>16&255,s>>8&255,s&255]},enumerable:!1},hexToAnsi256:{value:t=>E.rgbToAnsi256(...E.hexToRgb(t)),enumerable:!1},ansi256ToAnsi:{value(t){if(t<8)return 30+t;if(t<16)return 90+(t-8);let n,r,s;if(t>=232)n=((t-232)*10+8)/255,r=n,s=n;else{t-=16;let a=t%36;n=Math.floor(t/36)/5,r=Math.floor(a/6)/5,s=a%6/5}let o=Math.max(n,r,s)*2;if(o===0)return 30;let i=30+(Math.round(s)<<2|Math.round(r)<<1|Math.round(n));return o===2&&(i+=60),i},enumerable:!1},rgbToAnsi:{value:(t,n,r)=>E.ansi256ToAnsi(E.rgbToAnsi256(t,n,r)),enumerable:!1},hexToAnsi:{value:t=>E.ansi256ToAnsi(E.hexToAnsi256(t)),enumerable:!1}}),E}var fi=pi(),W=fi;import _t from"node:process";import mi from"node:os";import dr from"node:tty";function G(e,t=globalThis.Deno?globalThis.Deno.args:_t.argv){let n=e.startsWith("-")?"":e.length===1?"-":"--",r=t.indexOf(n+e),s=t.indexOf("--");return r!==-1&&(s===-1||r<s)}var{env:v}=_t,Ke;G("no-color")||G("no-colors")||G("color=false")||G("color=never")?Ke=0:(G("color")||G("colors")||G("color=true")||G("color=always"))&&(Ke=1);function pr(){return/^\d+$/.test(v.FORCE_COLOR)}function hi(){if("FORCE_COLOR"in v){if(v.FORCE_COLOR==="false")return 0;if(v.FORCE_COLOR==="true"||v.FORCE_COLOR.length===0)return 1;if(pr())return Math.min(Number.parseInt(v.FORCE_COLOR,10),3)}}function gi(e){return e===0?!1:{level:e,hasBasic:!0,has256:e>=2,has16m:e>=3}}function ki(e,{streamIsTTY:t,sniffFlags:n=!0}={}){let r=hi();r!==void 0&&(Ke=r);let s=n?Ke:r;if(s===0)return 0;if(n){if(G("color=16m")||G("color=full")||G("color=truecolor"))return 3;if(G("color=256"))return 2}if(s!==void 0&&pr())return s;if("TF_BUILD"in v&&"AGENT_NAME"in v)return 1;if(e&&!t&&s===void 0)return 0;let o=s||0;if(v.TERM==="dumb")return o;if(_t.platform==="win32"){let i=mi.release().split(".");return Number(i[0])>=10&&Number(i[2])>=10586?Number(i[2])>=14931?3:2:1}if("CI"in v)return["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(i=>i in v)?3:["TRAVIS","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(i=>i in v)||v.CI_NAME==="codeship"?1:o;if("TEAMCITY_VERSION"in v)return/^(?:9\.0*[1-9]\d*\.|\d{2,}\.)/.test(v.TEAMCITY_VERSION)?1:0;if(v.COLORTERM==="truecolor"||v.TERM==="xterm-kitty"||v.TERM==="xterm-ghostty"||v.TERM==="wezterm")return 3;if("TERM_PROGRAM"in v){let i=Number.parseInt((v.TERM_PROGRAM_VERSION||"").split(".",1)[0],10);switch(v.TERM_PROGRAM){case"iTerm.app":return i>=3?3:2;case"Apple_Terminal":return 2}}return/-256(?:color)?$/i.test(v.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(v.TERM)||"COLORTERM"in v?1:o}function ur(e,t={}){let n=ki(e,{streamIsTTY:e&&e.isTTY,...t});return gi(n)}var yi={stdout:ur({isTTY:dr.isatty(1)}),stderr:ur({isTTY:dr.isatty(2)})},fr=yi;var{stdout:mr,stderr:hr}=fr,xe=Symbol("GENERATOR"),we=Symbol("STYLER"),We=Symbol("IS_EMPTY"),Ve=Symbol("LEVEL"),Ee=Object.create(null),gr=e=>{if(!Number.isSafeInteger(e)||e<0||e>3)throw new Error("The `level` should be an integer from 0 to 3")},Si={enumerable:!0,get(){return this[Ve]},set(e){gr(e),this[Ve]=e}},bi=(e,t={})=>{t.level!==void 0&&gr(t.level);let n=mr?mr.level:0;e[Ve]=t.level===void 0?n:t.level};var Ti=e=>{let t=(...n)=>n.join(" ");return bi(t,e),Object.setPrototypeOf(t,ve.prototype),t};function ve(e){return Ti(e)}Object.setPrototypeOf(ve.prototype,Function.prototype);for(let[e,t]of Object.entries(W))Ee[e]={get(){let n=At(this,kr(t.open,t.close,this[we]),this[We]);return Object.defineProperty(this,e,{value:n}),n}};Ee.visible={get(){let e=At(this,this[we],!0);return Object.defineProperty(this,"visible",{value:e}),e}};var xi=(e,t)=>{let n=W[t];if(e==="rgb"){let s=(i,a,c)=>n.ansi(W.rgbToAnsi(i,a,c));return[s,s,(i,a,c)=>n.ansi256(W.rgbToAnsi256(i,a,c)),n.ansi16m]}if(e==="hex"){let s=i=>n.ansi(W.hexToAnsi(i));return[s,s,i=>n.ansi256(W.hexToAnsi256(i)),i=>n.ansi16m(...W.hexToRgb(i))]}let r=s=>n.ansi(W.ansi256ToAnsi(s));return[r,r,n.ansi256,n.ansi256]},wi=["rgb","hex","ansi256"];for(let e of wi){let t=e[0].toUpperCase()+e.slice(1);for(let[n,r]of[[e,"color"],["bg"+t,"bgColor"],["underline"+t,"underlineColor"]]){let{close:s}=W[r],o=xi(e,r);Ee[n]={get(){let i=function(a,c,l){let u=o[this.level](a,c,l);return At(this,kr(u,s,this[we]),this[We])};return Object.defineProperty(this,n,{value:i}),i}}}}var Ei=Object.defineProperties(()=>{},{...Ee,level:{enumerable:!0,get(){return this[xe].level},set(e){this[xe].level=e}}}),kr=(e,t,n)=>{let r,s;return n===void 0?(r=e,s=t):(r=n.openAll+e,s=t+n.closeAll),{open:e,close:t,openAll:r,closeAll:s,parent:n}},At=(e,t,n)=>{let r=(...s)=>s.length===1?Rt(r,""+s[0]):s.length===2?Rt(r,`${s[0]??""} ${s[1]??""}`):Rt(r,s.join(" "));return Object.setPrototypeOf(r,Ei),r[xe]=e[xe]??e,r[we]=t,r[We]=n,r},Rt=(e,t)=>{if(e[xe][Ve]<=0||!t)return e[We]?"":t;let n=e[we];if(n===void 0)return t;let{openAll:r,closeAll:s}=n;if(t.includes("\x1B"))for(;n!==void 0;)t=or(t,n.close,n.open),n=n.parent;let o=t.indexOf(`
6
+ `);return o!==-1&&(t=ir(t,s,r,o)),r+t+s};Object.defineProperties(ve.prototype,{...Ee,level:Si});var vi=ve(),op=ve({level:hr?hr.level:0});var m=vi;import{Command as lu}from"commander";import*as S from"node:fs";import*as k from"node:path";import{fileURLToPath as pc}from"node:url";import ie from"handlebars";var B="Container Runtime",J="bring-your-own";var j="database-management",q=".tiltignore",yr="service.json",se="docker-compose.yml",C=".autogenerated",Je="TILT_TECH_STACK.star",qe="TILT_RESOURCE_DEFAULTS.star",_="project.json",A="package.json",Dt=[Je,qe,"spec.master"],cp=["backend","frontend","library","sdk","worker","migrator","mcp","agent",J],Ot={backend:["dev","build","start"],worker:["dev","build","start"],migrator:["dev","build","start"],mcp:["dev","build","start"],agent:["dev","build","start"],frontend:["dev","build"],library:["dev","build"],sdk:["dev","build"],[J]:[]};var Nt=["monitoring","elk","debezium","golden_image","verdaccio"],P={frontend:{base:3e3,min:3e3,max:3999,range:"3000-3999"},backend:{base:4e3,min:4e3,max:4999,range:"4000-4999"},mcp:{base:4e3,min:4e3,max:5999,range:"4000-5999"},agent:{base:4e3,min:4e3,max:5999,range:"4000-5999"},[J]:{base:4e3,min:4e3,max:5999,range:"4000-5999"},worker:{base:6e3,min:6e3,max:6999,range:"6000-6999"},health:{base:5e3,min:5e3,max:5999,range:"5000-5999"},migrator:{base:7e3,min:7e3,max:7999,range:"7000-7999"}},Pe={tiltUi:10350,traefik:8080},Ct="https://tdk-landscape.github.io/tdk-website/docs/quickstart/";var Sr=["node_modules",".git",".tilt",".tilt-engine","dist","build",".prisma",".turbo","coverage","tmp","temp","__tests__","test","tests",".github",".vscode","docs"],br=["Dockerfile",se,"docker-compose.yaml","Tiltfile","vite.config.ts","tsconfig.json","tsconfig.build.json"],Pi={infra:"\u{1F3D7}\uFE0F",core:"\u{1F527}",api:"\u26A1",app:"\u{1F3A8}",orchestrator:"\u2699\uFE0F"};function lp(e){let t=e.toLowerCase();for(let[n,r]of Object.entries(Pi))if(t.includes(n))return r;return"\u{1F4E6}"}var $i="1.0.0",_i={runtime:"bun",bundler:"vite",language:"typescript",framework:"hono",database:"postgresql",orm:"prisma",messaging:"nats",linting:"biome",testing:"vitest"},Ri={frontend:{base:P.frontend.base,range:P.frontend.range,start:P.frontend.min,end:P.frontend.max},backend:{base:P.backend.base,range:P.backend.range,start:P.backend.min,end:P.backend.max},health:{base:P.health.base,range:P.health.range,start:P.health.min,end:P.health.max},worker:{base:P.worker.base,range:P.worker.range,start:P.worker.min,end:P.worker.max},migrator:{base:P.migrator.base,range:P.migrator.range,start:P.migrator.min,end:P.migrator.max},tiltUi:Pe.tiltUi,traefik:Pe.traefik},Ai={path:"/health",live:"/health/live",ready:"/health/ready",timeout:30,interval:5},Di={frontend:"-frontend",backend:"-backend",worker:"-worker",migrator:"-migrator",library:"-lib",sdk:"-sdk",validSeparators:["-","_"],maxLength:63,minLength:3},Oi={entrypoint:"web",network:"traefik-public",defaultHost:"localhost",appHost:"app.localhost",apiHost:"api.localhost",appSubdomainPrefix:"app",apiSubdomainPrefix:"api",defaultPort:8080,tlsEnabled:!1,entrypoints:["web"],middlewares:[],tls:{enabled:!1},healthcheckPath:"/health",healthcheckInterval:"10s",healthcheckTimeout:"5s",frontendPriorityBase:100},Ni=["node_modules","dist","build",".git",".prisma",".turbo","coverage","tmp","temp","__tests__","test","tests"],Ci={frontend:{suffix:"-frontend",portRange:"3000-3999"},backend:{suffix:"-backend",portRange:"4000-4999"},library:{suffix:"-library",portRange:null},sdk:{suffix:"-sdk",portRange:"3000-9999"},migrator:{suffix:"-migrator",portRange:"7000-7999"},worker:{suffix:"-worker",portRange:"6000-6999"}},ji={prisma:"Database ORM with migrations",nats:"Event streaming via NATS",redis:"Caching layer",infisical:"Secrets management",vitest:"Testing framework",traefik:"HTTP routing",websocket:"Real-time connections",graphql:"GraphQL support",grpc:"gRPC support",viteNode:"Vite Node runtime",maintenance:"Maintenance mode"},Ii={services:"services/product",sharedPlatform:"shared-platform-engineering",sharedProduct:"shared-product-engineering",sharedDdd:"shared-ddd-layers"},Fi={scanIntervalSeconds:5,maxManifestsPerRoot:50,servicePatterns:["services/product/*","services/platform/*"]},Li={dockerfile:"Dockerfile",context:"."},Mi={backend:{command:"bun",args:["run","dev"],env:{NODE_ENV:"development"}},frontend:{command:"bun",args:["run","dev"],env:{NODE_ENV:"development"}}},L={version:$i,tech:_i,ports:Ri,health:Ai,naming:Di,traefik:Oi,filewatchIgnores:Ni,serviceTypes:Ci,features:ji,paths:Ii,discovery:Fi,docker:Li,runtime:Mi};import{randomBytes as Ui}from"node:crypto";import{closeSync as Bi,fchmodSync as Hi,fsyncSync as Gi,openSync as Ki,renameSync as Vi,rmSync as Wi,statSync as Ji,writeFileSync as qi}from"node:fs";import{basename as zi,dirname as Yi,join as Xi}from"node:path";function $e(e,t){let n=Xi(Yi(e),`.${zi(e)}.${process.pid}.${Ui(4).toString("hex")}.tmp`),r;try{r=Ji(e).mode&511}catch{r=void 0}try{let s=Ki(n,"wx");try{r!==void 0&&Hi(s,r),qi(s,t,"utf-8"),Gi(s)}finally{Bi(s)}Vi(n,e)}catch(s){throw Wi(n,{force:!0}),s}}import{appendFileSync as Qi,existsSync as Tr,mkdirSync as Zi,readFileSync as ea,writeFileSync as xr}from"node:fs";import{resolve as jt}from"node:path";function bp(e,t,n){for(let[r,s]of t.entries())console.log(m.blue(`${s.emoji} ${s.description}...`)),s.type==="json"?na(e,s.filename,s.content):ra(e,s.filename,String(s.content)),n&&n(s,r,t.length)}function ta(e,t,n=2){let r=`${JSON.stringify(t,null,n)}
7
+ `;xr(e,r,"utf-8")}function na(e,t,n,r=2){let s=jt(e,t);ta(s,n,r)}function It(e,t){xr(e,t,"utf-8")}function ra(e,t,n){let r=jt(e,t);It(r,n)}function Tp(e){Tr(e)||Zi(e,{recursive:!0})}var sa=[".env",".tdk/.tdk-out/",".tdk/.project-id",".tdk/smoke/","node_modules/"];function xp(e){let t=jt(e,".gitignore"),n=Tr(t)?ea(t,"utf-8"):"",r=new Set(n.split(`
8
+ `).map(a=>a.trim().replace(/\/$/,""))),s=sa.filter(a=>!r.has(a.replace(/\/$/,"")));if(s.length===0)return[];let o=n&&!n.endsWith(`
9
9
  `)?`
10
- `:"";return Xi(t,`${o}${n?`
10
+ `:"";return Qi(t,`${o}${n?`
11
11
  # TDK (generated files and secrets)
12
12
  `:`# TDK (generated files and secrets)
13
13
  `}${s.join(`
14
14
  `)}
15
- `),s}import{existsSync as sa,lstatSync as oa}from"node:fs";import{isAbsolute as wr,normalize as ze,relative as ia,sep as Er}from"node:path";var vp=[`${C}/**`,".tdk/.tdk-out/**","Tiltfile","TILT_*.star",q,`${A} (create only)`,"shared-platform-engineering/docker-templates/**","services/platform/database-management/docker-compose.yml","product_autogenerated_resource_manifests/**","product_autogenerated_services_list/**"];function aa(e){let t=ze(e).split(Er).join("/");return wr(e)||t===".."||t.startsWith("../")?!1:t.split("/").includes(C)||t.startsWith(".tdk/.tdk-out/")||t==="shared-platform-engineering/docker-templates"||t.startsWith("shared-platform-engineering/docker-templates/")||t.startsWith("product_autogenerated_resource_manifests/")||t.startsWith("product_autogenerated_services_list/")?!0:t==="Tiltfile"||/^TILT_[^/]+\.star$/.test(t)||t===q||t===A||t==="services/platform/database-management/docker-compose.yml"}function oe(e,t){let n=wr(t)?ze(t):ze(`${e}/${t}`),r=ia(e,n).split(Er).join("/");if(!aa(r))throw new Error(`Refusing to write outside TDK's generated-file allowlist: ${r}`);let s=e;for(let o of r.split("/"))if(s=ze(`${s}/${o}`),sa(s)&&oa(s).isSymbolicLink())throw new Error(`Refusing to write through a symbolic link in generated path: ${r}`);return n}var _e=[j,"proxy"];import{existsSync as Gr,readFileSync as Vr}from"node:fs";import{copyFileSync as Ar,mkdirSync as ya,rmSync as Dr,writeFileSync as Or}from"node:fs";import{join as de}from"node:path";function I(e){return e==="backend"||e==="mcp"||e==="agent"}import{readFileSync as ma}from"node:fs";import{join as ha}from"node:path";import{existsSync as ua}from"node:fs";import{dirname as la,join as da,resolve as Pr}from"node:path";import{cwd as pa}from"node:process";var vr={name:"tdk-cli-internal",private:!0,version:"1.3.175",description:"TDK CLI \u2014 start services on your machine.",keywords:["tdk","tilt","cli","local-dev","microservices"],homepage:"https://github.com/tdk-landscape/tdk-cli-core#readme",bugs:{url:"https://github.com/tdk-landscape/tdk-cli-core/issues"},repository:{type:"git",url:"git+https://github.com/tdk-landscape/tdk-cli-core.git",directory:"cli"},license:"MIT",author:"TDK Team",type:"module",main:"./dist/index.js",types:"./dist/index.d.ts",bin:{tdk:"bin/tdk.js","tdk-cli":"bin/tdk.js"},files:["dist","dist-bundle","bin","templates","README.md","Tiltfile","engine","discovery","specs","ext","!ext/ide-components/code_executor","shared-platform-engineering/docker-templates"],scripts:{build:"tsc && node scripts/bundle.mjs","build:watch":"tsc --watch",lint:"biome check .","lint:fix":"biome check . --write",typecheck:"tsc --project tsconfig.typecheck.json",clean:"rm -rf dist",dev:"bun run build:watch",test:"vitest run","test:watch":"vitest",prepack:"../scripts/stage-npm-engine.sh && npm run build"},dependencies:{commander:"^15.0.0",handlebars:"^4.7.8"},devDependencies:{"@biomejs/biome":"^2.5.13","@types/node":"^22.0.0","@types/react":"^19.3.0",ajv:"^8.17.1",chalk:"^6.0.1",esbuild:"^0.28.2",ink:"^8.0.0",knip:"^6.38.0",react:"^19.3.0","react-devtools-core":"^8.0.0",typescript:"^7.0.2",vite:"^8.3.1",vitest:"^5.0.0"},engines:{node:">=22.12.0"}};function y(e=pa()){let t=Pr(e),n=Pr("/");for(;t!==n;){if(ua(da(t,".tdk",_)))return t;let r=la(t);if(r===t)break;t=r}return null}var Ye=null;function fa(){if(Ye)return Ye;let e=vr;if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Invalid package.json: expected object");let t=e;return Ye={name:String(t.name??"@tdk-landscape/tdk-cli-core"),version:String(t.version??"0.0.0"),fullPackage:t},Ye}function $r(){return fa().version}function le(){let e=y();if(e)try{let t=ma(ha(e,".tdk",_),"utf-8"),n=JSON.parse(t);if(n?.project?.name)return n.project.name}catch{}return"tdk-project"}function Ft(e){let t=le(),n=process.env.TDK_SERVICE_BASE_URL??`http://${t}.localhost${e?`:${e}`:""}`;try{let r=new URL(n.includes("://")?n:`http://${n}`),s=r.hostname,o=r.protocol==="https:"?"443":"80",i=r.port||(e?String(e):""),a=i===o?"":i;if(s==="localhost"||/^\d+\.\d+\.\d+\.\d+$/.test(s))return{appBase:`${r.protocol}//${s}${a?`:${a}`:""}`,apiBase:`${r.protocol}//${s}${a?`:${a}`:""}`};let c=s.replace(/^(app|api)\./,"");return{appBase:`${r.protocol}//app.${c}${a?`:${a}`:""}`,apiBase:`${r.protocol}//api.${c}${a?`:${a}`:""}`}}catch{return{appBase:`http://app.${t}.localhost`,apiBase:`http://api.${t}.localhost`}}}function ga(e){return`${e.replace(/\/+$/,"")}/health`}function Lt(e){if(I(e.config?.appType)){let t=e.name.replace(/-api$/,"");return e.config?.apiPath??`/api/${t}`}return e.config?.basePath??`/${e.name}`}function Mt(e,t){return Rr(e,t,n=>ga(n))}function _r(e,t){return Rr(e,t,n=>n)}function Rr(e,t,n){let{appBase:r,apiBase:s}=Ft(t);return e.filter(o=>o.config?.appType==="frontend"||I(o.config?.appType)).map(o=>{let i=I(o.config.appType)?s:r;return{name:o.name,appType:o.config.appType,url:`${i}${n(Lt(o))}`}})}async function ka(e,t){try{let n=await fetch(e.url,{method:"GET",redirect:"manual",signal:AbortSignal.timeout(t)});return{...e,ok:n.ok,status:n.status}}catch(n){let r=n instanceof Error&&n.name==="TimeoutError"?`no response within ${t}ms`:n instanceof Error?n.message:String(n);return{...e,ok:!1,error:r}}}async function Xe(e,t){return Promise.all(e.map(n=>ka(n,t)))}var Lr=60,Nr=1e3,Cr=1e4,jr=200,Ir=64*1024,Fr=new Set([404,502,503,504]),Sa=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","EHOSTUNREACH","ENETUNREACH"]),ba=new Set(["GET","HEAD","OPTIONS"]);function X(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Ta(e,t){if(ba.has(t))return!0;if(!X(e))return!1;let n=X(e.cause)?e.cause:void 0,r=e.code??n?.code;return typeof r=="string"&&Sa.has(r)}function Bt(e){if(!X(e))return['smoke: must be an object with "via" and "steps"'];let t=[];return e.via!=="proxy"&&t.push('smoke.via: only "proxy" is supported (the check must go through the public URL)'),e.timeoutSeconds!==void 0&&!(typeof e.timeoutSeconds=="number"&&e.timeoutSeconds>0)&&t.push("smoke.timeoutSeconds: must be a number greater than 0"),!Array.isArray(e.steps)||e.steps.length===0?(t.push("smoke.steps: needs at least one step"),t):(e.steps.forEach((n,r)=>{let s=`smoke.steps[${r}]`;if(!X(n)){t.push(`${s}: must be an object`);return}let o=n.path;(typeof o!="string"||!o.startsWith("/")||o.startsWith("//"))&&t.push(`${s}.path: must start with "/" and is appended to the public URL; a full URL or relative path would skip the proxy`),n.expect!==void 0&&!(typeof n.expect=="number"&&Number.isInteger(n.expect)&&n.expect>=100&&n.expect<=599)&&t.push(`${s}.expect: must be an HTTP status between 100 and 599`),n.bodyContains!==void 0&&typeof n.bodyContains!="string"&&t.push(`${s}.bodyContains: must be a string`),n.save!==void 0&&(X(n.save)&&Object.values(n.save).every(a=>typeof a=="string"&&a.startsWith("$."))||t.push(`${s}.save: must map names to paths such as "$.id"`))}),t)}function Mr(e,t){let{appBase:n,apiBase:r}=Ft(t),s=[];for(let o of e){let i=o.config;if(!i?.smoke)continue;let a=i.appType,c=I(a)||a===J;if(!c&&a!=="frontend"||i.exposeViaProxy===!1)continue;let u=c?r:n,d=i.healthCheckPath||(c&&a!==J?"/health":void 0);s.push({name:o.name,baseUrl:`${u}${Lt(o).replace(/\/+$/,"")}`,...d?.startsWith("/")?{readyPath:d}:{},smoke:i.smoke})}return s}var xa=10;function Ur(e,t={}){let n=t.timeoutSeconds??xa;return e.flatMap(r=>{let s=r.smoke.steps.filter(i=>(i.method??"GET").toUpperCase()==="GET"&&i.body===void 0&&!i.path.includes("{{")).map(i=>({...i,bodyContains:void 0}));if(s.length===0)return[];let o=Math.min(r.smoke.timeoutSeconds??Lr,n);return[{name:r.name,baseUrl:r.baseUrl,smoke:{via:r.smoke.via,timeoutSeconds:o,steps:s}}]})}function wa(e,t){let n=t.replace(/^\$\.?/,"").match(/[^.[\]]+/g)??[],r=e;for(let s of n){if(r==null||s==="__proto__"||s==="constructor"||s==="prototype"||!Object.hasOwn(r,s))return;let o=Object.getOwnPropertyDescriptor(r,s);if(!o||!("value"in o))return;r=o.value}return r}function Br(e,t){return e.replace(/\{\{(\w+)\}\}/g,(n,r)=>t[r]??n)}function Ut(e,t){return typeof e=="string"?Br(e,t):Array.isArray(e)?e.map(n=>Ut(n,t)):X(e)?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,Ut(r,t)])):e}function Qe(e){let t=e.replace(/\s+/g," ").trim();return t.length>jr?`${t.slice(0,jr)}...`:t}function Hr(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"step"}function Ea(e,t){let n=Hr(t),r=(e.get(n)??0)+1;return e.set(n,r),r===1?n:`${n}-${r}`}function va(e,t,n,r,s){try{let o=de(e,Hr(n.service),t);ya(o,{recursive:!0});let i=de(o,"latest.json"),a=de(o,"body.txt");return r===void 0?Dr(a,{force:!0}):Or(a,r),Or(i,`${JSON.stringify({...n,bodyPath:r===void 0?null:"body.txt"},null,2)}
16
- `),s&&(Ar(i,de(o,"last-success.json")),r===void 0?Dr(de(o,"last-success-body.txt"),{force:!0}):Ar(a,de(o,"last-success-body.txt"))),i}catch{return}}function Pa(e){let t=Buffer.from(e,"utf8");if(t.length<=Ir)return{body:e,truncated:!1,bytes:t.length};let n=t.subarray(0,Ir).toString("utf8").replace(/\uFFFD$/,"");return{body:n,truncated:!0,bytes:Buffer.byteLength(n,"utf8")}}async function $a(e,t={}){let n=t.fetch??((d,l)=>fetch(d,l)),r=t.now??Date.now,s=t.sleep??(d=>new Promise(l=>setTimeout(l,d))),o=(e.smoke.timeoutSeconds??Lr)*1e3,i=r()+o,a={},c=Bt(e.smoke);if(c.length>0)return{name:e.name,ok:!1,failure:`${e.name}: invalid smoke block: ${c.join("; ")}`};if(e.readyPath){let d=`${e.baseUrl}${e.readyPath}`;for(;;){try{let l=await n(d,{method:"GET",signal:AbortSignal.timeout(Cr)});if(await l.text(),!Fr.has(l.status)&&l.status<500)break}catch{}if(r()>=i)break;await s(Nr)}}i=r()+o;let u=new Map;for(let[d,l]of e.smoke.steps.entries()){let p=l.name??`step ${d+1}`,h=(l.method??"GET").toUpperCase(),f=`${e.baseUrl}${Br(l.path,a)}`,b=l.expect??200,w=l.body!==void 0,$,U="",g,R;for(;;){g=void 0,R=void 0,$=void 0;let G=!1;try{let F=await n(f,{method:h,headers:w?{"content-type":"application/json"}:void 0,body:w?JSON.stringify(Ut(l.body,a)):void 0,signal:AbortSignal.timeout(Cr)});$=F.status,U=await F.text()}catch(F){G=Ta(F,h),g=F instanceof Error?F.message:String(F);let re=X(F)?F.code??(X(F.cause)?F.cause.code:void 0):void 0;R=typeof re=="string"?re:void 0}if(!(g!==void 0&&G||$!==void 0&&$!==b&&Fr.has($))||r()>=i)break;await s(Nr)}let ne=`${e.name}: ${p}: ${h} ${f}`,ue;if(t.recordDir){let G=$===void 0?void 0:Pa(U),Te=g===void 0&&$===b&&(l.bodyContains===void 0||U.includes(l.bodyContains));ue=va(t.recordDir,Ea(u,p),{service:e.name,step:p,method:h,url:f,expectedStatus:b,status:$??null,...g===void 0?{}:{error:R??g},truncated:G?.truncated??!1,bodyBytes:G?.bytes??0},G?.body,Te)}let be=G=>({name:e.name,ok:!1,failure:G,recordPath:ue});if(g!==void 0)return be(`${ne} never answered (${g})`);if($!==b)return be(`${ne} returned ${$}, expected ${b}${U?`: ${Qe(U)}`:""}`);if(l.bodyContains!==void 0&&!U.includes(l.bodyContains))return be(`${ne} returned ${$} but the body does not contain "${l.bodyContains}": ${Qe(U)}`);if(l.save){let G;try{G=JSON.parse(U)}catch{return be(`${ne} returned a body that is not JSON, cannot save: ${Qe(U)}`)}for(let[Te,F]of Object.entries(l.save)){let re=wa(G,F);if(re==null||typeof re=="object")return be(`${ne} response has no ${F} to save as {{${Te}}}: ${Qe(U)}`);a[Te]=String(re)}}}return{name:e.name,ok:!0}}function qp(e){return`Smoke check failed: ${e.failure}${e.recordPath?` (record: ${e.recordPath})`:""}`}async function Kr(e,t={}){return Promise.all(e.map(n=>$a(n,t)))}var Re=1,Qp="https://tdk-landscape.github.io/schema.service.json",_a={dependencies:"deprecated, use dependsOn (still read for now)",envVars:"deprecated, use params (still read when params is absent)",jwtSecret:"ignored. A secret must not be committed: remove it and set JWT_SECRET in the project .env"},Ra=new Set(["$schema","agent","apiBasePath","apiPath","appName","appType","backendName","basePath","build","buildContext","databaseName","dependencies","dev","dependsOn","dockerfile","enabled","exposeViaProxy","featuresEnabled","framework","healthCheckPath","image","language","name","nats","params","playwright","port","replicas","restart","runtime","sablier","schemaVersion","secrets","smoke","stack","syncs","traefik","type"]),Aa=[{path:["healthCheckPath"],pattern:/^\/[a-z0-9/-]*$/,expected:"a path such as /health"},{path:["traefik","host"],pattern:/^[A-Za-z0-9.-]+$/,expected:"a hostname such as shop.backend.myproject.local"},{path:["traefik","pathPrefix"],pattern:/^\/[a-z0-9/-]*$/,expected:"a path such as /api/v1/shop-management"},{path:["traefik","healthCheck"],pattern:/^\/[a-z0-9/-]*$/,expected:"a path such as /health"},{path:["nats","queueGroup"],pattern:/^[A-Za-z0-9_.-]+$/,expected:"letters, digits, '_', '.' or '-'"},{path:["databaseName"],pattern:/^[A-Za-z0-9_-]+$/,expected:"letters, digits, '_' or '-'"},{path:["stack"],pattern:/^[A-Za-z0-9_-]+$/,expected:"letters, digits, '_' or '-'"},{path:["image"],pattern:/^[A-Za-z0-9._/:@-]+$/,expected:"an image reference such as ghcr.io/acme/app:1.0"}];function Ze(e,t){let n=[],r=new Set;for(let{path:s,pattern:o,expected:i}of Aa){let a=e;for(let u of s)a=a&&typeof a=="object"&&!Array.isArray(a)?a[u]:void 0;if(a==null||a==="")continue;let c=`${t}.${s.join(".")}`;(typeof a!="string"||!o.test(a))&&r.add(c),typeof a!="string"?n.push(`${c}: expected a string`):o.test(a)||n.push(`${c}: must be ${i} (no spaces, line breaks or YAML syntax)`)}for(let[s,o]of Da(e,t))r.has(s)||n.push(`${s}: ${o}`);return n}function Ht(e){for(let t=0;t<e.length;t++){let n=e.charCodeAt(t);if(n<32||n===127||n===133||n===8232||n===8233)return!0}return!1}function Da(e,t){let n=[],r=Object.entries(e).filter(([s])=>s!=="smoke").map(([s,o])=>[o,`${t}.${s}`]);for(let s of Object.keys(e))Ht(s)&&n.push([t,"a key contains a line break"]);for(;r.length>0;){let[s,o]=r.pop();if(typeof s=="string")Ht(s)&&n.push([o,"must not contain line breaks or control characters"]);else if(Array.isArray(s))for(let[i,a]of s.entries())r.push([a,`${o}[${i}]`]);else if(s&&typeof s=="object")for(let[i,a]of Object.entries(s))Ht(i)?n.push([o,"a key contains a line break"]):r.push([a,`${o}.${i}`])}return n.sort(([s],[o])=>s.localeCompare(o))}var Oa=["apiPath","basePath"];function Kt(e){if(!e||typeof e!="object"||Array.isArray(e))return[];let t=e;return Oa.filter(n=>n in t&&typeof t[n]!="string")}function Gt(e,t){if(!e||typeof e!="object"||Array.isArray(e))return{errors:[`${t}: expected a JSON object`],warnings:[]};let n=e,r=[];for(let a of["appName","appType","stack","schemaVersion"])a in n||r.push(`${t}.${a}: required field is missing`);for(let a of["appName","appType","stack"])a in n&&typeof n[a]!="string"&&r.push(`${t}.${a}: expected a string`);"schemaVersion"in n&&n.schemaVersion!==Re&&r.push(`${t}.schemaVersion: unsupported version ${String(n.schemaVersion)} (supported: ${Re})`);for(let a of Kt(n))r.push(`${t}.${a}: expected a string`);let s=n.dev,o=s&&typeof s=="object"&&!Array.isArray(s)?s.liveReload:void 0;if(o!==void 0&&typeof o!="boolean"&&r.push(`${t}.dev.liveReload: expected true or false`),r.push(...Ze(n,t)),"smoke"in n)for(let a of Bt(n.smoke))r.push(`${t}.${a}`);let i=Object.keys(n).flatMap(a=>{let c=_a[a];return c?[`${t}.${a}: ${c}`]:Ra.has(a)?[]:[`${t}.${a}: unknown field is preserved`]});return o===!0&&n.language!=="go"&&i.push(`${t}.dev.liveReload: only applies to Go services (language "go"); it is ignored here`),{errors:r,warnings:i,manifest:n}}function Wr(e,t){if(!Gr(e))return[];try{let n=JSON.parse(Vr(e,"utf-8"));return!n||typeof n!="object"||Array.isArray(n)?[]:Ze(n,t)}catch{return[]}}function Jr(e,t){if(!Gr(e))return{errors:[`${t}: file is missing`],warnings:[]};try{let n=JSON.parse(Vr(e,"utf-8"));return Gt(n,t)}catch(n){let r=n instanceof Error?n.message:String(n);return{errors:[`${t}: invalid JSON (${r})`],warnings:[]}}}import{existsSync as pe,readdirSync as ls,readFileSync as ds,statSync as Xt}from"node:fs";import{dirname as tc,join as Z}from"node:path";var Ae=class{data;options;constructor(t){this.data=new Map,this.options=t}has(t){let n=this.data.get(t);return n?Date.now()-n.timestamp>this.options.ttlMs?(this.data.delete(t),!1):!0:!1}get(t){if(this.has(t))return this.data.get(t)?.value}set(t,n){this.data.set(t,{value:n,timestamp:Date.now()})}delete(t){this.data.delete(t)}clear(){this.data.clear()}keys(){let t=[];for(let n of this.data.keys())this.has(n)&&t.push(n);return t}size(){return this.keys().length}};function qr(e){let t=0;return{isValid(){return Date.now()-t<e},markUpdated(){t=Date.now()},reset(){t=0}}}import{execFileSync as Fa,execSync as La}from"node:child_process";import{existsSync as zr}from"node:fs";import{delimiter as Yr,extname as Xr,join as Qr}from"node:path";import{delimiter as nf,extname as Na}from"node:path";function De(){return process.platform==="win32"}function Ca(e){return e==="linux"?"linux":e==="darwin"?"darwin":e==="win32"?"windows":null}function ja(e){return e==="x64"?"amd64":e==="arm64"?"arm64":null}function Ia(e,t){let n=Ca(e),r=ja(t);if(!n||!r||n==="windows"&&r!=="amd64")return null;let s=`tdk-${n}-${r}`;return n==="windows"?`${s}.exe`:s}function rf(){return Ia(process.platform,process.arch)}function sf(){return De()?"tdk.exe":"tdk"}function Vt(e,t=De()){return t?Na(e)?[e]:[e,`${e}.exe`,`${e}.cmd`,`${e}.bat`]:[e]}function O(e){let t=process.env.PATH??process.env.Path??"",n=De(),r=Vt(e,n);if(n&&!Xr(e))for(let s of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let o=s.toLowerCase();o&&!r.includes(`${e}${o}`)&&r.push(`${e}${o}`)}for(let s of t.split(Yr))if(s)for(let o of r){let i=Qr(s,o);if(zr(i))return i}return null}function Zr(e){let t=process.env.PATH??process.env.Path??"",n=De(),r=Vt(e,n);if(n&&!Xr(e))for(let i of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let a=i.toLowerCase();a&&!r.includes(`${e}${a}`)&&r.push(`${e}${a}`)}let s=[],o=new Set;for(let i of t.split(Yr))if(i)for(let a of r){let c=Qr(i,a);if(!zr(c))continue;let u=n?c.toLowerCase():c;o.has(u)||(o.add(u),s.push(c))}return s}var es=1e4;function ts(){let e=!1;if(process.platform==="win32")try{return Fa(O("docker")??"docker",["ps"],{stdio:"ignore",timeout:es,windowsHide:!0}),"running"}catch(t){return t.code==="ETIMEDOUT"?"unresponsive":"missing"}for(let t of["docker ps","colima status","podman ps"])try{return La(t,{stdio:"ignore",timeout:es}),"running"}catch(n){n.code==="ETIMEDOUT"&&(e=!0)}return e?"unresponsive":"missing"}function et(e,t){return e[t]??0}function Ma(e,t){let n=Array.from({length:t.length+1},(r,s)=>s);for(let r=1;r<=e.length;r++){let s=[r];for(let o=1;o<=t.length;o++){let i=e[r-1]===t[o-1]?0:1;s[o]=Math.min(et(s,o-1)+1,et(n,o)+1,et(n,o-1)+i)}n=s}return et(n,t.length)}function Ua(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length-1;n++)if(e[n]!==t[n]&&e[n]===t[n+1]&&e[n+1]===t[n]&&e.slice(0,n)===t.slice(0,n)&&e.slice(n+2)===t.slice(n+2))return!0;return!1}function ns(e,t){if(e.length<2||t.length===0||t.includes(e))return;let n=e.toLowerCase(),r,s=Number.POSITIVE_INFINITY;for(let o of t){if(o.length===0)continue;let i=o.toLowerCase(),a=Ua(n,i)?1:Ma(n,i),c=Math.max(1,Math.min(2,Math.floor(Math.max(n.length,i.length)/3)));a>c||(a<s||a===s&&(r===void 0||o<r))&&(r=o,s=a)}return r}import{spawn as Ba}from"node:child_process";import{join as Ha}from"node:path";function Ka(e,t=[],n={}){return new Promise((r,s)=>{let o=[e,...t];n.verbose&&console.log(`Executing: tilt ${o.join(" ")}`);let i=Ba(O("tilt")??"tilt",o,{stdio:n.inheritStdio?"inherit":"pipe",shell:!1,windowsHide:process.platform==="win32",timeout:n.timeoutMs}),a="",c="";n.inheritStdio||(i.stdout?.on("data",u=>{a+=u.toString()}),i.stderr?.on("data",u=>{c+=u.toString()})),i.on("close",u=>{r({exitCode:u??1,stdout:a,stderr:c})}),i.on("error",u=>{s(new Error(`Failed to spawn tilt: ${u.message}`))})})}async function rs(){try{return(await Ka("version",[],{inheritStdio:!1,timeoutMs:1e4})).exitCode===0}catch{return!1}}function Ga(){let e=y();if(!e)throw Y.notInProject();return Ha(e,".tdk",".tdk-out","Tiltfile")}function ss(e){let t=Ga();e.push("-f",t)}function bf(e,t={}){let n=[];return ss(n),t.focusTargets&&t.focusTargets.length>0&&n.push("--",`--focus=${t.focusTargets.join(",")}`),n.push(...e),t.verbose&&!t.quiet&&n.push("--verbose"),t.watch&&n.push("--watch"),n}function Tf(e={}){let t=[];return ss(t),e.focusTargets&&e.focusTargets.length>0&&t.push("--",`--focus=${e.focusTargets.join(",")}`),t}function os(e){return e instanceof Error?e.message:String(e)}function Rf(e,t){if(process.env.TDK_VERBOSE){let n=t!==void 0?`: ${os(t)}`:"";console.warn(m.gray(`${e}${n}`))}}var N=class extends Error{suggestions;exitCode;constructor(t,n=[],r=1){super(t),this.name="TdkError",this.suggestions=n,this.exitCode=r}display(){Ja(this.message,void 0,this.suggestions)}exit(){this.display(),process.exit(this.exitCode)}};function Wt(e,t,n=!1){let r=new Set;for(let s of e){let o=ns(s,t);o&&r.add(n?`Did you mean "${o}" for "${s}"?`:`Did you mean "${o}"?`)}return[...r]}var Y={tiltNotInstalled:()=>new N("Tilt CLI is not installed",["Install Tilt: `brew install tilt` (macOS)","Or download from: https://docs.tilt.dev/install.html","Verify with: `tilt version`",`Setup guide: ${Ct}`]),dockerNotAvailable:()=>new N("Docker (or a compatible container runtime) is not running",["Start Docker Desktop, then verify with: `docker ps`","Or start Colima: `colima start`","Or start the Docker service on Linux: `sudo systemctl start docker`",`Setup guide: ${Ct}`]),dockerNotResponding:()=>new N("Docker is running but not responding (`docker ps` hung for 10s)",["Quit and reopen Docker Desktop, or run `colima restart`","Then verify with: `docker ps`"]),stackNotFound:(e,t=[])=>new N(`Stack "${e}" not found`,[...Wt([e],t),"Run `tdk stacks` to see available stacks","Run `tdk stack` to assign resources to a stack"]),resourceNotFound:(e,t=[])=>new N(`Resource "${e}" not found`,[...Wt([e],t),"Run `tdk resources` to list all resources","Check the resource name spelling"]),unknownServices:(e,t)=>{let n=Wt(e,t,e.length>1);return new N(`Unknown service ${e.join(", ")}. Valid names: ${t.join(", ")}`,n,2)},directoryExists:e=>new N(`Directory already exists: ${e}`,["Use `--path` to specify a different location","Remove the existing directory if no longer needed"]),invalidPath:e=>new N(`Invalid path: ${e}`,["Path must be within the project directory",'Path cannot contain special characters like <>:"|?*']),notInProject:()=>new N("Could not find project root (no .tdk/project.json found)",["Run this from within a TDK project","Run `tdk project --yes` to initialize a new project"])};function Af(){let e=y();return e||Y.notInProject().exit()}function Va(e){e instanceof N&&e.exit(),console.error(m.red(`Error: ${os(e)}`)),process.exit(1)}async function Wa(e,t){try{return await e()}catch(n){return t?.verbose&&n instanceof Error&&n.stack&&console.error(m.gray(n.stack)),Va(n)}}async function Df(e,t){let n=[],r=ts();return r==="unresponsive"?n.push(Y.dockerNotResponding()):r==="missing"&&n.push(Y.dockerNotAvailable()),await rs()||n.push(Y.tiltNotInstalled()),n.length>0&&(console.error(m.red(`
15
+ `),s}import{existsSync as oa,lstatSync as ia}from"node:fs";import{isAbsolute as wr,normalize as ze,relative as aa,sep as Er}from"node:path";var $p=[`${C}/**`,".tdk/.tdk-out/**","Tiltfile","TILT_*.star",q,`${A} (create only)`,"shared-platform-engineering/docker-templates/**","services/platform/database-management/docker-compose.yml","product_autogenerated_resource_manifests/**","product_autogenerated_services_list/**"];function ca(e){let t=ze(e).split(Er).join("/");return wr(e)||t===".."||t.startsWith("../")?!1:t.split("/").includes(C)||t.startsWith(".tdk/.tdk-out/")||t==="shared-platform-engineering/docker-templates"||t.startsWith("shared-platform-engineering/docker-templates/")||t.startsWith("product_autogenerated_resource_manifests/")||t.startsWith("product_autogenerated_services_list/")?!0:t==="Tiltfile"||/^TILT_[^/]+\.star$/.test(t)||t===q||t===A||t==="services/platform/database-management/docker-compose.yml"}function oe(e,t){let n=wr(t)?ze(t):ze(`${e}/${t}`),r=aa(e,n).split(Er).join("/");if(!ca(r))throw new Error(`Refusing to write outside TDK's generated-file allowlist: ${r}`);let s=e;for(let o of r.split("/"))if(s=ze(`${s}/${o}`),oa(s)&&ia(s).isSymbolicLink())throw new Error(`Refusing to write through a symbolic link in generated path: ${r}`);return n}var _e=[j,"proxy"];import{existsSync as Kr,readFileSync as Vr}from"node:fs";import{copyFileSync as Ar,mkdirSync as Sa,rmSync as Dr,writeFileSync as Or}from"node:fs";import{join as ue}from"node:path";function I(e){return e==="backend"||e==="mcp"||e==="agent"}import{readFileSync as ha}from"node:fs";import{join as ga}from"node:path";import{existsSync as da}from"node:fs";import{dirname as ua,join as pa,resolve as Pr}from"node:path";import{cwd as fa}from"node:process";var vr={name:"tdk-cli-internal",private:!0,version:"1.3.177",description:"TDK CLI \u2014 start services on your machine.",keywords:["tdk","tilt","cli","local-dev","microservices"],homepage:"https://github.com/tdk-landscape/tdk-cli-core#readme",bugs:{url:"https://github.com/tdk-landscape/tdk-cli-core/issues"},repository:{type:"git",url:"git+https://github.com/tdk-landscape/tdk-cli-core.git",directory:"cli"},license:"MIT",author:"TDK Team",type:"module",main:"./dist/index.js",types:"./dist/index.d.ts",bin:{tdk:"bin/tdk.js","tdk-cli":"bin/tdk.js"},files:["dist","dist-bundle","bin","templates","README.md","Tiltfile","engine","discovery","specs","ext","!ext/ide-components/code_executor","shared-platform-engineering/docker-templates"],scripts:{build:"tsc && node scripts/bundle.mjs","build:watch":"tsc --watch",lint:"biome check .","lint:fix":"biome check . --write",typecheck:"tsc --project tsconfig.typecheck.json",clean:"rm -rf dist",dev:"bun run build:watch",test:"vitest run","test:watch":"vitest",prepack:"../scripts/stage-npm-engine.sh && npm run build"},dependencies:{commander:"^15.0.0",handlebars:"^4.7.8"},devDependencies:{"@biomejs/biome":"^2.5.13","@types/node":"^22.0.0","@types/react":"^19.3.0",ajv:"^8.17.1",chalk:"^6.0.1",esbuild:"^0.28.2",ink:"^8.0.0",knip:"^6.38.0",react:"^19.3.0","react-devtools-core":"^8.0.0",typescript:"^7.0.2",vite:"^8.3.1",vitest:"^5.0.0"},engines:{node:">=22.12.0"}};function y(e=fa()){let t=Pr(e),n=Pr("/");for(;t!==n;){if(da(pa(t,".tdk",_)))return t;let r=ua(t);if(r===t)break;t=r}return null}var Ye=null;function ma(){if(Ye)return Ye;let e=vr;if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Invalid package.json: expected object");let t=e;return Ye={name:String(t.name??"@tdk-landscape/tdk-cli-core"),version:String(t.version??"0.0.0"),fullPackage:t},Ye}function $r(){return ma().version}function de(){let e=y();if(e)try{let t=ha(ga(e,".tdk",_),"utf-8"),n=JSON.parse(t);if(n?.project?.name)return n.project.name}catch{}return"tdk-project"}function Ft(e){let t=de(),n=process.env.TDK_SERVICE_BASE_URL??`http://${t}.localhost${e?`:${e}`:""}`;try{let r=new URL(n.includes("://")?n:`http://${n}`),s=r.hostname,o=r.protocol==="https:"?"443":"80",i=r.port||(e?String(e):""),a=i===o?"":i;if(s==="localhost"||/^\d+\.\d+\.\d+\.\d+$/.test(s))return{appBase:`${r.protocol}//${s}${a?`:${a}`:""}`,apiBase:`${r.protocol}//${s}${a?`:${a}`:""}`};let c=s.replace(/^(app|api)\./,"");return{appBase:`${r.protocol}//app.${c}${a?`:${a}`:""}`,apiBase:`${r.protocol}//api.${c}${a?`:${a}`:""}`}}catch{return{appBase:`http://app.${t}.localhost`,apiBase:`http://api.${t}.localhost`}}}function ka(e){return`${e.replace(/\/+$/,"")}/health`}function Lt(e){if(I(e.config?.appType)){let t=e.name.replace(/-api$/,"");return e.config?.apiPath??`/api/${t}`}return e.config?.basePath??`/${e.name}`}function Mt(e,t){return Rr(e,t,n=>ka(n))}function _r(e,t){return Rr(e,t,n=>n)}function Rr(e,t,n){let{appBase:r,apiBase:s}=Ft(t);return e.filter(o=>o.config?.appType==="frontend"||I(o.config?.appType)).map(o=>{let i=I(o.config.appType)?s:r;return{name:o.name,appType:o.config.appType,url:`${i}${n(Lt(o))}`}})}async function ya(e,t){try{let n=await fetch(e.url,{method:"GET",redirect:"manual",signal:AbortSignal.timeout(t)});return{...e,ok:n.ok,status:n.status}}catch(n){let r=n instanceof Error&&n.name==="TimeoutError"?`no response within ${t}ms`:n instanceof Error?n.message:String(n);return{...e,ok:!1,error:r}}}async function Xe(e,t){return Promise.all(e.map(n=>ya(n,t)))}var Lr=60,Nr=1e3,Cr=1e4,jr=200,Ir=64*1024,Fr=new Set([404,502,503,504]),ba=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","EHOSTUNREACH","ENETUNREACH"]),Ta=new Set(["GET","HEAD","OPTIONS"]);function X(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function xa(e,t){if(Ta.has(t))return!0;if(!X(e))return!1;let n=X(e.cause)?e.cause:void 0,r=e.code??n?.code;return typeof r=="string"&&ba.has(r)}function Bt(e){if(!X(e))return['smoke: must be an object with "via" and "steps"'];let t=[];return e.via!=="proxy"&&t.push('smoke.via: only "proxy" is supported (the check must go through the public URL)'),e.timeoutSeconds!==void 0&&!(typeof e.timeoutSeconds=="number"&&e.timeoutSeconds>0)&&t.push("smoke.timeoutSeconds: must be a number greater than 0"),!Array.isArray(e.steps)||e.steps.length===0?(t.push("smoke.steps: needs at least one step"),t):(e.steps.forEach((n,r)=>{let s=`smoke.steps[${r}]`;if(!X(n)){t.push(`${s}: must be an object`);return}let o=n.path;(typeof o!="string"||!o.startsWith("/")||o.startsWith("//"))&&t.push(`${s}.path: must start with "/" and is appended to the public URL; a full URL or relative path would skip the proxy`),n.expect!==void 0&&!(typeof n.expect=="number"&&Number.isInteger(n.expect)&&n.expect>=100&&n.expect<=599)&&t.push(`${s}.expect: must be an HTTP status between 100 and 599`),n.bodyContains!==void 0&&typeof n.bodyContains!="string"&&t.push(`${s}.bodyContains: must be a string`),n.save!==void 0&&(X(n.save)&&Object.values(n.save).every(a=>typeof a=="string"&&a.startsWith("$."))||t.push(`${s}.save: must map names to paths such as "$.id"`))}),t)}function Mr(e,t){let{appBase:n,apiBase:r}=Ft(t),s=[];for(let o of e){let i=o.config;if(!i?.smoke)continue;let a=i.appType,c=I(a)||a===J;if(!c&&a!=="frontend"||i.exposeViaProxy===!1)continue;let l=c?r:n,u=i.healthCheckPath||(c&&a!==J?"/health":void 0);s.push({name:o.name,baseUrl:`${l}${Lt(o).replace(/\/+$/,"")}`,...u?.startsWith("/")?{readyPath:u}:{},smoke:i.smoke})}return s}var wa=10;function Ur(e,t={}){let n=t.timeoutSeconds??wa;return e.flatMap(r=>{let s=r.smoke.steps.filter(i=>(i.method??"GET").toUpperCase()==="GET"&&i.body===void 0&&!i.path.includes("{{")).map(i=>({...i,bodyContains:void 0}));if(s.length===0)return[];let o=Math.min(r.smoke.timeoutSeconds??Lr,n);return[{name:r.name,baseUrl:r.baseUrl,smoke:{via:r.smoke.via,timeoutSeconds:o,steps:s}}]})}function Ea(e,t){let n=t.replace(/^\$\.?/,"").match(/[^.[\]]+/g)??[],r=e;for(let s of n){if(r==null||s==="__proto__"||s==="constructor"||s==="prototype"||!Object.hasOwn(r,s))return;let o=Object.getOwnPropertyDescriptor(r,s);if(!o||!("value"in o))return;r=o.value}return r}function Br(e,t){return e.replace(/\{\{(\w+)\}\}/g,(n,r)=>t[r]??n)}function Ut(e,t){return typeof e=="string"?Br(e,t):Array.isArray(e)?e.map(n=>Ut(n,t)):X(e)?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,Ut(r,t)])):e}function Qe(e){let t=e.replace(/\s+/g," ").trim();return t.length>jr?`${t.slice(0,jr)}...`:t}function Hr(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"step"}function va(e,t){let n=Hr(t),r=(e.get(n)??0)+1;return e.set(n,r),r===1?n:`${n}-${r}`}function Pa(e,t,n,r,s){try{let o=ue(e,Hr(n.service),t);Sa(o,{recursive:!0});let i=ue(o,"latest.json"),a=ue(o,"body.txt");return r===void 0?Dr(a,{force:!0}):Or(a,r),Or(i,`${JSON.stringify({...n,bodyPath:r===void 0?null:"body.txt"},null,2)}
16
+ `),s&&(Ar(i,ue(o,"last-success.json")),r===void 0?Dr(ue(o,"last-success-body.txt"),{force:!0}):Ar(a,ue(o,"last-success-body.txt"))),i}catch{return}}function $a(e){let t=Buffer.from(e,"utf8");if(t.length<=Ir)return{body:e,truncated:!1,bytes:t.length};let n=t.subarray(0,Ir).toString("utf8").replace(/\uFFFD$/,"");return{body:n,truncated:!0,bytes:Buffer.byteLength(n,"utf8")}}async function _a(e,t={}){let n=t.fetch??((u,d)=>fetch(u,d)),r=t.now??Date.now,s=t.sleep??(u=>new Promise(d=>setTimeout(d,u))),o=(e.smoke.timeoutSeconds??Lr)*1e3,i=r()+o,a={},c=Bt(e.smoke);if(c.length>0)return{name:e.name,ok:!1,failure:`${e.name}: invalid smoke block: ${c.join("; ")}`};if(e.readyPath){let u=`${e.baseUrl}${e.readyPath}`;for(;;){try{let d=await n(u,{method:"GET",signal:AbortSignal.timeout(Cr)});if(await d.text(),!Fr.has(d.status)&&d.status<500)break}catch{}if(r()>=i)break;await s(Nr)}}i=r()+o;let l=new Map;for(let[u,d]of e.smoke.steps.entries()){let p=d.name??`step ${u+1}`,h=(d.method??"GET").toUpperCase(),f=`${e.baseUrl}${Br(d.path,a)}`,b=d.expect??200,w=d.body!==void 0,$,U="",g,R;for(;;){g=void 0,R=void 0,$=void 0;let K=!1;try{let F=await n(f,{method:h,headers:w?{"content-type":"application/json"}:void 0,body:w?JSON.stringify(Ut(d.body,a)):void 0,signal:AbortSignal.timeout(Cr)});$=F.status,U=await F.text()}catch(F){K=xa(F,h),g=F instanceof Error?F.message:String(F);let re=X(F)?F.code??(X(F.cause)?F.cause.code:void 0):void 0;R=typeof re=="string"?re:void 0}if(!(g!==void 0&&K||$!==void 0&&$!==b&&Fr.has($))||r()>=i)break;await s(Nr)}let ne=`${e.name}: ${p}: ${h} ${f}`,le;if(t.recordDir){let K=$===void 0?void 0:$a(U),Te=g===void 0&&$===b&&(d.bodyContains===void 0||U.includes(d.bodyContains));le=Pa(t.recordDir,va(l,p),{service:e.name,step:p,method:h,url:f,expectedStatus:b,status:$??null,...g===void 0?{}:{error:R??g},truncated:K?.truncated??!1,bodyBytes:K?.bytes??0},K?.body,Te)}let be=K=>({name:e.name,ok:!1,failure:K,recordPath:le});if(g!==void 0)return be(`${ne} never answered (${g})`);if($!==b)return be(`${ne} returned ${$}, expected ${b}${U?`: ${Qe(U)}`:""}`);if(d.bodyContains!==void 0&&!U.includes(d.bodyContains))return be(`${ne} returned ${$} but the body does not contain "${d.bodyContains}": ${Qe(U)}`);if(d.save){let K;try{K=JSON.parse(U)}catch{return be(`${ne} returned a body that is not JSON, cannot save: ${Qe(U)}`)}for(let[Te,F]of Object.entries(d.save)){let re=Ea(K,F);if(re==null||typeof re=="object")return be(`${ne} response has no ${F} to save as {{${Te}}}: ${Qe(U)}`);a[Te]=String(re)}}}return{name:e.name,ok:!0}}function Yp(e){return`Smoke check failed: ${e.failure}${e.recordPath?` (record: ${e.recordPath})`:""}`}async function Gr(e,t={}){return Promise.all(e.map(n=>_a(n,t)))}var Re=1,ef="https://tdk-landscape.github.io/schema.service.json",Ra={dependencies:"deprecated, use dependsOn (still read for now)",envVars:"deprecated, use params (still read when params is absent)",jwtSecret:"ignored. A secret must not be committed: remove it and set JWT_SECRET in the project .env"},Aa=new Set(["$schema","agent","apiBasePath","apiPath","appName","appType","backendName","basePath","build","buildContext","databaseName","dependencies","dev","dependsOn","dockerfile","enabled","exposeViaProxy","featuresEnabled","framework","healthCheckPath","image","language","name","nats","params","playwright","port","replicas","restart","runtime","sablier","schemaVersion","secrets","smoke","stack","syncs","traefik","type"]),Da=[{path:["healthCheckPath"],pattern:/^\/[a-z0-9/-]*$/,expected:"a path such as /health"},{path:["traefik","host"],pattern:/^[A-Za-z0-9.-]+$/,expected:"a hostname such as shop.backend.myproject.local"},{path:["traefik","pathPrefix"],pattern:/^\/[a-z0-9/-]*$/,expected:"a path such as /api/v1/shop-management"},{path:["traefik","healthCheck"],pattern:/^\/[a-z0-9/-]*$/,expected:"a path such as /health"},{path:["nats","queueGroup"],pattern:/^[A-Za-z0-9_.-]+$/,expected:"letters, digits, '_', '.' or '-'"},{path:["databaseName"],pattern:/^[A-Za-z0-9_-]+$/,expected:"letters, digits, '_' or '-'"},{path:["stack"],pattern:/^[A-Za-z0-9_-]+$/,expected:"letters, digits, '_' or '-'"},{path:["image"],pattern:/^[A-Za-z0-9._/:@-]+$/,expected:"an image reference such as ghcr.io/acme/app:1.0"}];function Ze(e,t){let n=[],r=new Set;for(let{path:s,pattern:o,expected:i}of Da){let a=e;for(let l of s)a=a&&typeof a=="object"&&!Array.isArray(a)?a[l]:void 0;if(a==null||a==="")continue;let c=`${t}.${s.join(".")}`;(typeof a!="string"||!o.test(a))&&r.add(c),typeof a!="string"?n.push(`${c}: expected a string`):o.test(a)||n.push(`${c}: must be ${i} (no spaces, line breaks or YAML syntax)`)}for(let[s,o]of Oa(e,t))r.has(s)||n.push(`${s}: ${o}`);return n}function Ht(e){for(let t=0;t<e.length;t++){let n=e.charCodeAt(t);if(n<32||n===127||n===133||n===8232||n===8233)return!0}return!1}function Oa(e,t){let n=[],r=Object.entries(e).filter(([s])=>s!=="smoke").map(([s,o])=>[o,`${t}.${s}`]);for(let s of Object.keys(e))Ht(s)&&n.push([t,"a key contains a line break"]);for(;r.length>0;){let[s,o]=r.pop();if(typeof s=="string")Ht(s)&&n.push([o,"must not contain line breaks or control characters"]);else if(Array.isArray(s))for(let[i,a]of s.entries())r.push([a,`${o}[${i}]`]);else if(s&&typeof s=="object")for(let[i,a]of Object.entries(s))Ht(i)?n.push([o,"a key contains a line break"]):r.push([a,`${o}.${i}`])}return n.sort(([s],[o])=>s.localeCompare(o))}var Na=["apiPath","basePath"];function Gt(e){if(!e||typeof e!="object"||Array.isArray(e))return[];let t=e;return Na.filter(n=>n in t&&typeof t[n]!="string")}function Kt(e,t){if(!e||typeof e!="object"||Array.isArray(e))return{errors:[`${t}: expected a JSON object`],warnings:[]};let n=e,r=[];for(let a of["appName","appType","stack","schemaVersion"])a in n||r.push(`${t}.${a}: required field is missing`);for(let a of["appName","appType","stack"])a in n&&typeof n[a]!="string"&&r.push(`${t}.${a}: expected a string`);"schemaVersion"in n&&n.schemaVersion!==Re&&r.push(`${t}.schemaVersion: unsupported version ${String(n.schemaVersion)} (supported: ${Re})`);for(let a of Gt(n))r.push(`${t}.${a}: expected a string`);let s=n.dev,o=s&&typeof s=="object"&&!Array.isArray(s)?s.liveReload:void 0;if(o!==void 0&&typeof o!="boolean"&&r.push(`${t}.dev.liveReload: expected true or false`),r.push(...Ze(n,t)),"smoke"in n)for(let a of Bt(n.smoke))r.push(`${t}.${a}`);let i=Object.keys(n).flatMap(a=>{let c=Ra[a];return c?[`${t}.${a}: ${c}`]:Aa.has(a)?[]:[`${t}.${a}: unknown field is preserved`]});return o===!0&&n.language!=="go"&&i.push(`${t}.dev.liveReload: only applies to Go services (language "go"); it is ignored here`),{errors:r,warnings:i,manifest:n}}function Wr(e,t){if(!Kr(e))return[];try{let n=JSON.parse(Vr(e,"utf-8"));return!n||typeof n!="object"||Array.isArray(n)?[]:Ze(n,t)}catch{return[]}}function Jr(e,t){if(!Kr(e))return{errors:[`${t}: file is missing`],warnings:[]};try{let n=JSON.parse(Vr(e,"utf-8"));return Kt(n,t)}catch(n){let r=n instanceof Error?n.message:String(n);return{errors:[`${t}: invalid JSON (${r})`],warnings:[]}}}import{existsSync as pe,readdirSync as ds,readFileSync as us,statSync as Xt}from"node:fs";import{dirname as nc,join as Z}from"node:path";var Ae=class{data;options;constructor(t){this.data=new Map,this.options=t}has(t){let n=this.data.get(t);return n?Date.now()-n.timestamp>this.options.ttlMs?(this.data.delete(t),!1):!0:!1}get(t){if(this.has(t))return this.data.get(t)?.value}set(t,n){this.data.set(t,{value:n,timestamp:Date.now()})}delete(t){this.data.delete(t)}clear(){this.data.clear()}keys(){let t=[];for(let n of this.data.keys())this.has(n)&&t.push(n);return t}size(){return this.keys().length}};function qr(e){let t=0;return{isValid(){return Date.now()-t<e},markUpdated(){t=Date.now()},reset(){t=0}}}import{execFileSync as La,execSync as Ma}from"node:child_process";import{existsSync as zr}from"node:fs";import{delimiter as Yr,extname as Xr,join as Qr}from"node:path";import{delimiter as sf,extname as Ca}from"node:path";function De(){return process.platform==="win32"}function ja(e){return e==="linux"?"linux":e==="darwin"?"darwin":e==="win32"?"windows":null}function Ia(e){return e==="x64"?"amd64":e==="arm64"?"arm64":null}function Fa(e,t){let n=ja(e),r=Ia(t);if(!n||!r||n==="windows"&&r!=="amd64")return null;let s=`tdk-${n}-${r}`;return n==="windows"?`${s}.exe`:s}function of(){return Fa(process.platform,process.arch)}function af(){return De()?"tdk.exe":"tdk"}function Vt(e,t=De()){return t?Ca(e)?[e]:[e,`${e}.exe`,`${e}.cmd`,`${e}.bat`]:[e]}function O(e){let t=process.env.PATH??process.env.Path??"",n=De(),r=Vt(e,n);if(n&&!Xr(e))for(let s of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let o=s.toLowerCase();o&&!r.includes(`${e}${o}`)&&r.push(`${e}${o}`)}for(let s of t.split(Yr))if(s)for(let o of r){let i=Qr(s,o);if(zr(i))return i}return null}function Zr(e){let t=process.env.PATH??process.env.Path??"",n=De(),r=Vt(e,n);if(n&&!Xr(e))for(let i of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let a=i.toLowerCase();a&&!r.includes(`${e}${a}`)&&r.push(`${e}${a}`)}let s=[],o=new Set;for(let i of t.split(Yr))if(i)for(let a of r){let c=Qr(i,a);if(!zr(c))continue;let l=n?c.toLowerCase():c;o.has(l)||(o.add(l),s.push(c))}return s}var es=1e4;function ts(){let e=!1;if(process.platform==="win32")try{return La(O("docker")??"docker",["ps"],{stdio:"ignore",timeout:es,windowsHide:!0}),"running"}catch(t){return t.code==="ETIMEDOUT"?"unresponsive":"missing"}for(let t of["docker ps","colima status","podman ps"])try{return Ma(t,{stdio:"ignore",timeout:es}),"running"}catch(n){n.code==="ETIMEDOUT"&&(e=!0)}return e?"unresponsive":"missing"}function et(e,t){return e[t]??0}function Ua(e,t){let n=Array.from({length:t.length+1},(r,s)=>s);for(let r=1;r<=e.length;r++){let s=[r];for(let o=1;o<=t.length;o++){let i=e[r-1]===t[o-1]?0:1;s[o]=Math.min(et(s,o-1)+1,et(n,o)+1,et(n,o-1)+i)}n=s}return et(n,t.length)}function Ba(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length-1;n++)if(e[n]!==t[n]&&e[n]===t[n+1]&&e[n+1]===t[n]&&e.slice(0,n)===t.slice(0,n)&&e.slice(n+2)===t.slice(n+2))return!0;return!1}function ns(e,t){if(e.length<2||t.length===0||t.includes(e))return;let n=e.toLowerCase(),r,s=Number.POSITIVE_INFINITY;for(let o of t){if(o.length===0)continue;let i=o.toLowerCase(),a=Ba(n,i)?1:Ua(n,i),c=Math.max(1,Math.min(2,Math.floor(Math.max(n.length,i.length)/3)));a>c||(a<s||a===s&&(r===void 0||o<r))&&(r=o,s=a)}return r}import{spawn as Ha}from"node:child_process";import{join as Ga}from"node:path";function Ka(e,t=[],n={}){return new Promise((r,s)=>{let o=[e,...t];n.verbose&&console.log(`Executing: tilt ${o.join(" ")}`);let i=Ha(O("tilt")??"tilt",o,{stdio:n.inheritStdio?"inherit":"pipe",shell:!1,windowsHide:process.platform==="win32",timeout:n.timeoutMs}),a="",c="";n.inheritStdio||(i.stdout?.on("data",l=>{a+=l.toString()}),i.stderr?.on("data",l=>{c+=l.toString()})),i.on("close",l=>{r({exitCode:l??1,stdout:a,stderr:c})}),i.on("error",l=>{s(new Error(`Failed to spawn tilt: ${l.message}`))})})}async function rs(){try{return(await Ka("version",[],{inheritStdio:!1,timeoutMs:1e4})).exitCode===0}catch{return!1}}function Va(){let e=y();if(!e)throw Y.notInProject();return Ga(e,".tdk",".tdk-out","Tiltfile")}function ss(e){let t=Va();e.push("-f",t)}function xf(e,t={}){let n=[];return ss(n),t.focusTargets&&t.focusTargets.length>0&&n.push("--",`--focus=${t.focusTargets.join(",")}`),n.push(...e),t.verbose&&!t.quiet&&n.push("--verbose"),t.watch&&n.push("--watch"),n}function wf(e={}){let t=[];return ss(t),e.focusTargets&&e.focusTargets.length>0&&t.push("--",`--focus=${e.focusTargets.join(",")}`),t}function os(e){return e instanceof Error?e.message:String(e)}function Df(e,t){if(process.env.TDK_VERBOSE){let n=t!==void 0?`: ${os(t)}`:"";console.warn(m.gray(`${e}${n}`))}}var N=class extends Error{suggestions;exitCode;constructor(t,n=[],r=1){super(t),this.name="TdkError",this.suggestions=n,this.exitCode=r}display(){qa(this.message,void 0,this.suggestions)}exit(){this.display(),process.exit(this.exitCode)}};function Wt(e,t,n=!1){let r=new Set;for(let s of e){let o=ns(s,t);o&&r.add(n?`Did you mean "${o}" for "${s}"?`:`Did you mean "${o}"?`)}return[...r]}var Y={tiltNotInstalled:()=>new N("Tilt CLI is not installed",["Install Tilt: `brew install tilt` (macOS)","Or download from: https://docs.tilt.dev/install.html","Verify with: `tilt version`",`Setup guide: ${Ct}`]),dockerNotAvailable:()=>new N("Docker (or a compatible container runtime) is not running",["Start Docker Desktop, then verify with: `docker ps`","Or start Colima: `colima start`","Or start the Docker service on Linux: `sudo systemctl start docker`",`Setup guide: ${Ct}`]),dockerNotResponding:()=>new N("Docker is running but not responding (`docker ps` hung for 10s)",["Quit and reopen Docker Desktop, or run `colima restart`","Then verify with: `docker ps`"]),stackNotFound:(e,t=[])=>new N(`Stack "${e}" not found`,[...Wt([e],t),"Run `tdk stacks` to see available stacks","Run `tdk stack` to assign resources to a stack"]),resourceNotFound:(e,t=[])=>new N(`Resource "${e}" not found`,[...Wt([e],t),"Run `tdk resources` to list all resources","Check the resource name spelling"]),unknownServices:(e,t)=>{let n=Wt(e,t,e.length>1);return new N(`Unknown service ${e.join(", ")}. Valid names: ${t.join(", ")}`,n,2)},directoryExists:e=>new N(`Directory already exists: ${e}`,["Use `--path` to specify a different location","Remove the existing directory if no longer needed"]),invalidPath:e=>new N(`Invalid path: ${e}`,["Path must be within the project directory",'Path cannot contain special characters like <>:"|?*']),notInProject:()=>new N("Could not find project root (no .tdk/project.json found)",["Run this from within a TDK project","Run `tdk project --yes` to initialize a new project"])};function Of(){let e=y();return e||Y.notInProject().exit()}function Wa(e){e instanceof N&&e.exit(),console.error(m.red(`Error: ${os(e)}`)),process.exit(1)}async function Ja(e,t){try{return await e()}catch(n){return t?.verbose&&n instanceof Error&&n.stack&&console.error(m.gray(n.stack)),Wa(n)}}async function Nf(e,t){let n=[],r=ts();return r==="unresponsive"?n.push(Y.dockerNotResponding()):r==="missing"&&n.push(Y.dockerNotAvailable()),await rs()||n.push(Y.tiltNotInstalled()),n.length>0&&(console.error(m.red(`
17
17
  TDK can't start - missing prerequisites:
18
- `)),n.forEach((s,o)=>{o>0&&console.error(""),s.display()}),console.error(m.gray("\nRun `tdk doctor` for a full environment check.")),process.exit(1)),Wa(e,t)}function Of(e,t=1){console.error(m.red(`Error: ${e}`)),process.exit(t)}function Ja(e,t,n){if(console.error(m.red(`\u274C ${e}`)),t&&console.error(m.gray(` ${t}`)),n&&n.length>0){console.error(m.yellow(`
19
- \u{1F4A1} Suggestions:`));for(let r of n)console.error(m.cyan(` \u2192 ${r}`))}}function Nf(e,t){console.error(m.red(`
20
- tilt ${e} failed with exit code ${t}`)),process.exit(t)}function qa(e,t,n){return e===1?t:n||`${t}s`}function T(e,t,n){return`${e} ${qa(e,t,n)}`}var za={month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"};function If(e){return new Date(e).toLocaleString("en-US",za)}function Ff(e){return new Date(e).toLocaleDateString("en-US",{month:"short",day:"numeric"})}var Jt={success:{color:"green",icon:"\u2713",chalkFn:m.green},error:{color:"red",icon:"\u2717",chalkFn:m.red},warning:{color:"yellow",icon:"\u25CB",chalkFn:m.yellow},unknown:{color:"gray",icon:"?",chalkFn:m.gray}};function qt(e){if(!e)return"unknown";let t=e.toLowerCase();return t==="ready"||t==="healthy"||t==="active"||t==="running"?"success":t==="error"||t==="failed"||t==="critical"||t==="stopped"?"error":t==="pending"||t==="starting"||t==="building"||t==="degraded"?"warning":"unknown"}function Lf(e){return Jt[qt(e)].color}function Mf(e){return Jt[qt(e)].icon}function Uf(e,t){return Jt[qt(t)].chalkFn(e)}var Ya={resources:{singular:"resource",command:"tdk resource <name>",context:`
18
+ `)),n.forEach((s,o)=>{o>0&&console.error(""),s.display()}),console.error(m.gray("\nRun `tdk doctor` for a full environment check.")),process.exit(1)),Ja(e,t)}function Cf(e,t=1){console.error(m.red(`Error: ${e}`)),process.exit(t)}function qa(e,t,n){if(console.error(m.red(`\u274C ${e}`)),t&&console.error(m.gray(` ${t}`)),n&&n.length>0){console.error(m.yellow(`
19
+ \u{1F4A1} Suggestions:`));for(let r of n)console.error(m.cyan(` \u2192 ${r}`))}}function jf(e,t){console.error(m.red(`
20
+ tilt ${e} failed with exit code ${t}`)),process.exit(t)}function za(e,t,n){return e===1?t:n||`${t}s`}function T(e,t,n){return`${e} ${za(e,t,n)}`}var Ya={month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"};function Lf(e){return new Date(e).toLocaleString("en-US",Ya)}function Mf(e){return new Date(e).toLocaleDateString("en-US",{month:"short",day:"numeric"})}var Jt={success:{color:"green",icon:"\u2713",chalkFn:m.green},error:{color:"red",icon:"\u2717",chalkFn:m.red},warning:{color:"yellow",icon:"\u25CB",chalkFn:m.yellow},unknown:{color:"gray",icon:"?",chalkFn:m.gray}};function qt(e){if(!e)return"unknown";let t=e.toLowerCase();return t==="ready"||t==="healthy"||t==="active"||t==="running"?"success":t==="error"||t==="failed"||t==="critical"||t==="stopped"?"error":t==="pending"||t==="starting"||t==="building"||t==="degraded"?"warning":"unknown"}function Uf(e){return Jt[qt(e)].color}function Bf(e){return Jt[qt(e)].icon}function Hf(e,t){return Jt[qt(t)].chalkFn(e)}var Xa={resources:{singular:"resource",command:"tdk resource <name>",context:`
21
21
  To create a resource:`},stacks:{singular:"stack",command:"tdk stack <stack-name>",context:`
22
22
  To create a stack, use:`},services:{singular:"service",command:"tdk resource <name>",context:`
23
23
  To create a service:`},"stack-services":{singular:"service",command:"tdk resource <name> --stack <stack-name>",context:`
24
- To add services to this stack:`}};function Bf(e,t){let n=Ya[e];console.log(t?m.yellow(`No ${n.singular}s found${t}.`):m.yellow(`No ${n.singular}s found.`)),console.log(m.gray(n.context)),console.log(m.gray(` ${n.command}`)),e==="stacks"&&(console.log(m.gray(`
25
- Or create a new resource with a stack:`)),console.log(m.gray(" tdk resource <name> --stack <stack-name>")))}function Hf(e){console.log(m.yellow(e||"Cancelled."))}function Kf(e){console.log(m.blue(`TDK ${e}
26
- `))}function Gf(e,t){console.log(m.green(`All ${e} are ${t}!`))}var zt=62;function Vf(e="\u2500",t=zt){return e.repeat(t)}function is(e,t=zt-2){let n=Math.max(0,t-e.length),r=Math.floor(n/2),s=n-r;return" ".repeat(r)+e+" ".repeat(s)}function Wf(e,t){return e.length>t?`${e.slice(0,t-1)}\u2026`:e.padEnd(t)}function Jf(e,t){return e.length<=t?e:`${e.slice(0,t-3)}...`}function qf(e){console.log(m.green(`\u2713 ${e}`))}function zf(e){console.log(m.blue(e))}function Yf(e,t=2){console.log(m.gray(`${" ".repeat(t)}${e}`))}function Xf(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function Qf(e,t,n=zt){let r=n-2,s="\u2500".repeat(r);console.log(),console.log(m.cyan(`\u256D${s}\u256E`)),console.log(m.cyan("\u2502")+m.bold.white(is(e,r))+m.cyan("\u2502")),t&&(console.log(m.cyan(`\u251C${s}\u2524`)),console.log(m.cyan("\u2502")+m.gray(is(t,r))+m.cyan("\u2502"))),console.log(m.cyan(`\u2570${s}\u256F`))}function as(e){if(e.length===0||e.every(n=>n==="unknown"))return"unknown";let t=e.filter(n=>n==="ready").length/e.length;return t>.9?"healthy":t>.5?"degraded":"error"}var Xa=/^[a-z0-9-]+$/;function cs(e){return Xa.test(e)}var Qa="Use lowercase letters, numbers, and hyphens only";function us(e,t){return`${e} "${t}" is not valid. ${Qa}, e.g. "${e==="Resource name"?"my-service":"my-stack"}".`}function Za(e){return e.trim()?cs(e)?{valid:!0}:{valid:!1,error:us("Resource name",e)}:{valid:!1,error:"Resource name is required"}}function ec(e){return e.trim()?cs(e)?{valid:!0}:{valid:!1,error:us("Stack name",e)}:{valid:!1,error:"Stack name is required"}}function nm(e){let t=e==="resource"?Za:ec;return n=>{let r=t(n);return r.valid?!0:r.error??"Invalid name"}}function rm(e){return Yt(Nt,e)?{valid:!0}:{valid:!1,error:`Invalid service. Must be one of: ${Nt.join(", ")}`}}function sm(e){return Number.isInteger(e)&&e>0&&e<=65535}function om(e){return!e.includes("\0")&&!/[<>:"|?*]/.test(e)}function im(e,t="_"){return e.replace(/[^a-zA-Z0-9-]/g,t).substring(0,100)}function Yt(e,t){return e.includes(t)}var nc=yr;function tn(e,t=5,n=0){let r=[];if(n>t)return r;let s=ls(e,{withFileTypes:!0});for(let o of s){let i=Z(e,o.name);if(o.isDirectory()){if(rc(o.name))continue;r.push(...tn(i,t,n+1))}else o.isFile()&&o.name===nc&&r.push(i)}return r}function nn(e){return tn(e)}function rc(e){return Yt(Sr,e)||e.startsWith(".")}function sc(e){if(!e||typeof e!="object")return!1;let t=e,n=typeof t.runtime=="string"||typeof t.appType=="string"||typeof t.type=="string";return typeof t.appName=="string"&&n}var tt=new Set;var Q=class extends Error{reason;constructor(t){super(t),this.reason=t,this.name="InvalidServiceJsonError"}};function Qt(e){return e instanceof Error?e.message:String(e)}function oc(e){let t;try{t=ds(e,"utf-8")}catch(c){throw new Q(`could not read file: ${Qt(c)}`)}let n;try{n=JSON.parse(t)}catch(c){throw new Q(`invalid JSON: ${Qt(c)}`)}if(!sc(n))throw new Q("missing required fields (appName, runtime or appType)");let r=Kt(n);if(r.length>0)throw new Q(r.map(c=>`${c}: expected a string`).join("; "));let s=Ze(n,e);if(s.length>0)throw new Q(s.join("; "));let o=n;for(let c of Gt(n,e).warnings)tt.has(c)||(tt.add(c),console.warn(`\u26A0\uFE0F ${c}`));let i={...o,appType:o.appType||o.type},a=tc(e);return{name:i.appName,path:a,configPath:e,config:i,stack:i.stack,port:i.port,type:i.appType}}function ps(e){let t=tn(e),n=[],r=[];for(let s of t)try{n.push(oc(s))}catch(o){r.push({path:s,reason:o instanceof Q?o.reason:Qt(o)})}return{resources:n,problems:r}}function ic(e){for(let t of e){let n=`skipped ${t.path}: ${t.reason}`;tt.has(n)||(tt.add(n),console.warn(`\u26A0\uFE0F ${n}`))}}function x(e){let{resources:t,problems:n}=ps(e);return ic(n),t}function Ne(){let e=y();if(!e)throw Y.notInProject();return x(e)}function ym(){let e=y();if(!e)throw Y.notInProject();let{resources:t,problems:n}=ps(e);if(n.length>0)throw new Error(n.map(r=>`Invalid service.json at ${r.path}: ${r.reason}`).join(`
27
- `));return t}function Sm(e){let t=x(e),n=new Set;for(let r of t)r.stack&&n.add(r.stack);return Array.from(n).sort()}function bm(e){let t=e||Ne(),n=new Set;for(let r of t)r.stack&&n.add(r.stack);return Array.from(n).sort()}function Tm(e=Ne()){let t=new Map;for(let r of e)if(r.stack){let s=t.get(r.stack);s?s.push(r):t.set(r.stack,[r])}let n=[];for(let[r,s]of t)n.push({name:r,description:T(s.length,"resource"),resources:s,resourceCount:s.length});return n.sort((r,s)=>r.name.localeCompare(s.name))}function xm(e,t){return(t??Ne()).some(r=>r.stack===e)}var rn=5e3,Zt=new Ae({ttlMs:rn}),en=new Ae({ttlMs:rn}),Oe=qr(rn);function wm(){Zt.clear(),en.clear(),Oe.reset()}function ac(e,t){if(e==="Dockerfile"||e.startsWith("docker-compose"))return"docker";if(e==="Tiltfile"||e.endsWith(".star"))return"tilt";if(e==="vite.config.ts"||e==="tsconfig.json"||e===A)return"config";if(e==="schema.prisma"||e.includes("migration"))return"prisma";if(t){let n=t.split(`
24
+ To add services to this stack:`}};function Gf(e,t){let n=Xa[e];console.log(t?m.yellow(`No ${n.singular}s found${t}.`):m.yellow(`No ${n.singular}s found.`)),console.log(m.gray(n.context)),console.log(m.gray(` ${n.command}`)),e==="stacks"&&(console.log(m.gray(`
25
+ Or create a new resource with a stack:`)),console.log(m.gray(" tdk resource <name> --stack <stack-name>")))}function Kf(e){console.log(m.yellow(e||"Cancelled."))}function Vf(e){console.log(m.blue(`TDK ${e}
26
+ `))}function Wf(e,t){console.log(m.green(`All ${e} are ${t}!`))}var zt=62;function Jf(e="\u2500",t=zt){return e.repeat(t)}function is(e,t=zt-2){let n=Math.max(0,t-e.length),r=Math.floor(n/2),s=n-r;return" ".repeat(r)+e+" ".repeat(s)}function qf(e,t){return e.length>t?`${e.slice(0,t-1)}\u2026`:e.padEnd(t)}function zf(e,t){return e.length<=t?e:`${e.slice(0,t-3)}...`}function Yf(e){console.log(m.green(`\u2713 ${e}`))}function Xf(e){console.log(m.blue(e))}function Qf(e,t=2){console.log(m.gray(`${" ".repeat(t)}${e}`))}function Zf(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function em(e,t,n=zt){let r=n-2,s="\u2500".repeat(r);console.log(),console.log(m.cyan(`\u256D${s}\u256E`)),console.log(m.cyan("\u2502")+m.bold.white(is(e,r))+m.cyan("\u2502")),t&&(console.log(m.cyan(`\u251C${s}\u2524`)),console.log(m.cyan("\u2502")+m.gray(is(t,r))+m.cyan("\u2502"))),console.log(m.cyan(`\u2570${s}\u256F`))}function as(e){if(e.length===0||e.every(n=>n==="unknown"))return"unknown";let t=e.filter(n=>n==="ready").length/e.length;return t>.9?"healthy":t>.5?"degraded":"error"}var Qa=/^[a-z0-9-]+$/;function cs(e){return Qa.test(e)}var Za="Use lowercase letters, numbers, and hyphens only";function ls(e,t){return`${e} "${t}" is not valid. ${Za}, e.g. "${e==="Resource name"?"my-service":"my-stack"}".`}function ec(e){return e.trim()?cs(e)?{valid:!0}:{valid:!1,error:ls("Resource name",e)}:{valid:!1,error:"Resource name is required"}}function tc(e){return e.trim()?cs(e)?{valid:!0}:{valid:!1,error:ls("Stack name",e)}:{valid:!1,error:"Stack name is required"}}function sm(e){let t=e==="resource"?ec:tc;return n=>{let r=t(n);return r.valid?!0:r.error??"Invalid name"}}function om(e){return Yt(Nt,e)?{valid:!0}:{valid:!1,error:`Invalid service. Must be one of: ${Nt.join(", ")}`}}function im(e){return Number.isInteger(e)&&e>0&&e<=65535}function am(e){return!e.includes("\0")&&!/[<>:"|?*]/.test(e)}function cm(e,t="_"){return e.replace(/[^a-zA-Z0-9-]/g,t).substring(0,100)}function Yt(e,t){return e.includes(t)}var rc=yr;function tn(e,t=5,n=0){let r=[];if(n>t)return r;let s=ds(e,{withFileTypes:!0});for(let o of s){let i=Z(e,o.name);if(o.isDirectory()){if(sc(o.name))continue;r.push(...tn(i,t,n+1))}else o.isFile()&&o.name===rc&&r.push(i)}return r}function nn(e){return tn(e)}function sc(e){return Yt(Sr,e)||e.startsWith(".")}function oc(e){if(!e||typeof e!="object")return!1;let t=e,n=typeof t.runtime=="string"||typeof t.appType=="string"||typeof t.type=="string";return typeof t.appName=="string"&&n}var tt=new Set;var Q=class extends Error{reason;constructor(t){super(t),this.reason=t,this.name="InvalidServiceJsonError"}};function Qt(e){return e instanceof Error?e.message:String(e)}function ic(e){let t;try{t=us(e,"utf-8")}catch(c){throw new Q(`could not read file: ${Qt(c)}`)}let n;try{n=JSON.parse(t)}catch(c){throw new Q(`invalid JSON: ${Qt(c)}`)}if(!oc(n))throw new Q("missing required fields (appName, runtime or appType)");let r=Gt(n);if(r.length>0)throw new Q(r.map(c=>`${c}: expected a string`).join("; "));let s=Ze(n,e);if(s.length>0)throw new Q(s.join("; "));let o=n;for(let c of Kt(n,e).warnings)tt.has(c)||(tt.add(c),console.warn(`\u26A0\uFE0F ${c}`));let i={...o,appType:o.appType||o.type},a=nc(e);return{name:i.appName,path:a,configPath:e,config:i,stack:i.stack,port:i.port,type:i.appType}}function ps(e){let t=tn(e),n=[],r=[];for(let s of t)try{n.push(ic(s))}catch(o){r.push({path:s,reason:o instanceof Q?o.reason:Qt(o)})}return{resources:n,problems:r}}function ac(e){for(let t of e){let n=`skipped ${t.path}: ${t.reason}`;tt.has(n)||(tt.add(n),console.warn(`\u26A0\uFE0F ${n}`))}}function x(e){let{resources:t,problems:n}=ps(e);return ac(n),t}function Ne(){let e=y();if(!e)throw Y.notInProject();return x(e)}function bm(){let e=y();if(!e)throw Y.notInProject();let{resources:t,problems:n}=ps(e);if(n.length>0)throw new Error(n.map(r=>`Invalid service.json at ${r.path}: ${r.reason}`).join(`
27
+ `));return t}function Tm(e){let t=x(e),n=new Set;for(let r of t)r.stack&&n.add(r.stack);return Array.from(n).sort()}function xm(e){let t=e||Ne(),n=new Set;for(let r of t)r.stack&&n.add(r.stack);return Array.from(n).sort()}function wm(e=Ne()){let t=new Map;for(let r of e)if(r.stack){let s=t.get(r.stack);s?s.push(r):t.set(r.stack,[r])}let n=[];for(let[r,s]of t)n.push({name:r,description:T(s.length,"resource"),resources:s,resourceCount:s.length});return n.sort((r,s)=>r.name.localeCompare(s.name))}function Em(e,t){return(t??Ne()).some(r=>r.stack===e)}var rn=5e3,Zt=new Ae({ttlMs:rn}),en=new Ae({ttlMs:rn}),Oe=qr(rn);function vm(){Zt.clear(),en.clear(),Oe.reset()}function cc(e,t){if(e==="Dockerfile"||e.startsWith("docker-compose"))return"docker";if(e==="Tiltfile"||e.endsWith(".star"))return"tilt";if(e==="vite.config.ts"||e==="tsconfig.json"||e===A)return"config";if(e==="schema.prisma"||e.includes("migration"))return"prisma";if(t){let n=t.split(`
28
28
  `).slice(0,10).join(`
29
- `);if(n.includes("GENERATED BY TDK")||n.includes("AUTOGENERATED"))return"generated"}return"unknown"}function cc(e){let t=e.configPath;if(Oe.isValid()){let h=Zt.get(t);if(h)return h}let n=e.path,r=Xt(e.configPath),s=r.mtime.toISOString(),o=r.mtime.toISOString(),i=uc(n),a=pe(Z(n,"Dockerfile")),c=pe(Z(n,"Tiltfile")),u=pe(Z(n,se))||pe(Z(n,"docker-compose.yaml")),d=e.config?.appType,l=d||"backend";d||(e.name.includes("frontend")?l="frontend":(e.name.includes("sdk")||e.name.includes("lib")||e.name.includes("infra"))&&(l="library"));let p={name:e.name,stack:e.stack,type:l,port:e.config?.port,createdAt:s,lastModified:o,dependencies:e.config?.dependsOn??[],hasDockerfile:a,hasTiltfile:c,hasDockerCompose:u,autogeneratedFiles:i,status:"unknown"};return Zt.set(t,p),Oe.markUpdated(),p}function uc(e){let t=[];for(let r of br){let s=Z(e,r);if(pe(s)){let o=Xt(s),i=ds(s,"utf-8");t.push({name:r,path:s,type:ac(r,i),size:o.size,lastModified:o.mtime.toISOString()})}}let n=Z(e,"prisma");if(pe(n)){let r=ls(n);for(let s of r)if(s==="schema.prisma"||s.includes("migration")){let o=Z(n,s),i=Xt(o);t.push({name:`prisma/${s}`,path:o,type:"prisma",size:i.size,lastModified:i.mtime.toISOString()})}}return t.sort((r,s)=>r.name.localeCompare(s.name))}function Em(e){let t=e.name;if(Oe.isValid()){let c=en.get(t);if(c)return c}let n=e.resources.map(c=>cc(c)),r=n.map(c=>new Date(c.createdAt).getTime()),s=Math.min(...r),o=Math.max(...r),i=as(n.map(c=>c.status)),a={name:e.name,resourceCount:n.length,createdAt:new Date(s).toISOString(),lastModified:new Date(o).toISOString(),resources:n,overallStatus:i};return en.set(t,a),Oe.markUpdated(),a}var lc={[j]:{name:j,description:"Generate and load the stack-level PostgreSQL docker-compose file",generatedFiles:["services/platform/database-management/docker-compose.yml"]}};function fs(e,t){return lc[t]?["pre_alpha","alpha","beta"].some(n=>e[n]?.enabledStacks?.includes(t)):!1}var pc=dc(new URL("../dist/generator/template-engine.js",import.meta.url).href),sn=k.dirname(pc);function Ce(e){let t=[k.join(sn,"..","..","templates"),k.join(sn,"..","templates"),k.join(sn,"..","..","..","templates"),k.join(process.cwd(),"node_modules","@tdk-landscape","tdk-cli-core","templates"),k.join(k.dirname(process.execPath),"tdk-cli","cli","templates")],n=[];for(let r of t){let s=k.join(r,e);n.push(s);try{return S.readFileSync(s,"utf-8")}catch{}}throw new Error(`Failed to load template ${e} from any of these paths: ${n.join(", ")}`)}var on=null;function fc(){return on||(on={[q]:Ce(".tiltignore.hbs"),[qe]:Ce("TILT_RESOURCE_DEFAULTS.star.hbs"),[Je]:Ce("TILT_TECH_STACK.star.hbs"),Tiltfile:Ce("Tiltfile.hbs"),"spec.master":Ce("spec.master.hbs")}),on}var mc={proxy:"Traefik reverse proxy",verdaccio:"Private npm registry","database-management":"PostgreSQL database"},hc={monitoring:"Signoz, SkyWalking (RAM intensive)",elk:"Elasticsearch/Logstash/Kibana",debezium:"CDC with Kafka/Zookeeper",golden_image:"Golden image rebuild (one-time)",verdaccio:"Premium local npm registry"},hs=["TILT_TECH_STACK.star","TILT_RESOURCE_DEFAULTS.star","spec.master","Tiltfile",".tiltignore"],nt=class{templatesDir;constructor(t){let n=wt("node:url").fileURLToPath(new URL("../dist/generator",import.meta.url))||k.dirname(new URL(new URL("../dist/generator/template-engine.js",import.meta.url).href).pathname);this.templatesDir=t||k.join(n,"..","..","templates"),this.registerHelpers()}quoteStarlarkString(t){return`"${t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}formatStarlarkValue(t){return t==null?"None":typeof t=="string"?this.quoteStarlarkString(t):typeof t=="boolean"?t?"True":"False":typeof t=="number"?String(t):Array.isArray(t)?`[${t.map(r=>this.formatStarlarkValue(r)).join(", ")}]`:typeof t=="object"?`{${Object.entries(t).map(([r,s])=>`${this.quoteStarlarkString(r)}: ${this.formatStarlarkValue(s)}`).join(", ")}}`:String(t)}registerHelpers(){ie.registerHelper("starlark",t=>new ie.SafeString(this.formatStarlarkValue(t))),ie.registerHelper("starlarkArray",t=>{if(!Array.isArray(t))return new ie.SafeString("[]");let n=t.map(r=>this.formatStarlarkValue(r));return new ie.SafeString(`[${n.join(", ")}]`)}),ie.registerHelper("json",t=>JSON.stringify(t))}buildContext(t){return{version:L.version,tech:L.tech,ports:L.ports,health:L.health,naming:L.naming,traefik:L.traefik,filewatchIgnores:[...L.filewatchIgnores],serviceTypes:L.serviceTypes,paths:L.paths,discovery:{scanIntervalSeconds:L.discovery.scanIntervalSeconds,maxManifestsPerRoot:L.discovery.maxManifestsPerRoot,paths:t.discovery.paths},docker:L.docker,runtime:L.runtime,project:t.project,phases:gc(t.phases),alwaysEnabledInfra:t.always_enabled_infra??[..._e],optionalInfra:t.optional_infra,serviceDescriptions:mc,infraDescriptions:hc}}loadTemplate(t){let n=k.join(this.templatesDir,`${t}.hbs`),r=S.existsSync(n)?S.readFileSync(n,"utf-8"):fc()[t];if(!r)throw new Error(`Template not found: ${n}`);return ie.compile(r)}generateTechStack(t){return this.loadTemplate(Je)(t)}generateServiceDefaults(t){return this.loadTemplate(qe)(t)}generateSpecMaster(t){return this.loadTemplate("spec.master")(t)}generateTiltfile(t){return this.loadTemplate("Tiltfile")(t)}generateTiltIgnore(t){return this.loadTemplate(".tiltignore")(t)}generateAll(t){let n=this.buildContext(t);return{"TILT_TECH_STACK.star":this.generateTechStack(n),"TILT_RESOURCE_DEFAULTS.star":this.generateServiceDefaults(n),"spec.master":this.generateSpecMaster(n),Tiltfile:this.generateTiltfile(n),".tiltignore":this.generateTiltIgnore(n)}}};function gc(e){let t={...e};for(let n of Object.keys(t))t[n]={...t[n],enabledStacks:Array.from(new Set(t[n].enabledStacks))};return t}function kc(e){return e.replace(/-/g,"_")}function yc(e){let t=kc(e.project.name||"tdk_project");return`###############################################################################
29
+ `);if(n.includes("GENERATED BY TDK")||n.includes("AUTOGENERATED"))return"generated"}return"unknown"}function lc(e){let t=e.configPath;if(Oe.isValid()){let h=Zt.get(t);if(h)return h}let n=e.path,r=Xt(e.configPath),s=r.mtime.toISOString(),o=r.mtime.toISOString(),i=dc(n),a=pe(Z(n,"Dockerfile")),c=pe(Z(n,"Tiltfile")),l=pe(Z(n,se))||pe(Z(n,"docker-compose.yaml")),u=e.config?.appType,d=u||"backend";u||(e.name.includes("frontend")?d="frontend":(e.name.includes("sdk")||e.name.includes("lib")||e.name.includes("infra"))&&(d="library"));let p={name:e.name,stack:e.stack,type:d,port:e.config?.port,createdAt:s,lastModified:o,dependencies:e.config?.dependsOn??[],hasDockerfile:a,hasTiltfile:c,hasDockerCompose:l,autogeneratedFiles:i,status:"unknown"};return Zt.set(t,p),Oe.markUpdated(),p}function dc(e){let t=[];for(let r of br){let s=Z(e,r);if(pe(s)){let o=Xt(s),i=us(s,"utf-8");t.push({name:r,path:s,type:cc(r,i),size:o.size,lastModified:o.mtime.toISOString()})}}let n=Z(e,"prisma");if(pe(n)){let r=ds(n);for(let s of r)if(s==="schema.prisma"||s.includes("migration")){let o=Z(n,s),i=Xt(o);t.push({name:`prisma/${s}`,path:o,type:"prisma",size:i.size,lastModified:i.mtime.toISOString()})}}return t.sort((r,s)=>r.name.localeCompare(s.name))}function Pm(e){let t=e.name;if(Oe.isValid()){let c=en.get(t);if(c)return c}let n=e.resources.map(c=>lc(c)),r=n.map(c=>new Date(c.createdAt).getTime()),s=Math.min(...r),o=Math.max(...r),i=as(n.map(c=>c.status)),a={name:e.name,resourceCount:n.length,createdAt:new Date(s).toISOString(),lastModified:new Date(o).toISOString(),resources:n,overallStatus:i};return en.set(t,a),Oe.markUpdated(),a}var uc={[j]:{name:j,description:"Generate and load the stack-level PostgreSQL docker-compose file",generatedFiles:["services/platform/database-management/docker-compose.yml"]}};function fs(e,t){return uc[t]?["pre_alpha","alpha","beta"].some(n=>e[n]?.enabledStacks?.includes(t)):!1}var fc=pc(new URL("../dist/generator/template-engine.js",import.meta.url).href),sn=k.dirname(fc);function Ce(e){let t=[k.join(sn,"..","..","templates"),k.join(sn,"..","templates"),k.join(sn,"..","..","..","templates"),k.join(process.cwd(),"node_modules","@tdk-landscape","tdk-cli-core","templates"),k.join(k.dirname(process.execPath),"tdk-cli","cli","templates")],n=[];for(let r of t){let s=k.join(r,e);n.push(s);try{return S.readFileSync(s,"utf-8")}catch{}}throw new Error(`Failed to load template ${e} from any of these paths: ${n.join(", ")}`)}var on=null;function mc(){return on||(on={[q]:Ce(".tiltignore.hbs"),[qe]:Ce("TILT_RESOURCE_DEFAULTS.star.hbs"),[Je]:Ce("TILT_TECH_STACK.star.hbs"),Tiltfile:Ce("Tiltfile.hbs"),"spec.master":Ce("spec.master.hbs")}),on}var hc={proxy:"Traefik reverse proxy",verdaccio:"Private npm registry","database-management":"PostgreSQL database"},gc={monitoring:"Signoz, SkyWalking (RAM intensive)",elk:"Elasticsearch/Logstash/Kibana",debezium:"CDC with Kafka/Zookeeper",golden_image:"Golden image rebuild (one-time)",verdaccio:"Premium local npm registry"},hs=["TILT_TECH_STACK.star","TILT_RESOURCE_DEFAULTS.star","spec.master","Tiltfile",".tiltignore"],nt=class{templatesDir;constructor(t){let n=wt("node:url").fileURLToPath(new URL("../dist/generator",import.meta.url))||k.dirname(new URL(new URL("../dist/generator/template-engine.js",import.meta.url).href).pathname);this.templatesDir=t||k.join(n,"..","..","templates"),this.registerHelpers()}quoteStarlarkString(t){return`"${t.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}formatStarlarkValue(t){return t==null?"None":typeof t=="string"?this.quoteStarlarkString(t):typeof t=="boolean"?t?"True":"False":typeof t=="number"?String(t):Array.isArray(t)?`[${t.map(r=>this.formatStarlarkValue(r)).join(", ")}]`:typeof t=="object"?`{${Object.entries(t).map(([r,s])=>`${this.quoteStarlarkString(r)}: ${this.formatStarlarkValue(s)}`).join(", ")}}`:String(t)}registerHelpers(){ie.registerHelper("starlark",t=>new ie.SafeString(this.formatStarlarkValue(t))),ie.registerHelper("starlarkArray",t=>{if(!Array.isArray(t))return new ie.SafeString("[]");let n=t.map(r=>this.formatStarlarkValue(r));return new ie.SafeString(`[${n.join(", ")}]`)}),ie.registerHelper("json",t=>JSON.stringify(t))}buildContext(t){return{version:L.version,tech:L.tech,ports:L.ports,health:L.health,naming:L.naming,traefik:L.traefik,filewatchIgnores:[...L.filewatchIgnores],serviceTypes:L.serviceTypes,paths:L.paths,discovery:{scanIntervalSeconds:L.discovery.scanIntervalSeconds,maxManifestsPerRoot:L.discovery.maxManifestsPerRoot,paths:t.discovery.paths},docker:L.docker,runtime:L.runtime,project:t.project,phases:kc(t.phases),alwaysEnabledInfra:t.always_enabled_infra??[..._e],optionalInfra:t.optional_infra,serviceDescriptions:hc,infraDescriptions:gc}}loadTemplate(t){let n=k.join(this.templatesDir,`${t}.hbs`),r=S.existsSync(n)?S.readFileSync(n,"utf-8"):mc()[t];if(!r)throw new Error(`Template not found: ${n}`);return ie.compile(r)}generateTechStack(t){return this.loadTemplate(Je)(t)}generateServiceDefaults(t){return this.loadTemplate(qe)(t)}generateSpecMaster(t){return this.loadTemplate("spec.master")(t)}generateTiltfile(t){return this.loadTemplate("Tiltfile")(t)}generateTiltIgnore(t){return this.loadTemplate(".tiltignore")(t)}generateAll(t){let n=this.buildContext(t);return{"TILT_TECH_STACK.star":this.generateTechStack(n),"TILT_RESOURCE_DEFAULTS.star":this.generateServiceDefaults(n),"spec.master":this.generateSpecMaster(n),Tiltfile:this.generateTiltfile(n),".tiltignore":this.generateTiltIgnore(n)}}};function kc(e){let t={...e};for(let n of Object.keys(t))t[n]={...t[n],enabledStacks:Array.from(new Set(t[n].enabledStacks))};return t}function yc(e){return e.replace(/-/g,"_")}function Sc(e){let t=yc(e.project.name||"tdk_project");return`###############################################################################
30
30
  # SYSTEM-GENERATED - DO NOT EDIT
31
31
  # Stack feature: database-management
32
32
  # Source: .tdk/project.json phases.*.enabledStacks includes "database-management"
@@ -61,16 +61,16 @@ networks:
61
61
 
62
62
  volumes:
63
63
  ${t}_postgres_data:
64
- `}function ms(e,t){if(!e||typeof e!="object")return!1;let n=e;for(let r of["pre_alpha","alpha","beta","out_of_scope"]){let s=n[r];if(!s||typeof s!="object"||!Array.isArray(s[t]))return!1}return!0}function Sc(e){if(!e||typeof e!="object")return null;let t=e;if(typeof t.version!="string"||!t.project||typeof t.project!="object")return null;let n=t.project;if(typeof n.name!="string"||typeof n.version!="string")return null;let r=null;if(ms(t.phases,"enabledStacks"))r=t.phases;else if(ms(t.stacks,"services")){let i=t.stacks;r={pre_alpha:{name:i.pre_alpha.name,description:i.pre_alpha.description,enabledStacks:i.pre_alpha.services},alpha:{name:i.alpha.name,description:i.alpha.description,enabledStacks:i.alpha.services},beta:{name:i.beta.name,description:i.beta.description,enabledStacks:i.beta.services},out_of_scope:{name:i.out_of_scope.name,description:i.out_of_scope.description,enabledStacks:i.out_of_scope.services}}}if(!r||!t.optional_infra||typeof t.optional_infra!="object")return null;let s=t.optional_infra;if(typeof s.monitoring!="boolean"||typeof s.elk!="boolean"||typeof s.debezium!="boolean"||typeof s.golden_image!="boolean"||typeof s.verdaccio!="boolean"||!t.discovery||typeof t.discovery!="object")return null;let o=t.discovery;return Array.isArray(o.paths)?{version:t.version,project:t.project,phases:r,always_enabled_infra:t.always_enabled_infra,optional_infra:t.optional_infra,discovery:t.discovery,overrides:t.overrides}:null}var an=class extends Error{};function rt(e){let t=k.join(e,".tdk",_);if(!S.existsSync(t))throw new an(`Project config not found: ${t}. Run 'tdk project --yes' first.`);let n=S.readFileSync(t,"utf-8"),r=JSON.parse(n),s=Sc(r);if(!s)throw new Error("Invalid project.json: missing or invalid required fields. Expected: version (string), project (object with name/version), phases (object with pre_alpha/alpha/beta/out_of_scope enabledStacks), optional_infra (object with boolean flags), discovery (object with paths array)");return s}async function bc(e){let t=x(e).filter(r=>r.config?.sablier?.enable===!0);t.length===0||await sr(e)||console.warn(`\u26A0\uFE0F Sablier (on-demand scaling) is a Premium feature - no valid license key found. ${t.length} resource${t.length===1?" has":"s have"} a \`sablier\` block, but it will have no effect without a license. Set TDK_LICENSE_KEY to a key that grants it, or remove the \`sablier\` block from the affected service.json file(s) to silence this warning.`)}function Tc(e,t){let n=oe(e,A);if(S.existsSync(n))return!1;let r={name:t.project.name||k.basename(e),version:t.project.version||"1.0.0",private:!0,type:"module",workspaces:t.discovery.paths};return It(n,`${JSON.stringify(r,null,2)}
65
- `),!0}async function Um(e,t={}){let n=rt(e),r=nn(e).flatMap(l=>Wr(l,k.relative(e,l).split(k.sep).join("/")));if(r.length>0)throw new Error(`Refusing to generate config from unsafe service.json values:
66
- ${r.map(l=>` ${l}`).join(`
67
- `)}`);await bc(e),Tc(e,n)&&!t.quiet&&console.log("\u2713 Generated: package.json (workspace root)");let s=Object.values(n.phases).some(l=>l.enabledStacks.includes("verdaccio"));(n.optional_infra.verdaccio||s)&&(await Ke(e)||console.warn("\u26A0\uFE0F Verdaccio is a Premium feature - no valid license key found. It's enabled in this project's config, but will have no effect without a license. Set TDK_LICENSE_KEY to a key that grants it, or run `tdk config disable-infra verdaccio` to silence this warning."));let o=k.join(e,".tdk",".tdk-out");S.existsSync(o)||S.mkdirSync(o,{recursive:!0});let a=new nt().generateAll(n);for(let l of hs){let p=a[l],h=oe(e,k.join(".tdk",".tdk-out",l));$e(h,p),t.quiet||console.log(`\u2713 Generated: .tdk/.tdk-out/${l}`)}if(fs(n.phases,j)){let l=oe(e,k.join("services","platform",j,se)),p=k.dirname(l);S.mkdirSync(p,{recursive:!0}),$e(l,yc(n)),t.quiet||console.log("\u2713 Generated: services/platform/database-management/docker-compose.yml")}let c=k.join(o,q),u=oe(e,q);if(S.existsSync(c)){if(!S.existsSync(u))S.copyFileSync(c,u),console.log("\u2713 Copied: .tiltignore \u2192 project root");else if(t.discardHandEdits){let l=S.readFileSync(u,"utf-8");l.includes(ys)&&l!==S.readFileSync(c,"utf-8")&&(S.copyFileSync(c,u),console.log("\u2713 Restored: .tiltignore \u2192 project root (hand edits discarded)"))}}let d=_c(e);for(let l of d)console.log(`\u2713 Copied: ${l} \u2192 project root`);await Rc(e),console.log(""),console.log("\u{1F4A1} To start Tilt: tdk up")}var xc=/\.(?:test|spec)\.[cm]?[jt]sx?$/;function gs(e){return xc.test(e)}function ks(e){if(S.existsSync(e))for(let t of S.readdirSync(e,{withFileTypes:!0})){let n=k.join(e,t.name);t.isDirectory()?ks(n):gs(n)&&S.rmSync(n,{force:!0})}}var wc=["engine","discovery","specs","ext"],Ec=[["shared-platform-engineering","docker-templates"]],vc=["install-deps.sh","bun-hoisted-symlink-fix.sh","prisma-bun-client-link-fix.sh","prisma-normalize-client.sh"];function Pc(){let e=wt("node:url").fileURLToPath(new URL("../dist/generator",import.meta.url))||process.cwd();for(let t=0;t<6;t++){if(S.existsSync(k.join(e,"Tiltfile"))&&S.existsSync(k.join(e,"engine")))return e;let n=k.dirname(e);if(n===e)break;e=n}return null}function $c(){let e=wt("node:url").fileURLToPath(new URL("../dist/generator",import.meta.url))||process.cwd();for(let r=0;r<8;r++){if(S.existsSync(k.join(e,"shared-platform-engineering","docker-templates")))return e;let s=k.dirname(e);if(s===e)break;e=s}let t=k.dirname(process.execPath);return[k.join(t,"tdk-cli"),k.join(process.cwd(),"node_modules","@tdk-landscape","tdk-cli-core")].find(r=>S.existsSync(k.join(r,"shared-platform-engineering","docker-templates")))??null}function _c(e){let t=$c(),n=[];if(!t)return console.warn("\u26A0\uFE0F TDK runtime assets not found - generated Dockerfiles may fail. Reinstall or upgrade TDK, then re-run `tdk project`."),n;for(let r of Ec){let s=k.join(t,...r),o=oe(e,k.join(...r));S.existsSync(s)&&(S.mkdirSync(k.dirname(o),{recursive:!0}),S.cpSync(s,o,{recursive:!0}),n.push(r.join("/")))}for(let r of vc){let s=k.join(e,"shared-platform-engineering","docker-templates",r);S.existsSync(s)||console.warn(`\u26A0\uFE0F Missing runtime asset after copy: ${s}`)}return n}async function Rc(e){let t=oe(e,k.join(".tdk",".tdk-out","tdk-cli-ext")),n=[];process.env.TDK_EXTENSION_SOURCE&&n.push(process.env.TDK_EXTENSION_SOURCE);let r=Pc();r&&n.push(r);let s=k.dirname(process.execPath);n.push(k.join(s,"tdk-cli")),n.push(k.join(e,"..","tdk-cli"));let o="";for(let i of n)if(i&&S.existsSync(k.join(i,"Tiltfile"))&&S.existsSync(k.join(i,"engine"))){o=i;break}if(!o){console.warn("\u26A0\uFE0F TDK extension not found - set TDK_EXTENSION_SOURCE to its checkout path and re-run `tdk project` (or `tdk config regenerate`) to vendor it before `tdk up`.");return}S.existsSync(t)||S.mkdirSync(t,{recursive:!0}),S.copyFileSync(k.join(o,"Tiltfile"),k.join(t,"Tiltfile"));for(let i of wc)ks(k.join(t,i)),S.cpSync(k.join(o,i),k.join(t,i),{recursive:!0,filter:a=>!gs(a)});console.log("\u2713 Vendored TDK extension \u2192 .tdk/.tdk-out/tdk-cli-ext/");try{let{applyPremiumOverlay:i}=await import("./extension-fetch-6XNTDF44.js");await i(e,t)}catch(i){console.warn(`\u26A0\uFE0F Premium overlay skipped: ${i.message}`)}}var ys="SYSTEM-GENERATED BY TDK CLI";function Bm(e){let t=[],n=[],r=[],s=[],o=(p,h,f)=>{h!==f&&(t.push(`${h===void 0?"Missing file":"Out of sync"}: ${p} (run 'tdk config regenerate')`),r.push({file:p,diff:Ac(p,h??"",f)}))},i=rt(e),c=new nt().generateAll(i),u=k.join(e,".tdk",".tdk-out");for(let p of hs){let h=c[p],f=k.join(u,p);o(`.tdk/.tdk-out/${p}`,S.existsSync(f)?S.readFileSync(f,"utf-8"):void 0,h)}let d=k.join(e,q),l=S.existsSync(d)?S.readFileSync(d,"utf-8"):void 0;l!==void 0&&!l.includes(ys)?n.push(".tiltignore: not generated by TDK, left as is"):o(q,l,c[q]);for(let p of nn(e)){let h=k.relative(e,p).split(k.sep).join("/"),f=Jr(p,h);t.push(...f.errors),n.push(...f.warnings);let b=Dc(e,p);t.push(...b.errors),s.push(...b.handEdited)}return{valid:t.length===0,errors:t,warnings:n,diffs:r,handEdited:s}}function Ac(e,t,n){let r=t.replace(/\n$/,"").split(`
64
+ `}function ms(e,t){if(!e||typeof e!="object")return!1;let n=e;for(let r of["pre_alpha","alpha","beta","out_of_scope"]){let s=n[r];if(!s||typeof s!="object"||!Array.isArray(s[t]))return!1}return!0}function bc(e){if(!e||typeof e!="object")return null;let t=e;if(typeof t.version!="string"||!t.project||typeof t.project!="object")return null;let n=t.project;if(typeof n.name!="string"||typeof n.version!="string")return null;let r=null;if(ms(t.phases,"enabledStacks"))r=t.phases;else if(ms(t.stacks,"services")){let i=t.stacks;r={pre_alpha:{name:i.pre_alpha.name,description:i.pre_alpha.description,enabledStacks:i.pre_alpha.services},alpha:{name:i.alpha.name,description:i.alpha.description,enabledStacks:i.alpha.services},beta:{name:i.beta.name,description:i.beta.description,enabledStacks:i.beta.services},out_of_scope:{name:i.out_of_scope.name,description:i.out_of_scope.description,enabledStacks:i.out_of_scope.services}}}if(!r||!t.optional_infra||typeof t.optional_infra!="object")return null;let s=t.optional_infra;if(typeof s.monitoring!="boolean"||typeof s.elk!="boolean"||typeof s.debezium!="boolean"||typeof s.golden_image!="boolean"||typeof s.verdaccio!="boolean"||!t.discovery||typeof t.discovery!="object")return null;let o=t.discovery;return Array.isArray(o.paths)?{version:t.version,project:t.project,phases:r,always_enabled_infra:t.always_enabled_infra,optional_infra:t.optional_infra,discovery:t.discovery,overrides:t.overrides}:null}var an=class extends Error{};function rt(e){let t=k.join(e,".tdk",_);if(!S.existsSync(t))throw new an(`Project config not found: ${t}. Run 'tdk project --yes' first.`);let n=S.readFileSync(t,"utf-8"),r=JSON.parse(n),s=bc(r);if(!s)throw new Error("Invalid project.json: missing or invalid required fields. Expected: version (string), project (object with name/version), phases (object with pre_alpha/alpha/beta/out_of_scope enabledStacks), optional_infra (object with boolean flags), discovery (object with paths array)");return s}async function Tc(e){let t=x(e).filter(r=>r.config?.sablier?.enable===!0);t.length===0||await sr(e)||console.warn(`\u26A0\uFE0F Sablier (on-demand scaling) is a Premium feature - no valid license key found. ${t.length} resource${t.length===1?" has":"s have"} a \`sablier\` block, but it will have no effect without a license. Set TDK_LICENSE_KEY to a key that grants it, or remove the \`sablier\` block from the affected service.json file(s) to silence this warning.`)}function xc(e,t){let n=oe(e,A);if(S.existsSync(n))return!1;let r={name:t.project.name||k.basename(e),version:t.project.version||"1.0.0",private:!0,type:"module",workspaces:t.discovery.paths};return It(n,`${JSON.stringify(r,null,2)}
65
+ `),!0}async function Hm(e,t={}){let n=rt(e),r=nn(e).flatMap(d=>Wr(d,k.relative(e,d).split(k.sep).join("/")));if(r.length>0)throw new Error(`Refusing to generate config from unsafe service.json values:
66
+ ${r.map(d=>` ${d}`).join(`
67
+ `)}`);await Tc(e),xc(e,n)&&!t.quiet&&console.log("\u2713 Generated: package.json (workspace root)");let s=Object.values(n.phases).some(d=>d.enabledStacks.includes("verdaccio"));(n.optional_infra.verdaccio||s)&&(await Ge(e)||console.warn("\u26A0\uFE0F Verdaccio is a Premium feature - no valid license key found. It's enabled in this project's config, but will have no effect without a license. Set TDK_LICENSE_KEY to a key that grants it, or run `tdk config disable-infra verdaccio` to silence this warning."));let o=k.join(e,".tdk",".tdk-out");S.existsSync(o)||S.mkdirSync(o,{recursive:!0});let a=new nt().generateAll(n);for(let d of hs){let p=a[d],h=oe(e,k.join(".tdk",".tdk-out",d));$e(h,p),t.quiet||console.log(`\u2713 Generated: .tdk/.tdk-out/${d}`)}if(fs(n.phases,j)){let d=oe(e,k.join("services","platform",j,se)),p=k.dirname(d);S.mkdirSync(p,{recursive:!0}),$e(d,Sc(n)),t.quiet||console.log("\u2713 Generated: services/platform/database-management/docker-compose.yml")}let c=k.join(o,q),l=oe(e,q);if(S.existsSync(c)){if(!S.existsSync(l))S.copyFileSync(c,l),console.log("\u2713 Copied: .tiltignore \u2192 project root");else if(t.discardHandEdits){let d=S.readFileSync(l,"utf-8");d.includes(ys)&&d!==S.readFileSync(c,"utf-8")&&(S.copyFileSync(c,l),console.log("\u2713 Restored: .tiltignore \u2192 project root (hand edits discarded)"))}}let u=Rc(e);for(let d of u)console.log(`\u2713 Copied: ${d} \u2192 project root`);await Ac(e),console.log(""),console.log("\u{1F4A1} To start Tilt: tdk up")}var wc=/\.(?:test|spec)\.[cm]?[jt]sx?$/;function gs(e){return wc.test(e)}function ks(e){if(S.existsSync(e))for(let t of S.readdirSync(e,{withFileTypes:!0})){let n=k.join(e,t.name);t.isDirectory()?ks(n):gs(n)&&S.rmSync(n,{force:!0})}}var Ec=["engine","discovery","specs","ext"],vc=[["shared-platform-engineering","docker-templates"]],Pc=["install-deps.sh","bun-hoisted-symlink-fix.sh","prisma-bun-client-link-fix.sh","prisma-normalize-client.sh"];function $c(){let e=wt("node:url").fileURLToPath(new URL("../dist/generator",import.meta.url))||process.cwd();for(let t=0;t<6;t++){if(S.existsSync(k.join(e,"Tiltfile"))&&S.existsSync(k.join(e,"engine")))return e;let n=k.dirname(e);if(n===e)break;e=n}return null}function _c(){let e=wt("node:url").fileURLToPath(new URL("../dist/generator",import.meta.url))||process.cwd();for(let r=0;r<8;r++){if(S.existsSync(k.join(e,"shared-platform-engineering","docker-templates")))return e;let s=k.dirname(e);if(s===e)break;e=s}let t=k.dirname(process.execPath);return[k.join(t,"tdk-cli"),k.join(process.cwd(),"node_modules","@tdk-landscape","tdk-cli-core")].find(r=>S.existsSync(k.join(r,"shared-platform-engineering","docker-templates")))??null}function Rc(e){let t=_c(),n=[];if(!t)return console.warn("\u26A0\uFE0F TDK runtime assets not found - generated Dockerfiles may fail. Reinstall or upgrade TDK, then re-run `tdk project`."),n;for(let r of vc){let s=k.join(t,...r),o=oe(e,k.join(...r));S.existsSync(s)&&(S.mkdirSync(k.dirname(o),{recursive:!0}),S.cpSync(s,o,{recursive:!0}),n.push(r.join("/")))}for(let r of Pc){let s=k.join(e,"shared-platform-engineering","docker-templates",r);S.existsSync(s)||console.warn(`\u26A0\uFE0F Missing runtime asset after copy: ${s}`)}return n}async function Ac(e){let t=oe(e,k.join(".tdk",".tdk-out","tdk-cli-ext")),n=[];process.env.TDK_EXTENSION_SOURCE&&n.push(process.env.TDK_EXTENSION_SOURCE);let r=$c();r&&n.push(r);let s=k.dirname(process.execPath);n.push(k.join(s,"tdk-cli")),n.push(k.join(e,"..","tdk-cli"));let o="";for(let i of n)if(i&&S.existsSync(k.join(i,"Tiltfile"))&&S.existsSync(k.join(i,"engine"))){o=i;break}if(!o){console.warn("\u26A0\uFE0F TDK extension not found - set TDK_EXTENSION_SOURCE to its checkout path and re-run `tdk project` (or `tdk config regenerate`) to vendor it before `tdk up`.");return}S.existsSync(t)||S.mkdirSync(t,{recursive:!0}),S.copyFileSync(k.join(o,"Tiltfile"),k.join(t,"Tiltfile"));for(let i of Ec)ks(k.join(t,i)),S.cpSync(k.join(o,i),k.join(t,i),{recursive:!0,filter:a=>!gs(a)});console.log("\u2713 Vendored TDK extension \u2192 .tdk/.tdk-out/tdk-cli-ext/");try{let{applyPremiumOverlay:i}=await import("./extension-fetch-6XNTDF44.js");await i(e,t)}catch(i){console.warn(`\u26A0\uFE0F Premium overlay skipped: ${i.message}`)}}var ys="SYSTEM-GENERATED BY TDK CLI";function Gm(e){let t=[],n=[],r=[],s=[],o=(p,h,f)=>{h!==f&&(t.push(`${h===void 0?"Missing file":"Out of sync"}: ${p} (run 'tdk config regenerate')`),r.push({file:p,diff:Dc(p,h??"",f)}))},i=rt(e),c=new nt().generateAll(i),l=k.join(e,".tdk",".tdk-out");for(let p of hs){let h=c[p],f=k.join(l,p);o(`.tdk/.tdk-out/${p}`,S.existsSync(f)?S.readFileSync(f,"utf-8"):void 0,h)}let u=k.join(e,q),d=S.existsSync(u)?S.readFileSync(u,"utf-8"):void 0;d!==void 0&&!d.includes(ys)?n.push(".tiltignore: not generated by TDK, left as is"):o(q,d,c[q]);for(let p of nn(e)){let h=k.relative(e,p).split(k.sep).join("/"),f=Jr(p,h);t.push(...f.errors),n.push(...f.warnings);let b=Oc(e,p);t.push(...b.errors),s.push(...b.handEdited)}return{valid:t.length===0,errors:t,warnings:n,diffs:r,handEdited:s}}function Dc(e,t,n){let r=t.replace(/\n$/,"").split(`
68
68
  `),s=n.replace(/\n$/,"").split(`
69
69
  `),o=[`--- a/${e}`,`+++ b/${e}`,`@@ -1,${r.length} +1,${s.length} @@`];for(let i of r)o.push(`-${i}`);for(let i of s)o.push(`+${i}`);return o.join(`
70
- `)}function Dc(e,t){let n=k.dirname(t),r=k.join(n,C);if(!S.existsSync(r))return{errors:[],handEdited:[]};let s=[],o=(d,l="")=>{for(let p of S.readdirSync(d,{withFileTypes:!0})){if(l===""&&p.name===".tdk-contract")continue;let h=k.join(l,p.name),f=k.join(d,p.name);p.isDirectory()?o(f,h):p.isFile()&&s.push({fullPath:f,relativeFile:h})}};if(o(r),s.length===0)return{errors:[],handEdited:[]};let i=k.join(r,".tdk-contract"),a=k.join(i,"service.json.source"),c=[],u=[];S.existsSync(a)?S.readFileSync(a,"utf-8")!==S.readFileSync(t,"utf-8")&&c.push(k.relative(e,t)+": service.json changed since generated outputs were written (run tdk up)"):c.push(k.relative(e,a)+": generated-file contract snapshot is missing (run tdk up to regenerate)");for(let d of s){if(d.relativeFile==="service.yaml")continue;let l=k.join(i,d.relativeFile),p=k.relative(e,d.fullPath);S.existsSync(l)?S.readFileSync(d.fullPath,"utf-8")!==S.readFileSync(l,"utf-8")&&(u.push(p.split(k.sep).join("/")),c.push(`${p}: generated file differs from its TDK snapshot (run tdk up to regenerate)`)):c.push(`${p}: generated-file snapshot is missing (run tdk up to regenerate)`)}return{errors:c,handEdited:u}}import{existsSync as Oc}from"node:fs";var st="docs/agent-hosts.md",cn=`WebContainers cannot run TDK: there is no Docker daemon or Tilt. Run \`tdk up\` on a machine with Docker. See ${st}.`,Ss=`Docker is not reachable from this Dev Container. Mount the host Docker socket (-v /var/run/docker.sock:/var/run/docker.sock) or add the docker-outside-of-docker feature to devcontainer.json, then retry. Docker-in-docker is not supported. See ${st}.`;function Nc(){return{env:process.env,versions:process.versions,platform:process.platform,fileExists:Oc}}function bs(e=Nc()){let{env:t,versions:n,platform:r,fileExists:s}=e;return n.webcontainer?{kind:"webcontainer",canUp:!1}:t.CODESPACES==="true"?{kind:"codespaces",canUp:!0}:t.REMOTE_CONTAINERS||s("/.dockerenv")&&t.DEVCONTAINER?{kind:"devcontainer",canUp:!0}:r==="win32"?{kind:"native-windows",canUp:t.TDK_ALLOW_NATIVE_WINDOWS==="1"}:r==="linux"&&t.WSL_DISTRO_NAME?{kind:"wsl2",canUp:!0}:{kind:"local",canUp:!0}}function Ts(e){return e==="devcontainer"||e==="codespaces"}function ot(e){return e.some(t=>I(t.config?.appType)||t.config?.appType==="frontend"||t.config?.appType==="worker")}import{existsSync as Cc,readFileSync as jc}from"node:fs";import{join as Ic,relative as xs,resolve as ws,sep as Fc}from"node:path";var Lc=2,Es=["services/*/*"];function vs(e){return e.split(Fc).filter(Boolean)}function Mc(e,t){let n=0,r=0,s=-1,o=0;for(;r<t.length;)if(n<e.length&&e[n]!=="*"&&(e[n]==="?"||e[n]===t[r]))n++,r++;else if(n<e.length&&e[n]==="*")s=n++,o=r;else if(s!==-1)n=s+1,r=++o;else return!1;for(;n<e.length&&e[n]==="*";)n++;return n===e.length}function Uc(e,t){return e.length===t.length&&e.every((n,r)=>Mc(n,t[r]))}function un(e){let t=Ic(e,".tdk",_);if(!Cc(t))return Es;try{let n=JSON.parse(jc(t,"utf-8"))?.discovery?.paths;if(Array.isArray(n)&&n.every(r=>typeof r=="string"))return n}catch{}return Es}function it(e,t,n){let r=vs(xs(e,ws(e,t)));return n.some(s=>{let o=vs(xs(e,ws(e,s)));for(let i=0;i<=Lc;i++){let a=r.length-i;if(a>0&&Uc(o,r.slice(0,a)))return!0}return!1})}function Ym(e,t,n,r){let s=un(e);if(it(e,t,s))return{path:t};let o=`services/${n}/${r}`;return it(e,o,s)?{path:o,adjustedFrom:t}:{path:t}}import{execFile as pu}from"node:child_process";import{promisify as fu}from"node:util";import{execFileSync as Os,execSync as Fe}from"node:child_process";import{existsSync as ln,readdirSync as Bc,readFileSync as dn}from"node:fs";import{join as fe}from"node:path";function Ps(e,t){return e==="pending"||e==="in_progress"||e==="none"||t==="pending"||t==="none"}var $s="container is running, but its health check is failing";function _s(e){let t=e?.runtimeStatus??"";if(t!=="ok")return t;let n=e?.composeResourceInfo?.healthStatus;return n==="unhealthy"?"error":n==="starting"?"pending":t}var je=1e4,Rs=3e3,Hc="http://localhost:4873";function Ns(e){return`'${e.replace(/'/g,"'\\''")}'`}function Ie(e,t,n,r,s){return process.platform==="win32"?Os(O(t)??t,n,{...s,windowsHide:!0}):e(r,s)}var Kc=[80,443];function pn(e){return e.replace(/-/g,"_")}function Gc(e,t){let n=new Set(t),r=[];for(let s of e.split(`
71
- `)){let o=s.trim();if(!o)continue;let i=o.indexOf(" "),a=i>=0?o.slice(0,i):o,c=i>=0?o.slice(i+1):"",u=[];for(let d of n)c.split(/[\s,]+/).some(p=>p.startsWith(`${d}->`)||p.includes(`:${d}->`))&&u.push(d);u.length>0&&r.push({name:a,ports:c,publishedPorts:u})}return r}function Cs(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return n===`${r}_traefik`||n.startsWith(`${r}_traefik`)}function Vc(e,t){return e.filter(n=>!Cs(n.name,t))}function fn(){try{return new Set(Ne().filter(e=>e.config?.sablier?.enable&&e.config?.sablier?.deferStart).map(e=>e.name))}catch{return new Set}}function mn(e,t=new Set){let r=JSON.parse(e).items??[],s=[],o=0,i=0,a=0;for(let c of r){let u=c.metadata?.name??"unknown",d=c.status?.updateStatus??"",l=_s(c.status),p=l==="error"&&c.status?.runtimeStatus==="ok",f=(c.status?.buildHistory?.[0]?.error??"").trim()||(p?$s:"");if(d==="error"||l==="error"){s.push({name:u,updateStatus:d,runtimeStatus:l,error:f.replace(/\s+/g," ").slice(0,800)});continue}if(d==="ok"&&(l==="ok"||l==="not_applicable")){a+=1;continue}u!=="(Tiltfile)"&&Ps(d,l)&&(t.has(u)?i+=1:o+=1)}return{failures:s,pendingCount:o,deferredCount:i,okCount:a,total:r.length}}var Wc=/failed to resolve source metadata for docker\.io\/library\/([A-Za-z0-9._-]+-l[1-4](?:-[a-z]+)*)(?::[^\s:]+)?:/i;function hn(e){let t=e.replace(/\s+/g," ").trim(),n=t.match(/Bind for [^ ]+:(\d+) failed: port is already allocated/i);if(n)return`host port ${n[1]} is already allocated`;if(/port is already allocated/i.test(t))return"a required host port is already allocated";let r=[...t.matchAll(/ConnectionRefused downloading package manifest (@[A-Za-z0-9._/-]+)/gi)].map(a=>a[1]);if(r.length>0){let a=[...new Set(r)],c=a.slice(0,4).join(", "),u=a.length>4?` (+${a.length-4} more)`:"";return`private registry ConnectionRefused for ${c}${u} \u2014 Verdaccio (:4873) is down or unreachable from the build`}let s=t.match(Wc);if(s)return`base image ${s[1]} was missing when this build started (the golden layers weren't built yet, or golden-layers-build failed) - Tilt does not retry a failed build by itself`;if(/install-deps\.sh/i.test(t)||/bun install(?: --production)?/i.test(t)||/npm (?:ci|install)/i.test(t))return"dependency install failed during ImageBuild \u2014 usually Verdaccio (:4873) unreachable or missing @scoped packages (ConnectionRefused downloading package manifest)";let o=t.match(/No such image:\s*([^\s]+)/i)?.[1]??t.match(/pull access denied for ([^,:\s]+)/i)?.[1]??void 0,i=t.match(/\bup\s+-d\s+--no-build\s+([A-Za-z0-9._-]+)/i)?.[1];if(o||i||/docker compose .*\bup\s+-d\s+--no-build\b/i.test(t)){let a=o??`${i??"service"}:dev`,c=i?` for ${i}`:"";return`compose run failed because image is missing (${a})${c} \u2014 wait for the ImageBuild resource to finish, then re-trigger the *-run-only resource`}return/bun run build/i.test(t)?"ImageBuild failed during `bun run build` (compile/typecheck) \u2014 open the resource logs in Tilt for the TypeScript/build error":(/ImageBuild:/i.test(t)||/^Command "/i.test(t),t.slice(0,220))}function As(e){return/ConnectionRefused downloading package manifest|Verdaccio|private registry|dependency install failed during ImageBuild|install-deps\.sh|bun install/i.test(e)}function gn(e=y()??process.cwd()){let t=fe(e,".tdk",_);if(!ln(t))return!1;try{let n=JSON.parse(dn(t,"utf-8"));return n.optional_infra?.verdaccio===!0||Object.values(n.phases??{}).some(r=>(r.enabledStacks??[]).includes("verdaccio"))}catch{return!1}}function js(e){for(let t of[fe(e,".npmrc"),fe(e,A)])if(ln(t))try{let n=dn(t,"utf-8");if(/:4873\b/.test(n)||/verdaccio/i.test(n))return!0}catch{}return!1}function Jc(e=y()??process.cwd()){return gn(e)||js(e)}function kn(e=Fe,t=y()??process.cwd(),n=process.env.VERDACCIO_URL??process.env.NPM_REGISTRY_URL??Hc,r=!0){if(!r&&!js(t))return{name:"Private npm registry",didPass:!0,isSkipped:!0,message:"Verdaccio is enabled in the project config but needs a Premium license, so TDK will not start it - skipped"};if(!Jc(t))return{name:"Private npm registry",didPass:!0,isSkipped:!0,message:"Private npm registry (Verdaccio) not enabled for this project - skipped"};let s=!1;try{let a=Ie(e,"docker",["ps","--format","{{.Names}}"],"docker ps --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:je});s=/verdaccio/i.test(a)}catch{}let o=!1,i="";try{let a=process.platform==="win32"?Os("curl.exe",["-fsS","-o","NUL","-w","%{http_code}","--max-time","2",n],{stdio:"pipe",encoding:"utf-8",timeout:Rs+1e3,windowsHide:!0}).trim():e(`curl -fsS -o /dev/null -w '%{http_code}' --max-time 2 ${Ns(n)}`,{stdio:"pipe",encoding:"utf-8",timeout:Rs+1e3}).trim();o=/^[23]\d\d$/.test(a),i=`HTTP ${a}`}catch(a){i=a instanceof Error?a.message.slice(0,120):"request failed"}return o?{name:"Private npm registry",didPass:!0,message:`Private npm registry reachable at ${n}${s?" (verdaccio container running)":""}`}:s?{name:"Private npm registry",didPass:!1,message:`Verdaccio container is running but ${n} is not responding (${i}). ImageBuilds that install @scoped packages will fail with ConnectionRefused downloading package manifest.`,fix:"Check `docker logs` for the verdaccio container, confirm port 4873 is published, then re-run `tdk doctor`."}:{name:"Private npm registry",didPass:!1,message:`Private npm registry (Verdaccio) is not reachable at ${n}. Docker ImageBuilds will fail with ConnectionRefused downloading package manifests for @tdk-landscape/* and project-scoped packages.`,fix:"Start the registry with `bun run verdaccio:start` (or `docker compose -f docker-compose.verdaccio.yml up -d`), publish packages with `bun run publish:all` / `scripts/build/publish-to-verdaccio.sh`, then `tilt trigger` failed resources or re-run `tdk up`."}}function yn(e=Fe,t=le(),n=Kc){let r=pn(t),s="";try{s=Ie(e,"docker",["ps","--format","{{.Names}}\\t{{.Ports}}"],"docker ps --format '{{.Names}}\\t{{.Ports}}'",{stdio:"pipe",encoding:"utf-8",timeout:je})}catch{return{name:"Ingress Ports",didPass:!0,isSkipped:!0,message:"Docker not available - skipped ingress port check"}}let o=Gc(s,n),i=Vc(o,r);if(i.length===0){let c=o.filter(u=>Cs(u.name,r));return c.length>0?{name:"Ingress Ports",didPass:!0,message:`Ingress ports ${n.join("/")} held by this project's Traefik (${c.map(u=>u.name).join(", ")})`}:{name:"Ingress Ports",didPass:!0,message:`Ingress ports ${n.join("/")} are free for Traefik`}}return{name:"Ingress Ports",didPass:!1,message:`Traefik cannot bind ingress ports because another container already owns them:
72
- ${i.map(c=>{let u=c.publishedPorts.join(", ");return`${c.name} (host ports ${u})`}).join(`
73
- `)}`,fix:`Stop the foreign container(s), e.g. \`docker stop ${i[0]?.name}\`, or shut down the other TDK/Tilt project using that Traefik. Then re-run \`tdk up\`.`}}function qc(e){let{status:t}=e;return t===void 0?e.error??"no response":t===404?"HTTP 404: Traefik is answering but has no route for this URL (container not started yet, or not running)":t===502||t===503||t===504?`HTTP ${t}: Traefik found the route but the container isn't answering (still starting, or unhealthy)`:`HTTP ${t}`}function Sn(e){let t=e.filter(o=>o.status!==void 0),n=e.filter(o=>!o.ok);if(t.length===0)return{name:"Service Health",didPass:!0,isSkipped:!0,message:`No services responded - skipped ping of ${T(e.length,"service")} (stack may be down, or Traefik never bound :80)`,fix:"If `tdk up` is already running, check Traefik/port 80 in the Tilt UI. Otherwise start with: tdk up"};if(n.length===0)return{name:"Service Health",didPass:!0,message:`All ${T(e.length,"service")} responding on /health`};let r=n.map(o=>`${o.name} (${qc(o)})
70
+ `)}function Oc(e,t){let n=k.dirname(t),r=k.join(n,C);if(!S.existsSync(r))return{errors:[],handEdited:[]};let s=[],o=(u,d="")=>{for(let p of S.readdirSync(u,{withFileTypes:!0})){if(d===""&&p.name===".tdk-contract")continue;let h=k.join(d,p.name),f=k.join(u,p.name);p.isDirectory()?o(f,h):p.isFile()&&s.push({fullPath:f,relativeFile:h})}};if(o(r),s.length===0)return{errors:[],handEdited:[]};let i=k.join(r,".tdk-contract"),a=k.join(i,"service.json.source"),c=[],l=[];S.existsSync(a)?S.readFileSync(a,"utf-8")!==S.readFileSync(t,"utf-8")&&c.push(k.relative(e,t)+": service.json changed since generated outputs were written (run tdk up)"):c.push(k.relative(e,a)+": generated-file contract snapshot is missing (run tdk up to regenerate)");for(let u of s){if(u.relativeFile==="service.yaml")continue;let d=k.join(i,u.relativeFile),p=k.relative(e,u.fullPath);S.existsSync(d)?S.readFileSync(u.fullPath,"utf-8")!==S.readFileSync(d,"utf-8")&&(l.push(p.split(k.sep).join("/")),c.push(`${p}: generated file differs from its TDK snapshot (run tdk up to regenerate)`)):c.push(`${p}: generated-file snapshot is missing (run tdk up to regenerate)`)}return{errors:c,handEdited:l}}import{existsSync as Nc}from"node:fs";var st="docs/agent-hosts.md",cn=`WebContainers cannot run TDK: there is no Docker daemon or Tilt. Run \`tdk up\` on a machine with Docker. See ${st}.`,Ss=`Docker is not reachable from this Dev Container. Mount the host Docker socket (-v /var/run/docker.sock:/var/run/docker.sock) or add the docker-outside-of-docker feature to devcontainer.json, then retry. Docker-in-docker is not supported. See ${st}.`;function Cc(){return{env:process.env,versions:process.versions,platform:process.platform,fileExists:Nc}}function bs(e=Cc()){let{env:t,versions:n,platform:r,fileExists:s}=e;return n.webcontainer?{kind:"webcontainer",canUp:!1}:t.CODESPACES==="true"?{kind:"codespaces",canUp:!0}:t.REMOTE_CONTAINERS||s("/.dockerenv")&&t.DEVCONTAINER?{kind:"devcontainer",canUp:!0}:r==="win32"?{kind:"native-windows",canUp:t.TDK_ALLOW_NATIVE_WINDOWS==="1"}:r==="linux"&&t.WSL_DISTRO_NAME?{kind:"wsl2",canUp:!0}:{kind:"local",canUp:!0}}function Ts(e){return e==="devcontainer"||e==="codespaces"}function ot(e){return e.some(t=>I(t.config?.appType)||t.config?.appType==="frontend"||t.config?.appType==="worker")}import{existsSync as jc,readFileSync as Ic}from"node:fs";import{join as Fc,relative as xs,resolve as ws,sep as Lc}from"node:path";var Mc=2,Es=["services/*/*"];function vs(e){return e.split(Lc).filter(Boolean)}function Uc(e,t){let n=0,r=0,s=-1,o=0;for(;r<t.length;)if(n<e.length&&e[n]!=="*"&&(e[n]==="?"||e[n]===t[r]))n++,r++;else if(n<e.length&&e[n]==="*")s=n++,o=r;else if(s!==-1)n=s+1,r=++o;else return!1;for(;n<e.length&&e[n]==="*";)n++;return n===e.length}function Bc(e,t){return e.length===t.length&&e.every((n,r)=>Uc(n,t[r]))}function ln(e){let t=Fc(e,".tdk",_);if(!jc(t))return Es;try{let n=JSON.parse(Ic(t,"utf-8"))?.discovery?.paths;if(Array.isArray(n)&&n.every(r=>typeof r=="string"))return n}catch{}return Es}function it(e,t,n){let r=vs(xs(e,ws(e,t)));return n.some(s=>{let o=vs(xs(e,ws(e,s)));for(let i=0;i<=Mc;i++){let a=r.length-i;if(a>0&&Bc(o,r.slice(0,a)))return!0}return!1})}function Qm(e,t,n,r){let s=ln(e);if(it(e,t,s))return{path:t};let o=`services/${n}/${r}`;return it(e,o,s)?{path:o,adjustedFrom:t}:{path:t}}import{execFile as fl}from"node:child_process";import{promisify as ml}from"node:util";import{execFileSync as Os,execSync as Fe}from"node:child_process";import{existsSync as dn,readdirSync as Hc,readFileSync as un}from"node:fs";import{join as fe}from"node:path";function Ps(e,t){return e==="pending"||e==="in_progress"||e==="none"||t==="pending"||t==="none"}var $s="container is running, but its health check is failing";function _s(e){let t=e?.runtimeStatus??"";if(t!=="ok")return t;let n=e?.composeResourceInfo?.healthStatus;return n==="unhealthy"?"error":n==="starting"?"pending":t}var je=1e4,Rs=3e3,Gc="http://localhost:4873";function Ns(e){return`'${e.replace(/'/g,"'\\''")}'`}function Ie(e,t,n,r,s){return process.platform==="win32"?Os(O(t)??t,n,{...s,windowsHide:!0}):e(r,s)}var Kc=[80,443];function pn(e){return e.replace(/-/g,"_")}function Vc(e,t){let n=new Set(t),r=[];for(let s of e.split(`
71
+ `)){let o=s.trim();if(!o)continue;let i=o.indexOf(" "),a=i>=0?o.slice(0,i):o,c=i>=0?o.slice(i+1):"",l=[];for(let u of n)c.split(/[\s,]+/).some(p=>p.startsWith(`${u}->`)||p.includes(`:${u}->`))&&l.push(u);l.length>0&&r.push({name:a,ports:c,publishedPorts:l})}return r}function Cs(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return n===`${r}_traefik`||n.startsWith(`${r}_traefik`)}function Wc(e,t){return e.filter(n=>!Cs(n.name,t))}function fn(){try{return new Set(Ne().filter(e=>e.config?.sablier?.enable&&e.config?.sablier?.deferStart).map(e=>e.name))}catch{return new Set}}function mn(e,t=new Set){let r=JSON.parse(e).items??[],s=[],o=0,i=0,a=0;for(let c of r){let l=c.metadata?.name??"unknown",u=c.status?.updateStatus??"",d=_s(c.status),p=d==="error"&&c.status?.runtimeStatus==="ok",f=(c.status?.buildHistory?.[0]?.error??"").trim()||(p?$s:"");if(u==="error"||d==="error"){s.push({name:l,updateStatus:u,runtimeStatus:d,error:f.replace(/\s+/g," ").slice(0,800)});continue}if(u==="ok"&&(d==="ok"||d==="not_applicable")){a+=1;continue}l!=="(Tiltfile)"&&Ps(u,d)&&(t.has(l)?i+=1:o+=1)}return{failures:s,pendingCount:o,deferredCount:i,okCount:a,total:r.length}}var Jc=/failed to resolve source metadata for docker\.io\/library\/([A-Za-z0-9._-]+-l[1-4](?:-[a-z]+)*)(?::[^\s:]+)?:/i;function hn(e){let t=e.replace(/\s+/g," ").trim(),n=t.match(/Bind for [^ ]+:(\d+) failed: port is already allocated/i);if(n)return`host port ${n[1]} is already allocated`;if(/port is already allocated/i.test(t))return"a required host port is already allocated";let r=[...t.matchAll(/ConnectionRefused downloading package manifest (@[A-Za-z0-9._/-]+)/gi)].map(a=>a[1]);if(r.length>0){let a=[...new Set(r)],c=a.slice(0,4).join(", "),l=a.length>4?` (+${a.length-4} more)`:"";return`private registry ConnectionRefused for ${c}${l} \u2014 Verdaccio (:4873) is down or unreachable from the build`}let s=t.match(Jc);if(s)return`base image ${s[1]} was missing when this build started (the golden layers weren't built yet, or golden-layers-build failed) - Tilt does not retry a failed build by itself`;if(/install-deps\.sh/i.test(t)||/bun install(?: --production)?/i.test(t)||/npm (?:ci|install)/i.test(t))return"dependency install failed during ImageBuild \u2014 usually Verdaccio (:4873) unreachable or missing @scoped packages (ConnectionRefused downloading package manifest)";let o=t.match(/No such image:\s*([^\s]+)/i)?.[1]??t.match(/pull access denied for ([^,:\s]+)/i)?.[1]??void 0,i=t.match(/\bup\s+-d\s+--no-build\s+([A-Za-z0-9._-]+)/i)?.[1];if(o||i||/docker compose .*\bup\s+-d\s+--no-build\b/i.test(t)){let a=o??`${i??"service"}:dev`,c=i?` for ${i}`:"";return`compose run failed because image is missing (${a})${c} \u2014 wait for the ImageBuild resource to finish, then re-trigger the *-run-only resource`}return/bun run build/i.test(t)?"ImageBuild failed during `bun run build` (compile/typecheck) \u2014 open the resource logs in Tilt for the TypeScript/build error":(/ImageBuild:/i.test(t)||/^Command "/i.test(t),t.slice(0,220))}function As(e){return/ConnectionRefused downloading package manifest|Verdaccio|private registry|dependency install failed during ImageBuild|install-deps\.sh|bun install/i.test(e)}function gn(e=y()??process.cwd()){let t=fe(e,".tdk",_);if(!dn(t))return!1;try{let n=JSON.parse(un(t,"utf-8"));return n.optional_infra?.verdaccio===!0||Object.values(n.phases??{}).some(r=>(r.enabledStacks??[]).includes("verdaccio"))}catch{return!1}}function js(e){for(let t of[fe(e,".npmrc"),fe(e,A)])if(dn(t))try{let n=un(t,"utf-8");if(/:4873\b/.test(n)||/verdaccio/i.test(n))return!0}catch{}return!1}function qc(e=y()??process.cwd()){return gn(e)||js(e)}function kn(e=Fe,t=y()??process.cwd(),n=process.env.VERDACCIO_URL??process.env.NPM_REGISTRY_URL??Gc,r=!0){if(!r&&!js(t))return{name:"Private npm registry",didPass:!0,isSkipped:!0,message:"Verdaccio is enabled in the project config but needs a Premium license, so TDK will not start it - skipped"};if(!qc(t))return{name:"Private npm registry",didPass:!0,isSkipped:!0,message:"Private npm registry (Verdaccio) not enabled for this project - skipped"};let s=!1;try{let a=Ie(e,"docker",["ps","--format","{{.Names}}"],"docker ps --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:je});s=/verdaccio/i.test(a)}catch{}let o=!1,i="";try{let a=process.platform==="win32"?Os("curl.exe",["-fsS","-o","NUL","-w","%{http_code}","--max-time","2",n],{stdio:"pipe",encoding:"utf-8",timeout:Rs+1e3,windowsHide:!0}).trim():e(`curl -fsS -o /dev/null -w '%{http_code}' --max-time 2 ${Ns(n)}`,{stdio:"pipe",encoding:"utf-8",timeout:Rs+1e3}).trim();o=/^[23]\d\d$/.test(a),i=`HTTP ${a}`}catch(a){i=a instanceof Error?a.message.slice(0,120):"request failed"}return o?{name:"Private npm registry",didPass:!0,message:`Private npm registry reachable at ${n}${s?" (verdaccio container running)":""}`}:s?{name:"Private npm registry",didPass:!1,message:`Verdaccio container is running but ${n} is not responding (${i}). ImageBuilds that install @scoped packages will fail with ConnectionRefused downloading package manifest.`,fix:"Check `docker logs` for the verdaccio container, confirm port 4873 is published, then re-run `tdk doctor`."}:{name:"Private npm registry",didPass:!1,message:`Private npm registry (Verdaccio) is not reachable at ${n}. Docker ImageBuilds will fail with ConnectionRefused downloading package manifests for @tdk-landscape/* and project-scoped packages.`,fix:"Start the registry with `bun run verdaccio:start` (or `docker compose -f docker-compose.verdaccio.yml up -d`), publish packages with `bun run publish:all` / `scripts/build/publish-to-verdaccio.sh`, then `tilt trigger` failed resources or re-run `tdk up`."}}function yn(e=Fe,t=de(),n=Kc){let r=pn(t),s="";try{s=Ie(e,"docker",["ps","--format","{{.Names}}\\t{{.Ports}}"],"docker ps --format '{{.Names}}\\t{{.Ports}}'",{stdio:"pipe",encoding:"utf-8",timeout:je})}catch{return{name:"Ingress Ports",didPass:!0,isSkipped:!0,message:"Docker not available - skipped ingress port check"}}let o=Vc(s,n),i=Wc(o,r);if(i.length===0){let c=o.filter(l=>Cs(l.name,r));return c.length>0?{name:"Ingress Ports",didPass:!0,message:`Ingress ports ${n.join("/")} held by this project's Traefik (${c.map(l=>l.name).join(", ")})`}:{name:"Ingress Ports",didPass:!0,message:`Ingress ports ${n.join("/")} are free for Traefik`}}return{name:"Ingress Ports",didPass:!1,message:`Traefik cannot bind ingress ports because another container already owns them:
72
+ ${i.map(c=>{let l=c.publishedPorts.join(", ");return`${c.name} (host ports ${l})`}).join(`
73
+ `)}`,fix:`Stop the foreign container(s), e.g. \`docker stop ${i[0]?.name}\`, or shut down the other TDK/Tilt project using that Traefik. Then re-run \`tdk up\`.`}}function zc(e){let{status:t}=e;return t===void 0?e.error??"no response":t===404?"HTTP 404: Traefik is answering but has no route for this URL (container not started yet, or not running)":t===502||t===503||t===504?`HTTP ${t}: Traefik found the route but the container isn't answering (still starting, or unhealthy)`:`HTTP ${t}`}function Sn(e){let t=e.filter(o=>o.status!==void 0),n=e.filter(o=>!o.ok);if(t.length===0)return{name:"Service Health",didPass:!0,isSkipped:!0,message:`No services responded - skipped ping of ${T(e.length,"service")} (stack may be down, or Traefik never bound :80)`,fix:"If `tdk up` is already running, check Traefik/port 80 in the Tilt UI. Otherwise start with: tdk up"};if(n.length===0)return{name:"Service Health",didPass:!0,message:`All ${T(e.length,"service")} responding on /health`};let r=n.map(o=>`${o.name} (${zc(o)})
74
74
  ${o.url}`).join(`
75
75
  `),s=n.some(o=>o.status===404);return{name:"Service Health",didPass:!1,message:`${T(n.length,"service")} not healthy (${e.length-n.length}/${e.length} healthy):
76
76
  ${r}`,fix:s?"If `tdk up` just started, images may still be building: re-run `tdk doctor` in a minute. Otherwise check `docker ps` and the resource in the Tilt UI, and compare `tdk networks` with the URL above.":"Check container state and routing: docker ps, then tdk networks to compare the advertised URLs against Traefik's routers"}}function bn(e){if(e.length===0)return{name:"Service Smoke",didPass:!0,isSkipped:!0,message:"No read-only smoke checks declared"};let t=e.filter(r=>!r.ok);if(t.length===0)return{name:"Service Smoke",didPass:!0,message:`All ${T(e.length,"service")} pass their smoke checks`};let n=t.map(r=>r.failure??`${r.name}: failed`).join(`
@@ -78,31 +78,31 @@ ${r.map(l=>` ${l}`).join(`
78
78
  ${n}`,fix:'Add the route the smoke step expects, or correct its "path" in the service.json "smoke" block. Then re-run tdk doctor.'}}function Is(e){let t=e.filter(s=>s.status!==void 0);if(t.length===0)return{name:"Advertised Endpoints",didPass:!0,isSkipped:!0,message:"No services responded - skipped advertised endpoint check"};let n=t.filter(s=>s.status===404);if(n.length===0)return{name:"Advertised Endpoints",didPass:!0,message:`${T(t.length,"advertised endpoint")} reachable`};let r=n.map(s=>`${s.name} (404)
79
79
  ${s.url}`).join(`
80
80
  `);return{name:"Advertised Endpoints",didPass:!0,isWarning:!0,message:`${T(n.length,"advertised link")} ${n.length===1?"returns":"return"} 404 (the service may be healthy, but nothing answers at this exact path):
81
- ${r}`,fix:'Nothing handles this exact path, so opening the link shows a 404 even when /health is fine. If this API has no root route, you can leave it. Otherwise add a GET route for it (for example one that returns the service name), or declare a read-only "smoke" step on a real route in service.json. The URL tdk networks and the TDK App print stays the same until the CLI changes how it reports it.'}}function Tn(e=Fe){let t="";try{t=Ie(e,"tilt",["get","uiresources","-o","json"],"tilt get uiresources -o json",{stdio:"pipe",encoding:"utf-8",timeout:je})}catch{return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"Tilt is not running - skipped resource status check",fix:"Start them with: tdk up"}}let n;try{n=mn(t,fn())}catch{return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"Could not parse Tilt resource status - skipped"}}if(n.total===0)return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"No Tilt UIResources found"};if(n.failures.length===0){let w=n.deferredCount>0?`, ${n.deferredCount} deferred`:"";return{name:"Tilt Resources",didPass:!0,message:`Tilt resources healthy (${n.okCount} ok, ${n.pendingCount} pending${w})`}}let r=Yc(n.failures),o=r.slice(0,20),i=r.length-o.length,a=o.map(w=>({failure:w,why:Qc(w,e)})),c=a.map(({failure:w,why:$})=>`${w.name}: ${$}`).join(`
82
- `),u=i>0?`
83
- \u2026and ${T(i,"more failed resource")}`:"",d=n.pendingCount>0?`
84
- ${T(n.pendingCount,"resource")} still pending/not started \u2014 often blocked by the failures above.`:"",l=n.deferredCount>0?`
81
+ ${r}`,fix:'Nothing handles this exact path, so opening the link shows a 404 even when /health is fine. If this API has no root route, you can leave it. Otherwise add a GET route for it (for example one that returns the service name), or declare a read-only "smoke" step on a real route in service.json. The URL tdk networks and the TDK App print stays the same until the CLI changes how it reports it.'}}function Tn(e=Fe){let t="";try{t=Ie(e,"tilt",["get","uiresources","-o","json"],"tilt get uiresources -o json",{stdio:"pipe",encoding:"utf-8",timeout:je})}catch{return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"Tilt is not running - skipped resource status check",fix:"Start them with: tdk up"}}let n;try{n=mn(t,fn())}catch{return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"Could not parse Tilt resource status - skipped"}}if(n.total===0)return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"No Tilt UIResources found"};if(n.failures.length===0){let w=n.deferredCount>0?`, ${n.deferredCount} deferred`:"";return{name:"Tilt Resources",didPass:!0,message:`Tilt resources healthy (${n.okCount} ok, ${n.pendingCount} pending${w})`}}let r=Xc(n.failures),o=r.slice(0,20),i=r.length-o.length,a=o.map(w=>({failure:w,why:Zc(w,e)})),c=a.map(({failure:w,why:$})=>`${w.name}: ${$}`).join(`
82
+ `),l=i>0?`
83
+ \u2026and ${T(i,"more failed resource")}`:"",u=n.pendingCount>0?`
84
+ ${T(n.pendingCount,"resource")} still pending/not started \u2014 often blocked by the failures above.`:"",d=n.deferredCount>0?`
85
85
  ${T(n.deferredCount,"resource")} intentionally deferred (sablier.deferStart) \u2014 not started until first request, unrelated to the failures above.`:"",p=r.some(w=>/port is already allocated/i.test(w.error)),h=r.some(w=>As(w.error)||As(hn(w.error))),f=a.some(({why:w})=>/Kafka broker unreachable|kafka:9092/i.test(w)),b="Open the Tilt UI URL printed by tdk up (default port "+Pe.tiltUi+" when TILT_PORT is unset), inspect the red resources, fix the listed errors, then `tilt trigger <resource>` or re-run `tdk up`.";return p?b="Free the conflicting host port (usually 80/443): `docker ps --filter publish=80` then `docker stop <other-traefik>`. Re-trigger Traefik in the Tilt UI or run `tdk up` again.":h?b="Start Verdaccio (`bun run verdaccio:start`), ensure packages are published (`bun run publish:all` or `bash scripts/build/publish-to-verdaccio.sh`), confirm `curl http://localhost:4873` works, then `tilt trigger` the failed resources.":f&&(b="Kafka is not running (optional infra). Start it, point the bridge at a real broker, or disable Kafka-dependent resources until Kafka is enabled."),{name:"Tilt Resources",didPass:!1,message:`Tilt reports ${T(n.failures.length,"failed resource")}:
86
- ${c}${u}${d}${l}`,fix:b}}var zc=/^(traefik|postgres|nats|infisical|verdaccio|proxy)([.-]|$)/i;function Ds(e){return zc.test(e)}function Yc(e){return[...e].sort((t,n)=>{let r=Ds(t.name)?0:1,s=Ds(n.name)?0:1;return r!==s?r-s:t.name.localeCompare(n.name)})}function Xc(e,t=Fe,n=le()){try{let r=Ie(t,"docker",["ps","-a","--format","{{.Names}}"],"docker ps -a --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:je}).split(`
87
- `).map(u=>u.trim()).filter(Boolean),s=`-autogenerated-${e}-1`,o=r.find(u=>u===e)??r.find(u=>u.startsWith(`${n}-`)&&u.endsWith(s))??r.find(u=>u.endsWith(s))??r.find(u=>u.includes(e));if(!o)return null;let i=Ie(t,"docker",["logs","--tail","120",o],`docker logs --tail 120 ${Ns(o)} 2>&1`,{stdio:"pipe",encoding:"utf-8",timeout:je});if(/getaddrinfo ENOTFOUND/i.test(i)&&/kafka:9092/i.test(i))return"runtime crash: Kafka broker unreachable (getaddrinfo ENOTFOUND kafka:9092)";if(/ECONNREFUSED/i.test(i)&&/kafka/i.test(i))return"runtime crash: Kafka connection refused";let a=i.match(/ConnectionRefused downloading package manifest (@[A-Za-z0-9._/-]+)/i);if(a?.[1])return`runtime/build log: private registry ConnectionRefused for ${a[1]}`;if(/ZodError/i.test(i)){let u=[...i.matchAll(/"path"\s*:\s*\[\s*"([^"]+)"\s*\]/g)].map(l=>l[1]),d=[...new Set(u)].slice(0,6);return d.length>0?`runtime crash: ZodError missing required config/env: ${d.join(", ")}`:"runtime crash: ZodError during config/env validation"}let c=i.match(/error:\s+Failed to [^:\n]+[^\n]{0,120}/i)?.[0]??i.match(/Failed to (?:start|initialize) [^\n]{0,120}/i)?.[0]??i.match(/^\s*error:\s+[^\n]{0,160}/im)?.[0];if(c)return`runtime crash: ${c.replace(/\s+/g," ").trim().slice(0,180)}`}catch{return null}return null}function Qc(e,t=Fe){return e.error?hn(e.error):e.runtimeStatus==="error"?Xc(e.name,t)??"runtime error (container crashed or unhealthy \u2014 check Tilt/docker logs)":e.updateStatus||e.runtimeStatus||"unknown error"}var Zc=/\.(ts|tsx|mts|js|mjs|cjs)$/,eu=new Set(["node_modules","dist",C,"tests","__tests__"]);function Fs(e){let t=[];for(let n of Bc(e,{withFileTypes:!0}))n.isDirectory()?eu.has(n.name)||t.push(...Fs(fe(e,n.name))):Zc.test(n.name)&&!/\.(test|spec)\./.test(n.name)&&t.push(fe(e,n.name));return t}function tu(e){let t=e?.healthCheckPath||"/health";return{container:t,traefik:e?.traefik?.healthCheck||t}}function nu(e){let t=[];for(let n of e){if(!I(n.config?.appType))continue;let r=fe(n.path,"src");if(!ln(r))continue;let s=Fs(r);if(s.length===0)continue;let o=s.map(u=>dn(u,"utf-8")),{container:i,traefik:a}=tu(n.config),c=i===a?[{path:i,usedBy:"container and Traefik healthchecks"}]:[{path:i,usedBy:"container healthcheck"},{path:a,usedBy:"Traefik healthcheck"}];for(let{path:u,usedBy:d}of c){let l=["'",'"',"`"].map(p=>`${p}${u}${p}`);o.some(p=>l.some(h=>p.includes(h)))||t.push({name:n.name,healthPath:u,usedBy:d})}}return t}function Ls(e=y()??process.cwd()){let t=[];try{t=x(e)}catch{return{name:"Health Routes",didPass:!0,isSkipped:!0,message:"Could not read services - skipped health route check"}}let n=t.filter(o=>I(o.config?.appType));if(n.length===0)return{name:"Health Routes",didPass:!0,isSkipped:!0,message:"No backend services to check"};let r=nu(n);return r.length===0?{name:"Health Routes",didPass:!0,message:`All ${T(n.length,"backend")} define their health route`}:{name:"Health Routes",didPass:!1,message:`Backends without a health route (the container never turns healthy, so Traefik returns 404):
86
+ ${c}${l}${u}${d}`,fix:b}}var Yc=/^(traefik|postgres|nats|infisical|verdaccio|proxy)([.-]|$)/i;function Ds(e){return Yc.test(e)}function Xc(e){return[...e].sort((t,n)=>{let r=Ds(t.name)?0:1,s=Ds(n.name)?0:1;return r!==s?r-s:t.name.localeCompare(n.name)})}function Qc(e,t=Fe,n=de()){try{let r=Ie(t,"docker",["ps","-a","--format","{{.Names}}"],"docker ps -a --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:je}).split(`
87
+ `).map(l=>l.trim()).filter(Boolean),s=`-autogenerated-${e}-1`,o=r.find(l=>l===e)??r.find(l=>l.startsWith(`${n}-`)&&l.endsWith(s))??r.find(l=>l.endsWith(s))??r.find(l=>l.includes(e));if(!o)return null;let i=Ie(t,"docker",["logs","--tail","120",o],`docker logs --tail 120 ${Ns(o)} 2>&1`,{stdio:"pipe",encoding:"utf-8",timeout:je});if(/getaddrinfo ENOTFOUND/i.test(i)&&/kafka:9092/i.test(i))return"runtime crash: Kafka broker unreachable (getaddrinfo ENOTFOUND kafka:9092)";if(/ECONNREFUSED/i.test(i)&&/kafka/i.test(i))return"runtime crash: Kafka connection refused";let a=i.match(/ConnectionRefused downloading package manifest (@[A-Za-z0-9._/-]+)/i);if(a?.[1])return`runtime/build log: private registry ConnectionRefused for ${a[1]}`;if(/ZodError/i.test(i)){let l=[...i.matchAll(/"path"\s*:\s*\[\s*"([^"]+)"\s*\]/g)].map(d=>d[1]),u=[...new Set(l)].slice(0,6);return u.length>0?`runtime crash: ZodError missing required config/env: ${u.join(", ")}`:"runtime crash: ZodError during config/env validation"}let c=i.match(/error:\s+Failed to [^:\n]+[^\n]{0,120}/i)?.[0]??i.match(/Failed to (?:start|initialize) [^\n]{0,120}/i)?.[0]??i.match(/^\s*error:\s+[^\n]{0,160}/im)?.[0];if(c)return`runtime crash: ${c.replace(/\s+/g," ").trim().slice(0,180)}`}catch{return null}return null}function Zc(e,t=Fe){return e.error?hn(e.error):e.runtimeStatus==="error"?Qc(e.name,t)??"runtime error (container crashed or unhealthy \u2014 check Tilt/docker logs)":e.updateStatus||e.runtimeStatus||"unknown error"}var el=/\.(ts|tsx|mts|js|mjs|cjs)$/,tl=new Set(["node_modules","dist",C,"tests","__tests__"]);function Fs(e){let t=[];for(let n of Hc(e,{withFileTypes:!0}))n.isDirectory()?tl.has(n.name)||t.push(...Fs(fe(e,n.name))):el.test(n.name)&&!/\.(test|spec)\./.test(n.name)&&t.push(fe(e,n.name));return t}function nl(e){let t=e?.healthCheckPath||"/health";return{container:t,traefik:e?.traefik?.healthCheck||t}}function rl(e){let t=[];for(let n of e){if(!I(n.config?.appType))continue;let r=fe(n.path,"src");if(!dn(r))continue;let s=Fs(r);if(s.length===0)continue;let o=s.map(l=>un(l,"utf-8")),{container:i,traefik:a}=nl(n.config),c=i===a?[{path:i,usedBy:"container and Traefik healthchecks"}]:[{path:i,usedBy:"container healthcheck"},{path:a,usedBy:"Traefik healthcheck"}];for(let{path:l,usedBy:u}of c){let d=["'",'"',"`"].map(p=>`${p}${l}${p}`);o.some(p=>d.some(h=>p.includes(h)))||t.push({name:n.name,healthPath:l,usedBy:u})}}return t}function Ls(e=y()??process.cwd()){let t=[];try{t=x(e)}catch{return{name:"Health Routes",didPass:!0,isSkipped:!0,message:"Could not read services - skipped health route check"}}let n=t.filter(o=>I(o.config?.appType));if(n.length===0)return{name:"Health Routes",didPass:!0,isSkipped:!0,message:"No backend services to check"};let r=rl(n);return r.length===0?{name:"Health Routes",didPass:!0,message:`All ${T(n.length,"backend")} define their health route`}:{name:"Health Routes",didPass:!1,message:`Backends without a health route (the container never turns healthy, so Traefik returns 404):
88
88
  ${r.map(o=>`${o.name}: no "${o.healthPath}" route in src/ (probed by the ${o.usedBy})`).join(`
89
- `)}`,fix:`Add the route, e.g. for Hono: app.get("${r[0]?.healthPath}", (c) => c.json({ status: "ok" })). To use a different path, set "healthCheckPath" (container healthcheck) or "traefik.healthCheck" (Traefik) in its service.json.`}}import{existsSync as au,readFileSync as cu}from"node:fs";import{join as uu}from"node:path";import{randomBytes as Ms}from"node:crypto";import{existsSync as wn,readFileSync as Us,writeFileSync as Bs}from"node:fs";import{join as En}from"node:path";var me=[{name:"VERDACCIO_URL_DOCKER",description:"Docker-internal URL of the private npm registry (Verdaccio, a paid feature)",required:!1,default:"http://verdaccio:4873",example:"http://verdaccio:4873"},{name:"VERDACCIO_URL",description:"Local URL of the private npm registry (Verdaccio, a paid feature)",required:!1,default:"http://localhost:4873"},{name:"TILT_ENV",description:"Tilt environment name",required:!0,default:"dev",example:"dev",complete:!0},{name:"DATABASE_URL",description:"PostgreSQL connection string (uses the generated DB_PASSWORD below)",required:!1},{name:"DB_PASSWORD",description:"PostgreSQL superuser password (docker-compose POSTGRES_PASSWORD)",required:!0,example:"postgres",complete:!0},{name:"JWT_SECRET",description:"Secret that signs local-jwt tokens (generated once per project; never shared between projects)",required:!1,complete:!0}],Hs=()=>Ms(16).toString("hex"),ru=()=>Ms(32).toString("hex");function xn(e,t){return e==="DB_PASSWORD"?t:e==="JWT_SECRET"?ru():e==="DATABASE_URL"?`postgresql://postgres:${t}@postgres:5432/app_dev`:me.find(n=>n.name===e)?.default??""}function su(e){let t=e.trim(),n=t[0];if(n==='"'||n==="'"){let s=!1;for(let o=1;o<t.length;o+=1){let i=t[o];if(s){s=!1;continue}if(i==="\\"){s=!0;continue}if(i===n){let a=t.slice(1,o);if(n==='"'){let c={n:`
90
- `,r:"\r",t:" ",'"':'"',"\\":"\\",$:"$"};return a.replace(/\\([nrt"\\$])/g,(u,d)=>c[d]??d)}return a.replace(/\\'/g,"'")}}return t}let r=e.search(/\s#/);return(r===-1?e:e.slice(0,r)).trim()}function he(e){let t=new Map,n=e.startsWith("\uFEFF")?e.slice(1):e;for(let r of n.split(/\r?\n/)){let s=r.trim();if(!s||s.startsWith("#"))continue;let o=s.startsWith("export ")?s.slice(7).trim():s,i=o.indexOf("=");if(i<=0)continue;let a=o.slice(0,i).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(a)&&t.set(a,su(o.slice(i+1)))}return t}function Ks(e){let t=[`# ${e.description}`];return e.required&&t.push("# Required (the value below is a working default)"),e.example&&t.push(`# Example: ${e.example}`),t}function Gs(){let e=Hs(),t=["# \u{1F527} TDK Environment Configuration","# Generated by `tdk project`. The defaults work as-is; edit only to change them.","# Keep this file out of git: it holds a generated database password and JWT secret.","#","# After editing, run: tdk config regenerate && tdk up",""];for(let n of me)t.push(...Ks(n)),t.push(`${n.name}=${xn(n.name,e)}`),t.push("");return t.join(`
91
- `)}function ou(e){let t=e.match(/^[a-z][a-z0-9+.-]*:\/\/[^:/@\s]+:([^@\s]*)@/i);if(!(!t||t[1].includes("$")))return t[1]}function Vs(e){let t=En(e,".env"),n={missing:[],invalid:[],warnings:[]};if(!wn(t))return{missing:me.filter(i=>i.required).map(i=>i.name),invalid:[],warnings:[".env file not found - will be auto-generated"]};let r=he(Us(t,"utf-8"));for(let i of me)i.required&&!r.has(i.name)&&n.missing.push(i.name),r.has(i.name)&&!(r.get(i.name)??"").trim()&&n.invalid.push(`${i.name} is set but empty`);let s=r.get("DATABASE_URL"),o=r.get("DB_PASSWORD");if(s&&o){let i=ou(s);i!==void 0&&i!==o&&n.warnings.push("DATABASE_URL carries a different password than DB_PASSWORD; the database container uses DB_PASSWORD")}return n}function iu(e,t,n){if(!he(e).has(t))return e;let s=e.indexOf("=");if(s<0)return e;let o=e.slice(s+1),i=o.search(/\s#/),a=i<0?"":o.slice(i);return e.slice(0,s+1)+n+a}function hh(e){let t=En(e,".env");if(!wn(t))return Bs(t,Gs(),{mode:384}),me.map(l=>l.name);let n=Us(t,"utf-8"),r=he(n),s=me.filter(l=>l.complete?r.has(l.name)?!(r.get(l.name)??"").trim():!0:!1);if(s.length===0)return[];let o=s.filter(l=>!r.has(l.name)),i=s.filter(l=>r.has(l.name)),a=r.get("DB_PASSWORD"),c=a?.trim()?a:Hs(),u=n.split(/(\r\n|\n|\r)/);for(let l of i){let p=-1;for(let h=0;h<u.length;h+=2)he(u[h]).has(l.name)&&(p=h);if(p<0)throw new Error(`Could not locate empty .env assignment for ${l.name}`);u[p]=iu(u[p],l.name,xn(l.name,c))}let d=u.join("");if(o.length>0){let l=["","# Added by TDK: keys this version expects. Existing values above were not changed.",""];for(let h of o)l.push(...Ks(h)),l.push(`${h.name}=${xn(h.name,c)}`),l.push("");let p=d.endsWith(`
92
- `)||d.endsWith("\r")?"":`
93
- `;d+=p+l.join(`
94
- `)}return $e(t,d),s.map(l=>l.name)}function gh(e){let t=En(e,".env");return wn(t)?!1:(Bs(t,Gs(),{mode:384}),!0)}var lu="[REDACTED]",Le=class extends Error{path;constructor(t,n){super(`Could not read ${t}: ${n}`),this.path=t,this.name="EnvUnreadableError"}},du=8;function vn(e){let t=uu(e,".env");if(!au(t))return[];let n;try{n=cu(t,"utf-8")}catch(s){throw new Le(t,s instanceof Error?s.message:String(s))}let r=[...he(n).values()].filter(s=>s.length>=du);return[...new Set(r)].sort((s,o)=>o.length-s.length)}function Me(e,t){let n=e;for(let r of t)n=n.split(r).join(lu);return n}function at(e,t){return t.length===0?e:typeof e=="string"?Me(e,t):Array.isArray(e)?e.map(n=>at(n,t)):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,at(r,t)])):e}var mu=fu(pu),hu=1e4,gu=5,Ws=10*6e4,ku=3,yu=200,Su=async e=>{let{stdout:t,stderr:n}=await mu("docker",e,{encoding:"utf-8",timeout:hu,windowsHide:!0});return`${t}${n}`};function bu(e,t){let n=pn(t).toLowerCase(),r=e.replace(/-/g,"_").toLowerCase();return r===n||r.startsWith(`${n}_`)}function Tu(e,t=Date.now()){if(e.status==="restarting")return!0;if(e.restartCount<gu)return!1;if(e.status==="running"){let r=Date.parse(e.startedAt);return Number.isNaN(r)||t-r<Ws}let n=Date.parse(e.finishedAt??"");return e.exitCode!==0&&!Number.isNaN(n)&&t-n<Ws}function xu(e,t){let n=/database "([^"]+)" does not exist/i.exec(e);return n?`database "${n[1]}" does not exist: re-run the project's database provisioning (tdk up) or create it`:/Cannot find module|MODULE_NOT_FOUND|module not found/i.test(e)?"a module is missing from the image: rebuild it (tdk up --force) after checking the resource's dependencies":/EADDRINUSE|address already in use/i.test(e)?"the port inside the container is already in use: check for two processes started by the same command":/ECONNREFUSED|connection refused|could not connect/i.test(e)?"a dependency is not reachable: check that the service it connects to is running and healthy":/\b(?:environment variable|env var)\b.*\b(?:missing|not set|required|undefined)\b/i.test(e)||/\b[A-Z][A-Z0-9_]{2,}\b (?:is )?(?:not set|required|missing)\b/.test(e)?"a required environment variable is missing: check the project's .env":t.exitCode===137?"killed (exit 137), usually out of memory: raise the container's memory limit":null}function wu(e){let t=[];for(let n of e.split(/\r?\n/)){let[r,s,o,i,a,c]=n.split(" ");!r||s===void 0||t.push({name:r.replace(/^\//,""),restartCount:Number(s)||0,status:o??"",startedAt:i??"",exitCode:Number(a)||0,finishedAt:c??""})}return t}async function Js(e,t=[],n=Su,r=Date.now()){let s="Crash-looping containers",o;try{o=(await n(["ps","-a","--format",'{{.ID}} {{.Label "com.docker.compose.project"}}'])).split(/\r?\n/).map(l=>l.split(" ")).filter(([l,p])=>l&&p&&bu(p,e)).map(([l])=>l)}catch{return{name:s,didPass:!0,isSkipped:!0,message:"Docker not available - skipped crash-loop check"}}if(o.length===0)return{name:s,didPass:!0,isSkipped:!0,message:"No project containers to check"};let i;try{i=wu(await n(["inspect","--format","{{.Name}} {{.RestartCount}} {{.State.Status}} {{.State.StartedAt}} {{.State.ExitCode}} {{.State.FinishedAt}}",...o]))}catch{return{name:s,didPass:!0,isSkipped:!0,message:"Containers changed while checking - skipped crash-loop check"}}let a=i.filter(d=>Tu(d,r));if(a.length===0)return{name:s,didPass:!0,message:"No project container is crash-looping"};let c=[],u=new Set;for(let d of a){let l="";try{l=await n(["logs","--tail",String(ku),d.name])}catch{}let p=Me(l,t).split(/\r?\n/).map(f=>f.trim().slice(0,yu)).filter(Boolean),h=xu(l,d);h&&u.add(h),c.push([`${d.name}: ${d.status}, restarted ${d.restartCount} times`,...p.map(f=>` | ${f}`)].join(`
89
+ `)}`,fix:`Add the route, e.g. for Hono: app.get("${r[0]?.healthPath}", (c) => c.json({ status: "ok" })). To use a different path, set "healthCheckPath" (container healthcheck) or "traefik.healthCheck" (Traefik) in its service.json.`}}import{existsSync as cl,readFileSync as ll}from"node:fs";import{join as dl}from"node:path";import{randomBytes as Ms}from"node:crypto";import{existsSync as wn,readFileSync as Us,writeFileSync as Bs}from"node:fs";import{join as En}from"node:path";var me=[{name:"VERDACCIO_URL_DOCKER",description:"Docker-internal URL of the private npm registry (Verdaccio, a paid feature)",required:!1,default:"http://verdaccio:4873",example:"http://verdaccio:4873"},{name:"VERDACCIO_URL",description:"Local URL of the private npm registry (Verdaccio, a paid feature)",required:!1,default:"http://localhost:4873"},{name:"TILT_ENV",description:"Tilt environment name",required:!0,default:"dev",example:"dev",complete:!0},{name:"DATABASE_URL",description:"PostgreSQL connection string (uses the generated DB_PASSWORD below)",required:!1},{name:"DB_PASSWORD",description:"PostgreSQL superuser password (docker-compose POSTGRES_PASSWORD)",required:!0,example:"postgres",complete:!0},{name:"JWT_SECRET",description:"Secret that signs local-jwt tokens (generated once per project; never shared between projects)",required:!1,complete:!0}],Hs=()=>Ms(16).toString("hex"),sl=()=>Ms(32).toString("hex");function xn(e,t){return e==="DB_PASSWORD"?t:e==="JWT_SECRET"?sl():e==="DATABASE_URL"?`postgresql://postgres:${t}@postgres:5432/app_dev`:me.find(n=>n.name===e)?.default??""}function ol(e){let t=e.trim(),n=t[0];if(n==='"'||n==="'"){let s=!1;for(let o=1;o<t.length;o+=1){let i=t[o];if(s){s=!1;continue}if(i==="\\"){s=!0;continue}if(i===n){let a=t.slice(1,o);if(n==='"'){let c={n:`
90
+ `,r:"\r",t:" ",'"':'"',"\\":"\\",$:"$"};return a.replace(/\\([nrt"\\$])/g,(l,u)=>c[u]??u)}return a.replace(/\\'/g,"'")}}return t}let r=e.search(/\s#/);return(r===-1?e:e.slice(0,r)).trim()}function he(e){let t=new Map,n=e.startsWith("\uFEFF")?e.slice(1):e;for(let r of n.split(/\r?\n/)){let s=r.trim();if(!s||s.startsWith("#"))continue;let o=s.startsWith("export ")?s.slice(7).trim():s,i=o.indexOf("=");if(i<=0)continue;let a=o.slice(0,i).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(a)&&t.set(a,ol(o.slice(i+1)))}return t}function Gs(e){let t=[`# ${e.description}`];return e.required&&t.push("# Required (the value below is a working default)"),e.example&&t.push(`# Example: ${e.example}`),t}function Ks(){let e=Hs(),t=["# \u{1F527} TDK Environment Configuration","# Generated by `tdk project`. The defaults work as-is; edit only to change them.","# Keep this file out of git: it holds a generated database password and JWT secret.","#","# After editing, run: tdk config regenerate && tdk up",""];for(let n of me)t.push(...Gs(n)),t.push(`${n.name}=${xn(n.name,e)}`),t.push("");return t.join(`
91
+ `)}function il(e){let t=e.match(/^[a-z][a-z0-9+.-]*:\/\/[^:/@\s]+:([^@\s]*)@/i);if(!(!t||t[1].includes("$")))return t[1]}function Vs(e){let t=En(e,".env"),n={missing:[],invalid:[],warnings:[]};if(!wn(t))return{missing:me.filter(i=>i.required).map(i=>i.name),invalid:[],warnings:[".env file not found - will be auto-generated"]};let r=he(Us(t,"utf-8"));for(let i of me)i.required&&!r.has(i.name)&&n.missing.push(i.name),r.has(i.name)&&!(r.get(i.name)??"").trim()&&n.invalid.push(`${i.name} is set but empty`);let s=r.get("DATABASE_URL"),o=r.get("DB_PASSWORD");if(s&&o){let i=il(s);i!==void 0&&i!==o&&n.warnings.push("DATABASE_URL carries a different password than DB_PASSWORD; the database container uses DB_PASSWORD")}return n}function al(e,t,n){if(!he(e).has(t))return e;let s=e.indexOf("=");if(s<0)return e;let o=e.slice(s+1),i=o.search(/\s#/),a=i<0?"":o.slice(i);return e.slice(0,s+1)+n+a}function kh(e){let t=En(e,".env");if(!wn(t))return Bs(t,Ks(),{mode:384}),me.map(d=>d.name);let n=Us(t,"utf-8"),r=he(n),s=me.filter(d=>d.complete?r.has(d.name)?!(r.get(d.name)??"").trim():!0:!1);if(s.length===0)return[];let o=s.filter(d=>!r.has(d.name)),i=s.filter(d=>r.has(d.name)),a=r.get("DB_PASSWORD"),c=a?.trim()?a:Hs(),l=n.split(/(\r\n|\n|\r)/);for(let d of i){let p=-1;for(let h=0;h<l.length;h+=2)he(l[h]).has(d.name)&&(p=h);if(p<0)throw new Error(`Could not locate empty .env assignment for ${d.name}`);l[p]=al(l[p],d.name,xn(d.name,c))}let u=l.join("");if(o.length>0){let d=["","# Added by TDK: keys this version expects. Existing values above were not changed.",""];for(let h of o)d.push(...Gs(h)),d.push(`${h.name}=${xn(h.name,c)}`),d.push("");let p=u.endsWith(`
92
+ `)||u.endsWith("\r")?"":`
93
+ `;u+=p+d.join(`
94
+ `)}return $e(t,u),s.map(d=>d.name)}function yh(e){let t=En(e,".env");return wn(t)?!1:(Bs(t,Ks(),{mode:384}),!0)}var ul="[REDACTED]",Le=class extends Error{path;constructor(t,n){super(`Could not read ${t}: ${n}`),this.path=t,this.name="EnvUnreadableError"}},pl=8;function vn(e){let t=dl(e,".env");if(!cl(t))return[];let n;try{n=ll(t,"utf-8")}catch(s){throw new Le(t,s instanceof Error?s.message:String(s))}let r=[...he(n).values()].filter(s=>s.length>=pl);return[...new Set(r)].sort((s,o)=>o.length-s.length)}function Me(e,t){let n=e;for(let r of t)n=n.split(r).join(ul);return n}function at(e,t){return t.length===0?e:typeof e=="string"?Me(e,t):Array.isArray(e)?e.map(n=>at(n,t)):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,at(r,t)])):e}var hl=ml(fl),gl=1e4,kl=5,Ws=10*6e4,yl=3,Sl=200,bl=async e=>{let{stdout:t,stderr:n}=await hl("docker",e,{encoding:"utf-8",timeout:gl,windowsHide:!0});return`${t}${n}`};function Tl(e,t){let n=pn(t).toLowerCase(),r=e.replace(/-/g,"_").toLowerCase();return r===n||r.startsWith(`${n}_`)}function xl(e,t=Date.now()){if(e.status==="restarting")return!0;if(e.restartCount<kl)return!1;if(e.status==="running"){let r=Date.parse(e.startedAt);return Number.isNaN(r)||t-r<Ws}let n=Date.parse(e.finishedAt??"");return e.exitCode!==0&&!Number.isNaN(n)&&t-n<Ws}function wl(e,t){let n=/database "([^"]+)" does not exist/i.exec(e);return n?`database "${n[1]}" does not exist: re-run the project's database provisioning (tdk up) or create it`:/Cannot find module|MODULE_NOT_FOUND|module not found/i.test(e)?"a module is missing from the image: rebuild it (tdk up --force) after checking the resource's dependencies":/EADDRINUSE|address already in use/i.test(e)?"the port inside the container is already in use: check for two processes started by the same command":/ECONNREFUSED|connection refused|could not connect/i.test(e)?"a dependency is not reachable: check that the service it connects to is running and healthy":/\b(?:environment variable|env var)\b.*\b(?:missing|not set|required|undefined)\b/i.test(e)||/\b[A-Z][A-Z0-9_]{2,}\b (?:is )?(?:not set|required|missing)\b/.test(e)?"a required environment variable is missing: check the project's .env":t.exitCode===137?"killed (exit 137), usually out of memory: raise the container's memory limit":null}function El(e){let t=[];for(let n of e.split(/\r?\n/)){let[r,s,o,i,a,c]=n.split(" ");!r||s===void 0||t.push({name:r.replace(/^\//,""),restartCount:Number(s)||0,status:o??"",startedAt:i??"",exitCode:Number(a)||0,finishedAt:c??""})}return t}async function Js(e,t=[],n=bl,r=Date.now()){let s="Crash-looping containers",o;try{o=(await n(["ps","-a","--format",'{{.ID}} {{.Label "com.docker.compose.project"}}'])).split(/\r?\n/).map(d=>d.split(" ")).filter(([d,p])=>d&&p&&Tl(p,e)).map(([d])=>d)}catch{return{name:s,didPass:!0,isSkipped:!0,message:"Docker not available - skipped crash-loop check"}}if(o.length===0)return{name:s,didPass:!0,isSkipped:!0,message:"No project containers to check"};let i;try{i=El(await n(["inspect","--format","{{.Name}} {{.RestartCount}} {{.State.Status}} {{.State.StartedAt}} {{.State.ExitCode}} {{.State.FinishedAt}}",...o]))}catch{return{name:s,didPass:!0,isSkipped:!0,message:"Containers changed while checking - skipped crash-loop check"}}let a=i.filter(u=>xl(u,r));if(a.length===0)return{name:s,didPass:!0,message:"No project container is crash-looping"};let c=[],l=new Set;for(let u of a){let d="";try{d=await n(["logs","--tail",String(yl),u.name])}catch{}let p=Me(d,t).split(/\r?\n/).map(f=>f.trim().slice(0,Sl)).filter(Boolean),h=wl(d,u);h&&l.add(h),c.push([`${u.name}: ${u.status}, restarted ${u.restartCount} times`,...p.map(f=>` | ${f}`)].join(`
95
95
  `))}return{name:s,didPass:!1,message:`${a.length} container${a.length===1?" is":"s are"} crash-looping:
96
96
  ${c.join(`
97
- `)}`,fix:[...u,"Read the full log: docker logs <container>"].join("; ")}}import{execFile as ju}from"node:child_process";import{realpathSync as Zs,statfsSync as Iu}from"node:fs";import{homedir as Fu}from"node:os";import{join as Lu}from"node:path";import{promisify as Mu}from"node:util";import{statfsSync as Eu}from"node:fs";import{homedir as vu}from"node:os";var ct="Disk Space",Pu=1024**3,$u=2,Pn=10,qs=["Free disk space, then retry: tdk doctor"," docker system prune -af # unused images and build cache (needs Docker running)"," npm cache clean --force"," bun pm cache rm"," brew cleanup -s"].join(`
98
- `);function zs(e=Eu,t=vu()){let n;try{let s=e(t);n=Number(s.bavail)*Number(s.bsize)/Pu}catch{return{name:ct,didPass:!0,isSkipped:!0,message:"Could not read free disk space"}}let r=`${n.toFixed(1)} GB free`;return n<$u?{name:ct,didPass:!1,message:`${r}: Docker cannot build or start containers`,fix:qs}:n<Pn?{name:ct,didPass:!1,isWarning:!0,message:`${r}: image builds may fail`,fix:qs}:{name:ct,didPass:!0,message:r}}var _u="Quit Docker Desktop completely (whale icon > Quit Docker Desktop), reopen it, and wait until it shows Running. If it keeps getting stuck, check free disk space. Then retry: tdk doctor";function Ys(e,t=process.platform){return t!=="darwin"||!e?null:{name:"Container Runtime",didPass:!1,message:"Docker Desktop is open, but its engine is not responding",fix:_u}}import{execFileSync as Ru}from"node:child_process";var $n=(e,t)=>Ru(e,t,{encoding:"utf-8",stdio:"pipe",windowsHide:!0}),Xs=["traefik-public","traefik-private","backend","database","infisical-network","verdaccio-network","proxy"];function _n(e){let t=e.replace(/-/g,"_");return Xs.map(n=>`${t}_${n}`)}function Qs(e){let t=new Set;for(let n of e)for(let r of["traefik-public","traefik-private"])n.endsWith(`_${r}`)&&t.add(n.slice(0,-(r.length+1)));return t}function Rn(e,t){for(let n of Xs)if(e.endsWith(`_${n}`)){let r=e.slice(0,-(n.length+1));if(t.has(r))return r}return null}function Dh(e,t=$n){let n=new Set(t("docker",["network","ls","--format","{{.Name}}"]).split(/\r?\n/).map(s=>s.trim()).filter(Boolean)),r={removed:[],kept:[]};for(let s of _n(e))if(n.has(s))try{t("docker",["network","rm",s]),r.removed.push(s)}catch(o){let i=String(o.stderr??o).trim();r.kept.push({name:s,reason:i.split(/\r?\n/)[0]??""})}return r}function ut(e,t=process.platform,n=$n){if(t==="win32")return[];let r;try{r=n("ps",["-axo","pid=,command="])}catch{return[]}let s=[];for(let o of r.split(/\r?\n/)){let i=/^\s*(\d+)\s+(.*)$/.exec(o);if(!i)continue;let a=i[2]??"",c=(a.split(/\s+/)[0]??"").split("/").at(-1),u=` -f ${e}`,d=a.indexOf(u),l=a[d+u.length];c==="tilt"&&/^\S+\s+up\s/.test(a)&&d>0&&(l===void 0||l===" ")&&s.push(Number(i[1]))}return s}function Oh(e,t=process.platform,n=$n){let r=ut(e,t,n);for(let s of r)try{n("kill",["-TERM",String(s)])}catch{}return r}async function Nh(e,t=8e3,n=ut){let r=Date.now()+t;for(;n(e).length>0;){if(Date.now()>=r)return!1;await new Promise(s=>setTimeout(s,250))}return!0}import{execFile as Au}from"node:child_process";function An(e){return new Promise(t=>{Au(O("tilt")??"tilt",["get","uiresources","-o","json","--port",String(e)],{timeout:15e3,maxBuffer:16*1024*1024},(n,r)=>t(n?null:r))})}function Du(e){let n=(JSON.parse(e).items??[]).filter(r=>r.status?.disableStatus?.state!=="Disabled").map(r=>r.status?.updateStatus==="not_applicable"?{...r,status:{...r.status,updateStatus:"ok"}}:r);return JSON.stringify({items:n})}function Ou(e){return(JSON.parse(e).items??[]).filter(t=>t.status?.disableStatus?.state!=="Disabled").flatMap(t=>t.metadata?.name?[t.metadata.name]:[])}function Nu(e,t){let n=JSON.parse(e).items??[],r=new Map(n.map(s=>[s.metadata?.name,s]));return{missing:t.filter(s=>!r.has(s)),disabled:t.filter(s=>r.get(s)?.status?.disableStatus?.state==="Disabled")}}function Cu(e,t,n){let r=mn(Du(e),t),s={ready:r.failures.length===0&&r.pendingCount===0&&r.okCount>0,failures:r.failures.map(o=>({name:o.name,message:o.error||`${o.updateStatus}/${o.runtimeStatus}`})),pending:r.pendingCount,timedOut:!1,enabled:Ou(e)};if(n&&n.length>0){let{missing:o,disabled:i}=Nu(e,n);if(o.length>0&&(s={...s,ready:!1,pending:s.pending+o.length}),i.length>0)return{settled:!0,result:{...s,ready:!1,failures:[...s.failures,...i.map(a=>({name:a,message:"disabled in Tilt"}))]}}}return{result:s,settled:s.ready||s.failures.length>0&&s.pending===0}}async function Lh(e,t={}){let n=t.timeoutMs??Number(process.env.TDK_UP_READY_TIMEOUT_MS??9e5),r=t.intervalMs??2e3,s=t.fetchJson??An,o=t.deferred??fn(),i=Date.now()+n,a={ready:!1,failures:[],pending:0,timedOut:!1,enabled:[]};for(;;){let c=await s(e);if(c)try{let u=Cu(c,o,t.expected);if(a=u.result,u.settled||a.failures.length>0&&t.isStalled?.(c))return a}catch{}if(Date.now()>=i)return{...a,ready:!1,timedOut:!0};await new Promise(u=>setTimeout(u,r))}}var lt=Mu(ju),Uu=15e3,Bu=/^tdk_doctor_probe_(\d+)$/,Hu=async e=>{let{stdout:t}=await lt("docker",e,{encoding:"utf-8",timeout:Uu,windowsHide:!0});return t};function Dn(e){return String(e.stderr??e).trim().split(/\r?\n/)[0]??""}var Ku=120;function Gu(e){let t=/^\s*(?:(?:(\d+)-)?(\d+):)?(\d+):(\d+)\s*$/.exec(e);if(!t)return null;let[,n="0",r="0",s="0",o="0"]=t;return((Number(n)*24+Number(r))*60+Number(s))*60+Number(o)}async function Vu(e,t=An,n=2,r=s=>new Promise(o=>setTimeout(o,s))){for(let s=0;s<n;s++){s>0&&await r(1e3);for(let o of e)if(await t(o)!==null)return!0}return!1}async function Wu(e){if(process.platform==="win32")return"unknown";try{let{stdout:t}=await lt("ps",["-p",String(e),"-o","etime="],{encoding:"utf-8",timeout:5e3}),n=Gu(t);if(n===null||n<Ku)return"unknown";let{stdout:r}=await lt("lsof",["-nP","-a","-p",String(e),"-iTCP","-sTCP:LISTEN","-Fn"],{encoding:"utf-8",timeout:5e3}),s=[...r.matchAll(/^n.*:(\d+)$/gm)].map(o=>Number(o[1]));return await Vu(s)?"healthy":"stale"}catch{return"unknown"}}function Ju(e=Hu){return{async listNetworks(){let t=(await e(["network","ls","--format","{{.Name}}"])).split(/\r?\n/).map(r=>r.trim()).filter(Boolean);return(await Promise.all(t.map(async r=>{try{let s=await e(["network","inspect","--format","{{len .Containers}}",r]);return{name:r,containers:Number(s.trim())||0}}catch(s){if(/no such network|not found/i.test(String(s)))return null;throw s}}))).filter(r=>r!==null)},async removeNetwork(t){try{await e(["network","rm",t])}catch(n){throw new Error(Dn(n))}},freeDiskGib(){try{let t=Iu(Fu());return Number(t.bavail)*Number(t.bsize)/1024**3}catch{return null}},async reclaimable(){let t=null;try{let r=await e(["system","df","--format","{{.Type}} {{.Reclaimable}}"]);for(let s of r.split(/\r?\n/)){let[o,i]=s.split(" ");o==="Build Cache"&&i&&(t=i.replace(/\s*\(.*\)/,"").trim())}}catch{}let n=0;try{n=(await e(["images","-q","-f","dangling=true"])).split(/\r?\n/).filter(Boolean).length}catch{}return{buildCache:t,danglingImages:n}},async prune(t){try{await e(t==="builder"?["builder","prune","-f"]:["image","prune","-f"])}catch(n){throw new Error(Dn(n))}},async tiltStatus(t){return Wu(t)},stopProcess(t){process.kill(t,"SIGTERM")},isProcessAlive(t){try{return process.kill(t,0),!0}catch(n){return n.code==="EPERM"}}}}var eo=Ju();async function to(e,t=eo,n={}){let r=[],s=[];for(let d of n.tiltPids??[])await t.tiltStatus(d)==="stale"?r.push({id:`stop-tilt:${d}`,check:"Tilt processes",scope:"project",command:`kill -TERM ${d}`,status:"planned",reason:"this project's Tilt is running but its UI does not answer"}):s.push(d);let o=s.length>0?`Tilt is running for this project (pid ${s.join(", ")}); run tdk down first`:void 0,i=await t.listNetworks(),a=t.freeDiskGib();if(a!==null&&a<Pn){let{buildCache:d,danglingImages:l}=await t.reclaimable(),p=`${a.toFixed(1)} GB free`;d&&!/^0(\.0+)?\s*B$/i.test(d)&&r.push({id:"prune:builder",check:"Disk Space",scope:"host",command:"docker builder prune -f",status:"planned",reason:`${p}; ${d} of build cache reclaimable`}),l>0&&r.push({id:"prune:images",check:"Disk Space",scope:"host",command:"docker image prune -f",status:"planned",reason:`${p}; ${l} untagged image${l===1?"":"s"}`})}let c=new Set(e?_n(e):[]),u=Qs(i.map(d=>d.name));for(let d of i){let l=Bu.exec(d.name),p,h,f="unused network";if(l)p="probe",h="Orphaned probe networks";else if(c.has(d.name))p="project",h="Docker networks";else if(n.machine&&Rn(d.name,u))p="machine",h="Docker networks",f=`unused network of project "${Rn(d.name,u)}"`;else continue;let b={id:`remove-network:${d.name}`,check:h,scope:p,command:`docker network rm ${d.name}`,status:"planned",reason:f};d.containers>0?(b.status="skipped",b.reason=`${d.containers} container(s) still attached`):p==="project"&&o?(b.status="skipped",b.reason=o):l&&t.isProcessAlive(Number(l[1]))&&(b.status="skipped",b.reason=`probe of a running process (pid ${l[1]})`),r.push(b)}return r}async function no(e,t,n=eo){let r=[];for(let s of e){if(s.status!=="planned"||t.dryRun){r.push(s);continue}if(!t.confirm){r.push({...s,status:"skipped",reason:"confirmation required; run in a terminal or pass --yes"});continue}let o=!1;try{o=await t.confirm(s)}catch{}if(!o){r.push({...s,status:"skipped",reason:"not confirmed"});continue}try{if(s.id.startsWith("prune:")){await n.prune(s.id==="prune:builder"?"builder":"images"),r.push({...s,status:"applied",reason:"pruned"});continue}if(s.id.startsWith("stop-tilt:")){n.stopProcess(Number(s.id.slice(10))),r.push({...s,status:"applied",reason:"stopped"});continue}await n.removeNetwork(s.id.slice(15)),r.push({...s,status:"applied",reason:"removed"})}catch(i){r.push({...s,status:"failed",reason:Dn(i)})}}return r}function ro(e){return e.some(t=>t.status==="failed")}async function qu(e){try{let{stdout:t}=await lt(e,["--version"],{encoding:"utf-8",timeout:5e3,windowsHide:!0});return t.trim().split(/\r?\n/)[0]||null}catch{return null}}async function zu(e=Zr("tdk"),t=qu){let n=new Set,r=[];for(let s of e){let o=s;try{o=Zs(s)}catch{}n.has(o)||(n.add(o),r.push({path:s,version:await t(s)}))}return r}async function so(e){let t=e??await zu();if(t.length<=1)return{name:"TDK installs",didPass:!0,message:"One tdk install on PATH"};let n=t.map(s=>`${s.path} (${s.version??"version unknown"})`).join(", "),r=new Set(t.map(s=>s.version));return{name:"TDK installs",didPass:!1,isWarning:!0,message:`${t.length} tdk installs on PATH${r.size>1?" with different versions":""}: ${n}`,fix:"Keep one: remove the others, or run tdk upgrade. The first on PATH is the one your shell runs; tools that launch /usr/local/bin/tdk directly may use another"}}function oo(e,t=ut){let n=new Set([e]);try{n.add(Zs(e))}catch{}let r=new Set;for(let s of n)for(let o of t(Lu(s,".tdk",".tdk-out","Tiltfile")))r.add(o);return[...r]}var On=1;function Yu(e,t=[]){return{schemaVersion:On,data:e,errors:t}}function Xu(e){return e instanceof N?{error:{code:"COMMAND_FAILED",message:e.message,...e.suggestions.length>0?{suggestions:e.suggestions}:{}},exitCode:e.exitCode}:{error:{code:"INTERNAL",message:e instanceof Error?e.message:String(e)},exitCode:2}}function Xh(e){let t=Xu(e);console.log(JSON.stringify(Yu(null,[t.error]))),console.error(t.error.message),process.exit(t.exitCode)}async function ao(e,t){let n=[],r=[],s=o=>{o.status==="fulfilled"?n.push(o.value):r.push({code:"INTERNAL",message:o.reason instanceof Error?o.reason.message:String(o.reason)})};for(let o of await Promise.allSettled(e.map(i=>Promise.resolve().then(i))))s(o);for(let o of t)for(let i of await Promise.allSettled([Promise.resolve().then(o)]))s(i);return{checks:n,errors:r}}function io(e){let t=e.find(n=>n.name===B);return t?t.didPass:null}function ee(e,t,n=[],r,s){return{schemaVersion:On,data:{ready:n.length===0&&e.every(o=>o.didPass||o.isSkipped||o.isWarning),inProject:t,checks:e,...s?{host:{...s,containerRuntimeReachable:io(e),canUp:s.canUp&&io(e)!==!1}}:{},...r!==void 0?{ports:{http:{requested:r?.requested.ingressHttp??80,chosen:r?.ingressHttp??null,explicit:r?.explicit.ingressHttp??!!process.env.TDK_HTTP_PORT,reason:r?.reason.ingressHttp??"port planning failed"},https:{requested:r?.requested.ingressHttps??443,chosen:r?.ingressHttps??null,explicit:r?.explicit.ingressHttps??!!process.env.TDK_HTTPS_PORT,reason:r?.reason.ingressHttps??"port planning failed"},postgres:{requested:r?.requested.postgres??5432,chosen:r?.postgres??null,explicit:r?.explicit.postgres??!!process.env.TDK_POSTGRES_PORT,reason:r?.reason.postgres??"port planning failed"}}}:{}},errors:n}}function co(e){return e.errors.length>0?2:e.data.ready?0:1}import{existsSync as Cn,readFileSync as uo}from"node:fs";import{dirname as Qu,join as Nn,normalize as Zu}from"node:path";function el(e){let t=new Set,n=/^load\s*\(([\s\S]*?)\)/gm;for(let r of e.matchAll(n)){let s=r[1]??"",o=/["']([^"']+)["']/g,i=Array.from(s.matchAll(o),a=>a[1]);for(let a of i.slice(1))a.startsWith("_")&&t.add(a)}return Array.from(t).sort()}function lo(e,t,n){return t==="ext://tdk-cli"?Nn(n,".tdk",".tdk-out","tdk-cli-ext","Tiltfile"):t.startsWith(".")||!t.includes("://")&&!t.startsWith("@")?Zu(Nn(Qu(e),t)):null}function tl(e,t,n){let r=[],s=/^load\s*\(([\s\S]*?)\)/gm;for(let o of t.matchAll(s)){let c=(o[1]??"").match(/["']([^"']+)["']/)?.[1];if(!c)continue;let u=lo(e,c,n);u&&(Cn(u)||r.push(`${e}: ${c} -> ${u}`))}return r}function nl(e,t,n){let r=[],s=/^load\s*\(([\s\S]*?)\)/gm;for(let o of t.matchAll(s)){let c=(o[1]??"").match(/["']([^"']+)["']/)?.[1];if(c){let u=lo(e,c,n);u&&r.push(u)}}return r}function rl(e,t){let n=new Set,r=[e];for(;r.length>0;){let s=r.pop();if(!s||n.has(s)||!Cn(s))continue;n.add(s);let o=uo(s,"utf-8");for(let i of nl(s,o,t))n.has(i)||r.push(i)}return Array.from(n).sort()}function po(){let e=y()??process.cwd(),t=Nn(e,".tdk",".tdk-out","Tiltfile");if(!Cn(t))return{name:"Starlark Load Exports",didPass:!0,isSkipped:!0,message:"No generated Tiltfile to check"};let n=[],r=[],s=rl(t,e);for(let i of s){let a=uo(i,"utf-8"),c=el(a);c.length>0&&n.push(`${i}: ${c.join(", ")}`);for(let u of tl(i,a,e))r.push(u)}if(n.length===0&&r.length===0)return{name:"Starlark Load Exports",didPass:!0,message:`${T(s.length,"reachable Starlark file")} ${s.length===1?"has":"have"} valid load exports and paths`};let o=[];return n.length>0&&o.push(`Private exported symbols:
97
+ `)}`,fix:[...l,"Read the full log: docker logs <container>"].join("; ")}}import{execFile as Il}from"node:child_process";import{realpathSync as Zs,statfsSync as Fl}from"node:fs";import{homedir as Ll}from"node:os";import{join as Ml}from"node:path";import{promisify as Ul}from"node:util";import{statfsSync as vl}from"node:fs";import{homedir as Pl}from"node:os";var ct="Disk Space",$l=1024**3,_l=2,Pn=10,qs=["Free disk space, then retry: tdk doctor"," docker system prune -af # unused images and build cache (needs Docker running)"," npm cache clean --force"," bun pm cache rm"," brew cleanup -s"].join(`
98
+ `);function zs(e=vl,t=Pl()){let n;try{let s=e(t);n=Number(s.bavail)*Number(s.bsize)/$l}catch{return{name:ct,didPass:!0,isSkipped:!0,message:"Could not read free disk space"}}let r=`${n.toFixed(1)} GB free`;return n<_l?{name:ct,didPass:!1,message:`${r}: Docker cannot build or start containers`,fix:qs}:n<Pn?{name:ct,didPass:!1,isWarning:!0,message:`${r}: image builds may fail`,fix:qs}:{name:ct,didPass:!0,message:r}}var Rl="Quit Docker Desktop completely (whale icon > Quit Docker Desktop), reopen it, and wait until it shows Running. If it keeps getting stuck, check free disk space. Then retry: tdk doctor";function Ys(e,t=process.platform){return t!=="darwin"||!e?null:{name:"Container Runtime",didPass:!1,message:"Docker Desktop is open, but its engine is not responding",fix:Rl}}import{execFileSync as Al}from"node:child_process";var $n=(e,t)=>Al(e,t,{encoding:"utf-8",stdio:"pipe",windowsHide:!0}),Xs=["traefik-public","traefik-private","backend","database","infisical-network","verdaccio-network","proxy"];function _n(e){let t=e.replace(/-/g,"_");return Xs.map(n=>`${t}_${n}`)}function Qs(e){let t=new Set;for(let n of e)for(let r of["traefik-public","traefik-private"])n.endsWith(`_${r}`)&&t.add(n.slice(0,-(r.length+1)));return t}function Rn(e,t){for(let n of Xs)if(e.endsWith(`_${n}`)){let r=e.slice(0,-(n.length+1));if(t.has(r))return r}return null}function Nh(e,t=$n){let n=new Set(t("docker",["network","ls","--format","{{.Name}}"]).split(/\r?\n/).map(s=>s.trim()).filter(Boolean)),r={removed:[],kept:[]};for(let s of _n(e))if(n.has(s))try{t("docker",["network","rm",s]),r.removed.push(s)}catch(o){let i=String(o.stderr??o).trim();r.kept.push({name:s,reason:i.split(/\r?\n/)[0]??""})}return r}function lt(e,t=process.platform,n=$n){if(t==="win32")return[];let r;try{r=n("ps",["-axo","pid=,command="])}catch{return[]}let s=[];for(let o of r.split(/\r?\n/)){let i=/^\s*(\d+)\s+(.*)$/.exec(o);if(!i)continue;let a=i[2]??"",c=(a.split(/\s+/)[0]??"").split("/").at(-1),l=` -f ${e}`,u=a.indexOf(l),d=a[u+l.length];c==="tilt"&&/^\S+\s+up\s/.test(a)&&u>0&&(d===void 0||d===" ")&&s.push(Number(i[1]))}return s}function Ch(e,t=process.platform,n=$n){let r=lt(e,t,n);for(let s of r)try{n("kill",["-TERM",String(s)])}catch{}return r}async function jh(e,t=8e3,n=lt){let r=Date.now()+t;for(;n(e).length>0;){if(Date.now()>=r)return!1;await new Promise(s=>setTimeout(s,250))}return!0}import{execFile as Dl}from"node:child_process";function An(e){return new Promise(t=>{Dl(O("tilt")??"tilt",["get","uiresources","-o","json","--port",String(e)],{timeout:15e3,maxBuffer:16*1024*1024},(n,r)=>t(n?null:r))})}function Ol(e){let n=(JSON.parse(e).items??[]).filter(r=>r.status?.disableStatus?.state!=="Disabled").map(r=>r.status?.updateStatus==="not_applicable"?{...r,status:{...r.status,updateStatus:"ok"}}:r);return JSON.stringify({items:n})}function Nl(e){return(JSON.parse(e).items??[]).filter(t=>t.status?.disableStatus?.state!=="Disabled").flatMap(t=>t.metadata?.name?[t.metadata.name]:[])}function Cl(e,t){let n=JSON.parse(e).items??[],r=new Map(n.map(s=>[s.metadata?.name,s]));return{missing:t.filter(s=>!r.has(s)),disabled:t.filter(s=>r.get(s)?.status?.disableStatus?.state==="Disabled")}}function jl(e,t,n){let r=mn(Ol(e),t),s={ready:r.failures.length===0&&r.pendingCount===0&&r.okCount>0,failures:r.failures.map(o=>({name:o.name,message:o.error||`${o.updateStatus}/${o.runtimeStatus}`})),pending:r.pendingCount,timedOut:!1,enabled:Nl(e)};if(n&&n.length>0){let{missing:o,disabled:i}=Cl(e,n);if(o.length>0&&(s={...s,ready:!1,pending:s.pending+o.length}),i.length>0)return{settled:!0,result:{...s,ready:!1,failures:[...s.failures,...i.map(a=>({name:a,message:"disabled in Tilt"}))]}}}return{result:s,settled:s.ready||s.failures.length>0&&s.pending===0}}async function Uh(e,t={}){let n=t.timeoutMs??Number(process.env.TDK_UP_READY_TIMEOUT_MS??9e5),r=t.intervalMs??2e3,s=t.fetchJson??An,o=t.deferred??fn(),i=Date.now()+n,a={ready:!1,failures:[],pending:0,timedOut:!1,enabled:[]};for(;;){let c=await s(e);if(c)try{let l=jl(c,o,t.expected);if(a=l.result,l.settled||a.failures.length>0&&t.isStalled?.(c))return a}catch{}if(Date.now()>=i)return{...a,ready:!1,timedOut:!0};await new Promise(l=>setTimeout(l,r))}}var dt=Ul(Il),Bl=15e3,Hl=/^tdk_doctor_probe_(\d+)$/,Gl=async e=>{let{stdout:t}=await dt("docker",e,{encoding:"utf-8",timeout:Bl,windowsHide:!0});return t};function Dn(e){return String(e.stderr??e).trim().split(/\r?\n/)[0]??""}var Kl=120;function Vl(e){let t=/^\s*(?:(?:(\d+)-)?(\d+):)?(\d+):(\d+)\s*$/.exec(e);if(!t)return null;let[,n="0",r="0",s="0",o="0"]=t;return((Number(n)*24+Number(r))*60+Number(s))*60+Number(o)}async function Wl(e,t=An,n=2,r=s=>new Promise(o=>setTimeout(o,s))){for(let s=0;s<n;s++){s>0&&await r(1e3);for(let o of e)if(await t(o)!==null)return!0}return!1}async function Jl(e){if(process.platform==="win32")return"unknown";try{let{stdout:t}=await dt("ps",["-p",String(e),"-o","etime="],{encoding:"utf-8",timeout:5e3}),n=Vl(t);if(n===null||n<Kl)return"unknown";let{stdout:r}=await dt("lsof",["-nP","-a","-p",String(e),"-iTCP","-sTCP:LISTEN","-Fn"],{encoding:"utf-8",timeout:5e3}),s=[...r.matchAll(/^n.*:(\d+)$/gm)].map(o=>Number(o[1]));return await Wl(s)?"healthy":"stale"}catch{return"unknown"}}function ql(e=Gl){return{async listNetworks(){let t=(await e(["network","ls","--format","{{.Name}}"])).split(/\r?\n/).map(r=>r.trim()).filter(Boolean);return(await Promise.all(t.map(async r=>{try{let s=await e(["network","inspect","--format","{{len .Containers}}",r]);return{name:r,containers:Number(s.trim())||0}}catch(s){if(/no such network|not found/i.test(String(s)))return null;throw s}}))).filter(r=>r!==null)},async removeNetwork(t){try{await e(["network","rm",t])}catch(n){throw new Error(Dn(n))}},freeDiskGib(){try{let t=Fl(Ll());return Number(t.bavail)*Number(t.bsize)/1024**3}catch{return null}},async reclaimable(){let t=null;try{let r=await e(["system","df","--format","{{.Type}} {{.Reclaimable}}"]);for(let s of r.split(/\r?\n/)){let[o,i]=s.split(" ");o==="Build Cache"&&i&&(t=i.replace(/\s*\(.*\)/,"").trim())}}catch{}let n=0;try{n=(await e(["images","-q","-f","dangling=true"])).split(/\r?\n/).filter(Boolean).length}catch{}return{buildCache:t,danglingImages:n}},async prune(t){try{await e(t==="builder"?["builder","prune","-f"]:["image","prune","-f"])}catch(n){throw new Error(Dn(n))}},async tiltStatus(t){return Jl(t)},stopProcess(t){process.kill(t,"SIGTERM")},isProcessAlive(t){try{return process.kill(t,0),!0}catch(n){return n.code==="EPERM"}}}}var eo=ql();async function to(e,t=eo,n={}){let r=[],s=[];for(let u of n.tiltPids??[])await t.tiltStatus(u)==="stale"?r.push({id:`stop-tilt:${u}`,check:"Tilt processes",scope:"project",command:`kill -TERM ${u}`,status:"planned",reason:"this project's Tilt is running but its UI does not answer"}):s.push(u);let o=s.length>0?`Tilt is running for this project (pid ${s.join(", ")}); run tdk down first`:void 0,i=await t.listNetworks(),a=t.freeDiskGib();if(a!==null&&a<Pn){let{buildCache:u,danglingImages:d}=await t.reclaimable(),p=`${a.toFixed(1)} GB free`;u&&!/^0(\.0+)?\s*B$/i.test(u)&&r.push({id:"prune:builder",check:"Disk Space",scope:"host",command:"docker builder prune -f",status:"planned",reason:`${p}; ${u} of build cache reclaimable`}),d>0&&r.push({id:"prune:images",check:"Disk Space",scope:"host",command:"docker image prune -f",status:"planned",reason:`${p}; ${d} untagged image${d===1?"":"s"}`})}let c=new Set(e?_n(e):[]),l=Qs(i.map(u=>u.name));for(let u of i){let d=Hl.exec(u.name),p,h,f="unused network";if(d)p="probe",h="Orphaned probe networks";else if(c.has(u.name))p="project",h="Docker networks";else if(n.machine&&Rn(u.name,l))p="machine",h="Docker networks",f=`unused network of project "${Rn(u.name,l)}"`;else continue;let b={id:`remove-network:${u.name}`,check:h,scope:p,command:`docker network rm ${u.name}`,status:"planned",reason:f};u.containers>0?(b.status="skipped",b.reason=`${u.containers} container(s) still attached`):p==="project"&&o?(b.status="skipped",b.reason=o):d&&t.isProcessAlive(Number(d[1]))&&(b.status="skipped",b.reason=`probe of a running process (pid ${d[1]})`),r.push(b)}return r}async function no(e,t,n=eo){let r=[];for(let s of e){if(s.status!=="planned"||t.dryRun){r.push(s);continue}if(!t.confirm){r.push({...s,status:"skipped",reason:"confirmation required; run in a terminal or pass --yes"});continue}let o=!1;try{o=await t.confirm(s)}catch{}if(!o){r.push({...s,status:"skipped",reason:"not confirmed"});continue}try{if(s.id.startsWith("prune:")){await n.prune(s.id==="prune:builder"?"builder":"images"),r.push({...s,status:"applied",reason:"pruned"});continue}if(s.id.startsWith("stop-tilt:")){n.stopProcess(Number(s.id.slice(10))),r.push({...s,status:"applied",reason:"stopped"});continue}await n.removeNetwork(s.id.slice(15)),r.push({...s,status:"applied",reason:"removed"})}catch(i){r.push({...s,status:"failed",reason:Dn(i)})}}return r}function ro(e){return e.some(t=>t.status==="failed")}async function zl(e){try{let{stdout:t}=await dt(e,["--version"],{encoding:"utf-8",timeout:5e3,windowsHide:!0});return t.trim().split(/\r?\n/)[0]||null}catch{return null}}async function Yl(e=Zr("tdk"),t=zl){let n=new Set,r=[];for(let s of e){let o=s;try{o=Zs(s)}catch{}n.has(o)||(n.add(o),r.push({path:s,version:await t(s)}))}return r}async function so(e){let t=e??await Yl();if(t.length<=1)return{name:"TDK installs",didPass:!0,message:"One tdk install on PATH"};let n=t.map(s=>`${s.path} (${s.version??"version unknown"})`).join(", "),r=new Set(t.map(s=>s.version));return{name:"TDK installs",didPass:!1,isWarning:!0,message:`${t.length} tdk installs on PATH${r.size>1?" with different versions":""}: ${n}`,fix:"Keep one: remove the others, or run tdk upgrade. The first on PATH is the one your shell runs; tools that launch /usr/local/bin/tdk directly may use another"}}function oo(e,t=lt){let n=new Set([e]);try{n.add(Zs(e))}catch{}let r=new Set;for(let s of n)for(let o of t(Ml(s,".tdk",".tdk-out","Tiltfile")))r.add(o);return[...r]}var On=1;function Xl(e,t=[]){return{schemaVersion:On,data:e,errors:t}}function Ql(e){return e instanceof N?{error:{code:"COMMAND_FAILED",message:e.message,...e.suggestions.length>0?{suggestions:e.suggestions}:{}},exitCode:e.exitCode}:{error:{code:"INTERNAL",message:e instanceof Error?e.message:String(e)},exitCode:2}}function Zh(e){let t=Ql(e);console.log(JSON.stringify(Xl(null,[t.error]))),console.error(t.error.message),process.exit(t.exitCode)}async function ao(e,t){let n=[],r=[],s=o=>{o.status==="fulfilled"?n.push(o.value):r.push({code:"INTERNAL",message:o.reason instanceof Error?o.reason.message:String(o.reason)})};for(let o of await Promise.allSettled(e.map(i=>Promise.resolve().then(i))))s(o);for(let o of t)for(let i of await Promise.allSettled([Promise.resolve().then(o)]))s(i);return{checks:n,errors:r}}function io(e){let t=e.find(n=>n.name===B);return t?t.didPass:null}function ee(e,t,n=[],r,s){return{schemaVersion:On,data:{ready:n.length===0&&e.every(o=>o.didPass||o.isSkipped||o.isWarning),inProject:t,checks:e,...s?{host:{...s,containerRuntimeReachable:io(e),canUp:s.canUp&&io(e)!==!1}}:{},...r!==void 0?{ports:{http:{requested:r?.requested.ingressHttp??80,chosen:r?.ingressHttp??null,explicit:r?.explicit.ingressHttp??!!process.env.TDK_HTTP_PORT,reason:r?.reason.ingressHttp??"port planning failed"},https:{requested:r?.requested.ingressHttps??443,chosen:r?.ingressHttps??null,explicit:r?.explicit.ingressHttps??!!process.env.TDK_HTTPS_PORT,reason:r?.reason.ingressHttps??"port planning failed"},postgres:{requested:r?.requested.postgres??5432,chosen:r?.postgres??null,explicit:r?.explicit.postgres??!!process.env.TDK_POSTGRES_PORT,reason:r?.reason.postgres??"port planning failed"}}}:{}},errors:n}}function co(e){return e.errors.length>0?2:e.data.ready?0:1}import{existsSync as Cn,readFileSync as lo}from"node:fs";import{dirname as Zl,join as Nn,normalize as ed}from"node:path";function td(e){let t=new Set,n=/^load\s*\(([\s\S]*?)\)/gm;for(let r of e.matchAll(n)){let s=r[1]??"",o=/["']([^"']+)["']/g,i=Array.from(s.matchAll(o),a=>a[1]);for(let a of i.slice(1))a.startsWith("_")&&t.add(a)}return Array.from(t).sort()}function uo(e,t,n){return t==="ext://tdk-cli"?Nn(n,".tdk",".tdk-out","tdk-cli-ext","Tiltfile"):t.startsWith(".")||!t.includes("://")&&!t.startsWith("@")?ed(Nn(Zl(e),t)):null}function nd(e,t,n){let r=[],s=/^load\s*\(([\s\S]*?)\)/gm;for(let o of t.matchAll(s)){let c=(o[1]??"").match(/["']([^"']+)["']/)?.[1];if(!c)continue;let l=uo(e,c,n);l&&(Cn(l)||r.push(`${e}: ${c} -> ${l}`))}return r}function rd(e,t,n){let r=[],s=/^load\s*\(([\s\S]*?)\)/gm;for(let o of t.matchAll(s)){let c=(o[1]??"").match(/["']([^"']+)["']/)?.[1];if(c){let l=uo(e,c,n);l&&r.push(l)}}return r}function sd(e,t){let n=new Set,r=[e];for(;r.length>0;){let s=r.pop();if(!s||n.has(s)||!Cn(s))continue;n.add(s);let o=lo(s,"utf-8");for(let i of rd(s,o,t))n.has(i)||r.push(i)}return Array.from(n).sort()}function po(){let e=y()??process.cwd(),t=Nn(e,".tdk",".tdk-out","Tiltfile");if(!Cn(t))return{name:"Starlark Load Exports",didPass:!0,isSkipped:!0,message:"No generated Tiltfile to check"};let n=[],r=[],s=sd(t,e);for(let i of s){let a=lo(i,"utf-8"),c=td(a);c.length>0&&n.push(`${i}: ${c.join(", ")}`);for(let l of nd(i,a,e))r.push(l)}if(n.length===0&&r.length===0)return{name:"Starlark Load Exports",didPass:!0,message:`${T(s.length,"reachable Starlark file")} ${s.length===1?"has":"have"} valid load exports and paths`};let o=[];return n.length>0&&o.push(`Private exported symbols:
99
99
  ${n.join(`
100
100
  `)}`),r.length>0&&o.push(`Missing relative load targets:
101
101
  ${r.join(`
102
102
  `)}`),{name:"Starlark Load Exports",didPass:!1,message:`Starlark load() issues will stop Tilt before services start:
103
103
  ${o.join(`
104
104
 
105
- `)}`,fix:"Regenerate with a current TDK (`tdk config regenerate`). If the issue remains, rename loaded symbols without leading underscores and update stale load paths."}}import{execFileSync as kl,execSync as yl}from"node:child_process";import{existsSync as Fn,readdirSync as $o,readFileSync as Be}from"node:fs";import{basename as Sl,dirname as bl,join as M,relative as Ue}from"node:path";function ag(e){return`import { Hono } from 'hono';
105
+ `)}`,fix:"Regenerate with a current TDK (`tdk config regenerate`). If the issue remains, rename loaded symbols without leading underscores and update stale load paths."}}import{execFileSync as Sd,execSync as bd}from"node:child_process";import{existsSync as Fn,readdirSync as _o,readFileSync as Be}from"node:fs";import{basename as Td,dirname as xd,join as M,relative as Ue}from"node:path";function lg(e){return`import { Hono } from 'hono';
106
106
 
107
107
  const app = new Hono();
108
108
 
@@ -142,7 +142,7 @@ export default {
142
142
  port,
143
143
  fetch: app.fetch,
144
144
  };
145
- `}var fo={id:"bun",label:"Bun + Hono",installHint:"bun install"};var sl="go run .",mo={id:"go",label:"Go 1.23 (net/http)",devCommand:sl,watch:["**/*.go","go.mod","go.sum"],installHint:"go mod tidy # optional: Docker builds the image for you",createFiles(e){return[{filename:"go.mod",content:`module ${e}
145
+ `}var fo={id:"bun",label:"Bun + Hono",installHint:"bun install"};var od="go run .",mo={id:"go",label:"Go 1.23 (net/http)",devCommand:od,watch:["**/*.go","go.mod","go.sum"],installHint:"go mod tidy # optional: Docker builds the image for you",createFiles(e){return[{filename:"go.mod",content:`module ${e}
146
146
 
147
147
  go 1.23
148
148
  `,description:"Generating go.mod",emoji:"\u{1F4E6}"},{filename:"main.go",content:`package main
@@ -205,7 +205,79 @@ func TestHealth(t *testing.T) {
205
205
  t.Fatalf("GET /health = %d, want %d", rec.Code, http.StatusOK)
206
206
  }
207
207
  }
208
- `,description:"Generating smoke test",emoji:"\u{1F9EA}"}]}};var ol="uvicorn main:app --app-dir src --host 0.0.0.0 --port ${PORT:-4000} --reload --reload-dir src",ho={id:"python",label:"Python 3.12 + FastAPI",devCommand:ol,watch:["src/**/*"],installHint:'pip install -e ".[dev]" # optional: Docker builds the image for you',createFiles(e){return[{filename:"pyproject.toml",content:`[project]
208
+ `,description:"Generating smoke test",emoji:"\u{1F9EA}"}]}};var id="node --watch src/index.js",ho={id:"node",label:"Node.js 22",devCommand:id,watch:["src/**/*"],installHint:"npm install # optional: Docker builds the image for you",createFiles(e){return[{filename:"package.json",content:`{
209
+ "name": "${e}",
210
+ "version": "1.0.0",
211
+ "type": "module",
212
+ "scripts": {
213
+ "dev": "node --watch src/index.js",
214
+ "start": "node src/index.js",
215
+ "test": "node --test"
216
+ }
217
+ }
218
+ `,description:"Generating package.json",emoji:"\u{1F4E6}"},{filename:"src/index.js",content:`import http from "node:http";
219
+
220
+ const name = "${e}";
221
+ const port = Number(process.env.PORT) || 3000;
222
+
223
+ function sendJson(res, status, data) {
224
+ res.writeHead(status, { "Content-Type": "application/json" });
225
+ res.end(JSON.stringify(data));
226
+ }
227
+
228
+ export const server = http.createServer((req, res) => {
229
+ const url = new URL(req.url, \`http://\${req.headers.host || "localhost"}\`);
230
+
231
+ // Health check endpoint (required by TILT_RESOURCE_DEFAULTS.star)
232
+ if (req.method === "GET" && url.pathname === "/health") {
233
+ return sendJson(res, 200, { status: "ok", service: name });
234
+ }
235
+
236
+ if (req.method === "GET" && url.pathname === "/") {
237
+ return sendJson(res, 200, {
238
+ service: name,
239
+ version: "1.0.0",
240
+ endpoints: ["/health"],
241
+ });
242
+ }
243
+
244
+ return sendJson(res, 404, { error: "Not Found" });
245
+ });
246
+
247
+ if (process.env.NODE_ENV !== "test") {
248
+ // "0.0.0.0" listens on every interface, which Traefik needs inside the container network.
249
+ server.listen(port, "0.0.0.0", () => {
250
+ console.log(\`\\n\u{1F680} \${name} running on http://localhost:\${port}\`);
251
+ console.log(\`\u{1F4CA} Health check: http://localhost:\${port}/health\\n\`);
252
+ });
253
+ }
254
+ `,description:"Generating backend source",emoji:"\u{1F4BB}"},{filename:"tests/health.test.js",content:`import assert from "node:assert/strict";
255
+ import { after, before, describe, it } from "node:test";
256
+ import { server } from "../src/index.js";
257
+
258
+ describe("health check", () => {
259
+ let baseUrl;
260
+
261
+ before((_, done) => {
262
+ server.listen(0, "127.0.0.1", () => {
263
+ const address = server.address();
264
+ baseUrl = \`http://127.0.0.1:\${address.port}\`;
265
+ done();
266
+ });
267
+ });
268
+
269
+ after((_, done) => {
270
+ server.close(done);
271
+ });
272
+
273
+ it("GET /health returns 200 with ok status", async () => {
274
+ const res = await fetch(\`\${baseUrl}/health\`);
275
+ assert.equal(res.status, 200);
276
+ const body = await res.json();
277
+ assert.deepEqual(body, { status: "ok", service: "${e}" });
278
+ });
279
+ });
280
+ `,description:"Generating smoke test",emoji:"\u{1F9EA}"}]}};var ad="uvicorn main:app --app-dir src --host 0.0.0.0 --port ${PORT:-4000} --reload --reload-dir src",go={id:"python",label:"Python 3.12 + FastAPI",devCommand:ad,watch:["src/**/*"],installHint:'pip install -e ".[dev]" # optional: Docker builds the image for you',createFiles(e){return[{filename:"pyproject.toml",content:`[project]
209
281
  name = "${e}"
210
282
  version = "0.0.1"
211
283
  requires-python = ">=3.12"
@@ -263,7 +335,7 @@ def test_health() -> None:
263
335
  response = client.get("/health")
264
336
  assert response.status_code == 200
265
337
  assert response.json() == {"status": "ok", "service": "${e}"}
266
- `,description:"Generating test file",emoji:"\u{1F9EA}"}]}};var il="cargo run",go={id:"rust",label:"Rust (axum)",devCommand:il,watch:["src/**/*.rs","Cargo.toml","Cargo.lock"],installHint:"cargo build # optional: Docker builds the image for you",createFiles(e){return[{filename:"Cargo.toml",content:`[package]
338
+ `,description:"Generating test file",emoji:"\u{1F9EA}"}]}};var cd="cargo run",ko={id:"rust",label:"Rust (axum)",devCommand:cd,watch:["src/**/*.rs","Cargo.toml","Cargo.lock"],installHint:"cargo build # optional: Docker builds the image for you",createFiles(e){return[{filename:"Cargo.toml",content:`[package]
267
339
  name = "${e}"
268
340
  version = "0.1.0"
269
341
  edition = "2021"
@@ -317,61 +389,61 @@ mod tests {
317
389
  assert_eq!(body["status"], "ok");
318
390
  }
319
391
  }
320
- `,description:"Generating backend source and smoke test",emoji:"\u{1F4BB}"}]}};var ko="bun",ge={bun:fo,python:ho,go:mo,rust:go};function al(e){let t=(e??ko).trim().toLowerCase(),n=Object.hasOwn(ge,t)?ge[t]:void 0;if(!n){let r=Object.keys(ge).join(", ");throw new N(`Unknown backend language "${e}". Supported languages: ${r}.`,[`Use one of: ${r}`,`Omit --language to use ${ko}`])}return n}function kg(e,t){if(e!=="backend"){if(t!==void 0)throw new N("--language can only be used with --type backend.",["Add --type backend, or drop --language for this resource type"]);return}return al(t)}import{exec as cl,execFile as ul}from"node:child_process";import{promisify as yo}from"node:util";var ll=yo(cl),V=async(e,t)=>{if(process.platform==="win32"){let r=e.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g)??[],[s,...o]=r.map(c=>c.startsWith('"')||c.startsWith("'")?c.slice(1,-1):c);if(!s)throw new Error("Command is empty");let i=O(s)??s,{stdout:a}=await yo(ul)(i,o,{encoding:"utf-8",timeout:t,windowsHide:!0,shell:!1});return a}let{stdout:n}=await ll(e,{encoding:"utf-8",timeout:t});return n};function So(e){let t=e;return t?.code==="ETIMEDOUT"||t?.killed===!0}import{existsSync as dl,readFileSync as bo}from"node:fs";import{join as te}from"node:path";var To=["postgres",j],xo=["pre_alpha","alpha","beta","out_of_scope"];function pl(e){return To.includes(e)}function wo(e){try{return JSON.parse(bo(te(e,".tdk",_),"utf-8"))}catch{return}}function ke(e){try{return dl(e)?bo(e,"utf-8"):void 0}catch{return}}function Eo(e,t){let n=s=>{let o=s;for(;o<e.length&&/\s/.test(e[o]);)o+=1;return o},r=0;for(;;){let s=e.indexOf(t,r);if(s===-1)return;let o=n(s+t.length);if(e[o]==="="&&(o=n(o+1),e[o]==="[")){let i=e.indexOf("]",o+1);return i===-1?void 0:[...e.slice(o+1,i).matchAll(/"([^"]+)"|'([^']+)'/g)].map(a=>a[1]??a[2]??"")}r=s+t.length}}function vo(e){let t=te(e,".tdk",".tdk-out","Tiltfile"),n=ke(t);if(n)return Eo(n,"ALWAYS_ENABLED_INFRA")}function fl(e){let t=te(e,".tdk",".tdk-out","spec.master"),n=ke(t);if(n!==void 0)return/"database-management"\s*:\s*True/.test(n)}function ml(e){let t=te(e,".tdk",".tdk-out"),n=ke(te(t,"Tiltfile")),r=ke(te(t,"spec.master")),s=ke(te(t,"tdk-cli-ext","discovery","config.star")),o=ke(te(t,"tdk-cli-ext","engine","topologies","tilt","config","profiles.star"));if(!n||!r||!s||!o)return!1;let i=r.match(/PRE_ALPHA_RESOURCES\s*=\s*\{([^}]*)\}/)?.[1],a=Eo(s,"CORE_INFRA");return/FOCUS_MODE\s*,\s*FOCUS_ENABLED_ALL\s*,\s*FOCUS_ENABLED_RESOURCES\s*=\s*Config\.apply_focus\(cfg\)/.test(n)&&/if FOCUS_MODE and FOCUS_ENABLED_ALL\s*:/.test(n)&&/"[^"]+"\s*:\s*True|'[^']+'\s*:\s*True/.test(i??"")&&(a?.includes("postgres")??!1)&&/["']postgres["']\s*:\s*["']database-management["']/.test(s)&&/for infra in CORE_INFRA_EXPORT\s*:/.test(o)&&/needed\[INFRA_STACK_MAP_EXPORT\[infra\]\]\s*=\s*True/.test(o)}function hl(e){let t=wo(e);if(!t)return!1;let n=t.phases??{};for(let s of xo){let o=n[s]?.enabledStacks;if(Array.isArray(o)&&o.includes(j))return!0}let r=t.always_enabled_infra??_e;return Array.isArray(r)&&r.includes(j)}function gl(e){let t=new Set;for(let s of To)t.add(s);for(let s of x(e))t.add(s.name),s.stack&&t.add(s.stack);let n=wo(e);if(n){let s=n.phases??{};for(let i of xo){let a=s[i]?.enabledStacks;if(Array.isArray(a))for(let c of a)t.add(c)}let o=n.always_enabled_infra??_e;if(Array.isArray(o))for(let i of o)t.add(i)}let r=vo(e);if(Array.isArray(r))for(let s of r)t.add(s);return t}function jn(e){let t=hl(e),n=vo(e),r=Array.isArray(n)&&n.includes(j),s=fl(e)===!0,o=t||r||s,i=!t&&ml(e),a=gl(e),c=[],u=[];for(let p of x(e)){let h=p.config?.dependsOn??[],f=!1;for(let b of h){if(pl(b)){f=!0;continue}a.has(b)||u.push({resource:p.name,name:b})}f&&c.push(p.name)}let d=o||c.length>0,l=o?"feature":c.length>0?"dependsOn":"none";return{featureOn:o,featureOnFromProjectJson:t,featureOnFromTiltfile:r,featureOnFromSpecMaster:s,focusWouldEnableDatabaseManagement:i,dependsOnUsers:c,willStart:d,reason:l,unknownDependsOnNames:u}}var pt=1e4,Tl=/\.(?:[cm]?[jt]sx?|vue)$/,xl=/(?:\.test\.|\.spec\.|\/tests?\/|\/__tests__\/)/,wl=7,El=new Set(["node_modules",C,"dist","tests","__tests__"]);function _o(e){try{let t=JSON.parse(Be(M(e,".tdk",_),"utf-8"));return typeof t?.project?.name=="string"?t.project.name:void 0}catch{return}}function vl(e){try{let t=JSON.parse(Be(e,"utf-8")).params;return t&&typeof t=="object"?t:{}}catch{return{}}}function In(e){try{let t=JSON.parse(Be(M(e,A),"utf-8"));return t&&typeof t=="object"?t:{}}catch{return{}}}function Po(e){if(typeof e!="string")return;let t=e.match(/(?:^|[^0-9])(\d+)(?:\.|$)/);return t?Number(t[1]):void 0}function Pl(e){let t=mt(e);if(t===void 0)return["missing prisma/schema.prisma"];let n=t.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,""),r=[],s=n.match(/datasource\s+\w+\s*\{([^}]*)\}/)?.[1]??"";return/provider\s*=\s*["']postgresql["']/.test(s)||r.push("schema provider is not postgresql"),/\b(?:url|directUrl)\s*=/.test(n)&&r.push("schema still declares url/directUrl"),r}function $l(e){let t=M(e,C,"prisma.config.autogenerated.ts"),r=[M(e,"prisma.config.ts"),t].find(i=>Fn(i));if(!r)return["missing prisma.config.ts or generated Prisma config"];let o=(mt(r)??"").match(/datasource\s*:\s*\{([^}]*)\}/)?.[1]??"";return/url\s*:\s*(?:env\(["']DATABASE_URL["']\)|process\.env\.DATABASE_URL)\s*,?/.test(o)?[]:['Prisma config datasource.url is not env("DATABASE_URL")']}function Ro(e=y()??process.cwd()){let t=x(e),n=t.filter(o=>o.config?.featuresEnabled?.includes("prisma")),r=[],s=t.filter(o=>o.config?.appType==="migrator");for(let o of t){let i=o.config?.features;Array.isArray(i)&&i.includes("prisma")&&!o.config?.featuresEnabled?.includes("prisma")&&r.push(`${o.name}: use featuresEnabled, not features, for Prisma`)}if(n.length===0)return r.length===0?{name:"Prisma 7 consistency",didPass:!0,isSkipped:!0,message:"No resources enable Prisma; Prisma consistency checks were skipped"}:{name:"Prisma 7 consistency",didPass:!1,message:`${T(r.length,"Prisma consistency error")}:
392
+ `,description:"Generating backend source and smoke test",emoji:"\u{1F4BB}"}]}};var yo="bun",ge={bun:fo,python:go,go:mo,rust:ko,node:ho};function ld(e){let t=(e??yo).trim().toLowerCase(),n=Object.hasOwn(ge,t)?ge[t]:void 0;if(!n){let r=Object.keys(ge).join(", ");throw new N(`Unknown backend language "${e}". Supported languages: ${r}.`,[`Use one of: ${r}`,`Omit --language to use ${yo}`])}return n}function Tg(e,t){if(e!=="backend"){if(t!==void 0)throw new N("--language can only be used with --type backend.",["Add --type backend, or drop --language for this resource type"]);return}return ld(t)}import{exec as dd,execFile as ud}from"node:child_process";import{promisify as So}from"node:util";var pd=So(dd),V=async(e,t)=>{if(process.platform==="win32"){let r=e.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g)??[],[s,...o]=r.map(c=>c.startsWith('"')||c.startsWith("'")?c.slice(1,-1):c);if(!s)throw new Error("Command is empty");let i=O(s)??s,{stdout:a}=await So(ud)(i,o,{encoding:"utf-8",timeout:t,windowsHide:!0,shell:!1});return a}let{stdout:n}=await pd(e,{encoding:"utf-8",timeout:t});return n};function bo(e){let t=e;return t?.code==="ETIMEDOUT"||t?.killed===!0}import{existsSync as fd,readFileSync as To}from"node:fs";import{join as te}from"node:path";var xo=["postgres",j],wo=["pre_alpha","alpha","beta","out_of_scope"];function md(e){return xo.includes(e)}function Eo(e){try{return JSON.parse(To(te(e,".tdk",_),"utf-8"))}catch{return}}function ke(e){try{return fd(e)?To(e,"utf-8"):void 0}catch{return}}function vo(e,t){let n=s=>{let o=s;for(;o<e.length&&/\s/.test(e[o]);)o+=1;return o},r=0;for(;;){let s=e.indexOf(t,r);if(s===-1)return;let o=n(s+t.length);if(e[o]==="="&&(o=n(o+1),e[o]==="[")){let i=e.indexOf("]",o+1);return i===-1?void 0:[...e.slice(o+1,i).matchAll(/"([^"]+)"|'([^']+)'/g)].map(a=>a[1]??a[2]??"")}r=s+t.length}}function Po(e){let t=te(e,".tdk",".tdk-out","Tiltfile"),n=ke(t);if(n)return vo(n,"ALWAYS_ENABLED_INFRA")}function hd(e){let t=te(e,".tdk",".tdk-out","spec.master"),n=ke(t);if(n!==void 0)return/"database-management"\s*:\s*True/.test(n)}function gd(e){let t=te(e,".tdk",".tdk-out"),n=ke(te(t,"Tiltfile")),r=ke(te(t,"spec.master")),s=ke(te(t,"tdk-cli-ext","discovery","config.star")),o=ke(te(t,"tdk-cli-ext","engine","topologies","tilt","config","profiles.star"));if(!n||!r||!s||!o)return!1;let i=r.match(/PRE_ALPHA_RESOURCES\s*=\s*\{([^}]*)\}/)?.[1],a=vo(s,"CORE_INFRA");return/FOCUS_MODE\s*,\s*FOCUS_ENABLED_ALL\s*,\s*FOCUS_ENABLED_RESOURCES\s*=\s*Config\.apply_focus\(cfg\)/.test(n)&&/if FOCUS_MODE and FOCUS_ENABLED_ALL\s*:/.test(n)&&/"[^"]+"\s*:\s*True|'[^']+'\s*:\s*True/.test(i??"")&&(a?.includes("postgres")??!1)&&/["']postgres["']\s*:\s*["']database-management["']/.test(s)&&/for infra in CORE_INFRA_EXPORT\s*:/.test(o)&&/needed\[INFRA_STACK_MAP_EXPORT\[infra\]\]\s*=\s*True/.test(o)}function kd(e){let t=Eo(e);if(!t)return!1;let n=t.phases??{};for(let s of wo){let o=n[s]?.enabledStacks;if(Array.isArray(o)&&o.includes(j))return!0}let r=t.always_enabled_infra??_e;return Array.isArray(r)&&r.includes(j)}function yd(e){let t=new Set;for(let s of xo)t.add(s);for(let s of x(e))t.add(s.name),s.stack&&t.add(s.stack);let n=Eo(e);if(n){let s=n.phases??{};for(let i of wo){let a=s[i]?.enabledStacks;if(Array.isArray(a))for(let c of a)t.add(c)}let o=n.always_enabled_infra??_e;if(Array.isArray(o))for(let i of o)t.add(i)}let r=Po(e);if(Array.isArray(r))for(let s of r)t.add(s);return t}function jn(e){let t=kd(e),n=Po(e),r=Array.isArray(n)&&n.includes(j),s=hd(e)===!0,o=t||r||s,i=!t&&gd(e),a=yd(e),c=[],l=[];for(let p of x(e)){let h=p.config?.dependsOn??[],f=!1;for(let b of h){if(md(b)){f=!0;continue}a.has(b)||l.push({resource:p.name,name:b})}f&&c.push(p.name)}let u=o||c.length>0,d=o?"feature":c.length>0?"dependsOn":"none";return{featureOn:o,featureOnFromProjectJson:t,featureOnFromTiltfile:r,featureOnFromSpecMaster:s,focusWouldEnableDatabaseManagement:i,dependsOnUsers:c,willStart:u,reason:d,unknownDependsOnNames:l}}var pt=1e4,wd=/\.(?:[cm]?[jt]sx?|vue)$/,Ed=/(?:\.test\.|\.spec\.|\/tests?\/|\/__tests__\/)/,vd=7,Pd=new Set(["node_modules",C,"dist","tests","__tests__"]);function Ro(e){try{let t=JSON.parse(Be(M(e,".tdk",_),"utf-8"));return typeof t?.project?.name=="string"?t.project.name:void 0}catch{return}}function $d(e){try{let t=JSON.parse(Be(e,"utf-8")).params;return t&&typeof t=="object"?t:{}}catch{return{}}}function In(e){try{let t=JSON.parse(Be(M(e,A),"utf-8"));return t&&typeof t=="object"?t:{}}catch{return{}}}function $o(e){if(typeof e!="string")return;let t=e.match(/(?:^|[^0-9])(\d+)(?:\.|$)/);return t?Number(t[1]):void 0}function _d(e){let t=mt(e);if(t===void 0)return["missing prisma/schema.prisma"];let n=t.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,""),r=[],s=n.match(/datasource\s+\w+\s*\{([^}]*)\}/)?.[1]??"";return/provider\s*=\s*["']postgresql["']/.test(s)||r.push("schema provider is not postgresql"),/\b(?:url|directUrl)\s*=/.test(n)&&r.push("schema still declares url/directUrl"),r}function Rd(e){let t=M(e,C,"prisma.config.autogenerated.ts"),r=[M(e,"prisma.config.ts"),t].find(i=>Fn(i));if(!r)return["missing prisma.config.ts or generated Prisma config"];let o=(mt(r)??"").match(/datasource\s*:\s*\{([^}]*)\}/)?.[1]??"";return/url\s*:\s*(?:env\(["']DATABASE_URL["']\)|process\.env\.DATABASE_URL)\s*,?/.test(o)?[]:['Prisma config datasource.url is not env("DATABASE_URL")']}function Ao(e=y()??process.cwd()){let t=x(e),n=t.filter(o=>o.config?.featuresEnabled?.includes("prisma")),r=[],s=t.filter(o=>o.config?.appType==="migrator");for(let o of t){let i=o.config?.features;Array.isArray(i)&&i.includes("prisma")&&!o.config?.featuresEnabled?.includes("prisma")&&r.push(`${o.name}: use featuresEnabled, not features, for Prisma`)}if(n.length===0)return r.length===0?{name:"Prisma 7 consistency",didPass:!0,isSkipped:!0,message:"No resources enable Prisma; Prisma consistency checks were skipped"}:{name:"Prisma 7 consistency",didPass:!1,message:`${T(r.length,"Prisma consistency error")}:
321
393
  ${r.join(`
322
- `)}`,fix:"Use featuresEnabled to opt into the validated Prisma 7 shape"};for(let o of n){let i=In(o.path).dependencies,c={...In(o.path).devDependencies??{},...i??{}},u=Po(c.prisma),d=Po(c["@prisma/client"]);if(u===void 0||d===void 0?r.push(`${o.name}: prisma and @prisma/client are required`):(u!==d||u!==wl)&&r.push(`${o.name}: prisma packages must both be major 7`),r.push(...Pl(M(o.path,"prisma","schema.prisma")).map(p=>`${o.name}: ${p}`)),r.push(...$l(o.path).map(p=>`${o.name}: ${p}`)),(o.config?.appType??o.type)==="migrator")o.config?.dependsOn?.some(h=>h==="postgres"||h===j)||r.push(`${o.name}: migrator must depend on postgres or database-management`);else{o.config?.dependsOn?.some(b=>s.some(w=>w.name===b))||r.push(`${o.name}: API must depend on its Prisma migrator`);let h=In(o.path).scripts;Object.entries(h??{}).some(([b,w])=>Lo.has(b)&&typeof w=="string"&&/prisma\s+migrate/.test(w))&&r.push(`${o.name}: API start script must not run prisma migrate`);let f=M(o.path,o.config?.dockerfile??"Dockerfile");dt(f,!0)&&r.push(`${o.name}: API image/startup must not run Prisma migrations`)}}return n.length>0&&!jn(e).willStart&&r.push("shared platform Postgres will not start for the Prisma resources"),r.length===0?{name:"Prisma 7 consistency",didPass:!0,message:"Prisma resources use the validated Prisma 7 shape"}:{name:"Prisma 7 consistency",didPass:!1,message:`${T(r.length,"Prisma consistency error")}:
394
+ `)}`,fix:"Use featuresEnabled to opt into the validated Prisma 7 shape"};for(let o of n){let i=In(o.path).dependencies,c={...In(o.path).devDependencies??{},...i??{}},l=$o(c.prisma),u=$o(c["@prisma/client"]);if(l===void 0||u===void 0?r.push(`${o.name}: prisma and @prisma/client are required`):(l!==u||l!==vd)&&r.push(`${o.name}: prisma packages must both be major 7`),r.push(..._d(M(o.path,"prisma","schema.prisma")).map(p=>`${o.name}: ${p}`)),r.push(...Rd(o.path).map(p=>`${o.name}: ${p}`)),(o.config?.appType??o.type)==="migrator")o.config?.dependsOn?.some(h=>h==="postgres"||h===j)||r.push(`${o.name}: migrator must depend on postgres or database-management`);else{o.config?.dependsOn?.some(b=>s.some(w=>w.name===b))||r.push(`${o.name}: API must depend on its Prisma migrator`);let h=In(o.path).scripts;Object.entries(h??{}).some(([b,w])=>Mo.has(b)&&typeof w=="string"&&/prisma\s+migrate/.test(w))&&r.push(`${o.name}: API start script must not run prisma migrate`);let f=M(o.path,o.config?.dockerfile??"Dockerfile");ut(f,!0)&&r.push(`${o.name}: API image/startup must not run Prisma migrations`)}}return n.length>0&&!jn(e).willStart&&r.push("shared platform Postgres will not start for the Prisma resources"),r.length===0?{name:"Prisma 7 consistency",didPass:!0,message:"Prisma resources use the validated Prisma 7 shape"}:{name:"Prisma 7 consistency",didPass:!1,message:`${T(r.length,"Prisma consistency error")}:
323
395
  ${r.join(`
324
- `)}`,fix:"Use Prisma 7 packages and config, put migrations in a migrator, and make the API depend on that migrator"}}function Ao(e){let t=new Map;for(let n of e){let r=n.config?.port;I(n.config?.appType)&&typeof r=="number"&&t.set(n.name,r)}return t}function _l(e){let t=e.config?.language;return typeof t=="string"&&Object.hasOwn(ge,t)&&ge[t].createFiles!==void 0}function Rl(e){return(e.config?.appType??e.type)===J}function Do(e=y()??process.cwd()){let t=x(e).filter(n=>!Rl(n)&&!_l(n)&&!Fn(M(n.path,A))).map(n=>n.name);return t.length===0?{name:"Resource package.json",didPass:!0,message:"Every resource has a package.json"}:{name:"Resource package.json",didPass:!1,message:`${T(t.length,"resource")} without a package.json: ${t.join(", ")}. The image build stops at "COPY .../package.json: not found"`,fix:"Add a package.json next to each service.json (copy one from a working resource), or delete the folder's service.json if it is not a service"}}function ft(e=y()??process.cwd()){let t=new Map;for(let s of x(e)){let o=t.get(s.name)??[];o.push(Ue(e,s.configPath)||s.configPath),t.set(s.name,o)}let n=[...t].filter(([,s])=>s.length>1);if(n.length===0)return{name:"Duplicate resource names",didPass:!0,message:"Every resource has a unique appName"};let r=n.map(([s,o])=>`"${s}" in ${o.join(" and ")}`);return{name:"Duplicate resource names",didPass:!1,message:`${T(n.length,"appName")} used by more than one resource:
396
+ `)}`,fix:"Use Prisma 7 packages and config, put migrations in a migrator, and make the API depend on that migrator"}}function Do(e){let t=new Map;for(let n of e){let r=n.config?.port;I(n.config?.appType)&&typeof r=="number"&&t.set(n.name,r)}return t}function Ad(e){let t=e.config?.language;return typeof t=="string"&&Object.hasOwn(ge,t)&&ge[t].createFiles!==void 0}function Dd(e){return(e.config?.appType??e.type)===J}function Oo(e=y()??process.cwd()){let t=x(e).filter(n=>!Dd(n)&&!Ad(n)&&!Fn(M(n.path,A))).map(n=>n.name);return t.length===0?{name:"Resource package.json",didPass:!0,message:"Every resource has a package.json"}:{name:"Resource package.json",didPass:!1,message:`${T(t.length,"resource")} without a package.json: ${t.join(", ")}. The image build stops at "COPY .../package.json: not found"`,fix:"Add a package.json next to each service.json (copy one from a working resource), or delete the folder's service.json if it is not a service"}}function ft(e=y()??process.cwd()){let t=new Map;for(let s of x(e)){let o=t.get(s.name)??[];o.push(Ue(e,s.configPath)||s.configPath),t.set(s.name,o)}let n=[...t].filter(([,s])=>s.length>1);if(n.length===0)return{name:"Duplicate resource names",didPass:!0,message:"Every resource has a unique appName"};let r=n.map(([s,o])=>`"${s}" in ${o.join(" and ")}`);return{name:"Duplicate resource names",didPass:!1,message:`${T(n.length,"appName")} used by more than one resource:
325
397
  ${r.join(`
326
- `)}`,fix:'Give each resource its own "appName" in its service.json. The name becomes the Compose service and the Traefik router, so two resources with one name collide'}}function Al(e){let t=e.config?.appType;return I(t)?!0:t===J&&e.config?.exposeViaProxy!==!1}function Oo(e=y()??process.cwd()){let t=new Map;for(let s of x(e)){let o=s.config?.port;if(typeof o!="number"||!Al(s))continue;let i=t.get(o)??[];i.push(s.name),t.set(o,i)}let n=[...t].filter(([,s])=>s.length>1);if(n.length===0)return{name:"Duplicate resource ports",didPass:!0,message:"No two routed resources use the same port"};let r=n.map(([s,o])=>`port ${s}: ${o.join(", ")}`);return{name:"Duplicate resource ports",didPass:!1,isWarning:!0,message:`${T(n.length,"port")} used by more than one routed resource:
398
+ `)}`,fix:'Give each resource its own "appName" in its service.json. The name becomes the Compose service and the Traefik router, so two resources with one name collide'}}function Od(e){let t=e.config?.appType;return I(t)?!0:t===J&&e.config?.exposeViaProxy!==!1}function No(e=y()??process.cwd()){let t=new Map;for(let s of x(e)){let o=s.config?.port;if(typeof o!="number"||!Od(s))continue;let i=t.get(o)??[];i.push(s.name),t.set(o,i)}let n=[...t].filter(([,s])=>s.length>1);if(n.length===0)return{name:"Duplicate resource ports",didPass:!0,message:"No two routed resources use the same port"};let r=n.map(([s,o])=>`port ${s}: ${o.join(", ")}`);return{name:"Duplicate resource ports",didPass:!1,isWarning:!0,message:`${T(n.length,"port")} used by more than one routed resource:
327
399
  ${r.join(`
328
- `)}`,fix:'Usually a copied service.json. Each container can listen on the same port, but pick distinct "port" values (tdk resource assigns free ones) so URLs like http://<resource>:<port> and localhost checks stay unambiguous'}}var Dl=/https?:\/\/([a-z][a-z0-9-]*):(\d+)/g;function No(e=y()??process.cwd()){let t=x(e),n=Ao(t),r=new Map([...n].map(([o,i])=>[i,o])),s=[];for(let o of t)for(let[i,a]of Object.entries(vl(o.configPath)))for(let[,c,u]of String(a).matchAll(Dl)){let d=Number(u),l=n.get(c);l!==void 0&&l!==d?s.push(`${o.name} param ${i}: ${c}:${d}, but ${c} listens on ${l}`):(c==="localhost"||c==="127.0.0.1")&&r.has(d)&&r.get(d)!==o.name&&s.push(`${o.name} param ${i}: localhost:${d} is ${o.name} itself inside its container; ${r.get(d)} is reached as ${r.get(d)}:${d}`)}return s.length===0?{name:"Service URL ports",didPass:!0,message:"Service URLs in params point at the ports the services listen on"}:{name:"Service URL ports",didPass:!1,message:`${T(s.length,"service URL")} in params that cannot connect:
400
+ `)}`,fix:'Usually a copied service.json. Each container can listen on the same port, but pick distinct "port" values (tdk resource assigns free ones) so URLs like http://<resource>:<port> and localhost checks stay unambiguous'}}var Nd=/https?:\/\/([a-z][a-z0-9-]*):(\d+)/g;function Co(e=y()??process.cwd()){let t=x(e),n=Do(t),r=new Map([...n].map(([o,i])=>[i,o])),s=[];for(let o of t)for(let[i,a]of Object.entries($d(o.configPath)))for(let[,c,l]of String(a).matchAll(Nd)){let u=Number(l),d=n.get(c);d!==void 0&&d!==u?s.push(`${o.name} param ${i}: ${c}:${u}, but ${c} listens on ${d}`):(c==="localhost"||c==="127.0.0.1")&&r.has(u)&&r.get(u)!==o.name&&s.push(`${o.name} param ${i}: localhost:${u} is ${o.name} itself inside its container; ${r.get(u)} is reached as ${r.get(u)}:${u}`)}return s.length===0?{name:"Service URL ports",didPass:!0,message:"Service URLs in params point at the ports the services listen on"}:{name:"Service URL ports",didPass:!1,message:`${T(s.length,"service URL")} in params that cannot connect:
329
401
  ${s.join(`
330
- `)}`,fix:'TDK runs each backend on the "port" in its service.json, and containers reach each other by resource name (http://<resource>:<port>). Use that port in the URL'}}function Ln(e){let t=[],n;try{n=$o(e,{withFileTypes:!0})}catch{return t}for(let r of n){let s=M(e,r.name);r.isDirectory()?El.has(r.name)||t.push(...Ln(s)):Tl.test(r.name)&&!xl.test(s)&&t.push(s)}return t}var Ol=/(?:localhost|127\.0\.0\.1):(\d{2,5})\b/g,Co=/^\s*(?:\/\/|\/\*|\*|<!--|#)/;function jo(e=y()??process.cwd()){let t=new Map;for(let r of x(e)){let s=r.config;if(!(I(s?.appType)||s?.appType===J&&s.exposeViaProxy!==!1))continue;let i=bl(r.path),a=s?.stack??Sl(i),c=`${i}\0${a}`,u=t.get(c)??{stack:a,resources:[]};u.resources.push(r),t.set(c,u)}let n=[];for(let{stack:r,resources:s}of t.values()){if(s.length<2)continue;let o=a=>!!(a.config?.traefik?.host||a.config?.traefik?.pathPrefix),i=s.filter(a=>!o(a)).map(a=>a.name);i.length>0&&n.push(`stack "${r}": ${i.sort().join(", ")} lose the shared /api/${r}-management route because ${s.length} backends share the stack; they are routed at /api/<name> only`);for(let a of["host","pathPrefix"]){let c=new Map;for(let u of s){let d=u.config?.traefik?.[a];d&&c.set(d,[...c.get(d)??[],u.name])}for(let[u,d]of c)d.length>1&&n.push(`stack "${r}": ${d.sort().join(" and ")} both set traefik.${a} "${u}", so Traefik cannot tell them apart`)}}return n.length===0?{name:"Stack API routes",didPass:!0,message:"No two backends in one service directory compete for one stack route"}:{name:"Stack API routes",didPass:!1,isWarning:!0,message:n.join(`
331
- `),fix:'Call each backend at /api/<name>, move one backend to its own stack, or give each its own "traefik.pathPrefix" in service.json'}}function Io(e=y()??process.cwd()){let t=x(e),n=new Map([...Ao(t)].map(([o,i])=>[i,o])),r=[];for(let o of t.filter(i=>i.config?.appType==="frontend"))for(let i of Ln(M(o.path,"src")))Be(i,"utf-8").split(`
332
- `).forEach((a,c)=>{if(!Co.test(a))for(let[,u]of a.matchAll(Ol)){let d=n.get(Number(u));d&&r.push(`${Ue(e,i)}:${c+1} calls localhost:${u} (${d})`)}});if(r.length===0)return{name:"Frontend backend URLs",didPass:!0,message:"No frontend calls a backend through a localhost port"};let s=_o(e)??"<project>";return{name:"Frontend backend URLs",didPass:!1,message:`${T(r.length,"frontend call")} to a backend port that TDK does not publish on localhost:
402
+ `)}`,fix:'TDK runs each backend on the "port" in its service.json, and containers reach each other by resource name (http://<resource>:<port>). Use that port in the URL'}}function Ln(e){let t=[],n;try{n=_o(e,{withFileTypes:!0})}catch{return t}for(let r of n){let s=M(e,r.name);r.isDirectory()?Pd.has(r.name)||t.push(...Ln(s)):wd.test(r.name)&&!Ed.test(s)&&t.push(s)}return t}var Cd=/(?:localhost|127\.0\.0\.1):(\d{2,5})\b/g,jo=/^\s*(?:\/\/|\/\*|\*|<!--|#)/;function Io(e=y()??process.cwd()){let t=new Map;for(let r of x(e)){let s=r.config;if(!(I(s?.appType)||s?.appType===J&&s.exposeViaProxy!==!1))continue;let i=xd(r.path),a=s?.stack??Td(i),c=`${i}\0${a}`,l=t.get(c)??{stack:a,resources:[]};l.resources.push(r),t.set(c,l)}let n=[];for(let{stack:r,resources:s}of t.values()){if(s.length<2)continue;let o=a=>!!(a.config?.traefik?.host||a.config?.traefik?.pathPrefix),i=s.filter(a=>!o(a)).map(a=>a.name);i.length>0&&n.push(`stack "${r}": ${i.sort().join(", ")} lose the shared /api/${r}-management route because ${s.length} backends share the stack; they are routed at /api/<name> only`);for(let a of["host","pathPrefix"]){let c=new Map;for(let l of s){let u=l.config?.traefik?.[a];u&&c.set(u,[...c.get(u)??[],l.name])}for(let[l,u]of c)u.length>1&&n.push(`stack "${r}": ${u.sort().join(" and ")} both set traefik.${a} "${l}", so Traefik cannot tell them apart`)}}return n.length===0?{name:"Stack API routes",didPass:!0,message:"No two backends in one service directory compete for one stack route"}:{name:"Stack API routes",didPass:!1,isWarning:!0,message:n.join(`
403
+ `),fix:'Call each backend at /api/<name>, move one backend to its own stack, or give each its own "traefik.pathPrefix" in service.json'}}function Fo(e=y()??process.cwd()){let t=x(e),n=new Map([...Do(t)].map(([o,i])=>[i,o])),r=[];for(let o of t.filter(i=>i.config?.appType==="frontend"))for(let i of Ln(M(o.path,"src")))Be(i,"utf-8").split(`
404
+ `).forEach((a,c)=>{if(!jo.test(a))for(let[,l]of a.matchAll(Cd)){let u=n.get(Number(l));u&&r.push(`${Ue(e,i)}:${c+1} calls localhost:${l} (${u})`)}});if(r.length===0)return{name:"Frontend backend URLs",didPass:!0,message:"No frontend calls a backend through a localhost port"};let s=Ro(e)??"<project>";return{name:"Frontend backend URLs",didPass:!1,message:`${T(r.length,"frontend call")} to a backend port that TDK does not publish on localhost:
333
405
  ${r.join(`
334
- `)}`,fix:`Backends are only reachable through Traefik: http://api.${s}.localhost/api/<name without -api>/... (for example catalog-api is /api/catalog). Use that URL, or the generated .autogenerated/env.ts`}}var Fo=/\b(?:prisma\s+(?:migrate\s+(?:deploy|dev|resolve)|db\s+push)|drizzle-kit\s+(?:migrate|push)|knex\s+migrate:\w+|typeorm\s+migration:run|mikro-orm\s+migration:up|sequelize(?:-cli)?\s+db:migrate|dbmate\s+(?:up|migrate)|atlas\s+migrate\s+apply|alembic\s+upgrade)\b/,Lo=new Set(["start","dev","serve","prestart","predev","preserve"]),Nl=/\.(?:sh|bash)$/,Cl=/^\s*(?:CMD|ENTRYPOINT)\b/i;function mt(e){try{return Be(e,"utf-8")}catch{return}}function jl(e){let t=mt(M(e,A));if(t===void 0)return[];let n={};try{n=JSON.parse(t)?.scripts??{}}catch{return[]}return Object.entries(n).filter(([r,s])=>Lo.has(r)&&typeof s=="string"&&Fo.test(s)).map(([r])=>`package.json "${r}" script`)}function dt(e,t){let n=mt(e);return n===void 0?!1:n.split(`
335
- `).some(r=>Fo.test(r.replace(/["'`,[\]]+/g," "))&&!Co.test(r)&&(!t||Cl.test(r)))}function Mo(e=y()??process.cwd()){let t=[];for(let n of x(e)){let r=n.config?.appType??n.type;if(r!=="backend"&&r!=="worker")continue;let s=n.path;for(let a of jl(s))t.push(`${n.name}: ${a}`);let o=M(s,n.config?.dockerfile??"Dockerfile");dt(o,!0)&&t.push(`${n.name}: ${Ue(e,o)} CMD or ENTRYPOINT`);let i=[];try{i=$o(s,{withFileTypes:!0})}catch{}for(let a of i){let c=M(s,a.name);a.isFile()&&Nl.test(a.name)&&dt(c,!1)&&t.push(`${n.name}: ${Ue(e,c)}`)}for(let a of Ln(M(s,"src")))dt(a,!1)&&t.push(`${n.name}: ${Ue(e,a)}`)}return t.length===0?{name:"Migrations outside the API",didPass:!0,message:"No backend or worker runs a migration command from its own start-up"}:{name:"Migrations outside the API",didPass:!1,isWarning:!0,message:`${T(t.length,"migration command")} run from a backend or worker's own start-up:
406
+ `)}`,fix:`Backends are only reachable through Traefik: http://api.${s}.localhost/api/<name without -api>/... (for example catalog-api is /api/catalog). Use that URL, or the generated .autogenerated/env.ts`}}var Lo=/\b(?:prisma\s+(?:migrate\s+(?:deploy|dev|resolve)|db\s+push)|drizzle-kit\s+(?:migrate|push)|knex\s+migrate:\w+|typeorm\s+migration:run|mikro-orm\s+migration:up|sequelize(?:-cli)?\s+db:migrate|dbmate\s+(?:up|migrate)|atlas\s+migrate\s+apply|alembic\s+upgrade)\b/,Mo=new Set(["start","dev","serve","prestart","predev","preserve"]),jd=/\.(?:sh|bash)$/,Id=/^\s*(?:CMD|ENTRYPOINT)\b/i;function mt(e){try{return Be(e,"utf-8")}catch{return}}function Fd(e){let t=mt(M(e,A));if(t===void 0)return[];let n={};try{n=JSON.parse(t)?.scripts??{}}catch{return[]}return Object.entries(n).filter(([r,s])=>Mo.has(r)&&typeof s=="string"&&Lo.test(s)).map(([r])=>`package.json "${r}" script`)}function ut(e,t){let n=mt(e);return n===void 0?!1:n.split(`
407
+ `).some(r=>Lo.test(r.replace(/["'`,[\]]+/g," "))&&!jo.test(r)&&(!t||Id.test(r)))}function Uo(e=y()??process.cwd()){let t=[];for(let n of x(e)){let r=n.config?.appType??n.type;if(r!=="backend"&&r!=="worker")continue;let s=n.path;for(let a of Fd(s))t.push(`${n.name}: ${a}`);let o=M(s,n.config?.dockerfile??"Dockerfile");ut(o,!0)&&t.push(`${n.name}: ${Ue(e,o)} CMD or ENTRYPOINT`);let i=[];try{i=_o(s,{withFileTypes:!0})}catch{}for(let a of i){let c=M(s,a.name);a.isFile()&&jd.test(a.name)&&ut(c,!1)&&t.push(`${n.name}: ${Ue(e,c)}`)}for(let a of Ln(M(s,"src")))ut(a,!1)&&t.push(`${n.name}: ${Ue(e,a)}`)}return t.length===0?{name:"Migrations outside the API",didPass:!0,message:"No backend or worker runs a migration command from its own start-up"}:{name:"Migrations outside the API",didPass:!1,isWarning:!0,message:`${T(t.length,"migration command")} run from a backend or worker's own start-up:
336
408
  ${t.join(`
337
- `)}`,fix:"Move the migration into a `migrator` resource (appType migrator) that the service depends on, so it runs once before the service starts instead of on every start and restart"}}function ht(e=y()??process.cwd()){let t=x(e).filter(r=>r.config?.featuresEnabled?.includes("nats")).map(r=>r.name);if(t.length===0)return{name:"NATS broker",didPass:!0,message:"No resource enables the nats feature",isSkipped:!0};if(Fn(M(e,"services","platform","messaging",se)))return{name:"NATS broker",didPass:!0,message:`${T(t.length,"resource")} enable nats and services/platform/messaging/docker-compose.yml is present`};let n=(_o(e)??"project").replace(/-/g,"_");return{name:"NATS broker",didPass:!1,message:`${t.join(", ")} enable the nats feature, but no NATS server will start: TDK only starts one when services/platform/messaging/docker-compose.yml exists, and it does not generate that file`,fix:`Create it with a "nats" service (image nats with -js, container_name ${n}_nats, network ${n}_backend, external) and a "redis" service, which TDK registers alongside it`}}function Uo(e=y()??process.cwd()){let t=jn(e),n=" (project resource set; tdk up may select a subset and not start Postgres)",r=t.focusWouldEnableDatabaseManagement?" Warning: generated Tiltfile default focus expands CORE_INFRA to database-management while project.json has it off; default tdk up takes the feature path.":"";if(t.unknownDependsOnNames.length>0){let o=t.unknownDependsOnNames.map(({resource:a,name:c})=>`"${c}" (from ${a})`).join(", "),i=t.willStart?` Postgres will start because ${t.reason==="feature"?"database-management is enabled":`resource(s) ${t.dependsOnUsers.join(", ")} depend on postgres/database-management`}${n}`:" Postgres will not start for this project.json/generated Tiltfile state.";return{name:"Shared platform Postgres",didPass:!1,message:`${T(t.unknownDependsOnNames.length,"unknown dependsOn name")}: ${o}. These are not known services or stacks, and are not the shared platform database names (postgres, database-management).${i}${r}`,fix:'Use "postgres" or "database-management" in dependsOn for the shared platform database, or fix the name to match an existing service'}}if(!t.willStart)return{name:"Shared platform Postgres",didPass:!0,isWarning:!!r,isSkipped:!r,message:r?r.trim():"Shared platform Postgres will not start: database-management is off and no resource depends on postgres or database-management."};if(t.reason==="feature"&&t.dependsOnUsers.length===0){let o=t.featureOnFromTiltfile||t.featureOnFromSpecMaster?" (generated Tiltfile/spec.master)":"";return{name:"Shared platform Postgres",didPass:!0,isWarning:!!r,message:`Shared platform Postgres will start because the database-management feature is enabled${o} (project-wide; not a tdk up selection).${r}`}}let s=t.reason==="feature"?`the database-management feature is enabled and resource(s) ${t.dependsOnUsers.join(", ")} depend on postgres/database-management`:`resource(s) ${t.dependsOnUsers.join(", ")} depend on postgres/database-management`;return{name:"Shared platform Postgres",didPass:!0,isWarning:!!r,message:`Shared platform Postgres will start because ${s}${n}${r}`}}function Il(e){let t=[];for(let n of e.split(`
338
- `)){let r=n.match(/^\s*(\d+)\s+.*\btilt up\b.*?\s-f\s+(\S+)/i);r&&t.push({pid:Number(r[1]),root:r[2].split(/[\\/]\.tdk[\\/]/i)[0]})}return t}function Bo(e=y()??process.cwd(),t=yl){let n;try{n=process.platform==="win32"?kl("powershell.exe",["-NoProfile","-Command","Get-CimInstance Win32_Process | Where-Object { $_.Name -eq 'tilt.exe' } | ForEach-Object { '{0} {1}' -f $_.ProcessId, $_.CommandLine }"],{encoding:"utf-8",timeout:pt,windowsHide:!0}):t("ps -Ao pid=,command=",{encoding:"utf-8",timeout:pt})}catch{return{name:"Tilt processes",didPass:!0,isSkipped:!0,message:"Could not list processes"}}let r=Il(n),s=r.filter(i=>i.root===e),o=r.filter(i=>i.root!==e);return s.length>1?{name:"Tilt processes",didPass:!1,message:`${s.length} Tilt processes are running for this project (pids ${s.map(i=>i.pid).join(", ")}). They fight over ports and containers`,fix:`Stop them all, then start one: tdk down && kill ${s.map(i=>i.pid).join(" ")} && tdk up`}:o.length>0?{name:"Tilt processes",didPass:!0,isSkipped:!0,message:`Another project's Tilt is running: ${o.map(a=>`${a.root} (pid ${a.pid})`).join(", ")}`,fix:"tdk up will use the next free Tilt UI port (10351, ...). If it is a leftover, run tdk down in that project"}:{name:"Tilt processes",didPass:!0,message:"No stray Tilt processes"}}async function Ho(e=V){let t=`tdk_doctor_probe_${process.pid}`;try{await e(`docker network create ${t}`,pt)}catch(n){let r=String(n.stderr??n);return/address pools/i.test(r)?{name:"Docker networks",didPass:!1,message:"Docker cannot create another network: all predefined address pools are in use. Each TDK project needs several",fix:"run tdk down --prune-networks in projects you are not using, or docker network prune (removes all unused networks)"}:{name:"Docker networks",didPass:!0,isSkipped:!0,message:"Could not test network creation"}}try{await e(`docker network rm ${t}`,pt)}catch{}return{name:"Docker networks",didPass:!0,message:"Docker can create networks"}}import{execFileSync as Go}from"node:child_process";import{existsSync as Hl,mkdirSync as Kl,readFileSync as Vo,realpathSync as Gl,writeFileSync as Vl}from"node:fs";import{join as He,resolve as Wl,sep as Jl}from"node:path";import{createServer as Ll}from"node:net";import{connect as Fl}from"node:net";function Ko(e,t=500){return new Promise(n=>{let r=Fl({port:e,host:"127.0.0.1"}),s=o=>{r.destroy(),n(o)};r.setTimeout(t,()=>s(!1)),r.once("connect",()=>s(!0)),r.once("error",()=>s(!1))})}var Ml={ingressHttp:{start:8080,end:8180},ingressHttps:{start:8443,end:8543},postgres:{start:15432,end:15532}},gt={ingressHttp:"TDK_HTTP_PORT",ingressHttps:"TDK_HTTPS_PORT",postgres:"TDK_POSTGRES_PORT"},Mn={ingressHttp:80,ingressHttps:443,postgres:5432},Un={ingressHttp:Mn.ingressHttp,ingressHttps:Mn.ingressHttps};function Ul(e,t){return e==="EACCES"&&t==="darwin"}async function Bn(e){return await Ko(e)?!1:new Promise(t=>{let n=Ll();n.once("error",r=>{t(Ul(r.code,process.platform))}),n.listen(e,"127.0.0.1",()=>n.close(()=>t(!0)))})}function Bl(e,t){let n=Number(t);if(!Number.isInteger(n)||n<1||n>65535)throw new Error(`${e} must be an integer between 1 and 65535 (received ${JSON.stringify(t)})`);return n}async function ye(e={}){let t=e.env??process.env,n=e.isAvailable??Bn,r={ingressHttp:!1,ingressHttps:!1,postgres:!1},s={ingressHttp:"",ingressHttps:"",postgres:""},o={explicit:r},i=new Set;for(let a of["ingressHttp","ingressHttps","postgres"]){let c=t[gt[a]],u=c!==void 0&&c.trim()!=="",d=e.ranges?.[a]??Ml[a],l=Un[a],p=u?[Bl(gt[a],c)]:[...l===void 0?[]:[l],...Array.from({length:d.end-d.start+1},(f,b)=>d.start+b)],h;for(let f of p)if(!i.has(f)){if(await n(f)){h=f;break}if(u)throw new Error(`${gt[a]}=${f} is already in use. Choose a free host port and retry.`)}if(h===void 0)throw new Error(`No available host port in ${d.start}-${d.end} for ${a}. Set ${gt[a]} to a free port and retry.`);i.add(h),o[a]=h,r[a]=u,s[a]=u?"explicit override":h===l?"requested port is free":`selected from fallback range ${d.start}-${d.end}`}return{...o,requested:{...Mn},reason:s}}function Vg(e){return`Host ports: HTTP ${e.ingressHttp}, HTTPS ${e.ingressHttps}, Postgres ${e.postgres}`}var Wo=He(".tdk",".tdk-out","host-ports.json");function ql(e,t,n){return e.split(`
339
- `).some(r=>{let[s="",o=""]=r.split("|"),i=s.toLowerCase(),a=t.toLowerCase();return(i.startsWith(`${a}_`)||i.startsWith(`${a}-`))&&o.includes(`:${n}->`)})}function Jo(e){let t=He(e,Wo);if(!Hl(t))return null;try{let n=JSON.parse(Vo(t,"utf-8"));if(!n||typeof n!="object")return null;let r=n;return!Number.isInteger(r.ingressHttp)||!Number.isInteger(r.ingressHttps)||!Number.isInteger(r.postgres)||!r.requested||!r.explicit||!r.reason?null:r}catch{return null}}function Qg(e,t){let n=He(e,Wo);Kl(He(e,".tdk",".tdk-out"),{recursive:!0}),Vl(n,`${JSON.stringify(t,null,2)}
340
- `,{encoding:"utf-8",mode:384})}function Zg(e){process.env.TDK_HTTP_PORT=String(e.ingressHttp),process.env.TDK_HTTPS_PORT=String(e.ingressHttps),process.env.TDK_POSTGRES_PORT=String(e.postgres)}var zl="com.docker.compose.project.working_dir";function Yl(e,t,n){let r=new Set([Wl(t)]);try{r.add(Gl(t))}catch{}return e.split(`
341
- `).some(s=>{let[,o="",i=""]=s.split("|");return!i||!o.includes(`:${n}->`)?!1:[...r].some(a=>i===a||i.startsWith(`${a}${Jl}`))})}function qo(e,t,n=()=>Go("docker",["ps","--format",`{{.Names}}|{{.Ports}}|{{.Label "${zl}"}}`],{encoding:"utf-8",timeout:5e3})){let r=Jo(e);if(!r||r.ingressHttp===t)return t;try{if(Yl(n(),e,r.ingressHttp))return r.ingressHttp}catch{}return t}async function kt(e,t={}){let n=Jo(e),r=["TDK_HTTP_PORT","TDK_HTTPS_PORT","TDK_POSTGRES_PORT"].some(u=>process.env[u]);if(t.inspectDocker===!1&&n&&!r)return n;let s="";try{let u=JSON.parse(Vo(He(e,".tdk",_),"utf-8"));s=String(u?.project?.name??"tdk-project").replace(/-/g,"_").toLowerCase()}catch{s="tdk_project"}let o="";if(t.inspectDocker!==!1)try{o=Go("docker",["ps","--format","{{.Names}}|{{.Ports}}"],{encoding:"utf-8",timeout:5e3})}catch{}let i=u=>ql(o,s,u),a=t.isPortFree??Bn,c=async u=>await a(u)||i(u);if(n&&!r){for(let u of[n.ingressHttp,n.ingressHttps,n.postgres])if(!await c(u))return ye({isAvailable:c});for(let[u,d]of Object.entries(Un)){let l=n[u];if(d!==void 0&&l!==d&&await c(d))return ye({isAvailable:c})}return n}return ye({isAvailable:c})}import{stdin as Xl,stdout as Ql}from"node:process";import{createInterface as Zl}from"node:readline/promises";async function yt(e){let t=Zl({input:Xl,output:Ql});try{return await new Promise((n,r)=>{t.once("close",()=>r(new Error("No input available to answer the prompt. Run this in a terminal."))),t.question(e).then(s=>n(s.trim()),r)})}finally{t.close()}}async function rk(e){let t=e.initial?` (${e.initial})`:"";for(;;){let r=await yt(`${e.message}${t} `)||e.initial||"",s=e.validate?.(r)??!0;if(s===!0)return r;console.log(s)}}async function zo(e){let t=e.initial??!0,n=t?"Y/n":"y/N";for(;;){let r=(await yt(`${e.message} (${n}) `)).toLowerCase();if(!r)return t;if(["y","yes"].includes(r))return!0;if(["n","no"].includes(r))return!1;console.log("Please answer yes or no.")}}async function sk(e){for(console.log(e.message),e.choices.forEach((t,n)=>{console.log(` ${n+1}. ${t.title}`)});;){let t=await yt("Choose one: "),n=Number.parseInt(t,10)-1,r=e.choices[n];if(r)return r.value;console.log(`Enter a number from 1 to ${e.choices.length}.`)}}async function ok(e){let t=e.choices.map((r,s)=>r.selected?s+1:null).filter(r=>r!==null),n=t.length>0?` [${t.join(",")}]`:"";for(console.log(e.message),e.choices.forEach((r,s)=>{let o=r.selected?"*":" ";console.log(` ${o} ${s+1}. ${r.title}`)});;){let r=await yt(`Choose one or more numbers, comma-separated${n}: `),s=r?r.split(",").map(a=>Number.parseInt(a.trim(),10)):t,o=Array.from(new Set(s)).map(a=>e.choices[a-1]).filter(a=>!!a).map(a=>a.value),i=e.validate?.(o)??!0;if(i===!0)return o;console.log(i)}}import{relative as ed}from"node:path";function St(e,t){return ed(e,t.configPath)||t.configPath}function Yo(e){let t=e.config?.dependsOn;return t===void 0?[]:Array.isArray(t)&&t.every(n=>typeof n=="string")?t:null}function td(e){let t=new Set(e.map(a=>a.name)),n=new Map(e.map(a=>[a.name,(Yo(a)??[]).filter(c=>t.has(c))])),r=new Map,s=new Map,o=[],i=a=>{s.set(a,"visiting"),o.push(a);for(let c of n.get(a)??[])if(s.get(c)==="visiting"){let u=o.slice(o.indexOf(c)),d=u.indexOf([...u].sort()[0]??c),l=[...u.slice(d),...u.slice(0,d)];r.set(l.join(">"),[...l,l[0]??c])}else s.has(c)||i(c);o.pop(),s.set(a,"done")};for(let a of[...n.keys()].sort())s.has(a)||i(a);return[...r.values()]}function Hn(e=y()??process.cwd()){let t=x(e).flatMap(n=>Yo(n)===null?[`${St(e,n)} dependsOn ${JSON.stringify(n.config?.dependsOn)}: expected an array of service names`]:[]);return t.length===0?{name:"dependsOn",didPass:!0,message:"Every dependsOn is a list of service names"}:{name:"dependsOn",didPass:!1,message:`${T(t.length,"invalid dependsOn","invalid dependsOn")}:
409
+ `)}`,fix:"Move the migration into a `migrator` resource (appType migrator) that the service depends on, so it runs once before the service starts instead of on every start and restart"}}function ht(e=y()??process.cwd()){let t=x(e).filter(r=>r.config?.featuresEnabled?.includes("nats")).map(r=>r.name);if(t.length===0)return{name:"NATS broker",didPass:!0,message:"No resource enables the nats feature",isSkipped:!0};if(Fn(M(e,"services","platform","messaging",se)))return{name:"NATS broker",didPass:!0,message:`${T(t.length,"resource")} enable nats and services/platform/messaging/docker-compose.yml is present`};let n=(Ro(e)??"project").replace(/-/g,"_");return{name:"NATS broker",didPass:!1,message:`${t.join(", ")} enable the nats feature, but no NATS server will start: TDK only starts one when services/platform/messaging/docker-compose.yml exists, and it does not generate that file`,fix:`Create it with a "nats" service (image nats with -js, container_name ${n}_nats, network ${n}_backend, external) and a "redis" service, which TDK registers alongside it`}}function Bo(e=y()??process.cwd()){let t=jn(e),n=" (project resource set; tdk up may select a subset and not start Postgres)",r=t.focusWouldEnableDatabaseManagement?" Warning: generated Tiltfile default focus expands CORE_INFRA to database-management while project.json has it off; default tdk up takes the feature path.":"";if(t.unknownDependsOnNames.length>0){let o=t.unknownDependsOnNames.map(({resource:a,name:c})=>`"${c}" (from ${a})`).join(", "),i=t.willStart?` Postgres will start because ${t.reason==="feature"?"database-management is enabled":`resource(s) ${t.dependsOnUsers.join(", ")} depend on postgres/database-management`}${n}`:" Postgres will not start for this project.json/generated Tiltfile state.";return{name:"Shared platform Postgres",didPass:!1,message:`${T(t.unknownDependsOnNames.length,"unknown dependsOn name")}: ${o}. These are not known services or stacks, and are not the shared platform database names (postgres, database-management).${i}${r}`,fix:'Use "postgres" or "database-management" in dependsOn for the shared platform database, or fix the name to match an existing service'}}if(!t.willStart)return{name:"Shared platform Postgres",didPass:!0,isWarning:!!r,isSkipped:!r,message:r?r.trim():"Shared platform Postgres will not start: database-management is off and no resource depends on postgres or database-management."};if(t.reason==="feature"&&t.dependsOnUsers.length===0){let o=t.featureOnFromTiltfile||t.featureOnFromSpecMaster?" (generated Tiltfile/spec.master)":"";return{name:"Shared platform Postgres",didPass:!0,isWarning:!!r,message:`Shared platform Postgres will start because the database-management feature is enabled${o} (project-wide; not a tdk up selection).${r}`}}let s=t.reason==="feature"?`the database-management feature is enabled and resource(s) ${t.dependsOnUsers.join(", ")} depend on postgres/database-management`:`resource(s) ${t.dependsOnUsers.join(", ")} depend on postgres/database-management`;return{name:"Shared platform Postgres",didPass:!0,isWarning:!!r,message:`Shared platform Postgres will start because ${s}${n}${r}`}}function Ld(e){let t=[];for(let n of e.split(`
410
+ `)){let r=n.match(/^\s*(\d+)\s+.*\btilt up\b.*?\s-f\s+(\S+)/i);r&&t.push({pid:Number(r[1]),root:r[2].split(/[\\/]\.tdk[\\/]/i)[0]})}return t}function Ho(e=y()??process.cwd(),t=bd){let n;try{n=process.platform==="win32"?Sd("powershell.exe",["-NoProfile","-Command","Get-CimInstance Win32_Process | Where-Object { $_.Name -eq 'tilt.exe' } | ForEach-Object { '{0} {1}' -f $_.ProcessId, $_.CommandLine }"],{encoding:"utf-8",timeout:pt,windowsHide:!0}):t("ps -Ao pid=,command=",{encoding:"utf-8",timeout:pt})}catch{return{name:"Tilt processes",didPass:!0,isSkipped:!0,message:"Could not list processes"}}let r=Ld(n),s=r.filter(i=>i.root===e),o=r.filter(i=>i.root!==e);return s.length>1?{name:"Tilt processes",didPass:!1,message:`${s.length} Tilt processes are running for this project (pids ${s.map(i=>i.pid).join(", ")}). They fight over ports and containers`,fix:`Stop them all, then start one: tdk down && kill ${s.map(i=>i.pid).join(" ")} && tdk up`}:o.length>0?{name:"Tilt processes",didPass:!0,isSkipped:!0,message:`Another project's Tilt is running: ${o.map(a=>`${a.root} (pid ${a.pid})`).join(", ")}`,fix:"tdk up will use the next free Tilt UI port (10351, ...). If it is a leftover, run tdk down in that project"}:{name:"Tilt processes",didPass:!0,message:"No stray Tilt processes"}}async function Go(e=V){let t=`tdk_doctor_probe_${process.pid}`;try{await e(`docker network create ${t}`,pt)}catch(n){let r=String(n.stderr??n);return/address pools/i.test(r)?{name:"Docker networks",didPass:!1,message:"Docker cannot create another network: all predefined address pools are in use. Each TDK project needs several",fix:"run tdk down --prune-networks in projects you are not using, or docker network prune (removes all unused networks)"}:{name:"Docker networks",didPass:!0,isSkipped:!0,message:"Could not test network creation"}}try{await e(`docker network rm ${t}`,pt)}catch{}return{name:"Docker networks",didPass:!0,message:"Docker can create networks"}}import{execFileSync as Vo}from"node:child_process";import{existsSync as Kd,mkdirSync as Vd,readFileSync as Wo,realpathSync as Wd,writeFileSync as Jd}from"node:fs";import{join as He,resolve as qd,sep as zd}from"node:path";import{createServer as Ud}from"node:net";import{connect as Md}from"node:net";function Ko(e,t=500){return new Promise(n=>{let r=Md({port:e,host:"127.0.0.1"}),s=o=>{r.destroy(),n(o)};r.setTimeout(t,()=>s(!1)),r.once("connect",()=>s(!0)),r.once("error",()=>s(!1))})}var Bd={ingressHttp:{start:8080,end:8180},ingressHttps:{start:8443,end:8543},postgres:{start:15432,end:15532}},gt={ingressHttp:"TDK_HTTP_PORT",ingressHttps:"TDK_HTTPS_PORT",postgres:"TDK_POSTGRES_PORT"},Mn={ingressHttp:80,ingressHttps:443,postgres:5432},Un={ingressHttp:Mn.ingressHttp,ingressHttps:Mn.ingressHttps};function Hd(e,t){return e==="EACCES"&&t==="darwin"}async function Bn(e){return await Ko(e)?!1:new Promise(t=>{let n=Ud();n.once("error",r=>{t(Hd(r.code,process.platform))}),n.listen(e,"127.0.0.1",()=>n.close(()=>t(!0)))})}function Gd(e,t){let n=Number(t);if(!Number.isInteger(n)||n<1||n>65535)throw new Error(`${e} must be an integer between 1 and 65535 (received ${JSON.stringify(t)})`);return n}async function ye(e={}){let t=e.env??process.env,n=e.isAvailable??Bn,r={ingressHttp:!1,ingressHttps:!1,postgres:!1},s={ingressHttp:"",ingressHttps:"",postgres:""},o={explicit:r},i=new Set;for(let a of["ingressHttp","ingressHttps","postgres"]){let c=t[gt[a]],l=c!==void 0&&c.trim()!=="",u=e.ranges?.[a]??Bd[a],d=Un[a],p=l?[Gd(gt[a],c)]:[...d===void 0?[]:[d],...Array.from({length:u.end-u.start+1},(f,b)=>u.start+b)],h;for(let f of p)if(!i.has(f)){if(await n(f)){h=f;break}if(l)throw new Error(`${gt[a]}=${f} is already in use. Choose a free host port and retry.`)}if(h===void 0)throw new Error(`No available host port in ${u.start}-${u.end} for ${a}. Set ${gt[a]} to a free port and retry.`);i.add(h),o[a]=h,r[a]=l,s[a]=l?"explicit override":h===d?"requested port is free":`selected from fallback range ${u.start}-${u.end}`}return{...o,requested:{...Mn},reason:s}}function zg(e){return`Host ports: HTTP ${e.ingressHttp}, HTTPS ${e.ingressHttps}, Postgres ${e.postgres}`}var Jo=He(".tdk",".tdk-out","host-ports.json");function Yd(e,t,n){return e.split(`
411
+ `).some(r=>{let[s="",o=""]=r.split("|"),i=s.toLowerCase(),a=t.toLowerCase();return(i.startsWith(`${a}_`)||i.startsWith(`${a}-`))&&o.includes(`:${n}->`)})}function qo(e){let t=He(e,Jo);if(!Kd(t))return null;try{let n=JSON.parse(Wo(t,"utf-8"));if(!n||typeof n!="object")return null;let r=n;return!Number.isInteger(r.ingressHttp)||!Number.isInteger(r.ingressHttps)||!Number.isInteger(r.postgres)||!r.requested||!r.explicit||!r.reason?null:r}catch{return null}}function nk(e,t){let n=He(e,Jo);Vd(He(e,".tdk",".tdk-out"),{recursive:!0}),Jd(n,`${JSON.stringify(t,null,2)}
412
+ `,{encoding:"utf-8",mode:384})}function rk(e){process.env.TDK_HTTP_PORT=String(e.ingressHttp),process.env.TDK_HTTPS_PORT=String(e.ingressHttps),process.env.TDK_POSTGRES_PORT=String(e.postgres)}var Xd="com.docker.compose.project.working_dir";function Qd(e,t,n){let r=new Set([qd(t)]);try{r.add(Wd(t))}catch{}return e.split(`
413
+ `).some(s=>{let[,o="",i=""]=s.split("|");return!i||!o.includes(`:${n}->`)?!1:[...r].some(a=>i===a||i.startsWith(`${a}${zd}`))})}function zo(e,t,n=()=>Vo("docker",["ps","--format",`{{.Names}}|{{.Ports}}|{{.Label "${Xd}"}}`],{encoding:"utf-8",timeout:5e3})){let r=qo(e);if(!r||r.ingressHttp===t)return t;try{if(Qd(n(),e,r.ingressHttp))return r.ingressHttp}catch{}return t}async function kt(e,t={}){let n=qo(e),r=["TDK_HTTP_PORT","TDK_HTTPS_PORT","TDK_POSTGRES_PORT"].some(l=>process.env[l]);if(t.inspectDocker===!1&&n&&!r)return n;let s="";try{let l=JSON.parse(Wo(He(e,".tdk",_),"utf-8"));s=String(l?.project?.name??"tdk-project").replace(/-/g,"_").toLowerCase()}catch{s="tdk_project"}let o="";if(t.inspectDocker!==!1)try{o=Vo("docker",["ps","--format","{{.Names}}|{{.Ports}}"],{encoding:"utf-8",timeout:5e3})}catch{}let i=l=>Yd(o,s,l),a=t.isPortFree??Bn,c=async l=>await a(l)||i(l);if(n&&!r){for(let l of[n.ingressHttp,n.ingressHttps,n.postgres])if(!await c(l))return ye({isAvailable:c});for(let[l,u]of Object.entries(Un)){let d=n[l];if(u!==void 0&&d!==u&&await c(u))return ye({isAvailable:c})}return n}return ye({isAvailable:c})}import{stdin as Zd,stdout as eu}from"node:process";import{createInterface as tu}from"node:readline/promises";async function yt(e){let t=tu({input:Zd,output:eu});try{return await new Promise((n,r)=>{t.once("close",()=>r(new Error("No input available to answer the prompt. Run this in a terminal."))),t.question(e).then(s=>n(s.trim()),r)})}finally{t.close()}}async function ak(e){let t=e.initial?` (${e.initial})`:"";for(;;){let r=await yt(`${e.message}${t} `)||e.initial||"",s=e.validate?.(r)??!0;if(s===!0)return r;console.log(s)}}async function Yo(e){let t=e.initial??!0,n=t?"Y/n":"y/N";for(;;){let r=(await yt(`${e.message} (${n}) `)).toLowerCase();if(!r)return t;if(["y","yes"].includes(r))return!0;if(["n","no"].includes(r))return!1;console.log("Please answer yes or no.")}}async function ck(e){for(console.log(e.message),e.choices.forEach((t,n)=>{console.log(` ${n+1}. ${t.title}`)});;){let t=await yt("Choose one: "),n=Number.parseInt(t,10)-1,r=e.choices[n];if(r)return r.value;console.log(`Enter a number from 1 to ${e.choices.length}.`)}}async function lk(e){let t=e.choices.map((r,s)=>r.selected?s+1:null).filter(r=>r!==null),n=t.length>0?` [${t.join(",")}]`:"";for(console.log(e.message),e.choices.forEach((r,s)=>{let o=r.selected?"*":" ";console.log(` ${o} ${s+1}. ${r.title}`)});;){let r=await yt(`Choose one or more numbers, comma-separated${n}: `),s=r?r.split(",").map(a=>Number.parseInt(a.trim(),10)):t,o=Array.from(new Set(s)).map(a=>e.choices[a-1]).filter(a=>!!a).map(a=>a.value),i=e.validate?.(o)??!0;if(i===!0)return o;console.log(i)}}import{relative as nu}from"node:path";function St(e,t){return nu(e,t.configPath)||t.configPath}function Xo(e){let t=e.config?.dependsOn;return t===void 0?[]:Array.isArray(t)&&t.every(n=>typeof n=="string")?t:null}function ru(e){let t=new Set(e.map(a=>a.name)),n=new Map(e.map(a=>[a.name,(Xo(a)??[]).filter(c=>t.has(c))])),r=new Map,s=new Map,o=[],i=a=>{s.set(a,"visiting"),o.push(a);for(let c of n.get(a)??[])if(s.get(c)==="visiting"){let l=o.slice(o.indexOf(c)),u=l.indexOf([...l].sort()[0]??c),d=[...l.slice(u),...l.slice(0,u)];r.set(d.join(">"),[...d,d[0]??c])}else s.has(c)||i(c);o.pop(),s.set(a,"done")};for(let a of[...n.keys()].sort())s.has(a)||i(a);return[...r.values()]}function Hn(e=y()??process.cwd()){let t=x(e).flatMap(n=>Xo(n)===null?[`${St(e,n)} dependsOn ${JSON.stringify(n.config?.dependsOn)}: expected an array of service names`]:[]);return t.length===0?{name:"dependsOn",didPass:!0,message:"Every dependsOn is a list of service names"}:{name:"dependsOn",didPass:!1,message:`${T(t.length,"invalid dependsOn","invalid dependsOn")}:
342
414
  ${t.join(`
343
- `)}`,fix:'Write "dependsOn" as an array of service names, for example ["postgres", "api"]'}}function Kn(e=y()??process.cwd()){let t=x(e),n=new Map(t.map(o=>[o.name,o])),r=td(t);if(r.length===0)return{name:"Circular dependencies",didPass:!0,message:"No service depends on itself through dependsOn"};let s=r.map(o=>{let i=n.get(o[0]??""),a=o[1]??"";return`${i?St(e,i):o[0]} dependsOn "${a}": circular dependency ${o.join(" -> ")}`});return{name:"Circular dependencies",didPass:!1,message:`${r.length} ${r.length===1?"circular dependency":"circular dependencies"}:
415
+ `)}`,fix:'Write "dependsOn" as an array of service names, for example ["postgres", "api"]'}}function Gn(e=y()??process.cwd()){let t=x(e),n=new Map(t.map(o=>[o.name,o])),r=ru(t);if(r.length===0)return{name:"Circular dependencies",didPass:!0,message:"No service depends on itself through dependsOn"};let s=r.map(o=>{let i=n.get(o[0]??""),a=o[1]??"";return`${i?St(e,i):o[0]} dependsOn "${a}": circular dependency ${o.join(" -> ")}`});return{name:"Circular dependencies",didPass:!1,message:`${r.length} ${r.length===1?"circular dependency":"circular dependencies"}:
344
416
  ${s.join(`
345
- `)}`,fix:'Remove one "dependsOn" entry in each cycle so the services no longer wait on each other, or move what they share into a third service'}}function Gn(e=y()??process.cwd()){let t=x(e).flatMap(n=>{let r=n.config?.port;return r===void 0?[]:typeof r=="number"&&Number.isInteger(r)&&r>=1&&r<=65535?[]:[`${St(e,n)} port ${JSON.stringify(r)}: not an integer from 1 to 65535`]});return t.length===0?{name:"Service ports",didPass:!0,message:"Every declared port is valid"}:{name:"Service ports",didPass:!1,message:`${T(t.length,"invalid port")}:
417
+ `)}`,fix:'Remove one "dependsOn" entry in each cycle so the services no longer wait on each other, or move what they share into a third service'}}function Kn(e=y()??process.cwd()){let t=x(e).flatMap(n=>{let r=n.config?.port;return r===void 0?[]:typeof r=="number"&&Number.isInteger(r)&&r>=1&&r<=65535?[]:[`${St(e,n)} port ${JSON.stringify(r)}: not an integer from 1 to 65535`]});return t.length===0?{name:"Service ports",didPass:!0,message:"Every declared port is valid"}:{name:"Service ports",didPass:!1,message:`${T(t.length,"invalid port")}:
346
418
  ${t.join(`
347
419
  `)}`,fix:'Set "port" to the port the service listens on, an integer from 1 to 65535'}}function Vn(e=y()??process.cwd(),t=!1){let n=[],r=[];for(let o of x(e)){let i=o.config?.schemaVersion;if(i===Re)continue;let a=St(e,o);i===void 0?n.push(`${a} schemaVersion: missing`):r.push(`${a} schemaVersion ${JSON.stringify(i)}: this tdk supports ${Re}`)}if(n.length===0&&r.length===0)return{name:"schemaVersion",didPass:!0,message:"Every service.json has a supported schemaVersion"};let s=[...n.length>0?["Run `tdk config migrate` to add the missing schemaVersion"]:[],...r.length>0?["A version this tdk does not support cannot be migrated: upgrade tdk"]:[]];return{name:"schemaVersion",didPass:!1,isWarning:!t,message:`${T(n.length+r.length,"service.json file")} without a supported schemaVersion:
348
420
  ${[...n,...r].join(`
349
- `)}`,fix:s.join(". ")}}function mk(e){let t=Vn(e);t.didPass||(console.warn(m.yellow(`\u26A0 ${t.message}`)),t.fix&&console.warn(m.gray(` ${t.fix}`)))}function hk(e,t={},n=process.exit){let r=[ft(e),Hn(e),Kn(e),Gn(e)].filter(o=>!o.didPass);if(r.length===0)return;let s=r.map(o=>`${o.message}${o.fix?`
421
+ `)}`,fix:s.join(". ")}}function yk(e){let t=Vn(e);t.didPass||(console.warn(m.yellow(`\u26A0 ${t.message}`)),t.fix&&console.warn(m.gray(` ${t.fix}`)))}function Sk(e,t={},n=process.exit){let r=[ft(e),Hn(e),Gn(e),Kn(e)].filter(o=>!o.didPass);if(r.length===0)return;let s=r.map(o=>`${o.message}${o.fix?`
350
422
  Fix: ${o.fix}`:""}`).join(`
351
- `);t.onInvalid?.(s);for(let o of r)console.error(m.red(`\u2717 ${o.message}`)),o.fix&&console.error(m.gray(` Fix: ${o.fix}`));n(1)}import{readFileSync as nd}from"node:fs";import{join as rd}from"node:path";function Xo(e){let t=e.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);return t?[Number(t[1]),Number(t[2]),Number(t[3]??0)]:null}function sd(e){try{return JSON.parse(nd(rd(e,".tdk",_),"utf-8"))?.minTdkVersion}catch{return}}function Qo(e,t){let n=sd(e);if(n===void 0)return{status:"none"};let r=typeof n=="string"?Xo(n):null;if(!r||!/^\d+\.\d+\.\d+$/.test(String(n).trim()))return{status:"malformed",message:`.tdk/project.json minTdkVersion ${JSON.stringify(n)} is not a version like "1.3.80"`,fix:'Set minTdkVersion to a MAJOR.MINOR.PATCH string, for example "1.3.80".'};let s=Xo(t),o=s!==null&&(()=>{for(let[a,c]of r.entries()){let u=s[a]??0;if(u!==c)return u>c}return!0})(),i=r.join(".");return o?{status:"ok",required:i}:{status:"too-old",required:i,message:`tdk ${t} is older than the ${i} this project requires (minTdkVersion)`,fix:"Run: tdk upgrade"}}var z=1e4,ae={dockerMissing:"See https://docs.docker.com/get-docker/",dockerDaemonDown:"Start Docker Desktop, OrbStack, or Colima, then retry: tdk doctor",tiltMissing:"curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash",bunMissing:"curl -fsSL https://bun.sh/install | bash",port80:"Stop the process bound to port 80, or stop local nginx/caddy. Then: tdk doctor",port5432:"Stop local Postgres or change the host port. Then: tdk doctor",notProject:"tdk project --yes"},ei="WSL2 detected. Use Docker Desktop WSL integration. Guide: docs/wsl2.md",ti="Native Windows landscape boot is unsupported. Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md",Wn=[0,25,0],ce=[1,2,0];function bt(e,t){let n=Yn(e);return n?Xn(n,t):!1}function cd(e,t,n=process.platform==="linux"&&!!process.env.WSL_DISTRO_NAME){if(!n)return{name:"WSL project location",didPass:!0,isSkipped:!0,message:"Not running in WSL2 - skipped project filesystem check"};let r=e.replace(/\\/g,"/").replace(/\/+$/,"").toLowerCase();if(r!=="/mnt/c"&&!r.startsWith("/mnt/c/"))return{name:"WSL project location",didPass:!0,message:`${ei} Project is on the WSL filesystem.`};let s=`${ei} Project is under /mnt/c (${e}); hot reload may be broken. Move it into the WSL filesystem, such as ~/projects.`;return{name:"WSL project location",didPass:!t,isWarning:!t,message:s,fix:"Move the repository under your WSL home directory (for example, ~/projects) and retry tdk doctor."}}function ud(e){let t=e.replace(/^\[(.*)\]$/,"$1");return t==="0.0.0.0"||/^[0:]*:0\.0\.0\.0$/.test(t)?!0:t.includes(":")&&/^[0:]+$/.test(t)}function ld(e=process.env,t=!1){let n=(e.TDK_BIND_ADDRESS??"").trim();return ud(n)?{name:"Dev Port Bind Address",didPass:!t,isWarning:!t,message:`TDK_BIND_ADDRESS is ${n}: Traefik and Postgres are reachable from other machines on the network.`,fix:"Unset TDK_BIND_ADDRESS to keep dev ports on 127.0.0.1. Keep it only when you test from another device on purpose."}:{name:"Dev Port Bind Address",didPass:!0,message:n?`Dev ports bind to ${n}`:"Dev ports bind to 127.0.0.1 (this machine only)"}}function ni(e){let t=e.filter(r=>!r.didPass&&!r.isSkipped&&!r.isWarning),n=e.filter(r=>r.didPass||r.isSkipped||r.isWarning);return t.sort((r,s)=>{let o=i=>i.name==="Host Ports"&&/\b5432\b/.test(i.message)?0:i.name==="Host Ports"?1:i.name==="Ingress Ports"?2:3;return o(r)-o(s)}),[...t,...n]}function dd(e,t){return t?e?"Doctor passed. Next: tdk up":"Doctor passed. Next: tdk project example":"Doctor failed. Fix the items above, then run: tdk doctor"}function Zn(e){return So(e)}function pd(e,t,n,r,s){return async(o=V)=>{try{return await o(t,z),{name:e,didPass:!0,message:n}}catch(i){return Zn(i)?{name:e,didPass:!1,message:`${e} did not respond within ${z/1e3}s`,fix:s}:{name:e,didPass:!1,message:r,fix:s}}}}async function Jn(e){try{return await V(e,z),!0}catch{return!1}}async function er(){if(process.platform==="win32")try{return await V("docker ps",z),{name:B,didPass:!0,message:"Docker Desktop Linux container engine is running"}}catch{return{name:B,didPass:!1,message:"Docker is not running",fix:ae.dockerDaemonDown}}let e=!!O("docker");try{return await V("docker ps",z),{name:B,didPass:!0,message:"Docker daemon is running"}}catch(n){if(Zn(n))return{name:B,didPass:!1,message:"Docker daemon is not responding",fix:ae.dockerDaemonDown}}let t=Ys(await Jn("pgrep -f com.docker.backend"));return t||(await Jn("colima status")?{name:B,didPass:!0,message:"Colima (Docker runtime) is running"}:O("colima")?{name:B,didPass:!1,message:"Colima is installed but not running",fix:ae.dockerDaemonDown}:await Jn("podman ps")?{name:B,didPass:!0,message:"Podman is running"}:e?{name:B,didPass:!1,message:"Docker daemon is not running",fix:ae.dockerDaemonDown}:{name:B,didPass:!1,message:"Docker is not running",fix:ae.dockerMissing})}var tr=pd("Docker Compose","docker compose version","Docker Compose plugin available","Docker Compose plugin not found","Install Docker Compose: https://docs.docker.com/compose/install/"),fd=[25,0,0],md=[2,20,2];function Yn(e){let t=e.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);return t?[Number(t[1]),Number(t[2]),Number(t[3]??0)]:null}function Xn(e,t){for(let[n,r]of t.entries()){let s=e[n]??0;if(s!==r)return s>r}return!0}async function nr(e=V){let t=async a=>String(await e(a,z)).trim(),n,r;try{[n,r]=await Promise.all([t("docker version --format '{{.Server.Version}}'"),t("docker compose version --short")])}catch{return{name:"Docker Versions",didPass:!0,isSkipped:!0,message:"Could not read Docker Engine/Compose versions - skipped version check"}}let s=Yn(n),o=Yn(r);if(!s||!o)return{name:"Docker Versions",didPass:!0,isSkipped:!0,message:`Unrecognized Docker version output (engine "${n}", compose "${r}") - skipped version check`};let i=[];return Xn(s,fd)||i.push(`Docker Engine ${n} (need 25.0+)`),Xn(o,md)||i.push(`Docker Compose ${r} (need 2.20.2+)`),i.length===0?{name:"Docker Versions",didPass:!0,message:`Docker Engine ${n} and Compose ${r} support generated healthchecks`}:{name:"Docker Versions",didPass:!1,message:`Docker is too old for generated healthchecks (they use start_interval):
423
+ `);t.onInvalid?.(s);for(let o of r)console.error(m.red(`\u2717 ${o.message}`)),o.fix&&console.error(m.gray(` Fix: ${o.fix}`));n(1)}import{readFileSync as su}from"node:fs";import{join as ou}from"node:path";function Qo(e){let t=e.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);return t?[Number(t[1]),Number(t[2]),Number(t[3]??0)]:null}function iu(e){try{return JSON.parse(su(ou(e,".tdk",_),"utf-8"))?.minTdkVersion}catch{return}}function Zo(e,t){let n=iu(e);if(n===void 0)return{status:"none"};let r=typeof n=="string"?Qo(n):null;if(!r||!/^\d+\.\d+\.\d+$/.test(String(n).trim()))return{status:"malformed",message:`.tdk/project.json minTdkVersion ${JSON.stringify(n)} is not a version like "1.3.80"`,fix:'Set minTdkVersion to a MAJOR.MINOR.PATCH string, for example "1.3.80".'};let s=Qo(t),o=s!==null&&(()=>{for(let[a,c]of r.entries()){let l=s[a]??0;if(l!==c)return l>c}return!0})(),i=r.join(".");return o?{status:"ok",required:i}:{status:"too-old",required:i,message:`tdk ${t} is older than the ${i} this project requires (minTdkVersion)`,fix:"Run: tdk upgrade"}}var z=1e4,ae={dockerMissing:"See https://docs.docker.com/get-docker/",dockerDaemonDown:"Start Docker Desktop, OrbStack, or Colima, then retry: tdk doctor",tiltMissing:"curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash",bunMissing:"curl -fsSL https://bun.sh/install | bash",port80:"Stop the process bound to port 80, or stop local nginx/caddy. Then: tdk doctor",port5432:"Stop local Postgres or change the host port. Then: tdk doctor",notProject:"tdk project --yes"},ti="WSL2 detected. Use Docker Desktop WSL integration. Guide: docs/wsl2.md",ni="Native Windows landscape boot is unsupported. Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md",Wn=[0,25,0],ce=[1,2,0];function bt(e,t){let n=Yn(e);return n?Xn(n,t):!1}function du(e,t,n=process.platform==="linux"&&!!process.env.WSL_DISTRO_NAME){if(!n)return{name:"WSL project location",didPass:!0,isSkipped:!0,message:"Not running in WSL2 - skipped project filesystem check"};let r=e.replace(/\\/g,"/").replace(/\/+$/,"").toLowerCase();if(r!=="/mnt/c"&&!r.startsWith("/mnt/c/"))return{name:"WSL project location",didPass:!0,message:`${ti} Project is on the WSL filesystem.`};let s=`${ti} Project is under /mnt/c (${e}); hot reload may be broken. Move it into the WSL filesystem, such as ~/projects.`;return{name:"WSL project location",didPass:!t,isWarning:!t,message:s,fix:"Move the repository under your WSL home directory (for example, ~/projects) and retry tdk doctor."}}function uu(e){let t=e.replace(/^\[(.*)\]$/,"$1");return t==="0.0.0.0"||/^[0:]*:0\.0\.0\.0$/.test(t)?!0:t.includes(":")&&/^[0:]+$/.test(t)}function pu(e=process.env,t=!1){let n=(e.TDK_BIND_ADDRESS??"").trim();return uu(n)?{name:"Dev Port Bind Address",didPass:!t,isWarning:!t,message:`TDK_BIND_ADDRESS is ${n}: Traefik and Postgres are reachable from other machines on the network.`,fix:"Unset TDK_BIND_ADDRESS to keep dev ports on 127.0.0.1. Keep it only when you test from another device on purpose."}:{name:"Dev Port Bind Address",didPass:!0,message:n?`Dev ports bind to ${n}`:"Dev ports bind to 127.0.0.1 (this machine only)"}}function ri(e){let t=e.filter(r=>!r.didPass&&!r.isSkipped&&!r.isWarning),n=e.filter(r=>r.didPass||r.isSkipped||r.isWarning);return t.sort((r,s)=>{let o=i=>i.name==="Host Ports"&&/\b5432\b/.test(i.message)?0:i.name==="Host Ports"?1:i.name==="Ingress Ports"?2:3;return o(r)-o(s)}),[...t,...n]}function fu(e,t){return t?e?"Doctor passed. Next: tdk up":"Doctor passed. Next: tdk project example":"Doctor failed. Fix the items above, then run: tdk doctor"}function Zn(e){return bo(e)}function mu(e,t,n,r,s){return async(o=V)=>{try{return await o(t,z),{name:e,didPass:!0,message:n}}catch(i){return Zn(i)?{name:e,didPass:!1,message:`${e} did not respond within ${z/1e3}s`,fix:s}:{name:e,didPass:!1,message:r,fix:s}}}}async function Jn(e){try{return await V(e,z),!0}catch{return!1}}async function er(){if(process.platform==="win32")try{return await V("docker ps",z),{name:B,didPass:!0,message:"Docker Desktop Linux container engine is running"}}catch{return{name:B,didPass:!1,message:"Docker is not running",fix:ae.dockerDaemonDown}}let e=!!O("docker");try{return await V("docker ps",z),{name:B,didPass:!0,message:"Docker daemon is running"}}catch(n){if(Zn(n))return{name:B,didPass:!1,message:"Docker daemon is not responding",fix:ae.dockerDaemonDown}}let t=Ys(await Jn("pgrep -f com.docker.backend"));return t||(await Jn("colima status")?{name:B,didPass:!0,message:"Colima (Docker runtime) is running"}:O("colima")?{name:B,didPass:!1,message:"Colima is installed but not running",fix:ae.dockerDaemonDown}:await Jn("podman ps")?{name:B,didPass:!0,message:"Podman is running"}:e?{name:B,didPass:!1,message:"Docker daemon is not running",fix:ae.dockerDaemonDown}:{name:B,didPass:!1,message:"Docker is not running",fix:ae.dockerMissing})}var tr=mu("Docker Compose","docker compose version","Docker Compose plugin available","Docker Compose plugin not found","Install Docker Compose: https://docs.docker.com/compose/install/"),hu=[25,0,0],gu=[2,20,2];function Yn(e){let t=e.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);return t?[Number(t[1]),Number(t[2]),Number(t[3]??0)]:null}function Xn(e,t){for(let[n,r]of t.entries()){let s=e[n]??0;if(s!==r)return s>r}return!0}async function nr(e=V){let t=async a=>String(await e(a,z)).trim(),n,r;try{[n,r]=await Promise.all([t("docker version --format '{{.Server.Version}}'"),t("docker compose version --short")])}catch{return{name:"Docker Versions",didPass:!0,isSkipped:!0,message:"Could not read Docker Engine/Compose versions - skipped version check"}}let s=Yn(n),o=Yn(r);if(!s||!o)return{name:"Docker Versions",didPass:!0,isSkipped:!0,message:`Unrecognized Docker version output (engine "${n}", compose "${r}") - skipped version check`};let i=[];return Xn(s,hu)||i.push(`Docker Engine ${n} (need 25.0+)`),Xn(o,gu)||i.push(`Docker Compose ${r} (need 2.20.2+)`),i.length===0?{name:"Docker Versions",didPass:!0,message:`Docker Engine ${n} and Compose ${r} support generated healthchecks`}:{name:"Docker Versions",didPass:!1,message:`Docker is too old for generated healthchecks (they use start_interval):
352
424
  ${i.join(`
353
- `)}`,fix:"Update Docker Desktop, or on Linux update docker-ce and the docker-compose-plugin package"}}async function rr(e=V){let t;try{t=String(await e("tilt version",z)).trim()}catch{return{name:"Tilt CLI",didPass:!1,message:"Tilt CLI not found",fix:ae.tiltMissing}}return bt(t,Wn)?{name:"Tilt CLI",didPass:!0,message:`Tilt ${t} is available`}:{name:"Tilt CLI",didPass:!1,message:`Tilt ${t||"version unknown"} is below the required v${Wn.join(".")} floor`,fix:`Install Tilt v${Wn.join(".")} or newer: https://docs.tilt.dev/install.html`}}async function hd(e=V){let t;try{t=String(await e("docker info --format '{{.OSType}}'",z)).trim().toLowerCase()}catch{return{name:"Docker OS",didPass:!0,isSkipped:!0,message:"Docker OS unavailable - daemon failure reported separately"}}return t!=="linux"?{name:"Docker OS",didPass:!1,message:`Docker is using the ${t||"unknown"} engine; TDK requires Linux containers`,fix:"Switch Docker Desktop to Linux containers, enable WSL2 integration, then retry tdk doctor."}:{name:"Docker OS",didPass:!0,message:"Docker is using Linux containers"}}async function gd(e=V){let t=y();if(!t)return{name:"Bun",didPass:!0,isSkipped:!0,message:"Not in a project - skipping Bun check"};if(!ot(x(t)))return{name:"Bun",didPass:!0,isSkipped:!0,message:"No generated JS services - skipping Bun check"};try{let n=String(await e("bun --version",z)).trim();return bt(n,ce)?{name:"Bun",didPass:!0,message:`Bun ${n} is available`}:{name:"Bun",didPass:!1,message:`Bun ${n||"version unknown"} is below the required ${ce.join(".")} floor`,fix:`Install Bun ${ce.join(".")} or newer: https://bun.sh/install`}}catch{return{name:"Bun",didPass:!1,message:"Bun is not available",fix:ae.bunMissing}}}function kd(){let e=y()??process.cwd(),t=Vs(e);if(t.missing.length>0)return{name:"Environment Variables",didPass:!1,message:`Missing required env variables: ${t.missing.join(", ")}`,fix:H(D(e,".env"))?`Edit .env and set these values:
425
+ `)}`,fix:"Update Docker Desktop, or on Linux update docker-ce and the docker-compose-plugin package"}}async function rr(e=V){let t;try{t=String(await e("tilt version",z)).trim()}catch{return{name:"Tilt CLI",didPass:!1,message:"Tilt CLI not found",fix:ae.tiltMissing}}return bt(t,Wn)?{name:"Tilt CLI",didPass:!0,message:`Tilt ${t} is available`}:{name:"Tilt CLI",didPass:!1,message:`Tilt ${t||"version unknown"} is below the required v${Wn.join(".")} floor`,fix:`Install Tilt v${Wn.join(".")} or newer: https://docs.tilt.dev/install.html`}}async function ku(e=V){let t;try{t=String(await e("docker info --format '{{.OSType}}'",z)).trim().toLowerCase()}catch{return{name:"Docker OS",didPass:!0,isSkipped:!0,message:"Docker OS unavailable - daemon failure reported separately"}}return t!=="linux"?{name:"Docker OS",didPass:!1,message:`Docker is using the ${t||"unknown"} engine; TDK requires Linux containers`,fix:"Switch Docker Desktop to Linux containers, enable WSL2 integration, then retry tdk doctor."}:{name:"Docker OS",didPass:!0,message:"Docker is using Linux containers"}}async function yu(e=V){let t=y();if(!t)return{name:"Bun",didPass:!0,isSkipped:!0,message:"Not in a project - skipping Bun check"};if(!ot(x(t)))return{name:"Bun",didPass:!0,isSkipped:!0,message:"No generated JS services - skipping Bun check"};try{let n=String(await e("bun --version",z)).trim();return bt(n,ce)?{name:"Bun",didPass:!0,message:`Bun ${n} is available`}:{name:"Bun",didPass:!1,message:`Bun ${n||"version unknown"} is below the required ${ce.join(".")} floor`,fix:`Install Bun ${ce.join(".")} or newer: https://bun.sh/install`}}catch{return{name:"Bun",didPass:!1,message:"Bun is not available",fix:ae.bunMissing}}}function Su(){let e=y()??process.cwd(),t=Vs(e);if(t.missing.length>0)return{name:"Environment Variables",didPass:!1,message:`Missing required env variables: ${t.missing.join(", ")}`,fix:H(D(e,".env"))?`Edit .env and set these values:
354
426
  ${t.missing.map(r=>`${r}=<value>`).join(`
355
- `)}`:"No .env file yet. Run `tdk project` to create one with working defaults."};if(t.invalid.length>0)return{name:"Environment Variables",didPass:!1,message:`Invalid env variables: ${t.invalid.join(", ")}`,fix:"Edit .env and provide values for empty variables"};let n=t.warnings.filter(r=>!r.startsWith(".env file not found"));return{name:"Environment Variables",didPass:!0,message:n.length>0?`All required environment variables are set (warning: ${n.join("; ")})`:"All required environment variables are set"}}function yd(){let e=y()??process.cwd(),t=D(e,".tdk",".tdk-out"),n=Dt.filter(r=>!H(D(t,r)));return n.length===0?{name:"Master Configs",didPass:!0,message:`${Dt.join(", ")} found`}:{name:"Master Configs",didPass:!1,message:`Master configs missing: ${n.join(", ")}`,fix:"Run: tdk project"}}function Sd(e=$r()){let t=y();if(!t)return{name:"TDK version",didPass:!0,isSkipped:!0,message:"Not in a project - skipping TDK version check"};let n=Qo(t,e);return n.status==="none"?{name:"TDK version",didPass:!0,isSkipped:!0,message:`tdk ${e} (no minTdkVersion in .tdk/project.json)`}:n.status==="malformed"||n.status==="too-old"?{name:"TDK version",didPass:!1,message:n.message,fix:n.fix}:{name:"TDK version",didPass:!0,message:`tdk ${e} meets minTdkVersion ${n.required}`}}function bd(){let e=y()??process.cwd(),t=un(e),n=x(e).filter(s=>!it(e,s.path,t));if(n.length===0)return{name:"Resource Discovery",didPass:!0,message:`All resources are covered by discovery.paths ${JSON.stringify(t)}`};let r=n.map(s=>qn(zn(e,s.path))).join(", ");return{name:"Resource Discovery",didPass:!1,message:`${T(n.length,"resource")} outside discovery.paths ${JSON.stringify(t)}: ${r}. \`tdk up\` will not start them`,fix:"Move each under services/<stack>/<name>, or add a matching pattern to discovery.paths in .tdk/project.json and run: tdk config regenerate"}}var Td=["install-deps.sh","bun-hoisted-symlink-fix.sh","prisma-bun-client-link-fix.sh","prisma-normalize-client.sh","infisical-entrypoint.sh"],xd=/shared-platform-engineering\/docker-templates\/([\w.-]+)/g;function wd(e){let t=new Set;for(let n of x(e)){let r=D(n.path,C);if(H(r)){for(let s of id(r))if(!(!s.startsWith("Dockerfile")||s.endsWith(".dockerignore")))for(let o of Se(D(r,s),"utf-8").matchAll(xd))t.add(o[1])}}return[...t]}function Ed(){let e=y()??process.cwd(),t=[];H(D(e,A))||t.push(`${A} (workspace root manifest)`);let n=D(e,"shared-platform-engineering","docker-templates"),r=[];try{r=wd(e)}catch{}for(let s of new Set([...Td,...r]))H(D(n,s))||t.push(`shared-platform-engineering/docker-templates/${s}`);return t.length===0?{name:"Generated Runtime Assets",didPass:!0,message:"Generated Docker runtime assets are present"}:{name:"Generated Runtime Assets",didPass:!1,message:`Generated Dockerfiles reference missing project runtime assets:
427
+ `)}`:"No .env file yet. Run `tdk project` to create one with working defaults."};if(t.invalid.length>0)return{name:"Environment Variables",didPass:!1,message:`Invalid env variables: ${t.invalid.join(", ")}`,fix:"Edit .env and provide values for empty variables"};let n=t.warnings.filter(r=>!r.startsWith(".env file not found"));return{name:"Environment Variables",didPass:!0,message:n.length>0?`All required environment variables are set (warning: ${n.join("; ")})`:"All required environment variables are set"}}function bu(){let e=y()??process.cwd(),t=D(e,".tdk",".tdk-out"),n=Dt.filter(r=>!H(D(t,r)));return n.length===0?{name:"Master Configs",didPass:!0,message:`${Dt.join(", ")} found`}:{name:"Master Configs",didPass:!1,message:`Master configs missing: ${n.join(", ")}`,fix:"Run: tdk project"}}function Tu(e=$r()){let t=y();if(!t)return{name:"TDK version",didPass:!0,isSkipped:!0,message:"Not in a project - skipping TDK version check"};let n=Zo(t,e);return n.status==="none"?{name:"TDK version",didPass:!0,isSkipped:!0,message:`tdk ${e} (no minTdkVersion in .tdk/project.json)`}:n.status==="malformed"||n.status==="too-old"?{name:"TDK version",didPass:!1,message:n.message,fix:n.fix}:{name:"TDK version",didPass:!0,message:`tdk ${e} meets minTdkVersion ${n.required}`}}function xu(){let e=y()??process.cwd(),t=ln(e),n=x(e).filter(s=>!it(e,s.path,t));if(n.length===0)return{name:"Resource Discovery",didPass:!0,message:`All resources are covered by discovery.paths ${JSON.stringify(t)}`};let r=n.map(s=>qn(zn(e,s.path))).join(", ");return{name:"Resource Discovery",didPass:!1,message:`${T(n.length,"resource")} outside discovery.paths ${JSON.stringify(t)}: ${r}. \`tdk up\` will not start them`,fix:"Move each under services/<stack>/<name>, or add a matching pattern to discovery.paths in .tdk/project.json and run: tdk config regenerate"}}var wu=["install-deps.sh","bun-hoisted-symlink-fix.sh","prisma-bun-client-link-fix.sh","prisma-normalize-client.sh","infisical-entrypoint.sh"],Eu=/shared-platform-engineering\/docker-templates\/([\w.-]+)/g;function vu(e){let t=new Set;for(let n of x(e)){let r=D(n.path,C);if(H(r)){for(let s of cu(r))if(!(!s.startsWith("Dockerfile")||s.endsWith(".dockerignore")))for(let o of Se(D(r,s),"utf-8").matchAll(Eu))t.add(o[1])}}return[...t]}function Pu(){let e=y()??process.cwd(),t=[];H(D(e,A))||t.push(`${A} (workspace root manifest)`);let n=D(e,"shared-platform-engineering","docker-templates"),r=[];try{r=vu(e)}catch{}for(let s of new Set([...wu,...r]))H(D(n,s))||t.push(`shared-platform-engineering/docker-templates/${s}`);return t.length===0?{name:"Generated Runtime Assets",didPass:!0,message:"Generated Docker runtime assets are present"}:{name:"Generated Runtime Assets",didPass:!1,message:`Generated Dockerfiles reference missing project runtime assets:
356
428
  ${t.join(`
357
- `)}`,fix:"Run `tdk project --yes` (or `tdk config regenerate`) with an updated TDK. `tdk up` also refreshes these assets before starting Tilt."}}function vd(){let e=y()??process.cwd(),t=x(e),n=[];for(let r of t){let s=D(r.path,A);if(!H(s))continue;let o=r.config?.appType??"backend",i=Ot[o]??Ot.backend,a;try{a=JSON.parse(Se(s,"utf-8")).scripts??{}}catch{n.push(`${r.name} (package.json is invalid JSON)`);continue}let c=i.filter(u=>!a[u]);c.length>0&&n.push(`${r.name}: missing "${c.join('", "')}"`)}return n.length===0?{name:"Startup Scripts",didPass:!0,message:"All services have required package.json scripts"}:{name:"Startup Scripts",didPass:!1,message:`Services missing required package.json scripts:
429
+ `)}`,fix:"Run `tdk project --yes` (or `tdk config regenerate`) with an updated TDK. `tdk up` also refreshes these assets before starting Tilt."}}function $u(){let e=y()??process.cwd(),t=x(e),n=[];for(let r of t){let s=D(r.path,A);if(!H(s))continue;let o=r.config?.appType??"backend",i=Ot[o]??Ot.backend,a;try{a=JSON.parse(Se(s,"utf-8")).scripts??{}}catch{n.push(`${r.name} (package.json is invalid JSON)`);continue}let c=i.filter(l=>!a[l]);c.length>0&&n.push(`${r.name}: missing "${c.join('", "')}"`)}return n.length===0?{name:"Startup Scripts",didPass:!0,message:"All services have required package.json scripts"}:{name:"Startup Scripts",didPass:!1,message:`Services missing required package.json scripts:
358
430
  ${n.join(`
359
431
  `)}`,fix:`Add the missing scripts to each service's package.json, e.g.:
360
432
  "dev": "bun run src/index.ts",
361
433
  "build": "tsc",
362
- "start": "bun run dist/index.js"`}}function si(e){if(e.startsWith("@"))return[e.split("/").slice(0,2).join("/")];let t=e.split("/")[0]??e;return[`@types/${t}`,t]}function oi(e,t,n=0){let r=e[t];if(typeof r!="string"||n>3)return!1;if(/(^|[\s;&|(])tsc(\s|$)/.test(r))return!0;for(let s of r.matchAll(/\b(?:bun|npm|pnpm|yarn)\s+run\s+([\w:.-]+)/g))if(oi(e,s[1],n+1))return!0;return!1}function ri(e){let t=si(e);return e.includes("/")||e.startsWith("@")?t[t.length-1]:t[0]}var Pd={"@types/bun":"^1.4.2","@types/node":"^20.0.0"};function $d(e,t){return(t.includes("bun")||e.has("@types/bun"))&&!e.has("@types/node")}function _d(){let e=y()??process.cwd(),t=x(e),n=[],r=new Set;for(let o of t){let i=D(o.path,A),a=D(o.path,C,"tsconfig.docker.autogenerated.json");if(!H(i)||!H(a))continue;let d=Qn(a)?.compilerOptions?.types;if(!Array.isArray(d))continue;let l=Qn(i),p=l?.scripts??{};if(!oi(p,"build"))continue;let h=new Set([...Object.keys(l?.devDependencies??{}),...Object.keys(l?.dependencies??{})]),f=d.filter(b=>typeof b=="string").filter(b=>!si(b).some(w=>h.has(w)));for(let b of f)r.add(ri(b));if(f.length>0){let b=f.map(w=>`"${w}" (needs ${ri(w)})`).join(", ");n.push(`${o.name}: "types" lists ${b}`)}$d(h,d)&&(r.add("@types/node"),n.push(`${o.name}: uses @types/bun, which references node types internally, but @types/node is not a direct dependency`))}if(n.length===0)return{name:"TypeScript Type Dependencies",didPass:!0,message:`Every service's Docker tsconfig "types" entry has its @types package installed`};let s=[...r].map(o=>{let i=Pd[o];return i?`"${o}": "${i}"`:`${o} (bun add -d ${o})`});return{name:"TypeScript Type Dependencies",didPass:!1,message:`\`bun run build\` will fail with TS2688 (Cannot find type definition file) because a @types package it needs is not a direct dependency:
434
+ "start": "bun run dist/index.js"`}}function oi(e){if(e.startsWith("@"))return[e.split("/").slice(0,2).join("/")];let t=e.split("/")[0]??e;return[`@types/${t}`,t]}function ii(e,t,n=0){let r=e[t];if(typeof r!="string"||n>3)return!1;if(/(^|[\s;&|(])tsc(\s|$)/.test(r))return!0;for(let s of r.matchAll(/\b(?:bun|npm|pnpm|yarn)\s+run\s+([\w:.-]+)/g))if(ii(e,s[1],n+1))return!0;return!1}function si(e){let t=oi(e);return e.includes("/")||e.startsWith("@")?t[t.length-1]:t[0]}var _u={"@types/bun":"^1.4.2","@types/node":"^20.0.0"};function Ru(e,t){return(t.includes("bun")||e.has("@types/bun"))&&!e.has("@types/node")}function Au(){let e=y()??process.cwd(),t=x(e),n=[],r=new Set;for(let o of t){let i=D(o.path,A),a=D(o.path,C,"tsconfig.docker.autogenerated.json");if(!H(i)||!H(a))continue;let u=Qn(a)?.compilerOptions?.types;if(!Array.isArray(u))continue;let d=Qn(i),p=d?.scripts??{};if(!ii(p,"build"))continue;let h=new Set([...Object.keys(d?.devDependencies??{}),...Object.keys(d?.dependencies??{})]),f=u.filter(b=>typeof b=="string").filter(b=>!oi(b).some(w=>h.has(w)));for(let b of f)r.add(si(b));if(f.length>0){let b=f.map(w=>`"${w}" (needs ${si(w)})`).join(", ");n.push(`${o.name}: "types" lists ${b}`)}Ru(h,u)&&(r.add("@types/node"),n.push(`${o.name}: uses @types/bun, which references node types internally, but @types/node is not a direct dependency`))}if(n.length===0)return{name:"TypeScript Type Dependencies",didPass:!0,message:`Every service's Docker tsconfig "types" entry has its @types package installed`};let s=[...r].map(o=>{let i=_u[o];return i?`"${o}": "${i}"`:`${o} (bun add -d ${o})`});return{name:"TypeScript Type Dependencies",didPass:!1,message:`\`bun run build\` will fail with TS2688 (Cannot find type definition file) because a @types package it needs is not a direct dependency:
363
435
  ${n.join(`
364
- `)}`,fix:`Add to each service's package.json devDependencies: ${s.join(", ")}`}}function Qn(e){try{return JSON.parse(Se(e,"utf-8"))}catch{return null}}function Rd(e){let n=Qn(e)?.compilerOptions;return n?.allowSyntheticDefaultImports===!0||n?.esModuleInterop===!0}function Ad(){let e=y()??process.cwd(),t=x(e).filter(r=>r.config?.appType==="frontend");if(t.length===0)return{name:"Frontend Docker Preflight",didPass:!0,isSkipped:!0,message:"No frontend services to check"};let n=[];for(let r of t){H(D(r.path,"public"))||n.push(`${r.name}: no public/ folder, but the Docker build copies it. Create it: mkdir -p ${qn(zn(e,D(r.path,"public")))} && touch ${qn(zn(e,D(r.path,"public",".gitkeep")))}`);let s=D(r.path,C,"Dockerfile.app.autogenerated"),o=D(r.path,C,"tsconfig.docker.autogenerated.json");if(H(s)){let i=Se(s,"utf-8"),a=/\bEXPOSE\s+80\b/.test(i),c=r.config?.stack,u=c?D(e,"services",c,C,"docker-compose.app.autogenerated.yml"):"";if(a&&u&&H(u)){let d=Se(u,"utf-8"),l=r.name.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),p=new RegExp(`traefik\\.http\\.services\\.${l}\\.loadbalancer\\.server\\.port=(\\d+)`),f=d.match(p)?.[1];f&&f!=="80"&&n.push(`${r.name}: nginx runtime exposes 80, but generated Traefik routes to ${f}`)}}if(H(o)&&!Rd(o)){let i=D(r.path,"src","main.tsx");if(H(i)){let a=Se(i,"utf-8"),c=[/import\s+\w+\s+from\s+["']react["']/,/import\s+\w+\s+from\s+["']react-dom\/client["']/].filter(u=>u.test(a)).map(u=>u.source.includes("react-dom")?"react-dom/client":"react");c.length>0&&n.push(`${r.name}: Docker tsconfig does not allow synthetic default imports, but src/main.tsx default-imports ${c.join(" and ")}`)}}}return n.length===0?{name:"Frontend Docker Preflight",didPass:!0,message:`${T(t.length,"frontend")} ${t.length===1?"has":"have"} compatible Docker build/routing metadata`}:{name:"Frontend Docker Preflight",didPass:!1,message:`Frontend Docker metadata has issues that will make \`tdk up\` fail or route 404:
436
+ `)}`,fix:`Add to each service's package.json devDependencies: ${s.join(", ")}`}}function Qn(e){try{return JSON.parse(Se(e,"utf-8"))}catch{return null}}function Du(e){let n=Qn(e)?.compilerOptions;return n?.allowSyntheticDefaultImports===!0||n?.esModuleInterop===!0}function Ou(){let e=y()??process.cwd(),t=x(e).filter(r=>r.config?.appType==="frontend");if(t.length===0)return{name:"Frontend Docker Preflight",didPass:!0,isSkipped:!0,message:"No frontend services to check"};let n=[];for(let r of t){H(D(r.path,"public"))||n.push(`${r.name}: no public/ folder, but the Docker build copies it. Create it: mkdir -p ${qn(zn(e,D(r.path,"public")))} && touch ${qn(zn(e,D(r.path,"public",".gitkeep")))}`);let s=D(r.path,C,"Dockerfile.app.autogenerated"),o=D(r.path,C,"tsconfig.docker.autogenerated.json");if(H(s)){let i=Se(s,"utf-8"),a=/\bEXPOSE\s+80\b/.test(i),c=r.config?.stack,l=c?D(e,"services",c,C,"docker-compose.app.autogenerated.yml"):"";if(a&&l&&H(l)){let u=Se(l,"utf-8"),d=r.name.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),p=new RegExp(`traefik\\.http\\.services\\.${d}\\.loadbalancer\\.server\\.port=(\\d+)`),f=u.match(p)?.[1];f&&f!=="80"&&n.push(`${r.name}: nginx runtime exposes 80, but generated Traefik routes to ${f}`)}}if(H(o)&&!Du(o)){let i=D(r.path,"src","main.tsx");if(H(i)){let a=Se(i,"utf-8"),c=[/import\s+\w+\s+from\s+["']react["']/,/import\s+\w+\s+from\s+["']react-dom\/client["']/].filter(l=>l.test(a)).map(l=>l.source.includes("react-dom")?"react-dom/client":"react");c.length>0&&n.push(`${r.name}: Docker tsconfig does not allow synthetic default imports, but src/main.tsx default-imports ${c.join(" and ")}`)}}}return n.length===0?{name:"Frontend Docker Preflight",didPass:!0,message:`${T(t.length,"frontend")} ${t.length===1?"has":"have"} compatible Docker build/routing metadata`}:{name:"Frontend Docker Preflight",didPass:!1,message:`Frontend Docker metadata has issues that will make \`tdk up\` fail or route 404:
365
437
  ${n.join(`
366
- `)}`,fix:'Regenerate with a current TDK (`tdk config regenerate`) and ensure frontend nginx runtimes route to port 80. For React entrypoints, prefer named imports: `import { StrictMode } from "react"` and `import { createRoot } from "react-dom/client"`.'}}var Dd=90,Od=80;function Nd(e){return e.split(`
367
- `).map(t=>t.trim()).filter(Boolean).map(t=>{let[n,r,s]=t.split(",");return{name:n??"unknown",memPct:Number.parseFloat((r??"").replace(/%/g,"")),cpuPct:Number.parseFloat((s??"").replace(/%/g,""))}}).filter(t=>Number.isFinite(t.memPct)&&Number.isFinite(t.cpuPct))}function Cd(){let e;try{e=od(O("docker")??"docker",["stats","--no-stream","--format","{{.Name}},{{.MemPerc}},{{.CPUPerc}}"],{stdio:"pipe",encoding:"utf-8",timeout:z,windowsHide:process.platform==="win32"})}catch(s){return{name:"Container Resource Health",didPass:!0,isSkipped:!0,message:Zn(s)?"Docker not responding - skipped container resource check":"Docker not running - skipped container resource check"}}let t=Nd(e);if(t.length===0)return{name:"Container Resource Health",didPass:!0,isSkipped:!0,message:"No running containers to check"};let n=t.filter(s=>s.memPct>=Dd&&s.cpuPct>=Od);if(n.length===0)return{name:"Container Resource Health",didPass:!0,message:`${T(t.length,"container")} within normal resource usage`};let r=n.map(s=>`${s.name} (mem ${s.memPct.toFixed(0)}%, cpu ${s.cpuPct.toFixed(0)}%)`).join(`
438
+ `)}`,fix:'Regenerate with a current TDK (`tdk config regenerate`) and ensure frontend nginx runtimes route to port 80. For React entrypoints, prefer named imports: `import { StrictMode } from "react"` and `import { createRoot } from "react-dom/client"`.'}}var Nu=90,Cu=80;function ju(e){return e.split(`
439
+ `).map(t=>t.trim()).filter(Boolean).map(t=>{let[n,r,s]=t.split(",");return{name:n??"unknown",memPct:Number.parseFloat((r??"").replace(/%/g,"")),cpuPct:Number.parseFloat((s??"").replace(/%/g,""))}}).filter(t=>Number.isFinite(t.memPct)&&Number.isFinite(t.cpuPct))}function Iu(){let e;try{e=au(O("docker")??"docker",["stats","--no-stream","--format","{{.Name}},{{.MemPerc}},{{.CPUPerc}}"],{stdio:"pipe",encoding:"utf-8",timeout:z,windowsHide:process.platform==="win32"})}catch(s){return{name:"Container Resource Health",didPass:!0,isSkipped:!0,message:Zn(s)?"Docker not responding - skipped container resource check":"Docker not running - skipped container resource check"}}let t=ju(e);if(t.length===0)return{name:"Container Resource Health",didPass:!0,isSkipped:!0,message:"No running containers to check"};let n=t.filter(s=>s.memPct>=Nu&&s.cpuPct>=Cu);if(n.length===0)return{name:"Container Resource Health",didPass:!0,message:`${T(t.length,"container")} within normal resource usage`};let r=n.map(s=>`${s.name} (mem ${s.memPct.toFixed(0)}%, cpu ${s.cpuPct.toFixed(0)}%)`).join(`
368
440
  `);return{name:"Container Resource Health",didPass:!1,message:`${T(n.length,"container")} pinned near its memory limit while burning CPU -- likely stuck in a boot-time retry/fetch loop, not a normal crash:
369
- ${r}`,fix:"Check the container's boot logs for a network fetch loop (e.g. `bunx <pkg>` re-downloading a CLI on every start instead of using one already installed): docker logs <container>. If a Prisma auto-migration is the cause, set AUTO_MIGRATE=false in the project's .env as a temporary unblock."}}var jd=5e3;async function Id(e,t){let n=y()??process.cwd(),r=Mt(x(n),t);return r.length===0?{name:"Service Health",didPass:!0,isSkipped:!0,message:"No routable services to ping"}:Sn(await Xe(r,e))}async function Fd(e,t){let n=y()??process.cwd(),r=x(n),s=Ur(Mr(r,t),{timeoutSeconds:Math.ceil(e/1e3)});return s.length===0?bn([]):(await Xe(Mt(r,t),e)).some(i=>i.status!==void 0)?bn(await Kr(s)):{name:"Service Smoke",didPass:!0,isSkipped:!0,message:"No services responded - skipped smoke checks"}}async function Ld(e,t){let n=y()??process.cwd(),r=x(n),s=_r(r,t);return s.length===0?{name:"Advertised Endpoints",didPass:!0,isSkipped:!0,message:"No routable services to check"}:Is(await Xe(s,e))}function Md(e,t){if(e.length===0){console.log(`${m.green("\u2713")} Nothing to repair
441
+ ${r}`,fix:"Check the container's boot logs for a network fetch loop (e.g. `bunx <pkg>` re-downloading a CLI on every start instead of using one already installed): docker logs <container>. If a Prisma auto-migration is the cause, set AUTO_MIGRATE=false in the project's .env as a temporary unblock."}}var Fu=5e3;async function Lu(e,t){let n=y()??process.cwd(),r=Mt(x(n),t);return r.length===0?{name:"Service Health",didPass:!0,isSkipped:!0,message:"No routable services to ping"}:Sn(await Xe(r,e))}async function Mu(e,t){let n=y()??process.cwd(),r=x(n),s=Ur(Mr(r,t),{timeoutSeconds:Math.ceil(e/1e3)});return s.length===0?bn([]):(await Xe(Mt(r,t),e)).some(i=>i.status!==void 0)?bn(await Gr(s)):{name:"Service Smoke",didPass:!0,isSkipped:!0,message:"No services responded - skipped smoke checks"}}async function Uu(e,t){let n=y()??process.cwd(),r=x(n),s=_r(r,t);return s.length===0?{name:"Advertised Endpoints",didPass:!0,isSkipped:!0,message:"No routable services to check"}:Is(await Xe(s,e))}function Bu(e,t){if(e.length===0){console.log(`${m.green("\u2713")} Nothing to repair
370
442
  `);return}for(let n of e){let r=n.status==="planned"?`${m.cyan("would run")}`:n.status==="applied"?m.green("ran"):n.status==="failed"?m.red("failed"):m.gray("skipped"),s=n.status==="planned"?"":` (${n.reason})`;console.log(`${r}: ${n.command}${s}`)}t&&console.log(m.gray(`
371
- Dry run: nothing was changed.`)),console.log("")}var Ud=new ad("doctor").description("Check environment readiness for TDK").option("--json","Output a versioned JSON readiness report",!1).exitOverride(e=>{e.exitCode===0&&process.exit(0),Ud.opts().json&&console.log(JSON.stringify(ee([],!1,[{code:"USAGE",message:e.message}]))),process.exit(2)}).option("--no-ping","Skip pinging running services' /health endpoints").option("--strict","Fail warnings such as a WSL project under /mnt/c").option("--fix","Repair this project's unused Docker networks and leftover doctor probes",!1).option("--dry-run","With --fix: list the repairs without changing anything",!1).option("--scope <scope>","With --fix: project (default) or machine, which also removes unused networks of other TDK projects","project").option("-y, --yes","With --fix: apply every repair without asking",!1).option("--ping-timeout <ms>","Per-service ping timeout in milliseconds",String(jd)).action(async e=>{let t=Number(e.pingTimeout);if(!/^\d+$/.test(e.pingTimeout)||!Number.isSafeInteger(t)||t<=0){let g="--ping-timeout must be a positive integer number of milliseconds";e.json&&console.log(JSON.stringify(ee([],!1,[{code:"USAGE",message:g}]))),console.error(g),process.exit(2);return}let n=!["project","machine"].includes(e.scope),r=e.scope!=="project"&&!e.fix;if(n||r||(e.dryRun||e.yes)&&!e.fix){let g=n?`--scope must be project or machine, got "${e.scope}"`:r?"--scope only applies with --fix":`${e.dryRun?"--dry-run":"--yes"} only applies with --fix`;e.json&&console.log(JSON.stringify(ee([],!1,[{code:"USAGE",message:g}]))),console.error(g),process.exit(2);return}e.json||console.log("TDK doctor checks your local Docker + Tilt development environment; it does not check cluster deployments.");let s=bs();if(process.platform==="win32"){if(e.json){let g=null;try{g=await ye()}catch{}console.log(JSON.stringify(ee([{name:"Native Windows support",didPass:!1,message:ti,fix:"Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md"}],!!y(),[],g,{...s,canUp:!1})))}console.error(ti),process.exit(1);return}if(s.kind==="webcontainer"){let g=ee([{name:"Host",didPass:!1,message:cn,fix:`Use a machine with Docker. Guide: ${st}`}],!!y(),[],void 0,s);e.json&&console.log(JSON.stringify(g)),console.error(cn),process.exit(1);return}e.json||(console.log(`
443
+ Dry run: nothing was changed.`)),console.log("")}var Hu=new lu("doctor").description("Check environment readiness for TDK").option("--json","Output a versioned JSON readiness report",!1).exitOverride(e=>{e.exitCode===0&&process.exit(0),Hu.opts().json&&console.log(JSON.stringify(ee([],!1,[{code:"USAGE",message:e.message}]))),process.exit(2)}).option("--no-ping","Skip pinging running services' /health endpoints").option("--strict","Fail warnings such as a WSL project under /mnt/c").option("--fix","Repair this project's unused Docker networks and leftover doctor probes",!1).option("--dry-run","With --fix: list the repairs without changing anything",!1).option("--scope <scope>","With --fix: project (default) or machine, which also removes unused networks of other TDK projects","project").option("-y, --yes","With --fix: apply every repair without asking",!1).option("--ping-timeout <ms>","Per-service ping timeout in milliseconds",String(Fu)).action(async e=>{let t=Number(e.pingTimeout);if(!/^\d+$/.test(e.pingTimeout)||!Number.isSafeInteger(t)||t<=0){let g="--ping-timeout must be a positive integer number of milliseconds";e.json&&console.log(JSON.stringify(ee([],!1,[{code:"USAGE",message:g}]))),console.error(g),process.exit(2);return}let n=!["project","machine"].includes(e.scope),r=e.scope!=="project"&&!e.fix;if(n||r||(e.dryRun||e.yes)&&!e.fix){let g=n?`--scope must be project or machine, got "${e.scope}"`:r?"--scope only applies with --fix":`${e.dryRun?"--dry-run":"--yes"} only applies with --fix`;e.json&&console.log(JSON.stringify(ee([],!1,[{code:"USAGE",message:g}]))),console.error(g),process.exit(2);return}e.json||console.log("TDK doctor checks your local Docker + Tilt development environment; it does not check cluster deployments.");let s=bs();if(process.platform==="win32"){if(e.json){let g=null;try{g=await ye()}catch{}console.log(JSON.stringify(ee([{name:"Native Windows support",didPass:!1,message:ni,fix:"Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md"}],!!y(),[],g,{...s,canUp:!1})))}console.error(ni),process.exit(1);return}if(s.kind==="webcontainer"){let g=ee([{name:"Host",didPass:!1,message:cn,fix:`Use a machine with Docker. Guide: ${st}`}],!!y(),[],void 0,s);e.json&&console.log(JSON.stringify(g)),console.error(cn),process.exit(1);return}e.json||(console.log(`
372
444
  ${m.bold("\u{1F50D} TDK Doctor")}
373
445
  `),console.log(`Checking environment...
374
- `));let o=y(),i;if(e.fix){try{let g;if(o)try{g=rt(o).project.name}catch{}let R=o?oo(o):[],ne=await to(g,void 0,{tiltPids:R,machine:e.scope==="machine"});i=await no(ne,{dryRun:e.dryRun,confirm:e.yes||!e.json&&process.stdin.isTTY?async ue=>e.yes||await zo({message:`Run \`${ue.command}\` (${ue.check}, ${ue.reason})?`}):void 0})}catch(g){i=[{id:"plan-fixes",check:"Docker networks",scope:"project",command:"docker network ls",status:"failed",reason:`could not list Docker networks: ${(g instanceof Error?g.message:String(g)).split(/\r?\n/)[0]}`}]}e.json||Md(i,e.dryRun)}let a,c;try{a=await kt(o??process.cwd())}catch(g){a=null,c=g instanceof Error?g.message:String(g)}let u=[()=>a?{name:"Host Ports",didPass:!0,message:`HTTP ${a.ingressHttp}, HTTPS ${a.ingressHttps}, Postgres ${a.postgres}`}:{name:"Host Ports",didPass:!1,message:c??"Could not select host ports",fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."},()=>a?yn(Zo,void 0,[a.ingressHttp,a.ingressHttps]):{name:"Ingress Ports",didPass:!1,message:"Ingress port plan is unavailable"},er,()=>zs(),hd,rr,tr,nr,gd,()=>cd(y()??process.cwd(),e.strict),()=>ld(process.env,e.strict),()=>Ho(),()=>so()],d=[()=>Sd(),yd,Ed,po,vd,()=>Ls(),_d,Ad,bd,()=>Do(),()=>ft(),()=>Hn(),()=>Kn(),()=>Gn(),()=>Vn(void 0,e.strict),()=>Oo(),()=>No(),()=>Io(),()=>jo(),()=>ht(),()=>Ro(),()=>Uo(),()=>Mo(),()=>Bo(),kd,async()=>{let g=y()??process.cwd(),R=gn(g)?await Ke(g):!0;return kn(Zo,g,void 0,R)},Cd,()=>{let g=y()??process.cwd(),R=[];try{R=vn(g)}catch{return{name:"Crash-looping containers",didPass:!0,isSkipped:!0,message:"Could not read .env - skipped crash-loop check"}}return Js(le(),R)},Tn];if(e.ping){let g=o?qo(o,a?.ingressHttp):a?.ingressHttp;d.push(()=>Id(t,g)),d.push(()=>Fd(t,g)),d.push(()=>Ld(t,g))}let l=!!o,{checks:p,errors:h}=await ao(u,l?d:[]);if(Ts(s.kind))for(let g of p)g.name===B&&!g.didPass&&(g.fix=Ss);let f=ee(ni(p),l,h,a,s);i&&(f.data.actions=i),i&&ro(i)&&(f.data.ready=!1);let w=co(f),$=f.data.ready;if(e.json){let g;try{g=vn(y()??process.cwd())}catch(R){if(!(R instanceof Le))throw R;console.log(JSON.stringify(ee([],l,[...h,{code:"ENV_UNREADABLE",message:R.message}]))),console.error(R.message),process.exit(1)}console.log(JSON.stringify(at(f,g)));for(let R of h)console.error(Me(R.message,g));w!==0&&process.exit(w);return}for(let g of h)console.error(`${m.red("\u2717")} Doctor check failed: ${g.message}`);for(let g of ni(p))!g.didPass&&!g.isSkipped&&!g.isWarning?(console.log(`${m.red("\u2717")} ${g.message}`),g.fix&&console.log(`${m.blue("\u2139")} Fix: ${g.fix}`)):g.isWarning?(console.log(`${m.yellow("\u26A0")} ${m.yellow(g.message)}`),g.fix&&console.log(`${m.blue("\u2139")} Fix: ${g.fix}`)):g.isSkipped?(console.log(`${m.gray("\u25CB")} ${m.gray(g.message)}`),g.fix&&console.log(`${m.blue("\u2139")} ${g.fix}`)):console.log(`${m.green("\u2713")} ${g.message}`);console.log(""),$&&!l&&(console.log(`${m.gray("\u25CB")} ${m.gray("Not in a TDK project, so project checks were skipped")}`),console.log(""));let U=dd(l,$);console.log(`${$?m.green(m.bold("\u2713")):m.red(m.bold("\u2717"))} ${U}`),w!==0&&process.exit(w)});function ii(e){return bt(e,ce)}var Tt=`${ce[0]}.${ce[1]}+`;function Kd(e,t){return{id:e,ok:t.didPass||!!t.isSkipped,message:t.message,fix:t.fix}}function ci(e){let[t=0,n=0]=String(e).split(".").map(r=>Number.parseInt(r,10));return!Number.isFinite(t)||!Number.isFinite(n)||t<22||t===22&&n<12}async function xt(e,t,n){try{return Kd(e,await t())}catch{return{id:e,ok:!1,message:n}}}function Gd(e){return e.isSkipped?{...e,didPass:!1,isSkipped:!1,message:`Could not verify Docker Engine/Compose minimum versions: ${e.message}`,fix:e.fix??"Start Docker and ensure Docker Engine 25+ and Compose 2.20.2+ are installed."}:e}function Vd(e){try{return x(e).some(t=>t.config?.featuresEnabled?.includes("prisma")??!1)}catch{return!1}}async function Wd(e={}){let t=e.cwd??process.cwd(),n=y(t),r=!!n,s=[],o=process.versions.node;s.push({id:"node",ok:!ci(o),message:o,fix:ci(o)?`Install Node.js 22.12+ (current: ${o}). https://nodejs.org`:void 0}),s.push(await xt("docker",er,"Docker daemon is not running")),s.push(await xt("compose",async()=>{let[f,b]=await Promise.all([tr(),nr()]);return f.didPass?Gd(b):f},"Docker Engine or Compose version check failed")),s.push(await xt("tilt",rr,"Tilt CLI not found"));let i=n?ot(x(n)):!0,a=!1,c=i?O("bun"):void 0;if(c)try{let f=ai(c,["--version"],{encoding:"utf-8",timeout:3e3}).trim();a=ii(f)}catch{}s.push(i?{id:"bun",ok:a,message:a?`Bun ${Tt} is available on PATH`:`Bun ${Tt} not found on PATH`,fix:a?void 0:"curl -fsSL https://bun.sh/install | bash"}:{id:"bun",ok:!0,message:"Bun not needed: no generated JS services"});try{let f=await kt(n??t);s.push({id:"ports",ok:!0,message:`HTTP ${f.ingressHttp}, HTTPS ${f.ingressHttps}, Postgres ${f.postgres}`})}catch(f){s.push({id:"ports",ok:!1,message:f instanceof Error?f.message:String(f),fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."})}if(n){let f=await xt("nats",()=>ht(n),"NATS broker check failed");if(f.ok||s.push(f),Vd(n)){let b=!1;try{let w=JSON.parse(Bd(Hd(n,".tdk",_),"utf-8")),$=String(w?.project?.name??"").replace(/-/g,"_");$&&(b=ai(O("docker")??"docker",["ps","--filter",`label=com.docker.compose.project=${$}`,"--filter","label=com.docker.compose.service=postgres","--filter","health=healthy","--format","{{.Names}}"],{encoding:"utf-8",timeout:3e3}).trim().length>0)}catch{}b||s.push({id:"prisma",ok:!1,message:"A Prisma resource is configured, but the project Postgres service is not healthy",fix:"Run `tdk up` to start the bundled Postgres, then check `tdk doctor`."})}}let u=s.filter(f=>!f.ok).slice(0,8),d=u.some(f=>["node","docker","compose","tilt","bun","ports"].includes(f.id)),l=u.some(f=>f.id==="bun"),p=u.length?d?l?`Cold start blocked. Bun ${Tt} must be installed on PATH.
375
- Prisma/NATS configuration is project-specific and generated after \`tdk project\`. Fix the machine checks below.`:"Cold start blocked. Bun/Prisma/NATS are not the first failure.\nThey are generated after `tdk project`. Fix the machine checks below.":"Machine is ready. Project wiring is not.":"",h=u.length?"":r?"Environment ready for TDK":`This machine is ready for TDK.
376
- Next: tdk project --yes`;return{ok:u.length===0,inProject:r,items:u,header:p,footer:h}}function Jd(e,t={}){let n=[e.header];for(let r of e.items)n.push(`FAIL ${r.id.padEnd(7)} ${r.message}`),r.fix&&n.push(` ${r.fix}`);return e.footer&&(t.includeSuccessFooter??!0)&&n.push(e.footer),n.filter(Boolean).join(`
377
- `)}async function hy(){let e=await Wd();e.items.some(n=>["node","docker","compose","tilt","bun","ports"].includes(n.id))&&(console.error(Jd(e)),process.exit(1))}export{Pt as a,m as b,vr as c,qr as d,J as e,j as f,yr as g,C as h,Je as i,qe as j,_ as k,A as l,Dt as m,ip as n,P as o,Pe as p,ap as q,y as r,$r as s,De as t,rf as u,sf as v,O as w,Zr as x,Ka as y,rs as z,Ga as A,bf as B,Tf as C,os as D,Rf as E,N as F,Y as G,Af as H,Wa as I,Df as J,Of as K,Nf as L,T as M,If as N,Ff as O,Lf as P,Mf as Q,Uf as R,Bf as S,Hf as T,Kf as U,Gf as V,zt as W,Vf as X,Wf as Y,Jf as Z,qf as _,zf as $,Yf as aa,Xf as ba,Qf as ca,I as da,Ft as ea,ga as fa,Lt as ga,_r as ha,Mr as ia,qp as ja,Kr as ka,Re as la,Qp as ma,Gt as na,as as oa,Za as pa,ec as qa,nm as ra,rm as sa,sm as ta,om as ua,im as va,Yt as wa,nn as xa,ps as ya,ic as za,x as Aa,Ne as Ba,ym as Ca,Sm as Da,bm as Ea,Tm as Fa,xm as Ga,wm as Ha,cc as Ia,Em as Ja,ye as Ka,Vg as La,Jo as Ma,Qg as Na,Zg as Oa,kt as Pa,Yu as Qa,Xu as Ra,Xh as Sa,yp as Ta,ea as Ua,Sp as Va,bp as Wa,Ce as Xa,nt as Ya,an as Za,rt as _a,Um as $a,$c as ab,_c as bb,Bm as cb,rk as db,zo as eb,sk as fb,ok as gb,ag as hb,kg as ib,To as jb,jn as kb,Ro as lb,Il as mb,cn as nb,Ss as ob,bs as pb,Ts as qb,un as rb,it as sb,Ym as tb,Ps as ub,_s as vb,fn as wb,mn as xb,hn as yb,Vs as zb,hh as Ab,gh as Bb,Le as Cb,vn as Db,Me as Eb,at as Fb,Dh as Gb,Oh as Hb,Nh as Ib,An as Jb,Du as Kb,Cu as Lb,Lh as Mb,mk as Nb,hk as Ob,Qo as Pb,Ud as Qb,ci as Rb,Gd as Sb,Wd as Tb,Jd as Ub,hy as Vb};
446
+ `));let o=y(),i;if(e.fix){try{let g;if(o)try{g=rt(o).project.name}catch{}let R=o?oo(o):[],ne=await to(g,void 0,{tiltPids:R,machine:e.scope==="machine"});i=await no(ne,{dryRun:e.dryRun,confirm:e.yes||!e.json&&process.stdin.isTTY?async le=>e.yes||await Yo({message:`Run \`${le.command}\` (${le.check}, ${le.reason})?`}):void 0})}catch(g){i=[{id:"plan-fixes",check:"Docker networks",scope:"project",command:"docker network ls",status:"failed",reason:`could not list Docker networks: ${(g instanceof Error?g.message:String(g)).split(/\r?\n/)[0]}`}]}e.json||Bu(i,e.dryRun)}let a,c;try{a=await kt(o??process.cwd())}catch(g){a=null,c=g instanceof Error?g.message:String(g)}let l=[()=>a?{name:"Host Ports",didPass:!0,message:`HTTP ${a.ingressHttp}, HTTPS ${a.ingressHttps}, Postgres ${a.postgres}`}:{name:"Host Ports",didPass:!1,message:c??"Could not select host ports",fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."},()=>a?yn(ei,void 0,[a.ingressHttp,a.ingressHttps]):{name:"Ingress Ports",didPass:!1,message:"Ingress port plan is unavailable"},er,()=>zs(),ku,rr,tr,nr,yu,()=>du(y()??process.cwd(),e.strict),()=>pu(process.env,e.strict),()=>Go(),()=>so()],u=[()=>Tu(),bu,Pu,po,$u,()=>Ls(),Au,Ou,xu,()=>Oo(),()=>ft(),()=>Hn(),()=>Gn(),()=>Kn(),()=>Vn(void 0,e.strict),()=>No(),()=>Co(),()=>Fo(),()=>Io(),()=>ht(),()=>Ao(),()=>Bo(),()=>Uo(),()=>Ho(),Su,async()=>{let g=y()??process.cwd(),R=gn(g)?await Ge(g):!0;return kn(ei,g,void 0,R)},Iu,()=>{let g=y()??process.cwd(),R=[];try{R=vn(g)}catch{return{name:"Crash-looping containers",didPass:!0,isSkipped:!0,message:"Could not read .env - skipped crash-loop check"}}return Js(de(),R)},Tn];if(e.ping){let g=o?zo(o,a?.ingressHttp):a?.ingressHttp;u.push(()=>Lu(t,g)),u.push(()=>Mu(t,g)),u.push(()=>Uu(t,g))}let d=!!o,{checks:p,errors:h}=await ao(l,d?u:[]);if(Ts(s.kind))for(let g of p)g.name===B&&!g.didPass&&(g.fix=Ss);let f=ee(ri(p),d,h,a,s);i&&(f.data.actions=i),i&&ro(i)&&(f.data.ready=!1);let w=co(f),$=f.data.ready;if(e.json){let g;try{g=vn(y()??process.cwd())}catch(R){if(!(R instanceof Le))throw R;console.log(JSON.stringify(ee([],d,[...h,{code:"ENV_UNREADABLE",message:R.message}]))),console.error(R.message),process.exit(1)}console.log(JSON.stringify(at(f,g)));for(let R of h)console.error(Me(R.message,g));w!==0&&process.exit(w);return}for(let g of h)console.error(`${m.red("\u2717")} Doctor check failed: ${g.message}`);for(let g of ri(p))!g.didPass&&!g.isSkipped&&!g.isWarning?(console.log(`${m.red("\u2717")} ${g.message}`),g.fix&&console.log(`${m.blue("\u2139")} Fix: ${g.fix}`)):g.isWarning?(console.log(`${m.yellow("\u26A0")} ${m.yellow(g.message)}`),g.fix&&console.log(`${m.blue("\u2139")} Fix: ${g.fix}`)):g.isSkipped?(console.log(`${m.gray("\u25CB")} ${m.gray(g.message)}`),g.fix&&console.log(`${m.blue("\u2139")} ${g.fix}`)):console.log(`${m.green("\u2713")} ${g.message}`);console.log(""),$&&!d&&(console.log(`${m.gray("\u25CB")} ${m.gray("Not in a TDK project, so project checks were skipped")}`),console.log(""));let U=fu(d,$);console.log(`${$?m.green(m.bold("\u2713")):m.red(m.bold("\u2717"))} ${U}`),w!==0&&process.exit(w)});function ai(e){return bt(e,ce)}var Tt=`${ce[0]}.${ce[1]}+`;function Vu(e,t){return{id:e,ok:t.didPass||!!t.isSkipped,message:t.message,fix:t.fix}}function li(e){let[t=0,n=0]=String(e).split(".").map(r=>Number.parseInt(r,10));return!Number.isFinite(t)||!Number.isFinite(n)||t<22||t===22&&n<12}async function xt(e,t,n){try{return Vu(e,await t())}catch{return{id:e,ok:!1,message:n}}}function Wu(e){return e.isSkipped?{...e,didPass:!1,isSkipped:!1,message:`Could not verify Docker Engine/Compose minimum versions: ${e.message}`,fix:e.fix??"Start Docker and ensure Docker Engine 25+ and Compose 2.20.2+ are installed."}:e}function Ju(e){try{return x(e).some(t=>t.config?.featuresEnabled?.includes("prisma")??!1)}catch{return!1}}async function qu(e={}){let t=e.cwd??process.cwd(),n=y(t),r=!!n,s=[],o=process.versions.node;s.push({id:"node",ok:!li(o),message:o,fix:li(o)?`Install Node.js 22.12+ (current: ${o}). https://nodejs.org`:void 0}),s.push(await xt("docker",er,"Docker daemon is not running")),s.push(await xt("compose",async()=>{let[f,b]=await Promise.all([tr(),nr()]);return f.didPass?Wu(b):f},"Docker Engine or Compose version check failed")),s.push(await xt("tilt",rr,"Tilt CLI not found"));let i=n?ot(x(n)):!0,a=!1,c=i?O("bun"):void 0;if(c)try{let f=ci(c,["--version"],{encoding:"utf-8",timeout:3e3}).trim();a=ai(f)}catch{}s.push(i?{id:"bun",ok:a,message:a?`Bun ${Tt} is available on PATH`:`Bun ${Tt} not found on PATH`,fix:a?void 0:"curl -fsSL https://bun.sh/install | bash"}:{id:"bun",ok:!0,message:"Bun not needed: no generated JS services"});try{let f=await kt(n??t);s.push({id:"ports",ok:!0,message:`HTTP ${f.ingressHttp}, HTTPS ${f.ingressHttps}, Postgres ${f.postgres}`})}catch(f){s.push({id:"ports",ok:!1,message:f instanceof Error?f.message:String(f),fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."})}if(n){let f=await xt("nats",()=>ht(n),"NATS broker check failed");if(f.ok||s.push(f),Ju(n)){let b=!1;try{let w=JSON.parse(Gu(Ku(n,".tdk",_),"utf-8")),$=String(w?.project?.name??"").replace(/-/g,"_");$&&(b=ci(O("docker")??"docker",["ps","--filter",`label=com.docker.compose.project=${$}`,"--filter","label=com.docker.compose.service=postgres","--filter","health=healthy","--format","{{.Names}}"],{encoding:"utf-8",timeout:3e3}).trim().length>0)}catch{}b||s.push({id:"prisma",ok:!1,message:"A Prisma resource is configured, but the project Postgres service is not healthy",fix:"Run `tdk up` to start the bundled Postgres, then check `tdk doctor`."})}}let l=s.filter(f=>!f.ok).slice(0,8),u=l.some(f=>["node","docker","compose","tilt","bun","ports"].includes(f.id)),d=l.some(f=>f.id==="bun"),p=l.length?u?d?`Cold start blocked. Bun ${Tt} must be installed on PATH.
447
+ Prisma/NATS configuration is project-specific and generated after \`tdk project\`. Fix the machine checks below.`:"Cold start blocked. Bun/Prisma/NATS are not the first failure.\nThey are generated after `tdk project`. Fix the machine checks below.":"Machine is ready. Project wiring is not.":"",h=l.length?"":r?"Environment ready for TDK":`This machine is ready for TDK.
448
+ Next: tdk project --yes`;return{ok:l.length===0,inProject:r,items:l,header:p,footer:h}}function zu(e,t={}){let n=[e.header];for(let r of e.items)n.push(`FAIL ${r.id.padEnd(7)} ${r.message}`),r.fix&&n.push(` ${r.fix}`);return e.footer&&(t.includeSuccessFooter??!0)&&n.push(e.footer),n.filter(Boolean).join(`
449
+ `)}async function Sy(){let e=await qu();e.items.some(n=>["node","docker","compose","tilt","bun","ports"].includes(n.id))&&(console.error(zu(e)),process.exit(1))}export{Pt as a,m as b,vr as c,qr as d,J as e,j as f,yr as g,C as h,Je as i,qe as j,_ as k,A as l,Dt as m,cp as n,P as o,Pe as p,lp as q,y as r,$r as s,De as t,of as u,af as v,O as w,Zr as x,Ka as y,rs as z,Va as A,xf as B,wf as C,os as D,Df as E,N as F,Y as G,Of as H,Ja as I,Nf as J,Cf as K,jf as L,T as M,Lf as N,Mf as O,Uf as P,Bf as Q,Hf as R,Gf as S,Kf as T,Vf as U,Wf as V,zt as W,Jf as X,qf as Y,zf as Z,Yf as _,Xf as $,Qf as aa,Zf as ba,em as ca,I as da,Ft as ea,ka as fa,Lt as ga,_r as ha,Mr as ia,Yp as ja,Gr as ka,Re as la,ef as ma,Kt as na,as as oa,ec as pa,tc as qa,sm as ra,om as sa,im as ta,am as ua,cm as va,Yt as wa,nn as xa,ps as ya,ac as za,x as Aa,Ne as Ba,bm as Ca,Tm as Da,xm as Ea,wm as Fa,Em as Ga,vm as Ha,lc as Ia,Pm as Ja,ye as Ka,zg as La,qo as Ma,nk as Na,rk as Oa,kt as Pa,Xl as Qa,Ql as Ra,Zh as Sa,bp as Ta,ta as Ua,Tp as Va,xp as Wa,Ce as Xa,nt as Ya,an as Za,rt as _a,Hm as $a,_c as ab,Rc as bb,Gm as cb,ak as db,Yo as eb,ck as fb,lk as gb,lg as hb,Tg as ib,xo as jb,jn as kb,Ao as lb,Ld as mb,cn as nb,Ss as ob,bs as pb,Ts as qb,ln as rb,it as sb,Qm as tb,Ps as ub,_s as vb,fn as wb,mn as xb,hn as yb,Vs as zb,kh as Ab,yh as Bb,Le as Cb,vn as Db,Me as Eb,at as Fb,Nh as Gb,Ch as Hb,jh as Ib,An as Jb,Ol as Kb,jl as Lb,Uh as Mb,yk as Nb,Sk as Ob,Zo as Pb,Hu as Qb,li as Rb,Wu as Sb,qu as Tb,zu as Ub,Sy as Vb};