@flisk-sh/flisk 1.3.192 → 1.3.198

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +4 -4
  3. package/cli/dist/cli.js +33 -9
  4. package/cli/dist/commands/help.js +1 -0
  5. package/cli/dist/commands/mcp.js +4 -1
  6. package/cli/dist/commands/open.js +104 -0
  7. package/cli/dist/commands/registry.js +2 -0
  8. package/cli/dist/commands/ui.js +1 -1
  9. package/cli/dist/commands/upgrade.js +2 -3
  10. package/cli/dist/mcp/tools.js +5 -2
  11. package/cli/dist/utils/cli-command.js +11 -2
  12. package/cli/dist/utils/doctor-fix.js +1 -1
  13. package/cli/dist/utils/one-command.js +66 -19
  14. package/cli/dist/utils/service-urls.js +6 -3
  15. package/cli/dist-bundle/chunk-CF46CD6R.js +6 -0
  16. package/cli/dist-bundle/chunk-DTIHDMED.js +5 -0
  17. package/cli/dist-bundle/chunk-DWHA5YKT.js +435 -0
  18. package/cli/dist-bundle/chunk-KBGQ4NJE.js +52 -0
  19. package/cli/dist-bundle/chunk-SB5WAMSU.js +5 -0
  20. package/cli/dist-bundle/chunk-US4D5GJJ.js +21 -0
  21. package/cli/dist-bundle/chunk-WPQOTHB5.js +4 -0
  22. package/cli/dist-bundle/{chunk-QR6O2A7L.js → chunk-YUARXGF4.js} +2 -2
  23. package/cli/dist-bundle/cli.js +251 -257
  24. package/cli/dist-bundle/cold-preflight-5TVSNLIV.js +2 -0
  25. package/cli/dist-bundle/one-command-TKXMWXCK.js +4 -0
  26. package/cli/dist-bundle/open-5SUD6LKB.js +2 -0
  27. package/cli/dist-bundle/project-5GTJYFAE.js +2 -0
  28. package/cli/dist-bundle/spinner-YLB6FYQH.js +2 -0
  29. package/cli/package.json +1 -1
  30. package/package.json +1 -1
  31. package/cli/dist-bundle/chunk-GOEBYLFN.js +0 -2
  32. package/cli/dist-bundle/chunk-RHSMS45X.js +0 -438
  33. package/cli/dist-bundle/chunk-XYFVXSEO.js +0 -75
  34. package/cli/dist-bundle/cold-preflight-ZJAU3E7K.js +0 -2
  35. package/cli/dist-bundle/one-command-A4R272U3.js +0 -4
  36. package/cli/dist-bundle/project-FOAR7E55.js +0 -2
  37. package/cli/dist-bundle/url-actions-D6ROTHZG.js +0 -2
@@ -0,0 +1,52 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{c as z,e as Q}from"./chunk-42IVF3YT.js";import{Fa as J,Ga as B,Qa as O,Ta as Y,cb as X,d as v,e as k,g as q,ga as L,h as x,i as P,j as F,k as W,l as A,p as d,q as N}from"./chunk-US4D5GJJ.js";import{b as V}from"./chunk-CF46CD6R.js";import{a as $}from"./chunk-6EA4DGCY.js";import{appendFileSync as le,existsSync as C,mkdirSync as fe,readFileSync as de,writeFileSync as Z}from"node:fs";import{dirname as pe,resolve as w}from"node:path";function ft(t,e,n){for(let[r,s]of e.entries())console.log(V.blue(`${s.emoji} ${s.description}...`)),s.type==="json"?me(t,s.filename,s.content):he(t,s.filename,String(s.content)),n&&n(s,r,e.length)}function ue(t,e,n=2){let r=`${JSON.stringify(e,null,n)}
3
+ `;Z(t,r,"utf-8")}function me(t,e,n,r=2){let s=w(t,e);ue(s,n,r)}function U(t,e){Z(t,e,"utf-8")}function he(t,e,n){let r=w(t,e);U(r,n)}function dt(t){C(t)||fe(t,{recursive:!0})}var ge=[".env",".tdk/.tdk-out/",".tdk/.project-id",".tdk/smoke/","node_modules/"];function Se(t){let e=w(t,".gitignore"),n=C(e)?de(e,"utf-8"):"",r=new Set(n.split(`
4
+ `).map(f=>f.trim().replace(/\/$/,""))),s=ge.filter(f=>!r.has(f.replace(/\/$/,"")));if(s.length===0)return[];let c=n&&!n.endsWith(`
5
+ `)?`
6
+ `:"";return le(e,`${c}${n?`
7
+ # Flisk (generated files and secrets)
8
+ `:`# Flisk (generated files and secrets)
9
+ `}${s.join(`
10
+ `)}
11
+ `),s}function ke(t){let e=w(t);for(;;){if(C(w(e,".git")))return!0;let n=pe(e);if(n===e)return!1;e=n}}function pt(t){if(ke(t))try{Se(t);return}catch(e){let n=e instanceof Error?e.message:String(e);return`Could not add .tdk/smoke/ to ${w(t,".gitignore")}: ${n}. Git may track the smoke response records.`}}import*as o from"node:fs";import*as i from"node:path";import{fileURLToPath as Oe}from"node:url";import _ from"handlebars";var ye="1.0.0",Te={runtime:"bun",bundler:"vite",language:"typescript",framework:"hono",database:"postgresql",orm:"prisma",messaging:"nats",linting:"biome",testing:"vitest"},Ee={frontend:{base:d.frontend.base,range:d.frontend.range,start:d.frontend.min,end:d.frontend.max},backend:{base:d.backend.base,range:d.backend.range,start:d.backend.min,end:d.backend.max},health:{base:d.health.base,range:d.health.range,start:d.health.min,end:d.health.max},worker:{base:d.worker.base,range:d.worker.range,start:d.worker.min,end:d.worker.max},migrator:{base:d.migrator.base,range:d.migrator.range,start:d.migrator.min,end:d.migrator.max},tiltUi:N.tiltUi,traefik:N.traefik},_e={path:"/health",live:"/health/live",ready:"/health/ready",timeout:30,interval:5},be={frontend:"-frontend",backend:"-backend",worker:"-worker",migrator:"-migrator",library:"-lib",sdk:"-sdk",validSeparators:["-","_"],maxLength:63,minLength:3},ve={entrypoint:"web",network:"traefik-public",defaultHost:"localhost",appHost:"app.localhost",apiHost:"api.localhost",appSubdomainPrefix:"app",apiSubdomainPrefix:"api",defaultPort:8080,tlsEnabled:!1,entrypoints:["web"],middlewares:[],tls:{enabled:!1},healthcheckPath:"/health",healthcheckInterval:"10s",healthcheckTimeout:"5s",frontendPriorityBase:100},we=["node_modules","dist","build",".git",".prisma",".turbo","coverage","tmp","temp","__tests__","test","tests"],xe={frontend:{suffix:"-frontend",portRange:"3000-3999"},backend:{suffix:"-backend",portRange:"4000-4999"},library:{suffix:"-library",portRange:null},sdk:{suffix:"-sdk",portRange:"3000-9999"},migrator:{suffix:"-migrator",portRange:"7000-7999"},worker:{suffix:"-worker",portRange:"6000-6999"}},Ae={prisma:"Database ORM with migrations",nats:"Event streaming via NATS",redis:"Caching layer",infisical:"Secrets management",vitest:"Testing framework",traefik:"HTTP routing",websocket:"Real-time connections",graphql:"GraphQL support",grpc:"gRPC support",viteNode:"Vite Node runtime",maintenance:"Maintenance mode"},Re={services:"services/product",sharedPlatform:"shared-platform-engineering",sharedProduct:"shared-product-engineering",sharedDdd:"shared-ddd-layers"},je={scanIntervalSeconds:5,maxManifestsPerRoot:50,servicePatterns:["services/product/*","services/platform/*"]},De={dockerfile:"Dockerfile",context:"."},Ie={backend:{command:"bun",args:["run","dev"],env:{NODE_ENV:"development"}},frontend:{command:"bun",args:["run","dev"],env:{NODE_ENV:"development"}}},g={version:ye,tech:Te,ports:Ee,health:_e,naming:be,traefik:ve,filewatchIgnores:we,serviceTypes:xe,features:Ae,paths:Re,discovery:je,docker:De,runtime:Ie};import{existsSync as $e,lstatSync as Pe}from"node:fs";import{isAbsolute as ee,normalize as j,relative as Fe,sep as te}from"node:path";var yt=[`${x}/**`,".tdk/.tdk-out/**","Tiltfile","TILT_*.star",k,`${A} (create only)`,"shared-platform-engineering/docker-templates/**","services/platform/database-management/docker-compose.yml","product_autogenerated_resource_manifests/**","product_autogenerated_services_list/**"];function Ne(t){let e=j(t).split(te).join("/");return ee(t)||e===".."||e.startsWith("../")?!1:e.split("/").includes(x)||e.startsWith(".tdk/.tdk-out/")||e==="shared-platform-engineering/docker-templates"||e.startsWith("shared-platform-engineering/docker-templates/")||e.startsWith("product_autogenerated_resource_manifests/")||e.startsWith("product_autogenerated_services_list/")?!0:e==="Tiltfile"||/^TILT_[^/]+\.star$/.test(e)||e===k||e===A||e==="services/platform/database-management/docker-compose.yml"}function E(t,e){let n=ee(e)?j(e):j(`${t}/${e}`),r=Fe(t,n).split(te).join("/");if(!Ne(r))throw new Error(`Refusing to write outside Flisk's generated-file allowlist: ${r}`);let s=t;for(let c of r.split("/"))if(s=j(`${s}/${c}`),$e(s)&&Pe(s).isSymbolicLink())throw new Error(`Refusing to write through a symbolic link in generated path: ${r}`);return n}var Le={[v]:{name:v,description:"Generate and load the stack-level PostgreSQL docker-compose file",generatedFiles:["services/platform/database-management/docker-compose.yml"]}};function ne(t,e){return Le[e]?["pre_alpha","alpha","beta"].some(n=>t[n]?.enabledStacks?.includes(e)):!1}var Ce=Oe(new URL("../dist/generator/template-engine.js",import.meta.url).href),G=i.dirname(Ce);function R(t){let e=[i.join(G,"..","..","templates"),i.join(G,"..","templates"),i.join(G,"..","..","..","templates"),i.join(process.cwd(),"node_modules","@flisk-sh","flisk","templates"),i.join(i.dirname(process.execPath),"tdk-cli","cli","templates")],n=[];for(let r of e){let s=i.join(r,t);n.push(s);try{return o.readFileSync(s,"utf-8")}catch{}}throw new Error(`Failed to load template ${t} from any of these paths: ${n.join(", ")}`)}var M=null;function Ue(){return M||(M={[k]:R(".tiltignore.hbs"),[F]:R("TILT_RESOURCE_DEFAULTS.star.hbs"),[P]:R("TILT_TECH_STACK.star.hbs"),Tiltfile:R("Tiltfile.hbs"),"spec.master":R("spec.master.hbs")}),M}var Ge={proxy:"Traefik reverse proxy",verdaccio:"Private npm registry","database-management":"PostgreSQL database"},Me={monitoring:"Signoz, SkyWalking (RAM intensive)",elk:"Elasticsearch/Logstash/Kibana",debezium:"CDC with Kafka/Zookeeper",golden_image:"Golden image rebuild (one-time)",verdaccio:"Premium local npm registry"},se=["TILT_TECH_STACK.star","TILT_RESOURCE_DEFAULTS.star","spec.master","Tiltfile",".tiltignore"],D=class{templatesDir;constructor(e){let n=$("node:url").fileURLToPath(new URL("../dist/generator",import.meta.url))||i.dirname(new URL(new URL("../dist/generator/template-engine.js",import.meta.url).href).pathname);this.templatesDir=e||i.join(n,"..","..","templates"),this.registerHelpers()}quoteStarlarkString(e){return`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}formatStarlarkValue(e){return e==null?"None":typeof e=="string"?this.quoteStarlarkString(e):typeof e=="boolean"?e?"True":"False":typeof e=="number"?String(e):Array.isArray(e)?`[${e.map(r=>this.formatStarlarkValue(r)).join(", ")}]`:typeof e=="object"?`{${Object.entries(e).map(([r,s])=>`${this.quoteStarlarkString(r)}: ${this.formatStarlarkValue(s)}`).join(", ")}}`:String(e)}registerHelpers(){_.registerHelper("starlark",e=>new _.SafeString(this.formatStarlarkValue(e))),_.registerHelper("starlarkArray",e=>{if(!Array.isArray(e))return new _.SafeString("[]");let n=e.map(r=>this.formatStarlarkValue(r));return new _.SafeString(`[${n.join(", ")}]`)}),_.registerHelper("json",e=>JSON.stringify(e))}buildContext(e){return{version:g.version,tech:g.tech,ports:g.ports,health:g.health,naming:g.naming,traefik:g.traefik,filewatchIgnores:[...g.filewatchIgnores],serviceTypes:g.serviceTypes,paths:g.paths,discovery:{scanIntervalSeconds:g.discovery.scanIntervalSeconds,maxManifestsPerRoot:g.discovery.maxManifestsPerRoot,paths:e.discovery.paths},docker:g.docker,runtime:g.runtime,project:e.project,phases:Ke(e.phases),alwaysEnabledInfra:e.always_enabled_infra??[...X],optionalInfra:e.optional_infra,serviceDescriptions:Ge,infraDescriptions:Me}}loadTemplate(e){let n=i.join(this.templatesDir,`${e}.hbs`),r=o.existsSync(n)?o.readFileSync(n,"utf-8"):Ue()[e];if(!r)throw new Error(`Template not found: ${n}`);return _.compile(r)}generateTechStack(e){return this.loadTemplate(P)(e)}generateServiceDefaults(e){return this.loadTemplate(F)(e)}generateSpecMaster(e){return this.loadTemplate("spec.master")(e)}generateTiltfile(e){return this.loadTemplate("Tiltfile")(e)}generateTiltIgnore(e){return this.loadTemplate(".tiltignore")(e)}generateAll(e){let n=this.buildContext(e);return{"TILT_TECH_STACK.star":this.generateTechStack(n),"TILT_RESOURCE_DEFAULTS.star":this.generateServiceDefaults(n),"spec.master":this.generateSpecMaster(n),Tiltfile:this.generateTiltfile(n),".tiltignore":this.generateTiltIgnore(n)}}};function Ke(t){let e={...t};for(let n of Object.keys(e))e[n]={...e[n],enabledStacks:Array.from(new Set(e[n].enabledStacks))};return e}function He(t){return t.replace(/-/g,"_")}function Ve(t){let e=He(t.project.name||"tdk_project");return`###############################################################################
12
+ # SYSTEM-GENERATED - DO NOT EDIT
13
+ # Stack feature: database-management
14
+ # Source: .tdk/project.json phases.*.enabledStacks includes "database-management"
15
+ # Regenerate with: flisk config regenerate
16
+ ###############################################################################
17
+
18
+ services:
19
+ postgres:
20
+ image: postgres:16-alpine
21
+ container_name: ${e}_postgres
22
+ restart: unless-stopped
23
+ environment:
24
+ POSTGRES_USER: ${e}
25
+ POSTGRES_PASSWORD: \${DB_PASSWORD}
26
+ POSTGRES_DB: postgres
27
+ ports:
28
+ - "\${TDK_BIND_ADDRESS:-127.0.0.1}:\${TDK_POSTGRES_PORT:-15432}:5432"
29
+ volumes:
30
+ - ${e}_postgres_data:/var/lib/postgresql/data
31
+ networks:
32
+ - database
33
+ healthcheck:
34
+ test: ["CMD-SHELL", "pg_isready -U ${e} -d postgres"]
35
+ interval: 5s
36
+ timeout: 5s
37
+ retries: 20
38
+
39
+ networks:
40
+ database:
41
+ name: ${e}_database
42
+ external: true
43
+
44
+ volumes:
45
+ ${e}_postgres_data:
46
+ `}function re(t,e){if(!t||typeof t!="object")return!1;let n=t;for(let r of["pre_alpha","alpha","beta","out_of_scope"]){let s=n[r];if(!s||typeof s!="object"||!Array.isArray(s[e]))return!1}return!0}function qe(t){if(!t||typeof t!="object")return null;let e=t;if(typeof e.version!="string"||!e.project||typeof e.project!="object")return null;let n=e.project;if(typeof n.name!="string"||typeof n.version!="string")return null;let r=null;if(re(e.phases,"enabledStacks"))r=e.phases;else if(re(e.stacks,"services")){let a=e.stacks;r={pre_alpha:{name:a.pre_alpha.name,description:a.pre_alpha.description,enabledStacks:a.pre_alpha.services},alpha:{name:a.alpha.name,description:a.alpha.description,enabledStacks:a.alpha.services},beta:{name:a.beta.name,description:a.beta.description,enabledStacks:a.beta.services},out_of_scope:{name:a.out_of_scope.name,description:a.out_of_scope.description,enabledStacks:a.out_of_scope.services}}}if(!r||!e.optional_infra||typeof e.optional_infra!="object")return null;let s=e.optional_infra;if(typeof s.monitoring!="boolean"||typeof s.elk!="boolean"||typeof s.debezium!="boolean"||typeof s.golden_image!="boolean"||typeof s.verdaccio!="boolean"||!e.discovery||typeof e.discovery!="object")return null;let c=e.discovery;return Array.isArray(c.paths)?{version:e.version,project:e.project,phases:r,always_enabled_infra:e.always_enabled_infra,optional_infra:e.optional_infra,discovery:e.discovery,overrides:e.overrides}:null}var K=class extends Error{};function ie(t){let e=i.join(t,".tdk",W),n;try{n=o.readFileSync(e,"utf-8")}catch(c){if(c?.code==="ENOENT")throw new K(`Project config not found: ${e}. Run 'flisk project --yes' first.`);let a=c instanceof Error?c.message:String(c);throw new Error(`Could not read project.json at ${e}: ${a}`)}let r;try{r=JSON.parse(n)}catch(c){let a=c instanceof Error?c.message:String(c);throw new Error(`Could not parse project.json at ${e}: ${a}`)}let s=qe(r);if(!s)throw new Error("Invalid project.json: missing or invalid required fields. Expected: version (string), project (object with name/version), phases (object with pre_alpha/alpha/beta/out_of_scope enabledStacks), optional_infra (object with boolean flags), discovery (object with paths array)");return s}async function We(t){let e=Y(t).filter(r=>r.config?.sablier?.enable===!0);e.length===0||await Q(t)||console.warn(`\u26A0\uFE0F Sablier (on-demand scaling) is a Premium feature - no valid license key found. ${e.length} resource${e.length===1?" has":"s have"} a \`sablier\` block, but it will have no effect without a license. Set TDK_LICENSE_KEY to a key that grants it, or remove the \`sablier\` block from the affected service.json file(s) to silence this warning.`)}function Je(t,e){let n=E(t,A);if(o.existsSync(n))return!1;let r={name:e.project.name||i.basename(t),version:e.project.version||"1.0.0",private:!0,type:"module",workspaces:e.discovery.paths};return U(n,`${JSON.stringify(r,null,2)}
47
+ `),!0}async function Nt(t,e={}){let n=ie(t),r=O(t).flatMap(l=>J(l,i.relative(t,l).split(i.sep).join("/")));if(r.length>0)throw new Error(`Refusing to generate config from unsafe service.json values:
48
+ ${r.map(l=>` ${l}`).join(`
49
+ `)}`);await We(t),Je(t,n)&&!e.quiet&&console.log("\u2713 Generated: package.json (workspace root)");let s=Object.values(n.phases).some(l=>l.enabledStacks.includes("verdaccio"));(n.optional_infra.verdaccio||s)&&(await z(t)||console.warn("\u26A0\uFE0F Verdaccio is a Premium feature - no valid license key found. It's enabled in this project's config, but will have no effect without a license. Set TDK_LICENSE_KEY to a key that grants it, or run `flisk config disable-infra verdaccio` to silence this warning."));let c=i.join(t,".tdk",".tdk-out");o.existsSync(c)||o.mkdirSync(c,{recursive:!0});let f=new D().generateAll(n);for(let l of se){let u=f[l],b=E(t,i.join(".tdk",".tdk-out",l));L(b,u),e.quiet||console.log(`\u2713 Generated: .tdk/.tdk-out/${l}`)}if(ne(n.phases,v)){let l=E(t,i.join("services","platform",v,q)),u=i.dirname(l);o.mkdirSync(u,{recursive:!0}),L(l,Ve(n)),e.quiet||console.log("\u2713 Generated: services/platform/database-management/docker-compose.yml")}let m=i.join(c,k),p=E(t,k);if(o.existsSync(m)){if(!o.existsSync(p))o.copyFileSync(m,p),console.log("\u2713 Copied: .tiltignore \u2192 project root");else if(e.discardHandEdits){let l=o.readFileSync(p,"utf-8");l.includes(ce)&&l!==o.readFileSync(m,"utf-8")&&(o.copyFileSync(m,p),console.log("\u2713 Restored: .tiltignore \u2192 project root (hand edits discarded)"))}}let S=et(t);for(let l of S)console.log(`\u2713 Copied: ${l} \u2192 project root`);await tt(t),console.log(""),console.log("\u{1F4A1} To start Tilt: flisk up")}var Be=/\.(?:test|spec)\.[cm]?[jt]sx?$/;function oe(t){return Be.test(t)}function ae(t){if(o.existsSync(t))for(let e of o.readdirSync(t,{withFileTypes:!0})){let n=i.join(t,e.name);e.isDirectory()?ae(n):oe(n)&&o.rmSync(n,{force:!0})}}var Ye=["engine","discovery","specs","ext"],ze=[["shared-platform-engineering","docker-templates"]],Qe=["install-deps.sh","bun-hoisted-symlink-fix.sh","prisma-bun-client-link-fix.sh","prisma-normalize-client.sh"];function Xe(){let t=$("node:url").fileURLToPath(new URL("../dist/generator",import.meta.url))||process.cwd();for(let e=0;e<6;e++){if(o.existsSync(i.join(t,"Tiltfile"))&&o.existsSync(i.join(t,"engine")))return t;let n=i.dirname(t);if(n===t)break;t=n}return null}function Ze(){let t=$("node:url").fileURLToPath(new URL("../dist/generator",import.meta.url))||process.cwd();for(let r=0;r<8;r++){if(o.existsSync(i.join(t,"shared-platform-engineering","docker-templates")))return t;let s=i.dirname(t);if(s===t)break;t=s}let e=i.dirname(process.execPath);return[i.join(e,"tdk-cli"),i.join(process.cwd(),"node_modules","@flisk-sh","flisk")].find(r=>o.existsSync(i.join(r,"shared-platform-engineering","docker-templates")))??null}function et(t){let e=Ze(),n=[];if(!e)return console.warn("\u26A0\uFE0F Flisk runtime assets not found - generated Dockerfiles may fail. Reinstall or upgrade Flisk, then re-run `flisk project`."),n;for(let r of ze){let s=i.join(e,...r),c=E(t,i.join(...r));o.existsSync(s)&&(o.mkdirSync(i.dirname(c),{recursive:!0}),o.cpSync(s,c,{recursive:!0}),n.push(r.join("/")))}for(let r of Qe){let s=i.join(t,"shared-platform-engineering","docker-templates",r);o.existsSync(s)||console.warn(`\u26A0\uFE0F Missing runtime asset after copy: ${s}`)}return n}async function tt(t){let e=E(t,i.join(".tdk",".tdk-out","tdk-cli-ext")),n=[];process.env.TDK_EXTENSION_SOURCE&&n.push(process.env.TDK_EXTENSION_SOURCE);let r=Xe();r&&n.push(r);let s=i.dirname(process.execPath);n.push(i.join(s,"tdk-cli")),n.push(i.join(t,"..","tdk-cli"));let c="";for(let a of n)if(a&&o.existsSync(i.join(a,"Tiltfile"))&&o.existsSync(i.join(a,"engine"))){c=a;break}if(!c){console.warn("\u26A0\uFE0F Flisk extension not found - set TDK_EXTENSION_SOURCE to its checkout path and re-run `flisk project` (or `flisk config regenerate`) to vendor it before `flisk up`.");return}o.existsSync(e)||o.mkdirSync(e,{recursive:!0}),o.copyFileSync(i.join(c,"Tiltfile"),i.join(e,"Tiltfile"));for(let a of Ye)ae(i.join(e,a)),o.cpSync(i.join(c,a),i.join(e,a),{recursive:!0,filter:f=>!oe(f)});console.log("\u2713 Vendored Flisk extension \u2192 .tdk/.tdk-out/tdk-cli-ext/");try{let{applyPremiumOverlay:a}=await import("./extension-fetch-6XNTDF44.js");await a(t,e)}catch(a){console.warn(`\u26A0\uFE0F Premium overlay skipped: ${a.message}`)}}var ce="SYSTEM-GENERATED BY Flisk CLI";function Lt(t,e){let n=[],r=[],s=[],c=[],a=(h,T,y)=>{T!==y&&(n.push(`${T===void 0?"Missing file":"Out of sync"}: ${h} (run 'flisk config regenerate')`),s.push({file:h,diff:nt(h,T??"",y)}))},f=ie(t),p=new D().generateAll(f),S=i.join(t,".tdk",".tdk-out");for(let h of se){let T=p[h],y=i.join(S,h);a(`.tdk/.tdk-out/${h}`,o.existsSync(y)?o.readFileSync(y,"utf-8"):void 0,T)}let l=i.join(t,k),u=o.existsSync(l)?o.readFileSync(l,"utf-8"):void 0;u!==void 0&&!u.includes(ce)?r.push(".tiltignore: not generated by Flisk, left as is"):a(k,u,p[k]);let b=e?.manifestPaths??O(t);for(let h of b){let T=i.relative(t,h).split(i.sep).join("/");if(!e?.skipManifestValidation){let H=B(h,T);n.push(...H.errors),r.push(...H.warnings)}let y=rt(t,h);n.push(...y.errors),c.push(...y.handEdited)}return{valid:n.length===0,errors:n,warnings:r,diffs:s,handEdited:c}}function nt(t,e,n){let r=e.replace(/\n$/,"").split(`
50
+ `),s=n.replace(/\n$/,"").split(`
51
+ `),c=[`--- a/${t}`,`+++ b/${t}`,`@@ -1,${r.length} +1,${s.length} @@`];for(let a of r)c.push(`-${a}`);for(let a of s)c.push(`+${a}`);return c.join(`
52
+ `)}function rt(t,e){let n=i.dirname(e),r=i.join(n,x);if(!o.existsSync(r))return{errors:[],handEdited:[]};let s=[],c=(S,l="")=>{for(let u of o.readdirSync(S,{withFileTypes:!0})){if(l===""&&u.name===".tdk-contract")continue;let b=i.join(l,u.name),h=i.join(S,u.name);u.isDirectory()?c(h,b):u.isFile()&&s.push({fullPath:h,relativeFile:b})}};if(c(r),s.length===0)return{errors:[],handEdited:[]};let a=i.join(r,".tdk-contract"),f=i.join(a,"service.json.source"),m=[],p=[];o.existsSync(f)?o.readFileSync(f,"utf-8")!==o.readFileSync(e,"utf-8")&&m.push(i.relative(t,e)+": service.json changed since generated outputs were written (run flisk up)"):m.push(i.relative(t,f)+": generated-file contract snapshot is missing (run flisk up to regenerate)");for(let S of s){if(S.relativeFile==="service.yaml")continue;let l=i.join(a,S.relativeFile),u=i.relative(t,S.fullPath);o.existsSync(l)?o.readFileSync(S.fullPath,"utf-8")!==o.readFileSync(l,"utf-8")&&(p.push(u.split(i.sep).join("/")),m.push(`${u}: generated file differs from its Flisk snapshot (run flisk up to regenerate)`)):m.push(`${u}: generated-file snapshot is missing (run flisk up to regenerate)`)}return{errors:m,handEdited:p}}import{stdin as st,stdout as it}from"node:process";import{createInterface as ot}from"node:readline/promises";async function I(t){let e=ot({input:st,output:it});try{return await new Promise((n,r)=>{e.once("close",()=>r(new Error("No input available to answer the prompt. Run this in a terminal."))),e.question(t).then(s=>n(s.trim()),r)})}finally{e.close()}}async function Gt(t){let e=t.initial?` (${t.initial})`:"";for(;;){let r=await I(`${t.message}${e} `)||t.initial||"",s=t.validate?.(r)??!0;if(s===!0)return r;console.log(s)}}async function Mt(t){let e=t.initial??!0,n=e?"Y/n":"y/N";for(;;){let r=(await I(`${t.message} (${n}) `)).toLowerCase();if(!r)return e;if(["y","yes"].includes(r))return!0;if(["n","no"].includes(r))return!1;console.log("Please answer yes or no.")}}async function Kt(t){for(console.log(t.message),t.choices.forEach((e,n)=>{console.log(` ${n+1}. ${e.title}`)});;){let e=await I("Choose one: "),n=Number.parseInt(e,10)-1,r=t.choices[n];if(r)return r.value;console.log(`Enter a number from 1 to ${t.choices.length}.`)}}async function Ht(t){let e=t.choices.map((r,s)=>r.selected?s+1:null).filter(r=>r!==null),n=e.length>0?` [${e.join(",")}]`:"";for(console.log(t.message),t.choices.forEach((r,s)=>{let c=r.selected?"*":" ";console.log(` ${c} ${s+1}. ${r.title}`)});;){let r=await I(`Choose one or more numbers, comma-separated${n}: `),s=e;if(r){let f=r.split(",").map(p=>p.trim()),m=f.find(p=>{if(!/^\d+$/.test(p))return!0;let S=Number.parseInt(p,10);return!t.choices[S-1]});if(m!==void 0){console.log(`"${m}" is not a valid choice (1-${t.choices.length})`);continue}s=f.map(p=>Number.parseInt(p,10))}let c=Array.from(new Set(s)).map(f=>t.choices[f-1]).filter(f=>!!f).map(f=>f.value),a=t.validate?.(c)??!0;if(a===!0)return c;console.log(a)}}export{ft as a,ue as b,dt as c,Se as d,pt as e,R as f,D as g,K as h,ie as i,Nt as j,Ze as k,et as l,Lt as m,Gt as n,Mt as o,Kt as p,Ht as q};
@@ -0,0 +1,5 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{Ta as w,cb as A,d as P,k as T}from"./chunk-US4D5GJJ.js";import{execFileSync as x}from"node:child_process";import{existsSync as G,mkdirSync as W,readFileSync as D,realpathSync as Y,writeFileSync as q}from"node:fs";import{join as S,resolve as V,sep as X}from"node:path";import{createServer as U}from"node:net";import{connect as K}from"node:net";function N(e,s=500){return new Promise(t=>{let r=K({port:e,host:"127.0.0.1"}),o=n=>{r.destroy(),t(n)};r.setTimeout(s,()=>o(!1)),r.once("connect",()=>o(!0)),r.once("error",()=>o(!1))})}var J={ingressHttp:{start:8080,end:8180},ingressHttps:{start:8443,end:8543},postgres:{start:15432,end:15532}},E={ingressHttp:"TDK_HTTP_PORT",ingressHttps:"TDK_HTTPS_PORT",postgres:"TDK_POSTGRES_PORT"},H={ingressHttp:80,ingressHttps:443,postgres:5432},k={ingressHttp:H.ingressHttp,ingressHttps:H.ingressHttps};function j(e,s){return e==="EACCES"&&s==="darwin"}async function b(e){return await N(e)?!1:new Promise(s=>{let t=U();t.once("error",r=>{s(j(r.code,process.platform))}),t.listen(e,"127.0.0.1",()=>t.close(()=>s(!0)))})}function B(e,s){let t=Number(s);if(!Number.isInteger(t)||t<1||t>65535)throw new Error(`${e} must be an integer between 1 and 65535 (received ${JSON.stringify(s)})`);return t}async function O(e={}){let s=e.env??process.env,t=e.isAvailable??b,r={ingressHttp:!1,ingressHttps:!1,postgres:!1},o={ingressHttp:"",ingressHttps:"",postgres:""},n={explicit:r},c=new Set;for(let a of["ingressHttp","ingressHttps","postgres"]){let f=s[E[a]],i=f!==void 0&&f.trim()!=="",u=e.ranges?.[a]??J[a],p=k[a],h=i?[B(E[a],f)]:[...p===void 0?[]:[p],...Array.from({length:u.end-u.start+1},(g,_)=>u.start+_)],d;for(let g of h)if(!c.has(g)){if(await t(g)){d=g;break}if(i)throw new Error(`${E[a]}=${g} is already in use. Choose a free host port and retry.`)}if(d===void 0)throw new Error(`No available host port in ${u.start}-${u.end} for ${a}. Set ${E[a]} to a free port and retry.`);c.add(d),n[a]=d,r[a]=i,o[a]=i?"explicit override":d===p?"requested port is free":`selected from fallback range ${u.start}-${u.end}`}return{...n,requested:{...H},reason:o}}function ue(e){return`Host ports: HTTP ${e.ingressHttp}, HTTPS ${e.ingressHttps}, Postgres ${e.postgres}`}var R=S(".tdk",".tdk-out","host-ports.json");function Q(e,s,t){return e.split(`
3
+ `).some(r=>{let[o="",n=""]=r.split("|"),c=o.toLowerCase(),a=s.toLowerCase();return(c.startsWith(`${a}_`)||c.startsWith(`${a}-`))&&n.includes(`:${t}->`)})}function F(e){let s=S(e,R);if(!G(s))return null;try{let t=JSON.parse(D(s,"utf-8"));if(!t||typeof t!="object")return null;let r=t;return!Number.isInteger(r.ingressHttp)||!Number.isInteger(r.ingressHttps)||!Number.isInteger(r.postgres)||!r.requested||!r.explicit||!r.reason?null:r}catch{return null}}function Se(e,s){let t=S(e,R);W(S(e,".tdk",".tdk-out"),{recursive:!0}),q(t,`${JSON.stringify(s,null,2)}
4
+ `,{encoding:"utf-8",mode:384})}function _e(e){process.env.TDK_HTTP_PORT=String(e.ingressHttp),process.env.TDK_HTTPS_PORT=String(e.ingressHttps),process.env.TDK_POSTGRES_PORT=String(e.postgres)}var z="com.docker.compose.project.working_dir";function Z(e,s,t){let r=new Set([V(s)]);try{r.add(Y(s))}catch{}return e.split(`
5
+ `).some(o=>{let[,n="",c=""]=o.split("|");return!c||!n.includes(`:${t}->`)?!1:[...r].some(a=>c===a||c.startsWith(`${a}${X}`))})}function Te(e,s,t=()=>x("docker",["ps","--format",`{{.Names}}|{{.Ports}}|{{.Label "${z}"}}`],{encoding:"utf-8",timeout:5e3})){let r=F(e);if(!r||r.ingressHttp===s)return s;try{if(Z(t(),e,r.ingressHttp))return r.ingressHttp}catch{}return s}async function Ee(e,s={}){let t=F(e),r=["TDK_HTTP_PORT","TDK_HTTPS_PORT","TDK_POSTGRES_PORT"].some(i=>process.env[i]);if(s.inspectDocker===!1&&t&&!r)return t;let o="";try{let i=JSON.parse(D(S(e,".tdk",T),"utf-8"));o=String(i?.project?.name??"tdk-project").replace(/-/g,"_").toLowerCase()}catch{o="tdk_project"}let n="";if(s.inspectDocker!==!1)try{n=x("docker",["ps","--format","{{.Names}}|{{.Ports}}"],{encoding:"utf-8",timeout:5e3})}catch{}let c=i=>Q(n,o,i),a=s.isPortFree??b,f=async i=>await a(i)||c(i);if(t&&!r){for(let i of[t.ingressHttp,t.ingressHttps,t.postgres])if(!await f(i))return O({isAvailable:f});for(let[i,u]of Object.entries(k)){let p=t[i];if(u!==void 0&&p!==u&&await f(u))return O({isAvailable:f})}return t}return O({isAvailable:f})}import{existsSync as ee,readFileSync as v}from"node:fs";import{join as l}from"node:path";var $=["postgres",P],L=["pre_alpha","alpha","beta","out_of_scope"];function te(e){return $.includes(e)}function C(e){try{return JSON.parse(v(l(e,".tdk",T),"utf-8"))}catch{return}}function m(e){try{return ee(e)?v(e,"utf-8"):void 0}catch{return}}function I(e,s){let t=o=>{let n=o;for(;n<e.length&&/\s/.test(e[n]);)n+=1;return n},r=0;for(;;){let o=e.indexOf(s,r);if(o===-1)return;let n=t(o+s.length);if(e[n]==="="&&(n=t(n+1),e[n]==="[")){let c=e.indexOf("]",n+1);return c===-1?void 0:[...e.slice(n+1,c).matchAll(/"([^"]+)"|'([^']+)'/g)].map(a=>a[1]??a[2]??"")}r=o+s.length}}function M(e){let s=l(e,".tdk",".tdk-out","Tiltfile"),t=m(s);if(t)return I(t,"ALWAYS_ENABLED_INFRA")}function se(e){let s=l(e,".tdk",".tdk-out","spec.master"),t=m(s);if(t!==void 0)return/"database-management"\s*:\s*True/.test(t)}function re(e){let s=l(e,".tdk",".tdk-out"),t=m(l(s,"Tiltfile")),r=m(l(s,"spec.master")),o=m(l(s,"tdk-cli-ext","discovery","config.star")),n=m(l(s,"tdk-cli-ext","engine","topologies","tilt","config","profiles.star"));if(!t||!r||!o||!n)return!1;let c=r.match(/PRE_ALPHA_RESOURCES\s*=\s*\{([^}]*)\}/)?.[1],a=I(o,"CORE_INFRA");return/FOCUS_MODE\s*,\s*FOCUS_ENABLED_ALL\s*,\s*FOCUS_ENABLED_RESOURCES\s*=\s*Config\.apply_focus\(cfg\)/.test(t)&&/if FOCUS_MODE and FOCUS_ENABLED_ALL\s*:/.test(t)&&/"[^"]+"\s*:\s*True|'[^']+'\s*:\s*True/.test(c??"")&&(a?.includes("postgres")??!1)&&/["']postgres["']\s*:\s*["']database-management["']/.test(o)&&/for infra in CORE_INFRA_EXPORT\s*:/.test(n)&&/needed\[INFRA_STACK_MAP_EXPORT\[infra\]\]\s*=\s*True/.test(n)}function ne(e){let s=C(e);if(!s)return!1;let t=s.phases??{};for(let o of L){let n=t[o]?.enabledStacks;if(Array.isArray(n)&&n.includes(P))return!0}let r=s.always_enabled_infra??A;return Array.isArray(r)&&r.includes(P)}function oe(e,s){let t=new Set;for(let n of $)t.add(n);for(let n of s)t.add(n.name),n.stack&&t.add(n.stack);let r=C(e);if(r){let n=r.phases??{};for(let a of L){let f=n[a]?.enabledStacks;if(Array.isArray(f))for(let i of f)t.add(i)}let c=r.always_enabled_infra??A;if(Array.isArray(c))for(let a of c)t.add(a)}let o=M(e);if(Array.isArray(o))for(let n of o)t.add(n);return t}function be(e,s=w(e)){let t=ne(e),r=M(e),o=Array.isArray(r)&&r.includes(P),n=se(e)===!0,c=t||o||n,a=!t&&re(e),f=oe(e,s),i=[],u=[];for(let d of s){let g=d.config?.dependsOn??[],_=!1;for(let y of g){if(te(y)){_=!0;continue}f.has(y)||u.push({resource:d.name,name:y})}_&&i.push(d.name)}let p=c||i.length>0,h=c?"feature":i.length>0?"dependsOn":"none";return{featureOn:c,featureOnFromProjectJson:t,featureOnFromTiltfile:o,featureOnFromSpecMaster:n,focusWouldEnableDatabaseManagement:a,dependsOnUsers:i,willStart:p,reason:h,unknownDependsOnNames:u}}export{O as a,ue as b,F as c,Se as d,_e as e,Te as f,Ee as g,$ as h,be as i};
@@ -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.198",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};
@@ -0,0 +1,4 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{a as k}from"./chunk-DTIHDMED.js";import{g as w,h as y}from"./chunk-SB5WAMSU.js";import{Ra as h,ba as d,ca as u,d as l,k as f,ra as m,s as p,ta as g}from"./chunk-US4D5GJJ.js";import{b as a}from"./chunk-CF46CD6R.js";import{Command as A}from"commander";import{readFileSync as E}from"node:fs";import{join as T}from"node:path";function $(n){let e=n.config;return e?Array.isArray(e.featuresEnabled)&&e.featuresEnabled.includes(l)?!0:(Array.isArray(e.dependsOn)?e.dependsOn:[]).some(o=>y.includes(o)):!1}function H(n,e){let i=n.replace(/-/g,"_"),o=[];for(let t of[...e].sort((r,s)=>r.name.localeCompare(s.name))){let r=t.resources.filter($).map(s=>s.name);r.length!==0&&o.push({name:`${i}_${t.name.replace(/-/g,"_")}`,stack:t.name,services:r.sort()})}return o.length===0?null:{name:"postgres",databases:o}}function x(n){try{let e=JSON.parse(E(T(n,".tdk",f),"utf-8"));return typeof e?.project?.name=="string"?e.project.name:null}catch{return null}}import{spawn as P}from"node:child_process";function j(n){try{let e=new URL(n);return e.protocol==="http:"||e.protocol==="https:"}catch{return!1}}function S(n,e=process.platform,i=P){if(!j(n))return Promise.resolve(!1);let o,t;return e==="darwin"?(o="open",t=[n]):e==="win32"?(o="rundll32.exe",t=["url.dll,FileProtocolHandler",n]):(o="xdg-open",t=[n]),new Promise(r=>{try{let s=i(o,t,{stdio:"ignore",detached:!0,windowsHide:!0});s.once("error",()=>r(!1)),s.once("spawn",()=>{typeof s.unref=="function"&&s.unref(),r(!0)})}catch{r(!1)}})}function B(n,e=process.platform,i=P){return new Promise(o=>{let t,r;e==="darwin"?(t="pbcopy",r=[]):e==="win32"?(t="clip",r=[]):(t="xclip",r=["-selection","clipboard"]);try{let s=i(t,r,{stdio:["pipe","ignore","ignore"],windowsHide:!0});s.on("error",()=>{o(!1)}),s.on("close",c=>{o(c===0)}),s.stdin?(s.stdin.on("error",()=>{o(!1)}),s.stdin.write(n,"utf-8"),s.stdin.end()):o(!1)}catch{o(!1)}})}async function N(n){let{resources:e}=h(n),i=await w(n,{inspectDocker:!1}),{appBase:o}=m(i?.ingressHttp,n);return e.filter(t=>t.config?.appType==="frontend").map(t=>({name:t.name,url:`${o}${g(t)}`}))}async function O(n,e=2e3){try{return(await fetch(n,{signal:AbortSignal.timeout(e)})).status<500}catch{return!1}}async function b(n,e=3e4,i){if(n.length===0)return;let o=Date.now(),t=o+e;for(;;){for(let s of n)if(await O(s.url))return s;let r=Date.now()-o;if(r>=e)return;i?.(r),await new Promise(s=>setTimeout(s,2e3))}}async function F(n){let e=n??p();if(!e)return console.log(a.yellow("Not in a Flisk project, so there is no frontend to open.")),console.log(a.gray("Run `flisk project --yes` first, or `flisk open` inside a project.")),null;let i=await N(e);if(i.length===0)return console.log(a.yellow("This project has no frontend service to open.")),console.log(a.gray("Start the stack with `flisk up` and add a frontend with `flisk resource`.")),null;let o=x(e);d(`Opening the first frontend of ${o??"this project"}`);for(let c of i)console.log(a.gray(` - ${c.name}: ${c.url}`));let t=k("Waiting for the frontend to answer..."),r=await b(i,12e4,c=>{t.text=`Waiting for the frontend to answer... ${Math.round(c/1e3)}s`});if(!r){t.fail("No frontend answered yet."),console.log(a.yellow("The stack is not serving the frontend yet.")),console.log(a.gray(" - Start the stack in another terminal: flisk up")),console.log(a.gray(" - Then run this again: flisk open"));for(let c of i)console.log(a.gray(` - ${c.name}: ${c.url}`));return null}t.succeed(`The frontend is up: ${r.name}`);let s=await S(r.url);return console.log(s?a.green(`
3
+ Opened ${r.url}`):a.yellow(`
4
+ Could not open a browser. Open ${r.url} yourself.`)),u("Run `flisk open` again to open the next frontend."),r.url}var Q=new A("open").description("Open the first frontend of the project in your browser").action(async()=>{await F()});export{H as a,x as b,S as c,B as d,N as e,O as f,b as g,F as h,Q as i};
@@ -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{I as z,K as G,La as re,M as E,Pa as ae,Qa as se,Sa as ie,Ua as ce,Va as le,W as T,Wa as de,X as B,b as p,ba as f,bb as N,ca as y,cb as pe,da as t,db as q,f as x,ja as ne,jb as D,ka as W,kb as Y,l as U,la as V,n as P,ob as J,pb as I,rb as C,t as F}from"./chunk-XYFVXSEO.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(`
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-KBGQ4NJE.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-US4D5GJJ.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-ZJAU3E7K.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...
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-5TVSNLIV.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(`