@flisk-sh/flisk 1.3.195 → 1.3.199
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +4 -4
- package/cli/dist/cli.js +56 -11
- package/cli/dist/commands/mcp.js +4 -1
- package/cli/dist/commands/open.js +35 -8
- package/cli/dist/commands/registry.js +1 -1
- package/cli/dist/commands/ui.js +1 -1
- package/cli/dist/commands/upgrade.js +2 -3
- package/cli/dist/mcp/tools.js +5 -2
- package/cli/dist/utils/cli-command.js +11 -2
- package/cli/dist/utils/doctor-fix.js +1 -1
- package/cli/dist/utils/one-command.js +112 -19
- package/cli/dist-bundle/{chunk-CXFHRZLM.js → chunk-3SPYAO2E.js} +1 -1
- package/cli/dist-bundle/chunk-6357RMGA.js +4 -0
- package/cli/dist-bundle/{chunk-32NCVCS7.js → chunk-7IWOM6M2.js} +1 -1
- package/cli/dist-bundle/chunk-CF46CD6R.js +6 -0
- package/cli/dist-bundle/chunk-DTIHDMED.js +5 -0
- package/cli/dist-bundle/chunk-GW7N23FV.js +21 -0
- package/cli/dist-bundle/{chunk-3RB2FQ46.js → chunk-HSNRMF4B.js} +9 -9
- package/cli/dist-bundle/{chunk-ZDH5BP3H.js → chunk-WMK2PS63.js} +2 -2
- package/cli/dist-bundle/cli.js +259 -265
- package/cli/dist-bundle/cold-preflight-WR2M53Z6.js +2 -0
- package/cli/dist-bundle/one-command-7OW747ML.js +4 -0
- package/cli/dist-bundle/open-635MSZHV.js +2 -0
- package/cli/dist-bundle/project-R7P6QBF4.js +2 -0
- package/cli/dist-bundle/spinner-YLB6FYQH.js +2 -0
- package/cli/package.json +1 -1
- package/package.json +1 -1
- package/cli/dist-bundle/chunk-DTJ6JCHV.js +0 -25
- package/cli/dist-bundle/chunk-TCN3L76U.js +0 -4
- package/cli/dist-bundle/cold-preflight-FSWLLA2X.js +0 -2
- package/cli/dist-bundle/one-command-A4R272U3.js +0 -4
- package/cli/dist-bundle/open-HXJVYBH7.js +0 -2
- package/cli/dist-bundle/project-5P6B5MAP.js +0 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
|
|
2
|
+
import{b as f}from"./chunk-CF46CD6R.js";var ar="Container Runtime",_="bring-your-own";var De="database-management",cr=".tiltignore",Ie="service.json",Q="docker-compose.yml",ur=".autogenerated",Ct="TILT_TECH_STACK.star",Dt="TILT_RESOURCE_DEFAULTS.star",B="project.json",je="package.json",fr=[Ct,Dt,"spec.master"],pr=["backend","frontend","library","sdk","worker","migrator","mcp","agent",_],lr={backend:["dev","build","start"],worker:["dev","build","start"],migrator:["dev","build","start"],mcp:["dev","build","start"],agent:["dev","build","start"],frontend:["dev","build"],library:["dev","build"],sdk:["dev","build"],[_]:[]};var Z=["monitoring","elk","debezium","golden_image","verdaccio"],dr={frontend:{base:3e3,min:3e3,max:3999,range:"3000-3999"},backend:{base:4e3,min:4e3,max:4999,range:"4000-4999"},mcp:{base:4e3,min:4e3,max:5999,range:"4000-5999"},agent:{base:4e3,min:4e3,max:5999,range:"4000-5999"},[_]:{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"}},mr={tiltUi:10350,traefik:8080},ee="https://flisk.sh/docs/quickstart/";var Ne=["node_modules",".git",".tilt",".tilt-engine","dist","build",".prisma",".turbo","coverage","tmp","temp","__tests__","test","tests",".github",".vscode","docs"],Pe=["Dockerfile",Q,"docker-compose.yaml","Tiltfile","vite.config.ts","tsconfig.json","tsconfig.build.json"],It={infra:"\u{1F3D7}\uFE0F",core:"\u{1F527}",api:"\u26A1",app:"\u{1F3A8}",orchestrator:"\u2699\uFE0F"};function hr(e){let t=e.toLowerCase();for(let[n,r]of Object.entries(It))if(t.includes(n))return r;return"\u{1F4E6}"}import{existsSync as Nt}from"node:fs";import{dirname as Pt,join as Ft,resolve as Ue}from"node:path";import{cwd as Ut}from"node:process";var Fe={name:"tdk-cli-internal",private:!0,version:"1.3.199",description:"Flisk CLI \u2014 start services on your machine.",keywords:["flisk","tilt","cli","local-dev","microservices"],homepage:"https://github.com/flisk-sh/flisk#readme",bugs:{url:"https://github.com/flisk-sh/flisk/issues"},repository:{type:"git",url:"git+https://github.com/flisk-sh/flisk.git",directory:"cli"},license:"MIT",author:"Flisk Team",type:"module",main:"./dist/index.js",types:"./dist/index.d.ts",bin:{flisk:"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","check:dist":"npm run build && ../scripts/check-cli-dist.sh",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","test:coverage":"vitest run --coverage --coverage.reportOnFailure --coverage.reporter=text --coverage.reporter=html --coverage.reporter=json-summary --coverage.reporter=json --coverage.reportsDirectory=coverage --reporter=default --reporter=json --outputFile.json=test-results/vitest.json",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","@vitest/coverage-v8":"^5.0.2",ajv:"^8.17.1",chalk:"^6.0.1",esbuild:"^0.28.2",ink:"^8.0.0",knip:"^6.38.0",react:"^19.3.0","react-devtools-core":"^8.0.0",typescript:"^7.0.2",vite:"^8.3.3",vitest:"^5.0.0"},engines:{node:">=22.12.0"}};function E(e=Ut()){let t=Ue(e),n=Ue("/");for(;t!==n;){if(Nt(Ft(t,".tdk",B)))return t;let r=Pt(t);if(r===t)break;t=r}return null}var V=null;function Mt(){if(V)return V;let e=Fe;if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Invalid package.json: expected object");let t=e;return V={name:String(t.name??"@flisk-sh/flisk"),version:String(t.version??"0.0.0"),fullPackage:t},V}function wr(){return Mt().version}import{existsSync as Me}from"node:fs";import{delimiter as Le,extname as Be,join as Ve}from"node:path";import{delimiter as br,extname as Lt}from"node:path";function U(){return process.platform==="win32"}function Bt(e){return e==="linux"?"linux":e==="darwin"?"darwin":e==="win32"?"windows":null}function Vt(e){return e==="x64"?"amd64":e==="arm64"?"arm64":null}function Gt(e,t){let n=Bt(e),r=Vt(t);if(!n||!r||n==="windows"&&r!=="amd64")return null;let o=`tdk-${n}-${r}`;return n==="windows"?`${o}.exe`:o}function Ar(){return Gt(process.platform,process.arch)}function Rr(){return U()?"tdk.exe":"flisk"}function te(e,t=U()){return t?Lt(e)?[e]:[e,`${e}.exe`,`${e}.cmd`,`${e}.bat`]:[e]}function G(e){let t=process.env.PATH??process.env.Path??"",n=U(),r=te(e,n);if(n&&!Be(e))for(let o of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let s=o.toLowerCase();s&&!r.includes(`${e}${s}`)&&r.push(`${e}${s}`)}for(let o of t.split(Le))if(o)for(let s of r){let i=Ve(o,s);if(Me(i))return i}return null}function Ir(e){let t=process.env.PATH??process.env.Path??"",n=U(),r=te(e,n);if(n&&!Be(e))for(let i of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let a=i.toLowerCase();a&&!r.includes(`${e}${a}`)&&r.push(`${e}${a}`)}let o=[],s=new Set;for(let i of t.split(Le))if(i)for(let a of r){let c=Ve(i,a);if(!Me(c))continue;let p=n?c.toLowerCase():c;s.has(p)||(s.add(p),o.push(c))}return o}import{execFileSync as Wt,execSync as Kt}from"node:child_process";var Ge=1e4;function We(){let e=!1;if(process.platform==="win32")try{return Wt(G("docker")??"docker",["ps"],{stdio:"ignore",timeout:Ge,windowsHide:!0}),"running"}catch(t){return t.code==="ETIMEDOUT"?"unresponsive":"missing"}for(let t of["docker ps","colima status","podman ps"])try{return Kt(t,{stdio:"ignore",timeout:Ge}),"running"}catch(n){n.code==="ETIMEDOUT"&&(e=!0)}return e?"unresponsive":"missing"}function W(e,t){return e[t]??0}function Ht(e,t){let n=Array.from({length:t.length+1},(r,o)=>o);for(let r=1;r<=e.length;r++){let o=[r];for(let s=1;s<=t.length;s++){let i=e[r-1]===t[s-1]?0:1;o[s]=Math.min(W(o,s-1)+1,W(n,s)+1,W(n,s-1)+i)}n=o}return W(n,t.length)}function zt(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 Ke(e,t){if(e.length<2||t.length===0||t.includes(e))return;let n=e.toLowerCase(),r,o=Number.POSITIVE_INFINITY;for(let s of t){if(s.length===0)continue;let i=s.toLowerCase(),a=zt(n,i)?1:Ht(n,i),c=Math.max(1,Math.min(2,Math.floor(Math.max(n.length,i.length)/3)));a>c||(a<o||a===o&&(r===void 0||s<r))&&(r=s,o=a)}return r}import{spawn as Jt}from"node:child_process";import{join as qt}from"node:path";function Yt(e,t=[],n={}){return new Promise((r,o)=>{let s=[e,...t];n.verbose&&console.log(`Executing: tilt ${s.join(" ")}`);let i=Jt(G("tilt")??"tilt",s,{stdio:n.inheritStdio?"inherit":"pipe",shell:!1,windowsHide:process.platform==="win32",timeout:n.timeoutMs}),a="",c="";n.inheritStdio||(i.stdout?.on("data",p=>{a+=p.toString()}),i.stderr?.on("data",p=>{c+=p.toString()})),i.on("close",p=>{r({exitCode:p??1,stdout:a,stderr:c})}),i.on("error",p=>{o(new Error(`Failed to spawn tilt: ${p.message}`))})})}async function He(){try{return(await Yt("version",[],{inheritStdio:!1,timeoutMs:1e4})).exitCode===0}catch{return!1}}function Xt(){let e=E();if(!e)throw $.notInProject();return qt(e,".tdk",".tdk-out","Tiltfile")}function ze(e){let t=Xt();e.push("-f",t)}function Wr(e,t={}){let n=[];return ze(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 Kr(e={}){let t=[];return ze(t),e.focusTargets&&e.focusTargets.length>0&&t.push("--",`--focus=${e.focusTargets.join(",")}`),t}function Je(e){return e instanceof Error?e.message:String(e)}function Zr(e,t){if(process.env.TDK_VERBOSE){let n=t!==void 0?`: ${Je(t)}`:"";console.warn(f.gray(`${e}${n}`))}}var S=class extends Error{suggestions;exitCode;constructor(t,n=[],r=1){super(t),this.name="TdkError",this.suggestions=n,this.exitCode=r}display(){oe(this.message,void 0,this.suggestions)}exit(){this.display(),process.exit(this.exitCode)}},re=class extends Error{code;constructor(t=1){super(`process.exit(${t})`),this.name="ProcessExitError",this.code=t}};function ne(e,t,n=!1){let r=new Set;for(let o of e){let s=Ke(o,t);s&&r.add(n?`Did you mean "${s}" for "${o}"?`:`Did you mean "${s}"?`)}return[...r]}var $={tiltNotInstalled:()=>new S("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: ${ee}`]),dockerNotAvailable:()=>new S("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: ${ee}`]),dockerNotResponding:()=>new S("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 S(`Stack "${e}" not found`,[...ne([e],t),"Run `flisk stacks` to see available stacks","Run `flisk stack` to assign resources to a stack"]),resourceNotFound:(e,t=[])=>new S(`Resource "${e}" not found`,[...ne([e],t),"Run `flisk resources` to list all resources","Check the resource name spelling"]),unknownServices:(e,t)=>{let n=ne(e,t,e.length>1);return new S(`Unknown service ${e.join(", ")}. Valid names: ${t.join(", ")}`,n,2)},directoryExists:e=>new S(`Directory already exists: ${e}`,["Use `--path` to specify a different location","Remove the existing directory if no longer needed"]),invalidPath:e=>new S(`Invalid path: ${e}`,["Path must be within the project directory",'Path cannot contain special characters like <>:"|?*']),notInProject:()=>new S("Could not find project root (no .tdk/project.json found)",["Run this from within a Flisk project","Run `flisk project --yes` to initialize a new project"])};function eo(){let e=E();return e||$.notInProject().exit()}function Qt(e){e instanceof S&&e.exit(),oe(Je(e)),process.exit(1)}async function Zt(e,t){try{return await e()}catch(n){if(n instanceof re)throw n;return t?.verbose&&n instanceof Error&&n.stack&&console.error(f.gray(n.stack)),Qt(n)}}async function to(e,t){let n=[],r=We();return r==="unresponsive"?n.push($.dockerNotResponding()):r==="missing"&&n.push($.dockerNotAvailable()),await He()||n.push($.tiltNotInstalled()),n.length>0&&(console.error(f.red(`
|
|
3
|
+
Flisk can't start - missing prerequisites:
|
|
4
|
+
`)),n.forEach((o,s)=>{s>0&&console.error(""),o.display()}),console.error(f.gray("\nRun `flisk doctor` for a full environment check.")),process.exit(1)),Zt(e,t)}function no(e,t=1,n){oe(e,void 0,n),process.exit(t)}function oe(e,t,n){if(console.error(f.red(`\u274C ${e}`)),t&&console.error(f.gray(` ${t}`)),n&&n.length>0){console.error(f.yellow(`
|
|
5
|
+
\u{1F4A1} Suggestions:`));for(let r of n)console.error(f.cyan(` \u2192 ${r}`))}}function ro(e,t){console.error(f.red(`
|
|
6
|
+
tilt ${e} failed with exit code ${t}`)),process.exit(t)}function en(e,t,n){return e===1?t:n||`${t}s`}function Ye(e,t,n){return`${e} ${en(e,t,n)}`}var tn={month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"};function io(e){return new Date(e).toLocaleString("en-US",tn)}function ao(e){return new Date(e).toLocaleDateString("en-US",{month:"short",day:"numeric"})}var se={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 ie(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 co(e){return se[ie(e)].color}function uo(e){return se[ie(e)].icon}function fo(e,t){return se[ie(t)].chalkFn(e)}var nn={resources:{singular:"resource",command:"flisk resource <name>",context:`
|
|
7
|
+
To create a resource:`},stacks:{singular:"stack",command:"flisk stack <stack-name>",context:`
|
|
8
|
+
To create a stack, use:`},services:{singular:"service",command:"flisk resource <name>",context:`
|
|
9
|
+
To create a service:`},"stack-services":{singular:"service",command:"flisk resource <name> --stack <stack-name>",context:`
|
|
10
|
+
To add services to this stack:`}};function po(e,t){let n=nn[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(`
|
|
11
|
+
Or create a new resource with a stack:`)),console.log(f.gray(" flisk resource <name> --stack <stack-name>")))}function lo(e){console.log(f.yellow(e||"Cancelled."))}function mo(e){console.log(f.blue(`Flisk ${e}
|
|
12
|
+
`))}function ho(e,t){console.log(f.green(`All ${e} are ${t}!`))}var ae=62;function go(e="\u2500",t=ae){return e.repeat(t)}function qe(e,t=ae-2){let n=Math.max(0,t-e.length),r=Math.floor(n/2),o=n-r;return" ".repeat(r)+e+" ".repeat(o)}function So(e,t){return e.length>t?`${e.slice(0,t-1)}\u2026`:e.padEnd(t)}function xo(e,t){return e.length<=t?e:`${e.slice(0,t-3)}...`}function yo(e){console.log(f.green(`\u2713 ${e}`))}function Eo(e){console.log(f.blue(e))}function ko(e,t=2){console.log(f.gray(`${" ".repeat(t)}${e}`))}function $o(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function wo(e,t,n=ae){let r=n-2,o="\u2500".repeat(r);console.log(),console.log(f.cyan(`\u256D${o}\u256E`)),console.log(f.cyan("\u2502")+f.bold.white(qe(e,r))+f.cyan("\u2502")),t&&(console.log(f.cyan(`\u251C${o}\u2524`)),console.log(f.cyan("\u2502")+f.gray(qe(t,r))+f.cyan("\u2502"))),console.log(f.cyan(`\u2570${o}\u256F`))}import{randomBytes as Qe}from"node:crypto";import{existsSync as ue,readFileSync as Ze,writeFileSync as et}from"node:fs";import{join as fe}from"node:path";import{randomBytes as rn}from"node:crypto";import{closeSync as on,fchmodSync as sn,fsyncSync as an,openSync as cn,renameSync as un,rmSync as fn,statSync as pn,writeFileSync as ln}from"node:fs";import{basename as dn,dirname as mn,join as hn}from"node:path";function Xe(e,t){let n=hn(mn(e),`.${dn(e)}.${process.pid}.${rn(4).toString("hex")}.tmp`),r;try{r=pn(e).mode&511}catch{r=void 0}try{let o=cn(n,"wx");try{r!==void 0&&sn(o,r),ln(o,t,"utf-8"),an(o)}finally{on(o)}un(n,e)}catch(o){throw fn(n,{force:!0}),o}}var R=[{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}],tt=()=>Qe(16).toString("hex"),gn=()=>Qe(32).toString("hex"),Io=R.filter(e=>e.complete).map(e=>e.name);function ce(e,t){return e==="DB_PASSWORD"?t:e==="JWT_SECRET"?gn():e==="DATABASE_URL"?`postgresql://postgres:${t}@postgres:5432/app_dev`:R.find(n=>n.name===e)?.default??""}function Sn(e){let t=e.trim(),n=t[0];if(n==='"'||n==="'"){let o=!1;for(let s=1;s<t.length;s+=1){let i=t[s];if(o){o=!1;continue}if(i==="\\"){o=!0;continue}if(i===n){let a=t.slice(1,s);if(n==='"'){let c={n:`
|
|
13
|
+
`,r:"\r",t:" ",'"':'"',"\\":"\\",$:"$"};return a.replace(/\\([nrt"\\$])/g,(p,l)=>c[l]??l)}return a.replace(/\\'/g,"'")}}return t}let r=e.search(/\s#/);return(r===-1?e:e.slice(0,r)).trim()}function O(e){let t=new Map,n=e.startsWith("\uFEFF")?e.slice(1):e;for(let r of n.split(/\r?\n/)){let o=r.trim();if(!o||o.startsWith("#"))continue;let s=o.startsWith("export ")?o.slice(7).trim():o,i=s.indexOf("=");if(i<=0)continue;let a=s.slice(0,i).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(a)&&t.set(a,Sn(s.slice(i+1)))}return t}function nt(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 rt(){let e=tt(),t=["# \u{1F527} Flisk Environment Configuration","# Generated by `flisk 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: flisk config regenerate && flisk up",""];for(let n of R)t.push(...nt(n)),t.push(`${n.name}=${ce(n.name,e)}`),t.push("");return t.join(`
|
|
14
|
+
`)}function xn(e){let t=e.match(/^[a-z][a-z0-9+.-]*:\/\/[^:/@\s]+:([^@\s]*)@/i);if(!(!t||t[1].includes("$")))return t[1]}function jo(e){let t=fe(e,".env"),n={missing:[],invalid:[],warnings:[]};if(!ue(t))return{missing:R.filter(i=>i.required).map(i=>i.name),invalid:[],warnings:[".env file not found - will be auto-generated"]};let r=O(Ze(t,"utf-8"));for(let i of R)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 o=r.get("DATABASE_URL"),s=r.get("DB_PASSWORD");if(o&&s){let i=xn(o);i!==void 0&&i!==s&&n.warnings.push("DATABASE_URL carries a different password than DB_PASSWORD; the database container uses DB_PASSWORD")}return n}function yn(e,t,n){if(!O(e).has(t))return e;let o=e.indexOf("=");if(o<0)return e;let s=e.slice(o+1),i=s.search(/\s#/),a=i<0?"":s.slice(i);return e.slice(0,o+1)+n+a}function No(e){let t=fe(e,".env");if(!ue(t))return et(t,rt(),{mode:384}),R.map(u=>u.name);let n=Ze(t,"utf-8"),r=O(n),o=R.filter(u=>u.complete?r.has(u.name)?!(r.get(u.name)??"").trim():!0:!1);if(o.length===0)return[];let s=o.filter(u=>!r.has(u.name)),i=o.filter(u=>r.has(u.name)),a=r.get("DB_PASSWORD"),c=a?.trim()?a:tt(),p=n.split(/(\r\n|\n|\r)/);for(let u of i){let h=-1;for(let d=0;d<p.length;d+=2)O(p[d]).has(u.name)&&(h=d);if(h<0)throw new Error(`Could not locate empty .env assignment for ${u.name}`);p[h]=yn(p[h],u.name,ce(u.name,c))}let l=p.join("");if(s.length>0){let u=["","# Added by Flisk: keys this version expects. Existing values above were not changed.",""];for(let d of s)u.push(...nt(d)),u.push(`${d.name}=${ce(d.name,c)}`),u.push("");let h=l.endsWith(`
|
|
15
|
+
`)||l.endsWith("\r")?"":`
|
|
16
|
+
`;l+=h+u.join(`
|
|
17
|
+
`)}return Xe(t,l),o.map(u=>u.name)}function Po(e){let t=fe(e,".env");return ue(t)?!1:(et(t,rt(),{mode:384}),!0)}import{readFileSync as En}from"node:fs";import{join as kn}from"node:path";function C(e){return e==="backend"||e==="mcp"||e==="agent"}function Wo(){return ot(E())}function ot(e){if(e)try{let t=En(kn(e,".tdk",B),"utf-8"),n=JSON.parse(t);if(n?.project?.name)return n.project.name}catch{}return"tdk-project"}function pe(e,t){let n=ot(t??E()),r=process.env.TDK_SERVICE_BASE_URL??`http://${n}.localhost${e?`:${e}`:""}`;try{let o=new URL(r.includes("://")?r:`http://${r}`),s=o.hostname,i=o.protocol==="https:"?"443":"80",a=o.port||(e?String(e):""),c=a===i?"":a;if(s==="localhost"||/^\d+\.\d+\.\d+\.\d+$/.test(s))return{appBase:`${o.protocol}//${s}${c?`:${c}`:""}`,apiBase:`${o.protocol}//${s}${c?`:${c}`:""}`};let p=s.replace(/^(app|api)\./,"");return{appBase:`${o.protocol}//app.${p}${c?`:${c}`:""}`,apiBase:`${o.protocol}//api.${p}${c?`:${c}`:""}`}}catch{return{appBase:`http://app.${n}.localhost`,apiBase:`http://api.${n}.localhost`}}}function $n(e){return`${e.replace(/\/+$/,"")}/health`}function le(e){if(C(e.config?.appType)){let t=e.name.replace(/-api$/,"");return e.config?.apiPath??`/api/${t}`}return e.config?.basePath??`/${e.name}`}function Ko(e,t){return st(e,t,n=>$n(n))}function Ho(e,t){return st(e,t,n=>n)}function st(e,t,n){let{appBase:r,apiBase:o}=pe(t);return e.filter(s=>s.config?.appType==="frontend"||C(s.config?.appType)).map(s=>{let i=C(s.config.appType)?o:r;return{name:s.name,appType:s.config.appType,url:`${i}${n(le(s))}`}})}async function wn(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 zo(e,t){return Promise.all(e.map(n=>wn(n,t)))}var vn=/^[a-z0-9-]+$/;function it(e){return vn.test(e)}var Tn="Use lowercase letters, numbers, and hyphens only";function at(e,t){return`${e} "${t}" is not valid. ${Tn}, e.g. "${e==="Resource name"?"my-service":"my-stack"}".`}function bn(e){return e.trim()?it(e)?{valid:!0}:{valid:!1,error:at("Resource name",e)}:{valid:!1,error:"Resource name is required"}}function An(e){return e.trim()?it(e)?{valid:!0}:{valid:!1,error:at("Stack name",e)}:{valid:!1,error:"Stack name is required"}}function Yo(e){let t=e==="resource"?bn:An;return n=>{let r=t(n);return r.valid?!0:r.error??"Invalid name"}}function Xo(e){return de(Z,e)?{valid:!0}:{valid:!1,error:`Invalid service. Must be one of: ${Z.join(", ")}`}}function Qo(e){return Number.isInteger(e)&&e>0&&e<=65535}function Zo(e){return!e.includes("\0")&&!/[<>:"|?*]/.test(e)}function es(e,t="_"){return e.replace(/[^a-zA-Z0-9-]/g,t).substring(0,100)}function de(e,t){return e.includes(t)}import Rt,{existsSync as I,readdirSync as qn,readFileSync as Yn,statSync as Ee}from"node:fs";import{dirname as Xn,join as b}from"node:path";var M=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 ct(e){let t=0;return{isValid(){return Date.now()-t<e},markUpdated(){t=Date.now()},reset(){t=0}}}import{existsSync as Tt,readFileSync as bt}from"node:fs";import{copyFileSync as dt,mkdirSync as jn,rmSync as mt,writeFileSync as ht}from"node:fs";import{join as D}from"node:path";import{existsSync as Rn,readFileSync as _n}from"node:fs";import{join as On}from"node:path";var Cn="[REDACTED]",me=class extends Error{path;constructor(t,n){super(`Could not read ${t}: ${n}`),this.path=t,this.name="EnvUnreadableError"}},Dn=8;function In(e,t=[]){let n=[...ut(On(e,".env")),...t.flatMap(r=>ut(r))];return[...new Set(n)].sort((r,o)=>o.length-r.length)}function ut(e){if(!Rn(e))return[];let t;try{t=_n(e,"utf-8")}catch(n){throw new me(e,n instanceof Error?n.message:String(n))}return[...O(t).values()].filter(n=>n.length>=Dn)}function pt(e,t){let n=e;for(let r of t)n=n.split(r).join(Cn);return n}function ft(e,t){return t.length===0?e:typeof e=="string"?pt(e,t):Array.isArray(e)?e.map(n=>ft(n,t)):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,ft(r,t)])):e}function lt(e,t=[]){let n;try{n=In(e,t)}catch(r){return()=>{throw r}}return r=>pt(r,n)}var kt=60,gt=1e3,St=1e4,xt=200,yt=64*1024,Et=new Set([404,502,503,504]),Nn=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","EHOSTUNREACH","ENETUNREACH"]),Pn=new Set(["GET","HEAD","OPTIONS"]);function v(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Fn(e,t){if(Pn.has(t))return!0;if(!v(e))return!1;let n=v(e.cause)?e.cause:void 0,r=e.code??n?.code;return typeof r=="string"&&Nn.has(r)}function ge(e){if(!v(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 o=`smoke.steps[${r}]`;if(!v(n)){t.push(`${o}: must be an object`);return}let s=n.path;(typeof s!="string"||!s.startsWith("/")||s.startsWith("//"))&&t.push(`${o}.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(`${o}.expect: must be an HTTP status between 100 and 599`),n.bodyContains!==void 0&&typeof n.bodyContains!="string"&&t.push(`${o}.bodyContains: must be a string`),n.save!==void 0&&(v(n.save)&&Object.values(n.save).every(a=>typeof a=="string"&&a.startsWith("$."))||t.push(`${o}.save: must map names to paths such as "$.id"`))}),t)}function ds(e,t){let{appBase:n,apiBase:r}=pe(t),o=[];for(let s of e){let i=s.config;if(!i?.smoke)continue;let a=i.appType,c=C(a)||a===_;if(!c&&a!=="frontend"||i.exposeViaProxy===!1)continue;let p=c?r:n,l=i.healthCheckPath||(c&&a!==_?"/health":void 0);o.push({name:s.name,baseUrl:`${p}${le(s).replace(/\/+$/,"")}`,...l?.startsWith("/")?{readyPath:l}:{},smoke:i.smoke})}return o}var Un=10;function ms(e,t={}){let n=t.timeoutSeconds??Un;return e.flatMap(r=>{let o=r.smoke.steps.filter(i=>(i.method??"GET").toUpperCase()==="GET"&&i.body===void 0&&!i.path.includes("{{")).map(i=>({...i,bodyContains:void 0}));if(o.length===0)return[];let s=Math.min(r.smoke.timeoutSeconds??kt,n);return[{name:r.name,baseUrl:r.baseUrl,smoke:{via:r.smoke.via,timeoutSeconds:s,steps:o}}]})}function Mn(e,t){let n=t.replace(/^\$\.?/,"").match(/[^.[\]]+/g)??[],r=e;for(let o of n){if(r==null||o==="__proto__"||o==="constructor"||o==="prototype"||!Object.hasOwn(r,o))return;let s=Object.getOwnPropertyDescriptor(r,o);if(!s||!("value"in s))return;r=s.value}return r}function $t(e,t){return e.replace(/\{\{(\w+)\}\}/g,(n,r)=>t[r]??n)}function he(e,t){return typeof e=="string"?$t(e,t):Array.isArray(e)?e.map(n=>he(n,t)):v(e)?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,he(r,t)])):e}function K(e){let t=e.replace(/\s+/g," ").trim();return t.length>xt?`${t.slice(0,xt)}...`:t}function wt(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"step"}function Ln(e,t){let n=wt(t),r=(e.get(n)??0)+1;return e.set(n,r),r===1?n:`${n}-${r}`}function Bn(e,t,n,r,o){try{let s=D(e,wt(n.service),t);jn(s,{recursive:!0});let i=D(s,"latest.json"),a=D(s,"body.txt");return r===void 0?mt(a,{force:!0}):ht(a,r),ht(i,`${JSON.stringify({...n,bodyPath:r===void 0?null:"body.txt"},null,2)}
|
|
18
|
+
`),o&&(dt(i,D(s,"last-success.json")),r===void 0?mt(D(s,"last-success-body.txt"),{force:!0}):dt(a,D(s,"last-success-body.txt"))),i}catch{return}}function Vn(e){let t=Buffer.from(e,"utf8");if(t.length<=yt)return{body:e,truncated:!1,bytes:t.length};let n=t.subarray(0,yt).toString("utf8").replace(/\uFFFD$/,"");return{body:n,truncated:!0,bytes:Buffer.byteLength(n,"utf8")}}async function Gn(e,t={}){let n=t.fetch??((l,u)=>fetch(l,u)),r=t.now??Date.now,o=t.sleep??(l=>new Promise(u=>setTimeout(u,l))),s=(e.smoke.timeoutSeconds??kt)*1e3,i=r()+s,a={},c=ge(e.smoke);if(c.length>0)return{name:e.name,ok:!1,failure:`${e.name}: invalid smoke block: ${c.join("; ")}`};if(e.readyPath){let l=`${e.baseUrl}${e.readyPath}`;for(;;){try{let u=await n(l,{method:"GET",signal:AbortSignal.timeout(St)});if(await u.text(),!Et.has(u.status)&&u.status<500)break}catch{}if(r()>=i)break;await o(gt)}}i=r()+s;let p=new Map;for(let[l,u]of e.smoke.steps.entries()){let h=u.name??`step ${l+1}`,d=(u.method??"GET").toUpperCase(),be=`${e.baseUrl}${$t(u.path,a)}`,j=u.expect??200,Ae=u.body!==void 0,x,N="",w,q;for(;;){w=void 0,q=void 0,x=void 0;let g=!1;try{let m=await n(be,{method:d,headers:Ae?{"content-type":"application/json"}:void 0,body:Ae?JSON.stringify(he(u.body,a)):void 0,signal:AbortSignal.timeout(St)});x=m.status,N=await m.text()}catch(m){g=Fn(m,d),w=m instanceof Error?m.message:String(m);let A=v(m)?m.code??(v(m.cause)?m.cause.code:void 0):void 0;q=typeof A=="string"?A:void 0}if(!(w!==void 0&&g||x!==void 0&&x!==j&&Et.has(x))||r()>=i)break;await o(gt)}let Re=!1,Y=g=>{if(!Re){if(!t.redact)return g;try{return t.redact(g)}catch(k){Re=!0;let m=k instanceof Error?k.message:String(k);t.warn?.(`${e.name}: ${h}: the response text was neither shown nor stored: ${m}`);return}}},X=Y(be),y=x===void 0?void 0:Y(N),_e=w===void 0?void 0:Y(w),Oe=w===void 0?void 0:q??_e,P=`${e.name}: ${h}: ${d} ${X??"(url withheld)"}`,Ce;if(t.recordDir){let g=y===void 0?void 0:Vn(y),k=w===void 0&&x===j&&(u.bodyContains===void 0||N.includes(u.bodyContains));Ce=Bn(t.recordDir,Ln(p,h),{service:e.name,step:h,method:d,...X===void 0?{}:{url:X},expectedStatus:j,status:x??null,...Oe===void 0?{}:{error:Oe},truncated:g?.truncated??!1,bodyBytes:g?.bytes??0},g?.body,k)}let F=g=>({name:e.name,ok:!1,failure:g,recordPath:Ce});if(w!==void 0)return F(`${P} never answered (${_e??"the error was withheld"})`);if(x!==j)return F(`${P} returned ${x}, expected ${j}${y?`: ${K(y)}`:""}`);if(u.bodyContains!==void 0&&!N.includes(u.bodyContains))return F(`${P} returned ${x} but the body does not contain "${u.bodyContains}"${y?`: ${K(y)}`:""}`);if(u.save){let g;try{g=JSON.parse(N)}catch{return F(`${P} returned a body that is not JSON, cannot save${y?`: ${K(y)}`:""}`)}for(let[k,m]of Object.entries(u.save)){let A=Mn(g,m);if(A==null||typeof A=="object")return F(`${P} response has no ${m} to save as {{${k}}}${y?`: ${K(y)}`:""}`);a[k]=String(A)}}}return{name:e.name,ok:!0}}function hs(e){return`Smoke check failed: ${e.failure}${e.recordPath?` (record: ${e.recordPath})`:""}`}function gs(e,t,n={}){return{redact:lt(e,n.envFiles??[]),...t?{warn:t}:{}}}async function Ss(e,t={}){return Promise.all(e.map(n=>Gn(n,t)))}var vt=1,ks="https://flisk.sh/schema.service.json",Wn={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"},Kn=new Set(["$schema","agent","apiBasePath","apiPath","appName","appType","backendName","basePath","build","buildContext","databaseName","dependencies","dev","dependsOn","dockerfile","enabled","exposeViaProxy","featuresEnabled","framework","healthCheckPath","image","language","name","nats","params","playwright","port","replicas","restart","runtime","sablier","schemaVersion","secrets","smoke","stack","syncs","traefik","type"]),Hn=[{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 H(e,t){let n=[],r=new Set;for(let{path:o,pattern:s,expected:i}of Hn){let a=e;for(let p of o)a=a&&typeof a=="object"&&!Array.isArray(a)?a[p]:void 0;if(a==null||a==="")continue;let c=`${t}.${o.join(".")}`;(typeof a!="string"||!s.test(a))&&r.add(c),typeof a!="string"?n.push(`${c}: expected a string`):s.test(a)||n.push(`${c}: must be ${i} (no spaces, line breaks or YAML syntax)`)}for(let[o,s]of zn(e,t))r.has(o)||n.push(`${o}: ${s}`);return n}function Se(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 zn(e,t){let n=[],r=Object.entries(e).filter(([o])=>o!=="smoke").map(([o,s])=>[s,`${t}.${o}`]);for(let o of Object.keys(e))Se(o)&&n.push([t,"a key contains a line break"]);for(;r.length>0;){let[o,s]=r.pop();if(typeof o=="string")Se(o)&&n.push([s,"must not contain line breaks or control characters"]);else if(Array.isArray(o))for(let[i,a]of o.entries())r.push([a,`${s}[${i}]`]);else if(o&&typeof o=="object")for(let[i,a]of Object.entries(o))Se(i)?n.push([s,"a key contains a line break"]):r.push([a,`${s}.${i}`])}return n.sort(([o],[s])=>o.localeCompare(s))}var Jn=["apiPath","basePath"];function xe(e){if(!e||typeof e!="object"||Array.isArray(e))return[];let t=e;return Jn.filter(n=>n in t&&typeof t[n]!="string")}function ye(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!==vt&&r.push(`${t}.schemaVersion: unsupported version ${String(n.schemaVersion)} (supported: ${vt})`);for(let a of xe(n))r.push(`${t}.${a}: expected a string`);let o=n.dev,s=o&&typeof o=="object"&&!Array.isArray(o)?o.liveReload:void 0;if(s!==void 0&&typeof s!="boolean"&&r.push(`${t}.dev.liveReload: expected true or false`),r.push(...H(n,t)),"smoke"in n)for(let a of ge(n.smoke))r.push(`${t}.${a}`);let i=Object.keys(n).flatMap(a=>{let c=Wn[a];return c?[`${t}.${a}: ${c}`]:Kn.has(a)?[]:[`${t}.${a}: unknown field is preserved`]});return s===!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 $s(e,t){if(!Tt(e))return[];try{let n=JSON.parse(bt(e,"utf-8"));return!n||typeof n!="object"||Array.isArray(n)?[]:H(n,t)}catch{return[]}}function ws(e,t){if(!Tt(e))return{errors:[`${t}: file is missing`],warnings:[]};try{let n=JSON.parse(bt(e,"utf-8"));return ye(n,t)}catch(n){let r=n instanceof Error?n.message:String(n);return{errors:[`${t}: invalid JSON (${r})`],warnings:[]}}}function At(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 Qn=Ie;function ve(e,t=5,n=0){let r=[];if(n>t)return r;let o=Rt.readdirSync(e,{withFileTypes:!0});for(let s of o){let i=b(e,s.name);if(s.isDirectory()){if(Zn(s.name))continue;r.push(...ve(i,t,n+1))}else s.isFile()&&s.name===Qn&&r.push(i)}return r}function Ps(e){return ve(e)}function Zn(e){return de(Ne,e)||e.startsWith(".")}function er(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 z=new Set;var T=class extends Error{reason;constructor(t){super(t),this.reason=t,this.name="InvalidServiceJsonError"}};function ke(e){return e instanceof Error?e.message:String(e)}function tr(e){let t;try{t=Rt.readFileSync(e,"utf-8")}catch(c){throw new T(`could not read file: ${ke(c)}`)}let n;try{n=JSON.parse(t)}catch(c){throw new T(`invalid JSON: ${ke(c)}`)}if(!er(n))throw new T("missing required fields (appName, runtime or appType)");let r=xe(n);if(r.length>0)throw new T(r.map(c=>`${c}: expected a string`).join("; "));let o=H(n,e);if(o.length>0)throw new T(o.join("; "));let s=n;for(let c of ye(n,e).warnings)z.has(c)||(z.add(c),console.warn(`\u26A0\uFE0F ${c}`));let i={...s,appType:s.appType||s.type},a=Xn(e);return{name:i.appName,path:a,configPath:e,config:i,stack:i.stack,port:i.port,type:i.appType}}function _t(e){let t=ve(e),n=[],r=[];for(let o of t)try{n.push(tr(o))}catch(s){r.push({path:o,reason:s instanceof T?s.reason:ke(s)})}return{resources:n,problems:r}}function nr(e){for(let t of e){let n=`skipped ${t.path}: ${t.reason}`;z.has(n)||(z.add(n),console.warn(`\u26A0\uFE0F ${n}`))}}function Ot(e){let{resources:t,problems:n}=_t(e);return nr(n),t}function J(){let e=E();if(!e)throw $.notInProject();return Ot(e)}function Fs(e){let t=e;if(!t){let n=E();if(!n)throw $.notInProject();t=_t(n)}if(t.problems.length>0)throw new Error(t.problems.map(n=>`Invalid service.json at ${n.path}: ${n.reason}`).join(`
|
|
19
|
+
`));return t.resources}function Us(e,t){let n=t??Ot(e);return rr(n)}function rr(e){let t=e||J(),n=new Set;for(let r of t)r.stack&&n.add(r.stack);return Array.from(n).sort()}function Ms(e=J()){let t=new Map;for(let r of e)if(r.stack){let o=t.get(r.stack);o?o.push(r):t.set(r.stack,[r])}let n=[];for(let[r,o]of t)n.push({name:r,description:Ye(o.length,"resource"),resources:o,resourceCount:o.length});return n.sort((r,o)=>r.name.localeCompare(o.name))}function Ls(e,t){return(t??J()).filter(r=>r.stack===e)}function Bs(e,t){return(t??J()).some(r=>r.stack===e)}var Te=5e3,$e=new M({ttlMs:Te}),we=new M({ttlMs:Te}),L=ct(Te);function Vs(){$e.clear(),we.clear(),L.reset()}function or(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===je)return"config";if(e==="schema.prisma"||e.includes("migration"))return"prisma";if(t){let n=t.split(`
|
|
20
|
+
`).slice(0,10).join(`
|
|
21
|
+
`);if(n.includes("GENERATED BY Flisk")||n.includes("AUTOGENERATED"))return"generated"}return"unknown"}function sr(e){let t=e.configPath;if(L.isValid()){let d=$e.get(t);if(d)return d}let n=e.path,r=Ee(e.configPath),o=r.mtime.toISOString(),s=r.mtime.toISOString(),i=ir(n),a=I(b(n,"Dockerfile")),c=I(b(n,"Tiltfile")),p=I(b(n,Q))||I(b(n,"docker-compose.yaml")),l=e.config?.appType,u=l||"backend";l||(e.name.includes("frontend")?u="frontend":(e.name.includes("sdk")||e.name.includes("lib")||e.name.includes("infra"))&&(u="library"));let h={name:e.name,stack:e.stack,type:u,port:e.config?.port,createdAt:o,lastModified:s,dependencies:e.config?.dependsOn??[],hasDockerfile:a,hasTiltfile:c,hasDockerCompose:p,autogeneratedFiles:i,status:"unknown"};return $e.set(t,h),L.markUpdated(),h}function ir(e){let t=[];for(let r of Pe){let o=b(e,r);if(I(o)){let s=Ee(o),i=Yn(o,"utf-8");t.push({name:r,path:o,type:or(r,i),size:s.size,lastModified:s.mtime.toISOString()})}}let n=b(e,"prisma");if(I(n)){let r=qn(n);for(let o of r)if(o==="schema.prisma"||o.includes("migration")){let s=b(n,o),i=Ee(s);t.push({name:`prisma/${o}`,path:s,type:"prisma",size:i.size,lastModified:i.mtime.toISOString()})}}return t.sort((r,o)=>r.name.localeCompare(o.name))}function Gs(e){let t=e.name;if(L.isValid()){let c=we.get(t);if(c)return c}let n=e.resources.map(c=>sr(c)),r=n.map(c=>new Date(c.createdAt).getTime()),o=Math.min(...r),s=Math.max(...r),i=At(n.map(c=>c.status)),a={name:e.name,resourceCount:n.length,createdAt:new Date(o).toISOString(),lastModified:new Date(s).toISOString(),resources:n,overallStatus:i};return we.set(t,a),L.markUpdated(),a}var Hs=[De,"proxy"];export{Fe as a,ar as b,_ as c,De as d,cr as e,Ie as f,Q as g,ur as h,Ct as i,Dt as j,B as k,je as l,fr as m,pr as n,lr as o,dr as p,mr as q,hr as r,E as s,wr as t,U as u,Ar as v,Rr as w,G as x,Ir as y,Yt as z,He as A,Xt as B,Wr as C,Kr as D,Je as E,Zr as F,S as G,$ as H,eo as I,Zt as J,to as K,no as L,oe as M,ro as N,Ye as O,io as P,ao as Q,co as R,uo as S,fo as T,po as U,lo as V,mo as W,ho as X,ae as Y,go as Z,So as _,xo as $,yo as aa,Eo as ba,ko as ca,$o as da,wo as ea,C as fa,Xe as ga,Io as ha,O as ia,jo as ja,No as ka,Po as la,me as ma,In as na,pt as oa,ft as pa,Wo as qa,pe as ra,$n as sa,le as ta,Ko as ua,Ho as va,zo as wa,ds as xa,ms as ya,hs as za,gs as Aa,Ss as Ba,vt as Ca,ks as Da,ye as Ea,$s as Fa,ws as Ga,At as Ha,bn as Ia,An as Ja,Yo as Ka,Xo as La,Qo as Ma,Zo as Na,es as Oa,de as Pa,Ps as Qa,_t as Ra,nr as Sa,Ot as Ta,J as Ua,Fs as Va,Us as Wa,rr as Xa,Ms as Ya,Ls as Za,Bs as _a,Vs as $a,sr as ab,Gs as bb,Hs as cb};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
|
|
2
|
-
import{
|
|
2
|
+
import{a as At,f as It,g as ae,i as Re}from"./chunk-7IWOM6M2.js";import{i as Mt,o as Lt}from"./chunk-3SPYAO2E.js";import{c as Ft}from"./chunk-42IVF3YT.js";import{Aa as _t,Ba as jt,Ca as De,G as J,O as g,Ta as b,Ua as Ot,b as x,c as re,d as Pt,fa as I,g as wt,h as D,ja as Tt,k as _,l as R,m as $e,ma as Et,na as Ee,o as Te,oa as oe,pa as Nt,q as vt,qa as K,s as m,t as xt,ua as Ne,va as Dt,wa as ie,x as $,xa as Rt,y as $t,ya as Ct}from"./chunk-GW7N23FV.js";import{b as y}from"./chunk-CF46CD6R.js";import{execFileSync as yn}from"node:child_process";import{readFileSync as ui}from"node:fs";import{join as pi}from"node:path";import{execFileSync as Po,execSync as tn}from"node:child_process";import{existsSync as E,readdirSync as wo,readFileSync as W}from"node:fs";import{join as w,normalize as lt,relative as ut}from"node:path";import{Command as vo}from"commander";import{existsSync as xn}from"node:fs";var ce="docs/agent-hosts.md",Ce=`WebContainers cannot run Flisk: there is no Docker daemon or Tilt. Run \`flisk up\` on a machine with Docker. See ${ce}.`,Ht=`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 ${ce}.`;function $n(){return{env:process.env,versions:process.versions,platform:process.platform,fileExists:xn}}function Ut(e=$n()){let{env:t,versions:s,platform:n,fileExists:r}=e;return s.webcontainer?{kind:"webcontainer",canUp:!1}:t.CODESPACES==="true"?{kind:"codespaces",canUp:!0}:t.REMOTE_CONTAINERS||r("/.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 Bt(e){return e==="devcontainer"||e==="codespaces"}function de(e){return e.some(t=>I(t.config?.appType)||t.config?.appType==="frontend"||t.config?.appType==="worker")}import{existsSync as Tn,readFileSync as En}from"node:fs";import{join as Nn,relative as Gt,resolve as Wt,sep as Dn}from"node:path";var Rn=2,Vt=["services/*/*"];function qt(e){return e.split(Dn).filter(Boolean)}function Cn(e,t){let s=0,n=0,r=-1,o=0;for(;n<t.length;)if(s<e.length&&e[s]!=="*"&&(e[s]==="?"||e[s]===t[n]))s++,n++;else if(s<e.length&&e[s]==="*")r=s++,o=n;else if(r!==-1)s=r+1,n=++o;else return!1;for(;s<e.length&&e[s]==="*";)s++;return s===e.length}function _n(e,t){return e.length===t.length&&e.every((s,n)=>Cn(s,t[n]))}function _e(e){let t=Nn(e,".tdk",_);if(!Tn(t))return Vt;try{let s=JSON.parse(En(t,"utf-8"))?.discovery?.paths;if(Array.isArray(s)&&s.every(n=>typeof n=="string"))return s}catch{}return Vt}function le(e,t,s){let n=qt(Gt(e,Wt(e,t)));return s.some(r=>{let o=qt(Gt(e,Wt(e,r)));for(let i=0;i<=Rn;i++){let a=n.length-i;if(a>0&&_n(o,n.slice(0,a)))return!0}return!1})}function Ti(e,t,s,n){let r=_e(e);if(le(e,t,r))return{path:t};let o=`services/${s}/${n}`;return le(e,o,r)?{path:o,adjustedFrom:t}:{path:t}}import{execFile as zn}from"node:child_process";import{promisify as Yn}from"node:util";import{execFileSync as Qt,execSync as X}from"node:child_process";import{existsSync as je,readdirSync as jn,readFileSync as Oe}from"node:fs";import{join as B}from"node:path";function Jt(e,t){return e==="pending"||e==="in_progress"||e==="none"||t==="pending"||t==="none"}var Kt="container is running, but its health check is failing";function zt(e){let t=e?.runtimeStatus??"";if(t!=="ok")return t;let s=e?.composeResourceInfo?.healthStatus;return s==="unhealthy"?"error":s==="starting"?"pending":t}var z=1e4,Yt=3e3,On="http://localhost:4873";function es(e){return`'${e.replace(/'/g,"'\\''")}'`}function Y(e,t,s,n,r){return process.platform==="win32"?Qt($(t)??t,s,{...r,windowsHide:!0}):e(n,r)}var An=[80,443];function Ae(e){return e.replace(/-/g,"_")}function In(e,t){let s=new Set(t),n=[];for(let r of e.split(`
|
|
3
3
|
`)){let o=r.trim();if(!o)continue;let i=o.indexOf(" "),a=i>=0?o.slice(0,i):o,c=i>=0?o.slice(i+1):"",d=[];for(let l of s)c.split(/[\s,]+/).some(h=>h.startsWith(`${l}->`)||h.includes(`:${l}->`))&&d.push(l);d.length>0&&n.push({name:a,ports:c,publishedPorts:d})}return n}function ts(e,t){let s=e.toLowerCase(),n=t.toLowerCase();return s===`${n}_traefik`||s.startsWith(`${n}_traefik`)}function Fn(e,t){return e.filter(s=>!ts(s.name,t))}function Ie(e){try{let t=e??Ot();return new Set(t.filter(s=>s.config?.sablier?.enable&&s.config?.sablier?.deferStart).map(s=>s.name))}catch{return new Set}}function Fe(e,t=new Set){let n=JSON.parse(e).items??[],r=[],o=0,i=0,a=0;for(let c of n){let d=c.metadata?.name??"unknown",l=c.status?.updateStatus??"",u=zt(c.status),h=u==="error"&&c.status?.runtimeStatus==="ok",P=(c.status?.buildHistory?.[0]?.error??"").trim()||(h?Kt:"");if(l==="error"||u==="error"){r.push({name:d,updateStatus:l,runtimeStatus:u,error:P.replace(/\s+/g," ").slice(0,800)});continue}if(l==="ok"&&(u==="ok"||u==="not_applicable")){a+=1;continue}d!=="(Tiltfile)"&&Jt(l,u)&&(t.has(d)?i+=1:o+=1)}return{failures:r,pendingCount:o,deferredCount:i,okCount:a,total:n.length}}var Mn=/failed to resolve source metadata for docker\.io\/library\/([A-Za-z0-9._-]+-l[1-4](?:-[a-z]+)*)(?::[^\s:]+)?:/i;function Me(e){let t=e.replace(/\s+/g," ").trim(),s=t.match(/Bind for [^ ]+:(\d+) failed: port is already allocated/i);if(s)return`host port ${s[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(", "),d=a.length>4?` (+${a.length-4} more)`:"";return`private registry ConnectionRefused for ${c}${d} \u2014 Verdaccio (:4873) is down or unreachable from the build`}let r=t.match(Mn);if(r)return`base image ${r[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 Xt(e){return/ConnectionRefused downloading package manifest|Verdaccio|private registry|dependency install failed during ImageBuild|install-deps\.sh|bun install/i.test(e)}function Le(e=m()??process.cwd()){let t=B(e,".tdk",_);if(!je(t))return!1;try{let s=JSON.parse(Oe(t,"utf-8"));return s.optional_infra?.verdaccio===!0||Object.values(s.phases??{}).some(n=>(n.enabledStacks??[]).includes("verdaccio"))}catch{return!1}}function ss(e){for(let t of[B(e,".npmrc"),B(e,R)])if(je(t))try{let s=Oe(t,"utf-8");if(/:4873\b/.test(s)||/verdaccio/i.test(s))return!0}catch{}return!1}function Ln(e=m()??process.cwd()){return Le(e)||ss(e)}function He(e=X,t=m()??process.cwd(),s=process.env.VERDACCIO_URL??process.env.NPM_REGISTRY_URL??On,n=!0){if(!n&&!ss(t))return{name:"Private npm registry",didPass:!0,isSkipped:!0,message:"Verdaccio is enabled in the project config but needs a Premium license, so Flisk will not start it - skipped"};if(!Ln(t))return{name:"Private npm registry",didPass:!0,isSkipped:!0,message:"Private npm registry (Verdaccio) not enabled for this project - skipped"};let r=!1;try{let a=Y(e,"docker",["ps","--format","{{.Names}}"],"docker ps --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:z});r=/verdaccio/i.test(a)}catch{}let o=!1,i="";try{let a=process.platform==="win32"?Qt("curl.exe",["-fsS","-o","NUL","-w","%{http_code}","--max-time","2",s],{stdio:"pipe",encoding:"utf-8",timeout:Yt+1e3,windowsHide:!0}).trim():e(`curl -fsS -o /dev/null -w '%{http_code}' --max-time 2 ${es(s)}`,{stdio:"pipe",encoding:"utf-8",timeout:Yt+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 ${s}${r?" (verdaccio container running)":""}`}:r?{name:"Private npm registry",didPass:!1,message:`Verdaccio container is running but ${s} 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 `flisk doctor`."}:{name:"Private npm registry",didPass:!1,message:`Private npm registry (Verdaccio) is not reachable at ${s}. Docker ImageBuilds will fail with ConnectionRefused downloading package manifests for @flisk-sh/* 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 `flisk up`."}}function Ue(e=X,t=K(),s=An){let n=Ae(t),r="";try{r=Y(e,"docker",["ps","--format","{{.Names}}\\t{{.Ports}}"],"docker ps --format '{{.Names}}\\t{{.Ports}}'",{stdio:"pipe",encoding:"utf-8",timeout:z})}catch{return{name:"Ingress Ports",didPass:!0,isSkipped:!0,message:"Docker not available - skipped ingress port check"}}let o=In(r,s),i=Fn(o,n);if(i.length===0){let c=o.filter(d=>ts(d.name,n));return c.length>0?{name:"Ingress Ports",didPass:!0,message:`Ingress ports ${s.join("/")} held by this project's Traefik (${c.map(d=>d.name).join(", ")})`}:{name:"Ingress Ports",didPass:!0,message:`Ingress ports ${s.join("/")} are free for Traefik`}}return{name:"Ingress Ports",didPass:!1,message:`Traefik cannot bind ingress ports because another container already owns them:
|
|
4
4
|
${i.map(c=>{let d=c.publishedPorts.join(", ");return`${c.name} (host ports ${d})`}).join(`
|
|
5
5
|
`)}`,fix:`Stop the foreign container(s), e.g. \`docker stop ${i[0]?.name}\`, or shut down the other Flisk/Tilt project using that Traefik. Then re-run \`flisk up\`.`}}function Hn(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 Be(e){let t=e.filter(o=>o.status!==void 0),s=e.filter(o=>!o.ok);if(t.length===0)return{name:"Service Health",didPass:!0,isSkipped:!0,message:`No services responded - skipped ping of ${g(e.length,"service")} (stack may be down, or Traefik never bound :80)`,fix:"If `flisk up` is already running, check Traefik/port 80 in the Tilt UI. Otherwise start with: flisk up"};if(s.length===0)return{name:"Service Health",didPass:!0,message:`All ${g(e.length,"service")} responding on /health`};let n=s.map(o=>`${o.name} (${Hn(o)})
|
|
@@ -22,14 +22,14 @@ import{i as Mt,o as Lt}from"./chunk-CXFHRZLM.js";import{c as Ft}from"./chunk-42I
|
|
|
22
22
|
`))}return{name:r,didPass:!1,message:`${a.length} container${a.length===1?" is":"s are"} crash-looping:
|
|
23
23
|
${c.join(`
|
|
24
24
|
`)}`,fix:[...d,"Read the full log: docker logs <container>"].join("; ")}}import{execFile as yr}from"node:child_process";import{realpathSync as fs,statfsSync as br}from"node:fs";import{homedir as Sr}from"node:os";import{join as Pr}from"node:path";import{promisify as wr}from"node:util";import{statfsSync as ar}from"node:fs";import{homedir as cr}from"node:os";var ue="Disk Space",dr=1024**3,lr=2,Ve=10,cs=["Free disk space, then retry: flisk 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(`
|
|
25
|
-
`);function ds(e=ar,t=cr()){let s;try{let r=e(t);s=Number(r.bavail)*Number(r.bsize)/dr}catch{return{name:ue,didPass:!0,isSkipped:!0,message:"Could not read free disk space"}}let n=`${s.toFixed(1)} GB free`;return s<lr?{name:ue,didPass:!1,message:`${n}: Docker cannot build or start containers`,fix:cs}:s<Ve?{name:ue,didPass:!1,isWarning:!0,message:`${n}: image builds may fail`,fix:cs}:{name:ue,didPass:!0,message:n}}var ur="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: flisk doctor";function ls(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:ur}}import{execFileSync as pr}from"node:child_process";var qe=(e,t)=>pr(e,t,{encoding:"utf-8",stdio:"pipe",windowsHide:!0}),us=["traefik-public","traefik-private","backend","database","infisical-network","verdaccio-network","proxy"];function Je(e){let t=e.replace(/-/g,"_");return us.map(s=>`${t}_${s}`)}function ps(e){let t=new Set;for(let s of e)for(let n of["traefik-public","traefik-private"])s.endsWith(`_${n}`)&&t.add(s.slice(0,-(n.length+1)));return t}function Ke(e,t){for(let s of us)if(e.endsWith(`_${s}`)){let n=e.slice(0,-(s.length+1));if(t.has(n))return n}return null}function zi(e,t=qe){let s=new Set(t("docker",["network","ls","--format","{{.Name}}"]).split(/\r?\n/).map(r=>r.trim()).filter(Boolean)),n={removed:[],kept:[]};for(let r of Je(e))if(s.has(r))try{t("docker",["network","rm",r]),n.removed.push(r)}catch(o){let i=String(o.stderr??o).trim();n.kept.push({name:r,reason:i.split(/\r?\n/)[0]??""})}return n}function pe(e,t=process.platform,s=qe){if(t==="win32")return[];let n;try{n=s("ps",["-axo","pid=,command="])}catch{return[]}let r=[];for(let o of n.split(/\r?\n/)){let i=/^\s*(\d+)\s+(.*)$/.exec(o);if(!i)continue;let a=i[2]??"",c=(a.split(/\s+/)[0]??"").split("/").at(-1),d=` -f ${e}`,l=a.indexOf(d),u=a[l+d.length];c==="tilt"&&/^\S+\s+up\s/.test(a)&&l>0&&(u===void 0||u===" ")&&r.push(Number(i[1]))}return r}function Yi(e,t=process.platform,s=qe){let n=pe(e,t,s);for(let r of n)try{s("kill",["-TERM",String(r)])}catch{}return n}async function Xi(e,t=8e3,s=pe){let n=Date.now()+t;for(;s(e).length>0;){if(Date.now()>=n)return!1;await new Promise(r=>setTimeout(r,250))}return!0}import{execFile as fr}from"node:child_process";function ze(e){return new Promise(t=>{fr($("tilt")??"tilt",["get","uiresources","-o","json","--port",String(e)],{timeout:15e3,maxBuffer:16*1024*1024},(s,n)=>t(s?null:n))})}function mr(e){let s=(JSON.parse(e).items??[]).filter(n=>n.status?.disableStatus?.state!=="Disabled").map(n=>n.status?.updateStatus==="not_applicable"?{...n,status:{...n.status,updateStatus:"ok"}}:n);return JSON.stringify({items:s})}function hr(e){return(JSON.parse(e).items??[]).filter(t=>t.status?.disableStatus?.state!=="Disabled").flatMap(t=>t.metadata?.name?[t.metadata.name]:[])}function gr(e,t){let s=JSON.parse(e).items??[],n=new Map(s.map(r=>[r.metadata?.name,r]));return{missing:t.filter(r=>!n.has(r)),disabled:t.filter(r=>n.get(r)?.status?.disableStatus?.state==="Disabled")}}function kr(e,t,s){let n=Fe(mr(e),t),r={ready:n.failures.length===0&&n.pendingCount===0&&n.okCount>0,failures:n.failures.map(o=>({name:o.name,message:o.error||`${o.updateStatus}/${o.runtimeStatus}`})),pending:n.pendingCount,timedOut:!1,enabled:hr(e)};if(s&&s.length>0){let{missing:o,disabled:i}=gr(e,s);if(o.length>0&&(r={...r,ready:!1,pending:r.pending+o.length}),i.length>0)return{settled:!0,result:{...r,ready:!1,failures:[...r.failures,...i.map(a=>({name:a,message:"disabled in Tilt"}))]}}}return{result:r,settled:r.ready||r.failures.length>0&&r.pending===0}}async function sa(e,t={}){let s=t.timeoutMs??Number(process.env.TDK_UP_READY_TIMEOUT_MS??9e5),n=t.intervalMs??2e3,r=t.fetchJson??ze,o=t.deferred??Ie(),i=Date.now()+s,a={ready:!1,failures:[],pending:0,timedOut:!1,enabled:[]};for(;;){let c=await r(e);if(c)try{let d=kr(c,o,t.expected);if(a=d.result,d.settled||a.failures.length>0&&t.isStalled?.(c))return a}catch{}if(Date.now()>=i)return{...a,ready:!1,timedOut:!0};await new Promise(d=>setTimeout(d,n))}}var fe=wr(yr),vr=15e3,xr=/^tdk_doctor_probe_(\d+)$/,$r=async e=>{let{stdout:t}=await fe("docker",e,{encoding:"utf-8",timeout:vr,windowsHide:!0});return t};function Ye(e){return String(e.stderr??e).trim().split(/\r?\n/)[0]??""}var Tr=120;function Er(e){let t=/^\s*(?:(?:(\d+)-)?(\d+):)?(\d+):(\d+)\s*$/.exec(e);if(!t)return null;let[,s="0",n="0",r="0",o="0"]=t;return((Number(s)*24+Number(n))*60+Number(r))*60+Number(o)}async function Nr(e,t=ze,s=2,n=r=>new Promise(o=>setTimeout(o,r))){for(let r=0;r<s;r++){r>0&&await n(1e3);for(let o of e)if(await t(o)!==null)return!0}return!1}async function Dr(e){if(process.platform==="win32")return"unknown";try{let{stdout:t}=await fe("ps",["-p",String(e),"-o","etime="],{encoding:"utf-8",timeout:5e3}),s=Er(t);if(s===null||s<Tr)return"unknown";let{stdout:n}=await fe("lsof",["-nP","-a","-p",String(e),"-iTCP","-sTCP:LISTEN","-Fn"],{encoding:"utf-8",timeout:5e3}),r=[...n.matchAll(/^n.*:(\d+)$/gm)].map(o=>Number(o[1]));return await Nr(r)?"healthy":"stale"}catch{return"unknown"}}function Rr(e=$r){return{async listNetworks(){let t=(await e(["network","ls","--format","{{.Name}}"])).split(/\r?\n/).map(n=>n.trim()).filter(Boolean);return(await Promise.all(t.map(async n=>{try{let r=await e(["network","inspect","--format","{{len .Containers}}",n]);return{name:n,containers:Number(r.trim())||0}}catch(r){if(/no such network|not found/i.test(String(r)))return null;throw r}}))).filter(n=>n!==null)},async removeNetwork(t){try{await e(["network","rm",t])}catch(s){throw new Error(Ye(s))}},freeDiskGib(){try{let t=br(Sr());return Number(t.bavail)*Number(t.bsize)/1024**3}catch{return null}},async reclaimable(){let t=null;try{let n=await e(["system","df","--format","{{.Type}} {{.Reclaimable}}"]);for(let r of n.split(/\r?\n/)){let[o,i]=r.split(" ");o==="Build Cache"&&i&&(t=i.replace(/\s*\(.*\)/,"").trim())}}catch{}let s=0;try{s=(await e(["images","-q","-f","dangling=true"])).split(/\r?\n/).filter(Boolean).length}catch{}return{buildCache:t,danglingImages:s}},async prune(t){try{await e(t==="builder"?["builder","prune","-f"]:["image","prune","-f"])}catch(s){throw new Error(Ye(s))}},async tiltStatus(t){return Dr(t)},stopProcess(t){process.kill(t,"SIGTERM")},isProcessAlive(t){try{return process.kill(t,0),!0}catch(s){return s.code==="EPERM"}}}}var ms=Rr();async function hs(e,t=ms,s={}){let n=[],r=[];for(let l of s.tiltPids??[])await t.tiltStatus(l)==="stale"?n.push({id:`stop-tilt:${l}`,check:"Tilt processes",scope:"project",command:`kill -TERM ${l}`,status:"planned",reason:"this project's Tilt is running but its UI does not answer"}):r.push(l);let o=r.length>0?`Tilt is running for this project (pid ${r.join(", ")}); run flisk down first`:void 0,i=await t.listNetworks(),a=t.freeDiskGib();if(a!==null&&a<Ve){let{buildCache:l,danglingImages:u}=await t.reclaimable(),h=`${a.toFixed(1)} GB free`;l&&!/^0(\.0+)?\s*B$/i.test(l)&&n.push({id:"prune:builder",check:"Disk Space",scope:"host",command:"docker builder prune -f",status:"planned",reason:`${h}; ${l} of build cache reclaimable`}),u>0&&n.push({id:"prune:images",check:"Disk Space",scope:"host",command:"docker image prune -f",status:"planned",reason:`${h}; ${u} untagged image${u===1?"":"s"}`})}let c=new Set(e?Je(e):[]),d=ps(i.map(l=>l.name));for(let l of i){let u=xr.exec(l.name),h,S,P="unused network";if(u)h="probe",S="Orphaned probe networks";else if(c.has(l.name))h="project",S="Docker networks";else if(s.machine&&Ke(l.name,d))h="machine",S="Docker networks",P=`unused network of project "${Ke(l.name,d)}"`;else continue;let k={id:`remove-network:${l.name}`,check:S,scope:h,command:`docker network rm ${l.name}`,status:"planned",reason:P};l.containers>0?(k.status="skipped",k.reason=`${l.containers} container(s) still attached`):h==="project"&&o?(k.status="skipped",k.reason=o):u&&t.isProcessAlive(Number(u[1]))&&(k.status="skipped",k.reason=`probe of a running process (pid ${u[1]})`),n.push(k)}return n}async function gs(e,t,s=ms){let n=[];for(let r of e){if(r.status!=="planned"||t.dryRun){n.push(r);continue}if(!t.confirm){n.push({...r,status:"skipped",reason:"confirmation required; run in a terminal or pass --yes"});continue}let o=!1;try{o=await t.confirm(r)}catch{}if(!o){n.push({...r,status:"skipped",reason:"not confirmed"});continue}try{if(r.id.startsWith("prune:")){await s.prune(r.id==="prune:builder"?"builder":"images"),n.push({...r,status:"applied",reason:"pruned"});continue}if(r.id.startsWith("stop-tilt:")){s.stopProcess(Number(r.id.slice(10))),n.push({...r,status:"applied",reason:"stopped"});continue}await s.removeNetwork(r.id.slice(15)),n.push({...r,status:"applied",reason:"removed"})}catch(i){n.push({...r,status:"failed",reason:Ye(i)})}}return n}function ks(e){return e.some(t=>t.status==="failed")}async function Cr(e){try{let{stdout:t}=await fe(e,["--version"],{encoding:"utf-8",timeout:5e3,windowsHide:!0});return t.trim().split(/\r?\n/)[0]||null}catch{return null}}async function _r(e=$t("flisk"),t=Cr){let s=new Set,n=[];for(let r of e){let o=r;try{o=fs(r)}catch{}s.has(o)||(s.add(o),n.push({path:r,version:await t(r)}))}return n}async function ys(e){let t=e??await _r();if(t.length<=1)return{name:"Flisk installs",didPass:!0,message:"One flisk install on PATH"};let s=t.map(r=>`${r.path} (${r.version??"version unknown"})`).join(", "),n=new Set(t.map(r=>r.version));return{name:"Flisk installs",didPass:!1,isWarning:!0,message:`${t.length} flisk installs on PATH${n.size>1?" with different versions":""}: ${s}`,fix:"Keep one: remove the others, or run flisk upgrade. The first on PATH is the one your shell runs; tools that launch /usr/local/bin/tdk directly may use another"}}function bs(e,t=pe){let s=new Set([e]);try{s.add(fs(e))}catch{}let n=new Set;for(let r of s)for(let o of t(Pr(r,".tdk",".tdk-out","Tiltfile")))n.add(o);return[...n]}var Xe=1;function jr(e,t=[]){return{schemaVersion:Xe,data:e,errors:t}}function Or(e){return e instanceof J?{error:{code:"COMMAND_FAILED",message:e.message,...e.suggestions.length>0?{suggestions:e.suggestions}:{}},exitCode:e.exitCode}:{error:{code:"INTERNAL",message:e instanceof Error?e.message:String(e)},exitCode:2}}function ha(e){let t=Or(e);console.log(JSON.stringify(jr(null,[t.error]))),console.error(t.error.message),process.exit(t.exitCode)}async function Ps(e,t){let s=[],n=[],r=o=>{o.status==="fulfilled"?s.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))))r(o);for(let o of t)for(let i of await Promise.allSettled([Promise.resolve().then(o)]))r(i);return{checks:s,errors:n}}function Ss(e){let t=e.find(s=>s.name===x);return t?t.didPass:null}function M(e,t,s=[],n,r){return{schemaVersion:Xe,data:{ready:s.length===0&&e.every(o=>o.didPass||o.isSkipped||o.isWarning),inProject:t,checks:e,...r?{host:{...r,containerRuntimeReachable:Ss(e),canUp:r.canUp&&Ss(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:s}}function ws(e){return e.errors.length>0?2:e.data.ready?0:1}import{existsSync as Qe,readFileSync as vs}from"node:fs";import{dirname as Ar,join as Ze,normalize as Ir}from"node:path";function Fr(e){let t=new Set,s=/^load\s*\(([\s\S]*?)\)/gm;for(let n of e.matchAll(s)){let r=n[1]??"",o=/["']([^"']+)["']/g,i=Array.from(r.matchAll(o),a=>a[1]);for(let a of i.slice(1))a.startsWith("_")&&t.add(a)}return Array.from(t).sort()}function xs(e,t,s){return t==="ext://tdk-cli"?Ze(s,".tdk",".tdk-out","tdk-cli-ext","Tiltfile"):t.startsWith(".")||!t.includes("://")&&!t.startsWith("@")?Ir(Ze(Ar(e),t)):null}function Mr(e,t,s){let n=[],r=/^load\s*\(([\s\S]*?)\)/gm;for(let o of t.matchAll(r)){let c=(o[1]??"").match(/["']([^"']+)["']/)?.[1];if(!c)continue;let d=xs(e,c,s);d&&(Qe(d)||n.push(`${e}: ${c} -> ${d}`))}return n}function Lr(e,t,s){let n=[],r=/^load\s*\(([\s\S]*?)\)/gm;for(let o of t.matchAll(r)){let c=(o[1]??"").match(/["']([^"']+)["']/)?.[1];if(c){let d=xs(e,c,s);d&&n.push(d)}}return n}function Hr(e,t){let s=new Set,n=[e];for(;n.length>0;){let r=n.pop();if(!r||s.has(r)||!Qe(r))continue;s.add(r);let o=vs(r,"utf-8");for(let i of Lr(r,o,t))s.has(i)||n.push(i)}return Array.from(s).sort()}function $s(){let e=m()??process.cwd(),t=Ze(e,".tdk",".tdk-out","Tiltfile");if(!Qe(t))return{name:"Starlark Load Exports",didPass:!0,isSkipped:!0,message:"No generated Tiltfile to check"};let s=[],n=[],r=Hr(t,e);for(let i of r){let a=vs(i,"utf-8"),c=Fr(a);c.length>0&&s.push(`${i}: ${c.join(", ")}`);for(let d of Mr(i,a,e))n.push(d)}if(s.length===0&&n.length===0)return{name:"Starlark Load Exports",didPass:!0,message:`${g(r.length,"reachable Starlark file")} ${r.length===1?"has":"have"} valid load exports and paths`};let o=[];return s.length>0&&o.push(`Private exported symbols:
|
|
25
|
+
`);function ds(e=ar,t=cr()){let s;try{let r=e(t);s=Number(r.bavail)*Number(r.bsize)/dr}catch{return{name:ue,didPass:!0,isSkipped:!0,message:"Could not read free disk space"}}let n=`${s.toFixed(1)} GB free`;return s<lr?{name:ue,didPass:!1,message:`${n}: Docker cannot build or start containers`,fix:cs}:s<Ve?{name:ue,didPass:!1,isWarning:!0,message:`${n}: image builds may fail`,fix:cs}:{name:ue,didPass:!0,message:n}}var ur="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: flisk doctor";function ls(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:ur}}import{execFileSync as pr}from"node:child_process";var qe=(e,t)=>pr(e,t,{encoding:"utf-8",stdio:"pipe",windowsHide:!0}),us=["traefik-public","traefik-private","backend","database","infisical-network","verdaccio-network","proxy"];function Je(e){let t=e.replace(/-/g,"_");return us.map(s=>`${t}_${s}`)}function ps(e){let t=new Set;for(let s of e)for(let n of["traefik-public","traefik-private"])s.endsWith(`_${n}`)&&t.add(s.slice(0,-(n.length+1)));return t}function Ke(e,t){for(let s of us)if(e.endsWith(`_${s}`)){let n=e.slice(0,-(s.length+1));if(t.has(n))return n}return null}function Yi(e,t=qe){let s=new Set(t("docker",["network","ls","--format","{{.Name}}"]).split(/\r?\n/).map(r=>r.trim()).filter(Boolean)),n={removed:[],kept:[]};for(let r of Je(e))if(s.has(r))try{t("docker",["network","rm",r]),n.removed.push(r)}catch(o){let i=String(o.stderr??o).trim();n.kept.push({name:r,reason:i.split(/\r?\n/)[0]??""})}return n}function pe(e,t=process.platform,s=qe){if(t==="win32")return[];let n;try{n=s("ps",["-axo","pid=,command="])}catch{return[]}let r=[];for(let o of n.split(/\r?\n/)){let i=/^\s*(\d+)\s+(.*)$/.exec(o);if(!i)continue;let a=i[2]??"",c=(a.split(/\s+/)[0]??"").split("/").at(-1),d=` -f ${e}`,l=a.indexOf(d),u=a[l+d.length];c==="tilt"&&/^\S+\s+up\s/.test(a)&&l>0&&(u===void 0||u===" ")&&r.push(Number(i[1]))}return r}function Xi(e,t=process.platform,s=qe){let n=pe(e,t,s);for(let r of n)try{s("kill",["-TERM",String(r)])}catch{}return n}async function Zi(e,t=8e3,s=pe){let n=Date.now()+t;for(;s(e).length>0;){if(Date.now()>=n)return!1;await new Promise(r=>setTimeout(r,250))}return!0}import{execFile as fr}from"node:child_process";function ze(e){return new Promise(t=>{fr($("tilt")??"tilt",["get","uiresources","-o","json","--port",String(e)],{timeout:15e3,maxBuffer:16*1024*1024},(s,n)=>t(s?null:n))})}function mr(e){let s=(JSON.parse(e).items??[]).filter(n=>n.status?.disableStatus?.state!=="Disabled").map(n=>n.status?.updateStatus==="not_applicable"?{...n,status:{...n.status,updateStatus:"ok"}}:n);return JSON.stringify({items:s})}function hr(e){return(JSON.parse(e).items??[]).filter(t=>t.status?.disableStatus?.state!=="Disabled").flatMap(t=>t.metadata?.name?[t.metadata.name]:[])}function gr(e,t){let s=JSON.parse(e).items??[],n=new Map(s.map(r=>[r.metadata?.name,r]));return{missing:t.filter(r=>!n.has(r)),disabled:t.filter(r=>n.get(r)?.status?.disableStatus?.state==="Disabled")}}function kr(e,t,s){let n=Fe(mr(e),t),r={ready:n.failures.length===0&&n.pendingCount===0&&n.okCount>0,failures:n.failures.map(o=>({name:o.name,message:o.error||`${o.updateStatus}/${o.runtimeStatus}`})),pending:n.pendingCount,timedOut:!1,enabled:hr(e)};if(s&&s.length>0){let{missing:o,disabled:i}=gr(e,s);if(o.length>0&&(r={...r,ready:!1,pending:r.pending+o.length}),i.length>0)return{settled:!0,result:{...r,ready:!1,failures:[...r.failures,...i.map(a=>({name:a,message:"disabled in Tilt"}))]}}}return{result:r,settled:r.ready||r.failures.length>0&&r.pending===0}}async function na(e,t={}){let s=t.timeoutMs??Number(process.env.TDK_UP_READY_TIMEOUT_MS??9e5),n=t.intervalMs??2e3,r=t.fetchJson??ze,o=t.deferred??Ie(),i=Date.now()+s,a={ready:!1,failures:[],pending:0,timedOut:!1,enabled:[]};for(;;){let c=await r(e);if(c)try{let d=kr(c,o,t.expected);if(a=d.result,d.settled||a.failures.length>0&&t.isStalled?.(c))return a}catch{}if(Date.now()>=i)return{...a,ready:!1,timedOut:!0};await new Promise(d=>setTimeout(d,n))}}var fe=wr(yr),vr=15e3,xr=/^tdk_doctor_probe_(\d+)$/,$r=async e=>{let{stdout:t}=await fe("docker",e,{encoding:"utf-8",timeout:vr,windowsHide:!0});return t};function Ye(e){return String(e.stderr??e).trim().split(/\r?\n/)[0]??""}var Tr=120;function Er(e){let t=/^\s*(?:(?:(\d+)-)?(\d+):)?(\d+):(\d+)\s*$/.exec(e);if(!t)return null;let[,s="0",n="0",r="0",o="0"]=t;return((Number(s)*24+Number(n))*60+Number(r))*60+Number(o)}async function Nr(e,t=ze,s=2,n=r=>new Promise(o=>setTimeout(o,r))){for(let r=0;r<s;r++){r>0&&await n(1e3);for(let o of e)if(await t(o)!==null)return!0}return!1}async function Dr(e){if(process.platform==="win32")return"unknown";try{let{stdout:t}=await fe("ps",["-p",String(e),"-o","etime="],{encoding:"utf-8",timeout:5e3}),s=Er(t);if(s===null||s<Tr)return"unknown";let{stdout:n}=await fe("lsof",["-nP","-a","-p",String(e),"-iTCP","-sTCP:LISTEN","-Fn"],{encoding:"utf-8",timeout:5e3}),r=[...n.matchAll(/^n.*:(\d+)$/gm)].map(o=>Number(o[1]));return await Nr(r)?"healthy":"stale"}catch{return"unknown"}}function Rr(e=$r){return{async listNetworks(){let t=(await e(["network","ls","--format","{{.Name}}"])).split(/\r?\n/).map(n=>n.trim()).filter(Boolean);return(await Promise.all(t.map(async n=>{try{let r=await e(["network","inspect","--format","{{len .Containers}}",n]);return{name:n,containers:Number(r.trim())||0}}catch(r){if(/no such network|not found/i.test(String(r)))return null;throw r}}))).filter(n=>n!==null)},async removeNetwork(t){try{await e(["network","rm",t])}catch(s){throw new Error(Ye(s))}},freeDiskGib(){try{let t=br(Sr());return Number(t.bavail)*Number(t.bsize)/1024**3}catch{return null}},async reclaimable(){let t=null;try{let n=await e(["system","df","--format","{{.Type}} {{.Reclaimable}}"]);for(let r of n.split(/\r?\n/)){let[o,i]=r.split(" ");o==="Build Cache"&&i&&(t=i.replace(/\s*\(.*\)/,"").trim())}}catch{}let s=0;try{s=(await e(["images","-q","-f","dangling=true"])).split(/\r?\n/).filter(Boolean).length}catch{}return{buildCache:t,danglingImages:s}},async prune(t){try{await e(t==="builder"?["builder","prune","-f"]:["image","prune","-f"])}catch(s){throw new Error(Ye(s))}},async tiltStatus(t){return Dr(t)},stopProcess(t){process.kill(t,"SIGTERM")},isProcessAlive(t){try{return process.kill(t,0),!0}catch(s){return s.code==="EPERM"}}}}var ms=Rr();async function hs(e,t=ms,s={}){let n=[],r=[];for(let l of s.tiltPids??[])await t.tiltStatus(l)==="stale"?n.push({id:`stop-tilt:${l}`,check:"Tilt processes",scope:"project",command:`kill -TERM ${l}`,status:"planned",reason:"this project's Tilt is running but its UI does not answer"}):r.push(l);let o=r.length>0?`Tilt is running for this project (pid ${r.join(", ")}); run flisk down first`:void 0,i=await t.listNetworks(),a=t.freeDiskGib();if(a!==null&&a<Ve){let{buildCache:l,danglingImages:u}=await t.reclaimable(),h=`${a.toFixed(1)} GB free`;l&&!/^0(\.0+)?\s*B$/i.test(l)&&n.push({id:"prune:builder",check:"Disk Space",scope:"host",command:"docker builder prune -f",status:"planned",reason:`${h}; ${l} of build cache reclaimable`}),u>0&&n.push({id:"prune:images",check:"Disk Space",scope:"host",command:"docker image prune -f",status:"planned",reason:`${h}; ${u} untagged image${u===1?"":"s"}`})}let c=new Set(e?Je(e):[]),d=ps(i.map(l=>l.name));for(let l of i){let u=xr.exec(l.name),h,S,P="unused network";if(u)h="probe",S="Orphaned probe networks";else if(c.has(l.name))h="project",S="Docker networks";else if(s.machine&&Ke(l.name,d))h="machine",S="Docker networks",P=`unused network of project "${Ke(l.name,d)}"`;else continue;let k={id:`remove-network:${l.name}`,check:S,scope:h,command:`docker network rm ${l.name}`,status:"planned",reason:P};l.containers>0?(k.status="skipped",k.reason=`${l.containers} container(s) still attached`):h==="project"&&o?(k.status="skipped",k.reason=o):u&&t.isProcessAlive(Number(u[1]))&&(k.status="skipped",k.reason=`probe of a running process (pid ${u[1]})`),n.push(k)}return n}async function gs(e,t,s=ms){let n=[];for(let r of e){if(r.status!=="planned"||t.dryRun){n.push(r);continue}if(!t.confirm){n.push({...r,status:"skipped",reason:"confirmation required; run in a terminal or pass --yes"});continue}let o=!1;try{o=await t.confirm(r)}catch{}if(!o){n.push({...r,status:"skipped",reason:"not confirmed"});continue}try{if(r.id.startsWith("prune:")){await s.prune(r.id==="prune:builder"?"builder":"images"),n.push({...r,status:"applied",reason:"pruned"});continue}if(r.id.startsWith("stop-tilt:")){s.stopProcess(Number(r.id.slice(10))),n.push({...r,status:"applied",reason:"stopped"});continue}await s.removeNetwork(r.id.slice(15)),n.push({...r,status:"applied",reason:"removed"})}catch(i){n.push({...r,status:"failed",reason:Ye(i)})}}return n}function ks(e){return e.some(t=>t.status==="failed")}async function Cr(e){try{let{stdout:t}=await fe(e,["--version"],{encoding:"utf-8",timeout:5e3,windowsHide:!0});return t.trim().split(/\r?\n/)[0]||null}catch{return null}}async function _r(e=$t("flisk"),t=Cr){let s=new Set,n=[];for(let r of e){let o=r;try{o=fs(r)}catch{}s.has(o)||(s.add(o),n.push({path:r,version:await t(r)}))}return n}async function ys(e){let t=e??await _r();if(t.length<=1)return{name:"Flisk installs",didPass:!0,message:"One flisk install on PATH"};let s=t.map(r=>`${r.path} (${r.version??"version unknown"})`).join(", "),n=new Set(t.map(r=>r.version));return{name:"Flisk installs",didPass:!1,isWarning:!0,message:`${t.length} flisk installs on PATH${n.size>1?" with different versions":""}: ${s}`,fix:"Keep one: remove the others, or run flisk upgrade. The first on PATH is the one your shell runs; tools that launch /usr/local/bin/flisk directly may use another"}}function bs(e,t=pe){let s=new Set([e]);try{s.add(fs(e))}catch{}let n=new Set;for(let r of s)for(let o of t(Pr(r,".tdk",".tdk-out","Tiltfile")))n.add(o);return[...n]}var Xe=1;function jr(e,t=[]){return{schemaVersion:Xe,data:e,errors:t}}function Or(e){return e instanceof J?{error:{code:"COMMAND_FAILED",message:e.message,...e.suggestions.length>0?{suggestions:e.suggestions}:{}},exitCode:e.exitCode}:{error:{code:"INTERNAL",message:e instanceof Error?e.message:String(e)},exitCode:2}}function ga(e){let t=Or(e);console.log(JSON.stringify(jr(null,[t.error]))),console.error(t.error.message),process.exit(t.exitCode)}async function Ps(e,t){let s=[],n=[],r=o=>{o.status==="fulfilled"?s.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))))r(o);for(let o of t)for(let i of await Promise.allSettled([Promise.resolve().then(o)]))r(i);return{checks:s,errors:n}}function Ss(e){let t=e.find(s=>s.name===x);return t?t.didPass:null}function M(e,t,s=[],n,r){return{schemaVersion:Xe,data:{ready:s.length===0&&e.every(o=>o.didPass||o.isSkipped||o.isWarning),inProject:t,checks:e,...r?{host:{...r,containerRuntimeReachable:Ss(e),canUp:r.canUp&&Ss(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:s}}function ws(e){return e.errors.length>0?2:e.data.ready?0:1}import{existsSync as Qe,readFileSync as vs}from"node:fs";import{dirname as Ar,join as Ze,normalize as Ir}from"node:path";function Fr(e){let t=new Set,s=/^load\s*\(([\s\S]*?)\)/gm;for(let n of e.matchAll(s)){let r=n[1]??"",o=/["']([^"']+)["']/g,i=Array.from(r.matchAll(o),a=>a[1]);for(let a of i.slice(1))a.startsWith("_")&&t.add(a)}return Array.from(t).sort()}function xs(e,t,s){return t==="ext://tdk-cli"?Ze(s,".tdk",".tdk-out","tdk-cli-ext","Tiltfile"):t.startsWith(".")||!t.includes("://")&&!t.startsWith("@")?Ir(Ze(Ar(e),t)):null}function Mr(e,t,s){let n=[],r=/^load\s*\(([\s\S]*?)\)/gm;for(let o of t.matchAll(r)){let c=(o[1]??"").match(/["']([^"']+)["']/)?.[1];if(!c)continue;let d=xs(e,c,s);d&&(Qe(d)||n.push(`${e}: ${c} -> ${d}`))}return n}function Lr(e,t,s){let n=[],r=/^load\s*\(([\s\S]*?)\)/gm;for(let o of t.matchAll(r)){let c=(o[1]??"").match(/["']([^"']+)["']/)?.[1];if(c){let d=xs(e,c,s);d&&n.push(d)}}return n}function Hr(e,t){let s=new Set,n=[e];for(;n.length>0;){let r=n.pop();if(!r||s.has(r)||!Qe(r))continue;s.add(r);let o=vs(r,"utf-8");for(let i of Lr(r,o,t))s.has(i)||n.push(i)}return Array.from(s).sort()}function $s(){let e=m()??process.cwd(),t=Ze(e,".tdk",".tdk-out","Tiltfile");if(!Qe(t))return{name:"Starlark Load Exports",didPass:!0,isSkipped:!0,message:"No generated Tiltfile to check"};let s=[],n=[],r=Hr(t,e);for(let i of r){let a=vs(i,"utf-8"),c=Fr(a);c.length>0&&s.push(`${i}: ${c.join(", ")}`);for(let d of Mr(i,a,e))n.push(d)}if(s.length===0&&n.length===0)return{name:"Starlark Load Exports",didPass:!0,message:`${g(r.length,"reachable Starlark file")} ${r.length===1?"has":"have"} valid load exports and paths`};let o=[];return s.length>0&&o.push(`Private exported symbols:
|
|
26
26
|
${s.join(`
|
|
27
27
|
`)}`),n.length>0&&o.push(`Missing relative load targets:
|
|
28
28
|
${n.join(`
|
|
29
29
|
`)}`),{name:"Starlark Load Exports",didPass:!1,message:`Starlark load() issues will stop Tilt before services start:
|
|
30
30
|
${o.join(`
|
|
31
31
|
|
|
32
|
-
`)}`,fix:"Regenerate with a current Flisk (`flisk config regenerate`). If the issue remains, rename loaded symbols without leading underscores and update stale load paths."}}import{execFileSync as zr,execSync as Yr}from"node:child_process";import{existsSync as tt,readdirSync as Is,readFileSync as Q}from"node:fs";import{basename as Xr,dirname as Zr,join as T,relative as Z}from"node:path";function
|
|
32
|
+
`)}`,fix:"Regenerate with a current Flisk (`flisk config regenerate`). If the issue remains, rename loaded symbols without leading underscores and update stale load paths."}}import{execFileSync as zr,execSync as Yr}from"node:child_process";import{existsSync as tt,readdirSync as Is,readFileSync as Q}from"node:fs";import{basename as Xr,dirname as Zr,join as T,relative as Z}from"node:path";function Ta(e){return Ts(e,!1)}function Ea(e){return Ts(e,!0)}function Ts(e,t){return`import { Hono } from 'hono';
|
|
33
33
|
${t?`import { sql } from 'drizzle-orm';
|
|
34
34
|
import { db } from './db.js';
|
|
35
35
|
`:""}
|
|
@@ -375,7 +375,7 @@ mod tests {
|
|
|
375
375
|
assert_eq!(body["status"], "ok");
|
|
376
376
|
}
|
|
377
377
|
}
|
|
378
|
-
`,description:"Generating backend source and smoke test",emoji:"\u{1F4BB}"}]}};var _s="bun",G={bun:Es,python:Rs,go:Ns,rust:Cs,node:Ds};function Vr(e){let t=(e??_s).trim().toLowerCase(),s=Object.hasOwn(G,t)?G[t]:void 0;if(!s){let n=Object.keys(G).join(", ");throw new J(`Unknown backend language "${e}". Supported languages: ${n}.`,[`Use one of: ${n}`,`Omit --language to use ${_s}`])}return s}function
|
|
378
|
+
`,description:"Generating backend source and smoke test",emoji:"\u{1F4BB}"}]}};var _s="bun",G={bun:Es,python:Rs,go:Ns,rust:Cs,node:Ds};function Vr(e){let t=(e??_s).trim().toLowerCase(),s=Object.hasOwn(G,t)?G[t]:void 0;if(!s){let n=Object.keys(G).join(", ");throw new J(`Unknown backend language "${e}". Supported languages: ${n}.`,[`Use one of: ${n}`,`Omit --language to use ${_s}`])}return s}function La(e,t){if(e!=="backend"){if(t!==void 0)throw new J("--language can only be used with --type backend.",["Add --type backend, or drop --language for this resource type"]);return}return Vr(t)}import{exec as qr,execFile as Jr}from"node:child_process";import{promisify as js}from"node:util";var Kr=js(qr),C=async(e,t)=>{if(process.platform==="win32"){let n=e.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g)??[],[r,...o]=n.map(c=>c.startsWith('"')||c.startsWith("'")?c.slice(1,-1):c);if(!r)throw new Error("Command is empty");let i=$(r)??r,{stdout:a}=await js(Jr)(i,o,{encoding:"utf-8",timeout:t,windowsHide:!0,shell:!1});return a}let{stdout:s}=await Kr(e,{encoding:"utf-8",timeout:t});return s};function Os(e){let t=e;return t?.code==="ETIMEDOUT"||t?.killed===!0}var he=1e4,Qr=/\.(?:[cm]?[jt]sx?|vue)$/,eo=/(?:\.test\.|\.spec\.|\/tests?\/|\/__tests__\/)/,to=7,so=new Set(["node_modules",D,"dist","tests","__tests__"]);function Fs(e){try{let t=JSON.parse(Q(T(e,".tdk",_),"utf-8"));return typeof t?.project?.name=="string"?t.project.name:void 0}catch{return}}function no(e){try{let t=JSON.parse(Q(e,"utf-8")).params;return t&&typeof t=="object"?t:{}}catch{return{}}}function et(e){try{let t=JSON.parse(Q(T(e,R),"utf-8"));return t&&typeof t=="object"?t:{}}catch{return{}}}function As(e){if(typeof e!="string")return;let t=e.match(/(?:^|[^0-9])(\d+)(?:\.|$)/);return t?Number(t[1]):void 0}function ro(e){let t=ke(e);if(t===void 0)return["missing prisma/schema.prisma"];let s=t.replace(/\/\*[\s\S]*?\*\//g,"").replace(/^\s*\/\/.*$/gm,""),n=[],r=s.match(/datasource\s+\w+\s*\{([^}]*)\}/)?.[1]??"";return/provider\s*=\s*["']postgresql["']/.test(r)||n.push("schema provider is not postgresql"),/\b(?:url|directUrl)\s*=/.test(s)&&n.push("schema still declares url/directUrl"),n}function oo(e){let t=T(e,D,"prisma.config.autogenerated.ts"),n=[T(e,"prisma.config.ts"),t].find(i=>tt(i));if(!n)return["missing prisma.config.ts or generated Prisma config"];let o=(ke(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 Ms(e=m()??process.cwd(),t=b(e)){let s=t.filter(o=>o.config?.featuresEnabled?.includes("prisma")),n=[],r=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(s.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:`${g(n.length,"Prisma consistency error")}:
|
|
379
379
|
${n.join(`
|
|
380
380
|
`)}`,fix:"Use featuresEnabled to opt into the validated Prisma 7 shape"};for(let o of s){let i=et(o.path).dependencies,c={...et(o.path).devDependencies??{},...i??{}},d=As(c.prisma),l=As(c["@prisma/client"]);if(d===void 0||l===void 0?n.push(`${o.name}: prisma and @prisma/client are required`):(d!==l||d!==to)&&n.push(`${o.name}: prisma packages must both be major 7`),n.push(...ro(T(o.path,"prisma","schema.prisma")).map(h=>`${o.name}: ${h}`)),n.push(...oo(o.path).map(h=>`${o.name}: ${h}`)),(o.config?.appType??o.type)==="migrator")o.config?.dependsOn?.some(S=>S==="postgres"||S===Pt)||n.push(`${o.name}: migrator must depend on postgres or database-management`);else{o.config?.dependsOn?.some(k=>r.some(p=>p.name===k))||n.push(`${o.name}: API must depend on its Prisma migrator, which depends on postgres or database-management`);let S=et(o.path).scripts;Object.entries(S??{}).some(([k,p])=>Js.has(k)&&typeof p=="string"&&/prisma\s+migrate/.test(p))&&n.push(`${o.name}: API start script must not run prisma migrate`);let P=T(o.path,o.config?.dockerfile??"Dockerfile");me(P,!0)&&n.push(`${o.name}: API image/startup must not run Prisma migrations`)}}return s.length>0&&!Re(e,t).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:`${g(n.length,"Prisma consistency error")}:
|
|
381
381
|
${n.join(`
|
|
@@ -401,7 +401,7 @@ mod tests {
|
|
|
401
401
|
${s.join(`
|
|
402
402
|
`)}`,fix:'Set "port" to the port the service listens on, an integer from 1 to 65535'}}function it(e=m()??process.cwd(),t=!1,s=b(e)){let n=[],r=[];for(let i of s){let a=i.config?.schemaVersion;if(a===De)continue;let c=be(e,i);a===void 0?n.push(`${c} schemaVersion: missing`):r.push(`${c} schemaVersion ${JSON.stringify(a)}: this flisk supports ${De}`)}if(n.length===0&&r.length===0)return{name:"schemaVersion",didPass:!0,message:"Every service.json has a supported schemaVersion"};let o=[...n.length>0?["Run `flisk config migrate` to add the missing schemaVersion"]:[],...r.length>0?["A version this flisk does not support cannot be migrated: upgrade flisk"]:[]];return{name:"schemaVersion",didPass:!1,isWarning:!t,message:`${g(n.length+r.length,"service.json file")} without a supported schemaVersion:
|
|
403
403
|
${[...n,...r].join(`
|
|
404
|
-
`)}`,fix:o.join(". ")}}function
|
|
404
|
+
`)}`,fix:o.join(". ")}}function lc(e,t){let s=it(e,!1,t);s.didPass||(console.warn(y.yellow(`\u26A0 ${s.message}`)),s.fix&&console.warn(y.gray(` ${s.fix}`)))}function uc(e,t={},s=process.exit){let n=t.resources??b(e),r=[ge(e,n),nt(e,n),rt(e,n),ot(e,n)].filter(i=>!i.didPass);if(r.length===0)return;let o=r.map(i=>`${i.message}${i.fix?`
|
|
405
405
|
Fix: ${i.fix}`:""}`).join(`
|
|
406
406
|
`);t.onInvalid?.(o);for(let i of r)console.error(y.red(`\u2717 ${i.message}`)),i.fix&&console.error(y.gray(` Fix: ${i.fix}`));s(1)}import{readFileSync as yo}from"node:fs";import{join as bo}from"node:path";function Qs(e){let t=e.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);return t?[Number(t[1]),Number(t[2]),Number(t[3]??0)]:null}function So(e){try{return JSON.parse(yo(bo(e,".tdk",_),"utf-8"))?.minTdkVersion}catch{return}}function en(e,t){let s=So(e);if(s===void 0)return{status:"none"};let n=typeof s=="string"?Qs(s):null;if(!n||!/^\d+\.\d+\.\d+$/.test(String(s).trim()))return{status:"malformed",message:`.tdk/project.json minTdkVersion ${JSON.stringify(s)} is not a version like "1.3.80"`,fix:'Set minTdkVersion to a MAJOR.MINOR.PATCH string, for example "1.3.80".'};let r=Qs(t),o=r!==null&&(()=>{for(let[a,c]of n.entries()){let d=r[a]??0;if(d!==c)return d>c}return!0})(),i=n.join(".");return o?{status:"ok",required:i}:{status:"too-old",required:i,message:`flisk ${t} is older than the ${i} this project requires (minTdkVersion)`,fix:"Run: flisk upgrade"}}var A=1e4,O={dockerMissing:"See https://docs.docker.com/get-docker/",dockerDaemonDown:"Start Docker Desktop, OrbStack, or Colima, then retry: flisk 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: flisk doctor",port5432:"Stop local Postgres or change the host port. Then: flisk doctor",notProject:"flisk project --yes"},sn="WSL2 detected. Use Docker Desktop WSL integration. Guide: docs/wsl2.md",nn="Native Windows landscape boot is unsupported. Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md",at=[0,25,0],H=[1,2,0];function Se(e,t){let s=ft(e);return s?mt(s,t):!1}function xo(e,t,s=process.platform==="linux"&&!!process.env.WSL_DISTRO_NAME){if(!s)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:`${sn} Project is on the WSL filesystem.`};let r=`${sn} 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:r,fix:"Move the repository under your WSL home directory (for example, ~/projects) and retry flisk doctor."}}function $o(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 To(e=process.env,t=!1){let s=(e.TDK_BIND_ADDRESS??"").trim();return $o(s)?{name:"Dev Port Bind Address",didPass:!t,isWarning:!t,message:`TDK_BIND_ADDRESS is ${s}: 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:s?`Dev ports bind to ${s}`:"Dev ports bind to 127.0.0.1 (this machine only)"}}function an(e){let t=e.filter(n=>!n.didPass&&!n.isSkipped&&!n.isWarning),s=e.filter(n=>n.didPass||n.isSkipped||n.isWarning);return t.sort((n,r)=>{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(r)}),[...t,...s]}function Eo(e,t){return t?e?"Doctor passed. Next: flisk up":"Doctor passed. Next: flisk project example":"Doctor failed. Fix the items above, then run: flisk doctor"}var pt={checkDockerOperatingSystem:"Docker OS",checkDockerCompose:"Docker Compose",checkDockerVersions:"Docker Versions",checkDockerNetworkCapacity:"Docker Network Pool",checkContainerResourceHealth:"Container Resource Health",checkCrashLoopingContainers:"Crash-looping containers",checkTiltResourceHealth:"Tilt Resources",checkServiceHealth:"Service Health",checkServiceSmoke:"Service Smoke",checkAdvertisedEndpoints:"Advertised Endpoints"},rn=new Set(["Docker OS","Docker Compose","Docker Versions","Docker Network Pool","Container Resource Health","Crash-looping containers","Tilt Resources","Service Health","Service Smoke","Advertised Endpoints",...Object.keys(pt)]);function No(e){return!!(e.requiresContainerRuntime||e.checkName&&rn.has(e.checkName)||e.name&&rn.has(e.name))}function j(e,t){let s=()=>t();return s.requiresContainerRuntime=!0,s.checkName=e,s}async function Do(e,t={}){let s=[],n=!!t.containerRuntimeFailed;for(let r of e){if(n&&No(r)){let i=r.checkName??(r.name&&pt[r.name]?pt[r.name]:r.name&&r.name!=="check"&&r.name!=="fn"?r.name:"Container check");s.push({name:i,didPass:!0,isSkipped:!0,message:`Docker not running - skipped ${i} check`});continue}let o=await r();if(s.push(o),o.name===x&&!o.didPass&&(n=!0),!t.all&&!o.didPass&&!o.isSkipped&&!o.isWarning)break}return s}function Ro(e){let t=0,s=0,n=0,r=0;for(let o of e)o.isSkipped?n++:o.isWarning?r++:o.didPass?t++:s++;return r>0?`${t} passed, ${r} warned, ${s} failed, ${n} skipped`:`${t} passed, ${s} failed, ${n} skipped`}function gt(e){return Os(e)}function Co(e,t,s,n,r){return async(o=C)=>{try{return await o(t,A),{name:e,didPass:!0,message:s}}catch(i){return gt(i)?{name:e,didPass:!1,message:`${e} did not respond within ${A/1e3}s`,fix:r}:{name:e,didPass:!1,message:n,fix:r}}}}async function ct(e){try{return await C(e,A),!0}catch{return!1}}async function kt(){if(process.platform==="win32")try{return await C("docker ps",A),{name:x,didPass:!0,message:"Docker Desktop Linux container engine is running"}}catch{return{name:x,didPass:!1,message:"Docker is not running",fix:O.dockerDaemonDown}}let e=!!$("docker");try{return await C("docker ps",A),{name:x,didPass:!0,message:"Docker daemon is running"}}catch(s){if(gt(s))return{name:x,didPass:!1,message:"Docker daemon is not responding",fix:O.dockerDaemonDown}}let t=ls(await ct("pgrep -f com.docker.backend"));return t||(await ct("colima status")?{name:x,didPass:!0,message:"Colima (Docker runtime) is running"}:$("colima")?{name:x,didPass:!1,message:"Colima is installed but not running",fix:O.dockerDaemonDown}:await ct("podman ps")?{name:x,didPass:!0,message:"Podman is running"}:e?{name:x,didPass:!1,message:"Docker daemon is not running",fix:O.dockerDaemonDown}:{name:x,didPass:!1,message:"Docker is not running",fix:O.dockerMissing})}var ee=Co("Docker Compose","docker compose version","Docker Compose plugin available","Docker Compose plugin not found","Install Docker Compose: https://docs.docker.com/compose/install/");ee.requiresContainerRuntime=!0;ee.checkName="Docker Compose";var _o=[25,0,0],jo=[2,20,2];function ft(e){let t=e.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);return t?[Number(t[1]),Number(t[2]),Number(t[3]??0)]:null}function mt(e,t){for(let[s,n]of t.entries()){let r=e[s]??0;if(r!==n)return r>n}return!0}async function te(e=C){let t=async a=>String(await e(a,A)).trim(),s,n;try{[s,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 r=ft(s),o=ft(n);if(!r||!o)return{name:"Docker Versions",didPass:!0,isSkipped:!0,message:`Unrecognized Docker version output (engine "${s}", compose "${n}") - skipped version check`};let i=[];return mt(r,_o)||i.push(`Docker Engine ${s} (need 25.0+)`),mt(o,jo)||i.push(`Docker Compose ${n} (need 2.20.2+)`),i.length===0?{name:"Docker Versions",didPass:!0,message:`Docker Engine ${s} and Compose ${n} support generated healthchecks`}:{name:"Docker Versions",didPass:!1,message:`Docker is too old for generated healthchecks (they use start_interval):
|
|
407
407
|
${i.join(`
|
|
@@ -427,9 +427,9 @@ Dry run: nothing was changed.`)),console.log("")}function dt(e){for(let t of an(
|
|
|
427
427
|
${y.bold("Project")}`),s?t.length>0&&dt(t):console.log(`${y.gray("\u25CB")} ${y.gray("Not in a Flisk project, so project checks were skipped")}`),console.log(""),console.log(Ro(o))):(dt(o),console.log(""),o.every(a=>a.didPass||a.isSkipped||a.isWarning)&&!s&&(console.log(`${y.gray("\u25CB")} ${y.gray("Not in a Flisk project, so project checks were skipped")}`),console.log("")))}var oi=new vo("doctor").description("Check environment readiness for Flisk").option("--all","Run every check and show Machine and Project sections with a summary",!1).option("--json","Output a versioned JSON readiness report",!1).exitOverride(e=>{e.exitCode===0&&process.exit(0),oi.opts().json&&console.log(JSON.stringify(M([],!1,[{code:"USAGE",message:e.message}]))),process.exit(2)}).option("--no-ping","Skip pinging running services' /health endpoints").option("--strict","Fail warnings such as a WSL project under /mnt/c").option("--fix","Repair this project's unused Docker networks and leftover doctor probes",!1).option("--dry-run","With --fix: list the repairs without changing anything",!1).option("--scope <scope>","With --fix: project (default) or machine, which also removes unused networks of other Flisk projects","project").option("-y, --yes","With --fix: apply every repair without asking",!1).option("--ping-timeout <ms>","Per-service ping timeout in milliseconds",String(Qo)).action(async e=>{let t=Number(e.pingTimeout);if(!/^\d+$/.test(e.pingTimeout)||!Number.isSafeInteger(t)||t<=0){let f="--ping-timeout must be a positive integer number of milliseconds";e.json&&console.log(JSON.stringify(M([],!1,[{code:"USAGE",message:f}]))),console.error(f),process.exit(2);return}let s=!["project","machine"].includes(e.scope),n=e.scope!=="project"&&!e.fix;if(s||n||(e.dryRun||e.yes)&&!e.fix){let f=s?`--scope must be project or machine, got "${e.scope}"`:n?"--scope only applies with --fix":`${e.dryRun?"--dry-run":"--yes"} only applies with --fix`;e.json&&console.log(JSON.stringify(M([],!1,[{code:"USAGE",message:f}]))),console.error(f),process.exit(2);return}e.json||console.log("Flisk doctor checks your local Docker + Tilt development environment; it does not check cluster deployments.");let r=Ut();if(process.platform==="win32"){if(e.json){let f=null;try{f=await At()}catch{}console.log(JSON.stringify(M([{name:"Native Windows support",didPass:!1,message:nn,fix:"Use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md"}],!!m(),[],f,{...r,canUp:!1})))}console.error(nn),process.exit(1);return}if(r.kind==="webcontainer"){let f=M([{name:"Host",didPass:!1,message:Ce,fix:`Use a machine with Docker. Guide: ${ce}`}],!!m(),[],void 0,r);e.json&&console.log(JSON.stringify(f)),console.error(Ce),process.exit(1);return}e.json||(console.log(`
|
|
428
428
|
${y.bold("\u{1F50D} Flisk Doctor")}
|
|
429
429
|
`),console.log(`Checking environment...
|
|
430
|
-
`));let o=m(),i;if(e.fix){try{let f;if(o)try{f=Mt(o).project.name}catch{}let v=o?bs(o):[],we=await hs(f,void 0,{tiltPids:v,machine:e.scope==="machine"});i=await gs(we,{dryRun:e.dryRun,confirm:e.yes||!e.json&&process.stdin.isTTY?async N=>e.yes||await Lt({message:`Run \`${N.command}\` (${N.check}, ${N.reason})?`}):void 0})}catch(f){i=[{id:"plan-fixes",check:"Docker networks",scope:"project",command:"docker network ls",status:"failed",reason:`could not list Docker networks: ${(f instanceof Error?f.message:String(f)).split(/\r?\n/)[0]}`}]}e.json||ni(i,e.dryRun)}let a,c;try{a=await ae(o??process.cwd())}catch(f){a=null,c=f instanceof Error?f.message:String(f)}let d=[()=>a?{name:"Host Ports",didPass:!0,message:`HTTP ${a.ingressHttp}, HTTPS ${a.ingressHttps}, Postgres ${a.postgres}`}:{name:"Host Ports",didPass:!1,message:c??"Could not select host ports",fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."},()=>a?Ue(tn,void 0,[a.ingressHttp,a.ingressHttps]):{name:"Ingress Ports",didPass:!1,message:"Ingress port plan is unavailable"},kt,()=>ds(),j("Docker OS",bt),yt,j("Docker Compose",ee),j("Docker Versions",te),Oo,()=>xo(m()??process.cwd(),e.strict),()=>To(process.env,e.strict),j("Docker Network Pool",()=>Xs()),()=>ys()],l=[()=>Fo(),Io,Bo,$s,Go,()=>os(),qo,Ko,Mo,()=>Hs(),()=>ge(),()=>nt(),()=>rt(),()=>ot(),()=>it(void 0,e.strict),()=>Us(),()=>Bs(),()=>Vs(),()=>Ws(),()=>ye(),()=>Ms(),()=>zs(),()=>Ks(),()=>Ys(),Ao,async()=>{let f=m()??process.cwd(),v=Le(f)?await Ft(f):!0;return He(tn,f,void 0,v)},j("Container Resource Health",Zo),j("Crash-looping containers",()=>{let f=m()??process.cwd(),v=[];try{v=Ee(f)}catch{return{name:"Crash-looping containers",didPass:!0,isSkipped:!0,message:"Could not read .env - skipped crash-loop check"}}return as(K(),v)}),j("Tilt Resources",We)];if(e.ping){let f=o?It(o,a?.ingressHttp):a?.ingressHttp;l.push(j("Service Health",()=>ei(t,f))),l.push(j("Service Smoke",()=>ti(t,f))),l.push(j("Advertised Endpoints",()=>si(t,f)))}let u=!!o,h=[],S=[],P,k=[];if(e.json||!e.all){let f=await Ps(d,u?l:[]);P=f.checks,k=f.errors}else{let f=async(N,wn=!1)=>{let vn=N.map(ne=>{let ve=async()=>{try{return await ne()}catch(xe){return k.push({code:"INTERNAL",message:xe instanceof Error?xe.message:String(xe)}),{name:ne.checkName??"Doctor check",didPass:!1,isSkipped:!1,message:"Check failed with an internal error"}}};return ve.requiresContainerRuntime=ne.requiresContainerRuntime,ve.checkName=ne.checkName,ve});return Do(vn,{all:!!e.all,containerRuntimeFailed:wn})};h=await f(d);let v=h.some(N=>!N.didPass&&!N.isSkipped&&!N.isWarning),we=h.some(N=>N.name===x&&!N.didPass);u&&(e.all||!v)&&(S=await f(l,we)),P=[...h,...S]}if(Bt(r.kind))for(let f of P)f.name===x&&!f.didPass&&(f.fix=Ht);let p=M(an(P),u,k,a,r);i&&(p.data.actions=i),i&&ks(i)&&(p.data.ready=!1);let U=ws(p),q=p.data.ready;if(e.json){let f;try{f=Ee(m()??process.cwd())}catch(v){if(!(v instanceof Et))throw v;console.log(JSON.stringify(M([],u,[...k,{code:"ENV_UNREADABLE",message:v.message}]))),console.error(v.message),process.exit(1)}console.log(JSON.stringify(Nt(p,f)));for(let v of k)console.error(oe(v.message,f));U!==0&&process.exit(U);return}for(let f of k)console.error(`${y.red("\u2717")} Doctor check failed: ${f.message}`);ri(h,S,u,e,P);let St=Eo(u,q);console.log(`${q?y.green(y.bold("\u2713")):y.red(y.bold("\u2717"))} ${St}`),U!==0&&process.exit(U)});function ln(e){return Se(e,H)}var se=`${H[0]}.${H[1]}+`;import{execFileSync as un}from"node:child_process";import{accessSync as pn,constants as fn,readdirSync as ii}from"node:fs";import{delimiter as ai,join as V}from"node:path";var F="flisk",mn="@flisk-sh/flisk",hn="@tdk-landscape/tdk-cli-core";function gn(e=F,t=process.env){let s=t.PATH??t.Path??"";for(let n of s.split(ai)){if(!n)continue;let r=[V(n,e),V(n,`${e}.cmd`),V(n,`${e}.exe`)];for(let o of r)try{return pn(o,fn.X_OK),!0}catch{}}return!1}function
|
|
431
|
-
(${F} project writes .tdk/ and the master configs into the current folder, so it starts clean in a folder of its own. Or clone a starter: ${F} project example)`}function
|
|
430
|
+
`));let o=m(),i;if(e.fix){try{let f;if(o)try{f=Mt(o).project.name}catch{}let v=o?bs(o):[],we=await hs(f,void 0,{tiltPids:v,machine:e.scope==="machine"});i=await gs(we,{dryRun:e.dryRun,confirm:e.yes||!e.json&&process.stdin.isTTY?async N=>e.yes||await Lt({message:`Run \`${N.command}\` (${N.check}, ${N.reason})?`}):void 0})}catch(f){i=[{id:"plan-fixes",check:"Docker networks",scope:"project",command:"docker network ls",status:"failed",reason:`could not list Docker networks: ${(f instanceof Error?f.message:String(f)).split(/\r?\n/)[0]}`}]}e.json||ni(i,e.dryRun)}let a,c;try{a=await ae(o??process.cwd())}catch(f){a=null,c=f instanceof Error?f.message:String(f)}let d=[()=>a?{name:"Host Ports",didPass:!0,message:`HTTP ${a.ingressHttp}, HTTPS ${a.ingressHttps}, Postgres ${a.postgres}`}:{name:"Host Ports",didPass:!1,message:c??"Could not select host ports",fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."},()=>a?Ue(tn,void 0,[a.ingressHttp,a.ingressHttps]):{name:"Ingress Ports",didPass:!1,message:"Ingress port plan is unavailable"},kt,()=>ds(),j("Docker OS",bt),yt,j("Docker Compose",ee),j("Docker Versions",te),Oo,()=>xo(m()??process.cwd(),e.strict),()=>To(process.env,e.strict),j("Docker Network Pool",()=>Xs()),()=>ys()],l=[()=>Fo(),Io,Bo,$s,Go,()=>os(),qo,Ko,Mo,()=>Hs(),()=>ge(),()=>nt(),()=>rt(),()=>ot(),()=>it(void 0,e.strict),()=>Us(),()=>Bs(),()=>Vs(),()=>Ws(),()=>ye(),()=>Ms(),()=>zs(),()=>Ks(),()=>Ys(),Ao,async()=>{let f=m()??process.cwd(),v=Le(f)?await Ft(f):!0;return He(tn,f,void 0,v)},j("Container Resource Health",Zo),j("Crash-looping containers",()=>{let f=m()??process.cwd(),v=[];try{v=Ee(f)}catch{return{name:"Crash-looping containers",didPass:!0,isSkipped:!0,message:"Could not read .env - skipped crash-loop check"}}return as(K(),v)}),j("Tilt Resources",We)];if(e.ping){let f=o?It(o,a?.ingressHttp):a?.ingressHttp;l.push(j("Service Health",()=>ei(t,f))),l.push(j("Service Smoke",()=>ti(t,f))),l.push(j("Advertised Endpoints",()=>si(t,f)))}let u=!!o,h=[],S=[],P,k=[];if(e.json||!e.all){let f=await Ps(d,u?l:[]);P=f.checks,k=f.errors}else{let f=async(N,wn=!1)=>{let vn=N.map(ne=>{let ve=async()=>{try{return await ne()}catch(xe){return k.push({code:"INTERNAL",message:xe instanceof Error?xe.message:String(xe)}),{name:ne.checkName??"Doctor check",didPass:!1,isSkipped:!1,message:"Check failed with an internal error"}}};return ve.requiresContainerRuntime=ne.requiresContainerRuntime,ve.checkName=ne.checkName,ve});return Do(vn,{all:!!e.all,containerRuntimeFailed:wn})};h=await f(d);let v=h.some(N=>!N.didPass&&!N.isSkipped&&!N.isWarning),we=h.some(N=>N.name===x&&!N.didPass);u&&(e.all||!v)&&(S=await f(l,we)),P=[...h,...S]}if(Bt(r.kind))for(let f of P)f.name===x&&!f.didPass&&(f.fix=Ht);let p=M(an(P),u,k,a,r);i&&(p.data.actions=i),i&&ks(i)&&(p.data.ready=!1);let U=ws(p),q=p.data.ready;if(e.json){let f;try{f=Ee(m()??process.cwd())}catch(v){if(!(v instanceof Et))throw v;console.log(JSON.stringify(M([],u,[...k,{code:"ENV_UNREADABLE",message:v.message}]))),console.error(v.message),process.exit(1)}console.log(JSON.stringify(Nt(p,f)));for(let v of k)console.error(oe(v.message,f));U!==0&&process.exit(U);return}for(let f of k)console.error(`${y.red("\u2717")} Doctor check failed: ${f.message}`);ri(h,S,u,e,P);let St=Eo(u,q);console.log(`${q?y.green(y.bold("\u2713")):y.red(y.bold("\u2717"))} ${St}`),U!==0&&process.exit(U)});function ln(e){return Se(e,H)}var se=`${H[0]}.${H[1]}+`;import{execFileSync as un}from"node:child_process";import{accessSync as pn,constants as fn,readdirSync as ii}from"node:fs";import{delimiter as ai,join as V}from"node:path";var F="flisk",mn="@flisk-sh/flisk",ci="https://github.com/flisk-sh/flisk",hn="@tdk-landscape/tdk-cli-core";function gn(e=F,t=process.env){let s=t.PATH??t.Path??"";for(let n of s.split(ai)){if(!n)continue;let r=[V(n,e),V(n,`${e}.cmd`),V(n,`${e}.exe`)];for(let o of r)try{return pn(o,fn.X_OK),!0}catch{}}return!1}function di(e=process.env){let t=e.HOME??e.USERPROFILE??"";if(!t)return"flisk-workspace";let s=V(t,"Documents");try{return pn(s,fn.F_OK),V(s,"flisk")}catch{return V(t,"flisk")}}function li(e){try{return ii(e).every(t=>t.startsWith("."))}catch{return!0}}function kn(e=process.env,t=process.cwd()){if(!gn(F,e))return`The \`${F}\` command is not on PATH (this run is not a global install). Install it with \`npm install -g ${mn}\`, then run \`${F} project --yes\`. If npm reports EEXIST for \`flisk\`, the old package still owns that command: run \`npm uninstall -g ${hn}\` first. The current release is published from ${ci}.`;if(li(t))return`Next: ${F} project --yes`;let s=di(e);return`Next: mkdir -p ${s} && cd ${s} && ${F} project --yes
|
|
431
|
+
(${F} project writes .tdk/ and the master configs into the current folder, so it starts clean in a folder of its own. Or clone a starter: ${F} project example)`}function sd(e=process.env){if(gn(F,e))return"present";let t=e.npm_execpath?.includes("bun")?"bun":"npm",s=t==="bun"?"bun remove -g":"npm uninstall -g";try{un(s,[hn],{stdio:"ignore",timeout:12e4})}catch{}try{return un(t,["install","-g",mn],{stdio:"inherit",timeout:3e5}),"installed"}catch{return"failed"}}var fi=["docker","compose","tilt"],Sn=["node","bun","ports"],Pn=["node",...fi,"bun","ports"];function mi(e,t){return{id:e,ok:t.didPass||!!t.isSkipped,message:t.message,fix:t.fix}}function bn(e){let[t=0,s=0]=String(e).split(".").map(n=>Number.parseInt(n,10));return!Number.isFinite(t)||!Number.isFinite(s)||t<22||t===22&&s<12}async function Pe(e,t,s){try{return mi(e,await t())}catch{return{id:e,ok:!1,message:s}}}function hi(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 gi(e){try{return b(e).some(t=>t.config?.featuresEnabled?.includes("prisma")??!1)}catch{return!1}}async function ki(e={}){let t=e.cwd??process.cwd(),s=e.scope??"runtime",n=m(t),r=!!n,o=[],i=process.versions.node;o.push({id:"node",ok:!bn(i),message:i,fix:bn(i)?`Install Node.js 22.12+ (current: ${i}). https://nodejs.org`:void 0}),s==="runtime"&&(o.push(await Pe("docker",kt,"Docker daemon is not running")),o.push(await Pe("compose",async()=>{let[p,L]=await Promise.all([ee(),te()]);return p.didPass?hi(L):p},"Docker Engine or Compose version check failed")),o.push(await Pe("tilt",yt,"Tilt CLI not found")));let a=n?de(b(n)):!0,c=!1,d=a?$("bun"):void 0;if(d)try{let p=yn(d,["--version"],{encoding:"utf-8",timeout:3e3}).trim();c=ln(p)}catch{}o.push(a?{id:"bun",ok:c,message:c?`Bun ${se} is available on PATH`:`Bun ${se} not found on PATH`,fix:c?void 0:"curl -fsSL https://bun.sh/install | bash"}:{id:"bun",ok:!0,message:"Bun not needed: no generated JS services"});try{let p=await ae(n??t,s==="scaffold"?{inspectDocker:!1}:{});o.push({id:"ports",ok:!0,message:`HTTP ${p.ingressHttp}, HTTPS ${p.ingressHttps}, Postgres ${p.postgres}`})}catch(p){o.push({id:"ports",ok:!1,message:p instanceof Error?p.message:String(p),fix:"Set TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT to available host ports."})}if(n&&s==="runtime"){let p=await Pe("nats",()=>ye(n),"NATS broker check failed");if(p.ok||o.push(p),gi(n)){let L=!1;try{let U=JSON.parse(ui(pi(n,".tdk",_),"utf-8")),q=String(U?.project?.name??"").replace(/-/g,"_");q&&(L=yn($("docker")??"docker",["ps","--filter",`label=com.docker.compose.project=${q}`,"--filter","label=com.docker.compose.service=postgres","--filter","health=healthy","--format","{{.Names}}"],{encoding:"utf-8",timeout:3e3}).trim().length>0)}catch{}L||o.push({id:"prisma",ok:!1,message:"A Prisma resource is configured, but the project Postgres service is not healthy",fix:"Run `flisk up` to start the bundled Postgres, then check `flisk doctor`."})}}let l=o.filter(p=>!p.ok).slice(0,8),u=s==="scaffold"?Sn:Pn,h=l.some(p=>u.includes(p.id)),S=l.some(p=>p.id==="bun"),P=l.length?h?s==="scaffold"?S?`Project setup blocked. Bun ${se} must be installed on PATH.
|
|
432
432
|
Fix the machine checks below.`:"Project setup blocked. Fix the machine checks below.":S?`Cold start blocked. Bun ${se} must be installed on PATH.
|
|
433
433
|
Prisma/NATS configuration is project-specific and generated after \`flisk project\`. Fix the machine checks below.`:"Cold start blocked. Bun/Prisma/NATS are not the first failure.\nThey are generated after `flisk project`. Fix the machine checks below.":"Machine is ready. Project wiring is not.":"",k=l.length?"":r?"Environment ready for Flisk":`This machine is ready for Flisk.
|
|
434
|
-
${kn()}`;return{ok:l.length===0,inProject:r,items:l,header:P,footer:k}}function
|
|
435
|
-
`)}async function
|
|
434
|
+
${kn()}`;return{ok:l.length===0,inProject:r,items:l,header:P,footer:k}}function yi(e,t={}){let s=[e.header];for(let n of e.items)s.push(`FAIL ${n.id.padEnd(7)} ${n.message}`),n.fix&&s.push(` ${n.fix}`);return e.footer&&(t.includeSuccessFooter??!0)&&s.push(e.footer),s.filter(Boolean).join(`
|
|
435
|
+
`)}async function kd(e={}){let t=e.scope??"runtime",s=await ki({scope:t}),n=t==="scaffold"?Sn:Pn;s.items.some(o=>n.includes(o.id))&&(console.error(yi(s)),process.exit(1))}function yd(e=$){return{hasDockerCli:!!e("docker"),hasTiltCli:!!e("tilt")}}function bd(e){let t=[];return e.hasDockerCli||t.push(`Docker is not installed. ${O.dockerMissing}`),e.hasTiltCli||t.push(`Tilt is not installed. ${O.tiltMissing}`),t.push("Docker and Tilt are only needed to start the stack: start them, then run `flisk doctor` (readiness) and `flisk up`."),t}export{jr as a,Or as b,ga as c,Ta as d,Ea as e,G as f,Vr as g,La as h,Ms as i,ho as j,Ce as k,Ht as l,Ut as m,Bt as n,_e as o,le as p,Ti as q,Jt as r,zt as s,Ie as t,Fe as u,Me as v,Yi as w,Xi as x,Zi as y,ze as z,mr as A,kr as B,na as C,lc as D,uc as E,en as F,oi as G,hn as H,sd as I,fi as J,Sn as K,Pn as L,bn as M,hi as N,ki as O,yi as P,kd as Q,yd as R,bd as S};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
|
|
2
|
-
import{a as O}from"./chunk-KGKKDD4K.js";import{b as N,c as pe,d as q,i as D,j as Y,n as J,o as I,q as C}from"./chunk-
|
|
2
|
+
import{a as O}from"./chunk-KGKKDD4K.js";import{b as N,c as pe,d as q,i as D,j as Y,n as J,o as I,q as C}from"./chunk-3SPYAO2E.js";import{H as z,J as G,L as E,Na as re,Ra as ae,Sa as se,Ua as ie,V as T,W as B,Wa as ce,Xa as le,Ya as de,aa as f,ba as y,ca as t,d as x,ja as ne,k as U,ka as W,la as V,m as P,s as F}from"./chunk-GW7N23FV.js";import{b as p}from"./chunk-CF46CD6R.js";import{execFileSync as ye}from"node:child_process";import{cpSync as be,existsSync as b,readdirSync as Se,readFileSync as K,writeFileSync as je}from"node:fs";import{basename as _e,dirname as we,join as j,resolve as M}from"node:path";import{cwd as ue}from"node:process";import{fileURLToPath as xe}from"node:url";import{Command as Pe}from"commander";var he="-y, --yes",ke="Skip prompts and confirmations; use defaults";function fe(e,o=ke){return e.option(he,o,!1)}async function ve(e,o=!0){let c=await I({message:e,initial:o});return c||T(),c}function Ne(e,o=1){e.valid||E(e.error??"Validation failed",o)}function De(e,o,c,a){return e.dryRun?(a?a():(console.log(`Dry run - ${o}`),console.log(`Would run: ${c}`)),!0):!1}async function Je(e,o){return await ve(e,!0)?!0:(o&&o(),!1)}var L=new Map;function me(e){e!==void 0?L.delete(e):L.clear()}function Ue(e=!1){let o=F(),c=o??"";if(!e){let r=L.get(c);if(r)return r}let{resources:a,problems:l}=o?ae(o):{resources:ie(),problems:[]},d=de(a),n=le(a);se(l);let g=a.filter(r=>!r.stack),m=new Map;for(let r of a)if(r.stack){let _=m.get(r.stack)||[];_.push(r),m.set(r.stack,_)}let k={resources:a,problems:l,stacks:d,stackNames:n,unassignedResources:g,resourcesByStack:m};return L.set(c,k),k}var A={proxy:{name:"proxy",description:"Traefik reverse proxy and API gateway for routing all services",category:"core",phase:"pre_alpha",enabled_by_default:!0,dependsOn:[]},verdaccio:{name:"verdaccio",description:"Verdaccio npm registry for package management and local publishing (Premium - requires TDK_LICENSE_KEY)",category:"premium",phase:"pre_alpha",enabled_by_default:!1,dependsOn:[]},[x]:{name:x,description:"PostgreSQL database for data persistence and SQL operations",category:"core",phase:"pre_alpha",enabled_by_default:!0,dependsOn:[]},monitoring:{name:"monitoring",description:"SigNoz or SkyWalking observability platform for monitoring and tracing",category:"optional",phase:"pre_alpha",enabled_by_default:!1,dependsOn:[x]},elk:{name:"elk",description:"Elasticsearch, Logstash, Kibana stack for log aggregation and analysis",category:"optional",phase:"pre_alpha",enabled_by_default:!1,dependsOn:[]},debezium:{name:"debezium",description:"Change Data Capture for real-time data streaming from databases",category:"optional",phase:"pre_alpha",enabled_by_default:!1,dependsOn:[x]},"golden-image":{name:"golden-image",description:"Pre-built Docker image layer for faster builds and smaller deployments",category:"optional",phase:"pre_alpha",enabled_by_default:!0,dependsOn:[]}};function H(e,o){try{return ce(e,o)}catch{return[]}}function Ee(e){return new Set([...e.phases.pre_alpha.enabledStacks,...e.phases.alpha.enabledStacks,...e.phases.beta.enabledStacks,...e.phases.out_of_scope.enabledStacks])}function Q(e,o){let c=Ee(e),a=o.filter(l=>!c.has(l));return a.length===0?(e.phases.pre_alpha.enabledStacks=Array.from(new Set(e.phases.pre_alpha.enabledStacks)),[]):(e.phases.pre_alpha.enabledStacks=Array.from(new Set([...e.phases.pre_alpha.enabledStacks,...a])),a)}function ft(e,o){let c=j(e,".tdk",U);if(!b(c))return[];let a=D(e),l=Q(a,H(e,o));return l.length>0&&N(c,a),l}function Ce(){return Object.values(A).filter(e=>e.enabled_by_default&&e.category==="core").map(e=>e.name)}function Oe(e,o){return o||(O[e]?.repo.split("/").pop()??e).replace(/\.git$/,"")}async function Ae(e,o,c){let a=O[e];if(!a){console.log(p.red(`
|
|
3
3
|
\u274C Unknown template: "${e}"`)),console.log(p.yellow(`
|
|
4
4
|
Available templates:`));for(let[n,g]of Object.entries(O))console.log(` ${p.cyan(n)} ${p.gray(`- ${g.description}`)}`);console.log(p.gray("\nOr run `flisk project` with no template for a blank project.")),process.exit(1)}let l=Oe(e,o);re(l)||z.invalidPath(l).exit();let d=M(ue(),l);b(d)&&Se(d).length>0&&z.directoryExists(d).exit(),B(`Cloning template: ${e}`),t(`${a.description}
|
|
5
5
|
`,0),t(`Source: ${a.bundledPath?"bundled Flisk example":a.repo}`,0),t(`Destination: ${d}
|
|
6
6
|
`,0);try{if(a.bundledPath){let n=M(we(xe(new URL("../dist/commands/project.js",import.meta.url).href)),"../../../");be(M(n,a.bundledPath),d,{recursive:!0});let g=_e(d).replace(/-/g,"_");for(let m of["services/platform/messaging/docker-compose.yml","services/shop/orders-api/service.json","services/shop/orders-api/src/index.ts","services/shop/orders-worker/service.json","services/shop/orders-worker/src/index.ts"]){let k=j(d,m),r=K(k,"utf-8");je(k,r.replaceAll("tdk_example",g))}}else ye("git",["clone",a.repo,d],{stdio:"inherit"})}catch{E(a.bundledPath?"Bundled example copy failed. Reinstall the Flisk CLI package and try again.":"git clone failed. Check you have git installed and network access.")}me(),console.log(p.green(`
|
|
7
7
|
\u2705 Cloned "${e}" into ${l}/`)),t(`
|
|
8
8
|
Next steps:`,0),t(`1. cd ${l}`),t("2. flisk doctor # check Docker/Tilt are ready"),t("3. flisk up # start the stack"),t(`
|
|
9
|
-
Runtime readiness:`,0);for(let n of c)t(n,0)}var R={version:"1.0",project:{name:"",version:"1.0.0"},phases:{pre_alpha:{name:"Pre-Alpha",description:"Core infrastructure and MVP services",enabledStacks:Ce()},alpha:{name:"Alpha",description:"Essential business services",enabledStacks:[]},beta:{name:"Beta",description:"Extended features",enabledStacks:[]},out_of_scope:{name:"Out of Scope",description:"Future releases",enabledStacks:[]}},optional_infra:{monitoring:!1,elk:!1,debezium:!1,golden_image:!0,verdaccio:!1},discovery:{paths:["services/*/*"]},overrides:{}},mt=fe(new Pe("project")).description("Initialize or validate project-level master configuration").argument("[template]",`Clone a starter example instead of a blank project (${Object.keys(O).join(", ")})`).option("--path <dir>","Directory to clone the template into (default: the template's repo name)").option("--check","Check if master configs exist and are in sync").option("--force","Overwrite existing configuration (dangerous)").option("--config-file <path>","Load project config from existing JSON file").action(async(e,o)=>{let{assertMachineReadyOrExit:c,detectRuntimePrerequisites:a,formatRuntimeNextSteps:l}=await import("./cold-preflight-
|
|
9
|
+
Runtime readiness:`,0);for(let n of c)t(n,0)}var R={version:"1.0",project:{name:"",version:"1.0.0"},phases:{pre_alpha:{name:"Pre-Alpha",description:"Core infrastructure and MVP services",enabledStacks:Ce()},alpha:{name:"Alpha",description:"Essential business services",enabledStacks:[]},beta:{name:"Beta",description:"Extended features",enabledStacks:[]},out_of_scope:{name:"Out of Scope",description:"Future releases",enabledStacks:[]}},optional_infra:{monitoring:!1,elk:!1,debezium:!1,golden_image:!0,verdaccio:!1},discovery:{paths:["services/*/*"]},overrides:{}},mt=fe(new Pe("project")).description("Initialize or validate project-level master configuration").argument("[template]",`Clone a starter example instead of a blank project (${Object.keys(O).join(", ")})`).option("--path <dir>","Directory to clone the template into (default: the template's repo name)").option("--check","Check if master configs exist and are in sync").option("--force","Overwrite existing configuration (dangerous)").option("--config-file <path>","Load project config from existing JSON file").action(async(e,o)=>{let{assertMachineReadyOrExit:c,detectRuntimePrerequisites:a,formatRuntimeNextSteps:l}=await import("./cold-preflight-WR2M53Z6.js");await c({scope:"scaffold"});let d=l(a());if(e){await G(async()=>Ae(e,o.path,d));return}await G(async()=>{let n=F();n||(n=ue(),y(`\u{1F680} Initializing new Flisk project...
|
|
10
10
|
`),t(`Location: ${n}
|
|
11
11
|
`,0));let g=j(n,".tdk"),m=j(g,U);if(o.check){let i=P.every(u=>b(j(n,".tdk",".tdk-out",u))),h=b(m);if(i&&h){let u=D(n);f("Project configuration is valid"),t(`Project: ${u.project.name}`,3),t(`Phases: ${Object.keys(u.phases).join(", ")}`,3),process.exit(0)}else{if(console.log(p.yellow("\u26A0\uFE0F Project configuration incomplete:")),h||t(".tdk/project.json (not found)",3),!i)for(let u of P.filter(S=>!b(j(n,".tdk/.tdk-out",S))))t(`.tdk/.tdk-out/${u} (not found)`,3);t("Run `flisk project` to create them."),process.exit(1)}}B("Project Configuration"),t(`Project root: ${n}
|
|
12
12
|
`,0),b(g)||(pe(g),f("Created: .tdk/ directory"));let k=b(m);if(k&&!o.force){f(".tdk/project.json exists");let i=JSON.parse(K(m,"utf-8")),h=D(n),u=H(n),S=Q(h,u);if((S.length>0||!i.phases)&&N(m,h),S.length>0&&t(`Auto-enabled discovered service stacks: ${S.join(", ")}`,0),y(`
|