@tdk-landscape/tdk-cli-core 1.3.148 → 1.3.150

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,50 +1,50 @@
1
1
  import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
- import{c as kn}from"./chunk-42IVF3YT.js";import{execFileSync as Js}from"node:child_process";import{readFileSync as cu}from"node:fs";import{join as uu}from"node:path";import{execFileSync as $c,execSync as Ms}from"node:child_process";import{existsSync as C,readdirSync as Rc,readFileSync as ae}from"node:fs";import{join as v,normalize as an,relative as cn}from"node:path";function yn(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 Sn(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 kr}from"./chunk-42IVF3YT.js";import{execFileSync as Js}from"node:child_process";import{readFileSync as cu}from"node:fs";import{join as uu}from"node:path";import{execFileSync as $c,execSync as Ls}from"node:child_process";import{existsSync as C,readdirSync as Rc,readFileSync as ae}from"node:fs";import{join as v,normalize as ir,relative as ar}from"node:path";function yr(e,t,r){let n=e.indexOf(t);if(n===-1)return e;let s=t.length,o=0,i="";do i+=e.slice(o,n)+t+r,o=n+s,n=e.indexOf(t,o);while(n!==-1);return i+=e.slice(o),i}function Sr(e,t,r,n){let s=0,o="";do{let i=e[n-1]==="\r";o+=e.slice(s,i?n-1:n)+t+(i?`\r
3
3
  `:`
4
- `)+n,s=r+1,r=e.indexOf(`
5
- `,s)}while(r!==-1);return o+=e.slice(s),o}var bn=(e=0)=>t=>`\x1B[${t+e}m`,tt=(e=0)=>t=>`\x1B[${38+e};5;${t}m`,nt=(e=0)=>(t,n,r)=>`\x1B[${38+e};2;${t};${n};${r}m`,zs=e=>`\x1B[58;5;${e<90?e-30:e-90+8}m`,T={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]}},gu=Object.keys(T.modifier),Ys=Object.keys(T.color),Xs=Object.keys(T.bgColor),ku=Object.keys(T.underlineColor),yu=[...Ys,...Xs];function Zs(){let e=new Map;for(let[t,n]of Object.entries(T)){for(let[r,s]of Object.entries(n))T[r]={open:`\x1B[${s[0]}m`,close:`\x1B[${s[1]}m`},n[r]=T[r],e.set(Number.parseInt(s[0],10),s[1]);Object.defineProperty(T,t,{value:n,enumerable:!1})}return Object.defineProperty(T,"codes",{value:e,enumerable:!1}),T.color.close="\x1B[39m",T.bgColor.close="\x1B[49m",T.underlineColor.close="\x1B[59m",T.color.ansi=bn(),T.color.ansi256=tt(),T.color.ansi16m=nt(),T.bgColor.ansi=bn(10),T.bgColor.ansi256=tt(10),T.bgColor.ansi16m=nt(10),T.underlineColor.ansi=zs,T.underlineColor.ansi256=tt(20),T.underlineColor.ansi16m=nt(20),Object.defineProperties(T,{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=>T.rgbToAnsi256(...T.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)=>T.ansi256ToAnsi(T.rgbToAnsi256(t,n,r)),enumerable:!1},hexToAnsi:{value:t=>T.ansi256ToAnsi(T.hexToAnsi256(t)),enumerable:!1}}),T}var Qs=Zs(),L=Qs;import rt from"node:process";import eo from"node:os";import Tn from"node:tty";function N(e,t=globalThis.Deno?globalThis.Deno.args:rt.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:x}=rt,$e;N("no-color")||N("no-colors")||N("color=false")||N("color=never")?$e=0:(N("color")||N("colors")||N("color=true")||N("color=always"))&&($e=1);function Pn(){return/^\d+$/.test(x.FORCE_COLOR)}function to(){if("FORCE_COLOR"in x){if(x.FORCE_COLOR==="false")return 0;if(x.FORCE_COLOR==="true"||x.FORCE_COLOR.length===0)return 1;if(Pn())return Math.min(Number.parseInt(x.FORCE_COLOR,10),3)}}function no(e){return e===0?!1:{level:e,hasBasic:!0,has256:e>=2,has16m:e>=3}}function ro(e,{streamIsTTY:t,sniffFlags:n=!0}={}){let r=to();r!==void 0&&($e=r);let s=n?$e:r;if(s===0)return 0;if(n){if(N("color=16m")||N("color=full")||N("color=truecolor"))return 3;if(N("color=256"))return 2}if(s!==void 0&&Pn())return s;if("TF_BUILD"in x&&"AGENT_NAME"in x)return 1;if(e&&!t&&s===void 0)return 0;let o=s||0;if(x.TERM==="dumb")return o;if(rt.platform==="win32"){let i=eo.release().split(".");return Number(i[0])>=10&&Number(i[2])>=10586?Number(i[2])>=14931?3:2:1}if("CI"in x)return["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(i=>i in x)?3:["TRAVIS","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(i=>i in x)||x.CI_NAME==="codeship"?1:o;if("TEAMCITY_VERSION"in x)return/^(?:9\.0*[1-9]\d*\.|\d{2,}\.)/.test(x.TEAMCITY_VERSION)?1:0;if(x.COLORTERM==="truecolor"||x.TERM==="xterm-kitty"||x.TERM==="xterm-ghostty"||x.TERM==="wezterm")return 3;if("TERM_PROGRAM"in x){let i=Number.parseInt((x.TERM_PROGRAM_VERSION||"").split(".",1)[0],10);switch(x.TERM_PROGRAM){case"iTerm.app":return i>=3?3:2;case"Apple_Terminal":return 2}}return/-256(?:color)?$/i.test(x.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(x.TERM)||"COLORTERM"in x?1:o}function xn(e,t={}){let n=ro(e,{streamIsTTY:e&&e.isTTY,...t});return no(n)}var so={stdout:xn({isTTY:Tn.isatty(1)}),stderr:xn({isTTY:Tn.isatty(2)})},vn=so;var{stdout:En,stderr:wn}=vn,le=Symbol("GENERATOR"),pe=Symbol("STYLER"),_e=Symbol("IS_EMPTY"),Re=Symbol("LEVEL"),fe=Object.create(null),$n=e=>{if(!Number.isSafeInteger(e)||e<0||e>3)throw new Error("The `level` should be an integer from 0 to 3")},oo={enumerable:!0,get(){return this[Re]},set(e){$n(e),this[Re]=e}},io=(e,t={})=>{t.level!==void 0&&$n(t.level);let n=En?En.level:0;e[Re]=t.level===void 0?n:t.level};var ao=e=>{let t=(...n)=>n.join(" ");return io(t,e),Object.setPrototypeOf(t,me.prototype),t};function me(e){return ao(e)}Object.setPrototypeOf(me.prototype,Function.prototype);for(let[e,t]of Object.entries(L))fe[e]={get(){let n=ot(this,Rn(t.open,t.close,this[pe]),this[_e]);return Object.defineProperty(this,e,{value:n}),n}};fe.visible={get(){let e=ot(this,this[pe],!0);return Object.defineProperty(this,"visible",{value:e}),e}};var co=(e,t)=>{let n=L[t];if(e==="rgb"){let s=(i,a,c)=>n.ansi(L.rgbToAnsi(i,a,c));return[s,s,(i,a,c)=>n.ansi256(L.rgbToAnsi256(i,a,c)),n.ansi16m]}if(e==="hex"){let s=i=>n.ansi(L.hexToAnsi(i));return[s,s,i=>n.ansi256(L.hexToAnsi256(i)),i=>n.ansi16m(...L.hexToRgb(i))]}let r=s=>n.ansi(L.ansi256ToAnsi(s));return[r,r,n.ansi256,n.ansi256]},uo=["rgb","hex","ansi256"];for(let e of uo){let t=e[0].toUpperCase()+e.slice(1);for(let[n,r]of[[e,"color"],["bg"+t,"bgColor"],["underline"+t,"underlineColor"]]){let{close:s}=L[r],o=co(e,r);fe[n]={get(){let i=function(a,c,u){let d=o[this.level](a,c,u);return ot(this,Rn(d,s,this[pe]),this[_e])};return Object.defineProperty(this,n,{value:i}),i}}}}var lo=Object.defineProperties(()=>{},{...fe,level:{enumerable:!0,get(){return this[le].level},set(e){this[le].level=e}}}),Rn=(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}},ot=(e,t,n)=>{let r=(...s)=>s.length===1?st(r,""+s[0]):s.length===2?st(r,`${s[0]??""} ${s[1]??""}`):st(r,s.join(" "));return Object.setPrototypeOf(r,lo),r[le]=e[le]??e,r[pe]=t,r[_e]=n,r},st=(e,t)=>{if(e[le][Re]<=0||!t)return e[_e]?"":t;let n=e[pe];if(n===void 0)return t;let{openAll:r,closeAll:s}=n;if(t.includes("\x1B"))for(;n!==void 0;)t=yn(t,n.close,n.open),n=n.parent;let o=t.indexOf(`
6
- `);return o!==-1&&(t=Sn(t,s,r,o)),r+t+s};Object.defineProperties(me.prototype,{...fe,level:oo});var po=me(),$u=me({level:wn?wn.level:0});var f=po;import{Command as _c}from"commander";import{existsSync as fo}from"node:fs";var Oe="docs/agent-hosts.md",it=`WebContainers cannot run TDK: there is no Docker daemon or Tilt. Run \`tdk up\` on a machine with Docker. See ${Oe}.`,_n=`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 ${Oe}.`;function mo(){return{env:process.env,versions:process.versions,platform:process.platform,fileExists:fo}}function On(e=mo()){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 An(e){return e==="devcontainer"||e==="codespaces"}function w(e){return e==="backend"||e==="mcp"}function Ae(e){return e.some(t=>w(t.config?.appType)||t.config?.appType==="frontend"||t.config?.appType==="worker")}var A="Container Runtime",B="bring-your-own";var U="database-management",Nu=".tiltignore",Dn="service.json",he="docker-compose.yml",F=".autogenerated",ho="TILT_TECH_STACK.star",go="TILT_RESOURCE_DEFAULTS.star",P="project.json",D="package.json",at=[ho,go,"spec.master"],ju=["backend","frontend","library","sdk","worker","migrator","mcp",B],ct={backend:["dev","build","start"],worker:["dev","build","start"],migrator:["dev","build","start"],mcp:["dev","build","start"],frontend:["dev","build"],library:["dev","build"],sdk:["dev","build"],[B]:[]};var ut=["monitoring","elk","debezium","golden_image","verdaccio"],Iu={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"},[B]:{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"}},Cn={tiltUi:10350,traefik:8080},dt="https://tdk-landscape.github.io/tdk-website/docs/quickstart/";var Nn=["node_modules",".git",".tilt",".tilt-engine","dist","build",".prisma",".turbo","coverage","tmp","temp","__tests__","test","tests",".github",".vscode","docs"],jn=["Dockerfile",he,"docker-compose.yaml","Tiltfile","vite.config.ts","tsconfig.json","tsconfig.build.json"],ko={infra:"\u{1F3D7}\uFE0F",core:"\u{1F527}",api:"\u26A1",app:"\u{1F3A8}",orchestrator:"\u2699\uFE0F"};function Fu(e){let t=e.toLowerCase();for(let[n,r]of Object.entries(ko))if(t.includes(n))return r;return"\u{1F4E6}"}import{existsSync as yo,readFileSync as So}from"node:fs";import{join as bo,relative as In,resolve as Fn,sep as To}from"node:path";var xo=2,Mn=["services/*/*"];function Ln(e){return e.split(To).filter(Boolean)}function Po(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 vo(e,t){return e.length===t.length&&e.every((n,r)=>Po(n,t[r]))}function lt(e){let t=bo(e,".tdk",P);if(!yo(t))return Mn;try{let n=JSON.parse(So(t,"utf-8"))?.discovery?.paths;if(Array.isArray(n)&&n.every(r=>typeof r=="string"))return n}catch{}return Mn}function De(e,t,n){let r=Ln(In(e,Fn(e,t)));return n.some(s=>{let o=Ln(In(e,Fn(e,s)));for(let i=0;i<=xo;i++){let a=r.length-i;if(a>0&&vo(o,r.slice(0,a)))return!0}return!1})}function Hu(e,t,n,r){let s=lt(e);if(De(e,t,s))return{path:t};let o=`services/${n}/${r}`;return De(e,o,s)?{path:o,adjustedFrom:t}:{path:t}}import{statfsSync as Eo}from"node:fs";import{homedir as wo}from"node:os";var Ce="Disk Space",$o=1024**3,Ro=2,_o=10,Bn=["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(`
7
- `);function Un(e=Eo,t=wo()){let n;try{let s=e(t);n=Number(s.bavail)*Number(s.bsize)/$o}catch{return{name:Ce,didPass:!0,isSkipped:!0,message:"Could not read free disk space"}}let r=`${n.toFixed(1)} GB free`;return n<Ro?{name:Ce,didPass:!1,message:`${r}: Docker cannot build or start containers`,fix:Bn}:n<_o?{name:Ce,didPass:!1,isWarning:!0,message:`${r}: image builds may fail`,fix:Bn}:{name:Ce,didPass:!0,message:r}}var Oo="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 Hn(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:Oo}}async function Kn(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 Vn(e){let t=e.find(n=>n.name===A);return t?t.didPass:null}function Y(e,t,n=[],r,s){return{schemaVersion:1,data:{ready:n.length===0&&e.every(o=>o.didPass||o.isSkipped||o.isWarning),inProject:t,checks:e,...s?{host:{...s,containerRuntimeReachable:Vn(e),canUp:s.canUp&&Vn(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 Gn(e){return e.errors.length>0?2:e.data.ready?0:1}import{execFileSync as Nr,execSync as xe}from"node:child_process";import{existsSync as At,readdirSync as Fi,readFileSync as Dt}from"node:fs";import{join as te}from"node:path";function Ao(e,t,n){return e===1?t:n||`${t}s`}function S(e,t,n){return`${e} ${Ao(e,t,n)}`}var Do={month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"};function Yu(e){return new Date(e).toLocaleString("en-US",Do)}function Xu(e){return new Date(e).toLocaleDateString("en-US",{month:"short",day:"numeric"})}var pt={success:{color:"green",icon:"\u2713",chalkFn:f.green},error:{color:"red",icon:"\u2717",chalkFn:f.red},warning:{color:"yellow",icon:"\u25CB",chalkFn:f.yellow},unknown:{color:"gray",icon:"?",chalkFn:f.gray}};function ft(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 Zu(e){return pt[ft(e)].color}function Qu(e){return pt[ft(e)].icon}function ed(e,t){return pt[ft(t)].chalkFn(e)}var Co={resources:{singular:"resource",command:"tdk resource <name>",context:`
4
+ `)+r,s=n+1,n=e.indexOf(`
5
+ `,s)}while(n!==-1);return o+=e.slice(s),o}var br=(e=0)=>t=>`\x1B[${t+e}m`,tt=(e=0)=>t=>`\x1B[${38+e};5;${t}m`,rt=(e=0)=>(t,r,n)=>`\x1B[${38+e};2;${t};${r};${n}m`,zs=e=>`\x1B[58;5;${e<90?e-30:e-90+8}m`,T={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]}},gu=Object.keys(T.modifier),Ys=Object.keys(T.color),Xs=Object.keys(T.bgColor),ku=Object.keys(T.underlineColor),yu=[...Ys,...Xs];function Zs(){let e=new Map;for(let[t,r]of Object.entries(T)){for(let[n,s]of Object.entries(r))T[n]={open:`\x1B[${s[0]}m`,close:`\x1B[${s[1]}m`},r[n]=T[n],e.set(Number.parseInt(s[0],10),s[1]);Object.defineProperty(T,t,{value:r,enumerable:!1})}return Object.defineProperty(T,"codes",{value:e,enumerable:!1}),T.color.close="\x1B[39m",T.bgColor.close="\x1B[49m",T.underlineColor.close="\x1B[59m",T.color.ansi=br(),T.color.ansi256=tt(),T.color.ansi16m=rt(),T.bgColor.ansi=br(10),T.bgColor.ansi256=tt(10),T.bgColor.ansi16m=rt(10),T.underlineColor.ansi=zs,T.underlineColor.ansi256=tt(20),T.underlineColor.ansi16m=rt(20),Object.defineProperties(T,{rgbToAnsi256:{value(t,r,n){return t===r&&r===n?t<8?16:t>248?231:Math.round((t-8)/247*24)+232:16+36*Math.round(t/255*5)+6*Math.round(r/255*5)+Math.round(n/255*5)},enumerable:!1},hexToRgb:{value(t){let r=/[\da-f]{6}|[\da-f]{3}/i.exec(t.toString(16));if(!r)return[0,0,0];let[n]=r;n.length===3&&(n=[...n].map(o=>o+o).join(""));let s=Number.parseInt(n,16);return[s>>16&255,s>>8&255,s&255]},enumerable:!1},hexToAnsi256:{value:t=>T.rgbToAnsi256(...T.hexToRgb(t)),enumerable:!1},ansi256ToAnsi:{value(t){if(t<8)return 30+t;if(t<16)return 90+(t-8);let r,n,s;if(t>=232)r=((t-232)*10+8)/255,n=r,s=r;else{t-=16;let a=t%36;r=Math.floor(t/36)/5,n=Math.floor(a/6)/5,s=a%6/5}let o=Math.max(r,n,s)*2;if(o===0)return 30;let i=30+(Math.round(s)<<2|Math.round(n)<<1|Math.round(r));return o===2&&(i+=60),i},enumerable:!1},rgbToAnsi:{value:(t,r,n)=>T.ansi256ToAnsi(T.rgbToAnsi256(t,r,n)),enumerable:!1},hexToAnsi:{value:t=>T.ansi256ToAnsi(T.hexToAnsi256(t)),enumerable:!1}}),T}var Qs=Zs(),L=Qs;import nt from"node:process";import eo from"node:os";import Tr from"node:tty";function N(e,t=globalThis.Deno?globalThis.Deno.args:nt.argv){let r=e.startsWith("-")?"":e.length===1?"-":"--",n=t.indexOf(r+e),s=t.indexOf("--");return n!==-1&&(s===-1||n<s)}var{env:x}=nt,$e;N("no-color")||N("no-colors")||N("color=false")||N("color=never")?$e=0:(N("color")||N("colors")||N("color=true")||N("color=always"))&&($e=1);function Pr(){return/^\d+$/.test(x.FORCE_COLOR)}function to(){if("FORCE_COLOR"in x){if(x.FORCE_COLOR==="false")return 0;if(x.FORCE_COLOR==="true"||x.FORCE_COLOR.length===0)return 1;if(Pr())return Math.min(Number.parseInt(x.FORCE_COLOR,10),3)}}function ro(e){return e===0?!1:{level:e,hasBasic:!0,has256:e>=2,has16m:e>=3}}function no(e,{streamIsTTY:t,sniffFlags:r=!0}={}){let n=to();n!==void 0&&($e=n);let s=r?$e:n;if(s===0)return 0;if(r){if(N("color=16m")||N("color=full")||N("color=truecolor"))return 3;if(N("color=256"))return 2}if(s!==void 0&&Pr())return s;if("TF_BUILD"in x&&"AGENT_NAME"in x)return 1;if(e&&!t&&s===void 0)return 0;let o=s||0;if(x.TERM==="dumb")return o;if(nt.platform==="win32"){let i=eo.release().split(".");return Number(i[0])>=10&&Number(i[2])>=10586?Number(i[2])>=14931?3:2:1}if("CI"in x)return["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(i=>i in x)?3:["TRAVIS","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(i=>i in x)||x.CI_NAME==="codeship"?1:o;if("TEAMCITY_VERSION"in x)return/^(?:9\.0*[1-9]\d*\.|\d{2,}\.)/.test(x.TEAMCITY_VERSION)?1:0;if(x.COLORTERM==="truecolor"||x.TERM==="xterm-kitty"||x.TERM==="xterm-ghostty"||x.TERM==="wezterm")return 3;if("TERM_PROGRAM"in x){let i=Number.parseInt((x.TERM_PROGRAM_VERSION||"").split(".",1)[0],10);switch(x.TERM_PROGRAM){case"iTerm.app":return i>=3?3:2;case"Apple_Terminal":return 2}}return/-256(?:color)?$/i.test(x.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(x.TERM)||"COLORTERM"in x?1:o}function xr(e,t={}){let r=no(e,{streamIsTTY:e&&e.isTTY,...t});return ro(r)}var so={stdout:xr({isTTY:Tr.isatty(1)}),stderr:xr({isTTY:Tr.isatty(2)})},vr=so;var{stdout:Er,stderr:wr}=vr,le=Symbol("GENERATOR"),pe=Symbol("STYLER"),_e=Symbol("IS_EMPTY"),Re=Symbol("LEVEL"),fe=Object.create(null),$r=e=>{if(!Number.isSafeInteger(e)||e<0||e>3)throw new Error("The `level` should be an integer from 0 to 3")},oo={enumerable:!0,get(){return this[Re]},set(e){$r(e),this[Re]=e}},io=(e,t={})=>{t.level!==void 0&&$r(t.level);let r=Er?Er.level:0;e[Re]=t.level===void 0?r:t.level};var ao=e=>{let t=(...r)=>r.join(" ");return io(t,e),Object.setPrototypeOf(t,me.prototype),t};function me(e){return ao(e)}Object.setPrototypeOf(me.prototype,Function.prototype);for(let[e,t]of Object.entries(L))fe[e]={get(){let r=ot(this,Rr(t.open,t.close,this[pe]),this[_e]);return Object.defineProperty(this,e,{value:r}),r}};fe.visible={get(){let e=ot(this,this[pe],!0);return Object.defineProperty(this,"visible",{value:e}),e}};var co=(e,t)=>{let r=L[t];if(e==="rgb"){let s=(i,a,c)=>r.ansi(L.rgbToAnsi(i,a,c));return[s,s,(i,a,c)=>r.ansi256(L.rgbToAnsi256(i,a,c)),r.ansi16m]}if(e==="hex"){let s=i=>r.ansi(L.hexToAnsi(i));return[s,s,i=>r.ansi256(L.hexToAnsi256(i)),i=>r.ansi16m(...L.hexToRgb(i))]}let n=s=>r.ansi(L.ansi256ToAnsi(s));return[n,n,r.ansi256,r.ansi256]},uo=["rgb","hex","ansi256"];for(let e of uo){let t=e[0].toUpperCase()+e.slice(1);for(let[r,n]of[[e,"color"],["bg"+t,"bgColor"],["underline"+t,"underlineColor"]]){let{close:s}=L[n],o=co(e,n);fe[r]={get(){let i=function(a,c,u){let d=o[this.level](a,c,u);return ot(this,Rr(d,s,this[pe]),this[_e])};return Object.defineProperty(this,r,{value:i}),i}}}}var lo=Object.defineProperties(()=>{},{...fe,level:{enumerable:!0,get(){return this[le].level},set(e){this[le].level=e}}}),Rr=(e,t,r)=>{let n,s;return r===void 0?(n=e,s=t):(n=r.openAll+e,s=t+r.closeAll),{open:e,close:t,openAll:n,closeAll:s,parent:r}},ot=(e,t,r)=>{let n=(...s)=>s.length===1?st(n,""+s[0]):s.length===2?st(n,`${s[0]??""} ${s[1]??""}`):st(n,s.join(" "));return Object.setPrototypeOf(n,lo),n[le]=e[le]??e,n[pe]=t,n[_e]=r,n},st=(e,t)=>{if(e[le][Re]<=0||!t)return e[_e]?"":t;let r=e[pe];if(r===void 0)return t;let{openAll:n,closeAll:s}=r;if(t.includes("\x1B"))for(;r!==void 0;)t=yr(t,r.close,r.open),r=r.parent;let o=t.indexOf(`
6
+ `);return o!==-1&&(t=Sr(t,s,n,o)),n+t+s};Object.defineProperties(me.prototype,{...fe,level:oo});var po=me(),$u=me({level:wr?wr.level:0});var f=po;import{Command as _c}from"commander";import{existsSync as fo}from"node:fs";var Oe="docs/agent-hosts.md",it=`WebContainers cannot run TDK: there is no Docker daemon or Tilt. Run \`tdk up\` on a machine with Docker. See ${Oe}.`,_r=`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 ${Oe}.`;function mo(){return{env:process.env,versions:process.versions,platform:process.platform,fileExists:fo}}function Or(e=mo()){let{env:t,versions:r,platform:n,fileExists:s}=e;return r.webcontainer?{kind:"webcontainer",canUp:!1}:t.CODESPACES==="true"?{kind:"codespaces",canUp:!0}:t.REMOTE_CONTAINERS||s("/.dockerenv")&&t.DEVCONTAINER?{kind:"devcontainer",canUp:!0}:n==="win32"?{kind:"native-windows",canUp:t.TDK_ALLOW_NATIVE_WINDOWS==="1"}:n==="linux"&&t.WSL_DISTRO_NAME?{kind:"wsl2",canUp:!0}:{kind:"local",canUp:!0}}function Ar(e){return e==="devcontainer"||e==="codespaces"}function w(e){return e==="backend"||e==="mcp"}function Ae(e){return e.some(t=>w(t.config?.appType)||t.config?.appType==="frontend"||t.config?.appType==="worker")}var A="Container Runtime",B="bring-your-own";var H="database-management",Nu=".tiltignore",Dr="service.json",he="docker-compose.yml",F=".autogenerated",ho="TILT_TECH_STACK.star",go="TILT_RESOURCE_DEFAULTS.star",P="project.json",D="package.json",at=[ho,go,"spec.master"],ju=["backend","frontend","library","sdk","worker","migrator","mcp",B],ct={backend:["dev","build","start"],worker:["dev","build","start"],migrator:["dev","build","start"],mcp:["dev","build","start"],frontend:["dev","build"],library:["dev","build"],sdk:["dev","build"],[B]:[]};var ut=["monitoring","elk","debezium","golden_image","verdaccio"],Iu={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"},[B]:{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"}},Cr={tiltUi:10350,traefik:8080},dt="https://tdk-landscape.github.io/tdk-website/docs/quickstart/";var Nr=["node_modules",".git",".tilt",".tilt-engine","dist","build",".prisma",".turbo","coverage","tmp","temp","__tests__","test","tests",".github",".vscode","docs"],jr=["Dockerfile",he,"docker-compose.yaml","Tiltfile","vite.config.ts","tsconfig.json","tsconfig.build.json"],ko={infra:"\u{1F3D7}\uFE0F",core:"\u{1F527}",api:"\u26A1",app:"\u{1F3A8}",orchestrator:"\u2699\uFE0F"};function Fu(e){let t=e.toLowerCase();for(let[r,n]of Object.entries(ko))if(t.includes(r))return n;return"\u{1F4E6}"}import{existsSync as yo,readFileSync as So}from"node:fs";import{join as bo,relative as Ir,resolve as Fr,sep as To}from"node:path";var xo=2,Mr=["services/*/*"];function Lr(e){return e.split(To).filter(Boolean)}function Po(e,t){let r=0,n=0,s=-1,o=0;for(;n<t.length;)if(r<e.length&&e[r]!=="*"&&(e[r]==="?"||e[r]===t[n]))r++,n++;else if(r<e.length&&e[r]==="*")s=r++,o=n;else if(s!==-1)r=s+1,n=++o;else return!1;for(;r<e.length&&e[r]==="*";)r++;return r===e.length}function vo(e,t){return e.length===t.length&&e.every((r,n)=>Po(r,t[n]))}function lt(e){let t=bo(e,".tdk",P);if(!yo(t))return Mr;try{let r=JSON.parse(So(t,"utf-8"))?.discovery?.paths;if(Array.isArray(r)&&r.every(n=>typeof n=="string"))return r}catch{}return Mr}function De(e,t,r){let n=Lr(Ir(e,Fr(e,t)));return r.some(s=>{let o=Lr(Ir(e,Fr(e,s)));for(let i=0;i<=xo;i++){let a=n.length-i;if(a>0&&vo(o,n.slice(0,a)))return!0}return!1})}function Hu(e,t,r,n){let s=lt(e);if(De(e,t,s))return{path:t};let o=`services/${r}/${n}`;return De(e,o,s)?{path:o,adjustedFrom:t}:{path:t}}import{statfsSync as Eo}from"node:fs";import{homedir as wo}from"node:os";var Ce="Disk Space",$o=1024**3,Ro=2,_o=10,Br=["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(`
7
+ `);function Ur(e=Eo,t=wo()){let r;try{let s=e(t);r=Number(s.bavail)*Number(s.bsize)/$o}catch{return{name:Ce,didPass:!0,isSkipped:!0,message:"Could not read free disk space"}}let n=`${r.toFixed(1)} GB free`;return r<Ro?{name:Ce,didPass:!1,message:`${n}: Docker cannot build or start containers`,fix:Br}:r<_o?{name:Ce,didPass:!1,isWarning:!0,message:`${n}: image builds may fail`,fix:Br}:{name:Ce,didPass:!0,message:n}}var Oo="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 Hr(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:Oo}}async function Kr(e,t){let r=[],n=[],s=o=>{o.status==="fulfilled"?r.push(o.value):n.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:r,errors:n}}function Vr(e){let t=e.find(r=>r.name===A);return t?t.didPass:null}function Y(e,t,r=[],n,s){return{schemaVersion:1,data:{ready:r.length===0&&e.every(o=>o.didPass||o.isSkipped||o.isWarning),inProject:t,checks:e,...s?{host:{...s,containerRuntimeReachable:Vr(e),canUp:s.canUp&&Vr(e)!==!1}}:{},...n!==void 0?{ports:{http:{requested:n?.requested.ingressHttp??80,chosen:n?.ingressHttp??null,explicit:n?.explicit.ingressHttp??!!process.env.TDK_HTTP_PORT,reason:n?.reason.ingressHttp??"port planning failed"},https:{requested:n?.requested.ingressHttps??443,chosen:n?.ingressHttps??null,explicit:n?.explicit.ingressHttps??!!process.env.TDK_HTTPS_PORT,reason:n?.reason.ingressHttps??"port planning failed"},postgres:{requested:n?.requested.postgres??5432,chosen:n?.postgres??null,explicit:n?.explicit.postgres??!!process.env.TDK_POSTGRES_PORT,reason:n?.reason.postgres??"port planning failed"}}}:{}},errors:r}}function Gr(e){return e.errors.length>0?2:e.data.ready?0:1}import{execFileSync as jn,execSync as xe}from"node:child_process";import{existsSync as At,readdirSync as Fi,readFileSync as Dt}from"node:fs";import{join as te}from"node:path";function Ao(e,t,r){return e===1?t:r||`${t}s`}function S(e,t,r){return`${e} ${Ao(e,t,r)}`}var Do={month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"};function Yu(e){return new Date(e).toLocaleString("en-US",Do)}function Xu(e){return new Date(e).toLocaleDateString("en-US",{month:"short",day:"numeric"})}var pt={success:{color:"green",icon:"\u2713",chalkFn:f.green},error:{color:"red",icon:"\u2717",chalkFn:f.red},warning:{color:"yellow",icon:"\u25CB",chalkFn:f.yellow},unknown:{color:"gray",icon:"?",chalkFn:f.gray}};function ft(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 Zu(e){return pt[ft(e)].color}function Qu(e){return pt[ft(e)].icon}function ed(e,t){return pt[ft(t)].chalkFn(e)}var Co={resources:{singular:"resource",command:"tdk resource <name>",context:`
8
8
  To create a resource:`},stacks:{singular:"stack",command:"tdk stack <stack-name>",context:`
9
9
  To create a stack, use:`},services:{singular:"service",command:"tdk resource <name>",context:`
10
10
  To create a service:`},"stack-services":{singular:"service",command:"tdk resource <name> --stack <stack-name>",context:`
11
- To add services to this stack:`}};function td(e,t){let n=Co[e];console.log(t?f.yellow(`No ${n.singular}s found${t}.`):f.yellow(`No ${n.singular}s found.`)),console.log(f.gray(n.context)),console.log(f.gray(` ${n.command}`)),e==="stacks"&&(console.log(f.gray(`
12
- Or create a new resource with a stack:`)),console.log(f.gray(" tdk resource <name> --stack <stack-name>")))}function nd(e){console.log(f.yellow(e||"Cancelled."))}function rd(e){console.log(f.blue(`TDK ${e}
13
- `))}function sd(e,t){console.log(f.green(`All ${e} are ${t}!`))}var mt=62;function od(e="\u2500",t=mt){return e.repeat(t)}function Wn(e,t=mt-2){let n=Math.max(0,t-e.length),r=Math.floor(n/2),s=n-r;return" ".repeat(r)+e+" ".repeat(s)}function id(e,t){return e.length>t?`${e.slice(0,t-1)}\u2026`:e.padEnd(t)}function ad(e,t){return e.length<=t?e:`${e.slice(0,t-3)}...`}function cd(e){console.log(f.green(`\u2713 ${e}`))}function ud(e){console.log(f.blue(e))}function dd(e,t=2){console.log(f.gray(`${" ".repeat(t)}${e}`))}function ld(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function pd(e,t,n=mt){let r=n-2,s="\u2500".repeat(r);console.log(),console.log(f.cyan(`\u256D${s}\u256E`)),console.log(f.cyan("\u2502")+f.bold.white(Wn(e,r))+f.cyan("\u2502")),t&&(console.log(f.cyan(`\u251C${s}\u2524`)),console.log(f.cyan("\u2502")+f.gray(Wn(t,r))+f.cyan("\u2502"))),console.log(f.cyan(`\u2570${s}\u256F`))}import{existsSync as jo}from"node:fs";import{dirname as Io,join as Fo,resolve as qn}from"node:path";import{cwd as Mo}from"node:process";var Jn={name:"tdk-cli-internal",private:!0,version:"1.3.148",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:"^7.1.1",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 m(e=Mo()){let t=qn(e),n=qn("/");for(;t!==n;){if(jo(Fo(t,".tdk",P)))return t;let r=Io(t);if(r===t)break;t=r}return null}var Ne=null;function Lo(){if(Ne)return Ne;let e=Jn;if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Invalid package.json: expected object");let t=e;return Ne={name:String(t.name??"@tdk-landscape/tdk-cli-core"),version:String(t.version??"0.0.0"),fullPackage:t},Ne}function zn(){return Lo().version}import{readFileSync as Bo}from"node:fs";import{join as Uo}from"node:path";function je(){let e=m();if(e)try{let t=Bo(Uo(e,".tdk",P),"utf-8"),n=JSON.parse(t);if(n?.project?.name)return n.project.name}catch{}return"tdk-project"}function ht(e){let t=je(),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 Ho(e){return`${e.replace(/\/+$/,"")}/health`}function gt(e){if(w(e.config?.appType)){let t=e.name.replace(/-api$/,"");return e.config?.apiPath??`/api/${t}`}return e.config?.basePath??`/${e.name}`}function kt(e,t){return Xn(e,t,n=>Ho(n))}function Yn(e,t){return Xn(e,t,n=>n)}function Xn(e,t,n){let{appBase:r,apiBase:s}=ht(t);return e.filter(o=>o.config?.appType==="frontend"||w(o.config?.appType)).map(o=>{let i=w(o.config.appType)?s:r;return{name:o.name,appType:o.config.appType,url:`${i}${n(gt(o))}`}})}async function Vo(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 Ie(e,t){return Promise.all(e.map(n=>Vo(n,t)))}import{existsSync as ee,readdirSync as Er,readFileSync as wr,statSync as Et}from"node:fs";import{dirname as Ri,join as J}from"node:path";var ge=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 Zn(e){let t=0;return{isValid(){return Date.now()-t<e},markUpdated(){t=Date.now()},reset(){t=0}}}import{execFileSync as Zo,execSync as Qo}from"node:child_process";import{existsSync as qo}from"node:fs";import{delimiter as zo,extname as Yo,join as Xo}from"node:path";import{delimiter as _d,extname as Ko}from"node:path";function Fe(){return process.platform==="win32"}function Go(e){return e==="linux"?"linux":e==="darwin"?"darwin":e==="win32"?"windows":null}function Wo(e){return e==="x64"?"amd64":e==="arm64"?"arm64":null}function Jo(e,t){let n=Go(e),r=Wo(t);if(!n||!r||n==="windows"&&r!=="amd64")return null;let s=`tdk-${n}-${r}`;return n==="windows"?`${s}.exe`:s}function Od(){return Jo(process.platform,process.arch)}function Ad(){return Fe()?"tdk.exe":"tdk"}function Qn(e,t=Fe()){return t?Ko(e)?[e]:[e,`${e}.exe`,`${e}.cmd`,`${e}.bat`]:[e]}function $(e){let t=process.env.PATH??process.env.Path??"",n=Fe(),r=Qn(e,n);if(n&&!Yo(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(zo))if(s)for(let o of r){let i=Xo(s,o);if(qo(i))return i}return null}var er=1e4;function tr(){let e=!1;if(process.platform==="win32")try{return Zo($("docker")??"docker",["ps"],{stdio:"ignore",timeout:er,windowsHide:!0}),"running"}catch(t){return t.code==="ETIMEDOUT"?"unresponsive":"missing"}for(let t of["docker ps","colima status","podman ps"])try{return Qo(t,{stdio:"ignore",timeout:er}),"running"}catch(n){n.code==="ETIMEDOUT"&&(e=!0)}return e?"unresponsive":"missing"}function Me(e,t){return e[t]??0}function ei(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(Me(s,o-1)+1,Me(n,o)+1,Me(n,o-1)+i)}n=s}return Me(n,t.length)}function ti(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 nr(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=ti(n,i)?1:ei(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 ni}from"node:child_process";import{join as ri}from"node:path";function si(e,t=[],n={}){return new Promise((r,s)=>{let o=[e,...t];n.verbose&&console.log(`Executing: tilt ${o.join(" ")}`);let i=ni($("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 rr(){try{return(await si("version",[],{inheritStdio:!1,timeoutMs:1e4})).exitCode===0}catch{return!1}}function oi(){let e=m();if(!e)throw H.notInProject();return ri(e,".tdk",".tdk-out","Tiltfile")}function sr(e){let t=oi();e.push("-f",t)}function Wd(e,t={}){let n=[];return sr(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 Jd(e={}){let t=[];return sr(t),e.force&&t.push("--force"),e.focusTargets&&e.focusTargets.length>0&&t.push("--",`--focus=${e.focusTargets.join(",")}`),t}function or(e){return e instanceof Error?e.message:String(e)}function tl(e,t){if(process.env.TDK_VERBOSE){let n=t!==void 0?`: ${or(t)}`:"";console.warn(f.gray(`${e}${n}`))}}var R=class extends Error{suggestions;exitCode;constructor(t,n=[],r=1){super(t),this.name="TdkError",this.suggestions=n,this.exitCode=r}display(){ci(this.message,void 0,this.suggestions)}exit(){this.display(),process.exit(this.exitCode)}};function yt(e,t,n=!1){let r=new Set;for(let s of e){let o=nr(s,t);o&&r.add(n?`Did you mean "${o}" for "${s}"?`:`Did you mean "${o}"?`)}return[...r]}var H={tiltNotInstalled:()=>new R("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: ${dt}`]),dockerNotAvailable:()=>new R("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: ${dt}`]),dockerNotResponding:()=>new R("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 R(`Stack "${e}" not found`,[...yt([e],t),"Run `tdk stacks` to see available stacks","Run `tdk stack` to assign resources to a stack"]),resourceNotFound:(e,t=[])=>new R(`Resource "${e}" not found`,[...yt([e],t),"Run `tdk resources` to list all resources","Check the resource name spelling"]),unknownServices:(e,t)=>{let n=yt(e,t,e.length>1);return new R(`Unknown service ${e.join(", ")}. Valid names: ${t.join(", ")}`,n,2)},directoryExists:e=>new R(`Directory already exists: ${e}`,["Use `--path` to specify a different location","Remove the existing directory if no longer needed"]),invalidPath:e=>new R(`Invalid path: ${e}`,["Path must be within the project directory",'Path cannot contain special characters like <>:"|?*']),notInProject:()=>new R("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 nl(){let e=m();return e||H.notInProject().exit()}function ii(e){e instanceof R&&e.exit(),console.error(f.red(`Error: ${or(e)}`)),process.exit(1)}async function ai(e,t){try{return await e()}catch(n){return t?.verbose&&n instanceof Error&&n.stack&&console.error(f.gray(n.stack)),ii(n)}}async function rl(e,t){let n=[],r=tr();return r==="unresponsive"?n.push(H.dockerNotResponding()):r==="missing"&&n.push(H.dockerNotAvailable()),await rr()||n.push(H.tiltNotInstalled()),n.length>0&&(console.error(f.red(`
11
+ To add services to this stack:`}};function td(e,t){let r=Co[e];console.log(t?f.yellow(`No ${r.singular}s found${t}.`):f.yellow(`No ${r.singular}s found.`)),console.log(f.gray(r.context)),console.log(f.gray(` ${r.command}`)),e==="stacks"&&(console.log(f.gray(`
12
+ Or create a new resource with a stack:`)),console.log(f.gray(" tdk resource <name> --stack <stack-name>")))}function rd(e){console.log(f.yellow(e||"Cancelled."))}function nd(e){console.log(f.blue(`TDK ${e}
13
+ `))}function sd(e,t){console.log(f.green(`All ${e} are ${t}!`))}var mt=62;function od(e="\u2500",t=mt){return e.repeat(t)}function Wr(e,t=mt-2){let r=Math.max(0,t-e.length),n=Math.floor(r/2),s=r-n;return" ".repeat(n)+e+" ".repeat(s)}function id(e,t){return e.length>t?`${e.slice(0,t-1)}\u2026`:e.padEnd(t)}function ad(e,t){return e.length<=t?e:`${e.slice(0,t-3)}...`}function cd(e){console.log(f.green(`\u2713 ${e}`))}function ud(e){console.log(f.blue(e))}function dd(e,t=2){console.log(f.gray(`${" ".repeat(t)}${e}`))}function ld(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function pd(e,t,r=mt){let n=r-2,s="\u2500".repeat(n);console.log(),console.log(f.cyan(`\u256D${s}\u256E`)),console.log(f.cyan("\u2502")+f.bold.white(Wr(e,n))+f.cyan("\u2502")),t&&(console.log(f.cyan(`\u251C${s}\u2524`)),console.log(f.cyan("\u2502")+f.gray(Wr(t,n))+f.cyan("\u2502"))),console.log(f.cyan(`\u2570${s}\u256F`))}import{existsSync as jo}from"node:fs";import{dirname as Io,join as Fo,resolve as qr}from"node:path";import{cwd as Mo}from"node:process";var Jr={name:"tdk-cli-internal",private:!0,version:"1.3.150",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:"^7.1.1",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 m(e=Mo()){let t=qr(e),r=qr("/");for(;t!==r;){if(jo(Fo(t,".tdk",P)))return t;let n=Io(t);if(n===t)break;t=n}return null}var Ne=null;function Lo(){if(Ne)return Ne;let e=Jr;if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Invalid package.json: expected object");let t=e;return Ne={name:String(t.name??"@tdk-landscape/tdk-cli-core"),version:String(t.version??"0.0.0"),fullPackage:t},Ne}function zr(){return Lo().version}import{readFileSync as Bo}from"node:fs";import{join as Uo}from"node:path";function je(){let e=m();if(e)try{let t=Bo(Uo(e,".tdk",P),"utf-8"),r=JSON.parse(t);if(r?.project?.name)return r.project.name}catch{}return"tdk-project"}function ht(e){let t=je(),r=process.env.TDK_SERVICE_BASE_URL??`http://${t}.localhost${e?`:${e}`:""}`;try{let n=new URL(r.includes("://")?r:`http://${r}`),s=n.hostname,o=n.protocol==="https:"?"443":"80",i=n.port||(e?String(e):""),a=i===o?"":i;if(s==="localhost"||/^\d+\.\d+\.\d+\.\d+$/.test(s))return{appBase:`${n.protocol}//${s}${a?`:${a}`:""}`,apiBase:`${n.protocol}//${s}${a?`:${a}`:""}`};let c=s.replace(/^(app|api)\./,"");return{appBase:`${n.protocol}//app.${c}${a?`:${a}`:""}`,apiBase:`${n.protocol}//api.${c}${a?`:${a}`:""}`}}catch{return{appBase:`http://app.${t}.localhost`,apiBase:`http://api.${t}.localhost`}}}function Ho(e){return`${e.replace(/\/+$/,"")}/health`}function gt(e){if(w(e.config?.appType)){let t=e.name.replace(/-api$/,"");return e.config?.apiPath??`/api/${t}`}return e.config?.basePath??`/${e.name}`}function kt(e,t){return Xr(e,t,r=>Ho(r))}function Yr(e,t){return Xr(e,t,r=>r)}function Xr(e,t,r){let{appBase:n,apiBase:s}=ht(t);return e.filter(o=>o.config?.appType==="frontend"||w(o.config?.appType)).map(o=>{let i=w(o.config.appType)?s:n;return{name:o.name,appType:o.config.appType,url:`${i}${r(gt(o))}`}})}async function Vo(e,t){try{let r=await fetch(e.url,{method:"GET",redirect:"manual",signal:AbortSignal.timeout(t)});return{...e,ok:r.ok,status:r.status}}catch(r){let n=r instanceof Error&&r.name==="TimeoutError"?`no response within ${t}ms`:r instanceof Error?r.message:String(r);return{...e,ok:!1,error:n}}}async function Ie(e,t){return Promise.all(e.map(r=>Vo(r,t)))}import{existsSync as ee,readdirSync as wn,readFileSync as $n,statSync as Et}from"node:fs";import{dirname as Ri,join as J}from"node:path";var ge=class{data;options;constructor(t){this.data=new Map,this.options=t}has(t){let r=this.data.get(t);return r?Date.now()-r.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,r){this.data.set(t,{value:r,timestamp:Date.now()})}delete(t){this.data.delete(t)}clear(){this.data.clear()}keys(){let t=[];for(let r of this.data.keys())this.has(r)&&t.push(r);return t}size(){return this.keys().length}};function Zr(e){let t=0;return{isValid(){return Date.now()-t<e},markUpdated(){t=Date.now()},reset(){t=0}}}import{execFileSync as Zo,execSync as Qo}from"node:child_process";import{existsSync as qo}from"node:fs";import{delimiter as zo,extname as Yo,join as Xo}from"node:path";import{delimiter as _d,extname as Ko}from"node:path";function Fe(){return process.platform==="win32"}function Go(e){return e==="linux"?"linux":e==="darwin"?"darwin":e==="win32"?"windows":null}function Wo(e){return e==="x64"?"amd64":e==="arm64"?"arm64":null}function Jo(e,t){let r=Go(e),n=Wo(t);if(!r||!n||r==="windows"&&n!=="amd64")return null;let s=`tdk-${r}-${n}`;return r==="windows"?`${s}.exe`:s}function Od(){return Jo(process.platform,process.arch)}function Ad(){return Fe()?"tdk.exe":"tdk"}function Qr(e,t=Fe()){return t?Ko(e)?[e]:[e,`${e}.exe`,`${e}.cmd`,`${e}.bat`]:[e]}function $(e){let t=process.env.PATH??process.env.Path??"",r=Fe(),n=Qr(e,r);if(r&&!Yo(e))for(let s of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let o=s.toLowerCase();o&&!n.includes(`${e}${o}`)&&n.push(`${e}${o}`)}for(let s of t.split(zo))if(s)for(let o of n){let i=Xo(s,o);if(qo(i))return i}return null}var en=1e4;function tn(){let e=!1;if(process.platform==="win32")try{return Zo($("docker")??"docker",["ps"],{stdio:"ignore",timeout:en,windowsHide:!0}),"running"}catch(t){return t.code==="ETIMEDOUT"?"unresponsive":"missing"}for(let t of["docker ps","colima status","podman ps"])try{return Qo(t,{stdio:"ignore",timeout:en}),"running"}catch(r){r.code==="ETIMEDOUT"&&(e=!0)}return e?"unresponsive":"missing"}function Me(e,t){return e[t]??0}function ei(e,t){let r=Array.from({length:t.length+1},(n,s)=>s);for(let n=1;n<=e.length;n++){let s=[n];for(let o=1;o<=t.length;o++){let i=e[n-1]===t[o-1]?0:1;s[o]=Math.min(Me(s,o-1)+1,Me(r,o)+1,Me(r,o-1)+i)}r=s}return Me(r,t.length)}function ti(e,t){if(e.length!==t.length)return!1;for(let r=0;r<e.length-1;r++)if(e[r]!==t[r]&&e[r]===t[r+1]&&e[r+1]===t[r]&&e.slice(0,r)===t.slice(0,r)&&e.slice(r+2)===t.slice(r+2))return!0;return!1}function rn(e,t){if(e.length<2||t.length===0||t.includes(e))return;let r=e.toLowerCase(),n,s=Number.POSITIVE_INFINITY;for(let o of t){if(o.length===0)continue;let i=o.toLowerCase(),a=ti(r,i)?1:ei(r,i),c=Math.max(1,Math.min(2,Math.floor(Math.max(r.length,i.length)/3)));a>c||(a<s||a===s&&(n===void 0||o<n))&&(n=o,s=a)}return n}import{spawn as ri}from"node:child_process";import{join as ni}from"node:path";function si(e,t=[],r={}){return new Promise((n,s)=>{let o=[e,...t];r.verbose&&console.log(`Executing: tilt ${o.join(" ")}`);let i=ri($("tilt")??"tilt",o,{stdio:r.inheritStdio?"inherit":"pipe",shell:!1,windowsHide:process.platform==="win32",timeout:r.timeoutMs}),a="",c="";r.inheritStdio||(i.stdout?.on("data",u=>{a+=u.toString()}),i.stderr?.on("data",u=>{c+=u.toString()})),i.on("close",u=>{n({exitCode:u??1,stdout:a,stderr:c})}),i.on("error",u=>{s(new Error(`Failed to spawn tilt: ${u.message}`))})})}async function nn(){try{return(await si("version",[],{inheritStdio:!1,timeoutMs:1e4})).exitCode===0}catch{return!1}}function oi(){let e=m();if(!e)throw V.notInProject();return ni(e,".tdk",".tdk-out","Tiltfile")}function sn(e){let t=oi();e.push("-f",t)}function Wd(e,t={}){let r=[];return sn(r),t.focusTargets&&t.focusTargets.length>0&&r.push("--",`--focus=${t.focusTargets.join(",")}`),r.push(...e),t.verbose&&!t.quiet&&r.push("--verbose"),t.watch&&r.push("--watch"),r}function Jd(e={}){let t=[];return sn(t),e.force&&t.push("--force"),e.focusTargets&&e.focusTargets.length>0&&t.push("--",`--focus=${e.focusTargets.join(",")}`),t}function on(e){return e instanceof Error?e.message:String(e)}function tl(e,t){if(process.env.TDK_VERBOSE){let r=t!==void 0?`: ${on(t)}`:"";console.warn(f.gray(`${e}${r}`))}}var R=class extends Error{suggestions;exitCode;constructor(t,r=[],n=1){super(t),this.name="TdkError",this.suggestions=r,this.exitCode=n}display(){ci(this.message,void 0,this.suggestions)}exit(){this.display(),process.exit(this.exitCode)}};function yt(e,t,r=!1){let n=new Set;for(let s of e){let o=rn(s,t);o&&n.add(r?`Did you mean "${o}" for "${s}"?`:`Did you mean "${o}"?`)}return[...n]}var V={tiltNotInstalled:()=>new R("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: ${dt}`]),dockerNotAvailable:()=>new R("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: ${dt}`]),dockerNotResponding:()=>new R("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 R(`Stack "${e}" not found`,[...yt([e],t),"Run `tdk stacks` to see available stacks","Run `tdk stack` to assign resources to a stack"]),resourceNotFound:(e,t=[])=>new R(`Resource "${e}" not found`,[...yt([e],t),"Run `tdk resources` to list all resources","Check the resource name spelling"]),unknownServices:(e,t)=>{let r=yt(e,t,e.length>1);return new R(`Unknown service ${e.join(", ")}. Valid names: ${t.join(", ")}`,r,2)},directoryExists:e=>new R(`Directory already exists: ${e}`,["Use `--path` to specify a different location","Remove the existing directory if no longer needed"]),invalidPath:e=>new R(`Invalid path: ${e}`,["Path must be within the project directory",'Path cannot contain special characters like <>:"|?*']),notInProject:()=>new R("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 rl(){let e=m();return e||V.notInProject().exit()}function ii(e){e instanceof R&&e.exit(),console.error(f.red(`Error: ${on(e)}`)),process.exit(1)}async function ai(e,t){try{return await e()}catch(r){return t?.verbose&&r instanceof Error&&r.stack&&console.error(f.gray(r.stack)),ii(r)}}async function nl(e,t){let r=[],n=tn();return n==="unresponsive"?r.push(V.dockerNotResponding()):n==="missing"&&r.push(V.dockerNotAvailable()),await nn()||r.push(V.tiltNotInstalled()),r.length>0&&(console.error(f.red(`
14
14
  TDK can't start - missing prerequisites:
15
- `)),n.forEach((s,o)=>{o>0&&console.error(""),s.display()}),console.error(f.gray("\nRun `tdk doctor` for a full environment check.")),process.exit(1)),ai(e,t)}function sl(e,t=1){console.error(f.red(`Error: ${e}`)),process.exit(t)}function ci(e,t,n){if(console.error(f.red(`\u274C ${e}`)),t&&console.error(f.gray(` ${t}`)),n&&n.length>0){console.error(f.yellow(`
16
- \u{1F4A1} Suggestions:`));for(let r of n)console.error(f.cyan(` \u2192 ${r}`))}}function ol(e,t){console.error(f.red(`
17
- tilt ${e} failed with exit code ${t}`)),process.exit(t)}import{existsSync as br,readFileSync as Tr}from"node:fs";import{copyFileSync as ir,mkdirSync as ui,rmSync as ar,writeFileSync as cr}from"node:fs";import{join as Q}from"node:path";var mr=60,ur=1e3,dr=1e4,lr=200,pr=64*1024,fr=new Set([404,502,503,504]),di=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","EHOSTUNREACH","ENETUNREACH"]),li=new Set(["GET","HEAD","OPTIONS"]);function G(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function pi(e,t){if(li.has(t))return!0;if(!G(e))return!1;let n=G(e.cause)?e.cause:void 0,r=e.code??n?.code;return typeof r=="string"&&di.has(r)}function bt(e){if(!G(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(!G(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&&(G(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 hr(e,t){let{appBase:n,apiBase:r}=ht(t),s=[];for(let o of e){let i=o.config;if(!i?.smoke)continue;let a=i.appType,c=w(a)||a===B;if(!c&&a!=="frontend"||i.exposeViaProxy===!1)continue;let u=c?r:n,d=i.healthCheckPath||(c&&a!==B?"/health":void 0);s.push({name:o.name,baseUrl:`${u}${gt(o).replace(/\/+$/,"")}`,...d?.startsWith("/")?{readyPath:d}:{},smoke:i.smoke})}return s}var fi=10;function gr(e,t={}){let n=t.timeoutSeconds??fi;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??mr,n);return[{name:r.name,baseUrl:r.baseUrl,smoke:{via:r.smoke.via,timeoutSeconds:o,steps:s}}]})}function mi(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 kr(e,t){return e.replace(/\{\{(\w+)\}\}/g,(n,r)=>t[r]??n)}function St(e,t){return typeof e=="string"?kr(e,t):Array.isArray(e)?e.map(n=>St(n,t)):G(e)?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,St(r,t)])):e}function Le(e){let t=e.replace(/\s+/g," ").trim();return t.length>lr?`${t.slice(0,lr)}...`:t}function yr(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"step"}function hi(e,t){let n=yr(t),r=(e.get(n)??0)+1;return e.set(n,r),r===1?n:`${n}-${r}`}function gi(e,t,n,r,s){try{let o=Q(e,yr(n.service),t);ui(o,{recursive:!0});let i=Q(o,"latest.json"),a=Q(o,"body.txt");return r===void 0?ar(a,{force:!0}):cr(a,r),cr(i,`${JSON.stringify({...n,bodyPath:r===void 0?null:"body.txt"},null,2)}
18
- `),s&&(ir(i,Q(o,"last-success.json")),r===void 0?ar(Q(o,"last-success-body.txt"),{force:!0}):ir(a,Q(o,"last-success-body.txt"))),i}catch{return}}function ki(e){let t=Buffer.from(e,"utf8");if(t.length<=pr)return{body:e,truncated:!1,bytes:t.length};let n=t.subarray(0,pr).toString("utf8").replace(/\uFFFD$/,"");return{body:n,truncated:!0,bytes:Buffer.byteLength(n,"utf8")}}async function yi(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??mr)*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(dr)});if(await l.text(),!fr.has(l.status)&&l.status<500)break}catch{}if(r()>=i)break;await s(ur)}}i=r()+o;let u=new Map;for(let[d,l]of e.smoke.steps.entries()){let g=l.name??`step ${d+1}`,k=(l.method??"GET").toUpperCase(),h=`${e.baseUrl}${kr(l.path,a)}`,p=l.expect??200,y=l.body!==void 0,E,j="",K,et;for(;;){K=void 0,et=void 0,E=void 0;let I=!1;try{let _=await n(h,{method:k,headers:y?{"content-type":"application/json"}:void 0,body:y?JSON.stringify(St(l.body,a)):void 0,signal:AbortSignal.timeout(dr)});E=_.status,j=await _.text()}catch(_){I=pi(_,k),K=_ instanceof Error?_.message:String(_);let z=G(_)?_.code??(G(_.cause)?_.cause.code:void 0):void 0;et=typeof z=="string"?z:void 0}if(!(K!==void 0&&I||E!==void 0&&E!==p&&fr.has(E))||r()>=i)break;await s(ur)}let ce=`${e.name}: ${g}: ${k} ${h}`,gn;if(t.recordDir){let I=E===void 0?void 0:ki(j),de=K===void 0&&E===p&&(l.bodyContains===void 0||j.includes(l.bodyContains));gn=gi(t.recordDir,hi(u,g),{service:e.name,step:g,method:k,url:h,expectedStatus:p,status:E??null,...K===void 0?{}:{error:et??K},truncated:I?.truncated??!1,bodyBytes:I?.bytes??0},I?.body,de)}let ue=I=>({name:e.name,ok:!1,failure:I,recordPath:gn});if(K!==void 0)return ue(`${ce} never answered (${K})`);if(E!==p)return ue(`${ce} returned ${E}, expected ${p}${j?`: ${Le(j)}`:""}`);if(l.bodyContains!==void 0&&!j.includes(l.bodyContains))return ue(`${ce} returned ${E} but the body does not contain "${l.bodyContains}": ${Le(j)}`);if(l.save){let I;try{I=JSON.parse(j)}catch{return ue(`${ce} returned a body that is not JSON, cannot save: ${Le(j)}`)}for(let[de,_]of Object.entries(l.save)){let z=mi(I,_);if(z==null||typeof z=="object")return ue(`${ce} response has no ${_} to save as {{${de}}}: ${Le(j)}`);a[de]=String(z)}}}return{name:e.name,ok:!0}}function pl(e){return`Smoke check failed: ${e.failure}${e.recordPath?` (record: ${e.recordPath})`:""}`}async function Sr(e,t={}){return Promise.all(e.map(n=>yi(n,t)))}var ke=1,gl="https://tdk-landscape.github.io/schema.service.json",Si={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"},bi=new Set(["$schema","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"]),Ti=[{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 Be(e,t){let n=[],r=new Set;for(let{path:s,pattern:o,expected:i}of Ti){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 xi(e,t))r.has(s)||n.push(`${s}: ${o}`);return n}function Tt(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 xi(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))Tt(s)&&n.push([t,"a key contains a line break"]);for(;r.length>0;){let[s,o]=r.pop();if(typeof s=="string")Tt(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))Tt(i)?n.push([o,"a key contains a line break"]):r.push([a,`${o}.${i}`])}return n.sort(([s],[o])=>s.localeCompare(o))}var Pi=["apiPath","basePath"];function xt(e){if(!e||typeof e!="object"||Array.isArray(e))return[];let t=e;return Pi.filter(n=>n in t&&typeof t[n]!="string")}function Pt(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!==ke&&r.push(`${t}.schemaVersion: unsupported version ${String(n.schemaVersion)} (supported: ${ke})`);for(let a of xt(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(...Be(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=Si[a];return c?[`${t}.${a}: ${c}`]:bi.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 kl(e,t){if(!br(e))return[];try{let n=JSON.parse(Tr(e,"utf-8"));return!n||typeof n!="object"||Array.isArray(n)?[]:Be(n,t)}catch{return[]}}function yl(e,t){if(!br(e))return{errors:[`${t}: file is missing`],warnings:[]};try{let n=JSON.parse(Tr(e,"utf-8"));return Pt(n,t)}catch(n){let r=n instanceof Error?n.message:String(n);return{errors:[`${t}: invalid JSON (${r})`],warnings:[]}}}function xr(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 vi=/^[a-z0-9-]+$/;function Pr(e){return vi.test(e)}var Ei="Use lowercase letters, numbers, and hyphens only";function vr(e,t){return`${e} "${t}" is not valid. ${Ei}, e.g. "${e==="Resource name"?"my-service":"my-stack"}".`}function wi(e){return e.trim()?Pr(e)?{valid:!0}:{valid:!1,error:vr("Resource name",e)}:{valid:!1,error:"Resource name is required"}}function $i(e){return e.trim()?Pr(e)?{valid:!0}:{valid:!1,error:vr("Stack name",e)}:{valid:!1,error:"Stack name is required"}}function xl(e){let t=e==="resource"?wi:$i;return n=>{let r=t(n);return r.valid?!0:r.error??"Invalid name"}}function Pl(e){return vt(ut,e)?{valid:!0}:{valid:!1,error:`Invalid service. Must be one of: ${ut.join(", ")}`}}function vl(e){return Number.isInteger(e)&&e>0&&e<=65535}function El(e){return!e.includes("\0")&&!/[<>:"|?*]/.test(e)}function wl(e,t="_"){return e.replace(/[^a-zA-Z0-9-]/g,t).substring(0,100)}function vt(e,t){return e.includes(t)}var _i=Dn;function _t(e,t=5,n=0){let r=[];if(n>t)return r;let s=Er(e,{withFileTypes:!0});for(let o of s){let i=J(e,o.name);if(o.isDirectory()){if(Oi(o.name))continue;r.push(..._t(i,t,n+1))}else o.isFile()&&o.name===_i&&r.push(i)}return r}function Ml(e){return _t(e)}function Oi(e){return vt(Nn,e)||e.startsWith(".")}function Ai(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 Ue=new Set;var W=class extends Error{reason;constructor(t){super(t),this.reason=t,this.name="InvalidServiceJsonError"}};function wt(e){return e instanceof Error?e.message:String(e)}function Di(e){let t;try{t=wr(e,"utf-8")}catch(c){throw new W(`could not read file: ${wt(c)}`)}let n;try{n=JSON.parse(t)}catch(c){throw new W(`invalid JSON: ${wt(c)}`)}if(!Ai(n))throw new W("missing required fields (appName, runtime or appType)");let r=xt(n);if(r.length>0)throw new W(r.map(c=>`${c}: expected a string`).join("; "));let s=Be(n,e);if(s.length>0)throw new W(s.join("; "));let o=n;for(let c of Pt(n,e).warnings)Ue.has(c)||(Ue.add(c),console.warn(`\u26A0\uFE0F ${c}`));let i={...o,appType:o.appType||o.type},a=Ri(e);return{name:i.appName,path:a,configPath:e,config:i,stack:i.stack,port:i.port,type:i.appType}}function $r(e){let t=_t(e),n=[],r=[];for(let s of t)try{n.push(Di(s))}catch(o){r.push({path:s,reason:o instanceof W?o.reason:wt(o)})}return{resources:n,problems:r}}function Ci(e){for(let t of e){let n=`skipped ${t.path}: ${t.reason}`;Ue.has(n)||(Ue.add(n),console.warn(`\u26A0\uFE0F ${n}`))}}function b(e){let{resources:t,problems:n}=$r(e);return Ci(n),t}function Se(){let e=m();if(!e)throw H.notInProject();return b(e)}function Ll(){let e=m();if(!e)throw H.notInProject();let{resources:t,problems:n}=$r(e);if(n.length>0)throw new Error(n.map(r=>`Invalid service.json at ${r.path}: ${r.reason}`).join(`
19
- `));return t}function Bl(e){let t=b(e),n=new Set;for(let r of t)r.stack&&n.add(r.stack);return Array.from(n).sort()}function Ul(e){let t=e||Se(),n=new Set;for(let r of t)r.stack&&n.add(r.stack);return Array.from(n).sort()}function Hl(e=Se()){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:S(s.length,"resource"),resources:s,resourceCount:s.length});return n.sort((r,s)=>r.name.localeCompare(s.name))}function Vl(e,t){return(t??Se()).some(r=>r.stack===e)}var Ot=5e3,$t=new ge({ttlMs:Ot}),Rt=new ge({ttlMs:Ot}),ye=Zn(Ot);function Kl(){$t.clear(),Rt.clear(),ye.reset()}function Ni(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===D)return"config";if(e==="schema.prisma"||e.includes("migration"))return"prisma";if(t){let n=t.split(`
15
+ `)),r.forEach((s,o)=>{o>0&&console.error(""),s.display()}),console.error(f.gray("\nRun `tdk doctor` for a full environment check.")),process.exit(1)),ai(e,t)}function sl(e,t=1){console.error(f.red(`Error: ${e}`)),process.exit(t)}function ci(e,t,r){if(console.error(f.red(`\u274C ${e}`)),t&&console.error(f.gray(` ${t}`)),r&&r.length>0){console.error(f.yellow(`
16
+ \u{1F4A1} Suggestions:`));for(let n of r)console.error(f.cyan(` \u2192 ${n}`))}}function ol(e,t){console.error(f.red(`
17
+ tilt ${e} failed with exit code ${t}`)),process.exit(t)}import{existsSync as Tn,readFileSync as xn}from"node:fs";import{copyFileSync as an,mkdirSync as ui,rmSync as cn,writeFileSync as un}from"node:fs";import{join as Q}from"node:path";var hn=60,dn=1e3,ln=1e4,pn=200,fn=64*1024,mn=new Set([404,502,503,504]),di=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","EHOSTUNREACH","ENETUNREACH"]),li=new Set(["GET","HEAD","OPTIONS"]);function G(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function pi(e,t){if(li.has(t))return!0;if(!G(e))return!1;let r=G(e.cause)?e.cause:void 0,n=e.code??r?.code;return typeof n=="string"&&di.has(n)}function bt(e){if(!G(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((r,n)=>{let s=`smoke.steps[${n}]`;if(!G(r)){t.push(`${s}: must be an object`);return}let o=r.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`),r.expect!==void 0&&!(typeof r.expect=="number"&&Number.isInteger(r.expect)&&r.expect>=100&&r.expect<=599)&&t.push(`${s}.expect: must be an HTTP status between 100 and 599`),r.bodyContains!==void 0&&typeof r.bodyContains!="string"&&t.push(`${s}.bodyContains: must be a string`),r.save!==void 0&&(G(r.save)&&Object.values(r.save).every(a=>typeof a=="string"&&a.startsWith("$."))||t.push(`${s}.save: must map names to paths such as "$.id"`))}),t)}function gn(e,t){let{appBase:r,apiBase:n}=ht(t),s=[];for(let o of e){let i=o.config;if(!i?.smoke)continue;let a=i.appType,c=w(a)||a===B;if(!c&&a!=="frontend"||i.exposeViaProxy===!1)continue;let u=c?n:r,d=i.healthCheckPath||(c&&a!==B?"/health":void 0);s.push({name:o.name,baseUrl:`${u}${gt(o).replace(/\/+$/,"")}`,...d?.startsWith("/")?{readyPath:d}:{},smoke:i.smoke})}return s}var fi=10;function kn(e,t={}){let r=t.timeoutSeconds??fi;return e.flatMap(n=>{let s=n.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(n.smoke.timeoutSeconds??hn,r);return[{name:n.name,baseUrl:n.baseUrl,smoke:{via:n.smoke.via,timeoutSeconds:o,steps:s}}]})}function mi(e,t){let r=t.replace(/^\$\.?/,"").match(/[^.[\]]+/g)??[],n=e;for(let s of r){if(n==null||s==="__proto__"||s==="constructor"||s==="prototype"||!Object.hasOwn(n,s))return;let o=Object.getOwnPropertyDescriptor(n,s);if(!o||!("value"in o))return;n=o.value}return n}function yn(e,t){return e.replace(/\{\{(\w+)\}\}/g,(r,n)=>t[n]??r)}function St(e,t){return typeof e=="string"?yn(e,t):Array.isArray(e)?e.map(r=>St(r,t)):G(e)?Object.fromEntries(Object.entries(e).map(([r,n])=>[r,St(n,t)])):e}function Le(e){let t=e.replace(/\s+/g," ").trim();return t.length>pn?`${t.slice(0,pn)}...`:t}function Sn(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"step"}function hi(e,t){let r=Sn(t),n=(e.get(r)??0)+1;return e.set(r,n),n===1?r:`${r}-${n}`}function gi(e,t,r,n,s){try{let o=Q(e,Sn(r.service),t);ui(o,{recursive:!0});let i=Q(o,"latest.json"),a=Q(o,"body.txt");return n===void 0?cn(a,{force:!0}):un(a,n),un(i,`${JSON.stringify({...r,bodyPath:n===void 0?null:"body.txt"},null,2)}
18
+ `),s&&(an(i,Q(o,"last-success.json")),n===void 0?cn(Q(o,"last-success-body.txt"),{force:!0}):an(a,Q(o,"last-success-body.txt"))),i}catch{return}}function ki(e){let t=Buffer.from(e,"utf8");if(t.length<=fn)return{body:e,truncated:!1,bytes:t.length};let r=t.subarray(0,fn).toString("utf8").replace(/\uFFFD$/,"");return{body:r,truncated:!0,bytes:Buffer.byteLength(r,"utf8")}}async function yi(e,t={}){let r=t.fetch??((d,l)=>fetch(d,l)),n=t.now??Date.now,s=t.sleep??(d=>new Promise(l=>setTimeout(l,d))),o=(e.smoke.timeoutSeconds??hn)*1e3,i=n()+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 r(d,{method:"GET",signal:AbortSignal.timeout(ln)});if(await l.text(),!mn.has(l.status)&&l.status<500)break}catch{}if(n()>=i)break;await s(dn)}}i=n()+o;let u=new Map;for(let[d,l]of e.smoke.steps.entries()){let g=l.name??`step ${d+1}`,k=(l.method??"GET").toUpperCase(),h=`${e.baseUrl}${yn(l.path,a)}`,p=l.expect??200,y=l.body!==void 0,E,j="",K,et;for(;;){K=void 0,et=void 0,E=void 0;let I=!1;try{let _=await r(h,{method:k,headers:y?{"content-type":"application/json"}:void 0,body:y?JSON.stringify(St(l.body,a)):void 0,signal:AbortSignal.timeout(ln)});E=_.status,j=await _.text()}catch(_){I=pi(_,k),K=_ instanceof Error?_.message:String(_);let z=G(_)?_.code??(G(_.cause)?_.cause.code:void 0):void 0;et=typeof z=="string"?z:void 0}if(!(K!==void 0&&I||E!==void 0&&E!==p&&mn.has(E))||n()>=i)break;await s(dn)}let ce=`${e.name}: ${g}: ${k} ${h}`,gr;if(t.recordDir){let I=E===void 0?void 0:ki(j),de=K===void 0&&E===p&&(l.bodyContains===void 0||j.includes(l.bodyContains));gr=gi(t.recordDir,hi(u,g),{service:e.name,step:g,method:k,url:h,expectedStatus:p,status:E??null,...K===void 0?{}:{error:et??K},truncated:I?.truncated??!1,bodyBytes:I?.bytes??0},I?.body,de)}let ue=I=>({name:e.name,ok:!1,failure:I,recordPath:gr});if(K!==void 0)return ue(`${ce} never answered (${K})`);if(E!==p)return ue(`${ce} returned ${E}, expected ${p}${j?`: ${Le(j)}`:""}`);if(l.bodyContains!==void 0&&!j.includes(l.bodyContains))return ue(`${ce} returned ${E} but the body does not contain "${l.bodyContains}": ${Le(j)}`);if(l.save){let I;try{I=JSON.parse(j)}catch{return ue(`${ce} returned a body that is not JSON, cannot save: ${Le(j)}`)}for(let[de,_]of Object.entries(l.save)){let z=mi(I,_);if(z==null||typeof z=="object")return ue(`${ce} response has no ${_} to save as {{${de}}}: ${Le(j)}`);a[de]=String(z)}}}return{name:e.name,ok:!0}}function pl(e){return`Smoke check failed: ${e.failure}${e.recordPath?` (record: ${e.recordPath})`:""}`}async function bn(e,t={}){return Promise.all(e.map(r=>yi(r,t)))}var ke=1,gl="https://tdk-landscape.github.io/schema.service.json",Si={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"},bi=new Set(["$schema","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"]),Ti=[{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 Be(e,t){let r=[],n=new Set;for(let{path:s,pattern:o,expected:i}of Ti){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))&&n.add(c),typeof a!="string"?r.push(`${c}: expected a string`):o.test(a)||r.push(`${c}: must be ${i} (no spaces, line breaks or YAML syntax)`)}for(let[s,o]of xi(e,t))n.has(s)||r.push(`${s}: ${o}`);return r}function Tt(e){for(let t=0;t<e.length;t++){let r=e.charCodeAt(t);if(r<32||r===127||r===133||r===8232||r===8233)return!0}return!1}function xi(e,t){let r=[],n=Object.entries(e).filter(([s])=>s!=="smoke").map(([s,o])=>[o,`${t}.${s}`]);for(let s of Object.keys(e))Tt(s)&&r.push([t,"a key contains a line break"]);for(;n.length>0;){let[s,o]=n.pop();if(typeof s=="string")Tt(s)&&r.push([o,"must not contain line breaks or control characters"]);else if(Array.isArray(s))for(let[i,a]of s.entries())n.push([a,`${o}[${i}]`]);else if(s&&typeof s=="object")for(let[i,a]of Object.entries(s))Tt(i)?r.push([o,"a key contains a line break"]):n.push([a,`${o}.${i}`])}return r.sort(([s],[o])=>s.localeCompare(o))}var Pi=["apiPath","basePath"];function xt(e){if(!e||typeof e!="object"||Array.isArray(e))return[];let t=e;return Pi.filter(r=>r in t&&typeof t[r]!="string")}function Pt(e,t){if(!e||typeof e!="object"||Array.isArray(e))return{errors:[`${t}: expected a JSON object`],warnings:[]};let r=e,n=[];for(let a of["appName","appType","stack","schemaVersion"])a in r||n.push(`${t}.${a}: required field is missing`);for(let a of["appName","appType","stack"])a in r&&typeof r[a]!="string"&&n.push(`${t}.${a}: expected a string`);"schemaVersion"in r&&r.schemaVersion!==ke&&n.push(`${t}.schemaVersion: unsupported version ${String(r.schemaVersion)} (supported: ${ke})`);for(let a of xt(r))n.push(`${t}.${a}: expected a string`);let s=r.dev,o=s&&typeof s=="object"&&!Array.isArray(s)?s.liveReload:void 0;if(o!==void 0&&typeof o!="boolean"&&n.push(`${t}.dev.liveReload: expected true or false`),n.push(...Be(r,t)),"smoke"in r)for(let a of bt(r.smoke))n.push(`${t}.${a}`);let i=Object.keys(r).flatMap(a=>{let c=Si[a];return c?[`${t}.${a}: ${c}`]:bi.has(a)?[]:[`${t}.${a}: unknown field is preserved`]});return o===!0&&r.language!=="go"&&i.push(`${t}.dev.liveReload: only applies to Go services (language "go"); it is ignored here`),{errors:n,warnings:i,manifest:r}}function kl(e,t){if(!Tn(e))return[];try{let r=JSON.parse(xn(e,"utf-8"));return!r||typeof r!="object"||Array.isArray(r)?[]:Be(r,t)}catch{return[]}}function yl(e,t){if(!Tn(e))return{errors:[`${t}: file is missing`],warnings:[]};try{let r=JSON.parse(xn(e,"utf-8"));return Pt(r,t)}catch(r){let n=r instanceof Error?r.message:String(r);return{errors:[`${t}: invalid JSON (${n})`],warnings:[]}}}function Pn(e){if(e.length===0||e.every(r=>r==="unknown"))return"unknown";let t=e.filter(r=>r==="ready").length/e.length;return t>.9?"healthy":t>.5?"degraded":"error"}var vi=/^[a-z0-9-]+$/;function vn(e){return vi.test(e)}var Ei="Use lowercase letters, numbers, and hyphens only";function En(e,t){return`${e} "${t}" is not valid. ${Ei}, e.g. "${e==="Resource name"?"my-service":"my-stack"}".`}function wi(e){return e.trim()?vn(e)?{valid:!0}:{valid:!1,error:En("Resource name",e)}:{valid:!1,error:"Resource name is required"}}function $i(e){return e.trim()?vn(e)?{valid:!0}:{valid:!1,error:En("Stack name",e)}:{valid:!1,error:"Stack name is required"}}function xl(e){let t=e==="resource"?wi:$i;return r=>{let n=t(r);return n.valid?!0:n.error??"Invalid name"}}function Pl(e){return vt(ut,e)?{valid:!0}:{valid:!1,error:`Invalid service. Must be one of: ${ut.join(", ")}`}}function vl(e){return Number.isInteger(e)&&e>0&&e<=65535}function El(e){return!e.includes("\0")&&!/[<>:"|?*]/.test(e)}function wl(e,t="_"){return e.replace(/[^a-zA-Z0-9-]/g,t).substring(0,100)}function vt(e,t){return e.includes(t)}var _i=Dr;function _t(e,t=5,r=0){let n=[];if(r>t)return n;let s=wn(e,{withFileTypes:!0});for(let o of s){let i=J(e,o.name);if(o.isDirectory()){if(Oi(o.name))continue;n.push(..._t(i,t,r+1))}else o.isFile()&&o.name===_i&&n.push(i)}return n}function Ml(e){return _t(e)}function Oi(e){return vt(Nr,e)||e.startsWith(".")}function Ai(e){if(!e||typeof e!="object")return!1;let t=e,r=typeof t.runtime=="string"||typeof t.appType=="string"||typeof t.type=="string";return typeof t.appName=="string"&&r}var Ue=new Set;var W=class extends Error{reason;constructor(t){super(t),this.reason=t,this.name="InvalidServiceJsonError"}};function wt(e){return e instanceof Error?e.message:String(e)}function Di(e){let t;try{t=$n(e,"utf-8")}catch(c){throw new W(`could not read file: ${wt(c)}`)}let r;try{r=JSON.parse(t)}catch(c){throw new W(`invalid JSON: ${wt(c)}`)}if(!Ai(r))throw new W("missing required fields (appName, runtime or appType)");let n=xt(r);if(n.length>0)throw new W(n.map(c=>`${c}: expected a string`).join("; "));let s=Be(r,e);if(s.length>0)throw new W(s.join("; "));let o=r;for(let c of Pt(r,e).warnings)Ue.has(c)||(Ue.add(c),console.warn(`\u26A0\uFE0F ${c}`));let i={...o,appType:o.appType||o.type},a=Ri(e);return{name:i.appName,path:a,configPath:e,config:i,stack:i.stack,port:i.port,type:i.appType}}function Rn(e){let t=_t(e),r=[],n=[];for(let s of t)try{r.push(Di(s))}catch(o){n.push({path:s,reason:o instanceof W?o.reason:wt(o)})}return{resources:r,problems:n}}function Ci(e){for(let t of e){let r=`skipped ${t.path}: ${t.reason}`;Ue.has(r)||(Ue.add(r),console.warn(`\u26A0\uFE0F ${r}`))}}function b(e){let{resources:t,problems:r}=Rn(e);return Ci(r),t}function Se(){let e=m();if(!e)throw V.notInProject();return b(e)}function Ll(){let e=m();if(!e)throw V.notInProject();let{resources:t,problems:r}=Rn(e);if(r.length>0)throw new Error(r.map(n=>`Invalid service.json at ${n.path}: ${n.reason}`).join(`
19
+ `));return t}function Bl(e){let t=b(e),r=new Set;for(let n of t)n.stack&&r.add(n.stack);return Array.from(r).sort()}function Ul(e){let t=e||Se(),r=new Set;for(let n of t)n.stack&&r.add(n.stack);return Array.from(r).sort()}function Hl(e=Se()){let t=new Map;for(let n of e)if(n.stack){let s=t.get(n.stack);s?s.push(n):t.set(n.stack,[n])}let r=[];for(let[n,s]of t)r.push({name:n,description:S(s.length,"resource"),resources:s,resourceCount:s.length});return r.sort((n,s)=>n.name.localeCompare(s.name))}function Vl(e,t){return(t??Se()).some(n=>n.stack===e)}var Ot=5e3,$t=new ge({ttlMs:Ot}),Rt=new ge({ttlMs:Ot}),ye=Zr(Ot);function Kl(){$t.clear(),Rt.clear(),ye.reset()}function Ni(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===D)return"config";if(e==="schema.prisma"||e.includes("migration"))return"prisma";if(t){let r=t.split(`
20
20
  `).slice(0,10).join(`
21
- `);if(n.includes("GENERATED BY TDK")||n.includes("AUTOGENERATED"))return"generated"}return"unknown"}function ji(e){let t=e.configPath;if(ye.isValid()){let k=$t.get(t);if(k)return k}let n=e.path,r=Et(e.configPath),s=r.mtime.toISOString(),o=r.mtime.toISOString(),i=Ii(n),a=ee(J(n,"Dockerfile")),c=ee(J(n,"Tiltfile")),u=ee(J(n,he))||ee(J(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 g={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 $t.set(t,g),ye.markUpdated(),g}function Ii(e){let t=[];for(let r of jn){let s=J(e,r);if(ee(s)){let o=Et(s),i=wr(s,"utf-8");t.push({name:r,path:s,type:Ni(r,i),size:o.size,lastModified:o.mtime.toISOString()})}}let n=J(e,"prisma");if(ee(n)){let r=Er(n);for(let s of r)if(s==="schema.prisma"||s.includes("migration")){let o=J(n,s),i=Et(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 Gl(e){let t=e.name;if(ye.isValid()){let c=Rt.get(t);if(c)return c}let n=e.resources.map(c=>ji(c)),r=n.map(c=>new Date(c.createdAt).getTime()),s=Math.min(...r),o=Math.max(...r),i=xr(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 Rt.set(t,a),ye.markUpdated(),a}function Rr(e,t){return e==="pending"||e==="in_progress"||e==="none"||t==="pending"||t==="none"}var _r="container is running, but its health check is failing";function Or(e){let t=e?.runtimeStatus??"";if(t!=="ok")return t;let n=e?.composeResourceInfo?.healthStatus;return n==="unhealthy"?"error":n==="starting"?"pending":t}var be=1e4,Ar=3e3,Mi="http://localhost:4873";function jr(e){return`'${e.replace(/'/g,"'\\''")}'`}function Te(e,t,n,r,s){return process.platform==="win32"?Nr($(t)??t,n,{...s,windowsHide:!0}):e(r,s)}var Li=[80,443];function Bi(e){return e.replace(/-/g,"_")}function Ui(e,t){let n=new Set(t),r=[];for(let s of e.split(`
22
- `)){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(g=>g.startsWith(`${d}->`)||g.includes(`:${d}->`))&&u.push(d);u.length>0&&r.push({name:a,ports:c,publishedPorts:u})}return r}function Ir(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return n===`${r}_traefik`||n.startsWith(`${r}_traefik`)}function Hi(e,t){return e.filter(n=>!Ir(n.name,t))}function Vi(){try{return new Set(Se().filter(e=>e.config?.sablier?.enable&&e.config?.sablier?.deferStart).map(e=>e.name))}catch{return new Set}}function Ki(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=Or(c.status),g=l==="error"&&c.status?.runtimeStatus==="ok",h=(c.status?.buildHistory?.[0]?.error??"").trim()||(g?_r:"");if(d==="error"||l==="error"){s.push({name:u,updateStatus:d,runtimeStatus:l,error:h.replace(/\s+/g," ").slice(0,800)});continue}if(d==="ok"&&(l==="ok"||l==="not_applicable")){a+=1;continue}u!=="(Tiltfile)"&&Rr(d,l)&&(t.has(u)?i+=1:o+=1)}return{failures:s,pendingCount:o,deferredCount:i,okCount:a,total:r.length}}var Gi=/failed to resolve source metadata for docker\.io\/library\/([A-Za-z0-9._-]+-l[1-4](?:-[a-z]+)*)(?::[^\s:]+)?:/i;function Ct(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(Gi);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 Dr(e){return/ConnectionRefused downloading package manifest|Verdaccio|private registry|dependency install failed during ImageBuild|install-deps\.sh|bun install/i.test(e)}function Nt(e=m()??process.cwd()){let t=te(e,".tdk",P);if(!At(t))return!1;try{let n=JSON.parse(Dt(t,"utf-8"));return n.optional_infra?.verdaccio===!0||Object.values(n.phases??{}).some(r=>(r.enabledStacks??[]).includes("verdaccio"))}catch{return!1}}function Fr(e){for(let t of[te(e,".npmrc"),te(e,D)])if(At(t))try{let n=Dt(t,"utf-8");if(/:4873\b/.test(n)||/verdaccio/i.test(n))return!0}catch{}return!1}function Wi(e=m()??process.cwd()){return Nt(e)||Fr(e)}function jt(e=xe,t=m()??process.cwd(),n=process.env.VERDACCIO_URL??process.env.NPM_REGISTRY_URL??Mi,r=!0){if(!r&&!Fr(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(!Wi(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=Te(e,"docker",["ps","--format","{{.Names}}"],"docker ps --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:be});s=/verdaccio/i.test(a)}catch{}let o=!1,i="";try{let a=process.platform==="win32"?Nr("curl.exe",["-fsS","-o","NUL","-w","%{http_code}","--max-time","2",n],{stdio:"pipe",encoding:"utf-8",timeout:Ar+1e3,windowsHide:!0}).trim():e(`curl -fsS -o /dev/null -w '%{http_code}' --max-time 2 ${jr(n)}`,{stdio:"pipe",encoding:"utf-8",timeout:Ar+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 It(e=xe,t=je(),n=Li){let r=Bi(t),s="";try{s=Te(e,"docker",["ps","--format","{{.Names}}\\t{{.Ports}}"],"docker ps --format '{{.Names}}\\t{{.Ports}}'",{stdio:"pipe",encoding:"utf-8",timeout:be})}catch{return{name:"Ingress Ports",didPass:!0,isSkipped:!0,message:"Docker not available - skipped ingress port check"}}let o=Ui(s,n),i=Hi(o,r);if(i.length===0){let c=o.filter(u=>Ir(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:
21
+ `);if(r.includes("GENERATED BY TDK")||r.includes("AUTOGENERATED"))return"generated"}return"unknown"}function ji(e){let t=e.configPath;if(ye.isValid()){let k=$t.get(t);if(k)return k}let r=e.path,n=Et(e.configPath),s=n.mtime.toISOString(),o=n.mtime.toISOString(),i=Ii(r),a=ee(J(r,"Dockerfile")),c=ee(J(r,"Tiltfile")),u=ee(J(r,he))||ee(J(r,"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 g={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 $t.set(t,g),ye.markUpdated(),g}function Ii(e){let t=[];for(let n of jr){let s=J(e,n);if(ee(s)){let o=Et(s),i=$n(s,"utf-8");t.push({name:n,path:s,type:Ni(n,i),size:o.size,lastModified:o.mtime.toISOString()})}}let r=J(e,"prisma");if(ee(r)){let n=wn(r);for(let s of n)if(s==="schema.prisma"||s.includes("migration")){let o=J(r,s),i=Et(o);t.push({name:`prisma/${s}`,path:o,type:"prisma",size:i.size,lastModified:i.mtime.toISOString()})}}return t.sort((n,s)=>n.name.localeCompare(s.name))}function Gl(e){let t=e.name;if(ye.isValid()){let c=Rt.get(t);if(c)return c}let r=e.resources.map(c=>ji(c)),n=r.map(c=>new Date(c.createdAt).getTime()),s=Math.min(...n),o=Math.max(...n),i=Pn(r.map(c=>c.status)),a={name:e.name,resourceCount:r.length,createdAt:new Date(s).toISOString(),lastModified:new Date(o).toISOString(),resources:r,overallStatus:i};return Rt.set(t,a),ye.markUpdated(),a}function _n(e,t){return e==="pending"||e==="in_progress"||e==="none"||t==="pending"||t==="none"}var On="container is running, but its health check is failing";function An(e){let t=e?.runtimeStatus??"";if(t!=="ok")return t;let r=e?.composeResourceInfo?.healthStatus;return r==="unhealthy"?"error":r==="starting"?"pending":t}var be=1e4,Dn=3e3,Mi="http://localhost:4873";function In(e){return`'${e.replace(/'/g,"'\\''")}'`}function Te(e,t,r,n,s){return process.platform==="win32"?jn($(t)??t,r,{...s,windowsHide:!0}):e(n,s)}var Li=[80,443];function Bi(e){return e.replace(/-/g,"_")}function Ui(e,t){let r=new Set(t),n=[];for(let s of e.split(`
22
+ `)){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 r)c.split(/[\s,]+/).some(g=>g.startsWith(`${d}->`)||g.includes(`:${d}->`))&&u.push(d);u.length>0&&n.push({name:a,ports:c,publishedPorts:u})}return n}function Fn(e,t){let r=e.toLowerCase(),n=t.toLowerCase();return r===`${n}_traefik`||r.startsWith(`${n}_traefik`)}function Hi(e,t){return e.filter(r=>!Fn(r.name,t))}function Vi(){try{return new Set(Se().filter(e=>e.config?.sablier?.enable&&e.config?.sablier?.deferStart).map(e=>e.name))}catch{return new Set}}function Ki(e,t=new Set){let n=JSON.parse(e).items??[],s=[],o=0,i=0,a=0;for(let c of n){let u=c.metadata?.name??"unknown",d=c.status?.updateStatus??"",l=An(c.status),g=l==="error"&&c.status?.runtimeStatus==="ok",h=(c.status?.buildHistory?.[0]?.error??"").trim()||(g?On:"");if(d==="error"||l==="error"){s.push({name:u,updateStatus:d,runtimeStatus:l,error:h.replace(/\s+/g," ").slice(0,800)});continue}if(d==="ok"&&(l==="ok"||l==="not_applicable")){a+=1;continue}u!=="(Tiltfile)"&&_n(d,l)&&(t.has(u)?i+=1:o+=1)}return{failures:s,pendingCount:o,deferredCount:i,okCount:a,total:n.length}}var Gi=/failed to resolve source metadata for docker\.io\/library\/([A-Za-z0-9._-]+-l[1-4](?:-[a-z]+)*)(?::[^\s:]+)?:/i;function Ct(e){let t=e.replace(/\s+/g," ").trim(),r=t.match(/Bind for [^ ]+:(\d+) failed: port is already allocated/i);if(r)return`host port ${r[1]} is already allocated`;if(/port is already allocated/i.test(t))return"a required host port is already allocated";let n=[...t.matchAll(/ConnectionRefused downloading package manifest (@[A-Za-z0-9._/-]+)/gi)].map(a=>a[1]);if(n.length>0){let a=[...new Set(n)],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(Gi);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 Cn(e){return/ConnectionRefused downloading package manifest|Verdaccio|private registry|dependency install failed during ImageBuild|install-deps\.sh|bun install/i.test(e)}function Nt(e=m()??process.cwd()){let t=te(e,".tdk",P);if(!At(t))return!1;try{let r=JSON.parse(Dt(t,"utf-8"));return r.optional_infra?.verdaccio===!0||Object.values(r.phases??{}).some(n=>(n.enabledStacks??[]).includes("verdaccio"))}catch{return!1}}function Mn(e){for(let t of[te(e,".npmrc"),te(e,D)])if(At(t))try{let r=Dt(t,"utf-8");if(/:4873\b/.test(r)||/verdaccio/i.test(r))return!0}catch{}return!1}function Wi(e=m()??process.cwd()){return Nt(e)||Mn(e)}function jt(e=xe,t=m()??process.cwd(),r=process.env.VERDACCIO_URL??process.env.NPM_REGISTRY_URL??Mi,n=!0){if(!n&&!Mn(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(!Wi(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=Te(e,"docker",["ps","--format","{{.Names}}"],"docker ps --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:be});s=/verdaccio/i.test(a)}catch{}let o=!1,i="";try{let a=process.platform==="win32"?jn("curl.exe",["-fsS","-o","NUL","-w","%{http_code}","--max-time","2",r],{stdio:"pipe",encoding:"utf-8",timeout:Dn+1e3,windowsHide:!0}).trim():e(`curl -fsS -o /dev/null -w '%{http_code}' --max-time 2 ${In(r)}`,{stdio:"pipe",encoding:"utf-8",timeout:Dn+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 ${r}${s?" (verdaccio container running)":""}`}:s?{name:"Private npm registry",didPass:!1,message:`Verdaccio container is running but ${r} 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 ${r}. 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 It(e=xe,t=je(),r=Li){let n=Bi(t),s="";try{s=Te(e,"docker",["ps","--format","{{.Names}}\\t{{.Ports}}"],"docker ps --format '{{.Names}}\\t{{.Ports}}'",{stdio:"pipe",encoding:"utf-8",timeout:be})}catch{return{name:"Ingress Ports",didPass:!0,isSkipped:!0,message:"Docker not available - skipped ingress port check"}}let o=Ui(s,r),i=Hi(o,n);if(i.length===0){let c=o.filter(u=>Fn(u.name,n));return c.length>0?{name:"Ingress Ports",didPass:!0,message:`Ingress ports ${r.join("/")} held by this project's Traefik (${c.map(u=>u.name).join(", ")})`}:{name:"Ingress Ports",didPass:!0,message:`Ingress ports ${r.join("/")} are free for Traefik`}}return{name:"Ingress Ports",didPass:!1,message:`Traefik cannot bind ingress ports because another container already owns them:
23
23
  ${i.map(c=>{let u=c.publishedPorts.join(", ");return`${c.name} (host ports ${u})`}).join(`
24
- `)}`,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 Ji(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 Ft(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 ${S(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 ${S(e.length,"service")} responding on /health`};let r=n.map(o=>`${o.name} (${Ji(o)})
24
+ `)}`,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 Ji(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 Ft(e){let t=e.filter(o=>o.status!==void 0),r=e.filter(o=>!o.ok);if(t.length===0)return{name:"Service Health",didPass:!0,isSkipped:!0,message:`No services responded - skipped ping of ${S(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(r.length===0)return{name:"Service Health",didPass:!0,message:`All ${S(e.length,"service")} responding on /health`};let n=r.map(o=>`${o.name} (${Ji(o)})
25
25
  ${o.url}`).join(`
26
- `),s=n.some(o=>o.status===404);return{name:"Service Health",didPass:!1,message:`${S(n.length,"service")} not healthy (${e.length-n.length}/${e.length} healthy):
27
- ${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 Mt(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 ${S(e.length,"service")} pass their smoke checks`};let n=t.map(r=>r.failure??`${r.name}: failed`).join(`
26
+ `),s=r.some(o=>o.status===404);return{name:"Service Health",didPass:!1,message:`${S(r.length,"service")} not healthy (${e.length-r.length}/${e.length} healthy):
27
+ ${n}`,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 Mt(e){if(e.length===0)return{name:"Service Smoke",didPass:!0,isSkipped:!0,message:"No read-only smoke checks declared"};let t=e.filter(n=>!n.ok);if(t.length===0)return{name:"Service Smoke",didPass:!0,message:`All ${S(e.length,"service")} pass their smoke checks`};let r=t.map(n=>n.failure??`${n.name}: failed`).join(`
28
28
  `);return{name:"Service Smoke",didPass:!1,message:`${S(t.length,"service")} failing a smoke check (${e.length-t.length}/${e.length} passing):
29
- ${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 Mr(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:`${S(t.length,"advertised endpoint")} reachable`};let r=n.map(s=>`${s.name} (404)
29
+ ${r}`,fix:'Add the route the smoke step expects, or correct its "path" in the service.json "smoke" block. Then re-run tdk doctor.'}}function Ln(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 r=t.filter(s=>s.status===404);if(r.length===0)return{name:"Advertised Endpoints",didPass:!0,message:`${S(t.length,"advertised endpoint")} reachable`};let n=r.map(s=>`${s.name} (404)
30
30
  ${s.url}`).join(`
31
- `);return{name:"Advertised Endpoints",didPass:!0,isWarning:!0,message:`${S(n.length,"advertised link")} ${n.length===1?"returns":"return"} 404 (the service may be healthy, but nothing answers at this exact path):
32
- ${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 Lt(e=xe){let t="";try{t=Te(e,"tilt",["get","uiresources","-o","json"],"tilt get uiresources -o json",{stdio:"pipe",encoding:"utf-8",timeout:be})}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=Ki(t,Vi())}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 y=n.deferredCount>0?`, ${n.deferredCount} deferred`:"";return{name:"Tilt Resources",didPass:!0,message:`Tilt resources healthy (${n.okCount} ok, ${n.pendingCount} pending${y})`}}let r=zi(n.failures),o=r.slice(0,20),i=r.length-o.length,a=o.map(y=>({failure:y,why:Xi(y,e)})),c=a.map(({failure:y,why:E})=>`${y.name}: ${E}`).join(`
31
+ `);return{name:"Advertised Endpoints",didPass:!0,isWarning:!0,message:`${S(r.length,"advertised link")} ${r.length===1?"returns":"return"} 404 (the service may be healthy, but nothing answers at this exact path):
32
+ ${n}`,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 Lt(e=xe){let t="";try{t=Te(e,"tilt",["get","uiresources","-o","json"],"tilt get uiresources -o json",{stdio:"pipe",encoding:"utf-8",timeout:be})}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 r;try{r=Ki(t,Vi())}catch{return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"Could not parse Tilt resource status - skipped"}}if(r.total===0)return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"No Tilt UIResources found"};if(r.failures.length===0){let y=r.deferredCount>0?`, ${r.deferredCount} deferred`:"";return{name:"Tilt Resources",didPass:!0,message:`Tilt resources healthy (${r.okCount} ok, ${r.pendingCount} pending${y})`}}let n=zi(r.failures),o=n.slice(0,20),i=n.length-o.length,a=o.map(y=>({failure:y,why:Xi(y,e)})),c=a.map(({failure:y,why:E})=>`${y.name}: ${E}`).join(`
33
33
  `),u=i>0?`
34
- \u2026and ${S(i,"more failed resource")}`:"",d=n.pendingCount>0?`
35
- ${S(n.pendingCount,"resource")} still pending/not started \u2014 often blocked by the failures above.`:"",l=n.deferredCount>0?`
36
- ${S(n.deferredCount,"resource")} intentionally deferred (sablier.deferStart) \u2014 not started until first request, unrelated to the failures above.`:"",g=r.some(y=>/port is already allocated/i.test(y.error)),k=r.some(y=>Dr(y.error)||Dr(Ct(y.error))),h=a.some(({why:y})=>/Kafka broker unreachable|kafka:9092/i.test(y)),p="Open the Tilt UI URL printed by tdk up (default port "+Cn.tiltUi+" when TILT_PORT is unset), inspect the red resources, fix the listed errors, then `tilt trigger <resource>` or re-run `tdk up`.";return g?p="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.":k?p="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.":h&&(p="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 ${S(n.failures.length,"failed resource")}:
37
- ${c}${u}${d}${l}`,fix:p}}var qi=/^(traefik|postgres|nats|infisical|verdaccio|proxy)([.-]|$)/i;function Cr(e){return qi.test(e)}function zi(e){return[...e].sort((t,n)=>{let r=Cr(t.name)?0:1,s=Cr(n.name)?0:1;return r!==s?r-s:t.name.localeCompare(n.name)})}function Yi(e,t=xe,n=je()){try{let r=Te(t,"docker",["ps","-a","--format","{{.Names}}"],"docker ps -a --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:be}).split(`
38
- `).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=Te(t,"docker",["logs","--tail","120",o],`docker logs --tail 120 ${jr(o)} 2>&1`,{stdio:"pipe",encoding:"utf-8",timeout:be});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 Xi(e,t=xe){return e.error?Ct(e.error):e.runtimeStatus==="error"?Yi(e.name,t)??"runtime error (container crashed or unhealthy \u2014 check Tilt/docker logs)":e.updateStatus||e.runtimeStatus||"unknown error"}var Zi=/\.(ts|tsx|mts|js|mjs|cjs)$/,Qi=new Set(["node_modules","dist",F,"tests","__tests__"]);function Lr(e){let t=[];for(let n of Fi(e,{withFileTypes:!0}))n.isDirectory()?Qi.has(n.name)||t.push(...Lr(te(e,n.name))):Zi.test(n.name)&&!/\.(test|spec)\./.test(n.name)&&t.push(te(e,n.name));return t}function ea(e){let t=e?.healthCheckPath||"/health";return{container:t,traefik:e?.traefik?.healthCheck||t}}function ta(e){let t=[];for(let n of e){if(!w(n.config?.appType))continue;let r=te(n.path,"src");if(!At(r))continue;let s=Lr(r);if(s.length===0)continue;let o=s.map(u=>Dt(u,"utf-8")),{container:i,traefik:a}=ea(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(g=>`${g}${u}${g}`);o.some(g=>l.some(k=>g.includes(k)))||t.push({name:n.name,healthPath:u,usedBy:d})}}return t}function Br(e=m()??process.cwd()){let t=[];try{t=b(e)}catch{return{name:"Health Routes",didPass:!0,isSkipped:!0,message:"Could not read services - skipped health route check"}}let n=t.filter(o=>w(o.config?.appType));if(n.length===0)return{name:"Health Routes",didPass:!0,isSkipped:!0,message:"No backend services to check"};let r=ta(n);return r.length===0?{name:"Health Routes",didPass:!0,message:`All ${S(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):
39
- ${r.map(o=>`${o.name}: no "${o.healthPath}" route in src/ (probed by the ${o.usedBy})`).join(`
40
- `)}`,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 Ut,readFileSync as Ur}from"node:fs";import{dirname as na,join as Bt,normalize as ra}from"node:path";function sa(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 Hr(e,t,n){return t==="ext://tdk-cli"?Bt(n,".tdk",".tdk-out","tdk-cli-ext","Tiltfile"):t.startsWith(".")||!t.includes("://")&&!t.startsWith("@")?ra(Bt(na(e),t)):null}function oa(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=Hr(e,c,n);u&&(Ut(u)||r.push(`${e}: ${c} -> ${u}`))}return r}function ia(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=Hr(e,c,n);u&&r.push(u)}}return r}function aa(e,t){let n=new Set,r=[e];for(;r.length>0;){let s=r.pop();if(!s||n.has(s)||!Ut(s))continue;n.add(s);let o=Ur(s,"utf-8");for(let i of ia(s,o,t))n.has(i)||r.push(i)}return Array.from(n).sort()}function Vr(){let e=m()??process.cwd(),t=Bt(e,".tdk",".tdk-out","Tiltfile");if(!Ut(t))return{name:"Starlark Load Exports",didPass:!0,isSkipped:!0,message:"No generated Tiltfile to check"};let n=[],r=[],s=aa(t,e);for(let i of s){let a=Ur(i,"utf-8"),c=sa(a);c.length>0&&n.push(`${i}: ${c.join(", ")}`);for(let u of oa(i,a,e))r.push(u)}if(n.length===0&&r.length===0)return{name:"Starlark Load Exports",didPass:!0,message:`${S(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:
41
- ${n.join(`
42
- `)}`),r.length>0&&o.push(`Missing relative load targets:
34
+ \u2026and ${S(i,"more failed resource")}`:"",d=r.pendingCount>0?`
35
+ ${S(r.pendingCount,"resource")} still pending/not started \u2014 often blocked by the failures above.`:"",l=r.deferredCount>0?`
36
+ ${S(r.deferredCount,"resource")} intentionally deferred (sablier.deferStart) \u2014 not started until first request, unrelated to the failures above.`:"",g=n.some(y=>/port is already allocated/i.test(y.error)),k=n.some(y=>Cn(y.error)||Cn(Ct(y.error))),h=a.some(({why:y})=>/Kafka broker unreachable|kafka:9092/i.test(y)),p="Open the Tilt UI URL printed by tdk up (default port "+Cr.tiltUi+" when TILT_PORT is unset), inspect the red resources, fix the listed errors, then `tilt trigger <resource>` or re-run `tdk up`.";return g?p="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.":k?p="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.":h&&(p="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 ${S(r.failures.length,"failed resource")}:
37
+ ${c}${u}${d}${l}`,fix:p}}var qi=/^(traefik|postgres|nats|infisical|verdaccio|proxy)([.-]|$)/i;function Nn(e){return qi.test(e)}function zi(e){return[...e].sort((t,r)=>{let n=Nn(t.name)?0:1,s=Nn(r.name)?0:1;return n!==s?n-s:t.name.localeCompare(r.name)})}function Yi(e,t=xe,r=je()){try{let n=Te(t,"docker",["ps","-a","--format","{{.Names}}"],"docker ps -a --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:be}).split(`
38
+ `).map(u=>u.trim()).filter(Boolean),s=`-autogenerated-${e}-1`,o=n.find(u=>u===e)??n.find(u=>u.startsWith(`${r}-`)&&u.endsWith(s))??n.find(u=>u.endsWith(s))??n.find(u=>u.includes(e));if(!o)return null;let i=Te(t,"docker",["logs","--tail","120",o],`docker logs --tail 120 ${In(o)} 2>&1`,{stdio:"pipe",encoding:"utf-8",timeout:be});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 Xi(e,t=xe){return e.error?Ct(e.error):e.runtimeStatus==="error"?Yi(e.name,t)??"runtime error (container crashed or unhealthy \u2014 check Tilt/docker logs)":e.updateStatus||e.runtimeStatus||"unknown error"}var Zi=/\.(ts|tsx|mts|js|mjs|cjs)$/,Qi=new Set(["node_modules","dist",F,"tests","__tests__"]);function Bn(e){let t=[];for(let r of Fi(e,{withFileTypes:!0}))r.isDirectory()?Qi.has(r.name)||t.push(...Bn(te(e,r.name))):Zi.test(r.name)&&!/\.(test|spec)\./.test(r.name)&&t.push(te(e,r.name));return t}function ea(e){let t=e?.healthCheckPath||"/health";return{container:t,traefik:e?.traefik?.healthCheck||t}}function ta(e){let t=[];for(let r of e){if(!w(r.config?.appType))continue;let n=te(r.path,"src");if(!At(n))continue;let s=Bn(n);if(s.length===0)continue;let o=s.map(u=>Dt(u,"utf-8")),{container:i,traefik:a}=ea(r.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(g=>`${g}${u}${g}`);o.some(g=>l.some(k=>g.includes(k)))||t.push({name:r.name,healthPath:u,usedBy:d})}}return t}function Un(e=m()??process.cwd()){let t=[];try{t=b(e)}catch{return{name:"Health Routes",didPass:!0,isSkipped:!0,message:"Could not read services - skipped health route check"}}let r=t.filter(o=>w(o.config?.appType));if(r.length===0)return{name:"Health Routes",didPass:!0,isSkipped:!0,message:"No backend services to check"};let n=ta(r);return n.length===0?{name:"Health Routes",didPass:!0,message:`All ${S(r.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):
39
+ ${n.map(o=>`${o.name}: no "${o.healthPath}" route in src/ (probed by the ${o.usedBy})`).join(`
40
+ `)}`,fix:`Add the route, e.g. for Hono: app.get("${n[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 Ut,readFileSync as Hn}from"node:fs";import{dirname as ra,join as Bt,normalize as na}from"node:path";function sa(e){let t=new Set,r=/^load\s*\(([\s\S]*?)\)/gm;for(let n of e.matchAll(r)){let s=n[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 Vn(e,t,r){return t==="ext://tdk-cli"?Bt(r,".tdk",".tdk-out","tdk-cli-ext","Tiltfile"):t.startsWith(".")||!t.includes("://")&&!t.startsWith("@")?na(Bt(ra(e),t)):null}function oa(e,t,r){let n=[],s=/^load\s*\(([\s\S]*?)\)/gm;for(let o of t.matchAll(s)){let c=(o[1]??"").match(/["']([^"']+)["']/)?.[1];if(!c)continue;let u=Vn(e,c,r);u&&(Ut(u)||n.push(`${e}: ${c} -> ${u}`))}return n}function ia(e,t,r){let n=[],s=/^load\s*\(([\s\S]*?)\)/gm;for(let o of t.matchAll(s)){let c=(o[1]??"").match(/["']([^"']+)["']/)?.[1];if(c){let u=Vn(e,c,r);u&&n.push(u)}}return n}function aa(e,t){let r=new Set,n=[e];for(;n.length>0;){let s=n.pop();if(!s||r.has(s)||!Ut(s))continue;r.add(s);let o=Hn(s,"utf-8");for(let i of ia(s,o,t))r.has(i)||n.push(i)}return Array.from(r).sort()}function Kn(){let e=m()??process.cwd(),t=Bt(e,".tdk",".tdk-out","Tiltfile");if(!Ut(t))return{name:"Starlark Load Exports",didPass:!0,isSkipped:!0,message:"No generated Tiltfile to check"};let r=[],n=[],s=aa(t,e);for(let i of s){let a=Hn(i,"utf-8"),c=sa(a);c.length>0&&r.push(`${i}: ${c.join(", ")}`);for(let u of oa(i,a,e))n.push(u)}if(r.length===0&&n.length===0)return{name:"Starlark Load Exports",didPass:!0,message:`${S(s.length,"reachable Starlark file")} ${s.length===1?"has":"have"} valid load exports and paths`};let o=[];return r.length>0&&o.push(`Private exported symbols:
43
41
  ${r.join(`
42
+ `)}`),n.length>0&&o.push(`Missing relative load targets:
43
+ ${n.join(`
44
44
  `)}`),{name:"Starlark Load Exports",didPass:!1,message:`Starlark load() issues will stop Tilt before services start:
45
45
  ${o.join(`
46
46
 
47
- `)}`,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 Ta,execSync as xa}from"node:child_process";import{existsSync as Gt,readdirSync as ss,readFileSync as ve}from"node:fs";import{basename as Pa,dirname as va,join as O,relative as Pe}from"node:path";function lp(e){return`import { Hono } from 'hono';
47
+ `)}`,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 Ta,execSync as xa}from"node:child_process";import{existsSync as Gt,readdirSync as os,readFileSync as ve}from"node:fs";import{basename as Pa,dirname as va,join as O,relative as Pe}from"node:path";function lp(e){return`import { Hono } from 'hono';
48
48
 
49
49
  const app = new Hono();
50
50
 
@@ -84,7 +84,7 @@ export default {
84
84
  port,
85
85
  fetch: app.fetch,
86
86
  };
87
- `}var Kr={id:"bun",label:"Bun + Hono",installHint:"bun install"};var ca="go run .",Gr={id:"go",label:"Go 1.23 (net/http)",devCommand:ca,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}
87
+ `}var Gn={id:"bun",label:"Bun + Hono",installHint:"bun install"};var ca="go run .",Wn={id:"go",label:"Go 1.23 (net/http)",devCommand:ca,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}
88
88
 
89
89
  go 1.23
90
90
  `,description:"Generating go.mod",emoji:"\u{1F4E6}"},{filename:"main.go",content:`package main
@@ -147,7 +147,7 @@ func TestHealth(t *testing.T) {
147
147
  t.Fatalf("GET /health = %d, want %d", rec.Code, http.StatusOK)
148
148
  }
149
149
  }
150
- `,description:"Generating smoke test",emoji:"\u{1F9EA}"}]}};var ua="uvicorn main:app --app-dir src --host 0.0.0.0 --port ${PORT:-4000} --reload --reload-dir src",Wr={id:"python",label:"Python 3.12 + FastAPI",devCommand:ua,watch:["src/**/*"],installHint:'pip install -e ".[dev]" # optional: Docker builds the image for you',createFiles(e){return[{filename:"pyproject.toml",content:`[project]
150
+ `,description:"Generating smoke test",emoji:"\u{1F9EA}"}]}};var ua="uvicorn main:app --app-dir src --host 0.0.0.0 --port ${PORT:-4000} --reload --reload-dir src",Jn={id:"python",label:"Python 3.12 + FastAPI",devCommand:ua,watch:["src/**/*"],installHint:'pip install -e ".[dev]" # optional: Docker builds the image for you',createFiles(e){return[{filename:"pyproject.toml",content:`[project]
151
151
  name = "${e}"
152
152
  version = "0.0.1"
153
153
  requires-python = ">=3.12"
@@ -205,7 +205,7 @@ def test_health() -> None:
205
205
  response = client.get("/health")
206
206
  assert response.status_code == 200
207
207
  assert response.json() == {"status": "ok", "service": "${e}"}
208
- `,description:"Generating test file",emoji:"\u{1F9EA}"}]}};var da="cargo run",Jr={id:"rust",label:"Rust (axum)",devCommand:da,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]
208
+ `,description:"Generating test file",emoji:"\u{1F9EA}"}]}};var da="cargo run",qn={id:"rust",label:"Rust (axum)",devCommand:da,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]
209
209
  name = "${e}"
210
210
  version = "0.1.0"
211
211
  edition = "2021"
@@ -259,64 +259,64 @@ mod tests {
259
259
  assert_eq!(body["status"], "ok");
260
260
  }
261
261
  }
262
- `,description:"Generating backend source and smoke test",emoji:"\u{1F4BB}"}]}};var qr="bun",ne={bun:Kr,python:Wr,go:Gr,rust:Jr};function la(e){let t=(e??qr).trim().toLowerCase(),n=Object.hasOwn(ne,t)?ne[t]:void 0;if(!n){let r=Object.keys(ne).join(", ");throw new R(`Unknown backend language "${e}". Supported languages: ${r}.`,[`Use one of: ${r}`,`Omit --language to use ${qr}`])}return n}function Tp(e,t){if(e!=="backend"){if(t!==void 0)throw new R("--language can only be used with --type backend.",["Add --type backend, or drop --language for this resource type"]);return}return la(t)}import{exec as pa,execFile as fa}from"node:child_process";import{promisify as zr}from"node:util";var ma=zr(pa),M=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=$(s)??s,{stdout:a}=await zr(fa)(i,o,{encoding:"utf-8",timeout:t,windowsHide:!0,shell:!1});return a}let{stdout:n}=await ma(e,{encoding:"utf-8",timeout:t});return n};function Yr(e){let t=e;return t?.code==="ETIMEDOUT"||t?.killed===!0}import{existsSync as ha,readFileSync as Xr}from"node:fs";import{join as q}from"node:path";var Ht=[U,"proxy"];var Zr=["postgres",U],Qr=["pre_alpha","alpha","beta","out_of_scope"];function ga(e){return Zr.includes(e)}function es(e){try{return JSON.parse(Xr(q(e,".tdk",P),"utf-8"))}catch{return}}function re(e){try{return ha(e)?Xr(e,"utf-8"):void 0}catch{return}}function ts(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 ns(e){let t=q(e,".tdk",".tdk-out","Tiltfile"),n=re(t);if(n)return ts(n,"ALWAYS_ENABLED_INFRA")}function ka(e){let t=q(e,".tdk",".tdk-out","spec.master"),n=re(t);if(n!==void 0)return/"database-management"\s*:\s*True/.test(n)}function ya(e){let t=q(e,".tdk",".tdk-out"),n=re(q(t,"Tiltfile")),r=re(q(t,"spec.master")),s=re(q(t,"tdk-cli-ext","discovery","config.star")),o=re(q(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=ts(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 Sa(e){let t=es(e);if(!t)return!1;let n=t.phases??{};for(let s of Qr){let o=n[s]?.enabledStacks;if(Array.isArray(o)&&o.includes(U))return!0}let r=t.always_enabled_infra??Ht;return Array.isArray(r)&&r.includes(U)}function ba(e){let t=new Set;for(let s of Zr)t.add(s);for(let s of b(e))t.add(s.name),s.stack&&t.add(s.stack);let n=es(e);if(n){let s=n.phases??{};for(let i of Qr){let a=s[i]?.enabledStacks;if(Array.isArray(a))for(let c of a)t.add(c)}let o=n.always_enabled_infra??Ht;if(Array.isArray(o))for(let i of o)t.add(i)}let r=ns(e);if(Array.isArray(r))for(let s of r)t.add(s);return t}function Vt(e){let t=Sa(e),n=ns(e),r=Array.isArray(n)&&n.includes(U),s=ka(e)===!0,o=t||r||s,i=!t&&ya(e),a=ba(e),c=[],u=[];for(let g of b(e)){let k=g.config?.dependsOn??[],h=!1;for(let p of k){if(ga(p)){h=!0;continue}a.has(p)||u.push({resource:g.name,name:p})}h&&c.push(g.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 Ve=1e4,Ea=/\.(?:[cm]?[jt]sx?|vue)$/,wa=/(?:\.test\.|\.spec\.|\/tests?\/|\/__tests__\/)/,$a=7,Ra=new Set(["node_modules",F,"dist","tests","__tests__"]);function os(e){try{let t=JSON.parse(ve(O(e,".tdk",P),"utf-8"));return typeof t?.project?.name=="string"?t.project.name:void 0}catch{return}}function _a(e){try{let t=JSON.parse(ve(e,"utf-8")).params;return t&&typeof t=="object"?t:{}}catch{return{}}}function Kt(e){try{let t=JSON.parse(ve(O(e,D),"utf-8"));return t&&typeof t=="object"?t:{}}catch{return{}}}function rs(e){if(typeof e!="string")return;let t=e.match(/(?:^|[^0-9])(\d+)(?:\.|$)/);return t?Number(t[1]):void 0}function Oa(e){let t=Ge(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 Aa(e){let t=O(e,F,"prisma.config.autogenerated.ts"),r=[O(e,"prisma.config.ts"),t].find(i=>Gt(i));if(!r)return["missing prisma.config.ts or generated Prisma config"];let o=(Ge(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 is(e=m()??process.cwd()){let t=b(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:`${S(r.length,"Prisma consistency error")}:
263
- ${r.join(`
264
- `)}`,fix:"Use featuresEnabled to opt into the validated Prisma 7 shape"};for(let o of n){let i=Kt(o.path).dependencies,c={...Kt(o.path).devDependencies??{},...i??{}},u=rs(c.prisma),d=rs(c["@prisma/client"]);if(u===void 0||d===void 0?r.push(`${o.name}: prisma and @prisma/client are required`):(u!==d||u!==$a)&&r.push(`${o.name}: prisma packages must both be major 7`),r.push(...Oa(O(o.path,"prisma","schema.prisma")).map(g=>`${o.name}: ${g}`)),r.push(...Aa(o.path).map(g=>`${o.name}: ${g}`)),(o.config?.appType??o.type)==="migrator")o.config?.dependsOn?.some(k=>k==="postgres"||k===U)||r.push(`${o.name}: migrator must depend on postgres or database-management`);else{o.config?.dependsOn?.some(p=>s.some(y=>y.name===p))||r.push(`${o.name}: API must depend on its Prisma migrator`);let k=Kt(o.path).scripts;Object.entries(k??{}).some(([p,y])=>hs.has(p)&&typeof y=="string"&&/prisma\s+migrate/.test(y))&&r.push(`${o.name}: API start script must not run prisma migrate`);let h=O(o.path,o.config?.dockerfile??"Dockerfile");He(h,!0)&&r.push(`${o.name}: API image/startup must not run Prisma migrations`)}}return n.length>0&&!Vt(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:`${S(r.length,"Prisma consistency error")}:
265
- ${r.join(`
266
- `)}`,fix:"Use Prisma 7 packages and config, put migrations in a migrator, and make the API depend on that migrator"}}function as(e){let t=new Map;for(let n of e){let r=n.config?.port;w(n.config?.appType)&&typeof r=="number"&&t.set(n.name,r)}return t}function Da(e){let t=e.config?.language;return typeof t=="string"&&Object.hasOwn(ne,t)&&ne[t].createFiles!==void 0}function Ca(e){return(e.config?.appType??e.type)===B}function cs(e=m()??process.cwd()){let t=b(e).filter(n=>!Ca(n)&&!Da(n)&&!Gt(O(n.path,D))).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:`${S(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 Ke(e=m()??process.cwd()){let t=new Map;for(let s of b(e)){let o=t.get(s.name)??[];o.push(Pe(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:`${S(n.length,"appName")} used by more than one resource:
267
- ${r.join(`
268
- `)}`,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 Na(e){let t=e.config?.appType;return w(t)?!0:t===B&&e.config?.exposeViaProxy!==!1}function us(e=m()??process.cwd()){let t=new Map;for(let s of b(e)){let o=s.config?.port;if(typeof o!="number"||!Na(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:`${S(n.length,"port")} used by more than one routed resource:
269
- ${r.join(`
270
- `)}`,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 ja=/https?:\/\/([a-z][a-z0-9-]*):(\d+)/g;function ds(e=m()??process.cwd()){let t=b(e),n=as(t),r=new Map([...n].map(([o,i])=>[i,o])),s=[];for(let o of t)for(let[i,a]of Object.entries(_a(o.configPath)))for(let[,c,u]of String(a).matchAll(ja)){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:`${S(s.length,"service URL")} in params that cannot connect:
262
+ `,description:"Generating backend source and smoke test",emoji:"\u{1F4BB}"}]}};var zn="bun",re={bun:Gn,python:Jn,go:Wn,rust:qn};function la(e){let t=(e??zn).trim().toLowerCase(),r=Object.hasOwn(re,t)?re[t]:void 0;if(!r){let n=Object.keys(re).join(", ");throw new R(`Unknown backend language "${e}". Supported languages: ${n}.`,[`Use one of: ${n}`,`Omit --language to use ${zn}`])}return r}function Tp(e,t){if(e!=="backend"){if(t!==void 0)throw new R("--language can only be used with --type backend.",["Add --type backend, or drop --language for this resource type"]);return}return la(t)}import{exec as pa,execFile as fa}from"node:child_process";import{promisify as Yn}from"node:util";var ma=Yn(pa),M=async(e,t)=>{if(process.platform==="win32"){let n=e.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g)??[],[s,...o]=n.map(c=>c.startsWith('"')||c.startsWith("'")?c.slice(1,-1):c);if(!s)throw new Error("Command is empty");let i=$(s)??s,{stdout:a}=await Yn(fa)(i,o,{encoding:"utf-8",timeout:t,windowsHide:!0,shell:!1});return a}let{stdout:r}=await ma(e,{encoding:"utf-8",timeout:t});return r};function Xn(e){let t=e;return t?.code==="ETIMEDOUT"||t?.killed===!0}import{existsSync as ha,readFileSync as Zn}from"node:fs";import{join as q}from"node:path";var Ht=[H,"proxy"];var Qn=["postgres",H],es=["pre_alpha","alpha","beta","out_of_scope"];function ga(e){return Qn.includes(e)}function ts(e){try{return JSON.parse(Zn(q(e,".tdk",P),"utf-8"))}catch{return}}function ne(e){try{return ha(e)?Zn(e,"utf-8"):void 0}catch{return}}function rs(e,t){let r=s=>{let o=s;for(;o<e.length&&/\s/.test(e[o]);)o+=1;return o},n=0;for(;;){let s=e.indexOf(t,n);if(s===-1)return;let o=r(s+t.length);if(e[o]==="="&&(o=r(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]??"")}n=s+t.length}}function ns(e){let t=q(e,".tdk",".tdk-out","Tiltfile"),r=ne(t);if(r)return rs(r,"ALWAYS_ENABLED_INFRA")}function ka(e){let t=q(e,".tdk",".tdk-out","spec.master"),r=ne(t);if(r!==void 0)return/"database-management"\s*:\s*True/.test(r)}function ya(e){let t=q(e,".tdk",".tdk-out"),r=ne(q(t,"Tiltfile")),n=ne(q(t,"spec.master")),s=ne(q(t,"tdk-cli-ext","discovery","config.star")),o=ne(q(t,"tdk-cli-ext","engine","topologies","tilt","config","profiles.star"));if(!r||!n||!s||!o)return!1;let i=n.match(/PRE_ALPHA_RESOURCES\s*=\s*\{([^}]*)\}/)?.[1],a=rs(s,"CORE_INFRA");return/FOCUS_MODE\s*,\s*FOCUS_ENABLED_ALL\s*,\s*FOCUS_ENABLED_RESOURCES\s*=\s*Config\.apply_focus\(cfg\)/.test(r)&&/if FOCUS_MODE and FOCUS_ENABLED_ALL\s*:/.test(r)&&/"[^"]+"\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 Sa(e){let t=ts(e);if(!t)return!1;let r=t.phases??{};for(let s of es){let o=r[s]?.enabledStacks;if(Array.isArray(o)&&o.includes(H))return!0}let n=t.always_enabled_infra??Ht;return Array.isArray(n)&&n.includes(H)}function ba(e){let t=new Set;for(let s of Qn)t.add(s);for(let s of b(e))t.add(s.name),s.stack&&t.add(s.stack);let r=ts(e);if(r){let s=r.phases??{};for(let i of es){let a=s[i]?.enabledStacks;if(Array.isArray(a))for(let c of a)t.add(c)}let o=r.always_enabled_infra??Ht;if(Array.isArray(o))for(let i of o)t.add(i)}let n=ns(e);if(Array.isArray(n))for(let s of n)t.add(s);return t}function Vt(e){let t=Sa(e),r=ns(e),n=Array.isArray(r)&&r.includes(H),s=ka(e)===!0,o=t||n||s,i=!t&&ya(e),a=ba(e),c=[],u=[];for(let g of b(e)){let k=g.config?.dependsOn??[],h=!1;for(let p of k){if(ga(p)){h=!0;continue}a.has(p)||u.push({resource:g.name,name:p})}h&&c.push(g.name)}let d=o||c.length>0,l=o?"feature":c.length>0?"dependsOn":"none";return{featureOn:o,featureOnFromProjectJson:t,featureOnFromTiltfile:n,featureOnFromSpecMaster:s,focusWouldEnableDatabaseManagement:i,dependsOnUsers:c,willStart:d,reason:l,unknownDependsOnNames:u}}var Ve=1e4,Ea=/\.(?:[cm]?[jt]sx?|vue)$/,wa=/(?:\.test\.|\.spec\.|\/tests?\/|\/__tests__\/)/,$a=7,Ra=new Set(["node_modules",F,"dist","tests","__tests__"]);function is(e){try{let t=JSON.parse(ve(O(e,".tdk",P),"utf-8"));return typeof t?.project?.name=="string"?t.project.name:void 0}catch{return}}function _a(e){try{let t=JSON.parse(ve(e,"utf-8")).params;return t&&typeof t=="object"?t:{}}catch{return{}}}function Kt(e){try{let t=JSON.parse(ve(O(e,D),"utf-8"));return t&&typeof t=="object"?t:{}}catch{return{}}}function ss(e){if(typeof e!="string")return;let t=e.match(/(?:^|[^0-9])(\d+)(?:\.|$)/);return t?Number(t[1]):void 0}function Oa(e){let t=Ge(e);if(t===void 0)return["missing prisma/schema.prisma"];let r=t.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,""),n=[],s=r.match(/datasource\s+\w+\s*\{([^}]*)\}/)?.[1]??"";return/provider\s*=\s*["']postgresql["']/.test(s)||n.push("schema provider is not postgresql"),/\b(?:url|directUrl)\s*=/.test(r)&&n.push("schema still declares url/directUrl"),n}function Aa(e){let t=O(e,F,"prisma.config.autogenerated.ts"),n=[O(e,"prisma.config.ts"),t].find(i=>Gt(i));if(!n)return["missing prisma.config.ts or generated Prisma config"];let o=(Ge(n)??"").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 as(e=m()??process.cwd()){let t=b(e),r=t.filter(o=>o.config?.featuresEnabled?.includes("prisma")),n=[],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")&&n.push(`${o.name}: use featuresEnabled, not features, for Prisma`)}if(r.length===0)return n.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:`${S(n.length,"Prisma consistency error")}:
263
+ ${n.join(`
264
+ `)}`,fix:"Use featuresEnabled to opt into the validated Prisma 7 shape"};for(let o of r){let i=Kt(o.path).dependencies,c={...Kt(o.path).devDependencies??{},...i??{}},u=ss(c.prisma),d=ss(c["@prisma/client"]);if(u===void 0||d===void 0?n.push(`${o.name}: prisma and @prisma/client are required`):(u!==d||u!==$a)&&n.push(`${o.name}: prisma packages must both be major 7`),n.push(...Oa(O(o.path,"prisma","schema.prisma")).map(g=>`${o.name}: ${g}`)),n.push(...Aa(o.path).map(g=>`${o.name}: ${g}`)),(o.config?.appType??o.type)==="migrator")o.config?.dependsOn?.some(k=>k==="postgres"||k===H)||n.push(`${o.name}: migrator must depend on postgres or database-management`);else{o.config?.dependsOn?.some(p=>s.some(y=>y.name===p))||n.push(`${o.name}: API must depend on its Prisma migrator`);let k=Kt(o.path).scripts;Object.entries(k??{}).some(([p,y])=>gs.has(p)&&typeof y=="string"&&/prisma\s+migrate/.test(y))&&n.push(`${o.name}: API start script must not run prisma migrate`);let h=O(o.path,o.config?.dockerfile??"Dockerfile");He(h,!0)&&n.push(`${o.name}: API image/startup must not run Prisma migrations`)}}return r.length>0&&!Vt(e).willStart&&n.push("shared platform Postgres will not start for the Prisma resources"),n.length===0?{name:"Prisma 7 consistency",didPass:!0,message:"Prisma resources use the validated Prisma 7 shape"}:{name:"Prisma 7 consistency",didPass:!1,message:`${S(n.length,"Prisma consistency error")}:
265
+ ${n.join(`
266
+ `)}`,fix:"Use Prisma 7 packages and config, put migrations in a migrator, and make the API depend on that migrator"}}function cs(e){let t=new Map;for(let r of e){let n=r.config?.port;w(r.config?.appType)&&typeof n=="number"&&t.set(r.name,n)}return t}function Da(e){let t=e.config?.language;return typeof t=="string"&&Object.hasOwn(re,t)&&re[t].createFiles!==void 0}function Ca(e){return(e.config?.appType??e.type)===B}function us(e=m()??process.cwd()){let t=b(e).filter(r=>!Ca(r)&&!Da(r)&&!Gt(O(r.path,D))).map(r=>r.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:`${S(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 Ke(e=m()??process.cwd()){let t=new Map;for(let s of b(e)){let o=t.get(s.name)??[];o.push(Pe(e,s.configPath)||s.configPath),t.set(s.name,o)}let r=[...t].filter(([,s])=>s.length>1);if(r.length===0)return{name:"Duplicate resource names",didPass:!0,message:"Every resource has a unique appName"};let n=r.map(([s,o])=>`"${s}" in ${o.join(" and ")}`);return{name:"Duplicate resource names",didPass:!1,message:`${S(r.length,"appName")} used by more than one resource:
267
+ ${n.join(`
268
+ `)}`,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 Na(e){let t=e.config?.appType;return w(t)?!0:t===B&&e.config?.exposeViaProxy!==!1}function ds(e=m()??process.cwd()){let t=new Map;for(let s of b(e)){let o=s.config?.port;if(typeof o!="number"||!Na(s))continue;let i=t.get(o)??[];i.push(s.name),t.set(o,i)}let r=[...t].filter(([,s])=>s.length>1);if(r.length===0)return{name:"Duplicate resource ports",didPass:!0,message:"No two routed resources use the same port"};let n=r.map(([s,o])=>`port ${s}: ${o.join(", ")}`);return{name:"Duplicate resource ports",didPass:!1,isWarning:!0,message:`${S(r.length,"port")} used by more than one routed resource:
269
+ ${n.join(`
270
+ `)}`,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 ja=/https?:\/\/([a-z][a-z0-9-]*):(\d+)/g;function ls(e=m()??process.cwd()){let t=b(e),r=cs(t),n=new Map([...r].map(([o,i])=>[i,o])),s=[];for(let o of t)for(let[i,a]of Object.entries(_a(o.configPath)))for(let[,c,u]of String(a).matchAll(ja)){let d=Number(u),l=r.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")&&n.has(d)&&n.get(d)!==o.name&&s.push(`${o.name} param ${i}: localhost:${d} is ${o.name} itself inside its container; ${n.get(d)} is reached as ${n.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:`${S(s.length,"service URL")} in params that cannot connect:
271
271
  ${s.join(`
272
- `)}`,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 Wt(e){let t=[],n;try{n=ss(e,{withFileTypes:!0})}catch{return t}for(let r of n){let s=O(e,r.name);r.isDirectory()?Ra.has(r.name)||t.push(...Wt(s)):Ea.test(r.name)&&!wa.test(s)&&t.push(s)}return t}var Ia=/(?:localhost|127\.0\.0\.1):(\d{2,5})\b/g,ls=/^\s*(?:\/\/|\/\*|\*|<!--|#)/;function ps(e=m()??process.cwd()){let t=new Map;for(let r of b(e)){let s=r.config;if(!(w(s?.appType)||s?.appType===B&&s.exposeViaProxy!==!1))continue;let i=va(r.path),a=s?.stack??Pa(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(`
273
- `),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 fs(e=m()??process.cwd()){let t=b(e),n=new Map([...as(t)].map(([o,i])=>[i,o])),r=[];for(let o of t.filter(i=>i.config?.appType==="frontend"))for(let i of Wt(O(o.path,"src")))ve(i,"utf-8").split(`
274
- `).forEach((a,c)=>{if(!ls.test(a))for(let[,u]of a.matchAll(Ia)){let d=n.get(Number(u));d&&r.push(`${Pe(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=os(e)??"<project>";return{name:"Frontend backend URLs",didPass:!1,message:`${S(r.length,"frontend call")} to a backend port that TDK does not publish on localhost:
275
- ${r.join(`
276
- `)}`,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 ms=/\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/,hs=new Set(["start","dev","serve","prestart","predev","preserve"]),Fa=/\.(?:sh|bash)$/,Ma=/^\s*(?:CMD|ENTRYPOINT)\b/i;function Ge(e){try{return ve(e,"utf-8")}catch{return}}function La(e){let t=Ge(O(e,D));if(t===void 0)return[];let n={};try{n=JSON.parse(t)?.scripts??{}}catch{return[]}return Object.entries(n).filter(([r,s])=>hs.has(r)&&typeof s=="string"&&ms.test(s)).map(([r])=>`package.json "${r}" script`)}function He(e,t){let n=Ge(e);return n===void 0?!1:n.split(`
277
- `).some(r=>ms.test(r.replace(/["'`,[\]]+/g," "))&&!ls.test(r)&&(!t||Ma.test(r)))}function gs(e=m()??process.cwd()){let t=[];for(let n of b(e)){let r=n.config?.appType??n.type;if(r!=="backend"&&r!=="worker")continue;let s=n.path;for(let a of La(s))t.push(`${n.name}: ${a}`);let o=O(s,n.config?.dockerfile??"Dockerfile");He(o,!0)&&t.push(`${n.name}: ${Pe(e,o)} CMD or ENTRYPOINT`);let i=[];try{i=ss(s,{withFileTypes:!0})}catch{}for(let a of i){let c=O(s,a.name);a.isFile()&&Fa.test(a.name)&&He(c,!1)&&t.push(`${n.name}: ${Pe(e,c)}`)}for(let a of Wt(O(s,"src")))He(a,!1)&&t.push(`${n.name}: ${Pe(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:`${S(t.length,"migration command")} run from a backend or worker's own start-up:
272
+ `)}`,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 Wt(e){let t=[],r;try{r=os(e,{withFileTypes:!0})}catch{return t}for(let n of r){let s=O(e,n.name);n.isDirectory()?Ra.has(n.name)||t.push(...Wt(s)):Ea.test(n.name)&&!wa.test(s)&&t.push(s)}return t}var Ia=/(?:localhost|127\.0\.0\.1):(\d{2,5})\b/g,ps=/^\s*(?:\/\/|\/\*|\*|<!--|#)/;function fs(e=m()??process.cwd()){let t=new Map;for(let n of b(e)){let s=n.config;if(!(w(s?.appType)||s?.appType===B&&s.exposeViaProxy!==!1))continue;let i=va(n.path),a=s?.stack??Pa(i),c=`${i}\0${a}`,u=t.get(c)??{stack:a,resources:[]};u.resources.push(n),t.set(c,u)}let r=[];for(let{stack:n,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&&r.push(`stack "${n}": ${i.sort().join(", ")} lose the shared /api/${n}-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&&r.push(`stack "${n}": ${d.sort().join(" and ")} both set traefik.${a} "${u}", so Traefik cannot tell them apart`)}}return r.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:r.join(`
273
+ `),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 ms(e=m()??process.cwd()){let t=b(e),r=new Map([...cs(t)].map(([o,i])=>[i,o])),n=[];for(let o of t.filter(i=>i.config?.appType==="frontend"))for(let i of Wt(O(o.path,"src")))ve(i,"utf-8").split(`
274
+ `).forEach((a,c)=>{if(!ps.test(a))for(let[,u]of a.matchAll(Ia)){let d=r.get(Number(u));d&&n.push(`${Pe(e,i)}:${c+1} calls localhost:${u} (${d})`)}});if(n.length===0)return{name:"Frontend backend URLs",didPass:!0,message:"No frontend calls a backend through a localhost port"};let s=is(e)??"<project>";return{name:"Frontend backend URLs",didPass:!1,message:`${S(n.length,"frontend call")} to a backend port that TDK does not publish on localhost:
275
+ ${n.join(`
276
+ `)}`,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 hs=/\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/,gs=new Set(["start","dev","serve","prestart","predev","preserve"]),Fa=/\.(?:sh|bash)$/,Ma=/^\s*(?:CMD|ENTRYPOINT)\b/i;function Ge(e){try{return ve(e,"utf-8")}catch{return}}function La(e){let t=Ge(O(e,D));if(t===void 0)return[];let r={};try{r=JSON.parse(t)?.scripts??{}}catch{return[]}return Object.entries(r).filter(([n,s])=>gs.has(n)&&typeof s=="string"&&hs.test(s)).map(([n])=>`package.json "${n}" script`)}function He(e,t){let r=Ge(e);return r===void 0?!1:r.split(`
277
+ `).some(n=>hs.test(n.replace(/["'`,[\]]+/g," "))&&!ps.test(n)&&(!t||Ma.test(n)))}function ks(e=m()??process.cwd()){let t=[];for(let r of b(e)){let n=r.config?.appType??r.type;if(n!=="backend"&&n!=="worker")continue;let s=r.path;for(let a of La(s))t.push(`${r.name}: ${a}`);let o=O(s,r.config?.dockerfile??"Dockerfile");He(o,!0)&&t.push(`${r.name}: ${Pe(e,o)} CMD or ENTRYPOINT`);let i=[];try{i=os(s,{withFileTypes:!0})}catch{}for(let a of i){let c=O(s,a.name);a.isFile()&&Fa.test(a.name)&&He(c,!1)&&t.push(`${r.name}: ${Pe(e,c)}`)}for(let a of Wt(O(s,"src")))He(a,!1)&&t.push(`${r.name}: ${Pe(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:`${S(t.length,"migration command")} run from a backend or worker's own start-up:
278
278
  ${t.join(`
279
- `)}`,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 We(e=m()??process.cwd()){let t=b(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(Gt(O(e,"services","platform","messaging",he)))return{name:"NATS broker",didPass:!0,message:`${S(t.length,"resource")} enable nats and services/platform/messaging/docker-compose.yml is present`};let n=(os(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 ks(e=m()??process.cwd()){let t=Vt(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:`${S(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 Ba(e){let t=[];for(let n of e.split(`
280
- `)){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 ys(e=m()??process.cwd(),t=xa){let n;try{n=process.platform==="win32"?Ta("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:Ve,windowsHide:!0}):t("ps -Ao pid=,command=",{encoding:"utf-8",timeout:Ve})}catch{return{name:"Tilt processes",didPass:!0,isSkipped:!0,message:"Could not list processes"}}let r=Ba(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 Ss(e=M){let t=`tdk_doctor_probe_${process.pid}`;try{await e(`docker network create ${t}`,Ve)}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}`,Ve)}catch{}return{name:"Docker networks",didPass:!0,message:"Docker can create networks"}}import{randomBytes as Ts}from"node:crypto";import{existsSync as qt,readFileSync as xs,writeFileSync as Ps}from"node:fs";import{join as zt}from"node:path";import{randomBytes as Ua}from"node:crypto";import{closeSync as Ha,fchmodSync as Va,fsyncSync as Ka,openSync as Ga,renameSync as Wa,rmSync as Ja,statSync as qa,writeFileSync as za}from"node:fs";import{basename as Ya,dirname as Xa,join as Za}from"node:path";function bs(e,t){let n=Za(Xa(e),`.${Ya(e)}.${process.pid}.${Ua(4).toString("hex")}.tmp`),r;try{r=qa(e).mode&511}catch{r=void 0}try{let s=Ga(n,"wx");try{r!==void 0&&Va(s,r),za(s,t,"utf-8"),Ka(s)}finally{Ha(s)}Wa(n,e)}catch(s){throw Ja(n,{force:!0}),s}}var se=[{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}],vs=()=>Ts(16).toString("hex"),Qa=()=>Ts(32).toString("hex");function Jt(e,t){return e==="DB_PASSWORD"?t:e==="JWT_SECRET"?Qa():e==="DATABASE_URL"?`postgresql://postgres:${t}@postgres:5432/app_dev`:se.find(n=>n.name===e)?.default??""}function ec(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:`
281
- `,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 oe(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,ec(o.slice(i+1)))}return t}function Es(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 ws(){let e=vs(),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 se)t.push(...Es(n)),t.push(`${n.name}=${Jt(n.name,e)}`),t.push("");return t.join(`
282
- `)}function tc(e){let t=e.match(/^[a-z][a-z0-9+.-]*:\/\/[^:/@\s]+:([^@\s]*)@/i);if(!(!t||t[1].includes("$")))return t[1]}function $s(e){let t=zt(e,".env"),n={missing:[],invalid:[],warnings:[]};if(!qt(t))return{missing:se.filter(i=>i.required).map(i=>i.name),invalid:[],warnings:[".env file not found - will be auto-generated"]};let r=oe(xs(t,"utf-8"));for(let i of se)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=tc(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 nc(e,t,n){if(!oe(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 tf(e){let t=zt(e,".env");if(!qt(t))return Ps(t,ws(),{mode:384}),se.map(l=>l.name);let n=xs(t,"utf-8"),r=oe(n),s=se.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:vs(),u=n.split(/(\r\n|\n|\r)/);for(let l of i){let g=-1;for(let k=0;k<u.length;k+=2)oe(u[k]).has(l.name)&&(g=k);if(g<0)throw new Error(`Could not locate empty .env assignment for ${l.name}`);u[g]=nc(u[g],l.name,Jt(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 k of o)l.push(...Es(k)),l.push(`${k.name}=${Jt(k.name,c)}`),l.push("");let g=d.endsWith(`
279
+ `)}`,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 We(e=m()??process.cwd()){let t=b(e).filter(n=>n.config?.featuresEnabled?.includes("nats")).map(n=>n.name);if(t.length===0)return{name:"NATS broker",didPass:!0,message:"No resource enables the nats feature",isSkipped:!0};if(Gt(O(e,"services","platform","messaging",he)))return{name:"NATS broker",didPass:!0,message:`${S(t.length,"resource")} enable nats and services/platform/messaging/docker-compose.yml is present`};let r=(is(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 ${r}_nats, network ${r}_backend, external) and a "redis" service, which TDK registers alongside it`}}function ys(e=m()??process.cwd()){let t=Vt(e),r=" (project resource set; tdk up may select a subset and not start Postgres)",n=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`}${r}`:" Postgres will not start for this project.json/generated Tiltfile state.";return{name:"Shared platform Postgres",didPass:!1,message:`${S(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}${n}`,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:!!n,isSkipped:!n,message:n?n.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:!!n,message:`Shared platform Postgres will start because the database-management feature is enabled${o} (project-wide; not a tdk up selection).${n}`}}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:!!n,message:`Shared platform Postgres will start because ${s}${r}${n}`}}function Ba(e){let t=[];for(let r of e.split(`
280
+ `)){let n=r.match(/^\s*(\d+)\s+.*\btilt up\b.*?\s-f\s+(\S+)/i);n&&t.push({pid:Number(n[1]),root:n[2].split(/[\\/]\.tdk[\\/]/i)[0]})}return t}function Ss(e=m()??process.cwd(),t=xa){let r;try{r=process.platform==="win32"?Ta("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:Ve,windowsHide:!0}):t("ps -Ao pid=,command=",{encoding:"utf-8",timeout:Ve})}catch{return{name:"Tilt processes",didPass:!0,isSkipped:!0,message:"Could not list processes"}}let n=Ba(r),s=n.filter(i=>i.root===e),o=n.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 bs(e=M){let t=`tdk_doctor_probe_${process.pid}`;try{await e(`docker network create ${t}`,Ve)}catch(r){let n=String(r.stderr??r);return/address pools/i.test(n)?{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}`,Ve)}catch{}return{name:"Docker networks",didPass:!0,message:"Docker can create networks"}}import{randomBytes as xs}from"node:crypto";import{existsSync as qt,readFileSync as Ps,writeFileSync as vs}from"node:fs";import{join as zt}from"node:path";import{randomBytes as Ua}from"node:crypto";import{closeSync as Ha,fchmodSync as Va,fsyncSync as Ka,openSync as Ga,renameSync as Wa,rmSync as Ja,statSync as qa,writeFileSync as za}from"node:fs";import{basename as Ya,dirname as Xa,join as Za}from"node:path";function Ts(e,t){let r=Za(Xa(e),`.${Ya(e)}.${process.pid}.${Ua(4).toString("hex")}.tmp`),n;try{n=qa(e).mode&511}catch{n=void 0}try{let s=Ga(r,"wx");try{n!==void 0&&Va(s,n),za(s,t,"utf-8"),Ka(s)}finally{Ha(s)}Wa(r,e)}catch(s){throw Ja(r,{force:!0}),s}}var se=[{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}],Es=()=>xs(16).toString("hex"),Qa=()=>xs(32).toString("hex");function Jt(e,t){return e==="DB_PASSWORD"?t:e==="JWT_SECRET"?Qa():e==="DATABASE_URL"?`postgresql://postgres:${t}@postgres:5432/app_dev`:se.find(r=>r.name===e)?.default??""}function ec(e){let t=e.trim(),r=t[0];if(r==='"'||r==="'"){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===r){let a=t.slice(1,o);if(r==='"'){let c={n:`
281
+ `,r:"\r",t:" ",'"':'"',"\\":"\\",$:"$"};return a.replace(/\\([nrt"\\$])/g,(u,d)=>c[d]??d)}return a.replace(/\\'/g,"'")}}return t}let n=e.search(/\s#/);return(n===-1?e:e.slice(0,n)).trim()}function oe(e){let t=new Map,r=e.startsWith("\uFEFF")?e.slice(1):e;for(let n of r.split(/\r?\n/)){let s=n.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,ec(o.slice(i+1)))}return t}function ws(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 $s(){let e=Es(),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 r of se)t.push(...ws(r)),t.push(`${r.name}=${Jt(r.name,e)}`),t.push("");return t.join(`
282
+ `)}function tc(e){let t=e.match(/^[a-z][a-z0-9+.-]*:\/\/[^:/@\s]+:([^@\s]*)@/i);if(!(!t||t[1].includes("$")))return t[1]}function Rs(e){let t=zt(e,".env"),r={missing:[],invalid:[],warnings:[]};if(!qt(t))return{missing:se.filter(i=>i.required).map(i=>i.name),invalid:[],warnings:[".env file not found - will be auto-generated"]};let n=oe(Ps(t,"utf-8"));for(let i of se)i.required&&!n.has(i.name)&&r.missing.push(i.name),n.has(i.name)&&!(n.get(i.name)??"").trim()&&r.invalid.push(`${i.name} is set but empty`);let s=n.get("DATABASE_URL"),o=n.get("DB_PASSWORD");if(s&&o){let i=tc(s);i!==void 0&&i!==o&&r.warnings.push("DATABASE_URL carries a different password than DB_PASSWORD; the database container uses DB_PASSWORD")}return r}function rc(e,t,r){if(!oe(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)+r+a}function tf(e){let t=zt(e,".env");if(!qt(t))return vs(t,$s(),{mode:384}),se.map(l=>l.name);let r=Ps(t,"utf-8"),n=oe(r),s=se.filter(l=>l.complete?n.has(l.name)?!(n.get(l.name)??"").trim():!0:!1);if(s.length===0)return[];let o=s.filter(l=>!n.has(l.name)),i=s.filter(l=>n.has(l.name)),a=n.get("DB_PASSWORD"),c=a?.trim()?a:Es(),u=r.split(/(\r\n|\n|\r)/);for(let l of i){let g=-1;for(let k=0;k<u.length;k+=2)oe(u[k]).has(l.name)&&(g=k);if(g<0)throw new Error(`Could not locate empty .env assignment for ${l.name}`);u[g]=rc(u[g],l.name,Jt(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 k of o)l.push(...ws(k)),l.push(`${k.name}=${Jt(k.name,c)}`),l.push("");let g=d.endsWith(`
283
283
  `)||d.endsWith("\r")?"":`
284
284
  `;d+=g+l.join(`
285
- `)}return bs(t,d),s.map(l=>l.name)}function nf(e){let t=zt(e,".env");return qt(t)?!1:(Ps(t,ws(),{mode:384}),!0)}import{execFileSync as _s}from"node:child_process";import{existsSync as cc,mkdirSync as uc,readFileSync as Os,realpathSync as dc,writeFileSync as lc}from"node:fs";import{join as Ee,resolve as pc,sep as fc}from"node:path";import{createServer as sc}from"node:net";import{connect as rc}from"node:net";function Rs(e,t=500){return new Promise(n=>{let r=rc({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 oc={ingressHttp:{start:8080,end:8180},ingressHttps:{start:8443,end:8543},postgres:{start:15432,end:15532}},Je={ingressHttp:"TDK_HTTP_PORT",ingressHttps:"TDK_HTTPS_PORT",postgres:"TDK_POSTGRES_PORT"},Yt={ingressHttp:80,ingressHttps:443,postgres:5432},Xt={ingressHttp:Yt.ingressHttp,ingressHttps:Yt.ingressHttps};function ic(e,t){return e==="EACCES"&&t==="darwin"}async function Zt(e){return await Rs(e)?!1:new Promise(t=>{let n=sc();n.once("error",r=>{t(ic(r.code,process.platform))}),n.listen(e,"127.0.0.1",()=>n.close(()=>t(!0)))})}function ac(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 ie(e={}){let t=e.env??process.env,n=e.isAvailable??Zt,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[Je[a]],u=c!==void 0&&c.trim()!=="",d=e.ranges?.[a]??oc[a],l=Xt[a],g=u?[ac(Je[a],c)]:[...l===void 0?[]:[l],...Array.from({length:d.end-d.start+1},(h,p)=>d.start+p)],k;for(let h of g)if(!i.has(h)){if(await n(h)){k=h;break}if(u)throw new Error(`${Je[a]}=${h} is already in use. Choose a free host port and retry.`)}if(k===void 0)throw new Error(`No available host port in ${d.start}-${d.end} for ${a}. Set ${Je[a]} to a free port and retry.`);i.add(k),o[a]=k,r[a]=u,s[a]=u?"explicit override":k===l?"requested port is free":`selected from fallback range ${d.start}-${d.end}`}return{...o,requested:{...Yt},reason:s}}function uf(e){return`Host ports: HTTP ${e.ingressHttp}, HTTPS ${e.ingressHttps}, Postgres ${e.postgres}`}var As=Ee(".tdk",".tdk-out","host-ports.json");function mc(e,t,n){return e.split(`
286
- `).some(r=>{let[s="",o=""]=r.split("|"),i=s.toLowerCase(),a=t.toLowerCase();return(i.startsWith(`${a}_`)||i.startsWith(`${a}-`))&&o.includes(`:${n}->`)})}function Ds(e){let t=Ee(e,As);if(!cc(t))return null;try{let n=JSON.parse(Os(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 gf(e,t){let n=Ee(e,As);uc(Ee(e,".tdk",".tdk-out"),{recursive:!0}),lc(n,`${JSON.stringify(t,null,2)}
287
- `,{encoding:"utf-8",mode:384})}function kf(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 hc="com.docker.compose.project.working_dir";function gc(e,t,n){let r=new Set([pc(t)]);try{r.add(dc(t))}catch{}return e.split(`
288
- `).some(s=>{let[,o="",i=""]=s.split("|");return!i||!o.includes(`:${n}->`)?!1:[...r].some(a=>i===a||i.startsWith(`${a}${fc}`))})}function Cs(e,t,n=()=>_s("docker",["ps","--format",`{{.Names}}|{{.Ports}}|{{.Label "${hc}"}}`],{encoding:"utf-8",timeout:5e3})){let r=Ds(e);if(!r||r.ingressHttp===t)return t;try{if(gc(n(),e,r.ingressHttp))return r.ingressHttp}catch{}return t}async function qe(e,t={}){let n=Ds(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(Os(Ee(e,".tdk",P),"utf-8"));s=String(u?.project?.name??"tdk-project").replace(/-/g,"_").toLowerCase()}catch{s="tdk_project"}let o="";if(t.inspectDocker!==!1)try{o=_s("docker",["ps","--format","{{.Names}}|{{.Ports}}"],{encoding:"utf-8",timeout:5e3})}catch{}let i=u=>mc(o,s,u),a=t.isPortFree??Zt,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 ie({isAvailable:c});for(let[u,d]of Object.entries(Xt)){let l=n[u];if(d!==void 0&&l!==d&&await c(d))return ie({isAvailable:c})}return n}return ie({isAvailable:c})}import{existsSync as kc,readFileSync as yc}from"node:fs";import{join as Sc}from"node:path";var bc="[REDACTED]",we=class extends Error{path;constructor(t,n){super(`Could not read ${t}: ${n}`),this.path=t,this.name="EnvUnreadableError"}},Tc=8;function Ns(e){let t=Sc(e,".env");if(!kc(t))return[];let n;try{n=yc(t,"utf-8")}catch(s){throw new we(t,s instanceof Error?s.message:String(s))}let r=[...oe(n).values()].filter(s=>s.length>=Tc);return[...new Set(r)].sort((s,o)=>o.length-s.length)}function Qt(e,t){let n=e;for(let r of t)n=n.split(r).join(bc);return n}function ze(e,t){return t.length===0?e:typeof e=="string"?Qt(e,t):Array.isArray(e)?e.map(n=>ze(n,t)):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,ze(r,t)])):e}import{relative as xc}from"node:path";function Ye(e,t){return xc(e,t.configPath)||t.configPath}function js(e){let t=e.config?.dependsOn;return t===void 0?[]:Array.isArray(t)&&t.every(n=>typeof n=="string")?t:null}function Pc(e){let t=new Set(e.map(a=>a.name)),n=new Map(e.map(a=>[a.name,(js(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 en(e=m()??process.cwd()){let t=b(e).flatMap(n=>js(n)===null?[`${Ye(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:`${S(t.length,"invalid dependsOn","invalid dependsOn")}:
285
+ `)}return Ts(t,d),s.map(l=>l.name)}function rf(e){let t=zt(e,".env");return qt(t)?!1:(vs(t,$s(),{mode:384}),!0)}import{execFileSync as Os}from"node:child_process";import{existsSync as cc,mkdirSync as uc,readFileSync as As,realpathSync as dc,writeFileSync as lc}from"node:fs";import{join as Ee,resolve as pc,sep as fc}from"node:path";import{createServer as sc}from"node:net";import{connect as nc}from"node:net";function _s(e,t=500){return new Promise(r=>{let n=nc({port:e,host:"127.0.0.1"}),s=o=>{n.destroy(),r(o)};n.setTimeout(t,()=>s(!1)),n.once("connect",()=>s(!0)),n.once("error",()=>s(!1))})}var oc={ingressHttp:{start:8080,end:8180},ingressHttps:{start:8443,end:8543},postgres:{start:15432,end:15532}},Je={ingressHttp:"TDK_HTTP_PORT",ingressHttps:"TDK_HTTPS_PORT",postgres:"TDK_POSTGRES_PORT"},Yt={ingressHttp:80,ingressHttps:443,postgres:5432},Xt={ingressHttp:Yt.ingressHttp,ingressHttps:Yt.ingressHttps};function ic(e,t){return e==="EACCES"&&t==="darwin"}async function Zt(e){return await _s(e)?!1:new Promise(t=>{let r=sc();r.once("error",n=>{t(ic(n.code,process.platform))}),r.listen(e,"127.0.0.1",()=>r.close(()=>t(!0)))})}function ac(e,t){let r=Number(t);if(!Number.isInteger(r)||r<1||r>65535)throw new Error(`${e} must be an integer between 1 and 65535 (received ${JSON.stringify(t)})`);return r}async function ie(e={}){let t=e.env??process.env,r=e.isAvailable??Zt,n={ingressHttp:!1,ingressHttps:!1,postgres:!1},s={ingressHttp:"",ingressHttps:"",postgres:""},o={explicit:n},i=new Set;for(let a of["ingressHttp","ingressHttps","postgres"]){let c=t[Je[a]],u=c!==void 0&&c.trim()!=="",d=e.ranges?.[a]??oc[a],l=Xt[a],g=u?[ac(Je[a],c)]:[...l===void 0?[]:[l],...Array.from({length:d.end-d.start+1},(h,p)=>d.start+p)],k;for(let h of g)if(!i.has(h)){if(await r(h)){k=h;break}if(u)throw new Error(`${Je[a]}=${h} is already in use. Choose a free host port and retry.`)}if(k===void 0)throw new Error(`No available host port in ${d.start}-${d.end} for ${a}. Set ${Je[a]} to a free port and retry.`);i.add(k),o[a]=k,n[a]=u,s[a]=u?"explicit override":k===l?"requested port is free":`selected from fallback range ${d.start}-${d.end}`}return{...o,requested:{...Yt},reason:s}}function uf(e){return`Host ports: HTTP ${e.ingressHttp}, HTTPS ${e.ingressHttps}, Postgres ${e.postgres}`}var Ds=Ee(".tdk",".tdk-out","host-ports.json");function mc(e,t,r){return e.split(`
286
+ `).some(n=>{let[s="",o=""]=n.split("|"),i=s.toLowerCase(),a=t.toLowerCase();return(i.startsWith(`${a}_`)||i.startsWith(`${a}-`))&&o.includes(`:${r}->`)})}function Cs(e){let t=Ee(e,Ds);if(!cc(t))return null;try{let r=JSON.parse(As(t,"utf-8"));if(!r||typeof r!="object")return null;let n=r;return!Number.isInteger(n.ingressHttp)||!Number.isInteger(n.ingressHttps)||!Number.isInteger(n.postgres)||!n.requested||!n.explicit||!n.reason?null:n}catch{return null}}function gf(e,t){let r=Ee(e,Ds);uc(Ee(e,".tdk",".tdk-out"),{recursive:!0}),lc(r,`${JSON.stringify(t,null,2)}
287
+ `,{encoding:"utf-8",mode:384})}function kf(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 hc="com.docker.compose.project.working_dir";function gc(e,t,r){let n=new Set([pc(t)]);try{n.add(dc(t))}catch{}return e.split(`
288
+ `).some(s=>{let[,o="",i=""]=s.split("|");return!i||!o.includes(`:${r}->`)?!1:[...n].some(a=>i===a||i.startsWith(`${a}${fc}`))})}function Ns(e,t,r=()=>Os("docker",["ps","--format",`{{.Names}}|{{.Ports}}|{{.Label "${hc}"}}`],{encoding:"utf-8",timeout:5e3})){let n=Cs(e);if(!n||n.ingressHttp===t)return t;try{if(gc(r(),e,n.ingressHttp))return n.ingressHttp}catch{}return t}async function qe(e,t={}){let r=Cs(e),n=["TDK_HTTP_PORT","TDK_HTTPS_PORT","TDK_POSTGRES_PORT"].some(u=>process.env[u]);if(t.inspectDocker===!1&&r&&!n)return r;let s="";try{let u=JSON.parse(As(Ee(e,".tdk",P),"utf-8"));s=String(u?.project?.name??"tdk-project").replace(/-/g,"_").toLowerCase()}catch{s="tdk_project"}let o="";if(t.inspectDocker!==!1)try{o=Os("docker",["ps","--format","{{.Names}}|{{.Ports}}"],{encoding:"utf-8",timeout:5e3})}catch{}let i=u=>mc(o,s,u),a=t.isPortFree??Zt,c=async u=>await a(u)||i(u);if(r&&!n){for(let u of[r.ingressHttp,r.ingressHttps,r.postgres])if(!await c(u))return ie({isAvailable:c});for(let[u,d]of Object.entries(Xt)){let l=r[u];if(d!==void 0&&l!==d&&await c(d))return ie({isAvailable:c})}return r}return ie({isAvailable:c})}import{existsSync as kc,readFileSync as yc}from"node:fs";import{join as Sc}from"node:path";var bc="[REDACTED]",we=class extends Error{path;constructor(t,r){super(`Could not read ${t}: ${r}`),this.path=t,this.name="EnvUnreadableError"}},Tc=8;function js(e){let t=Sc(e,".env");if(!kc(t))return[];let r;try{r=yc(t,"utf-8")}catch(s){throw new we(t,s instanceof Error?s.message:String(s))}let n=[...oe(r).values()].filter(s=>s.length>=Tc);return[...new Set(n)].sort((s,o)=>o.length-s.length)}function Qt(e,t){let r=e;for(let n of t)r=r.split(n).join(bc);return r}function ze(e,t){return t.length===0?e:typeof e=="string"?Qt(e,t):Array.isArray(e)?e.map(r=>ze(r,t)):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([r,n])=>[r,ze(n,t)])):e}import{relative as xc}from"node:path";function Ye(e,t){return xc(e,t.configPath)||t.configPath}function Is(e){let t=e.config?.dependsOn;return t===void 0?[]:Array.isArray(t)&&t.every(r=>typeof r=="string")?t:null}function Pc(e){let t=new Set(e.map(a=>a.name)),r=new Map(e.map(a=>[a.name,(Is(a)??[]).filter(c=>t.has(c))])),n=new Map,s=new Map,o=[],i=a=>{s.set(a,"visiting"),o.push(a);for(let c of r.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)];n.set(l.join(">"),[...l,l[0]??c])}else s.has(c)||i(c);o.pop(),s.set(a,"done")};for(let a of[...r.keys()].sort())s.has(a)||i(a);return[...n.values()]}function er(e=m()??process.cwd()){let t=b(e).flatMap(r=>Is(r)===null?[`${Ye(e,r)} dependsOn ${JSON.stringify(r.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:`${S(t.length,"invalid dependsOn","invalid dependsOn")}:
289
289
  ${t.join(`
290
- `)}`,fix:'Write "dependsOn" as an array of service names, for example ["postgres", "api"]'}}function tn(e=m()??process.cwd()){let t=b(e),n=new Map(t.map(o=>[o.name,o])),r=Pc(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?Ye(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"}:
290
+ `)}`,fix:'Write "dependsOn" as an array of service names, for example ["postgres", "api"]'}}function tr(e=m()??process.cwd()){let t=b(e),r=new Map(t.map(o=>[o.name,o])),n=Pc(t);if(n.length===0)return{name:"Circular dependencies",didPass:!0,message:"No service depends on itself through dependsOn"};let s=n.map(o=>{let i=r.get(o[0]??""),a=o[1]??"";return`${i?Ye(e,i):o[0]} dependsOn "${a}": circular dependency ${o.join(" -> ")}`});return{name:"Circular dependencies",didPass:!1,message:`${n.length} ${n.length===1?"circular dependency":"circular dependencies"}:
291
291
  ${s.join(`
292
- `)}`,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 nn(e=m()??process.cwd()){let t=b(e).flatMap(n=>{let r=n.config?.port;return r===void 0?[]:typeof r=="number"&&Number.isInteger(r)&&r>=1&&r<=65535?[]:[`${Ye(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:`${S(t.length,"invalid port")}:
292
+ `)}`,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 rr(e=m()??process.cwd()){let t=b(e).flatMap(r=>{let n=r.config?.port;return n===void 0?[]:typeof n=="number"&&Number.isInteger(n)&&n>=1&&n<=65535?[]:[`${Ye(e,r)} port ${JSON.stringify(n)}: 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:`${S(t.length,"invalid port")}:
293
293
  ${t.join(`
294
- `)}`,fix:'Set "port" to the port the service listens on, an integer from 1 to 65535'}}function rn(e=m()??process.cwd(),t=!1){let n=[],r=[];for(let o of b(e)){let i=o.config?.schemaVersion;if(i===ke)continue;let a=Ye(e,o);i===void 0?n.push(`${a} schemaVersion: missing`):r.push(`${a} schemaVersion ${JSON.stringify(i)}: this tdk supports ${ke}`)}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:`${S(n.length+r.length,"service.json file")} without a supported schemaVersion:
295
- ${[...n,...r].join(`
296
- `)}`,fix:s.join(". ")}}function Of(e){let t=rn(e);t.didPass||(console.warn(f.yellow(`\u26A0 ${t.message}`)),t.fix&&console.warn(f.gray(` ${t.fix}`)))}function Af(e,t={},n=process.exit){let r=[Ke(e),en(e),tn(e),nn(e)].filter(o=>!o.didPass);if(r.length===0)return;let s=r.map(o=>`${o.message}${o.fix?`
294
+ `)}`,fix:'Set "port" to the port the service listens on, an integer from 1 to 65535'}}function nr(e=m()??process.cwd(),t=!1){let r=[],n=[];for(let o of b(e)){let i=o.config?.schemaVersion;if(i===ke)continue;let a=Ye(e,o);i===void 0?r.push(`${a} schemaVersion: missing`):n.push(`${a} schemaVersion ${JSON.stringify(i)}: this tdk supports ${ke}`)}if(r.length===0&&n.length===0)return{name:"schemaVersion",didPass:!0,message:"Every service.json has a supported schemaVersion"};let s=[...r.length>0?["Run `tdk config migrate` to add the missing schemaVersion"]:[],...n.length>0?["A version this tdk does not support cannot be migrated: upgrade tdk"]:[]];return{name:"schemaVersion",didPass:!1,isWarning:!t,message:`${S(r.length+n.length,"service.json file")} without a supported schemaVersion:
295
+ ${[...r,...n].join(`
296
+ `)}`,fix:s.join(". ")}}function Of(e){let t=nr(e);t.didPass||(console.warn(f.yellow(`\u26A0 ${t.message}`)),t.fix&&console.warn(f.gray(` ${t.fix}`)))}function Af(e,t={},r=process.exit){let n=[Ke(e),er(e),tr(e),rr(e)].filter(o=>!o.didPass);if(n.length===0)return;let s=n.map(o=>`${o.message}${o.fix?`
297
297
  Fix: ${o.fix}`:""}`).join(`
298
- `);t.onInvalid?.(s);for(let o of r)console.error(f.red(`\u2717 ${o.message}`)),o.fix&&console.error(f.gray(` Fix: ${o.fix}`));n(1)}import{readFileSync as vc}from"node:fs";import{join as Ec}from"node:path";function Is(e){let t=e.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);return t?[Number(t[1]),Number(t[2]),Number(t[3]??0)]:null}function wc(e){try{return JSON.parse(vc(Ec(e,".tdk",P),"utf-8"))?.minTdkVersion}catch{return}}function Fs(e,t){let n=wc(e);if(n===void 0)return{status:"none"};let r=typeof n=="string"?Is(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=Is(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 V=1e4,X={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"},Ls="WSL2 detected. Use Docker Desktop WSL integration. Guide: docs/wsl2.md",Bs="Native Windows landscape boot is unsupported. Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md",sn=[0,25,0],Z=[1,2,0];function Xe(e,t){let n=un(e);return n?dn(n,t):!1}function Oc(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:`${Ls} Project is on the WSL filesystem.`};let s=`${Ls} 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 Ac(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 Dc(e=process.env,t=!1){let n=(e.TDK_BIND_ADDRESS??"").trim();return Ac(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 Us(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 Cc(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 Vs(e){return Yr(e)}function Nc(e,t,n,r,s){return async()=>{try{return await M(t,V),{name:e,didPass:!0,message:n}}catch{return{name:e,didPass:!1,message:r,fix:s}}}}async function on(e){try{return await M(e,V),!0}catch{return!1}}async function pn(){if(process.platform==="win32")try{return await M("docker ps",V),{name:A,didPass:!0,message:"Docker Desktop Linux container engine is running"}}catch{return{name:A,didPass:!1,message:"Docker is not running",fix:X.dockerDaemonDown}}let e=!!$("docker");try{return await M("docker ps",V),{name:A,didPass:!0,message:"Docker daemon is running"}}catch(n){if(Vs(n))return{name:A,didPass:!1,message:"Docker daemon is not responding",fix:X.dockerDaemonDown}}let t=Hn(await on("pgrep -f com.docker.backend"));return t||(await on("colima status")?{name:A,didPass:!0,message:"Colima (Docker runtime) is running"}:$("colima")?{name:A,didPass:!1,message:"Colima is installed but not running",fix:X.dockerDaemonDown}:await on("podman ps")?{name:A,didPass:!0,message:"Podman is running"}:e?{name:A,didPass:!1,message:"Docker daemon is not running",fix:X.dockerDaemonDown}:{name:A,didPass:!1,message:"Docker is not running",fix:X.dockerMissing})}var fn=Nc("Docker Compose","docker compose version","Docker Compose plugin available","Docker Compose plugin not found","Install Docker Compose: https://docs.docker.com/compose/install/"),jc=[25,0,0],Ic=[2,20,2];function un(e){let t=e.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);return t?[Number(t[1]),Number(t[2]),Number(t[3]??0)]:null}function dn(e,t){for(let[n,r]of t.entries()){let s=e[n]??0;if(s!==r)return s>r}return!0}async function mn(e=M){let t=async a=>String(await e(a,V)).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=un(n),o=un(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 dn(s,jc)||i.push(`Docker Engine ${n} (need 25.0+)`),dn(o,Ic)||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):
298
+ `);t.onInvalid?.(s);for(let o of n)console.error(f.red(`\u2717 ${o.message}`)),o.fix&&console.error(f.gray(` Fix: ${o.fix}`));r(1)}import{readFileSync as vc}from"node:fs";import{join as Ec}from"node:path";function Fs(e){let t=e.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);return t?[Number(t[1]),Number(t[2]),Number(t[3]??0)]:null}function wc(e){try{return JSON.parse(vc(Ec(e,".tdk",P),"utf-8"))?.minTdkVersion}catch{return}}function Ms(e,t){let r=wc(e);if(r===void 0)return{status:"none"};let n=typeof r=="string"?Fs(r):null;if(!n||!/^\d+\.\d+\.\d+$/.test(String(r).trim()))return{status:"malformed",message:`.tdk/project.json minTdkVersion ${JSON.stringify(r)} is not a version like "1.3.80"`,fix:'Set minTdkVersion to a MAJOR.MINOR.PATCH string, for example "1.3.80".'};let s=Fs(t),o=s!==null&&(()=>{for(let[a,c]of n.entries()){let u=s[a]??0;if(u!==c)return u>c}return!0})(),i=n.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 U=1e4,X={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"},Bs="WSL2 detected. Use Docker Desktop WSL integration. Guide: docs/wsl2.md",Us="Native Windows landscape boot is unsupported. Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md",sr=[0,25,0],Z=[1,2,0];function Xe(e,t){let r=cr(e);return r?ur(r,t):!1}function Oc(e,t,r=process.platform==="linux"&&!!process.env.WSL_DISTRO_NAME){if(!r)return{name:"WSL project location",didPass:!0,isSkipped:!0,message:"Not running in WSL2 - skipped project filesystem check"};let n=e.replace(/\\/g,"/").replace(/\/+$/,"").toLowerCase();if(n!=="/mnt/c"&&!n.startsWith("/mnt/c/"))return{name:"WSL project location",didPass:!0,message:`${Bs} Project is on the WSL filesystem.`};let s=`${Bs} 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 Ac(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 Dc(e=process.env,t=!1){let r=(e.TDK_BIND_ADDRESS??"").trim();return Ac(r)?{name:"Dev Port Bind Address",didPass:!t,isWarning:!t,message:`TDK_BIND_ADDRESS is ${r}: 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:r?`Dev ports bind to ${r}`:"Dev ports bind to 127.0.0.1 (this machine only)"}}function Hs(e){let t=e.filter(n=>!n.didPass&&!n.isSkipped&&!n.isWarning),r=e.filter(n=>n.didPass||n.isSkipped||n.isWarning);return t.sort((n,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(n)-o(s)}),[...t,...r]}function Cc(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 lr(e){return Xn(e)}function Nc(e,t,r,n,s){return async(o=M)=>{try{return await o(t,U),{name:e,didPass:!0,message:r}}catch(i){return lr(i)?{name:e,didPass:!1,message:`${e} did not respond within ${U/1e3}s`,fix:s}:{name:e,didPass:!1,message:n,fix:s}}}}async function or(e){try{return await M(e,U),!0}catch{return!1}}async function pr(){if(process.platform==="win32")try{return await M("docker ps",U),{name:A,didPass:!0,message:"Docker Desktop Linux container engine is running"}}catch{return{name:A,didPass:!1,message:"Docker is not running",fix:X.dockerDaemonDown}}let e=!!$("docker");try{return await M("docker ps",U),{name:A,didPass:!0,message:"Docker daemon is running"}}catch(r){if(lr(r))return{name:A,didPass:!1,message:"Docker daemon is not responding",fix:X.dockerDaemonDown}}let t=Hr(await or("pgrep -f com.docker.backend"));return t||(await or("colima status")?{name:A,didPass:!0,message:"Colima (Docker runtime) is running"}:$("colima")?{name:A,didPass:!1,message:"Colima is installed but not running",fix:X.dockerDaemonDown}:await or("podman ps")?{name:A,didPass:!0,message:"Podman is running"}:e?{name:A,didPass:!1,message:"Docker daemon is not running",fix:X.dockerDaemonDown}:{name:A,didPass:!1,message:"Docker is not running",fix:X.dockerMissing})}var fr=Nc("Docker Compose","docker compose version","Docker Compose plugin available","Docker Compose plugin not found","Install Docker Compose: https://docs.docker.com/compose/install/"),jc=[25,0,0],Ic=[2,20,2];function cr(e){let t=e.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);return t?[Number(t[1]),Number(t[2]),Number(t[3]??0)]:null}function ur(e,t){for(let[r,n]of t.entries()){let s=e[r]??0;if(s!==n)return s>n}return!0}async function mr(e=M){let t=async a=>String(await e(a,U)).trim(),r,n;try{[r,n]=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=cr(r),o=cr(n);if(!s||!o)return{name:"Docker Versions",didPass:!0,isSkipped:!0,message:`Unrecognized Docker version output (engine "${r}", compose "${n}") - skipped version check`};let i=[];return ur(s,jc)||i.push(`Docker Engine ${r} (need 25.0+)`),ur(o,Ic)||i.push(`Docker Compose ${n} (need 2.20.2+)`),i.length===0?{name:"Docker Versions",didPass:!0,message:`Docker Engine ${r} and Compose ${n} support generated healthchecks`}:{name:"Docker Versions",didPass:!1,message:`Docker is too old for generated healthchecks (they use start_interval):
299
299
  ${i.join(`
300
- `)}`,fix:"Update Docker Desktop, or on Linux update docker-ce and the docker-compose-plugin package"}}async function hn(e=M){let t;try{t=String(await e("tilt version",V)).trim()}catch{return{name:"Tilt CLI",didPass:!1,message:"Tilt CLI not found",fix:X.tiltMissing}}return Xe(t,sn)?{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${sn.join(".")} floor`,fix:`Install Tilt v${sn.join(".")} or newer: https://docs.tilt.dev/install.html`}}async function Fc(e=M){let t;try{t=String(await e("docker info --format '{{.OSType}}'",V)).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 Mc(e=M){let t=m();if(!t)return{name:"Bun",didPass:!0,isSkipped:!0,message:"Not in a project - skipping Bun check"};if(!Ae(b(t)))return{name:"Bun",didPass:!0,isSkipped:!0,message:"No generated JS services - skipping Bun check"};try{let n=String(await e("bun --version",V)).trim();return Xe(n,Z)?{name:"Bun",didPass:!0,message:`Bun ${n} is available`}:{name:"Bun",didPass:!1,message:`Bun ${n||"version unknown"} is below the required ${Z.join(".")} floor`,fix:`Install Bun ${Z.join(".")} or newer: https://bun.sh/install`}}catch{return{name:"Bun",didPass:!1,message:"Bun is not available",fix:X.bunMissing}}}function Lc(){let e=m()??process.cwd(),t=$s(e);if(t.missing.length>0)return{name:"Environment Variables",didPass:!1,message:`Missing required env variables: ${t.missing.join(", ")}`,fix:C(v(e,".env"))?`Edit .env and set these values:
301
- ${t.missing.map(r=>`${r}=<value>`).join(`
302
- `)}`:"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 Bc(){let e=m()??process.cwd(),t=v(e,".tdk",".tdk-out"),n=at.filter(r=>!C(v(t,r)));return n.length===0?{name:"Master Configs",didPass:!0,message:`${at.join(", ")} found`}:{name:"Master Configs",didPass:!1,message:`Master configs missing: ${n.join(", ")}`,fix:"Run: tdk project"}}function Uc(e=zn()){let t=m();if(!t)return{name:"TDK version",didPass:!0,isSkipped:!0,message:"Not in a project - skipping TDK version check"};let n=Fs(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 Hc(){let e=m()??process.cwd(),t=lt(e),n=b(e).filter(s=>!De(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=>an(cn(e,s.path))).join(", ");return{name:"Resource Discovery",didPass:!1,message:`${S(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 Vc=["install-deps.sh","bun-hoisted-symlink-fix.sh","prisma-bun-client-link-fix.sh","prisma-normalize-client.sh","infisical-entrypoint.sh"],Kc=/shared-platform-engineering\/docker-templates\/([\w.-]+)/g;function Gc(e){let t=new Set;for(let n of b(e)){let r=v(n.path,F);if(C(r)){for(let s of Rc(r))if(!(!s.startsWith("Dockerfile")||s.endsWith(".dockerignore")))for(let o of ae(v(r,s),"utf-8").matchAll(Kc))t.add(o[1])}}return[...t]}function Wc(){let e=m()??process.cwd(),t=[];C(v(e,D))||t.push(`${D} (workspace root manifest)`);let n=v(e,"shared-platform-engineering","docker-templates"),r=[];try{r=Gc(e)}catch{}for(let s of new Set([...Vc,...r]))C(v(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:
300
+ `)}`,fix:"Update Docker Desktop, or on Linux update docker-ce and the docker-compose-plugin package"}}async function hr(e=M){let t;try{t=String(await e("tilt version",U)).trim()}catch{return{name:"Tilt CLI",didPass:!1,message:"Tilt CLI not found",fix:X.tiltMissing}}return Xe(t,sr)?{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${sr.join(".")} floor`,fix:`Install Tilt v${sr.join(".")} or newer: https://docs.tilt.dev/install.html`}}async function Fc(e=M){let t;try{t=String(await e("docker info --format '{{.OSType}}'",U)).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 Mc(e=M){let t=m();if(!t)return{name:"Bun",didPass:!0,isSkipped:!0,message:"Not in a project - skipping Bun check"};if(!Ae(b(t)))return{name:"Bun",didPass:!0,isSkipped:!0,message:"No generated JS services - skipping Bun check"};try{let r=String(await e("bun --version",U)).trim();return Xe(r,Z)?{name:"Bun",didPass:!0,message:`Bun ${r} is available`}:{name:"Bun",didPass:!1,message:`Bun ${r||"version unknown"} is below the required ${Z.join(".")} floor`,fix:`Install Bun ${Z.join(".")} or newer: https://bun.sh/install`}}catch{return{name:"Bun",didPass:!1,message:"Bun is not available",fix:X.bunMissing}}}function Lc(){let e=m()??process.cwd(),t=Rs(e);if(t.missing.length>0)return{name:"Environment Variables",didPass:!1,message:`Missing required env variables: ${t.missing.join(", ")}`,fix:C(v(e,".env"))?`Edit .env and set these values:
301
+ ${t.missing.map(n=>`${n}=<value>`).join(`
302
+ `)}`:"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 r=t.warnings.filter(n=>!n.startsWith(".env file not found"));return{name:"Environment Variables",didPass:!0,message:r.length>0?`All required environment variables are set (warning: ${r.join("; ")})`:"All required environment variables are set"}}function Bc(){let e=m()??process.cwd(),t=v(e,".tdk",".tdk-out"),r=at.filter(n=>!C(v(t,n)));return r.length===0?{name:"Master Configs",didPass:!0,message:`${at.join(", ")} found`}:{name:"Master Configs",didPass:!1,message:`Master configs missing: ${r.join(", ")}`,fix:"Run: tdk project"}}function Uc(e=zr()){let t=m();if(!t)return{name:"TDK version",didPass:!0,isSkipped:!0,message:"Not in a project - skipping TDK version check"};let r=Ms(t,e);return r.status==="none"?{name:"TDK version",didPass:!0,isSkipped:!0,message:`tdk ${e} (no minTdkVersion in .tdk/project.json)`}:r.status==="malformed"||r.status==="too-old"?{name:"TDK version",didPass:!1,message:r.message,fix:r.fix}:{name:"TDK version",didPass:!0,message:`tdk ${e} meets minTdkVersion ${r.required}`}}function Hc(){let e=m()??process.cwd(),t=lt(e),r=b(e).filter(s=>!De(e,s.path,t));if(r.length===0)return{name:"Resource Discovery",didPass:!0,message:`All resources are covered by discovery.paths ${JSON.stringify(t)}`};let n=r.map(s=>ir(ar(e,s.path))).join(", ");return{name:"Resource Discovery",didPass:!1,message:`${S(r.length,"resource")} outside discovery.paths ${JSON.stringify(t)}: ${n}. \`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 Vc=["install-deps.sh","bun-hoisted-symlink-fix.sh","prisma-bun-client-link-fix.sh","prisma-normalize-client.sh","infisical-entrypoint.sh"],Kc=/shared-platform-engineering\/docker-templates\/([\w.-]+)/g;function Gc(e){let t=new Set;for(let r of b(e)){let n=v(r.path,F);if(C(n)){for(let s of Rc(n))if(!(!s.startsWith("Dockerfile")||s.endsWith(".dockerignore")))for(let o of ae(v(n,s),"utf-8").matchAll(Kc))t.add(o[1])}}return[...t]}function Wc(){let e=m()??process.cwd(),t=[];C(v(e,D))||t.push(`${D} (workspace root manifest)`);let r=v(e,"shared-platform-engineering","docker-templates"),n=[];try{n=Gc(e)}catch{}for(let s of new Set([...Vc,...n]))C(v(r,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:
303
303
  ${t.join(`
304
- `)}`,fix:"Run `tdk project --yes` (or `tdk config regenerate`) with an updated TDK. `tdk up` also refreshes these assets before starting Tilt."}}function Jc(){let e=m()??process.cwd(),t=b(e),n=[];for(let r of t){let s=v(r.path,D);if(!C(s))continue;let o=r.config?.appType??"backend",i=ct[o]??ct.backend,a;try{a=JSON.parse(ae(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:
305
- ${n.join(`
304
+ `)}`,fix:"Run `tdk project --yes` (or `tdk config regenerate`) with an updated TDK. `tdk up` also refreshes these assets before starting Tilt."}}function Jc(){let e=m()??process.cwd(),t=b(e),r=[];for(let n of t){let s=v(n.path,D);if(!C(s))continue;let o=n.config?.appType??"backend",i=ct[o]??ct.backend,a;try{a=JSON.parse(ae(s,"utf-8")).scripts??{}}catch{r.push(`${n.name} (package.json is invalid JSON)`);continue}let c=i.filter(u=>!a[u]);c.length>0&&r.push(`${n.name}: missing "${c.join('", "')}"`)}return r.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:
305
+ ${r.join(`
306
306
  `)}`,fix:`Add the missing scripts to each service's package.json, e.g.:
307
307
  "dev": "bun run src/index.ts",
308
308
  "build": "tsc",
309
- "start": "bun run dist/index.js"`}}function Ks(e){if(e.startsWith("@"))return[e.split("/").slice(0,2).join("/")];let t=e.split("/")[0]??e;return[`@types/${t}`,t]}function Gs(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(Gs(e,s[1],n+1))return!0;return!1}function Hs(e){let t=Ks(e);return e.includes("/")||e.startsWith("@")?t[t.length-1]:t[0]}var qc={"@types/bun":"^1.4.2","@types/node":"^20.0.0"};function zc(e,t){return(t.includes("bun")||e.has("@types/bun"))&&!e.has("@types/node")}function Yc(){let e=m()??process.cwd(),t=b(e),n=[],r=new Set;for(let o of t){let i=v(o.path,D),a=v(o.path,F,"tsconfig.docker.autogenerated.json");if(!C(i)||!C(a))continue;let d=ln(a)?.compilerOptions?.types;if(!Array.isArray(d))continue;let l=ln(i),g=l?.scripts??{};if(!Gs(g,"build"))continue;let k=new Set([...Object.keys(l?.devDependencies??{}),...Object.keys(l?.dependencies??{})]),h=d.filter(p=>typeof p=="string").filter(p=>!Ks(p).some(y=>k.has(y)));for(let p of h)r.add(Hs(p));if(h.length>0){let p=h.map(y=>`"${y}" (needs ${Hs(y)})`).join(", ");n.push(`${o.name}: "types" lists ${p}`)}zc(k,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=qc[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:
310
- ${n.join(`
311
- `)}`,fix:`Add to each service's package.json devDependencies: ${s.join(", ")}`}}function ln(e){try{return JSON.parse(ae(e,"utf-8"))}catch{return null}}function Xc(e){let n=ln(e)?.compilerOptions;return n?.allowSyntheticDefaultImports===!0||n?.esModuleInterop===!0}function Zc(){let e=m()??process.cwd(),t=b(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){C(v(r.path,"public"))||n.push(`${r.name}: no public/ folder, but the Docker build copies it. Create it: mkdir -p ${an(cn(e,v(r.path,"public")))} && touch ${an(cn(e,v(r.path,"public",".gitkeep")))}`);let s=v(r.path,F,"Dockerfile.app.autogenerated"),o=v(r.path,F,"tsconfig.docker.autogenerated.json");if(C(s)){let i=ae(s,"utf-8"),a=/\bEXPOSE\s+80\b/.test(i),c=r.config?.stack,u=c?v(e,"services",c,F,"docker-compose.app.autogenerated.yml"):"";if(a&&u&&C(u)){let d=ae(u,"utf-8"),l=r.name.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),g=new RegExp(`traefik\\.http\\.services\\.${l}\\.loadbalancer\\.server\\.port=(\\d+)`),h=d.match(g)?.[1];h&&h!=="80"&&n.push(`${r.name}: nginx runtime exposes 80, but generated Traefik routes to ${h}`)}}if(C(o)&&!Xc(o)){let i=v(r.path,"src","main.tsx");if(C(i)){let a=ae(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:`${S(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:
312
- ${n.join(`
309
+ "start": "bun run dist/index.js"`}}function Ks(e){if(e.startsWith("@"))return[e.split("/").slice(0,2).join("/")];let t=e.split("/")[0]??e;return[`@types/${t}`,t]}function Gs(e,t,r=0){let n=e[t];if(typeof n!="string"||r>3)return!1;if(/(^|[\s;&|(])tsc(\s|$)/.test(n))return!0;for(let s of n.matchAll(/\b(?:bun|npm|pnpm|yarn)\s+run\s+([\w:.-]+)/g))if(Gs(e,s[1],r+1))return!0;return!1}function Vs(e){let t=Ks(e);return e.includes("/")||e.startsWith("@")?t[t.length-1]:t[0]}var qc={"@types/bun":"^1.4.2","@types/node":"^20.0.0"};function zc(e,t){return(t.includes("bun")||e.has("@types/bun"))&&!e.has("@types/node")}function Yc(){let e=m()??process.cwd(),t=b(e),r=[],n=new Set;for(let o of t){let i=v(o.path,D),a=v(o.path,F,"tsconfig.docker.autogenerated.json");if(!C(i)||!C(a))continue;let d=dr(a)?.compilerOptions?.types;if(!Array.isArray(d))continue;let l=dr(i),g=l?.scripts??{};if(!Gs(g,"build"))continue;let k=new Set([...Object.keys(l?.devDependencies??{}),...Object.keys(l?.dependencies??{})]),h=d.filter(p=>typeof p=="string").filter(p=>!Ks(p).some(y=>k.has(y)));for(let p of h)n.add(Vs(p));if(h.length>0){let p=h.map(y=>`"${y}" (needs ${Vs(y)})`).join(", ");r.push(`${o.name}: "types" lists ${p}`)}zc(k,d)&&(n.add("@types/node"),r.push(`${o.name}: uses @types/bun, which references node types internally, but @types/node is not a direct dependency`))}if(r.length===0)return{name:"TypeScript Type Dependencies",didPass:!0,message:`Every service's Docker tsconfig "types" entry has its @types package installed`};let s=[...n].map(o=>{let i=qc[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:
310
+ ${r.join(`
311
+ `)}`,fix:`Add to each service's package.json devDependencies: ${s.join(", ")}`}}function dr(e){try{return JSON.parse(ae(e,"utf-8"))}catch{return null}}function Xc(e){let r=dr(e)?.compilerOptions;return r?.allowSyntheticDefaultImports===!0||r?.esModuleInterop===!0}function Zc(){let e=m()??process.cwd(),t=b(e).filter(n=>n.config?.appType==="frontend");if(t.length===0)return{name:"Frontend Docker Preflight",didPass:!0,isSkipped:!0,message:"No frontend services to check"};let r=[];for(let n of t){C(v(n.path,"public"))||r.push(`${n.name}: no public/ folder, but the Docker build copies it. Create it: mkdir -p ${ir(ar(e,v(n.path,"public")))} && touch ${ir(ar(e,v(n.path,"public",".gitkeep")))}`);let s=v(n.path,F,"Dockerfile.app.autogenerated"),o=v(n.path,F,"tsconfig.docker.autogenerated.json");if(C(s)){let i=ae(s,"utf-8"),a=/\bEXPOSE\s+80\b/.test(i),c=n.config?.stack,u=c?v(e,"services",c,F,"docker-compose.app.autogenerated.yml"):"";if(a&&u&&C(u)){let d=ae(u,"utf-8"),l=n.name.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),g=new RegExp(`traefik\\.http\\.services\\.${l}\\.loadbalancer\\.server\\.port=(\\d+)`),h=d.match(g)?.[1];h&&h!=="80"&&r.push(`${n.name}: nginx runtime exposes 80, but generated Traefik routes to ${h}`)}}if(C(o)&&!Xc(o)){let i=v(n.path,"src","main.tsx");if(C(i)){let a=ae(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&&r.push(`${n.name}: Docker tsconfig does not allow synthetic default imports, but src/main.tsx default-imports ${c.join(" and ")}`)}}}return r.length===0?{name:"Frontend Docker Preflight",didPass:!0,message:`${S(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:
312
+ ${r.join(`
313
313
  `)}`,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 Qc=90,eu=80;function tu(e){return e.split(`
314
- `).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 nu(){let e;try{e=$c($("docker")??"docker",["stats","--no-stream","--format","{{.Name}},{{.MemPerc}},{{.CPUPerc}}"],{stdio:"pipe",encoding:"utf-8",timeout:V,windowsHide:process.platform==="win32"})}catch(s){return{name:"Container Resource Health",didPass:!0,isSkipped:!0,message:Vs(s)?"Docker not responding - skipped container resource check":"Docker not running - skipped container resource check"}}let t=tu(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>=Qc&&s.cpuPct>=eu);if(n.length===0)return{name:"Container Resource Health",didPass:!0,message:`${S(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(`
315
- `);return{name:"Container Resource Health",didPass:!1,message:`${S(n.length,"container")} pinned near its memory limit while burning CPU -- likely stuck in a boot-time retry/fetch loop, not a normal crash:
316
- ${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 ru=5e3;async function su(e,t){let n=m()??process.cwd(),r=kt(b(n),t);return r.length===0?{name:"Service Health",didPass:!0,isSkipped:!0,message:"No routable services to ping"}:Ft(await Ie(r,e))}async function ou(e,t){let n=m()??process.cwd(),r=b(n),s=gr(hr(r,t),{timeoutSeconds:Math.ceil(e/1e3)});return s.length===0?Mt([]):(await Ie(kt(r,t),e)).some(i=>i.status!==void 0)?Mt(await Sr(s)):{name:"Service Smoke",didPass:!0,isSkipped:!0,message:"No services responded - skipped smoke checks"}}async function iu(e,t){let n=m()??process.cwd(),r=b(n),s=Yn(r,t);return s.length===0?{name:"Advertised Endpoints",didPass:!0,isSkipped:!0,message:"No routable services to check"}:Mr(await Ie(s,e))}var au=new _c("doctor").description("Check environment readiness for TDK").option("--json","Output a versioned JSON readiness report",!1).exitOverride(e=>{e.exitCode===0&&process.exit(0),au.opts().json&&console.log(JSON.stringify(Y([],!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("--ping-timeout <ms>","Per-service ping timeout in milliseconds",String(ru)).action(async e=>{let t=Number(e.pingTimeout);if(!/^\d+$/.test(e.pingTimeout)||!Number.isSafeInteger(t)||t<=0){let p="--ping-timeout must be a positive integer number of milliseconds";e.json&&console.log(JSON.stringify(Y([],!1,[{code:"USAGE",message:p}]))),console.error(p),process.exit(2);return}e.json||console.log("TDK doctor checks your local Docker + Tilt development environment; it does not check cluster deployments.");let n=On();if(process.platform==="win32"){if(e.json){let p=null;try{p=await ie()}catch{}console.log(JSON.stringify(Y([{name:"Native Windows support",didPass:!1,message:Bs,fix:"Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md"}],!!m(),[],p,{...n,canUp:!1})))}console.error(Bs),process.exit(1);return}if(n.kind==="webcontainer"){let p=Y([{name:"Host",didPass:!1,message:it,fix:`Use a machine with Docker. Guide: ${Oe}`}],!!m(),[],void 0,n);e.json&&console.log(JSON.stringify(p)),console.error(it),process.exit(1);return}e.json||(console.log(`
314
+ `).map(t=>t.trim()).filter(Boolean).map(t=>{let[r,n,s]=t.split(",");return{name:r??"unknown",memPct:Number.parseFloat((n??"").replace(/%/g,"")),cpuPct:Number.parseFloat((s??"").replace(/%/g,""))}}).filter(t=>Number.isFinite(t.memPct)&&Number.isFinite(t.cpuPct))}function ru(){let e;try{e=$c($("docker")??"docker",["stats","--no-stream","--format","{{.Name}},{{.MemPerc}},{{.CPUPerc}}"],{stdio:"pipe",encoding:"utf-8",timeout:U,windowsHide:process.platform==="win32"})}catch(s){return{name:"Container Resource Health",didPass:!0,isSkipped:!0,message:lr(s)?"Docker not responding - skipped container resource check":"Docker not running - skipped container resource check"}}let t=tu(e);if(t.length===0)return{name:"Container Resource Health",didPass:!0,isSkipped:!0,message:"No running containers to check"};let r=t.filter(s=>s.memPct>=Qc&&s.cpuPct>=eu);if(r.length===0)return{name:"Container Resource Health",didPass:!0,message:`${S(t.length,"container")} within normal resource usage`};let n=r.map(s=>`${s.name} (mem ${s.memPct.toFixed(0)}%, cpu ${s.cpuPct.toFixed(0)}%)`).join(`
315
+ `);return{name:"Container Resource Health",didPass:!1,message:`${S(r.length,"container")} pinned near its memory limit while burning CPU -- likely stuck in a boot-time retry/fetch loop, not a normal crash:
316
+ ${n}`,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 nu=5e3;async function su(e,t){let r=m()??process.cwd(),n=kt(b(r),t);return n.length===0?{name:"Service Health",didPass:!0,isSkipped:!0,message:"No routable services to ping"}:Ft(await Ie(n,e))}async function ou(e,t){let r=m()??process.cwd(),n=b(r),s=kn(gn(n,t),{timeoutSeconds:Math.ceil(e/1e3)});return s.length===0?Mt([]):(await Ie(kt(n,t),e)).some(i=>i.status!==void 0)?Mt(await bn(s)):{name:"Service Smoke",didPass:!0,isSkipped:!0,message:"No services responded - skipped smoke checks"}}async function iu(e,t){let r=m()??process.cwd(),n=b(r),s=Yr(n,t);return s.length===0?{name:"Advertised Endpoints",didPass:!0,isSkipped:!0,message:"No routable services to check"}:Ln(await Ie(s,e))}var au=new _c("doctor").description("Check environment readiness for TDK").option("--json","Output a versioned JSON readiness report",!1).exitOverride(e=>{e.exitCode===0&&process.exit(0),au.opts().json&&console.log(JSON.stringify(Y([],!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("--ping-timeout <ms>","Per-service ping timeout in milliseconds",String(nu)).action(async e=>{let t=Number(e.pingTimeout);if(!/^\d+$/.test(e.pingTimeout)||!Number.isSafeInteger(t)||t<=0){let p="--ping-timeout must be a positive integer number of milliseconds";e.json&&console.log(JSON.stringify(Y([],!1,[{code:"USAGE",message:p}]))),console.error(p),process.exit(2);return}e.json||console.log("TDK doctor checks your local Docker + Tilt development environment; it does not check cluster deployments.");let r=Or();if(process.platform==="win32"){if(e.json){let p=null;try{p=await ie()}catch{}console.log(JSON.stringify(Y([{name:"Native Windows support",didPass:!1,message:Us,fix:"Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md"}],!!m(),[],p,{...r,canUp:!1})))}console.error(Us),process.exit(1);return}if(r.kind==="webcontainer"){let p=Y([{name:"Host",didPass:!1,message:it,fix:`Use a machine with Docker. Guide: ${Oe}`}],!!m(),[],void 0,r);e.json&&console.log(JSON.stringify(p)),console.error(it),process.exit(1);return}e.json||(console.log(`
317
317
  ${f.bold("\u{1F50D} TDK Doctor")}
318
318
  `),console.log(`Checking environment...
319
- `));let r=m(),s,o;try{s=await qe(r??process.cwd())}catch(p){s=null,o=p instanceof Error?p.message:String(p)}let i=[()=>s?{name:"Host Ports",didPass:!0,message:`HTTP ${s.ingressHttp}, HTTPS ${s.ingressHttps}, Postgres ${s.postgres}`}:{name:"Host Ports",didPass:!1,message:o??"Could not select host ports",fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."},()=>s?It(Ms,void 0,[s.ingressHttp,s.ingressHttps]):{name:"Ingress Ports",didPass:!1,message:"Ingress port plan is unavailable"},pn,()=>Un(),Fc,hn,fn,mn,Mc,()=>Oc(m()??process.cwd(),e.strict),()=>Dc(process.env,e.strict),()=>Ss()],a=[()=>Uc(),Bc,Wc,Vr,Jc,()=>Br(),Yc,Zc,Hc,()=>cs(),()=>Ke(),()=>en(),()=>tn(),()=>nn(),()=>rn(void 0,e.strict),()=>us(),()=>ds(),()=>fs(),()=>ps(),()=>We(),()=>is(),()=>ks(),()=>gs(),()=>ys(),Lc,async()=>{let p=m()??process.cwd(),y=Nt(p)?await kn(p):!0;return jt(Ms,p,void 0,y)},nu,Lt];if(e.ping){let p=r?Cs(r,s?.ingressHttp):s?.ingressHttp;a.push(()=>su(t,p)),a.push(()=>ou(t,p)),a.push(()=>iu(t,p))}let c=!!r,{checks:u,errors:d}=await Kn(i,c?a:[]);if(An(n.kind))for(let p of u)p.name===A&&!p.didPass&&(p.fix=_n);let l=Y(Us(u),c,d,s,n),g=Gn(l),k=l.data.ready;if(e.json){let p;try{p=Ns(m()??process.cwd())}catch(y){if(!(y instanceof we))throw y;console.log(JSON.stringify(Y([],c,[...d,{code:"ENV_UNREADABLE",message:y.message}]))),console.error(y.message),process.exit(1)}console.log(JSON.stringify(ze(l,p)));for(let y of d)console.error(Qt(y.message,p));g!==0&&process.exit(g);return}for(let p of d)console.error(`${f.red("\u2717")} Doctor check failed: ${p.message}`);for(let p of Us(u))!p.didPass&&!p.isSkipped&&!p.isWarning?(console.log(`${f.red("\u2717")} ${p.message}`),p.fix&&console.log(`${f.blue("\u2139")} Fix: ${p.fix}`)):p.isWarning?(console.log(`${f.yellow("\u26A0")} ${f.yellow(p.message)}`),p.fix&&console.log(`${f.blue("\u2139")} Fix: ${p.fix}`)):p.isSkipped?(console.log(`${f.gray("\u25CB")} ${f.gray(p.message)}`),p.fix&&console.log(`${f.blue("\u2139")} ${p.fix}`)):console.log(`${f.green("\u2713")} ${p.message}`);console.log(""),k&&!c&&(console.log(`${f.gray("\u25CB")} ${f.gray("Not in a TDK project, so project checks were skipped")}`),console.log(""));let h=Cc(c,k);console.log(`${k?f.green(f.bold("\u2713")):f.red(f.bold("\u2717"))} ${h}`),g!==0&&process.exit(g)});function Ws(e){return Xe(e,Z)}var Ze=`${Z[0]}.${Z[1]}+`;function du(e,t){return{id:e,ok:t.didPass||!!t.isSkipped,message:t.message,fix:t.fix}}function qs(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 Qe(e,t,n){try{return du(e,await t())}catch{return{id:e,ok:!1,message:n}}}function lu(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 pu(e){try{return b(e).some(t=>t.config?.featuresEnabled?.includes("prisma")??!1)}catch{return!1}}async function fu(e={}){let t=e.cwd??process.cwd(),n=m(t),r=!!n,s=[],o=process.versions.node;s.push({id:"node",ok:!qs(o),message:o,fix:qs(o)?`Install Node.js 22.12+ (current: ${o}). https://nodejs.org`:void 0}),s.push(await Qe("docker",pn,"Docker daemon is not running")),s.push(await Qe("compose",async()=>{let[h,p]=await Promise.all([fn(),mn()]);return h.didPass?lu(p):h},"Docker Engine or Compose version check failed")),s.push(await Qe("tilt",hn,"Tilt CLI not found"));let i=n?Ae(b(n)):!0,a=!1,c=i?$("bun"):void 0;if(c)try{let h=Js(c,["--version"],{encoding:"utf-8",timeout:3e3}).trim();a=Ws(h)}catch{}s.push(i?{id:"bun",ok:a,message:a?`Bun ${Ze} is available on PATH`:`Bun ${Ze} 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 h=await qe(n??t);s.push({id:"ports",ok:!0,message:`HTTP ${h.ingressHttp}, HTTPS ${h.ingressHttps}, Postgres ${h.postgres}`})}catch(h){s.push({id:"ports",ok:!1,message:h instanceof Error?h.message:String(h),fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."})}if(n){let h=await Qe("nats",()=>We(n),"NATS broker check failed");if(h.ok||s.push(h),pu(n)){let p=!1;try{let y=JSON.parse(cu(uu(n,".tdk",P),"utf-8")),E=String(y?.project?.name??"").replace(/-/g,"_");E&&(p=Js($("docker")??"docker",["ps","--filter",`label=com.docker.compose.project=${E}`,"--filter","label=com.docker.compose.service=postgres","--filter","health=healthy","--format","{{.Names}}"],{encoding:"utf-8",timeout:3e3}).trim().length>0)}catch{}p||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(h=>!h.ok).slice(0,8),d=u.some(h=>["node","docker","compose","tilt","bun","ports"].includes(h.id)),l=u.some(h=>h.id==="bun"),g=u.length?d?l?`Cold start blocked. Bun ${Ze} must be installed on PATH.
320
- 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.":"",k=u.length?"":r?"Environment ready for TDK":`This machine is ready for TDK.
321
- Next: tdk project --yes`;return{ok:u.length===0,inProject:r,items:u,header:g,footer:k}}function mu(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(`
322
- `)}async function $m(){let e=await fu();e.items.some(n=>["node","docker","compose","tilt","bun","ports"].includes(n.id))&&(console.error(mu(e)),process.exit(1))}export{f as a,Jn as b,B as c,U as d,Nu as e,Dn as f,he as g,F as h,ho as i,go as j,P as k,D as l,at as m,ju as n,Iu as o,Cn as p,Fu as q,bs as r,Ht as s,w as t,m as u,zn as v,ht as w,Ho as x,gt as y,hr as z,pl as A,Sr as B,ke as C,gl as D,Pt as E,kl as F,yl as G,Zn as H,Fe as I,Od as J,Ad as K,$ as L,si as M,rr as N,oi as O,Wd as P,Jd as Q,or as R,tl as S,R as T,H as U,nl as V,ai as W,rl as X,sl as Y,ol as Z,S as _,Yu as $,Xu as aa,Zu as ba,Qu as ca,ed as da,td as ea,nd as fa,rd as ga,sd as ha,mt as ia,od as ja,id as ka,ad as la,cd as ma,ud as na,dd as oa,ld as pa,pd as qa,xr as ra,wi as sa,$i as ta,xl as ua,Pl as va,vl as wa,El as xa,wl as ya,vt as za,Ml as Aa,$r as Ba,Ci as Ca,b as Da,Se as Ea,Ll as Fa,Bl as Ga,Ul as Ha,Hl as Ia,Vl as Ja,Kl as Ka,ji as La,Gl as Ma,lp as Na,Tp as Oa,Zr as Pa,Vt as Qa,is as Ra,it as Sa,_n as Ta,On as Ua,An as Va,lt as Wa,De as Xa,Hu as Ya,Rr as Za,Or as _a,Vi as $a,Ki as ab,Ct as bb,$s as cb,tf as db,nf as eb,ie as fb,uf as gb,Ds as hb,gf as ib,kf as jb,qe as kb,we as lb,Ns as mb,Qt as nb,ze as ob,Of as pb,Af as qb,Fs as rb,au as sb,qs as tb,lu as ub,fu as vb,mu as wb,$m as xb};
319
+ `));let n=m(),s,o;try{s=await qe(n??process.cwd())}catch(p){s=null,o=p instanceof Error?p.message:String(p)}let i=[()=>s?{name:"Host Ports",didPass:!0,message:`HTTP ${s.ingressHttp}, HTTPS ${s.ingressHttps}, Postgres ${s.postgres}`}:{name:"Host Ports",didPass:!1,message:o??"Could not select host ports",fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."},()=>s?It(Ls,void 0,[s.ingressHttp,s.ingressHttps]):{name:"Ingress Ports",didPass:!1,message:"Ingress port plan is unavailable"},pr,()=>Ur(),Fc,hr,fr,mr,Mc,()=>Oc(m()??process.cwd(),e.strict),()=>Dc(process.env,e.strict),()=>bs()],a=[()=>Uc(),Bc,Wc,Kn,Jc,()=>Un(),Yc,Zc,Hc,()=>us(),()=>Ke(),()=>er(),()=>tr(),()=>rr(),()=>nr(void 0,e.strict),()=>ds(),()=>ls(),()=>ms(),()=>fs(),()=>We(),()=>as(),()=>ys(),()=>ks(),()=>Ss(),Lc,async()=>{let p=m()??process.cwd(),y=Nt(p)?await kr(p):!0;return jt(Ls,p,void 0,y)},ru,Lt];if(e.ping){let p=n?Ns(n,s?.ingressHttp):s?.ingressHttp;a.push(()=>su(t,p)),a.push(()=>ou(t,p)),a.push(()=>iu(t,p))}let c=!!n,{checks:u,errors:d}=await Kr(i,c?a:[]);if(Ar(r.kind))for(let p of u)p.name===A&&!p.didPass&&(p.fix=_r);let l=Y(Hs(u),c,d,s,r),g=Gr(l),k=l.data.ready;if(e.json){let p;try{p=js(m()??process.cwd())}catch(y){if(!(y instanceof we))throw y;console.log(JSON.stringify(Y([],c,[...d,{code:"ENV_UNREADABLE",message:y.message}]))),console.error(y.message),process.exit(1)}console.log(JSON.stringify(ze(l,p)));for(let y of d)console.error(Qt(y.message,p));g!==0&&process.exit(g);return}for(let p of d)console.error(`${f.red("\u2717")} Doctor check failed: ${p.message}`);for(let p of Hs(u))!p.didPass&&!p.isSkipped&&!p.isWarning?(console.log(`${f.red("\u2717")} ${p.message}`),p.fix&&console.log(`${f.blue("\u2139")} Fix: ${p.fix}`)):p.isWarning?(console.log(`${f.yellow("\u26A0")} ${f.yellow(p.message)}`),p.fix&&console.log(`${f.blue("\u2139")} Fix: ${p.fix}`)):p.isSkipped?(console.log(`${f.gray("\u25CB")} ${f.gray(p.message)}`),p.fix&&console.log(`${f.blue("\u2139")} ${p.fix}`)):console.log(`${f.green("\u2713")} ${p.message}`);console.log(""),k&&!c&&(console.log(`${f.gray("\u25CB")} ${f.gray("Not in a TDK project, so project checks were skipped")}`),console.log(""));let h=Cc(c,k);console.log(`${k?f.green(f.bold("\u2713")):f.red(f.bold("\u2717"))} ${h}`),g!==0&&process.exit(g)});function Ws(e){return Xe(e,Z)}var Ze=`${Z[0]}.${Z[1]}+`;function du(e,t){return{id:e,ok:t.didPass||!!t.isSkipped,message:t.message,fix:t.fix}}function qs(e){let[t=0,r=0]=String(e).split(".").map(n=>Number.parseInt(n,10));return!Number.isFinite(t)||!Number.isFinite(r)||t<22||t===22&&r<12}async function Qe(e,t,r){try{return du(e,await t())}catch{return{id:e,ok:!1,message:r}}}function lu(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 pu(e){try{return b(e).some(t=>t.config?.featuresEnabled?.includes("prisma")??!1)}catch{return!1}}async function fu(e={}){let t=e.cwd??process.cwd(),r=m(t),n=!!r,s=[],o=process.versions.node;s.push({id:"node",ok:!qs(o),message:o,fix:qs(o)?`Install Node.js 22.12+ (current: ${o}). https://nodejs.org`:void 0}),s.push(await Qe("docker",pr,"Docker daemon is not running")),s.push(await Qe("compose",async()=>{let[h,p]=await Promise.all([fr(),mr()]);return h.didPass?lu(p):h},"Docker Engine or Compose version check failed")),s.push(await Qe("tilt",hr,"Tilt CLI not found"));let i=r?Ae(b(r)):!0,a=!1,c=i?$("bun"):void 0;if(c)try{let h=Js(c,["--version"],{encoding:"utf-8",timeout:3e3}).trim();a=Ws(h)}catch{}s.push(i?{id:"bun",ok:a,message:a?`Bun ${Ze} is available on PATH`:`Bun ${Ze} 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 h=await qe(r??t);s.push({id:"ports",ok:!0,message:`HTTP ${h.ingressHttp}, HTTPS ${h.ingressHttps}, Postgres ${h.postgres}`})}catch(h){s.push({id:"ports",ok:!1,message:h instanceof Error?h.message:String(h),fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."})}if(r){let h=await Qe("nats",()=>We(r),"NATS broker check failed");if(h.ok||s.push(h),pu(r)){let p=!1;try{let y=JSON.parse(cu(uu(r,".tdk",P),"utf-8")),E=String(y?.project?.name??"").replace(/-/g,"_");E&&(p=Js($("docker")??"docker",["ps","--filter",`label=com.docker.compose.project=${E}`,"--filter","label=com.docker.compose.service=postgres","--filter","health=healthy","--format","{{.Names}}"],{encoding:"utf-8",timeout:3e3}).trim().length>0)}catch{}p||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(h=>!h.ok).slice(0,8),d=u.some(h=>["node","docker","compose","tilt","bun","ports"].includes(h.id)),l=u.some(h=>h.id==="bun"),g=u.length?d?l?`Cold start blocked. Bun ${Ze} must be installed on PATH.
320
+ 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.":"",k=u.length?"":n?"Environment ready for TDK":`This machine is ready for TDK.
321
+ Next: tdk project --yes`;return{ok:u.length===0,inProject:n,items:u,header:g,footer:k}}function mu(e,t={}){let r=[e.header];for(let n of e.items)r.push(`FAIL ${n.id.padEnd(7)} ${n.message}`),n.fix&&r.push(` ${n.fix}`);return e.footer&&(t.includeSuccessFooter??!0)&&r.push(e.footer),r.filter(Boolean).join(`
322
+ `)}async function $m(){let e=await fu();e.items.some(r=>["node","docker","compose","tilt","bun","ports"].includes(r.id))&&(console.error(mu(e)),process.exit(1))}export{f as a,Jr as b,B as c,H as d,Nu as e,Dr as f,he as g,F as h,ho as i,go as j,P as k,D as l,at as m,ju as n,Iu as o,Cr as p,Fu as q,Ts as r,Ht as s,w as t,m as u,zr as v,ht as w,Ho as x,gt as y,gn as z,pl as A,bn as B,ke as C,gl as D,Pt as E,kl as F,yl as G,Zr as H,Fe as I,Od as J,Ad as K,$ as L,si as M,nn as N,oi as O,Wd as P,Jd as Q,on as R,tl as S,R as T,V as U,rl as V,ai as W,nl as X,sl as Y,ol as Z,S as _,Yu as $,Xu as aa,Zu as ba,Qu as ca,ed as da,td as ea,rd as fa,nd as ga,sd as ha,mt as ia,od as ja,id as ka,ad as la,cd as ma,ud as na,dd as oa,ld as pa,pd as qa,Pn as ra,wi as sa,$i as ta,xl as ua,Pl as va,vl as wa,El as xa,wl as ya,vt as za,Ml as Aa,Rn as Ba,Ci as Ca,b as Da,Se as Ea,Ll as Fa,Bl as Ga,Ul as Ha,Hl as Ia,Vl as Ja,Kl as Ka,ji as La,Gl as Ma,lp as Na,Tp as Oa,Qn as Pa,Vt as Qa,as as Ra,it as Sa,_r as Ta,Or as Ua,Ar as Va,lt as Wa,De as Xa,Hu as Ya,_n as Za,An as _a,Vi as $a,Ki as ab,Ct as bb,Rs as cb,tf as db,rf as eb,ie as fb,uf as gb,Cs as hb,gf as ib,kf as jb,qe as kb,we as lb,js as mb,Qt as nb,ze as ob,Of as pb,Af as qb,Ms as rb,au as sb,qs as tb,lu as ub,fu as vb,mu as wb,$m as xb};