@flisk-sh/flisk 1.4.2 → 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +148 -49
- package/cli/dist/backend-languages/bun.js +5 -0
- package/cli/dist/backend-languages/go.js +3 -1
- package/cli/dist/cli.js +9 -0
- package/cli/dist/commands/completion.js +8 -1
- package/cli/dist/commands/config.js +130 -55
- package/cli/dist/commands/doctor.js +66 -27
- package/cli/dist/commands/down.js +33 -1
- package/cli/dist/commands/logs.js +39 -1
- package/cli/dist/commands/project.js +12 -0
- package/cli/dist/commands/resource.js +39 -11
- package/cli/dist/commands/status.js +57 -19
- package/cli/dist/commands/up.js +221 -18
- package/cli/dist/commands/upgrade.js +2 -2
- package/cli/dist/frontend-frameworks/next.js +197 -0
- package/cli/dist/frontend-frameworks/react.js +81 -12
- package/cli/dist/frontend-frameworks/registry.js +5 -4
- package/cli/dist/frontend-frameworks/vue.js +82 -12
- package/cli/dist/generator/resource-templates.js +2 -4
- package/cli/dist/generator/template-engine.js +5 -3
- package/cli/dist/utils/bun-requirement.js +7 -4
- package/cli/dist/utils/cold-preflight.js +55 -34
- package/cli/dist/utils/config-explain.js +197 -0
- package/cli/dist/utils/demo-reset.js +22 -0
- package/cli/dist/utils/discovery-paths.js +7 -1
- package/cli/dist/utils/doctor-native.js +96 -0
- package/cli/dist/utils/host-port-plan.js +8 -3
- package/cli/dist/utils/native-project.js +41 -0
- package/cli/dist/utils/native-runtime.js +513 -0
- package/cli/dist/utils/native-service.js +95 -0
- package/cli/dist/utils/native-up.js +156 -0
- package/cli/dist/utils/platform.js +1 -1
- package/cli/dist/utils/port-conflict-fix.js +16 -14
- package/cli/dist/utils/port-occupant.js +35 -0
- package/cli/dist/utils/project-features.js +7 -16
- package/cli/dist/utils/project-templates.js +9 -9
- package/cli/dist/utils/resource-features.js +5 -5
- package/cli/dist/utils/service-manifest.js +20 -3
- package/cli/dist/utils/service-urls.js +11 -0
- package/cli/dist/utils/services.js +15 -2
- package/cli/dist/utils/startup-report.js +4 -3
- package/cli/dist/utils/tar.js +33 -28
- package/cli/dist/utils/tilt-logs.js +8 -0
- package/cli/dist/utils/tilt-process.js +4 -3
- package/cli/dist/utils/windows-doctor.js +18 -15
- package/cli/dist-bundle/chunk-BIVAAWBX.js +24 -0
- package/cli/dist-bundle/{chunk-YNCBBJ4V.js → chunk-C4UFBXRD.js} +1 -1
- package/cli/dist-bundle/{chunk-53L2JN7G.js → chunk-CAEMWNPF.js} +1 -1
- package/cli/dist-bundle/chunk-CDKEHFW6.js +35 -0
- package/cli/dist-bundle/{chunk-5QBYM33Q.js → chunk-DPQK5TIS.js} +1 -1
- package/cli/dist-bundle/chunk-ETXZ5LUG.js +18 -0
- package/cli/dist-bundle/chunk-GPUJ55MI.js +3 -0
- package/cli/dist-bundle/chunk-GT76VMUL.js +130 -0
- package/cli/dist-bundle/{chunk-IGN5UC3P.js → chunk-IDNES5PE.js} +14 -7
- package/cli/dist-bundle/{chunk-MWOVYIBB.js → chunk-MUDE4DZD.js} +5 -5
- package/cli/dist-bundle/chunk-QEBN6ZVQ.js +2 -0
- package/cli/dist-bundle/{chunk-I7TGIK5N.js → chunk-R7DWXISM.js} +1 -1
- package/cli/dist-bundle/{chunk-DU2BN46C.js → chunk-U5FCQF42.js} +1 -1
- package/cli/dist-bundle/{chunk-3XODDLRJ.js → chunk-WCGBVETR.js} +1 -1
- package/cli/dist-bundle/cli.js +626 -389
- package/cli/dist-bundle/cold-preflight-KUWOL2Q2.js +2 -0
- package/cli/dist-bundle/{demo-stage-OHNTP2UJ.js → demo-stage-QCC4IWXR.js} +1 -1
- package/cli/dist-bundle/{extension-fetch-VEFSCG4B.js → extension-fetch-KIPYDIRM.js} +1 -1
- package/cli/dist-bundle/{open-XROJ6YEY.js → open-AZNX4AC5.js} +1 -1
- package/cli/dist-bundle/project-5SWIGCNP.js +2 -0
- package/cli/dist-bundle/{project-templates-EYSQG2EO.js → project-templates-2VQPUBSQ.js} +1 -1
- package/cli/dist-bundle/{services-BIMF6MVU.js → services-EY5WKPHQ.js} +1 -1
- package/cli/dist-bundle/{tilt-port-owner-ZY5M2JC4.js → tilt-port-owner-UBU6JWOA.js} +1 -1
- package/cli/package.json +1 -1
- package/examples/{tdk-example → flisk-example}/README.md +2 -2
- package/package.json +2 -2
- package/runtime/discovery/AGENTS.md +1 -1
- package/runtime/discovery/TILT_DISCOVERY.star +1 -1
- package/runtime/discovery/deterministic.star +1 -1
- package/runtime/engine/AGENTS.md +3 -3
- package/runtime/engine/README.md +1 -1
- package/runtime/engine/REFACTORING_MANIFEST_SYSTEM.md +1 -1
- package/runtime/engine/assets/docker/wake-gateway/decide.ts +1 -1
- package/runtime/engine/assets/docker/wake-gateway/server.ts +2 -2
- package/runtime/engine/assets/scripts/mac-m1-resource-monitor.sh +6 -6
- package/runtime/engine/schemas/service-schema.json +99 -21
- package/runtime/engine/scripts/debug-container.sh +1 -1
- package/runtime/engine/scripts/generate-manifest.sh +2 -2
- package/runtime/engine/topologies/platform/docker/compose/compose.star +40 -4
- package/runtime/engine/topologies/platform/docker/compose/traefik_standalone.star +19 -4
- package/runtime/engine/topologies/platform/docker/constants.star +2 -2
- package/runtime/engine/topologies/platform/docker/dockerfile/language_dockerfile.star +6 -0
- package/runtime/engine/topologies/platform/docker/dockerfile/next_dockerfile.star +83 -0
- package/runtime/engine/topologies/platform/docker/index.star +4 -0
- package/runtime/engine/topologies/platform/docker/layers/prisma/filesystem_setup.star +7 -0
- package/runtime/engine/topologies/platform/docker/networking/traefik.star +85 -46
- package/runtime/engine/topologies/platform/docker/networking/traefik_static_routes.star +2 -2
- package/runtime/engine/topologies/tilt/common/utils_output.star +1 -0
- package/runtime/engine/topologies/tilt/generators/validators.star +1 -1
- package/runtime/engine/topologies/tilt/generators/vite/frontend.star +2 -2
- package/runtime/engine/topologies/tilt/generators/vite/generators.star +3 -0
- package/runtime/engine/topologies/tilt/manifest/constants.star +3 -0
- package/runtime/engine/topologies/tilt/manifest/mapper.star +1 -1
- package/runtime/engine/topologies/tilt/manifest/parser.star +9 -3
- package/runtime/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +9 -4
- package/runtime/engine/topologies/tilt/resources/orchestrator/generators/dependencies/resolver.star +50 -24
- package/runtime/engine/topologies/tilt/resources/orchestrator/generators/env.star +11 -2
- package/runtime/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +23 -9
- package/runtime/ext/ide-components/README.md +1 -1
- package/runtime/ext/ui-enhancements/extension.yaml +2 -2
- package/runtime/specs/specs/TILT_SERVICE_DEFAULTS.star +1 -1
- package/runtime/specs/specs/TILT_TECH_STACK.star +1 -1
- package/cli/dist-bundle/chunk-43XWL2PB.js +0 -61
- package/cli/dist-bundle/chunk-5F7YP5IR.js +0 -17
- package/cli/dist-bundle/chunk-ETKUVKJ2.js +0 -35
- package/cli/dist-bundle/chunk-K6SOCO6V.js +0 -3
- package/cli/dist-bundle/chunk-YHYRGWUH.js +0 -24
- package/cli/dist-bundle/chunk-YL56J2WX.js +0 -2
- package/cli/dist-bundle/cold-preflight-ZOPR7PWJ.js +0 -2
- package/cli/dist-bundle/project-7PTIOHGF.js +0 -2
- /package/examples/{tdk-example → flisk-example}/LICENSE +0 -0
- /package/examples/{tdk-example → flisk-example}/TILT_SERVICE_DEFAULTS.star +0 -0
- /package/examples/{tdk-example → flisk-example}/TILT_TECH_STACK.star +0 -0
- /package/examples/{tdk-example → flisk-example}/Tiltfile +0 -0
- /package/examples/{tdk-example → flisk-example}/services/platform/messaging/docker-compose.yml +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-api/package.json +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-api/service.json +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-api/src/index.ts +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-app/index.html +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-app/package.json +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-app/public/.gitkeep +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-app/service.json +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-app/src/main.tsx +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-app/src/orders.tsx +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-app/src/style.css +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-worker/package.json +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-worker/service.json +0 -0
- /package/examples/{tdk-example → flisk-example}/services/shop/orders-worker/src/index.ts +0 -0
|
@@ -36,15 +36,16 @@ export function checkWindowsRuntimeTools() {
|
|
|
36
36
|
return {
|
|
37
37
|
name: "Windows Runtime Tools",
|
|
38
38
|
didPass: false,
|
|
39
|
-
message: "Docker is not running
|
|
40
|
-
fix:
|
|
39
|
+
message: "Docker is not running or not installed.",
|
|
40
|
+
fix: '1. Install Docker Desktop: https://www.docker.com/products/docker-desktop/\n2. Start Docker Desktop and wait for "Running" status\n3. Enable WSL2 backend in Settings → General\n4. Enable WSL Integration for Ubuntu in Settings → Resources → WSL Integration\n5. Verify: docker version && docker compose version\nDocs: https://docs.docker.com/desktop/wsl/',
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
if (!findOnPath("tilt")) {
|
|
44
44
|
return {
|
|
45
45
|
name: "Windows Runtime Tools",
|
|
46
46
|
didPass: false,
|
|
47
|
-
message: "tilt.exe not found on PATH.
|
|
47
|
+
message: "tilt.exe not found on PATH.",
|
|
48
|
+
fix: "Install Tilt:\n curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash\nOr download from: https://docs.tilt.dev/install.html\nVerify: tilt version",
|
|
48
49
|
};
|
|
49
50
|
}
|
|
50
51
|
const bun = findOnPath("bun");
|
|
@@ -55,6 +56,7 @@ export function checkWindowsRuntimeTools() {
|
|
|
55
56
|
name: "Windows Runtime Tools",
|
|
56
57
|
didPass: false,
|
|
57
58
|
message: "node.exe not found on PATH for this npm installation.",
|
|
59
|
+
fix: "Install Node.js 22.12+: https://nodejs.org/\nOr use Bun (includes Node.js): https://bun.sh/install",
|
|
58
60
|
};
|
|
59
61
|
}
|
|
60
62
|
return {
|
|
@@ -62,7 +64,7 @@ export function checkWindowsRuntimeTools() {
|
|
|
62
64
|
didPass: true,
|
|
63
65
|
message: bun
|
|
64
66
|
? `Docker (${docker}), Tilt, and Bun found on PATH`
|
|
65
|
-
: `Docker (${docker}) and Tilt found on PATH; ⚠️ Bun was not found (generated services need Bun)`,
|
|
67
|
+
: `Docker (${docker}) and Tilt found on PATH; ⚠️ Bun was not found (generated services need Bun)\n Fix: curl -fsSL https://bun.sh/install | bash\n Verify: bun --version`,
|
|
66
68
|
};
|
|
67
69
|
}
|
|
68
70
|
export function checkWindowsDockerMode() {
|
|
@@ -76,8 +78,8 @@ export function checkWindowsDockerMode() {
|
|
|
76
78
|
return {
|
|
77
79
|
name: "Docker container mode",
|
|
78
80
|
didPass: false,
|
|
79
|
-
message: "Docker Desktop is using Windows containers.
|
|
80
|
-
fix:
|
|
81
|
+
message: "Docker Desktop is using Windows containers. Flisk requires Linux containers.",
|
|
82
|
+
fix: '1. Open Docker Desktop → Settings → General\n2. Ensure "Use WSL 2 instead of Hyper-V" is checked\n3. Click "Apply & Restart"\n4. Verify: docker info --format \'{{.OSType}}\' (should print "linux")\nDocs: https://docs.docker.com/desktop/wsl/',
|
|
81
83
|
};
|
|
82
84
|
}
|
|
83
85
|
return {
|
|
@@ -90,7 +92,8 @@ export function checkWindowsDockerMode() {
|
|
|
90
92
|
return {
|
|
91
93
|
name: "Docker container mode",
|
|
92
94
|
didPass: false,
|
|
93
|
-
message: "Docker is not
|
|
95
|
+
message: "Docker daemon is not responding.",
|
|
96
|
+
fix: '1. Start Docker Desktop and wait for "Running" status\n2. Verify: docker version\n3. If stuck: restart Docker Desktop or run `systemctl restart docker` in WSL2\nDocs: https://docs.docker.com/desktop/troubleshoot/',
|
|
94
97
|
};
|
|
95
98
|
}
|
|
96
99
|
}
|
|
@@ -102,12 +105,12 @@ export async function checkWindowsHostConfiguration() {
|
|
|
102
105
|
excludedRanges = parseExcludedPortRanges(output);
|
|
103
106
|
}
|
|
104
107
|
catch {
|
|
105
|
-
warnings.push("Could not inspect Windows Hyper-V excluded TCP port ranges.");
|
|
108
|
+
warnings.push("Could not inspect Windows Hyper-V excluded TCP port ranges.\n Fix: run as Administrator: netsh interface ipv4 show excludedportrange protocol=tcp\n If netsh fails, this check is skipped.");
|
|
106
109
|
}
|
|
107
110
|
const requiredPorts = [80, 443, 5432];
|
|
108
111
|
const excluded = requiredPorts.filter((port) => excludedRanges.some(([start, end]) => port >= start && port <= end));
|
|
109
112
|
if (excluded.length > 0) {
|
|
110
|
-
warnings.push(`⚠️ Windows reserved port${excluded.length > 1 ? "s" : ""} ${excluded.join(", ")} for Hyper-V/WSL
|
|
113
|
+
warnings.push(`⚠️ Windows reserved port${excluded.length > 1 ? "s" : ""} ${excluded.join(", ")} for Hyper-V/WSL.\n Fix 1 (reset reserved ranges): run as Administrator: net stop winnat && net start winnat\n Fix 2 (change Flisk ports): set FLISK_HTTP_PORT, FLISK_HTTPS_PORT, FLISK_POSTGRES_PORT in project config\n Verify: flisk doctor\n Docs: https://github.com/flisk-sh/flisk/blob/main/docs/wsl2.md#troubleshooting`);
|
|
111
114
|
}
|
|
112
115
|
const occupied = [];
|
|
113
116
|
for (const port of requiredPorts) {
|
|
@@ -131,10 +134,10 @@ export async function checkWindowsHostConfiguration() {
|
|
|
131
134
|
"-Command",
|
|
132
135
|
`$ports = '${externallyOccupied.join(",")}'.Split(','); foreach ($port in $ports) { Get-NetTCPConnection -LocalPort ([int]$port) -State Listen -ErrorAction SilentlyContinue | ForEach-Object { $connection = $_; $service = Get-CimInstance Win32_Service | Where-Object { $_.ProcessId -eq $connection.OwningProcess } | Select-Object -First 1; if ([int]$port -eq 80 -and ($service.Name -eq 'W3SVC' -or $connection.OwningProcess -eq 4)) { '80: IIS / World Wide Web Publishing (HTTP.sys)' } elseif ($service) { '{0}: {1}' -f $port, $service.DisplayName } else { '{0}: PID {1}' -f $port, $connection.OwningProcess } } }`,
|
|
133
136
|
], { encoding: "utf-8", timeout: 10_000, windowsHide: true }).trim();
|
|
134
|
-
warnings.push(`⚠️ Ports ${externallyOccupied.join(", ")} are already listening${owners ? `:\n${owners}` : "."}`);
|
|
137
|
+
warnings.push(`⚠️ Ports ${externallyOccupied.join(", ")} are already listening${owners ? `:\n${owners}` : "."}\n Fix: stop the conflicting service or change Flisk ports (FLISK_HTTP_PORT, etc.)\n Verify: flisk doctor\n Docs: https://github.com/flisk-sh/flisk/blob/main/docs/wsl2.md#troubleshooting`);
|
|
135
138
|
}
|
|
136
139
|
catch {
|
|
137
|
-
warnings.push(`⚠️ Ports ${externallyOccupied.join(", ")} are already in use
|
|
140
|
+
warnings.push(`⚠️ Ports ${externallyOccupied.join(", ")} are already in use.\n Fix: netstat -ano | findstr :${externallyOccupied.join(" :")}\n Verify: flisk doctor`);
|
|
138
141
|
}
|
|
139
142
|
}
|
|
140
143
|
let dnsOk = true;
|
|
@@ -149,7 +152,7 @@ export async function checkWindowsHostConfiguration() {
|
|
|
149
152
|
}
|
|
150
153
|
}
|
|
151
154
|
if (!dnsOk) {
|
|
152
|
-
warnings.push(`${WINDOWS_DNS_FAILURE}\
|
|
155
|
+
warnings.push(`${WINDOWS_DNS_FAILURE}\n Fix: add these lines to C:\\Windows\\System32\\drivers\\etc\\hosts (run Notepad as Administrator):\n 127.0.0.1 flisk.localhost\n 127.0.0.1 example.flisk.localhost\n Verify: ping flisk.localhost (should resolve to 127.0.0.1)\n Docs: https://github.com/flisk-sh/flisk/blob/main/docs/wsl2.md#troubleshooting`);
|
|
153
156
|
}
|
|
154
157
|
try {
|
|
155
158
|
const autocrlf = execFileSync("git", ["config", "core.autocrlf"], {
|
|
@@ -158,18 +161,18 @@ export async function checkWindowsHostConfiguration() {
|
|
|
158
161
|
windowsHide: true,
|
|
159
162
|
}).trim();
|
|
160
163
|
if (autocrlf.toLowerCase() === "true") {
|
|
161
|
-
warnings.push(
|
|
164
|
+
warnings.push('git core.autocrlf is true; generated files may get CRLF while Docker Linux containers expect LF.\n Fix: git config core.autocrlf input (run in Flisk repo root)\n Verify: git config core.autocrlf (should show "input")');
|
|
162
165
|
}
|
|
163
166
|
}
|
|
164
167
|
catch {
|
|
165
168
|
// No repository-local setting to report.
|
|
166
169
|
}
|
|
167
|
-
warnings.push("Docker Desktop Settings → Resources → File sharing must include this project directory
|
|
170
|
+
warnings.push("Docker Desktop Settings → Resources → File sharing must include this project directory.\n Fix: Docker Desktop → Settings → Resources → File sharing → add project path\n Verify: flisk doctor");
|
|
168
171
|
return {
|
|
169
172
|
name: "Windows ports and DNS",
|
|
170
173
|
didPass: dnsOk && externallyOccupied.length === 0,
|
|
171
174
|
message: warnings.length > 0
|
|
172
|
-
? warnings.join("\n")
|
|
175
|
+
? warnings.join("\n\n")
|
|
173
176
|
: "Required ports are available and Flisk localhost DNS resolves to loopback",
|
|
174
177
|
...(dnsOk ? {} : { fix: WINDOWS_DNS_FAILURE }),
|
|
175
178
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import{createRequire as __fliskRequire}from'node:module';const require=__fliskRequire(import.meta.url);
|
|
2
|
+
import{J as H,a as h,ma as D,na as U,y as x}from"./chunk-ETXZ5LUG.js";import{C as j,L as R,j as A,m as w,n as F,t as L,x as T}from"./chunk-C4UFBXRD.js";import{execFileSync as K}from"node:child_process";import{existsSync as de,mkdirSync as fe,readFileSync as G,realpathSync as pe,writeFileSync as he}from"node:fs";import{join as $,resolve as me,sep as ge}from"node:path";import{createServer as ae}from"node:net";import{connect as ie}from"node:net";function B(e,t=500){return new Promise(r=>{let s=ie({port:e,host:"127.0.0.1"}),n=o=>{s.destroy(),r(o)};s.setTimeout(t,()=>n(!1)),s.once("connect",()=>n(!0)),s.once("error",()=>n(!1))})}var ce={ingressHttp:{start:8080,end:8180},ingressHttps:{start:8443,end:8543},postgres:{start:15432,end:15532}},b={ingressHttp:"FLISK_HTTP_PORT",ingressHttps:"FLISK_HTTPS_PORT",postgres:"FLISK_POSTGRES_PORT"},E={ingressHttp:80,ingressHttps:443,postgres:5432},O={ingressHttp:E.ingressHttp,ingressHttps:E.ingressHttps};function ue(e,t){return e==="EACCES"&&t==="darwin"}async function I(e){return await B(e)?!1:new Promise(t=>{let r=ae();r.once("error",s=>{t(ue(s.code,process.platform))}),r.listen(e,"127.0.0.1",()=>r.close(()=>t(!0)))})}function le(e,t){let r=Number(t);if(!Number.isInteger(r)||r<1||r>65535)throw new R(`${e} must be an integer between 1 and 65535 (received ${JSON.stringify(t)})`,["Provide a valid port number between 1 and 65535"],1);return r}async function _(e={}){let t=e.env??process.env,r=e.isAvailable??I,s={ingressHttp:!1,ingressHttps:!1,postgres:!1},n={ingressHttp:"",ingressHttps:"",postgres:""},o={explicit:s},c=new Set;for(let a of["ingressHttp","ingressHttps","postgres"]){let u=t[b[a]],i=u!==void 0&&u.trim()!=="",l=e.ranges?.[a]??ce[a],d=O[a],f=i?[le(b[a],u)]:[...d===void 0?[]:[d],...Array.from({length:l.end-l.start+1},(g,k)=>l.start+k)],m;for(let g of f)if(!c.has(g)){if(await r(g)){m=g;break}if(i)throw new R(`${b[a]}=${g} is already in use. Choose a free host port and retry.`,["Choose a different free host port or unset the environment variable to use fallback ranges"],1)}if(m===void 0)throw new R(`No available host port in ${l.start}-${l.end} for ${a}. Set ${b[a]} to a free port and retry.`,[`Free up port range ${l.start}-${l.end} or set ${b[a]} to an available port`],1);c.add(m),o[a]=m,s[a]=i,n[a]=i?"explicit override":m===d?"requested port is free":`selected from fallback range ${l.start}-${l.end}`}return{...o,requested:{...E},reason:n}}function Je(e){return`Host ports: HTTP ${e.ingressHttp}, HTTPS ${e.ingressHttps}, Postgres ${e.postgres}`}var V=$(".flisk",".flisk-out","host-ports.json");function ke(e,t,r){return e.split(`
|
|
3
|
+
`).some(s=>{let[n="",o=""]=s.split("|"),c=n.toLowerCase(),a=t.toLowerCase();return(c.startsWith(`${a}_`)||c.startsWith(`${a}-`))&&o.includes(`:${r}->`)})}function W(e){let t=$(e,V);if(!de(t))return null;try{let r=JSON.parse(G(t,"utf-8"));if(!r||typeof r!="object")return null;let s=r;return!Number.isInteger(s.ingressHttp)||!Number.isInteger(s.ingressHttps)||!Number.isInteger(s.postgres)||!s.requested||!s.explicit||!s.reason?null:s}catch{return null}}function Xe(e,t){let r=$(e,V);fe($(e,".flisk",".flisk-out"),{recursive:!0}),he(r,`${JSON.stringify(t,null,2)}
|
|
4
|
+
`,{encoding:"utf-8",mode:384})}function et(e){process.env.FLISK_HTTP_PORT=String(e.ingressHttp),process.env.FLISK_HTTPS_PORT=String(e.ingressHttps),process.env.FLISK_POSTGRES_PORT=String(e.postgres)}var Pe="com.docker.compose.project.working_dir";function Se(e,t,r){let s=new Set([me(t)]);try{s.add(pe(t))}catch{}return e.split(`
|
|
5
|
+
`).some(n=>{let[,o="",c=""]=n.split("|");return!c||!o.includes(`:${r}->`)?!1:[...s].some(a=>c===a||c.startsWith(`${a}${ge}`))})}function tt(e,t,r=()=>K("docker",["ps","--format",`{{.Names}}|{{.Ports}}|{{.Label "${Pe}"}}`],{encoding:"utf-8",timeout:5e3})){let s=W(e);if(!s||s.ingressHttp===t)return t;try{if(Se(r(),e,s.ingressHttp))return s.ingressHttp}catch{}return t}async function rt(e,t={}){let r=W(e),s=["FLISK_HTTP_PORT","FLISK_HTTPS_PORT","FLISK_POSTGRES_PORT"].some(i=>process.env[i]);if(t.inspectDocker===!1&&r&&!s)return r;let n="";try{let i=JSON.parse(G($(e,".flisk",w),"utf-8"));n=String(i?.project?.name??"flisk-project").replace(/-/g,"_").toLowerCase()}catch{n="flisk_project"}let o="";if(t.inspectDocker!==!1)try{o=K("docker",["ps","--format","{{.Names}}|{{.Ports}}"],{encoding:"utf-8",timeout:5e3})}catch{}let c=i=>ke(o,n,i),a=t.isPortFree??I,u=async i=>await a(i)||c(i);if(r&&!s){for(let i of[r.ingressHttp,r.ingressHttps,r.postgres])if(!await u(i))return _({isAvailable:u});for(let[i,l]of Object.entries(O)){let d=r[i];if(l!==void 0&&d!==l&&await u(l))return _({isAvailable:u})}return r}return _({isAvailable:u})}import{execFileSync as X,execSync as S}from"node:child_process";import{existsSync as C,readdirSync as Te,readFileSync as N}from"node:fs";import{createServer as be}from"node:net";import{join as P}from"node:path";function J(e,t){return e==="pending"||e==="in_progress"||e==="none"||t==="pending"||t==="none"}var M="container is running, but its health check is failing";function z(e){let t=e?.runtimeStatus??"";if(t!=="ok")return t;let r=e?.composeResourceInfo?.healthStatus;return r==="unhealthy"?"error":r==="starting"?"pending":t}var y=1e4,q=3e3,$e="http://localhost:4873";function ee(e){return`'${e.replace(/'/g,"'\\''")}'`}function v(e,t,r,s,n){return process.platform==="win32"&&e===S?X(j(t)??t,r,{...n,windowsHide:!0}):e(s,n)}var ye=[80,443];function ve(e){return e.replace(/-/g,"_")}function we(e,t){let r=new Set(t),s=[];for(let n of e.split(`
|
|
6
|
+
`)){let o=n.trim();if(!o)continue;let c=o.indexOf(" "),a=c>=0?o.slice(0,c):o,u=c>=0?o.slice(c+1):"",i=[];for(let l of r)u.split(/[\s,]+/).some(f=>f.startsWith(`${l}->`)||f.includes(`:${l}->`))&&i.push(l);i.length>0&&s.push({name:a,ports:u,publishedPorts:i})}return s}function te(e,t){let r=e.toLowerCase(),s=t.toLowerCase();return r===`${s}_traefik`||r.startsWith(`${s}_traefik`)}function Re(e,t){return e.filter(r=>!te(r.name,t))}function _e(e){try{let t=e??U();return new Set(t.filter(r=>r.config?.sablier?.enable&&r.config?.sablier?.deferStart).map(r=>r.name))}catch{return new Set}}function xe(e,t=new Set){let s=JSON.parse(e).items??[],n=[],o=0,c=0,a=0;for(let u of s){let i=u.metadata?.name??"unknown",l=u.status?.updateStatus??"",d=z(u.status),f=d==="error"&&u.status?.runtimeStatus==="ok",g=(u.status?.buildHistory?.[0]?.error??"").trim()||(f?M:"");if(l==="error"||d==="error"){n.push({name:i,updateStatus:l,runtimeStatus:d,error:g.replace(/\s+/g," ").slice(0,800)});continue}if(l==="ok"&&(d==="ok"||d==="not_applicable")){a+=1;continue}i!=="(Tiltfile)"&&J(l,d)&&(t.has(i)?c+=1:o+=1)}return{failures:n,pendingCount:o,deferredCount:c,okCount:a,total:s.length}}var He=/failed to resolve source metadata for docker\.io\/library\/([A-Za-z0-9._-]+-l[1-4](?:-[a-z]+)*)(?::[^\s:]+)?:/i;function re(e){let t=e.replace(/\s+/g," ").trim(),r=t.match(/Bind for [^ ]+:(\d+) failed: port is already allocated/i);if(r)return`host port ${r[1]} is already allocated`;if(/port is already allocated/i.test(t))return"a required host port is already allocated";let s=[...t.matchAll(/ConnectionRefused downloading package manifest (@[A-Za-z0-9._/-]+)/gi)].map(a=>a[1]);if(s.length>0){let a=[...new Set(s)],u=a.slice(0,4).join(", "),i=a.length>4?` (+${a.length-4} more)`:"";return`private registry ConnectionRefused for ${u}${i} \u2014 Verdaccio (:4873) is down or unreachable from the build`}let n=t.match(He);if(n)return`base image ${n[1]} was missing when this build started (the golden layers weren't built yet, or golden-layers-build failed) - Tilt does not retry a failed build by itself`;if(/install-deps\.sh/i.test(t)||/bun install(?: --production)?/i.test(t)||/npm (?:ci|install)/i.test(t))return"dependency install failed during ImageBuild \u2014 usually Verdaccio (:4873) unreachable or missing @scoped packages (ConnectionRefused downloading package manifest)";let o=t.match(/No such image:\s*([^\s]+)/i)?.[1]??t.match(/pull access denied for ([^,:\s]+)/i)?.[1]??void 0,c=t.match(/\bup\s+-d\s+--no-build\s+([A-Za-z0-9._-]+)/i)?.[1];if(o||c||/docker compose .*\bup\s+-d\s+--no-build\b/i.test(t)){let a=o??`${c??"service"}:dev`,u=c?` for ${c}`:"";return`compose run failed because image is missing (${a})${u} \u2014 wait for the ImageBuild resource to finish, then re-trigger the *-run-only resource`}return/bun run build/i.test(t)?"ImageBuild failed during `bun run build` (compile/typecheck) \u2014 open the resource logs in Tilt for the TypeScript/build error":(/ImageBuild:/i.test(t)||/^Command "/i.test(t),t.slice(0,220))}function Z(e){return/ConnectionRefused downloading package manifest|Verdaccio|private registry|dependency install failed during ImageBuild|install-deps\.sh|bun install/i.test(e)}function Ee(e=T()??process.cwd()){let t=P(e,".flisk",w);if(!C(t))return!1;try{let r=JSON.parse(N(t,"utf-8"));return r.optional_infra?.verdaccio===!0||Object.values(r.phases??{}).some(s=>(s.enabledStacks??[]).includes("verdaccio"))}catch{return!1}}function se(e){for(let t of[P(e,".npmrc"),P(e,F)])if(C(t))try{let r=N(t,"utf-8");if(/:4873\b/.test(r)||/verdaccio/i.test(r))return!0}catch{}return!1}function Oe(e=T()??process.cwd()){return Ee(e)||se(e)}function kt(e=S,t=T()??process.cwd(),r=process.env.VERDACCIO_URL??process.env.NPM_REGISTRY_URL??$e,s=!0){if(!s&&!se(t))return{name:"Private npm registry",didPass:!0,isSkipped:!0,message:"Verdaccio is enabled in the project config but needs a Premium license, so Flisk will not start it - skipped"};if(!Oe(t))return{name:"Private npm registry",didPass:!0,isSkipped:!0,message:"Private npm registry (Verdaccio) not enabled for this project - skipped"};let n=!1;try{let a=v(e,"docker",["ps","--format","{{.Names}}"],"docker ps --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:y});n=/verdaccio/i.test(a)}catch{}let o=!1,c="";try{let a=process.platform==="win32"?X("curl.exe",["-fsS","-o","NUL","-w","%{http_code}","--max-time","2",r],{stdio:"pipe",encoding:"utf-8",timeout:q+1e3,windowsHide:!0}).trim():e(`curl -fsS -o /dev/null -w '%{http_code}' --max-time 2 ${ee(r)}`,{stdio:"pipe",encoding:"utf-8",timeout:q+1e3}).trim();o=/^[23]\d\d$/.test(a),c=`HTTP ${a}`}catch(a){c=a instanceof Error?a.message.slice(0,120):"request failed"}return o?{name:"Private npm registry",didPass:!0,message:`Private npm registry reachable at ${r}${n?" (verdaccio container running)":""}`}:n?{name:"Private npm registry",didPass:!1,message:`Verdaccio container is running but ${r} is not responding (${c}). ImageBuilds that install @scoped packages will fail with ConnectionRefused downloading package manifest.`,fix:"Check `docker logs` for the verdaccio container, confirm port 4873 is published, then re-run `flisk doctor`."}:{name:"Private npm registry",didPass:!1,message:`Private npm registry (Verdaccio) is not reachable at ${r}. Docker ImageBuilds will fail with ConnectionRefused downloading package manifests for @flisk-sh/* and project-scoped packages.`,fix:"Start the registry with `bun run verdaccio:start` (or `docker compose -f docker-compose.verdaccio.yml up -d`), publish packages with `bun run publish:all` / `scripts/build/publish-to-verdaccio.sh`, then `tilt trigger` failed resources or re-run `flisk up`."}}function Pt(e=S,t=H(),r=ye){let s=ve(t),n="";try{n=v(e,"docker",["ps","--format","{{.Names}}\\t{{.Ports}}"],"docker ps --format '{{.Names}}\\t{{.Ports}}'",{stdio:"pipe",encoding:"utf-8",timeout:y})}catch{return{name:"Ingress Ports",didPass:!0,isSkipped:!0,message:"Docker not available - skipped ingress port check"}}let o=we(n,r),c=Re(o,s);if(c.length===0){let u=o.filter(i=>te(i.name,s));return u.length>0?{name:"Ingress Ports",didPass:!0,message:`Ingress ports ${r.join("/")} held by this project's Traefik (${u.map(i=>i.name).join(", ")})`}:{name:"Ingress Ports",didPass:!0,message:`Ingress ports ${r.join("/")} are free for Traefik`}}return{name:"Ingress Ports",didPass:!1,message:`Traefik cannot bind ingress ports because another container already owns them:
|
|
7
|
+
${c.map(u=>{let i=u.publishedPorts.join(", ");return`${u.name} (host ports ${i})`}).join(`
|
|
8
|
+
`)}`,fix:`Stop the foreign container(s), e.g. \`docker stop ${c[0]?.name}\`, or shut down the other Flisk/Tilt project using that Traefik. Then re-run \`flisk up\`.`}}function Y(e,t){return new Promise(r=>{let s=be();s.once("error",n=>r(n.code==="EADDRINUSE"?"in-use":"unknown")),s.once("listening",()=>s.close(()=>r("free"))),s.listen(e,t)})}async function St(e){for(let t=0;t<2;t++){let r=await Y(e,"0.0.0.0");if(r==="unknown")return r;if(r==="free"){let s=await Y(e,"127.0.0.1");if(s==="free"||s==="unknown")return s}t===0&&await new Promise(s=>setTimeout(s,50))}return"in-use"}function Ie(e){let{status:t}=e;return t===void 0?e.error??"no response":t===404?"HTTP 404: Traefik is answering but has no route for this URL (container not started yet, or not running)":t===502||t===503||t===504?`HTTP ${t}: Traefik found the route but the container isn't answering (still starting, or unhealthy)`:`HTTP ${t}`}function Tt(e){let t=e.filter(o=>o.status!==void 0),r=e.filter(o=>!o.ok);if(t.length===0)return{name:"Service Health",didPass:!0,isSkipped:!0,message:`No services responded - skipped ping of ${h(e.length,"service")} (stack may be down, or Traefik never bound :80)`,fix:"If `flisk up` is already running, check Traefik/port 80 in the Tilt UI. Otherwise start with: flisk up"};if(r.length===0)return{name:"Service Health",didPass:!0,message:`All ${h(e.length,"service")} responding on /health`};let s=r.map(o=>`${o.name} (${Ie(o)})
|
|
9
|
+
${o.url}`).join(`
|
|
10
|
+
`),n=r.some(o=>o.status===404);return{name:"Service Health",didPass:!1,message:`${h(r.length,"service")} not healthy (${e.length-r.length}/${e.length} healthy):
|
|
11
|
+
${s}`,fix:n?"If `flisk up` just started, images may still be building: re-run `flisk doctor` in a minute. Otherwise check `docker ps` and the resource in the Tilt UI, and compare `flisk networks` with the URL above.":"Check container state and routing: docker ps, then flisk networks to compare the advertised URLs against Traefik's routers"}}function bt(e){if(e.length===0)return{name:"Service Smoke",didPass:!0,isSkipped:!0,message:"No read-only smoke checks declared"};let t=e.filter(s=>!s.ok);if(t.length===0)return{name:"Service Smoke",didPass:!0,message:`All ${h(e.length,"service")} pass their smoke checks`};let r=t.map(s=>s.failure??`${s.name}: failed`).join(`
|
|
12
|
+
`);return{name:"Service Smoke",didPass:!1,message:`${h(t.length,"service")} failing a smoke check (${e.length-t.length}/${e.length} passing):
|
|
13
|
+
${r}`,fix:'Add the route the smoke step expects, or correct its "path" in the service.json "smoke" block. Then re-run flisk doctor.'}}function $t(e){let t=e.filter(n=>n.status!==void 0);if(t.length===0)return{name:"Advertised Endpoints",didPass:!0,isSkipped:!0,message:"No services responded - skipped advertised endpoint check"};let r=t.filter(n=>n.status===404);if(r.length===0)return{name:"Advertised Endpoints",didPass:!0,message:`${h(t.length,"advertised endpoint")} reachable`};let s=r.map(n=>`${n.name} (404)
|
|
14
|
+
${n.url}`).join(`
|
|
15
|
+
`);return{name:"Advertised Endpoints",didPass:!0,isWarning:!0,message:`${h(r.length,"advertised link")} ${r.length===1?"returns":"return"} 404 (the service may be healthy, but nothing answers at this exact path):
|
|
16
|
+
${s}`,fix:'Nothing handles this exact path, so opening the link shows a 404 even when /health is fine. If this API has no root route, you can leave it. Otherwise add a GET route for it (for example one that returns the service name), or declare a read-only "smoke" step on a real route in service.json. The URL flisk networks and the Flisk App print stays the same until the CLI changes how it reports it.'}}function yt(e=S){let t="";try{t=v(e,"tilt",["get","uiresources","-o","json"],"tilt get uiresources -o json",{stdio:"pipe",encoding:"utf-8",timeout:y})}catch{return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"Tilt is not running - skipped resource status check",fix:"Start them with: flisk up"}}let r;try{r=xe(t,_e())}catch{return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"Could not parse Tilt resource status - skipped"}}if(r.total===0)return{name:"Tilt Resources",didPass:!0,isSkipped:!0,message:"No Tilt UIResources found"};if(r.failures.length===0){let p=r.deferredCount>0?`, ${r.deferredCount} deferred`:"";return{name:"Tilt Resources",didPass:!0,message:`Tilt resources healthy (${r.okCount} ok, ${r.pendingCount} pending${p})`}}let s=Ne(r.failures),o=s.slice(0,20),c=s.length-o.length,a=o.map(p=>({failure:p,why:Fe(p,e)})),u=a.map(({failure:p,why:oe})=>`${p.name}: ${oe}`).join(`
|
|
17
|
+
`),i=c>0?`
|
|
18
|
+
\u2026and ${h(c,"more failed resource")}`:"",l=r.pendingCount>0?`
|
|
19
|
+
${h(r.pendingCount,"resource")} still pending/not started \u2014 often blocked by the failures above.`:"",d=r.deferredCount>0?`
|
|
20
|
+
${h(r.deferredCount,"resource")} intentionally deferred (sablier.deferStart) \u2014 not started until first request, unrelated to the failures above.`:"",f=s.some(p=>/port is already allocated/i.test(p.error)),m=s.some(p=>Z(p.error)||Z(re(p.error))),g=a.some(({why:p})=>/Kafka broker unreachable|kafka:9092/i.test(p)),k="Open the Tilt UI URL printed by flisk up (default port "+L.tiltUi+" when TILT_PORT is unset), inspect the red resources, fix the listed errors, then `tilt trigger <resource>` or re-run `flisk up`.";return f?k="Free the conflicting host port (usually 80/443): `docker ps --filter publish=80` then `docker stop <other-traefik>`. Re-trigger Traefik in the Tilt UI or run `flisk up` again.":m?k="Start Verdaccio (`bun run verdaccio:start`), ensure packages are published (`bun run publish:all` or `bash scripts/build/publish-to-verdaccio.sh`), confirm `curl http://localhost:4873` works, then `tilt trigger` the failed resources.":g&&(k="Kafka is not running (optional infra). Start it, point the bridge at a real broker, or disable Kafka-dependent resources until Kafka is enabled."),{name:"Tilt Resources",didPass:!1,message:`Tilt reports ${h(r.failures.length,"failed resource")}:
|
|
21
|
+
${u}${i}${l}${d}`,fix:k}}var Ce=/^(traefik|postgres|nats|infisical|verdaccio|proxy)([.-]|$)/i;function Q(e){return Ce.test(e)}function Ne(e){return[...e].sort((t,r)=>{let s=Q(t.name)?0:1,n=Q(r.name)?0:1;return s!==n?s-n:t.name.localeCompare(r.name)})}function Ae(e,t=S,r=H()){try{let s=v(t,"docker",["ps","-a","--format","{{.Names}}"],"docker ps -a --format '{{.Names}}'",{stdio:"pipe",encoding:"utf-8",timeout:y}).split(`
|
|
22
|
+
`).map(i=>i.trim()).filter(Boolean),n=`-autogenerated-${e}-1`,o=s.find(i=>i===e)??s.find(i=>i.startsWith(`${r}-`)&&i.endsWith(n))??s.find(i=>i.endsWith(n))??s.find(i=>i.includes(e));if(!o)return null;let c=v(t,"docker",["logs","--tail","120",o],`docker logs --tail 120 ${ee(o)} 2>&1`,{stdio:"pipe",encoding:"utf-8",timeout:y});if(/getaddrinfo ENOTFOUND/i.test(c)&&/kafka:9092/i.test(c))return"runtime crash: Kafka broker unreachable (getaddrinfo ENOTFOUND kafka:9092)";if(/ECONNREFUSED/i.test(c)&&/kafka/i.test(c))return"runtime crash: Kafka connection refused";let a=c.match(/ConnectionRefused downloading package manifest (@[A-Za-z0-9._/-]+)/i);if(a?.[1])return`runtime/build log: private registry ConnectionRefused for ${a[1]}`;if(/ZodError/i.test(c)){let i=[...c.matchAll(/"path"\s*:\s*\[\s*"([^"]+)"\s*\]/g)].map(d=>d[1]),l=[...new Set(i)].slice(0,6);return l.length>0?`runtime crash: ZodError missing required config/env: ${l.join(", ")}`:"runtime crash: ZodError during config/env validation"}let u=c.match(/error:\s+Failed to [^:\n]+[^\n]{0,120}/i)?.[0]??c.match(/Failed to (?:start|initialize) [^\n]{0,120}/i)?.[0]??c.match(/^\s*error:\s+[^\n]{0,160}/im)?.[0];if(u)return`runtime crash: ${u.replace(/\s+/g," ").trim().slice(0,180)}`}catch{return null}return null}function Fe(e,t=S){return e.error?re(e.error):e.runtimeStatus==="error"?Ae(e.name,t)??"runtime error (container crashed or unhealthy \u2014 check Tilt/docker logs)":e.updateStatus||e.runtimeStatus||"unknown error"}var Le=/\.(ts|tsx|mts|js|mjs|cjs)$/,je=new Set(["node_modules","dist",A,"tests","__tests__"]);function ne(e){let t=[];for(let r of Te(e,{withFileTypes:!0}))r.isDirectory()?je.has(r.name)||t.push(...ne(P(e,r.name))):Le.test(r.name)&&!/\.(test|spec)\./.test(r.name)&&t.push(P(e,r.name));return t}function De(e){let t=e?.healthCheckPath||"/health";return{container:t,traefik:e?.traefik?.healthCheck||t}}function Ue(e){let t=[];for(let r of e){if(!x(r.config?.appType))continue;let s=P(r.path,"src");if(!C(s))continue;let n=ne(s);if(n.length===0)continue;let o=n.map(i=>N(i,"utf-8")),{container:c,traefik:a}=De(r.config),u=c===a?[{path:c,usedBy:"container and Traefik healthchecks"}]:[{path:c,usedBy:"container healthcheck"},{path:a,usedBy:"Traefik healthcheck"}];for(let{path:i,usedBy:l}of u){let d=["'",'"',"`"].map(f=>`${f}${i}${f}`);o.some(f=>d.some(m=>f.includes(m)))||t.push({name:r.name,healthPath:i,usedBy:l})}}return t}function vt(e=T()??process.cwd()){let t=[];try{t=D(e)}catch{return{name:"Health Routes",didPass:!0,isSkipped:!0,message:"Could not read services - skipped health route check"}}let r=t.filter(o=>x(o.config?.appType));if(r.length===0)return{name:"Health Routes",didPass:!0,isSkipped:!0,message:"No backend services to check"};let s=Ue(r);return s.length===0?{name:"Health Routes",didPass:!0,message:`All ${h(r.length,"backend")} define their health route`}:{name:"Health Routes",didPass:!1,message:`Backends without a health route (the container never turns healthy, so Traefik returns 404):
|
|
23
|
+
${s.map(o=>`${o.name}: no "${o.healthPath}" route in src/ (probed by the ${o.usedBy})`).join(`
|
|
24
|
+
`)}`,fix:`Add the route, e.g. for Hono: app.get("${s[0]?.healthPath}", (c) => c.json({ status: "ok" })). To use a different path, set "healthCheckPath" (container healthcheck) or "traefik.healthCheck" (Traefik) in its service.json.`}}export{_ as a,Je as b,W as c,Xe as d,et as e,tt as f,rt as g,J as h,z as i,ve as j,we as k,_e as l,xe as m,re as n,Ee as o,kt as p,Pt as q,St as r,Tt as s,bt as t,$t as u,yt as v,vt as w};
|
|
@@ -3,7 +3,7 @@ function G(e,t,r){let o=e.indexOf(t);if(o===-1)return e;let n=t.length,s=0,i="";
|
|
|
3
3
|
`:`
|
|
4
4
|
`)+r,n=o+1,o=e.indexOf(`
|
|
5
5
|
`,n)}while(o!==-1);return s+=e.slice(n),s}var Y=(e=0)=>t=>`\x1B[${t+e}m`,S=(e=0)=>t=>`\x1B[${38+e};5;${t}m`,I=(e=0)=>(t,r,o)=>`\x1B[${38+e};2;${t};${r};${o}m`,he=e=>`\x1B[58;5;${e<90?e-30:e-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]}},K=Object.keys(l.modifier),_=Object.keys(l.color),N=Object.keys(l.bgColor),ge=Object.keys(l.underlineColor),H=[..._,...N];function be(){let e=new Map;for(let[t,r]of Object.entries(l)){for(let[o,n]of Object.entries(r))l[o]={open:`\x1B[${n[0]}m`,close:`\x1B[${n[1]}m`},r[o]=l[o],e.set(Number.parseInt(n[0],10),n[1]);Object.defineProperty(l,t,{value:r,enumerable:!1})}return Object.defineProperty(l,"codes",{value:e,enumerable:!1}),l.color.close="\x1B[39m",l.bgColor.close="\x1B[49m",l.underlineColor.close="\x1B[59m",l.color.ansi=Y(),l.color.ansi256=S(),l.color.ansi16m=I(),l.bgColor.ansi=Y(10),l.bgColor.ansi256=S(10),l.bgColor.ansi16m=I(10),l.underlineColor.ansi=he,l.underlineColor.ansi256=S(20),l.underlineColor.ansi16m=I(20),Object.defineProperties(l,{rgbToAnsi256:{value(t,r,o){return t===r&&r===o?t<8?16:t>248?231:Math.round((t-8)/247*24)+232:16+36*Math.round(t/255*5)+6*Math.round(r/255*5)+Math.round(o/255*5)},enumerable:!1},hexToRgb:{value(t){let r=/[\da-f]{6}|[\da-f]{3}/i.exec(t.toString(16));if(!r)return[0,0,0];let[o]=r;o.length===3&&(o=[...o].map(s=>s+s).join(""));let n=Number.parseInt(o,16);return[n>>16&255,n>>8&255,n&255]},enumerable:!1},hexToAnsi256:{value:t=>l.rgbToAnsi256(...l.hexToRgb(t)),enumerable:!1},ansi256ToAnsi:{value(t){if(t<8)return 30+t;if(t<16)return 90+(t-8);let r,o,n;if(t>=232)r=((t-232)*10+8)/255,o=r,n=r;else{t-=16;let a=t%36;r=Math.floor(t/36)/5,o=Math.floor(a/6)/5,n=a%6/5}let s=Math.max(r,o,n)*2;if(s===0)return 30;let i=30+(Math.round(n)<<2|Math.round(o)<<1|Math.round(r));return s===2&&(i+=60),i},enumerable:!1},rgbToAnsi:{value:(t,r,o)=>l.ansi256ToAnsi(l.rgbToAnsi256(t,r,o)),enumerable:!1},hexToAnsi:{value:t=>l.ansi256ToAnsi(l.hexToAnsi256(t)),enumerable:!1}}),l}var xe=be(),m=xe;import j from"node:process";import Ee from"node:os";import W from"node:tty";function d(e,t=globalThis.Deno?globalThis.Deno.args:j.argv){let r=e.startsWith("-")?"":e.length===1?"-":"--",o=t.indexOf(r+e),n=t.indexOf("--");return o!==-1&&(n===-1||o<n)}var{env:c}=j,R;d("no-color")||d("no-colors")||d("color=false")||d("color=never")?R=0:(d("color")||d("colors")||d("color=true")||d("color=always"))&&(R=1);function z(){return/^\d+$/.test(c.FORCE_COLOR)}function Te(){if("FORCE_COLOR"in c){if(c.FORCE_COLOR==="false")return 0;if(c.FORCE_COLOR==="true"||c.FORCE_COLOR.length===0)return 1;if(z())return Math.min(Number.parseInt(c.FORCE_COLOR,10),3)}}function Ce(e){return e===0?!1:{level:e,hasBasic:!0,has256:e>=2,has16m:e>=3}}function Re(e,{streamIsTTY:t,sniffFlags:r=!0}={}){let o=Te();o!==void 0&&(R=o);let n=r?R:o;if(n===0)return 0;if(r){if(d("color=16m")||d("color=full")||d("color=truecolor"))return 3;if(d("color=256"))return 2}if(n!==void 0&&z())return n;if("TF_BUILD"in c&&"AGENT_NAME"in c)return 1;if(e&&!t&&n===void 0)return 0;let s=n||0;if(c.TERM==="dumb")return s;if(j.platform==="win32"){let i=Ee.release().split(".");return Number(i[0])>=10&&Number(i[2])>=10586?Number(i[2])>=14931?3:2:1}if("CI"in c)return["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(i=>i in c)?3:["TRAVIS","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(i=>i in c)||c.CI_NAME==="codeship"?1:s;if("TEAMCITY_VERSION"in c)return/^(?:9\.0*[1-9]\d*\.|\d{2,}\.)/.test(c.TEAMCITY_VERSION)?1:0;if(c.COLORTERM==="truecolor"||c.TERM==="xterm-kitty"||c.TERM==="xterm-ghostty"||c.TERM==="wezterm")return 3;if("TERM_PROGRAM"in c){let i=Number.parseInt((c.TERM_PROGRAM_VERSION||"").split(".",1)[0],10);switch(c.TERM_PROGRAM){case"iTerm.app":return i>=3?3:2;case"Apple_Terminal":return 2}}return/-256(?:color)?$/i.test(c.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(c.TERM)||"COLORTERM"in c?1:s}function J(e,t={}){let r=Re(e,{streamIsTTY:e&&e.isTTY,...t});return Ce(r)}var ke={stdout:J({isTTY:W.isatty(1)}),stderr:J({isTTY:W.isatty(2)})},X=ke;var{stdout:q,stderr:Q}=X,b=Symbol("GENERATOR"),x=Symbol("STYLER"),y=Symbol("IS_EMPTY"),k=Symbol("LEVEL"),E=Object.create(null),Z=e=>{if(!Number.isSafeInteger(e)||e<0||e>3)throw new Error("The `level` should be an integer from 0 to 3")},ye={enumerable:!0,get(){return this[k]},set(e){Z(e),this[k]=e}},Oe=(e,t={})=>{t.level!==void 0&&Z(t.level);let r=q?q.level:0;e[k]=t.level===void 0?r:t.level};var ve=e=>{let t=(...r)=>r.join(" ");return Oe(t,e),Object.setPrototypeOf(t,T.prototype),t};function T(e){return ve(e)}Object.setPrototypeOf(T.prototype,Function.prototype);for(let[e,t]of Object.entries(m))E[e]={get(){let r=M(this,ee(t.open,t.close,this[x]),this[y]);return Object.defineProperty(this,e,{value:r}),r}};E.visible={get(){let e=M(this,this[x],!0);return Object.defineProperty(this,"visible",{value:e}),e}};var Ae=(e,t)=>{let r=m[t];if(e==="rgb"){let n=(i,a,u)=>r.ansi(m.rgbToAnsi(i,a,u));return[n,n,(i,a,u)=>r.ansi256(m.rgbToAnsi256(i,a,u)),r.ansi16m]}if(e==="hex"){let n=i=>r.ansi(m.hexToAnsi(i));return[n,n,i=>r.ansi256(m.hexToAnsi256(i)),i=>r.ansi16m(...m.hexToRgb(i))]}let o=n=>r.ansi(m.ansi256ToAnsi(n));return[o,o,r.ansi256,r.ansi256]},we=["rgb","hex","ansi256"];for(let e of we){let t=e[0].toUpperCase()+e.slice(1);for(let[r,o]of[[e,"color"],["bg"+t,"bgColor"],["underline"+t,"underlineColor"]]){let{close:n}=m[o],s=Ae(e,o);E[r]={get(){let i=function(a,u,f){let me=s[this.level](a,u,f);return M(this,ee(me,n,this[x]),this[y])};return Object.defineProperty(this,r,{value:i}),i}}}}var Se=Object.defineProperties(()=>{},{...E,level:{enumerable:!0,get(){return this[b].level},set(e){this[b].level=e}}}),ee=(e,t,r)=>{let o,n;return r===void 0?(o=e,n=t):(o=r.openAll+e,n=t+r.closeAll),{open:e,close:t,openAll:o,closeAll:n,parent:r}},M=(e,t,r)=>{let o=(...n)=>n.length===1?F(o,""+n[0]):n.length===2?F(o,`${n[0]??""} ${n[1]??""}`):F(o,n.join(" "));return Object.setPrototypeOf(o,Se),o[b]=e[b]??e,o[x]=t,o[y]=r,o},F=(e,t)=>{if(e[b][k]<=0||!t)return e[y]?"":t;let r=e[x];if(r===void 0)return t;let{openAll:o,closeAll:n}=r;if(t.includes("\x1B"))for(;r!==void 0;)t=G(t,r.close,r.open),r=r.parent;let s=t.indexOf(`
|
|
6
|
-
`);return s!==-1&&(t=V(t,n,o,s)),o+t+n};Object.defineProperties(T.prototype,{...E,level:ye});var Ie=T(),ut=T({level:Q?Q.level:0});var h=Ie;var te={name:"flisk-cli-internal",private:!0,version:"1.4.2",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/flisk.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 . ../tests/generated ../tests/runtime-layout","lint:fix":"biome check . ../tests/generated ../tests/runtime-layout --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":"^26.6.5","@types/react":"^19.3.0","@vitest/coverage-v8":"5.0.5",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.5"},engines:{node:">=22.12.0"}};var mt="Container Runtime",P="bring-your-own";var ht="database-management",gt=".tiltignore",bt="service.json",Ne="docker-compose.yml",xt=".autogenerated",je="TILT_TECH_STACK.star",Fe="TILT_RESOURCE_DEFAULTS.star",re="project.json",Et="package.json",Tt=[je,Fe,"spec.master"],Ct=["backend","frontend","library","sdk","worker","migrator","mcp","agent",P],Rt={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"],[P]:[]};var kt=["monitoring","elk","debezium","golden_image","verdaccio"],yt={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"},[P]:{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"}},Ot={tiltUi:10350,traefik:8080},B="https://flisk.sh/docs/quickstart/";var vt=["node_modules",".git",".tilt",".tilt-engine","dist","build",".prisma",".turbo","coverage","tmp","temp","__tests__","test","tests",".github",".vscode","docs"],At=["Dockerfile",Ne,"docker-compose.yaml","Tiltfile","vite.config.ts","tsconfig.json","tsconfig.build.json"],Me={infra:"\u{1F3D7}\uFE0F",core:"\u{1F527}",api:"\u26A1",app:"\u{1F3A8}",orchestrator:"\u2699\uFE0F"};function wt(e){let t=e.toLowerCase();for(let[r,o]of Object.entries(Me))if(t.includes(r))return o;return"\u{1F4E6}"}import{existsSync as Pe}from"node:fs";import{dirname as Be,join as De,resolve as oe}from"node:path";import{cwd as Le}from"node:process";function v(e=Le()){let t=oe(e),r=oe("/");for(;t!==r;){if(Pe(De(t,".flisk",re)))return t;let o=Be(t);if(o===t)break;t=o}return null}var O=null;function $e(){if(O)return O;let e=te;if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Invalid package.json: expected object");let t=e;return O={name:String(t.name??"@flisk-sh/flisk"),version:String(t.version??"0.0.0"),fullPackage:t},O}function Mt(){return $e().version}import{existsSync as ne}from"node:fs";import{delimiter as se,extname as ie,join as le}from"node:path";import{delimiter as Dt,extname as Ue}from"node:path";function C(){return process.platform==="win32"}function Ge(e){return e==="linux"?"linux":e==="darwin"?"darwin":e==="win32"?"windows":null}function Ve(e){return e==="x64"?"amd64":e==="arm64"?"arm64":null}function Ye(e,t){let r=Ge(e),o=Ve(t);if(!r||!o||r==="windows"&&o!=="amd64")return null;let n=`tdk-${r}-${o}`;return r==="windows"?`${n}.exe`:n}function Lt(){return Ye(process.platform,process.arch)}function $t(){return C()?"flisk.exe":"flisk"}function D(e,t=C()){return t?Ue(e)?[e]:[e,`${e}.exe`,`${e}.cmd`,`${e}.bat`]:[e]}function A(e){let t=process.env.PATH??process.env.Path??"",r=C(),o=D(e,r);if(r&&!ie(e))for(let n of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let s=n.toLowerCase();s&&!o.includes(`${e}${s}`)&&o.push(`${e}${s}`)}for(let n of t.split(se))if(n)for(let s of o){let i=le(n,s);if(ne(i))return i}return null}function Kt(e){let t=process.env.PATH??process.env.Path??"",r=C(),o=D(e,r);if(r&&!ie(e))for(let i of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let a=i.toLowerCase();a&&!o.includes(`${e}${a}`)&&o.push(`${e}${a}`)}let n=[],s=new Set;for(let i of t.split(se))if(i)for(let a of o){let u=le(i,a);if(!ne(u))continue;let f=r?u.toLowerCase():u;s.has(f)||(s.add(f),n.push(u))}return n}import{execFileSync as Ke,execSync as He}from"node:child_process";var ce=1e4;function ae(){let e=!1;if(process.platform==="win32")try{return Ke(A("docker")??"docker",["ps"],{stdio:"ignore",timeout:ce,windowsHide:!0}),"running"}catch(t){return t.code==="ETIMEDOUT"?"unresponsive":"missing"}for(let t of["docker ps","colima status","podman ps"])try{return He(t,{stdio:"ignore",timeout:ce}),"running"}catch(r){r.code==="ETIMEDOUT"&&(e=!0)}return e?"unresponsive":"missing"}function w(e,t){return e[t]??0}function We(e,t){let r=Array.from({length:t.length+1},(o,n)=>n);for(let o=1;o<=e.length;o++){let n=[o];for(let s=1;s<=t.length;s++){let i=e[o-1]===t[s-1]?0:1;n[s]=Math.min(w(n,s-1)+1,w(r,s)+1,w(r,s-1)+i)}r=n}return w(r,t.length)}function Je(e,t){if(e.length!==t.length)return!1;for(let r=0;r<e.length-1;r++)if(e[r]!==t[r]&&e[r]===t[r+1]&&e[r+1]===t[r]&&e.slice(0,r)===t.slice(0,r)&&e.slice(r+2)===t.slice(r+2))return!0;return!1}function ue(e,t){if(e.length<2||t.length===0||t.includes(e))return;let r=e.toLowerCase(),o,n=Number.POSITIVE_INFINITY;for(let s of t){if(s.length===0)continue;let i=s.toLowerCase(),a=Je(r,i)?1:We(r,i),u=Math.max(1,Math.min(2,Math.floor(Math.max(r.length,i.length)/3)));a>u||(a<n||a===n&&(o===void 0||s<o))&&(o=s,n=a)}return o}import{spawn as ze}from"node:child_process";import{join as Xe}from"node:path";function qe(e,t=[],r={}){return new Promise((o,n)=>{let s=[e,...t];r.verbose&&console.log(`Executing: tilt ${s.join(" ")}`);let i=ze(A("tilt")??"tilt",s,{stdio:r.inheritStdio?"inherit":"pipe",shell:!1,windowsHide:process.platform==="win32",timeout:r.timeoutMs}),a="",u="";r.inheritStdio||(i.stdout?.on("data",f=>{a+=f.toString()}),i.stderr?.on("data",f=>{u+=f.toString()})),i.on("close",f=>{o({exitCode:f??1,stdout:a,stderr:u})}),i.on("error",f=>{n(new Error(`Failed to spawn tilt: ${f.message}`))})})}async function fe(){try{return(await qe("version",[],{inheritStdio:!1,timeoutMs:1e4})).exitCode===0}catch{return!1}}function Qe(){let e=v();if(!e)throw g.notInProject();return Xe(e,".flisk",".flisk-out","Tiltfile")}function de(e){let t=Qe();e.push("-f",t)}function rr(e,t={}){let r=[];return de(r),t.focusTargets&&t.focusTargets.length>0&&r.push("--",`--focus=${t.focusTargets.join(",")}`),r.push(...e),t.verbose&&!t.quiet&&r.push("--verbose"),t.watch&&r.push("--watch"),r}function or(e={}){let t=[];return de(t),e.focusTargets&&e.focusTargets.length>0&&t.push("--",`--focus=${e.focusTargets.join(",")}`),t}function pe(e){return e instanceof Error?e.message:String(e)}function fr(e,t){if(process.env.FLISK_VERBOSE){let r=t!==void 0?`: ${pe(t)}`:"";console.warn(h.gray(`${e}${r}`))}}var p=class extends Error{suggestions;exitCode;constructor(t,r=[],o=1){super(t),this.name="FliskError",this.suggestions=r,this.exitCode=o}display(){U(this.message,void 0,this.suggestions)}exit(){this.display(),process.exit(this.exitCode)}},$=class extends Error{code;constructor(t=1){super(`process.exit(${t})`),this.name="ProcessExitError",this.code=t}};function L(e,t,r=!1){let o=new Set;for(let n of e){let s=ue(n,t);s&&o.add(r?`Did you mean "${s}" for "${n}"?`:`Did you mean "${s}"?`)}return[...o]}var g={tiltNotInstalled:()=>new p("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: ${B}`]),dockerNotAvailable:()=>new p("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: ${B}`]),dockerNotResponding:()=>new p("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 p(`Stack "${e}" not found`,[...L([e],t),"Run `flisk stacks` to see available stacks","Run `flisk stack` to assign resources to a stack"]),resourceNotFound:(e,t=[])=>new p(`Resource "${e}" not found`,[...L([e],t),"Run `flisk resources` to list all resources","Check the resource name spelling"]),unknownServices:(e,t)=>{let r=L(e,t,e.length>1);return new p(`Unknown service ${e.join(", ")}. Valid names: ${t.join(", ")}`,r,2)},directoryExists:e=>new p(`Directory already exists: ${e}`,["Use `--path` to specify a different location","Remove the existing directory if no longer needed"]),invalidPath:e=>new p(`Invalid path: ${e}`,["Path must be within the project directory",'Path cannot contain special characters like <>:"|?*']),notInProject:()=>new p("Could not find project root (no .flisk/project.json found)",["Run this from within a Flisk project","Run `flisk project --yes` to initialize a new project"])};function dr(){let e=v();return e||g.notInProject().exit()}function Ze(e){e instanceof p&&e.exit(),U(pe(e)),process.exit(1)}async function et(e,t){try{return await e()}catch(r){if(r instanceof $)throw r;return t?.verbose&&r instanceof Error&&r.stack&&console.error(h.gray(r.stack)),Ze(r)}}async function pr(e,t){let r=[],o=ae();return o==="unresponsive"?r.push(g.dockerNotResponding()):o==="missing"&&r.push(g.dockerNotAvailable()),await fe()||r.push(g.tiltNotInstalled()),r.length>0&&(console.error(h.red(`
|
|
6
|
+
`);return s!==-1&&(t=V(t,n,o,s)),o+t+n};Object.defineProperties(T.prototype,{...E,level:ye});var Ie=T(),ut=T({level:Q?Q.level:0});var h=Ie;var te={name:"flisk-cli-internal",private:!0,version:"1.4.6",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/flisk.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 . ../tests/generated ../tests/runtime-layout","lint:fix":"biome check . ../tests/generated ../tests/runtime-layout --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":"^26.6.5","@types/react":"^19.3.0","@vitest/coverage-v8":"5.0.5",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.5"},engines:{node:">=22.12.0"}};var mt="Container Runtime",P="bring-your-own";var ht="database-management",gt=".tiltignore",bt="service.json",Ne="docker-compose.yml",xt=".autogenerated",je="TILT_TECH_STACK.star",Fe="TILT_RESOURCE_DEFAULTS.star",re="project.json",Et="package.json",Tt=[je,Fe,"spec.master"],Ct=["backend","frontend","library","sdk","worker","migrator","mcp","agent",P],Rt={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"],[P]:[]};var kt=["monitoring","elk","debezium","golden_image","verdaccio"],yt={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"},[P]:{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"}},Ot={tiltUi:10350,traefik:8080},B="https://flisk.sh/docs/quickstart/";var vt=["node_modules",".git",".tilt",".tilt-engine","dist","build",".prisma",".turbo","coverage","tmp","temp","__tests__","test","tests",".github",".vscode","docs"],At=["Dockerfile",Ne,"docker-compose.yaml","Tiltfile","vite.config.ts","tsconfig.json","tsconfig.build.json"],Me={infra:"\u{1F3D7}\uFE0F",core:"\u{1F527}",api:"\u26A1",app:"\u{1F3A8}",orchestrator:"\u2699\uFE0F"};function wt(e){let t=e.toLowerCase();for(let[r,o]of Object.entries(Me))if(t.includes(r))return o;return"\u{1F4E6}"}import{existsSync as Pe}from"node:fs";import{dirname as Be,join as De,resolve as oe}from"node:path";import{cwd as Le}from"node:process";function v(e=Le()){let t=oe(e),r=oe("/");for(;t!==r;){if(Pe(De(t,".flisk",re)))return t;let o=Be(t);if(o===t)break;t=o}return null}var O=null;function $e(){if(O)return O;let e=te;if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Invalid package.json: expected object");let t=e;return O={name:String(t.name??"@flisk-sh/flisk"),version:String(t.version??"0.0.0"),fullPackage:t},O}function Mt(){return $e().version}import{existsSync as ne}from"node:fs";import{delimiter as se,extname as ie,join as le}from"node:path";import{delimiter as Dt,extname as Ue}from"node:path";function C(){return process.platform==="win32"}function Ge(e){return e==="linux"?"linux":e==="darwin"?"darwin":e==="win32"?"windows":null}function Ve(e){return e==="x64"?"amd64":e==="arm64"?"arm64":null}function Ye(e,t){let r=Ge(e),o=Ve(t);if(!r||!o||r==="windows"&&o!=="amd64")return null;let n=`flisk-${r}-${o}`;return r==="windows"?`${n}.exe`:n}function Lt(){return Ye(process.platform,process.arch)}function $t(){return C()?"flisk.exe":"flisk"}function D(e,t=C()){return t?Ue(e)?[e]:[e,`${e}.exe`,`${e}.cmd`,`${e}.bat`]:[e]}function A(e){let t=process.env.PATH??process.env.Path??"",r=C(),o=D(e,r);if(r&&!ie(e))for(let n of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let s=n.toLowerCase();s&&!o.includes(`${e}${s}`)&&o.push(`${e}${s}`)}for(let n of t.split(se))if(n)for(let s of o){let i=le(n,s);if(ne(i))return i}return null}function Kt(e){let t=process.env.PATH??process.env.Path??"",r=C(),o=D(e,r);if(r&&!ie(e))for(let i of(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";")){let a=i.toLowerCase();a&&!o.includes(`${e}${a}`)&&o.push(`${e}${a}`)}let n=[],s=new Set;for(let i of t.split(se))if(i)for(let a of o){let u=le(i,a);if(!ne(u))continue;let f=r?u.toLowerCase():u;s.has(f)||(s.add(f),n.push(u))}return n}import{execFileSync as Ke,execSync as He}from"node:child_process";var ce=1e4;function ae(){let e=!1;if(process.platform==="win32")try{return Ke(A("docker")??"docker",["ps"],{stdio:"ignore",timeout:ce,windowsHide:!0}),"running"}catch(t){return t.code==="ETIMEDOUT"?"unresponsive":"missing"}for(let t of["docker ps","colima status","podman ps"])try{return He(t,{stdio:"ignore",timeout:ce}),"running"}catch(r){r.code==="ETIMEDOUT"&&(e=!0)}return e?"unresponsive":"missing"}function w(e,t){return e[t]??0}function We(e,t){let r=Array.from({length:t.length+1},(o,n)=>n);for(let o=1;o<=e.length;o++){let n=[o];for(let s=1;s<=t.length;s++){let i=e[o-1]===t[s-1]?0:1;n[s]=Math.min(w(n,s-1)+1,w(r,s)+1,w(r,s-1)+i)}r=n}return w(r,t.length)}function Je(e,t){if(e.length!==t.length)return!1;for(let r=0;r<e.length-1;r++)if(e[r]!==t[r]&&e[r]===t[r+1]&&e[r+1]===t[r]&&e.slice(0,r)===t.slice(0,r)&&e.slice(r+2)===t.slice(r+2))return!0;return!1}function ue(e,t){if(e.length<2||t.length===0||t.includes(e))return;let r=e.toLowerCase(),o,n=Number.POSITIVE_INFINITY;for(let s of t){if(s.length===0)continue;let i=s.toLowerCase(),a=Je(r,i)?1:We(r,i),u=Math.max(1,Math.min(2,Math.floor(Math.max(r.length,i.length)/3)));a>u||(a<n||a===n&&(o===void 0||s<o))&&(o=s,n=a)}return o}import{spawn as ze}from"node:child_process";import{join as Xe}from"node:path";function qe(e,t=[],r={}){return new Promise((o,n)=>{let s=[e,...t];r.verbose&&console.log(`Executing: tilt ${s.join(" ")}`);let i=ze(A("tilt")??"tilt",s,{stdio:r.inheritStdio?"inherit":"pipe",shell:!1,windowsHide:process.platform==="win32",timeout:r.timeoutMs}),a="",u="";r.inheritStdio||(i.stdout?.on("data",f=>{a+=f.toString()}),i.stderr?.on("data",f=>{u+=f.toString()})),i.on("close",f=>{o({exitCode:f??1,stdout:a,stderr:u})}),i.on("error",f=>{n(new Error(`Failed to spawn tilt: ${f.message}`))})})}async function fe(){try{return(await qe("version",[],{inheritStdio:!1,timeoutMs:1e4})).exitCode===0}catch{return!1}}function Qe(){let e=v();if(!e)throw g.notInProject();return Xe(e,".flisk",".flisk-out","Tiltfile")}function de(e){let t=Qe();e.push("-f",t)}function rr(e,t={}){let r=[];return de(r),t.focusTargets&&t.focusTargets.length>0&&r.push("--",`--focus=${t.focusTargets.join(",")}`),r.push(...e),t.verbose&&!t.quiet&&r.push("--verbose"),t.watch&&r.push("--watch"),r}function or(e={}){let t=[];return de(t),e.focusTargets&&e.focusTargets.length>0&&t.push("--",`--focus=${e.focusTargets.join(",")}`),t}function pe(e){return e instanceof Error?e.message:String(e)}function fr(e,t){if(process.env.FLISK_VERBOSE){let r=t!==void 0?`: ${pe(t)}`:"";console.warn(h.gray(`${e}${r}`))}}var p=class extends Error{suggestions;exitCode;constructor(t,r=[],o=1){super(t),this.name="FliskError",this.suggestions=r,this.exitCode=o}display(){U(this.message,void 0,this.suggestions)}exit(){this.display(),process.exit(this.exitCode)}},$=class extends Error{code;constructor(t=1){super(`process.exit(${t})`),this.name="ProcessExitError",this.code=t}};function L(e,t,r=!1){let o=new Set;for(let n of e){let s=ue(n,t);s&&o.add(r?`Did you mean "${s}" for "${n}"?`:`Did you mean "${s}"?`)}return[...o]}var g={tiltNotInstalled:()=>new p("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: ${B}`]),dockerNotAvailable:()=>new p("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: ${B}`]),dockerNotResponding:()=>new p("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 p(`Stack "${e}" not found`,[...L([e],t),"Run `flisk stacks` to see available stacks","Run `flisk stack` to assign resources to a stack"]),resourceNotFound:(e,t=[])=>new p(`Resource "${e}" not found`,[...L([e],t),"Run `flisk resources` to list all resources","Check the resource name spelling"]),unknownServices:(e,t)=>{let r=L(e,t,e.length>1);return new p(`Unknown service ${e.join(", ")}. Valid names: ${t.join(", ")}`,r,2)},directoryExists:e=>new p(`Directory already exists: ${e}`,["Use `--path` to specify a different location","Remove the existing directory if no longer needed"]),invalidPath:e=>new p(`Invalid path: ${e}`,["Path must be within the project directory",'Path cannot contain special characters like <>:"|?*']),notInProject:()=>new p("Could not find project root (no .flisk/project.json found)",["Run this from within a Flisk project","Run `flisk project --yes` to initialize a new project"])};function dr(){let e=v();return e||g.notInProject().exit()}function Ze(e){e instanceof p&&e.exit(),U(pe(e)),process.exit(1)}async function et(e,t){try{return await e()}catch(r){if(r instanceof $)throw r;return t?.verbose&&r instanceof Error&&r.stack&&console.error(h.gray(r.stack)),Ze(r)}}async function pr(e,t){let r=[],o=ae();return o==="unresponsive"?r.push(g.dockerNotResponding()):o==="missing"&&r.push(g.dockerNotAvailable()),await fe()||r.push(g.tiltNotInstalled()),r.length>0&&(console.error(h.red(`
|
|
7
7
|
Flisk can't start - missing prerequisites:
|
|
8
8
|
`)),r.forEach((n,s)=>{s>0&&console.error(""),n.display()}),console.error(h.gray("\nRun `flisk doctor` for a full environment check.")),process.exit(1)),et(e,t)}function mr(e,t=1,r){U(e,void 0,r),process.exit(t)}function U(e,t,r){if(console.error(h.red(`\u274C ${e}`)),t&&console.error(h.gray(` ${t}`)),r&&r.length>0){console.error(h.yellow(`
|
|
9
9
|
\u{1F4A1} Suggestions:`));for(let o of r)console.error(h.cyan(` \u2192 ${o}`))}}function hr(e,t){console.error(h.red(`
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{createRequire as __fliskRequire}from'node:module';const require=__fliskRequire(import.meta.url);
|
|
2
|
-
import{f as A}from"./chunk-
|
|
2
|
+
import{f as A}from"./chunk-C4UFBXRD.js";var o=[A,"proxy"];export{o as a};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import{createRequire as __fliskRequire}from'node:module';const require=__fliskRequire(import.meta.url);
|
|
2
|
+
import{a as $}from"./chunk-QEBN6ZVQ.js";import{b as O,c as V,d as Y,p as J,q as K,v as L,w as I,y as A}from"./chunk-MUDE4DZD.js";import{C as ie,D as G,E as W,fa as ae,h as D,i as B,ka as se,la as ce,na as le,o as h,p as b,pa as pe,q as t,qa as fe,ra as de}from"./chunk-ETXZ5LUG.js";import{N as U,P as z,R as C,b as g,f as P,m as N,o as E,x as T}from"./chunk-C4UFBXRD.js";import{execFileSync as je}from"node:child_process";import{cpSync as _e,existsSync as S,readdirSync as we,readFileSync as H,writeFileSync as xe}from"node:fs";import{basename as he,dirname as Pe,isAbsolute as Ee,join as j,resolve as M}from"node:path";import{cwd as ke}from"node:process";import{fileURLToPath as Ce}from"node:url";import{Command as Oe}from"commander";var ye="-y, --yes",be="Skip prompts and confirmations; use defaults";function ue(e,o=be){return e.option(ye,o,!1)}async function Se(e,o=!0){let l=await I({message:e,initial:o});return l||D(),l}function Le(e,o=1){e.valid||C(e.error??"Validation failed",o)}function Ie(e,o,l,s){return e.dryRun?(s?s():(console.log(`Dry run - ${o}`),console.log(`Would run: ${l}`)),!0):!1}async function qe(e,o){return await Se(e,!0)?!0:(o&&o(),!1)}var q=new Map;function me(e){e!==void 0?q.delete(e):q.clear()}function Be(e=!1){let o=T(),l=o??"";if(!e){let f=q.get(l);if(f)return f}let{resources:s,problems:p}=o?se(o):{resources:le(),problems:[]},u=de(s),n=fe(s);ce(p);let r=s.filter(f=>!f.stack),d=new Map;for(let f of s)if(f.stack){let a=d.get(f.stack)||[];a.push(f),d.set(f.stack,a)}let m={resources:s,problems:p,stacks:u,stackNames:n,unassignedResources:r,resourcesByStack:d};return q.set(l,m),m}var R={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 FLISK_LICENSE_KEY)",category:"premium",phase:"pre_alpha",enabled_by_default:!1,dependsOn:[]},[P]:{name:P,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:[P]},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:[P]},"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 Q(e,o){try{return pe(e,o)}catch{return[]}}function Ae(e){return new Set([...e.phases.pre_alpha.enabledStacks,...e.phases.alpha.enabledStacks,...e.phases.beta.enabledStacks,...e.phases.out_of_scope.enabledStacks])}function X(e,o){let l=Ae(e),s=o.filter(p=>!l.has(p));return s.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,...s])),s)}function gt(e,o){let l=j(e,".flisk",N);if(!S(l))return[];let s=J(e),p=X(s,Q(e,o));return p.length>0&&O(l,s),p}function $e(){return Object.values(R).filter(e=>e.enabled_by_default&&e.category==="core").map(e=>e.name)}function Re(e,o){return o||($[e]?.repo.split("/").pop()??e).replace(/\.git$/,"")}function ge(e){return e.split(`
|
|
3
|
+
`).map(l=>l.trim()).filter(Boolean).pop()??"unknown error"}async function Fe(e,o,l,s={}){let p=$[e];if(!p){console.log(g.red(`
|
|
4
|
+
\u274C Unknown template: "${e}"`)),console.log(g.yellow(`
|
|
5
|
+
Available templates:`));for(let[r,d]of Object.entries($))console.log(` ${g.cyan(r)} ${g.gray(`- ${d.description}`)}`);console.log(g.gray("\nOr run `flisk project` with no template for a blank project.")),process.exit(1)}let u=Re(e,o);ae(u)||U.invalidPath(u).exit();let n=Ee(u)?u:M(ke(),u);S(n)&&we(n).length>0&&U.directoryExists(n).exit(),s.quiet||(B(`Cloning template: ${e}`),t(`${p.description}
|
|
6
|
+
`,0),t(`Source: ${p.bundledPath?"bundled Flisk example":p.repo}`,0),t(`Destination: ${n}
|
|
7
|
+
`,0));try{if(p.bundledPath){let r=M(Pe(Ce(new URL("../dist/commands/project.js",import.meta.url).href)),"../../../");_e(M(r,p.bundledPath),n,{recursive:!0});let d=he(n).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 f=j(n,m),a=H(f,"utf-8");xe(f,a.replaceAll("flisk_example",d))}}else je("git",["clone",p.repo,n],{stdio:["ignore","pipe","pipe"],encoding:"utf-8"})}catch(r){let d=r instanceof Error?r.message:String(r),m=p.bundledPath?`Bundled example copy failed (${ge(d)}). Reinstall the Flisk CLI package and try again.`:`git clone failed: ${ge(d)}. Check you have git installed and network access.`;if(s.quiet)throw new Error(m);C(m)}if(me(),!s.quiet){console.log(g.green(`
|
|
8
|
+
\u2705 Cloned "${e}" into ${u}/`)),t(`
|
|
9
|
+
Next steps:`,0),t(`1. cd ${u}`),t("2. flisk doctor # check Docker/Tilt are ready"),t("3. flisk up # start the stack"),t(`
|
|
10
|
+
Runtime readiness:`,0);for(let r of l)t(r,0)}}var w={version:"1.0",project:{name:"",version:"1.0.0"},phases:{pre_alpha:{name:"Pre-Alpha",description:"Core infrastructure and MVP services",enabledStacks:$e()},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:{}};function ht(e){let o=JSON.parse(JSON.stringify(w));o.project.name=he(e)||"my-project",V(j(e,".flisk")),O(j(e,".flisk",N),o)}var kt=ue(new Oe("project")).alias("init").description("Initialize or validate project-level master configuration").argument("[template]",`Clone a starter example instead of a blank project (${Object.keys($).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").option("-q, --quiet","Only print what fails; used by `flisk demo`",!1).action(async(e,o)=>{let{assertMachineReadyOrExit:l,detectRuntimePrerequisites:s,formatRuntimeNextSteps:p}=await import("./cold-preflight-KUWOL2Q2.js");await l({scope:"scaffold"});let u=p(s()),n=!!o.quiet;if(e){await z(async()=>Fe(e,o.path,u,{quiet:n}));return}await z(async()=>{let r=T();r||(r=ke(),n||(b(`\u{1F680} Initializing new Flisk project...
|
|
11
|
+
`),t(`Location: ${r}
|
|
12
|
+
`,0)));let d=j(r,".flisk"),m=j(d,N);if(o.check){let c=E.every(k=>S(j(r,".flisk",".flisk-out",k))),v=S(m);if(c&&v){let k=J(r);h("Project configuration is valid"),t(`Project: ${k.project.name}`,3),t(`Phases: ${Object.keys(k.phases).join(", ")}`,3),process.exit(0)}else{if(console.log(g.yellow("\u26A0\uFE0F Project configuration incomplete:")),v||t(".flisk/project.json (not found)",3),!c)for(let k of E.filter(_=>!S(j(r,".flisk/.flisk-out",_))))t(`.flisk/.flisk-out/${k} (not found)`,3);t("Run `flisk project` to create them."),process.exit(1)}}n||(B("Project Configuration"),t(`Project root: ${r}
|
|
13
|
+
`,0)),S(d)||(V(d),n||h("Created: .flisk/ directory"));let f=S(m);if(f&&!o.force){n||h(".flisk/project.json exists");let c=JSON.parse(H(m,"utf-8")),v=J(r),k=Q(r),_=X(v,k);if((_.length>0||!c.phases)&&O(m,v),_.length>0&&!n&&t(`Auto-enabled discovered service stacks: ${_.join(", ")}`,0),n||b(`
|
|
14
|
+
\u{1F4CB} Regenerating master configuration files...
|
|
15
|
+
`),await K(r,{quiet:n}),W(r))n||h("Created: .env (the defaults work as-is)");else{let y=G(r);y.length>0&&!n&&h(`Updated: .env (added ${y.join(", ")}; existing values unchanged)`)}let F=Y(r);if(F.length>0&&!n&&h(`Added to .gitignore: ${F.join(", ")}`),!n){console.log(g.green(`
|
|
16
|
+
\u2705 Project configuration regenerated!`)),t(`
|
|
17
|
+
Generated in .flisk/.flisk-out/:`,0);for(let y of E)t(`- ${y}`);t(`
|
|
18
|
+
Runtime readiness:`,0);for(let y of u)t(y,0)}return}if(f&&o.force&&!o.yes&&(console.log(g.red(`
|
|
19
|
+
\u26A0\uFE0F WARNING: --force will overwrite .flisk/project.json!`)),!await I({message:"This will reset your project configuration. Continue?",initial:!1}))){D();return}let a,Z=Q(r);if(o.configFile){let c=M(o.configFile);S(c)||C(`Config file not found: ${c}`);let v=H(c,"utf-8");a=JSON.parse(v),n||h(`Loaded config from: ${c}`)}else if(o.yes)a=JSON.parse(JSON.stringify(w)),a.project.name=r.split("/").pop()||"my-project",n||console.log(g.gray("Using default configuration (non-interactive mode)"));else{b(`\u{1F4DD} Project Setup Wizard
|
|
20
|
+
`);let c=await L({message:"Project name:",initial:r.split("/").pop()||"my-project",validate:i=>i.trim()!==""||"Project name is required"}),v=await L({message:"Project version:",initial:"1.0.0-alpha"}),k=Object.values(R).filter(i=>i.category==="core"&&i.phase==="pre_alpha"),_=new Set(k.map(i=>i.name)),ne=await A({message:"Select Pre-Alpha enabled stacks (core infrastructure):",choices:[...k.map(i=>({title:i.description,value:i.name,selected:i.enabled_by_default})),...Z.filter(i=>!_.has(i)).map(i=>({title:`${i} (discovered service stack)`,value:i,selected:!0}))]}),F=await A({message:"Select Alpha enabled stacks (core business):",choices:[{title:"api (Backend API)",value:"api"},{title:"app (Frontend app)",value:"app"}]}),y=await A({message:"Select Beta enabled stacks (extended features):",choices:[{title:"worker (Background jobs)",value:"worker"},{title:"migrator (Database migrations)",value:"migrator"}]}),x=await A({message:"Enable optional infrastructure (high resource):",choices:Object.values(R).filter(i=>i.category==="optional").concat(Object.values(R).filter(i=>i.category==="premium")).map(i=>({title:i.description,value:i.name,selected:i.enabled_by_default}))});b(`
|
|
21
|
+
\u{1F4C2} Service discovery`),t("What: folder patterns Flisk scans for a service.json in each match."),t("Where: type one or more globs, comma-separated."),t("How: saved as discovery.paths in .flisk/project.json - editable later."),t(`Example: ${w.discovery.paths.join(", ")}
|
|
22
|
+
`);let ve=await L({message:"Folders to scan:",initial:w.discovery.paths.join(", ")});a=JSON.parse(JSON.stringify(w)),a.project.name=c,a.project.version=v,a.phases.pre_alpha.enabledStacks=Array.from(new Set(ne)),a.phases.alpha.enabledStacks=Array.from(new Set(F)),a.phases.beta.enabledStacks=Array.from(new Set(y)),a.optional_infra.monitoring=x.includes("monitoring"),a.optional_infra.elk=x.includes("elk"),a.optional_infra.debezium=x.includes("debezium"),a.optional_infra.golden_image=x.includes("golden_image"),a.optional_infra.verdaccio=x.includes("verdaccio");let re=ve.split(",").map(i=>i.trim()).filter(i=>i.length>0);a.discovery.paths=re.length>0?re:w.discovery.paths}let ee=X(a,Z);if(ee.length>0&&!n&&t(`Auto-enabled discovered service stacks: ${ee.join(", ")}`,0),n||b(`
|
|
23
|
+
\u{1F4CB} Creating project configuration...
|
|
24
|
+
`),O(m,a),n||(h("Created: .flisk/project.json"),t(`\u2192 Project: ${a.project.name}`),b(`
|
|
25
|
+
\u{1F4CB} Generating master configuration files...
|
|
26
|
+
`)),await K(r,{quiet:n}),n||b(`
|
|
27
|
+
\u{1F527} Setting up environment variables...
|
|
28
|
+
`),W(r))n||h("Created: .env (the defaults work as-is)");else{let c=G(r);c.length>0?n||h(`Updated: .env (added ${c.join(", ")}; existing values unchanged)`):n||h("Found: .env (environment already configured)")}let te=ie(r);if(te.missing.length>0){console.log(g.yellow(`
|
|
29
|
+
\u26A0\uFE0F Missing required environment variables:`));for(let c of te.missing)t(`- ${c}`,1);t("\u2192 Edit .env and fill in these values before running `flisk up`",1)}let oe=Y(r);if(oe.length>0&&!n&&h(`Added to .gitignore: ${oe.join(", ")}`),!n){console.log(g.green(`
|
|
30
|
+
\u2705 Project configuration complete!`)),t(`
|
|
31
|
+
Generated files in .flisk/.flisk-out/:`,0);for(let c of E)t(`- ${c}`);t(`
|
|
32
|
+
Environment configuration:`,0),t("- .env (contains all required variables)"),t(`
|
|
33
|
+
Source file:`,0),t("- .flisk/project.json (edit this to change project structure)"),t(`
|
|
34
|
+
Next steps:`,0),t("1. flisk resource api --type backend --stack app # scaffold a service"),t("2. flisk up app # start it"),t(`
|
|
35
|
+
Runtime readiness:`,0);for(let c of u)t(c,0);t("\nAfter editing .flisk/project.json, run `flisk config regenerate`.",0)}})});export{me as a,Be as b,ue as c,Le as d,Ie as e,qe as f,gt as g,Re as h,Fe as i,ht as j,kt as k};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import{createRequire as __fliskRequire}from'node:module';const require=__fliskRequire(import.meta.url);
|
|
2
|
-
import{E as C,t as $}from"./chunk-
|
|
2
|
+
import{E as C,t as $}from"./chunk-C4UFBXRD.js";var g=class extends Error{kind;constructor(i,a){super(i),this.kind=a,this.name="TiltEventsLoadError"}};function m(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)?n:null}var w="\x1B",k="\x07",I=new RegExp(`${w}(?:\\[[0-?]*[ -/]*[@-~]|\\][^${k}${w}]*(?:${k}|${w}\\\\)?|[@-Z\\\\-_])`,"g"),O=new RegExp("[\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f]","g");function U(n){return n.replace(I,"").replace(O,"")}function r(n){return typeof n!="string"?void 0:U(n).trim()||void 0}function _(n){return Array.isArray(n)?n.flatMap(i=>{let a=r(i);return a?[a]:[]}):[]}function L(n){let i=m(n);if(!i||!Array.isArray(i.items))throw new Error("Tilt returned an invalid UIResource list");let a=[],e=[];for(let s of i.items){let u=m(s),N=m(u?.metadata),t=r(N?.name);if(!u||!t)continue;let c=m(u.status);a.push({name:t,runtimeStatus:r(c?.runtimeStatus),updateStatus:r(c?.updateStatus),hasPendingChanges:typeof c?.hasPendingChanges=="boolean"?c.hasPendingChanges:void 0});let x=Array.isArray(c?.buildHistory)?c.buildHistory:[];for(let[d,A]of x.entries()){let o=m(A);if(!o)continue;let f=r(o.error),l=_(o.warnings),p=[f,...l].filter(S=>!!S),h=r(o.spanID);e.push({id:`${t}:build:${h??String(d)}`,resourceName:t,kind:f?"failed":l.length?"warning":"success",title:f?"Build failed":l.length?"Build completed with warnings":"Build completed",occurredAt:r(o.finishTime)??r(o.startTime),details:p.length?p.join("; "):void 0})}let T=m(c?.currentBuild);T&&e.push({id:`${t}:current-build`,resourceName:t,kind:"running",title:"Build in progress",occurredAt:r(T.startTime)});let b=r(c?.pendingBuildSince);!T&&(c?.queued===!0||b)&&e.push({id:`${t}:queued`,resourceName:t,kind:"warning",title:"Update queued",occurredAt:b});let y=r(c?.lastDeployTime),E=y?Date.parse(y):Number.NaN,R=e.some(d=>d.resourceName===t&&d.kind==="success"&&d.occurredAt!==void 0&&Date.parse(d.occurredAt)===E);y&&!R&&e.push({id:`${t}:last-deploy`,resourceName:t,kind:"success",title:"Last deployed",occurredAt:y});let B=Array.isArray(c?.conditions)?c.conditions:[];for(let[d,A]of B.entries()){let o=m(A);if(!o)continue;let f=r(o.type),l=r(o.status),p=r(o.reason),h=r(o.message);if(!f&&!p&&!h||l==="True"&&!p&&!h)continue;let S=[p,h].filter(D=>!!D).join(": ");e.push({id:`${t}:condition:${d}:${f??"status"}`,resourceName:t,kind:l==="False"?"warning":"status",title:`Condition ${f??"status"}${l?`: ${l}`:""}`,occurredAt:r(o.lastTransitionTime),details:S||void 0})}}return e.sort((s,u)=>{if(s.kind==="running"&&u.kind!=="running")return-1;if(u.kind==="running"&&s.kind!=="running")return 1;let N=s.occurredAt?Date.parse(s.occurredAt):Number.NaN,t=u.occurredAt?Date.parse(u.occurredAt):Number.NaN;return Number.isNaN(N)?Number.isNaN(t)?s.resourceName.localeCompare(u.resourceName):1:Number.isNaN(t)?-1:t-N}),{resources:a,events:e}}async function q(){let n=process.env.TILT_PORT??String($.tiltUi),i;try{i=await C("get",["uiresources","-o","json","--port",n],{inheritStdio:!1,timeoutMs:1e4})}catch(e){let s=e instanceof Error?e.message:String(e),u=/ENOENT|not found|no such file|connection refused|failed to connect|could not connect|unable to connect|Tilt is not running/i.test(s)?"unavailable":"error";throw new g(s,u)}if(i.exitCode!==0){let e=i.stderr.trim()||`tilt get exited with code ${i.exitCode}`,s=/connection refused|failed to connect|could not connect|unable to connect|Tilt is not running|no running Tilt/i.test(e)?"unavailable":"error";throw new g(e,s)}let a;try{a=JSON.parse(i.stdout)}catch{throw new g("Tilt returned invalid UIResource JSON","error")}try{return L(a)}catch(e){throw new g(e instanceof Error?e.message:"Tilt returned an invalid UIResource list","error")}}export{g as a,U as b,q as c};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import{createRequire as __fliskRequire}from'node:module';const require=__fliskRequire(import.meta.url);
|
|
2
|
+
import{N as Y,b as p,e as P,h as ke,i as be,m as we,n as Ae,r as J,u as Te,v as Re,x as R}from"./chunk-C4UFBXRD.js";import ct,{existsSync as C,readdirSync as cn,readFileSync as un,statSync as pe}from"node:fs";import{dirname as fn,join as b}from"node:path";var I=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 _e(e){let t=0;return{isValid(){return Date.now()-t<e},markUpdated(){t=Date.now()},reset(){t=0}}}function pt(e,t,n){return e===1?t:n||`${t}s`}function Ce(e,t,n){return`${e} ${pt(e,t,n)}`}var dt={month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"};function vn(e){return new Date(e).toLocaleString("en-US",dt)}function kn(e){return new Date(e).toLocaleDateString("en-US",{month:"short",day:"numeric"})}var Z={success:{color:"green",icon:"\u2713",chalkFn:p.green},error:{color:"red",icon:"\u2717",chalkFn:p.red},warning:{color:"yellow",icon:"\u25CB",chalkFn:p.yellow},unknown:{color:"gray",icon:"?",chalkFn:p.gray}};function Q(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 bn(e){return Z[Q(e)].color}function wn(e){return Z[Q(e)].icon}function An(e,t){return Z[Q(t)].chalkFn(e)}var lt={resources:{singular:"resource",command:"flisk resource <name>",context:`
|
|
3
|
+
To create a resource:`},stacks:{singular:"stack",command:"flisk stack <stack-name>",context:`
|
|
4
|
+
To create a stack, use:`},services:{singular:"service",command:"flisk resource <name>",context:`
|
|
5
|
+
To create a service:`},"stack-services":{singular:"service",command:"flisk resource <name> --stack <stack-name>",context:`
|
|
6
|
+
To add services to this stack:`}};function Tn(e,t){let n=lt[e];console.log(t?p.yellow(`No ${n.singular}s found${t}.`):p.yellow(`No ${n.singular}s found.`)),console.log(p.gray(n.context)),console.log(p.gray(` ${n.command}`)),e==="stacks"&&(console.log(p.gray(`
|
|
7
|
+
Or create a new resource with a stack:`)),console.log(p.gray(" flisk resource <name> --stack <stack-name>")))}function Rn(e){console.log(p.yellow(e||"Cancelled."))}function _n(e){console.log(p.blue(`Flisk ${e}
|
|
8
|
+
`))}function On(e,t){console.log(p.green(`All ${e} are ${t}!`))}var X=62;function Cn(e="\u2500",t=X){return e.repeat(t)}function Oe(e,t=X-2){let n=Math.max(0,t-e.length),r=Math.floor(n/2),o=n-r;return" ".repeat(r)+e+" ".repeat(o)}function Dn(e,t){return e.length>t?`${e.slice(0,t-1)}\u2026`:e.padEnd(t)}function Nn(e,t){return e.length<=t?e:`${e.slice(0,t-3)}...`}function Fn(e){console.log(p.green(`\u2713 ${e}`))}function jn(e){console.log(p.blue(e))}function Pn(e,t=2){console.log(p.gray(`${" ".repeat(t)}${e}`))}function In(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function Mn(e,t,n=X){let r=n-2,o="\u2500".repeat(r);console.log(),console.log(p.cyan(`\u256D${o}\u256E`)),console.log(p.cyan("\u2502")+p.bold.white(Oe(e,r))+p.cyan("\u2502")),t&&(console.log(p.cyan(`\u251C${o}\u2524`)),console.log(p.cyan("\u2502")+p.gray(Oe(t,r))+p.cyan("\u2502"))),console.log(p.cyan(`\u2570${o}\u256F`))}var mt=["image","dockerfile"];function v(e){return typeof e?.command=="string"&&e.command.trim()!==""}function ee(e){return v(e.config)}function U(e){let t=ht(e),n=[];if("command"in e&&!v(e)&&n.push(`service ${t}: command must be a non-empty string`),!v(e))return n;let r=mt.filter(s=>e[s]!==void 0&&e[s]!=="");r.length>0&&n.push(`service ${t}: declares both command and ${r.join(" and ")}; a service has exactly one runtime source (remove ${r.length===1?"it":"them"} to run the command locally, or remove command to run in Docker)`);let o=e.env;if(o!==void 0){let s=o!==null&&typeof o=="object"&&!Array.isArray(o),i=s?Object.entries(o).filter(([a,u])=>!/^[A-Za-z_][A-Za-z0-9_]*$/.test(a)||typeof u!="string").map(([a])=>a):[];s?i.length>0&&n.push(`service ${t}: env ${i.join(", ")}: names must be letters, digits or _ (not starting with a digit) and values must be strings`):n.push(`service ${t}: env must be an object of string values`)}return n}function ht(e){let t=typeof e.appName=="string"?e.appName:e.name;return typeof t=="string"&&t?`"${t}"`:"(unnamed)"}function Un(e,t=e){let n=t.filter(ee).map(r=>r.name);return e.length>0&&e.every(ee)?{mode:"native",mixed:[]}:{mode:"container",mixed:n}}function Ln(e,t){return[`This run mixes services that run as local processes (${e.join(", ")}) with services that run in Docker (${t.join(", ")}).`,"Flisk cannot start both kinds in one project yet.","Give every service a `command` to run without Docker, or remove `command` from these services to run them in Docker."].join(`
|
|
9
|
+
`)}function Vn(e){return e.length>0&&e.every(ee)}function Wn(e){let t=e.trim().split(/\s+/);for(let n of t)if(!/^[A-Za-z_][A-Za-z0-9_]*=/.test(n)&&!(n==="exec"||n==="env"))return/^[A-Za-z0-9_./@+-]+$/.test(n)?n:null;return null}import{existsSync as rt,readFileSync as ot}from"node:fs";import{copyFileSync as Ge,mkdirSync as Vt,rmSync as qe,writeFileSync as Ke}from"node:fs";import{join as O}from"node:path";function A(e){return e==="backend"||e==="mcp"||e==="agent"}import{existsSync as Dt,readFileSync as Nt}from"node:fs";import{join as Ft}from"node:path";import{randomBytes as Ne}from"node:crypto";import{existsSync as ne,readFileSync as Fe,writeFileSync as je}from"node:fs";import{join as re}from"node:path";import{randomBytes as gt}from"node:crypto";import{closeSync as yt,fchmodSync as St,fsyncSync as $t,openSync as xt,renameSync as Et,rmSync as vt,statSync as kt,writeFileSync as bt}from"node:fs";import{basename as wt,dirname as At,join as Tt}from"node:path";function De(e,t){let n=Tt(At(e),`.${wt(e)}.${process.pid}.${gt(4).toString("hex")}.tmp`),r;try{r=kt(e).mode&511}catch{r=void 0}try{let o=xt(n,"wx");try{r!==void 0&&St(o,r),bt(o,t,"utf-8"),$t(o)}finally{yt(o)}Et(n,e)}catch(o){throw vt(n,{force:!0}),o}}var T=[{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}],Pe=()=>Ne(16).toString("hex"),Rt=()=>Ne(32).toString("hex"),er=T.filter(e=>e.complete).map(e=>e.name);function te(e,t){return e==="DB_PASSWORD"?t:e==="JWT_SECRET"?Rt():e==="DATABASE_URL"?`postgresql://postgres:${t}@postgres:5432/app_dev`:T.find(n=>n.name===e)?.default??""}function _t(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 u={n:`
|
|
10
|
+
`,r:"\r",t:" ",'"':'"',"\\":"\\",$:"$"};return a.replace(/\\([nrt"\\$])/g,(f,d)=>u[d]??d)}return a.replace(/\\'/g,"'")}}return t}let r=e.search(/\s#/);return(r===-1?e:e.slice(0,r)).trim()}function _(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,_t(s.slice(i+1)))}return t}function Ie(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 Me(){let e=Pe(),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 T)t.push(...Ie(n)),t.push(`${n.name}=${te(n.name,e)}`),t.push("");return t.join(`
|
|
11
|
+
`)}function Ot(e){let t=e.match(/^[a-z][a-z0-9+.-]*:\/\/[^:/@\s]+:([^@\s]*)@/i);if(!(!t||t[1].includes("$")))return t[1]}function tr(e){let t=re(e,".env"),n={missing:[],invalid:[],warnings:[]};if(!ne(t))return{missing:T.filter(i=>i.required).map(i=>i.name),invalid:[],warnings:[".env file not found - will be auto-generated"]};let r=_(Fe(t,"utf-8"));for(let i of T)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=Ot(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 Ct(e,t,n){if(!_(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 nr(e){let t=re(e,".env");if(!ne(t))return je(t,Me(),{mode:384}),T.map(c=>c.name);let n=Fe(t,"utf-8"),r=_(n),o=T.filter(c=>c.complete?r.has(c.name)?!(r.get(c.name)??"").trim():!0:!1);if(o.length===0)return[];let s=o.filter(c=>!r.has(c.name)),i=o.filter(c=>r.has(c.name)),a=r.get("DB_PASSWORD"),u=a?.trim()?a:Pe(),f=n.split(/(\r\n|\n|\r)/);for(let c of i){let h=-1;for(let l=0;l<f.length;l+=2)_(f[l]).has(c.name)&&(h=l);if(h<0)throw new Error(`Could not locate empty .env assignment for ${c.name}`);f[h]=Ct(f[h],c.name,te(c.name,u))}let d=f.join("");if(s.length>0){let c=["","# Added by Flisk: keys this version expects. Existing values above were not changed.",""];for(let l of s)c.push(...Ie(l)),c.push(`${l.name}=${te(l.name,u)}`),c.push("");let h=d.endsWith(`
|
|
12
|
+
`)||d.endsWith("\r")?"":`
|
|
13
|
+
`;d+=h+c.join(`
|
|
14
|
+
`)}return De(t,d),o.map(c=>c.name)}function rr(e){let t=re(e,".env");return ne(t)?!1:(je(t,Me(),{mode:384}),!0)}var jt="[REDACTED]",oe=class extends Error{path;constructor(t,n){super(`Could not read ${t}: ${n}`),this.path=t,this.name="EnvUnreadableError"}},Pt=8;function It(e,t=[]){let n=[...Be(Ft(e,".env")),...t.flatMap(r=>Be(r))];return[...new Set(n)].sort((r,o)=>o.length-r.length)}function Be(e){if(!Dt(e))return[];let t;try{t=Nt(e,"utf-8")}catch(n){throw new oe(e,n instanceof Error?n.message:String(n))}return[..._(t).values()].filter(n=>n.length>=Pt)}function Le(e,t){let n=e;for(let r of t)n=n.split(r).join(jt);return n}function Ue(e,t){return t.length===0?e:typeof e=="string"?Le(e,t):Array.isArray(e)?e.map(n=>Ue(n,t)):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,Ue(r,t)])):e}function Ve(e,t=[]){let n;try{n=It(e,t)}catch(r){return()=>{throw r}}return r=>Le(r,n)}import{readFileSync as Mt}from"node:fs";import{join as Bt}from"node:path";function mr(){return We(R())}function We(e){if(e)try{let t=Mt(Bt(e,".flisk",we),"utf-8"),n=JSON.parse(t);if(n?.project?.name)return n.project.name}catch{}return"flisk-project"}function L(e,t){let n=We(t??R()),r=process.env.FLISK_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):""),u=a===i?"":a;if(s==="localhost"||/^\d+\.\d+\.\d+\.\d+$/.test(s))return{appBase:`${o.protocol}//${s}${u?`:${u}`:""}`,apiBase:`${o.protocol}//${s}${u?`:${u}`:""}`};let f=s.replace(/^(app|api)\./,"");return{appBase:`${o.protocol}//app.${f}${u?`:${u}`:""}`,apiBase:`${o.protocol}//api.${f}${u?`:${u}`:""}`}}catch{return{appBase:`http://app.${n}.localhost`,apiBase:`http://api.${n}.localhost`}}}function Ut(e){return`${e.replace(/\/+$/,"")}/health`}function V(e){if(A(e.config?.appType)){let t=e.name.replace(/-api$/,"");return e.config?.apiPath??`/api/${t}`}return e.config?.basePath??`/${e.name}`}function hr(e,t){let n=e.config?.appType;if(n!=="frontend"&&!A(n))return;let{appBase:r,apiBase:o}=L(t);return`${n==="frontend"?r:o}${V(e)}`}function gr(e,t){return ze(e,t,n=>Ut(n))}function yr(e,t){return ze(e,t,n=>n)}function ze(e,t,n){let{appBase:r,apiBase:o}=L(t);return e.filter(s=>s.config?.appType==="frontend"||A(s.config?.appType)).map(s=>{let i=A(s.config.appType)?o:r;return{name:s.name,appType:s.config.appType,url:`${i}${n(V(s))}`}})}async function Lt(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 Sr(e,t){return Promise.all(e.map(n=>Lt(n,t)))}var Xe=60,He=1e3,Je=1e4,Ye=200,Ze=64*1024,Qe=new Set([404,502,503,504]),Wt=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","EHOSTUNREACH","ENETUNREACH"]),zt=new Set(["GET","HEAD","OPTIONS"]);function k(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Gt(e,t){if(zt.has(t))return!0;if(!k(e))return!1;let n=k(e.cause)?e.cause:void 0,r=e.code??n?.code;return typeof r=="string"&&Wt.has(r)}function ie(e){if(!k(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(!k(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&&(k(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 Ar(e,t){let{appBase:n,apiBase:r}=L(t),o=[];for(let s of e){let i=s.config;if(!i?.smoke)continue;let a=i.appType,u=A(a)||a===P;if(!u&&a!=="frontend"||i.exposeViaProxy===!1)continue;let f=u?r:n,d=i.healthCheckPath||(u&&a!==P?"/health":void 0);o.push({name:s.name,baseUrl:`${f}${V(s).replace(/\/+$/,"")}`,...d?.startsWith("/")?{readyPath:d}:{},smoke:i.smoke})}return o}var qt=10;function Tr(e,t={}){let n=t.timeoutSeconds??qt;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??Xe,n);return[{name:r.name,baseUrl:r.baseUrl,smoke:{via:r.smoke.via,timeoutSeconds:s,steps:o}}]})}function Kt(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 et(e,t){return e.replace(/\{\{(\w+)\}\}/g,(n,r)=>t[r]??n)}function se(e,t){return typeof e=="string"?et(e,t):Array.isArray(e)?e.map(n=>se(n,t)):k(e)?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,se(r,t)])):e}function W(e){let t=e.replace(/\s+/g," ").trim();return t.length>Ye?`${t.slice(0,Ye)}...`:t}function tt(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"step"}function Ht(e,t){let n=tt(t),r=(e.get(n)??0)+1;return e.set(n,r),r===1?n:`${n}-${r}`}function Jt(e,t,n,r,o){try{let s=O(e,tt(n.service),t);Vt(s,{recursive:!0});let i=O(s,"latest.json"),a=O(s,"body.txt");return r===void 0?qe(a,{force:!0}):Ke(a,r),Ke(i,`${JSON.stringify({...n,bodyPath:r===void 0?null:"body.txt"},null,2)}
|
|
15
|
+
`),o&&(Ge(i,O(s,"last-success.json")),r===void 0?qe(O(s,"last-success-body.txt"),{force:!0}):Ge(a,O(s,"last-success-body.txt"))),i}catch{return}}function Yt(e){let t=Buffer.from(e,"utf8");if(t.length<=Ze)return{body:e,truncated:!1,bytes:t.length};let n=t.subarray(0,Ze).toString("utf8").replace(/\uFFFD$/,"");return{body:n,truncated:!0,bytes:Buffer.byteLength(n,"utf8")}}async function Zt(e,t={}){let n=t.fetch??((d,c)=>fetch(d,c)),r=t.now??Date.now,o=t.sleep??(d=>new Promise(c=>setTimeout(c,d))),s=(e.smoke.timeoutSeconds??Xe)*1e3,i=r()+s,a={},u=ie(e.smoke);if(u.length>0)return{name:e.name,ok:!1,failure:`${e.name}: invalid smoke block: ${u.join("; ")}`};if(e.readyPath){let d=`${e.baseUrl}${e.readyPath}`;for(;;){try{let c=await n(d,{method:"GET",signal:AbortSignal.timeout(Je)});if(await c.text(),!Qe.has(c.status)&&c.status<500)break}catch{}if(r()>=i)break;await o(He)}}i=r()+s;let f=new Map;for(let[d,c]of e.smoke.steps.entries()){let h=c.name??`step ${d+1}`,l=(c.method??"GET").toUpperCase(),ye=`${e.baseUrl}${et(c.path,a)}`,D=c.expect??200,Se=c.body!==void 0,y,N="",E,q;for(;;){E=void 0,q=void 0,y=void 0;let g=!1;try{let m=await n(ye,{method:l,headers:Se?{"content-type":"application/json"}:void 0,body:Se?JSON.stringify(se(c.body,a)):void 0,signal:AbortSignal.timeout(Je)});y=m.status,N=await m.text()}catch(m){g=Gt(m,l),E=m instanceof Error?m.message:String(m);let w=k(m)?m.code??(k(m.cause)?m.cause.code:void 0):void 0;q=typeof w=="string"?w:void 0}if(!(E!==void 0&&g||y!==void 0&&y!==D&&Qe.has(y))||r()>=i)break;await o(He)}let $e=!1,K=g=>{if(!$e){if(!t.redact)return g;try{return t.redact(g)}catch($){$e=!0;let m=$ instanceof Error?$.message:String($);t.warn?.(`${e.name}: ${h}: the response text was neither shown nor stored: ${m}`);return}}},H=K(ye),S=y===void 0?void 0:K(N),xe=E===void 0?void 0:K(E),Ee=E===void 0?void 0:q??xe,F=`${e.name}: ${h}: ${l} ${H??"(url withheld)"}`,ve;if(t.recordDir){let g=S===void 0?void 0:Yt(S),$=E===void 0&&y===D&&(c.bodyContains===void 0||N.includes(c.bodyContains));ve=Jt(t.recordDir,Ht(f,h),{service:e.name,step:h,method:l,...H===void 0?{}:{url:H},expectedStatus:D,status:y??null,...Ee===void 0?{}:{error:Ee},truncated:g?.truncated??!1,bodyBytes:g?.bytes??0},g?.body,$)}let j=g=>({name:e.name,ok:!1,failure:g,recordPath:ve});if(E!==void 0)return j(`${F} never answered (${xe??"the error was withheld"})`);if(y!==D)return j(`${F} returned ${y}, expected ${D}${S?`: ${W(S)}`:""}`);if(c.bodyContains!==void 0&&!N.includes(c.bodyContains))return j(`${F} returned ${y} but the body does not contain "${c.bodyContains}"${S?`: ${W(S)}`:""}`);if(c.save){let g;try{g=JSON.parse(N)}catch{return j(`${F} returned a body that is not JSON, cannot save${S?`: ${W(S)}`:""}`)}for(let[$,m]of Object.entries(c.save)){let w=Kt(g,m);if(w==null||typeof w=="object")return j(`${F} response has no ${m} to save as {{${$}}}${S?`: ${W(S)}`:""}`);a[$]=String(w)}}}return{name:e.name,ok:!0}}function Rr(e){return`Smoke check failed: ${e.failure}${e.recordPath?` (record: ${e.recordPath})`:""}`}function _r(e,t,n={}){return{redact:Ve(e,n.envFiles??[]),...t?{warn:t}:{}}}async function Or(e,t={}){return Promise.all(e.map(n=>Zt(n,t)))}var nt=1,jr="https://flisk.sh/schema.service.json",Qt={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"},Xt=new Set(["$schema","agent","apiBasePath","apiPath","appName","appType","backendName","basePath","build","buildContext","command","databaseName","dependencies","dev","dependsOn","dockerfile","enabled","env","exposeViaProxy","featuresEnabled","framework","healthCheckPath","image","language","name","nats","params","playwright","port","replicas","restart","runtime","sablier","schemaVersion","secrets","smoke","stack","syncs","traefik","type"]),en=[{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"},{path:["basePath"],pattern:/^\/[a-z0-9/-]*$/,expected:"a path such as /storefront"}];function z(e,t){let n=[],r=new Set;for(let{path:o,pattern:s,expected:i}of en){let a=e;for(let f of o)a=a&&typeof a=="object"&&!Array.isArray(a)?a[f]:void 0;if(a==null||a==="")continue;let u=`${t}.${o.join(".")}`;(typeof a!="string"||!s.test(a))&&r.add(u),typeof a!="string"?n.push(`${u}: expected a string`):s.test(a)||n.push(`${u}: must be ${i} (no spaces, line breaks or YAML syntax)`)}for(let[o,s]of tn(e,t))r.has(o)||n.push(`${o}: ${s}`);return n}function ae(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 tn(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))ae(o)&&n.push([t,"a key contains a line break"]);for(;r.length>0;){let[o,s]=r.pop();if(typeof o=="string")ae(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))ae(i)?n.push([s,"a key contains a line break"]):r.push([a,`${s}.${i}`])}return n.sort(([o],[s])=>o.localeCompare(s))}var nn=["apiPath","basePath"];function ce(e){if(!e||typeof e!="object"||Array.isArray(e))return[];let t=e;return nn.filter(n=>n in t&&typeof t[n]!="string")}function ue(e,t){if(!e||typeof e!="object"||Array.isArray(e))return{errors:[`${t}: expected a JSON object`],warnings:[]};let n=e,r=[];if(v(n))!("appName"in n)&&typeof n.name!="string"&&r.push(`${t}.name: required field is missing`),"schemaVersion"in n||r.push(`${t}.schemaVersion: required field is missing`);else 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!==nt&&r.push(`${t}.schemaVersion: unsupported version ${String(n.schemaVersion)} (supported: ${nt})`);for(let a of ce(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(...z(n,t)),r.push(...U(n).map(a=>`${t}: ${a}`)),"smoke"in n)for(let a of ie(n.smoke))r.push(`${t}.${a}`);let i=Object.keys(n).flatMap(a=>{let u=Qt[a];return u?[`${t}.${a}: ${u}`]:Xt.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 Pr(e,t){if(!rt(e))return[];try{let n=JSON.parse(ot(e,"utf-8"));return!n||typeof n!="object"||Array.isArray(n)?[]:z(n,t)}catch{return[]}}function Ir(e,t){if(!rt(e))return{errors:[`${t}: file is missing`],warnings:[]};try{let n=JSON.parse(ot(e,"utf-8"));return ue(n,t)}catch(n){let r=n instanceof Error?n.message:String(n);return{errors:[`${t}: invalid JSON (${r})`],warnings:[]}}}function st(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 rn=/^[a-z0-9-]+$/;function it(e){return rn.test(e)}var on="Use lowercase letters, numbers, and hyphens only";function at(e,t){return`${e} "${t}" is not valid. ${on}, e.g. "${e==="Resource name"?"my-service":"my-stack"}".`}function sn(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 Lr(e){let t=e==="resource"?sn:an;return n=>{let r=t(n);return r.valid?!0:r.error??"Invalid name"}}function Vr(e){return fe(J,e)?{valid:!0}:{valid:!1,error:`Invalid service. Must be one of: ${J.join(", ")}`}}function Wr(e){return Number.isInteger(e)&&e>0&&e<=65535}function zr(e){return!e.includes("\0")&&!/[<>:"|?*]/.test(e)}function Gr(e,t="_"){return e.replace(/[^a-zA-Z0-9-]/g,t).substring(0,100)}function fe(e,t){return e.includes(t)}var pn=ke;function he(e,t=5,n=0){let r=[];if(n>t)return r;let o=ct.readdirSync(e,{withFileTypes:!0});for(let s of o){let i=b(e,s.name);if(s.isDirectory()){if(dn(s.name))continue;r.push(...he(i,t,n+1))}else s.isFile()&&s.name===pn&&r.push(i)}return r}function oo(e){return he(e)}function dn(e){return fe(Te,e)||e.startsWith(".")}function ln(e){if(!e||typeof e!="object")return!1;let t=e;if(v(t))return typeof t.appName=="string"||typeof t.name=="string";let n=typeof t.runtime=="string"||typeof t.appType=="string"||typeof t.type=="string";return typeof t.appName=="string"&&n}var M=new Set;function so(){M.clear()}var x=class extends Error{reason;constructor(t){super(t),this.reason=t,this.name="InvalidServiceJsonError"}};function de(e){return e instanceof Error?e.message:String(e)}function mn(e){let t;try{t=ct.readFileSync(e,"utf-8")}catch(f){throw new x(`could not read file: ${de(f)}`)}let n;try{n=JSON.parse(t)}catch(f){throw new x(`invalid JSON: ${de(f)}`)}if(!ln(n))throw new x("missing required fields (appName, runtime or appType)");let r=U(n);if(r.length>0)throw new x(r.join("; "));let o=ce(n);if(o.length>0)throw new x(o.map(f=>`${f}: expected a string`).join("; "));let s=z(n,e);if(s.length>0)throw new x(s.join("; "));let i=n;for(let f of ue(n,e).warnings)M.has(f)||(M.add(f),console.warn(`\u26A0\uFE0F ${f}`));let a={...i,appName:i.appName??String(i.name),appType:i.appType||i.type||(v(i)?P:void 0)},u=fn(e);return{name:a.appName,path:u,configPath:e,config:a,stack:a.stack,port:a.port,type:a.appType}}function ut(e){let t=he(e),n=[],r=[];for(let o of t)try{n.push(mn(o))}catch(s){r.push({path:o,reason:s instanceof x?s.reason:de(s)})}return{resources:n,problems:r}}function hn(e){for(let t of e){let n=`skipped ${t.path}: ${t.reason}`;M.has(n)||(M.add(n),console.warn(`\u26A0\uFE0F ${n}`))}}function ft(e){let{resources:t,problems:n}=ut(e);return hn(n),t}function G(){let e=R();if(!e)throw Y.notInProject();return ft(e)}function io(e){let t=e;if(!t){let n=R();if(!n)throw Y.notInProject();t=ut(n)}if(t.problems.length>0)throw new Error(t.problems.map(n=>`Invalid service.json at ${n.path}: ${n.reason}`).join(`
|
|
16
|
+
`));return t.resources}function ao(e,t){let n=t??ft(e);return gn(n)}function gn(e){let t=e||G(),n=new Set;for(let r of t)r.stack&&n.add(r.stack);return Array.from(n).sort()}function co(e=G()){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:Ce(o.length,"resource"),resources:o,resourceCount:o.length});return n.sort((r,o)=>r.name.localeCompare(o.name))}function uo(e,t){return(t??G()).filter(r=>r.stack===e)}function fo(e,t){return(t??G()).some(r=>r.stack===e)}var ge=5e3,le=new I({ttlMs:ge}),me=new I({ttlMs:ge}),B=_e(ge);function po(){le.clear(),me.clear(),B.reset()}function yn(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===Ae)return"config";if(e==="schema.prisma"||e.includes("migration"))return"prisma";if(t){let n=t.split(`
|
|
17
|
+
`).slice(0,10).join(`
|
|
18
|
+
`);if(n.includes("GENERATED BY Flisk")||n.includes("AUTOGENERATED"))return"generated"}return"unknown"}function Sn(e){let t=e.configPath;if(B.isValid()){let l=le.get(t);if(l)return l}let n=e.path,r=pe(e.configPath),o=r.mtime.toISOString(),s=r.mtime.toISOString(),i=$n(n),a=C(b(n,"Dockerfile")),u=C(b(n,"Tiltfile")),f=C(b(n,be))||C(b(n,"docker-compose.yaml")),d=e.config?.appType,c=d||"backend";d||(e.name.includes("frontend")?c="frontend":(e.name.includes("sdk")||e.name.includes("lib")||e.name.includes("infra"))&&(c="library"));let h={name:e.name,stack:e.stack,type:c,port:e.config?.port,createdAt:o,lastModified:s,dependencies:e.config?.dependsOn??[],hasDockerfile:a,hasTiltfile:u,hasDockerCompose:f,autogeneratedFiles:i,status:"unknown"};return le.set(t,h),B.markUpdated(),h}function $n(e){let t=[];for(let r of Re){let o=b(e,r);if(C(o)){let s=pe(o),i=un(o,"utf-8");t.push({name:r,path:o,type:yn(r,i),size:s.size,lastModified:s.mtime.toISOString()})}}let n=b(e,"prisma");if(C(n)){let r=cn(n);for(let o of r)if(o==="schema.prisma"||o.includes("migration")){let s=b(n,o),i=pe(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 lo(e){let t=e.name;if(B.isValid()){let u=me.get(t);if(u)return u}let n=e.resources.map(u=>Sn(u)),r=n.map(u=>new Date(u.createdAt).getTime()),o=Math.min(...r),s=Math.max(...r),i=st(n.map(u=>u.status)),a={name:e.name,resourceCount:n.length,createdAt:new Date(o).toISOString(),lastModified:new Date(s).toISOString(),resources:n,overallStatus:i};return me.set(t,a),B.markUpdated(),a}export{Ce as a,vn as b,kn as c,bn as d,wn as e,An as f,Tn as g,Rn as h,_n as i,On as j,X as k,Cn as l,Dn as m,Nn as n,Fn as o,jn as p,Pn as q,In as r,Mn as s,ee as t,Un as u,Ln as v,Vn as w,Wn as x,A as y,De as z,er as A,_ as B,tr as C,nr as D,rr as E,oe as F,It as G,Le as H,Ue as I,mr as J,L as K,Ut as L,V as M,hr as N,gr as O,yr as P,Sr as Q,Ar as R,Tr as S,Rr as T,_r as U,Or as V,nt as W,jr as X,ue as Y,Pr as Z,Ir as _,st as $,sn as aa,an as ba,Lr as ca,Vr as da,Wr as ea,zr as fa,Gr as ga,fe as ha,oo as ia,so as ja,ut as ka,hn as la,ft as ma,G as na,io as oa,ao as pa,gn as qa,co as ra,uo as sa,fo as ta,po as ua,Sn as va,lo as wa};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{createRequire as __fliskRequire}from'node:module';const require=__fliskRequire(import.meta.url);
|
|
2
|
+
import{randomUUID as F}from"node:crypto";import{existsSync as p,mkdirSync as g,readFileSync as y,statSync as M,writeFileSync as h}from"node:fs";import{homedir as k}from"node:os";import{join as a}from"node:path";import{spawnSync as _}from"node:child_process";import{existsSync as E,mkdirSync as w,mkdtempSync as N,readdirSync as $,renameSync as C,rmSync as L,statSync as j,writeFileSync as O}from"node:fs";import{tmpdir as D}from"node:os";import{join as c}from"node:path";function v(e,r){let n=N(c(D(),"flisk-ext-"));try{let o=c(n,"bundle.tar.gz");O(o,e),w(r,{recursive:!0});let t=process.platform==="win32"?"tar.exe":"tar",i=_(t,["xzf",o,"-C",r,"--strip-components=1"],{stdio:"pipe",windowsHide:!0});if(i.status!==0){let s=c(n,"fallback");w(s,{recursive:!0});let f=_(t,["xzf",o,"-C",s],{stdio:"pipe",windowsHide:!0});if(f.status!==0)throw new Error(`tar extraction failed: ${f.stderr?.toString()||i.stderr?.toString()||"unknown error"}`);let l=$(s),[u]=l,m=l.length===1&&u!==void 0&&E(c(s,u))&&j(c(s,u)).isDirectory()?c(s,u):s;for(let d of $(m))C(c(m,d),c(r,d))}}finally{L(n,{recursive:!0,force:!0})}}var U="https://tdk-extension-dist.oranguman.workers.dev/v1/premium/bundle.tar.gz",A=["playwright","c4-diagram","logging","agents-md","sablier","verdaccio"],z=720*60*1e3,S={"typescript/playwright_config.star":"engine/topologies/tilt/generators/typescript/playwright_config.star","generators/agents_md.star":"engine/topologies/tilt/generators/agents_md.star","c4_diagram.star":"engine/topologies/tilt/generators/c4_diagram.star","observability/logging.star":"engine/topologies/platform/observability/logging.star","generators/database_provisioner.star":"engine/topologies/tilt/generators/database_provisioner.star","generators/dependency_manifest.star":"engine/topologies/tilt/generators/dependency_manifest.star","generators/fixed_frontend_tsconfig.star":"engine/topologies/tilt/generators/typescript/fixed_frontend_tsconfig.star","synthetic_monitor.star":"engine/resources/synthetic_monitor.star","synthetic-monitor-topology.star":"engine/topologies/platform/services/synthetic-monitor.star","database-management-service.yaml":"platform/services/platform/database-management/service.yaml","networking/sablier_container_cycle.star":"engine/topologies/platform/docker/networking/sablier_container_cycle.star","registries/verdaccio_loader.star":"engine/topologies/platform/registries/verdaccio_loader.star"};function P(){return process.env.FLISK_LICENSE_KEY?.trim()||null}function R(){return process.env.FLISK_PREMIUM_ENDPOINT?.trim()||U}function I(e){let r=a(e,".flisk",".project-id");if(p(r))return y(r,"utf-8").trim();let n=F();return g(a(e,".flisk"),{recursive:!0}),h(r,`${n}
|
|
3
|
+
`),n}function B(e){let r=e.replace(/[^a-zA-Z0-9_-]/g,"_");return a(k(),".flisk","cache",`premium-${r}`,"premium.tar.gz")}function x(e){return p(e)?Date.now()-M(e).mtimeMs<z:!1}async function T(e,r,n){let o=`${R()}?resource=${encodeURIComponent(r)}&projectId=${encodeURIComponent(n)}`,t=await fetch(o,{headers:{Authorization:`Bearer ${e}`}});return t.status!==401?t:(await t.arrayBuffer().catch(()=>{}),fetch(`${o}&key=${encodeURIComponent(e)}`))}async function H(e,r){let n=[];for(let o of A){let t;try{t=await T(e,o,r)}catch(i){return console.warn(`\u26A0\uFE0F Premium fetch failed (network error): ${i.message}`),null}if(t.ok){let i=Buffer.from(await t.arrayBuffer());return console.info(`\u{1F50E} Premium entitlement probe: granted resource=${o} (HTTP ${t.status}); prior denials=${n.join(", ")||"none"}`),console.info(`\u{1F50E} Premium bundle download: ${i.byteLength} bytes`),i}if(t.status===401||t.status===403){n.push(`${o}=${t.status}`);continue}return console.warn(`\u26A0\uFE0F Premium fetch failed: ${o} returned HTTP ${t.status}; prior entitlement probes: ${n.join(", ")||"none"}`),null}return console.warn(`\u26A0\uFE0F Premium entitlement probes denied: ${n.join(", ")}`),null}async function re(e,r){let n=P();if(!n)return!1;let o=B(n);if(x(o))console.info("\u{1F50E} Premium bundle cache: hit (cached bundle reused)");else{console.info("\u{1F50E} Premium bundle cache: miss; requesting bundle from distribution service");let t=I(e),i=await H(n,t);if(!i)return console.warn("\u26A0\uFE0F No premium resources unlocked for this key - using free tier only."),!1;g(a(o,".."),{recursive:!0}),h(o,i)}try{let t=a(o,"..","extracted");g(t,{recursive:!0}),v(y(o),t);let i=0,s=[];for(let[l,u]of Object.entries(S)){let m=a(t,l);if(!p(m)){s.push(l);continue}let d=a(r,u);g(a(d,".."),{recursive:!0}),h(d,y(m)),i++}let f=a(t,"networking/sablier_container_cycle.star");if(console.info(`\u{1F50E} Premium bundle contents: mapped=${i}/${Object.keys(S).length}; sablier_overlay=${p(f)?"present":"MISSING"}`),s.length>0&&console.info(`\u{1F50E} Premium bundle missing mapped files: ${s.join(", ")}`),!p(f)&&process.env.FLISK_PREMIUM_DIAGNOSTICS==="1"){let l=await G(e);console.info(`\u{1F50E} Sablier entitlement check: ${l?"granted":"not confirmed"}; compare with sablier_overlay above to distinguish license access from bundle contents`)}return i>0?(console.log(`\u2713 Premium resources unlocked (${i} file${i===1?"":"s"})`),!0):!1}catch(t){return console.warn(`\u26A0\uFE0F Failed to apply premium overlay: ${t.message}`),!1}}function K(e,r){let n=e.replace(/[^a-zA-Z0-9_-]/g,"_");return a(k(),".flisk","cache",`premium-${n}`,`${r}-access.json`)}async function b(e,r){let n=P();if(!n)return!1;let o=K(n,r);if(x(o))try{let s=JSON.parse(y(o,"utf-8"));return console.info(`\u{1F50E} ${r} entitlement probe: cache=${s.granted===!0?"granted":"denied"}`),s.granted===!0}catch{}let t=I(e),i=!1;try{let s=await T(n,r,t);i=s.ok,console.info(`\u{1F50E} ${r} entitlement probe: HTTP ${s.status} (${i?"granted":"denied"})`),s.body&&await s.arrayBuffer().catch(()=>{})}catch(s){return console.warn(`\u26A0\uFE0F ${r} license check failed (network error): ${s.message}`),!1}try{g(a(o,".."),{recursive:!0}),h(o,JSON.stringify({granted:i,checked:new Date().toISOString()}))}catch{}return i}async function ne(e){return b(e,"verdaccio")}async function oe(e){return b(e,"ddd")}async function G(e){return b(e,"sablier")}export{v as a,re as b,ne as c,oe as d,G as e};
|