@flisk-sh/flisk 1.3.204 → 1.3.206

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 (64) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/cli/dist/cli.js +251 -90
  3. package/cli/dist/commands/doctor.js +29 -15
  4. package/cli/dist/commands/project.js +108 -60
  5. package/cli/dist/commands/resource.js +3 -1
  6. package/cli/dist/commands/up.js +8 -5
  7. package/cli/dist/generator/template-engine.js +17 -9
  8. package/cli/dist/utils/cli-command.js +3 -1
  9. package/cli/dist/utils/colima.js +23 -4
  10. package/cli/dist/utils/demo-stage.js +315 -0
  11. package/cli/dist/utils/doctor-fix.js +35 -9
  12. package/cli/dist/utils/machine-output.js +27 -0
  13. package/cli/dist/utils/native-windows.js +20 -0
  14. package/cli/dist/utils/one-command.js +15 -8
  15. package/cli/dist/utils/project-templates.js +1 -0
  16. package/cli/dist-bundle/chunk-3QQGL3NQ.js +35 -0
  17. package/cli/dist-bundle/chunk-4W6OXDLK.js +17 -0
  18. package/cli/dist-bundle/chunk-53M5D4KE.js +2 -0
  19. package/cli/dist-bundle/{chunk-BS6G2SLM.js → chunk-5CFVN3W3.js} +1 -1
  20. package/cli/dist-bundle/{chunk-RFHMXJTK.js → chunk-6Y6G7PSD.js} +1 -1
  21. package/cli/dist-bundle/chunk-7C5VA6CW.js +57 -0
  22. package/cli/dist-bundle/chunk-D2BXXJDM.js +7 -0
  23. package/cli/dist-bundle/chunk-GANRXKBM.js +2 -0
  24. package/cli/dist-bundle/chunk-GIMHTZNR.js +2 -0
  25. package/cli/dist-bundle/chunk-GOEBYLFN.js +2 -0
  26. package/cli/dist-bundle/chunk-LI3BXAX5.js +2 -0
  27. package/cli/dist-bundle/{chunk-WMF4AFAE.js → chunk-NCEK46NX.js} +10 -10
  28. package/cli/dist-bundle/chunk-ODVBKN6S.js +2 -0
  29. package/cli/dist-bundle/{chunk-Z6UD7UZH.js → chunk-PHI5AT3H.js} +2 -2
  30. package/cli/dist-bundle/chunk-XSPMLWAE.js +10 -0
  31. package/cli/dist-bundle/chunk-YZRPX76N.js +2 -0
  32. package/cli/dist-bundle/cli.js +269 -267
  33. package/cli/dist-bundle/cold-preflight-4I24DQLW.js +2 -0
  34. package/cli/dist-bundle/{colima-4ID4BGHC.js → colima-SVZX2UML.js} +1 -1
  35. package/cli/dist-bundle/demo-stage-EOMANLAD.js +7 -0
  36. package/cli/dist-bundle/native-windows-X5XVLFJS.js +2 -0
  37. package/cli/dist-bundle/one-command-P6XVAXWV.js +5 -0
  38. package/cli/dist-bundle/open-6374RNL6.js +2 -0
  39. package/cli/dist-bundle/project-IRWFRXWA.js +2 -0
  40. package/cli/dist-bundle/project-templates-JDRE7AVL.js +2 -0
  41. package/cli/dist-bundle/services-VIIBMWD4.js +2 -0
  42. package/cli/dist-bundle/tilt-port-owner-AN3ITRTR.js +2 -0
  43. package/cli/dist-bundle/url-actions-D6ROTHZG.js +2 -0
  44. package/cli/package.json +4 -4
  45. package/engine/assets/docker/wake-gateway/Dockerfile +1 -1
  46. package/engine/topologies/platform/docker/compose/compose.star +20 -18
  47. package/engine/topologies/platform/docker/compose/unsafe_value.star +23 -0
  48. package/engine/topologies/platform/docker/networking/traefik.star +19 -0
  49. package/package.json +2 -2
  50. package/cli/dist-bundle/chunk-CBFVK3TF.js +0 -21
  51. package/cli/dist-bundle/chunk-CF46CD6R.js +0 -6
  52. package/cli/dist-bundle/chunk-DTIHDMED.js +0 -5
  53. package/cli/dist-bundle/chunk-EPBYRJE3.js +0 -2
  54. package/cli/dist-bundle/chunk-GD5676UE.js +0 -52
  55. package/cli/dist-bundle/chunk-MKJNQTIN.js +0 -2
  56. package/cli/dist-bundle/chunk-QSPFSZCS.js +0 -34
  57. package/cli/dist-bundle/chunk-ZVGY7COV.js +0 -4
  58. package/cli/dist-bundle/cold-preflight-FXOZ5SR5.js +0 -2
  59. package/cli/dist-bundle/one-command-YP6L6MMM.js +0 -5
  60. package/cli/dist-bundle/open-UQ6DF3XN.js +0 -2
  61. package/cli/dist-bundle/project-GTYHCCFG.js +0 -2
  62. package/cli/dist-bundle/spinner-YLB6FYQH.js +0 -2
  63. package/cli/dist-bundle/tilt-port-owner-KLNX2ZI2.js +0 -2
  64. /package/cli/dist-bundle/{devtools-ZUHXW33W.js → devtools-MGITLOWZ.js} +0 -0
@@ -0,0 +1,2 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{A as d,B as e,C as f,D as g,E as h,F as i,G as j,x as a,y as b,z as c}from"./chunk-7C5VA6CW.js";import"./chunk-NCEK46NX.js";import"./chunk-5CFVN3W3.js";import"./chunk-42IVF3YT.js";import"./chunk-YZRPX76N.js";import"./chunk-PHI5AT3H.js";import"./chunk-GANRXKBM.js";import"./chunk-LI3BXAX5.js";import"./chunk-4W6OXDLK.js";import"./chunk-XSPMLWAE.js";import"./chunk-6EA4DGCY.js";export{c as MACHINE_CHECK_IDS,a as RUNTIME_CHECK_IDS,b as SCAFFOLD_CHECK_IDS,h as assertMachineReadyOrExit,i as detectRuntimePrerequisites,g as formatColdPreflight,j as formatRuntimeNextSteps,d as nodeTooOld,e as requireVerifiedDockerVersions,f as runColdPreflight};
@@ -1,2 +1,2 @@
1
1
  import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
- import{a,b,c,d}from"./chunk-MKJNQTIN.js";import"./chunk-6EA4DGCY.js";export{b as checkColima,a as isColimaDocker,d as nativeLimaPath,c as planColimaRepair};
2
+ import{a,b,c,d}from"./chunk-YZRPX76N.js";import"./chunk-6EA4DGCY.js";export{b as checkColima,a as isColimaDocker,d as nativeLimaPath,c as planColimaRepair};
@@ -0,0 +1,7 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{b as R}from"./chunk-ODVBKN6S.js";import{b as c}from"./chunk-XSPMLWAE.js";import"./chunk-6EA4DGCY.js";var v=12,_=24,F={plain:e=>e,bold:c.bold,dim:c.gray,ok:c.green,warn:c.yellow,err:c.red},S={pending:"\u25CB",active:"\u25D0",done:"\u2714",failed:"\u2716"},j={pending:"dim",active:"warn",done:"ok",failed:"err"};function o(e){return R(String(e)).replace(/[\n\r\t]/g," ")}function g(e){if(!Number.isFinite(e)||e<0)return"0.0s";if(e<1e4)return`${(e/1e3).toFixed(1)}s`;if(e<6e4)return`${Math.round(e/1e3)}s`;let n=Math.floor(e/6e4),i=Math.round(e%6e4/1e3);return`${n}m ${i}s`}function $(e){return e.reduce((n,i)=>n+i.text.length,0)}function k(e,n){if(n<=0)return[];let i=[],l=0;for(let s of e){if(l>=n)break;let t=n-l;if(s.text.length<=t){i.push(s),l+=s.text.length;continue}i.push({...s,text:`${s.text.slice(0,Math.max(0,t-1))}\u2026`}),l=n}return i}function w(e,n){let i=k(e,n),l=n-$(i);return l<=0?i:[...i,{text:" ".repeat(l),style:"plain"}]}function M(e,n,i){let l=$(n),s=i-l-1;if(s<4)return w(k([...e,...n],i),i);let t=k(e,s),r=i-$(t)-l;return[...t,{text:" ".repeat(Math.max(1,r)),style:"plain"},...n]}function b(e){return[{text:` ${"\u2500".repeat(Math.max(0,e-2))}`,style:"dim"}]}function P(e,n){return M([{text:" ",style:"plain"},{text:S[e.status],style:j[e.status]},{text:" ",style:"plain"},{text:o(e.label),style:e.status==="pending"?"dim":"plain"}],e.elapsedMs===void 0?[]:[{text:g(e.elapsedMs),style:"dim"}],n)}function Y(e){let n=Math.max(0,e.servicesTotal);if(n===0)return"no services found";let l=[`${Math.min(Math.max(0,e.servicesReady),n)} of ${n} services ready`];return e.servicesBuilding>0&&l.push(`${e.servicesBuilding} building`),l.join(" \xB7 ")}function E(e,n=80){let i=Number.isFinite(n)&&n>0?n:80,l=Math.max(_,Math.min(i-1,78)),s=[],t=a=>s.push(w(a,l)),r=()=>t([]);if(e.done){t(M([{text:" ",style:"plain"},{text:"\u2714",style:"ok"},{text:" Your stack is running",style:"ok"}],[{text:g(e.elapsedMs),style:"dim"}],l)),t([{text:" ",style:"plain"},{text:o(e.subtitle),style:"dim"}]),r();for(let a of e.done.urls.slice(0,2))t([{text:" ",style:"plain"},{text:o(a),style:"plain"}]);r(),t(b(l)),t([{text:" ",style:"plain"},{text:o(e.done.summary),style:"plain"}]),t([{text:" ",style:"plain"},{text:o(e.done.hint),style:"dim"}]),r(),t([{text:" ",style:"plain"},{text:`flisk ${o(e.done.version)}`,style:"dim"}])}else if(e.failure){let a=e.phases.find(p=>p.status==="failed");t(M([{text:" ",style:"plain"},{text:"\u2716",style:"err"},{text:" ",style:"plain"},{text:o(a?.label??"The demo stopped"),style:"err"}],[{text:g(e.elapsedMs),style:"dim"}],l)),r(),t([{text:" ",style:"plain"},{text:o(e.failure.message),style:"plain"}]),e.failure.fix&&t([{text:" ",style:"plain"},{text:o(e.failure.fix),style:"dim"}]),r(),t(b(l)),e.detail&&t([{text:" ",style:"plain"},{text:o(e.detail),style:"dim"}]),e.failure.logPath&&t([{text:" ",style:"plain"},{text:`log: ${o(e.failure.logPath)}`,style:"dim"}])}else{t([{text:" ",style:"plain"},{text:o(e.title),style:"bold"}]),t([{text:" ",style:"plain"},{text:o(e.subtitle),style:"dim"}]),r();let a=e.phases.slice(0,4);for(let p of a)t(P(p,l));for(let p=a.length;p<4;p+=1)r();r(),t(b(l)),t([{text:" ",style:"plain"},{text:o(e.detail??""),style:"dim"}]),t(M([{text:" ",style:"plain"},{text:Y(e),style:"plain"}],[{text:g(e.elapsedMs),style:"dim"}],l))}for(;s.length<v;)s.push(w([],l));return s.slice(0,v)}function A(e){return e.map(n=>n.map(i=>i.text).join(""))}function D(e){return e.map(n=>F[n.style](n.text)).join("")}function H(e,n=process.stderr,i=Date.now){let l=n.isTTY===!0,s=i(),t={...e},r=!1,a="",p="",f,T=()=>{let u=!!(t.done||t.failure);return{...t,elapsedMs:u?t.elapsedMs:i()-s}},x=()=>{let u=T(),m=E(u,n.columns??80),y=A(m);if(!l){let h=y.join(`
3
+ `);if(h===p)return;p=h,n.write(`${y.filter(L=>L.trim()!=="").join(`
4
+ `)}
5
+ `);return}let d=y.join(`
6
+ `);if(!(d===a&&r)){a=d,r&&n.write(`\x1B[${v}A`);for(let h of m)n.write(`\r\x1B[2K${D(h)}
7
+ `);r=!0}};return l&&(x(),f=setInterval(x,200),f.unref?.()),{update(u){t={...t,...u,phases:u.phases??t.phases},x()},fail(u,m,y){t={...t,elapsedMs:i()-s,failure:{message:u,fix:m,logPath:y},phases:t.phases.map(d=>d.status==="active"?{...d,status:"failed"}:d)},x()},finish(u){t={...t,elapsedMs:i()-s,done:u},x()},stop(){f&&clearInterval(f),f=void 0}}}export{v as FRAME_ROWS,H as createDemoStage,g as formatElapsed,A as frameToPlain,E as renderDemoFrame,o as sanitizeCell,D as styleRow};
@@ -0,0 +1,2 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{a,b}from"./chunk-53M5D4KE.js";import"./chunk-6EA4DGCY.js";export{a as NATIVE_WINDOWS_REFUSAL,b as nativeWindowsStackRefusal};
@@ -0,0 +1,5 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import"./chunk-6EA4DGCY.js";import{spawn as d}from"node:child_process";import{readdirSync as p}from"node:fs";import{join as l}from"node:path";var m="Frontend URLs";function y(r){let i=r.split(`
3
+ `),t=i.findIndex(e=>e.includes(m));if(t!==-1)for(let e of i.slice(t+1)){let n=e.match(/^\s*-\s+\S+:\s+(https?:\/\/\S+)/);if(n)return n[1];if(e.trim()===""||e.includes("URLs:"))break}}function j(r,i,t=process.env,e=d){return new Promise(n=>{let o=e(process.execPath,[r,"project","--yes","--quiet"],{cwd:i,env:t,stdio:["ignore","pipe","pipe"]}),c="";o.stdout?.on("data",s=>{c+=String(s)}),o.stderr?.on("data",s=>{c+=String(s)}),o.on("error",s=>n({ok:!1,error:s.message,output:c})),o.on("close",s=>{if(s===0){n({ok:!0,output:c});return}let u=c.split(`
4
+ `).map(a=>a.trim()).filter(Boolean).pop();n({ok:!1,error:u??`the project setup failed (code ${s})`,output:c})})})}function h(r){for(let i of r.split(`
5
+ `)){let t=i.trim();if(t.startsWith("{"))try{let e=JSON.parse(t),o=(e.data??{}).ok===!0;return{ok:o,data:e.data??{},error:o?void 0:e.errors?.[0]?.message??"the stack did not come up",raw:r}}catch{}}}function P(r,i,t=process.env,e=d){return new Promise(n=>{let o=e(process.execPath,[r,"up","--json"],{cwd:i,env:t,stdio:["inherit","pipe","pipe"]}),c="",s=!1,u=a=>{s||(s=!0,o.unref?.(),n(a))};o.stdout?.on("data",a=>{c+=String(a);let f=h(c);f&&u(f)}),o.stderr?.on("data",a=>{c+=String(a)}),o.on("error",a=>u({ok:!1,error:a.message,raw:c})),o.on("close",a=>u({ok:!1,error:`the stack stopped before it was ready (code ${a})`,raw:c}))})}function R(r,i){if(!i(r))return r;for(let t=2;t<1e3;t+=1){let e=`${r}-${t}`;if(!i(e))return e}return r}function k(r,i=4){let t=[],e=(n,o)=>{if(o>i)return;let c;try{c=p(n,{withFileTypes:!0}).map(s=>s.name)}catch{return}c.includes("package.json")&&t.push(n);for(let s of p(n,{withFileTypes:!0}))!s.isDirectory()||s.name==="node_modules"||s.name.startsWith(".")||e(l(n,s.name),o+1)};return e(r,0),t}async function D(r,i=x){let t=[];for(let e of k(r)){let n=await i("bun",["install"],e);t.push({dir:e,ok:n===0})}return t}function x(r,i,t){return new Promise(e=>{let n=d(r,i,{cwd:t,stdio:"ignore"});n.on("error",()=>e(1)),n.on("close",o=>e(o??1))})}export{y as findFrontendUrl,k as findServiceDirs,j as initializeProject,D as installServiceDependencies,R as nextAvailableProjectDir,h as parseStackEnvelope,P as runStackQuiet};
@@ -0,0 +1,2 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{d as a,e as b,f as c,g as d,h as e,i as f}from"./chunk-D2BXXJDM.js";import"./chunk-GOEBYLFN.js";import"./chunk-PHI5AT3H.js";import"./chunk-GANRXKBM.js";import"./chunk-LI3BXAX5.js";import"./chunk-4W6OXDLK.js";import"./chunk-XSPMLWAE.js";import"./chunk-6EA4DGCY.js";export{d as findReadyFrontend,b as isFrontendReady,a as listFrontendTargets,f as openCommand,e as openFirstFrontend,c as pickReadyFrontend};
@@ -0,0 +1,2 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{g as a,h as b,i as c,j as d}from"./chunk-3QQGL3NQ.js";import"./chunk-GIMHTZNR.js";import"./chunk-NCEK46NX.js";import"./chunk-42IVF3YT.js";import"./chunk-LI3BXAX5.js";import"./chunk-4W6OXDLK.js";import"./chunk-XSPMLWAE.js";import"./chunk-6EA4DGCY.js";export{c as cloneProjectTemplate,a as enableDiscoveredStacks,d as projectCommand,b as templateTargetDir};
@@ -0,0 +1,2 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{a,b}from"./chunk-GIMHTZNR.js";import"./chunk-6EA4DGCY.js";export{a as PROJECT_TEMPLATES,b as bareTemplateArg};
@@ -0,0 +1,2 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{ca as a,da as b,ea as c,fa as d,ga as e,ha as f,ia as g,ja as h,ka as i,la as j,ma as k,na as l,oa as m,pa as n,qa as o}from"./chunk-4W6OXDLK.js";import"./chunk-XSPMLWAE.js";import"./chunk-6EA4DGCY.js";export{m as clearMetadataCache,f as discoverResources,e as discoverResourcesFromRoot,g as discoverResourcesStrict,c as discoverResourcesWithProblems,a as discoverServiceManifestPaths,h as discoverStackNames,j as discoverStacks,i as getAllStacks,n as getResourceMetadata,k as getResourcesForStack,o as getStackMetadata,b as resetPrintedServiceWarnings,l as stackExists,d as warnAboutSkippedFiles};
@@ -0,0 +1,2 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{a,b,c}from"./chunk-6Y6G7PSD.js";import"./chunk-5CFVN3W3.js";import"./chunk-GANRXKBM.js";import"./chunk-LI3BXAX5.js";import"./chunk-4W6OXDLK.js";import"./chunk-XSPMLWAE.js";import"./chunk-6EA4DGCY.js";export{c as classifyTiltPorts,a as findTiltPortOwner,b as isForeignTilt};
@@ -0,0 +1,2 @@
1
+ import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
+ import{a,b,c}from"./chunk-GOEBYLFN.js";import"./chunk-6EA4DGCY.js";export{c as copyToClipboard,a as isValidHttpUrl,b as openUrl};
package/cli/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tdk-cli-internal",
3
3
  "private": true,
4
- "version": "1.3.204",
4
+ "version": "1.3.206",
5
5
  "description": "Flisk CLI — start services on your machine.",
6
6
  "keywords": [
7
7
  "flisk",
@@ -61,9 +61,9 @@
61
61
  },
62
62
  "devDependencies": {
63
63
  "@biomejs/biome": "^2.5.13",
64
- "@types/node": "^22.0.0",
64
+ "@types/node": "^26.6.5",
65
65
  "@types/react": "^19.3.0",
66
- "@vitest/coverage-v8": "^5.0.2",
66
+ "@vitest/coverage-v8": "5.0.5",
67
67
  "ajv": "^8.17.1",
68
68
  "chalk": "^6.0.1",
69
69
  "esbuild": "^0.28.2",
@@ -73,7 +73,7 @@
73
73
  "react-devtools-core": "^8.0.0",
74
74
  "typescript": "^7.0.2",
75
75
  "vite": "^8.3.3",
76
- "vitest": "^5.0.0"
76
+ "vitest": "5.0.5"
77
77
  },
78
78
  "engines": {
79
79
  "node": ">=22.12.0"
@@ -7,7 +7,7 @@
7
7
  # documented `tilt trigger` command rather than depending on Tilt's
8
8
  # undocumented internal HTTP API).
9
9
 
10
- FROM oven/bun:1.3.11-alpine@sha256:7ed9f74c326d1c260abe247ac423ccbf5ac92af62bb442d515d1f92f21e8ea9b AS base
10
+ FROM oven/bun:1.4.3-alpine@sha256:629e17411f1f129dbec3af78d5af9c9f2a937435c80349437206c6b0b7422373 AS base
11
11
 
12
12
  # Pin to the same Tilt version this workspace runs (v0.37.7) so `tilt trigger`
13
13
  # talks the same protocol as the real daemon it's connecting to. Installed
@@ -20,6 +20,7 @@ OUTPUT = struct(AUTOGENERATED_FOLDER = ".autogenerated")
20
20
 
21
21
 
22
22
  load("./compose_helpers.star", "compose_build_config")
23
+ load("./unsafe_value.star", "reject_unsafe_value")
23
24
  load("../networking/traefik.star", "get_frontend_traefik_labels", "get_backend_traefik_labels")
24
25
  load("../networking/api_path_constants.star", "get_api_path_for_domain", "get_frontend_base_path")
25
26
  load("../secrets/infisical.star", "get_infisical_environment_vars")
@@ -80,7 +81,7 @@ def generate_frontend_compose(resource_path, resource_name, res, manifest=None):
80
81
  """Generate frontend docker-compose entry with Traefik routing."""
81
82
  res_name = res['name']
82
83
  image_name = PlatformDockerConstants.app_image_name(resource_name, res_name)
83
- stack = manifest.get('stack', resource_name) if manifest else resource_name
84
+ stack = reject_unsafe_value(manifest.get('stack', resource_name) if manifest else resource_name, 'stack')
84
85
 
85
86
  target_path = res.get('target_path', manifest.get('target_path', '/usr/share/nginx/html'))
86
87
  use_nginx = 'nginx' in target_path or target_path == '/usr/share/nginx/html'
@@ -90,16 +91,16 @@ def generate_frontend_compose(resource_path, resource_name, res, manifest=None):
90
91
  # healthcheck probe a port nothing listens on, which left the container marked
91
92
  # unhealthy -- and Traefik's Docker provider skips unhealthy containers, so the
92
93
  # router was never registered and every request 404'd.
93
- port = NGINX_CONTAINER_PORT if use_nginx else manifest.get('port', BASE_PORT_FRONTEND)
94
+ port = NGINX_CONTAINER_PORT if use_nginx else reject_unsafe_value(manifest.get('port', BASE_PORT_FRONTEND), 'port')
94
95
 
95
96
  # Base path for routing on {project}.localhost. Shared with the Vite config and
96
97
  # PUBLIC_URL generators -- see get_frontend_base_path for why they must agree.
97
- base_path = get_frontend_base_path(manifest, res_name)
98
+ base_path = reject_unsafe_value(get_frontend_base_path(manifest, res_name), 'basePath')
98
99
 
99
100
  traefik_cfg = manifest.get('traefik', {}) if manifest else {}
100
- traefik_host = traefik_cfg.get('host')
101
+ traefik_host = reject_unsafe_value(traefik_cfg.get('host'), 'traefik.host')
101
102
  # Use custom dockerfile from manifest if specified, otherwise use autogenerated default
102
- dockerfile_path = res.get('dockerfile', OUTPUT.AUTOGENERATED_FOLDER + '/Dockerfile.app.autogenerated')
103
+ dockerfile_path = reject_unsafe_value(res.get('dockerfile', OUTPUT.AUTOGENERATED_FOLDER + '/Dockerfile.app.autogenerated'), 'dockerfile')
103
104
  # Handle flat service structure (e.g., services/product/identity-management-frontend) vs nested (services/product/domain/service)
104
105
  # Detect flat structure: services/product/{service} (3 path parts after root)
105
106
  # vs nested: services/product/{domain}/{service} (4+ path parts)
@@ -162,7 +163,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
162
163
  Generate a single backend docker-compose entry.
163
164
  """
164
165
  res_name = res['name']
165
- stack = manifest.get('stack', resource_name) if manifest else resource_name
166
+ stack = reject_unsafe_value(manifest.get('stack', resource_name) if manifest else resource_name, 'stack')
166
167
 
167
168
  # Get full service path from resource (for cross-root service support)
168
169
  full_resource_path = res.get('_resource_path', resource_path + '/' + res_name)
@@ -170,30 +171,30 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
170
171
  # Calculate correct relative path to env_file from compose file location
171
172
  env_file_rel_path = _compute_env_file_rel_path(resource_path, full_resource_path, '.env.backend.autogenerated')
172
173
 
173
- internal_port = manifest.get('port', BASE_PORT_BACKEND) if manifest else BASE_PORT_BACKEND
174
+ internal_port = reject_unsafe_value(manifest.get('port', BASE_PORT_BACKEND), 'port') if manifest else BASE_PORT_BACKEND
174
175
  dev_port = internal_port
175
176
  # Use PROJECT_NAME from PlatformDockerConstants for portable database naming
176
177
  _db_prefix = PlatformDockerConstants.PROJECT_NAME + "_"
177
- db_name = manifest.get('databaseName', _db_prefix + stack) if manifest else _db_prefix + stack
178
+ db_name = reject_unsafe_value(manifest.get('databaseName', _db_prefix + stack) if manifest else _db_prefix + stack, 'databaseName')
178
179
 
179
180
  # Compute database URLs using centralized constants
180
181
  db_url_for_tilt = PlatformDockerConstants.get_database_url_for_env(db_name)
181
182
  db_url_with_fallback = PlatformDockerConstants.get_compose_env_database_url(db_name)
182
183
 
183
- health_path = manifest.get('healthCheckPath', HEALTH_CHECK_PATH) if manifest else HEALTH_CHECK_PATH
184
+ health_path = reject_unsafe_value(manifest.get('healthCheckPath', HEALTH_CHECK_PATH) if manifest else HEALTH_CHECK_PATH, 'healthCheckPath')
184
185
  # A bring-your-own service without healthCheckPath may not serve HTTP. None means no HTTP probe: no Traefik health check labels.
185
186
  if manifest and manifest.get('appType') == 'bring-your-own' and not manifest.get('healthCheckPath'):
186
187
  health_path = None
187
188
 
188
189
  traefik_cfg = manifest.get('traefik', {}) if manifest else {}
189
- traefik_host = traefik_cfg.get('host', stack + '.backend.' + _PROJECT_NAME + '.local')
190
+ traefik_host = reject_unsafe_value(traefik_cfg.get('host', stack + '.backend.' + _PROJECT_NAME + '.local'), 'traefik.host')
190
191
  # ALPHA: Use proper API v1 path with -management suffix via api_path_constants
191
192
  # Old default: '/api/' + stack
192
193
  # New default: get_api_path_for_domain → /api/v1/{stack}-management
193
- traefik_path = traefik_cfg.get('pathPrefix', get_api_path_for_domain(stack, manifest))
194
+ traefik_path = reject_unsafe_value(traefik_cfg.get('pathPrefix', get_api_path_for_domain(stack, manifest)), 'traefik.pathPrefix')
194
195
 
195
196
  nats_cfg = manifest.get('nats', {}) if manifest else {}
196
- nats_queue = nats_cfg.get('queueGroup', stack + '_backend_svc')
197
+ nats_queue = reject_unsafe_value(nats_cfg.get('queueGroup', stack + '_backend_svc'), 'nats.queueGroup')
197
198
  nats_url = PlatformDockerConstants.NATS_URL
198
199
 
199
200
  # Auth configuration: one shared builder keeps this identical to the generated env file (see AuthConfig.from_manifest).
@@ -203,6 +204,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
203
204
  # secrets.required / secrets.optional, read from the project .env by Compose (empty with TDK_SECRET_PROVIDER=infisical)
204
205
  secrets_env = get_secret_environment_lines(manifest, res_name)
205
206
 
207
+ byo_image = reject_unsafe_value(manifest.get('image'), 'image') if manifest else None
206
208
  # Use .autogenerated/Dockerfile.app.autogenerated by default for build config (primary only)
207
209
  if manifest and manifest.get('appType') == 'bring-your-own':
208
210
  if manifest.get('image'):
@@ -216,10 +218,10 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
216
218
  # `buildContext` (relative to the service directory) moves the context
217
219
  # to the source tree an imported Dockerfile lives in; `dockerfile` is then
218
220
  # relative to that context, as in Compose.
219
- custom_context = manifest.get('buildContext')
221
+ custom_context = reject_unsafe_value(manifest.get('buildContext'), 'buildContext')
220
222
  if custom_context and custom_context != '.':
221
223
  build_context = build_context + '/' + custom_context
222
- dockerfile = manifest.get('dockerfile', 'Dockerfile')
224
+ dockerfile = reject_unsafe_value(manifest.get('dockerfile', 'Dockerfile'), 'dockerfile')
223
225
  if dockerfile.startswith('./'):
224
226
  dockerfile = dockerfile[2:]
225
227
  build_config = """ build:
@@ -276,7 +278,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
276
278
  agent_env = ""
277
279
  agent_volume_section = ""
278
280
  if manifest and type(manifest.get('agent')) == 'dict':
279
- agent_durability = manifest['agent'].get('durability', 'files')
281
+ agent_durability = reject_unsafe_value(manifest['agent'].get('durability', 'files'), 'agent.durability')
280
282
  agent_env = " - AGENT_DURABILITY={}\n".format(agent_durability)
281
283
  if agent_durability == 'files':
282
284
  agent_volume = res_name + '-agent-state'
@@ -289,7 +291,7 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
289
291
  else:
290
292
  # Traefik's load-balancer check can be overridden separately in service.json
291
293
  # (`traefik.healthCheck`); it defaults to the container check's path.
292
- traefik_health_path = traefik_cfg.get('healthCheck') or health_path
294
+ traefik_health_path = reject_unsafe_value(traefik_cfg.get('healthCheck'), 'traefik.healthCheck') or health_path
293
295
  traefik_labels = get_backend_traefik_labels(
294
296
  resource_entry_name=resource_entry_name,
295
297
  traefik_host=traefik_host,
@@ -354,8 +356,8 @@ def _generate_single_backend_entry(resource_path, resource_name, res, manifest,
354
356
  res_name=res_name,
355
357
  resource_name=resource_name,
356
358
  image_name=(
357
- manifest.get('image')
358
- if manifest and manifest.get('appType') == 'bring-your-own' and manifest.get('image')
359
+ byo_image
360
+ if manifest and manifest.get('appType') == 'bring-your-own' and byo_image
359
361
  else PlatformDockerConstants.app_image_name(resource_name, res_name)
360
362
  ),
361
363
  build_config=build_config,
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2026 Flisk Landscape contributors
2
+ # SPDX-License-Identifier: MIT
3
+ # =============================================================================
4
+ # Defence in depth for values written into generated Compose / Traefik YAML.
5
+ # parser.star already refuses these values, but a caller that reaches a generator directly bypasses it.
6
+ # A line break is the only way to add a YAML key, so refuse it here too (GHSA-phgf-pww4-7jxc, #710).
7
+ # Keep in step with _LINE_BREAK_OR_CONTROL in engine/topologies/tilt/manifest/parser.star and
8
+ # hasLineBreakOrControl in cli/src/utils/service-manifest.ts. This file has no load() on purpose.
9
+ # =============================================================================
10
+
11
+ _LINE_BREAK_OR_CONTROL = [chr(i) for i in range(32)] + [chr(127), "\u0085", "\u2028", "\u2029"]
12
+
13
+ def reject_unsafe_value(value, field):
14
+ """Return value unchanged, or fail() if a string contains a line break or control character.
15
+
16
+ Non-strings (None, numbers) pass through. The value is not echoed, because it may contain the line break that makes it dangerous.
17
+ """
18
+ if type(value) != "string":
19
+ return value
20
+ for bad in _LINE_BREAK_OR_CONTROL:
21
+ if bad in value:
22
+ fail("MANIFEST ERROR: '{}' must not contain line breaks or control characters".format(field))
23
+ return value
@@ -37,10 +37,17 @@ load("./sablier_container_cycle.star",
37
37
  "sablier_middleware_suffix",
38
38
  "sablier_container_labels",
39
39
  )
40
+ load("../compose/unsafe_value.star", "reject_unsafe_value")
40
41
 
41
42
 
42
43
  def get_frontend_traefik_labels(res_name, domain, base_path, port, traefik_host=None, manifest=None):
43
44
  """Generate Traefik labels for frontend services."""
45
+ reject_unsafe_value(res_name, 'res_name')
46
+ reject_unsafe_value(domain, 'domain')
47
+ reject_unsafe_value(base_path, 'base_path')
48
+ reject_unsafe_value(port, 'port')
49
+ reject_unsafe_value(traefik_host, 'traefik_host')
50
+
44
51
  # Priority based on path length ensures more specific paths win over broader ones
45
52
  router_priority = TRAEFIK_FRONTEND_PRIORITY_BASE + len(base_path or "")
46
53
  frontend_route_rule = frontend_rule(res_name, base_path, traefik_host)
@@ -111,6 +118,18 @@ def get_backend_traefik_labels(
111
118
  manifest=None,
112
119
  ):
113
120
  """Generate Traefik labels for backend services with enhanced health checks."""
121
+ reject_unsafe_value(resource_entry_name, 'resource_entry_name')
122
+ reject_unsafe_value(traefik_host, 'traefik_host')
123
+ reject_unsafe_value(traefik_path, 'traefik_path')
124
+ reject_unsafe_value(traefik_resource_name, 'traefik_resource_name')
125
+ reject_unsafe_value(health_path, 'health_path')
126
+ reject_unsafe_value(internal_port, 'internal_port')
127
+ if manifest:
128
+ reject_unsafe_value(manifest.get('stack'), 'stack')
129
+ traefik_cfg = manifest.get('traefik') or {}
130
+ reject_unsafe_value(traefik_cfg.get('host'), 'traefik.host')
131
+ reject_unsafe_value(traefik_cfg.get('pathPrefix'), 'traefik.pathPrefix')
132
+
114
133
  backend_route_rule = backend_rule(traefik_host, traefik_path)
115
134
  backend_entrypoints = build_entrypoints(
116
135
  TRAEFIK_BACKEND_ENABLE_HTTP,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flisk-sh/flisk",
3
- "version": "1.3.204",
3
+ "version": "1.3.206",
4
4
  "description": "Flisk CLI — start services on your machine.",
5
5
  "homepage": "https://flisk.sh",
6
6
  "repository": {
@@ -82,7 +82,7 @@
82
82
  "chalk": "^6.0.1",
83
83
  "ink": "^8.0.0",
84
84
  "react": "^19.3.0",
85
- "@types/node": "^22.0.0",
85
+ "@types/node": "^26.6.5",
86
86
  "knip": "^6.38.0",
87
87
  "yaml": "^2.9.1"
88
88
  },
@@ -1,21 +0,0 @@
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.204",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,6 +0,0 @@
1
- import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
- function x(r,e,t){let n=r.indexOf(e);if(n===-1)return r;let o=e.length,s=0,i="";do i+=r.slice(s,n)+e+t,s=n+o,n=r.indexOf(e,s);while(n!==-1);return i+=r.slice(s),i}function I(r,e,t,n){let o=0,s="";do{let i=r[n-1]==="\r";s+=r.slice(o,i?n-1:n)+e+(i?`\r
3
- `:`
4
- `)+t,o=n+1,n=r.indexOf(`
5
- `,o)}while(n!==-1);return s+=r.slice(o),s}var F=(r=0)=>e=>`\x1B[${e+r}m`,T=(r=0)=>e=>`\x1B[${38+r};5;${e}m`,R=(r=0)=>(e,t,n)=>`\x1B[${38+r};2;${e};${t};${n}m`,$=r=>`\x1B[58;5;${r<90?r-30:r-90+8}m`,l={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],underlineDouble:["4:2",24],underlineCurly:["4:3",24],underlineDotted:["4:4",24],underlineDashed:["4:5",24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]},underlineColor:{underlineBlack:["58;5;0",59],underlineRed:["58;5;1",59],underlineGreen:["58;5;2",59],underlineYellow:["58;5;3",59],underlineBlue:["58;5;4",59],underlineMagenta:["58;5;5",59],underlineCyan:["58;5;6",59],underlineWhite:["58;5;7",59],underlineBlackBright:["58;5;8",59],underlineGray:["58;5;8",59],underlineGrey:["58;5;8",59],underlineRedBright:["58;5;9",59],underlineGreenBright:["58;5;10",59],underlineYellowBright:["58;5;11",59],underlineBlueBright:["58;5;12",59],underlineMagentaBright:["58;5;13",59],underlineCyanBright:["58;5;14",59],underlineWhiteBright:["58;5;15",59]}},M=Object.keys(l.modifier),y=Object.keys(l.color),E=Object.keys(l.bgColor),U=Object.keys(l.underlineColor),S=[...y,...E];function V(){let r=new Map;for(let[e,t]of Object.entries(l)){for(let[n,o]of Object.entries(t))l[n]={open:`\x1B[${o[0]}m`,close:`\x1B[${o[1]}m`},t[n]=l[n],r.set(Number.parseInt(o[0],10),o[1]);Object.defineProperty(l,e,{value:t,enumerable:!1})}return Object.defineProperty(l,"codes",{value:r,enumerable:!1}),l.color.close="\x1B[39m",l.bgColor.close="\x1B[49m",l.underlineColor.close="\x1B[59m",l.color.ansi=F(),l.color.ansi256=T(),l.color.ansi16m=R(),l.bgColor.ansi=F(10),l.bgColor.ansi256=T(10),l.bgColor.ansi16m=R(10),l.underlineColor.ansi=$,l.underlineColor.ansi256=T(20),l.underlineColor.ansi16m=R(20),Object.defineProperties(l,{rgbToAnsi256:{value(e,t,n){return e===t&&t===n?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(t/255*5)+Math.round(n/255*5)},enumerable:!1},hexToRgb:{value(e){let t=/[\da-f]{6}|[\da-f]{3}/i.exec(e.toString(16));if(!t)return[0,0,0];let[n]=t;n.length===3&&(n=[...n].map(s=>s+s).join(""));let o=Number.parseInt(n,16);return[o>>16&255,o>>8&255,o&255]},enumerable:!1},hexToAnsi256:{value:e=>l.rgbToAnsi256(...l.hexToRgb(e)),enumerable:!1},ansi256ToAnsi:{value(e){if(e<8)return 30+e;if(e<16)return 90+(e-8);let t,n,o;if(e>=232)t=((e-232)*10+8)/255,n=t,o=t;else{e-=16;let f=e%36;t=Math.floor(e/36)/5,n=Math.floor(f/6)/5,o=f%6/5}let s=Math.max(t,n,o)*2;if(s===0)return 30;let i=30+(Math.round(o)<<2|Math.round(n)<<1|Math.round(t));return s===2&&(i+=60),i},enumerable:!1},rgbToAnsi:{value:(e,t,n)=>l.ansi256ToAnsi(l.rgbToAnsi256(e,t,n)),enumerable:!1},hexToAnsi:{value:e=>l.ansi256ToAnsi(l.hexToAnsi256(e)),enumerable:!1}}),l}var W=V(),c=W;import A from"node:process";import K from"node:os";import v from"node:tty";function a(r,e=globalThis.Deno?globalThis.Deno.args:A.argv){let t=r.startsWith("-")?"":r.length===1?"-":"--",n=e.indexOf(t+r),o=e.indexOf("--");return n!==-1&&(o===-1||n<o)}var{env:u}=A,g;a("no-color")||a("no-colors")||a("color=false")||a("color=never")?g=0:(a("color")||a("colors")||a("color=true")||a("color=always"))&&(g=1);function L(){return/^\d+$/.test(u.FORCE_COLOR)}function z(){if("FORCE_COLOR"in u){if(u.FORCE_COLOR==="false")return 0;if(u.FORCE_COLOR==="true"||u.FORCE_COLOR.length===0)return 1;if(L())return Math.min(Number.parseInt(u.FORCE_COLOR,10),3)}}function H(r){return r===0?!1:{level:r,hasBasic:!0,has256:r>=2,has16m:r>=3}}function q(r,{streamIsTTY:e,sniffFlags:t=!0}={}){let n=z();n!==void 0&&(g=n);let o=t?g:n;if(o===0)return 0;if(t){if(a("color=16m")||a("color=full")||a("color=truecolor"))return 3;if(a("color=256"))return 2}if(o!==void 0&&L())return o;if("TF_BUILD"in u&&"AGENT_NAME"in u)return 1;if(r&&!e&&o===void 0)return 0;let s=o||0;if(u.TERM==="dumb")return s;if(A.platform==="win32"){let i=K.release().split(".");return Number(i[0])>=10&&Number(i[2])>=10586?Number(i[2])>=14931?3:2:1}if("CI"in u)return["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(i=>i in u)?3:["TRAVIS","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(i=>i in u)||u.CI_NAME==="codeship"?1:s;if("TEAMCITY_VERSION"in u)return/^(?:9\.0*[1-9]\d*\.|\d{2,}\.)/.test(u.TEAMCITY_VERSION)?1:0;if(u.COLORTERM==="truecolor"||u.TERM==="xterm-kitty"||u.TERM==="xterm-ghostty"||u.TERM==="wezterm")return 3;if("TERM_PROGRAM"in u){let i=Number.parseInt((u.TERM_PROGRAM_VERSION||"").split(".",1)[0],10);switch(u.TERM_PROGRAM){case"iTerm.app":return i>=3?3:2;case"Apple_Terminal":return 2}}return/-256(?:color)?$/i.test(u.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(u.TERM)||"COLORTERM"in u?1:s}function _(r,e={}){let t=q(r,{streamIsTTY:r&&r.isTTY,...e});return H(t)}var J={stdout:_({isTTY:v.isatty(1)}),stderr:_({isTTY:v.isatty(2)})},w=J;var{stdout:j,stderr:G}=w,h=Symbol("GENERATOR"),b=Symbol("STYLER"),O=Symbol("IS_EMPTY"),C=Symbol("LEVEL"),m=Object.create(null),k=r=>{if(!Number.isSafeInteger(r)||r<0||r>3)throw new Error("The `level` should be an integer from 0 to 3")},Q={enumerable:!0,get(){return this[C]},set(r){k(r),this[C]=r}},X=(r,e={})=>{e.level!==void 0&&k(e.level);let t=j?j.level:0;r[C]=e.level===void 0?t:e.level};var Z=r=>{let e=(...t)=>t.join(" ");return X(e,r),Object.setPrototypeOf(e,p.prototype),e};function p(r){return Z(r)}Object.setPrototypeOf(p.prototype,Function.prototype);for(let[r,e]of Object.entries(c))m[r]={get(){let t=B(this,P(e.open,e.close,this[b]),this[O]);return Object.defineProperty(this,r,{value:t}),t}};m.visible={get(){let r=B(this,this[b],!0);return Object.defineProperty(this,"visible",{value:r}),r}};var ee=(r,e)=>{let t=c[e];if(r==="rgb"){let o=(i,f,d)=>t.ansi(c.rgbToAnsi(i,f,d));return[o,o,(i,f,d)=>t.ansi256(c.rgbToAnsi256(i,f,d)),t.ansi16m]}if(r==="hex"){let o=i=>t.ansi(c.hexToAnsi(i));return[o,o,i=>t.ansi256(c.hexToAnsi256(i)),i=>t.ansi16m(...c.hexToRgb(i))]}let n=o=>t.ansi(c.ansi256ToAnsi(o));return[n,n,t.ansi256,t.ansi256]},re=["rgb","hex","ansi256"];for(let r of re){let e=r[0].toUpperCase()+r.slice(1);for(let[t,n]of[[r,"color"],["bg"+e,"bgColor"],["underline"+e,"underlineColor"]]){let{close:o}=c[n],s=ee(r,n);m[t]={get(){let i=function(f,d,D){let Y=s[this.level](f,d,D);return B(this,P(Y,o,this[b]),this[O])};return Object.defineProperty(this,t,{value:i}),i}}}}var te=Object.defineProperties(()=>{},{...m,level:{enumerable:!0,get(){return this[h].level},set(r){this[h].level=r}}}),P=(r,e,t)=>{let n,o;return t===void 0?(n=r,o=e):(n=t.openAll+r,o=e+t.closeAll),{open:r,close:e,openAll:n,closeAll:o,parent:t}},B=(r,e,t)=>{let n=(...o)=>o.length===1?N(n,""+o[0]):o.length===2?N(n,`${o[0]??""} ${o[1]??""}`):N(n,o.join(" "));return Object.setPrototypeOf(n,te),n[h]=r[h]??r,n[b]=e,n[O]=t,n},N=(r,e)=>{if(r[h][C]<=0||!e)return r[O]?"":e;let t=r[b];if(t===void 0)return e;let{openAll:n,closeAll:o}=t;if(e.includes("\x1B"))for(;t!==void 0;)e=x(e,t.close,t.open),t=t.parent;let s=e.indexOf(`
6
- `);return s!==-1&&(e=I(e,o,n,s)),n+e+o};Object.defineProperties(p.prototype,{...m,level:Q});var ne=p(),he=p({level:G?G.level:0});var be=ne;export{y as a,be as b};
@@ -1,5 +0,0 @@
1
- import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
- import{b as n}from"./chunk-CF46CD6R.js";var o=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"];function w(f){let r=process.stderr,i=r.isTTY===!0,s=0,t=f,a,l=()=>r.write(`\r\x1B[2K${n.cyan(o[s])} ${t}`);i?(l(),a=setInterval(()=>{s=(s+1)%o.length,l()},80)):r.write(`- ${t}
3
- `);let c=(e,$)=>{a&&clearInterval(a),r.write(`${i?"\r\x1B[2K":""}${e} ${$??t}
4
- `)};return{get text(){return t},set text(e){t=e,i||r.write(`- ${t}
5
- `)},succeed:e=>c(n.green("\u2714"),e),fail:e=>c(n.red("\u2716"),e),warn:e=>c(n.yellow("\u26A0"),e)}}export{w as a};
@@ -1,2 +0,0 @@
1
- import{createRequire as __tdkRequire}from'node:module';const require=__tdkRequire(import.meta.url);
2
- import{Ta as _,cb as A,d as u,k as S}from"./chunk-CBFVK3TF.js";import{existsSync as w,readFileSync as h}from"node:fs";import{join as i}from"node:path";var O=["postgres",u],y=["pre_alpha","alpha","beta","out_of_scope"];function D(e){return O.includes(e)}function b(e){try{return JSON.parse(h(i(e,".tdk",S),"utf-8"))}catch{return}}function d(e){try{return w(e)?h(e,"utf-8"):void 0}catch{return}}function k(e,s){let n=r=>{let t=r;for(;t<e.length&&/\s/.test(e[t]);)t+=1;return t},a=0;for(;;){let r=e.indexOf(s,a);if(r===-1)return;let t=n(r+s.length);if(e[t]==="="&&(t=n(t+1),e[t]==="[")){let o=e.indexOf("]",t+1);return o===-1?void 0:[...e.slice(t+1,o).matchAll(/"([^"]+)"|'([^']+)'/g)].map(f=>f[1]??f[2]??"")}a=r+s.length}}function N(e){let s=i(e,".tdk",".tdk-out","Tiltfile"),n=d(s);if(n)return k(n,"ALWAYS_ENABLED_INFRA")}function M(e){let s=i(e,".tdk",".tdk-out","spec.master"),n=d(s);if(n!==void 0)return/"database-management"\s*:\s*True/.test(n)}function x(e){let s=i(e,".tdk",".tdk-out"),n=d(i(s,"Tiltfile")),a=d(i(s,"spec.master")),r=d(i(s,"tdk-cli-ext","discovery","config.star")),t=d(i(s,"tdk-cli-ext","engine","topologies","tilt","config","profiles.star"));if(!n||!a||!r||!t)return!1;let o=a.match(/PRE_ALPHA_RESOURCES\s*=\s*\{([^}]*)\}/)?.[1],f=k(r,"CORE_INFRA");return/FOCUS_MODE\s*,\s*FOCUS_ENABLED_ALL\s*,\s*FOCUS_ENABLED_RESOURCES\s*=\s*Config\.apply_focus\(cfg\)/.test(n)&&/if FOCUS_MODE and FOCUS_ENABLED_ALL\s*:/.test(n)&&/"[^"]+"\s*:\s*True|'[^']+'\s*:\s*True/.test(o??"")&&(f?.includes("postgres")??!1)&&/["']postgres["']\s*:\s*["']database-management["']/.test(r)&&/for infra in CORE_INFRA_EXPORT\s*:/.test(t)&&/needed\[INFRA_STACK_MAP_EXPORT\[infra\]\]\s*=\s*True/.test(t)}function C(e){let s=b(e);if(!s)return!1;let n=s.phases??{};for(let r of y){let t=n[r]?.enabledStacks;if(Array.isArray(t)&&t.includes(u))return!0}let a=s.always_enabled_infra??A;return Array.isArray(a)&&a.includes(u)}function L(e,s){let n=new Set;for(let t of O)n.add(t);for(let t of s)n.add(t.name),t.stack&&n.add(t.stack);let a=b(e);if(a){let t=a.phases??{};for(let f of y){let l=t[f]?.enabledStacks;if(Array.isArray(l))for(let c of l)n.add(c)}let o=a.always_enabled_infra??A;if(Array.isArray(o))for(let f of o)n.add(f)}let r=N(e);if(Array.isArray(r))for(let t of r)n.add(t);return n}function $(e,s=_(e)){let n=C(e),a=N(e),r=Array.isArray(a)&&a.includes(u),t=M(e)===!0,o=n||r||t,f=!n&&x(e),l=L(e,s),c=[],E=[];for(let p of s){let P=p.config?.dependsOn??[],g=!1;for(let m of P){if(D(m)){g=!0;continue}l.has(m)||E.push({resource:p.name,name:m})}g&&c.push(p.name)}let T=o||c.length>0,F=o?"feature":c.length>0?"dependsOn":"none";return{featureOn:o,featureOnFromProjectJson:n,featureOnFromTiltfile:r,featureOnFromSpecMaster:t,focusWouldEnableDatabaseManagement:f,dependsOnUsers:c,willStart:T,reason:F,unknownDependsOnNames:E}}export{O as a,$ as b};