@flisk-sh/flisk 0.0.0-stage → 1.3.189

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. package/CHANGELOG.md +492 -0
  2. package/LICENSE +21 -0
  3. package/README.md +479 -2
  4. package/Tiltfile +151 -0
  5. package/cli/bin/flisk.js +42 -0
  6. package/cli/dist/agent-runtimes/custom.js +335 -0
  7. package/cli/dist/agent-runtimes/registry.js +34 -0
  8. package/cli/dist/backend-frameworks/elysia.js +38 -0
  9. package/cli/dist/backend-frameworks/express.js +49 -0
  10. package/cli/dist/backend-frameworks/fastify.js +43 -0
  11. package/cli/dist/backend-frameworks/h3.js +37 -0
  12. package/cli/dist/backend-frameworks/koa.js +47 -0
  13. package/cli/dist/backend-frameworks/mcp.js +86 -0
  14. package/cli/dist/backend-frameworks/nestjs.js +55 -0
  15. package/cli/dist/backend-frameworks/registry.js +134 -0
  16. package/cli/dist/backend-frameworks/types.js +1 -0
  17. package/cli/dist/backend-languages/bun.js +76 -0
  18. package/cli/dist/backend-languages/go.js +125 -0
  19. package/cli/dist/backend-languages/node.js +122 -0
  20. package/cli/dist/backend-languages/python.js +94 -0
  21. package/cli/dist/backend-languages/registry.js +37 -0
  22. package/cli/dist/backend-languages/rust.js +82 -0
  23. package/cli/dist/backend-languages/types.js +1 -0
  24. package/cli/dist/cli.js +29 -0
  25. package/cli/dist/commands/__tests__/project-e2e-helpers.js +49 -0
  26. package/cli/dist/commands/__tests__/ui-loading-screen.test.js +16 -0
  27. package/cli/dist/commands/agent.js +182 -0
  28. package/cli/dist/commands/completion-candidates.js +116 -0
  29. package/cli/dist/commands/completion.js +843 -0
  30. package/cli/dist/commands/config.js +362 -0
  31. package/cli/dist/commands/doctor.js +1504 -0
  32. package/cli/dist/commands/down.js +114 -0
  33. package/cli/dist/commands/eject.js +108 -0
  34. package/cli/dist/commands/help.js +152 -0
  35. package/cli/dist/commands/import.js +164 -0
  36. package/cli/dist/commands/logs.js +119 -0
  37. package/cli/dist/commands/maintainers.js +102 -0
  38. package/cli/dist/commands/mcp.js +28 -0
  39. package/cli/dist/commands/networks.js +306 -0
  40. package/cli/dist/commands/project.js +447 -0
  41. package/cli/dist/commands/projects.js +103 -0
  42. package/cli/dist/commands/registry.js +53 -0
  43. package/cli/dist/commands/resource.js +992 -0
  44. package/cli/dist/commands/resources.js +127 -0
  45. package/cli/dist/commands/restart.js +89 -0
  46. package/cli/dist/commands/runtime.js +75 -0
  47. package/cli/dist/commands/stack.js +171 -0
  48. package/cli/dist/commands/stacks.js +71 -0
  49. package/cli/dist/commands/status.js +211 -0
  50. package/cli/dist/commands/ui.js +725 -0
  51. package/cli/dist/commands/up.js +609 -0
  52. package/cli/dist/commands/upgrade.js +840 -0
  53. package/cli/dist/commands/version.js +10 -0
  54. package/cli/dist/components/Accessible.js +11 -0
  55. package/cli/dist/components/BaseTooltip.js +30 -0
  56. package/cli/dist/components/DetailPanel.js +33 -0
  57. package/cli/dist/components/FileTree.js +51 -0
  58. package/cli/dist/components/ResourceSelectInput.js +42 -0
  59. package/cli/dist/components/ResourceTable.js +35 -0
  60. package/cli/dist/components/ServiceIssues.js +13 -0
  61. package/cli/dist/components/TUIHeader.js +27 -0
  62. package/cli/dist/components/TabBar.js +27 -0
  63. package/cli/dist/components/Tooltip.js +13 -0
  64. package/cli/dist/components/index.js +11 -0
  65. package/cli/dist/components/ui-theme.js +120 -0
  66. package/cli/dist/config/platform-standards.js +182 -0
  67. package/cli/dist/frontend-frameworks/lit.js +64 -0
  68. package/cli/dist/frontend-frameworks/preact.js +62 -0
  69. package/cli/dist/frontend-frameworks/qwik.js +61 -0
  70. package/cli/dist/frontend-frameworks/react.js +69 -0
  71. package/cli/dist/frontend-frameworks/registry.js +83 -0
  72. package/cli/dist/frontend-frameworks/solid.js +62 -0
  73. package/cli/dist/frontend-frameworks/svelte.js +67 -0
  74. package/cli/dist/frontend-frameworks/tanstack-router.js +101 -0
  75. package/cli/dist/frontend-frameworks/types.js +1 -0
  76. package/cli/dist/frontend-frameworks/vanilla.js +59 -0
  77. package/cli/dist/frontend-frameworks/vue.js +72 -0
  78. package/cli/dist/generator/__tests__/golden-helpers.js +43 -0
  79. package/cli/dist/generator/extension-fetch.js +291 -0
  80. package/cli/dist/generator/resource-templates.js +133 -0
  81. package/cli/dist/generator/template-engine.js +801 -0
  82. package/cli/dist/index.js +10 -0
  83. package/cli/dist/mcp/server.js +101 -0
  84. package/cli/dist/mcp/tools.js +351 -0
  85. package/cli/dist/program.js +37 -0
  86. package/cli/dist/types/index.js +38 -0
  87. package/cli/dist/utils/agent-host.js +36 -0
  88. package/cli/dist/utils/atomic-write.js +36 -0
  89. package/cli/dist/utils/bun-floor.js +9 -0
  90. package/cli/dist/utils/bun-requirement.js +10 -0
  91. package/cli/dist/utils/cache.js +63 -0
  92. package/cli/dist/utils/cold-preflight.js +257 -0
  93. package/cli/dist/utils/command-helpers.js +57 -0
  94. package/cli/dist/utils/constants.js +160 -0
  95. package/cli/dist/utils/discovery-context.js +71 -0
  96. package/cli/dist/utils/discovery-paths.js +93 -0
  97. package/cli/dist/utils/docker.js +34 -0
  98. package/cli/dist/utils/doctor-crashloop.js +161 -0
  99. package/cli/dist/utils/doctor-fix.js +391 -0
  100. package/cli/dist/utils/doctor-host.js +66 -0
  101. package/cli/dist/utils/doctor-report.js +78 -0
  102. package/cli/dist/utils/doctor-runtime.js +880 -0
  103. package/cli/dist/utils/doctor-starlark.js +132 -0
  104. package/cli/dist/utils/doctor-wiring.js +698 -0
  105. package/cli/dist/utils/down-cleanup.js +125 -0
  106. package/cli/dist/utils/env-validator.js +266 -0
  107. package/cli/dist/utils/errors.js +175 -0
  108. package/cli/dist/utils/exec-async.js +31 -0
  109. package/cli/dist/utils/file-helpers.js +104 -0
  110. package/cli/dist/utils/formatting.js +165 -0
  111. package/cli/dist/utils/generated-paths.js +51 -0
  112. package/cli/dist/utils/help-command.js +11 -0
  113. package/cli/dist/utils/host-port-config.js +140 -0
  114. package/cli/dist/utils/host-port-plan.js +100 -0
  115. package/cli/dist/utils/json-output.js +29 -0
  116. package/cli/dist/utils/machine-output.js +33 -0
  117. package/cli/dist/utils/paths.js +43 -0
  118. package/cli/dist/utils/platform.js +58 -0
  119. package/cli/dist/utils/port-assignment.js +75 -0
  120. package/cli/dist/utils/port-conflict-fix.js +25 -0
  121. package/cli/dist/utils/port-fallback-notice.js +17 -0
  122. package/cli/dist/utils/port-listener-probe.js +20 -0
  123. package/cli/dist/utils/project-config-defaults.js +17 -0
  124. package/cli/dist/utils/project-features.js +91 -0
  125. package/cli/dist/utils/project-templates.js +32 -0
  126. package/cli/dist/utils/prompt.js +97 -0
  127. package/cli/dist/utils/resource-features.js +184 -0
  128. package/cli/dist/utils/resource-kind.js +9 -0
  129. package/cli/dist/utils/schema-version-gate.js +45 -0
  130. package/cli/dist/utils/search-status.js +12 -0
  131. package/cli/dist/utils/secret-redaction.js +73 -0
  132. package/cli/dist/utils/service-config-checks.js +189 -0
  133. package/cli/dist/utils/service-manifest.js +254 -0
  134. package/cli/dist/utils/service-runtime-state.js +66 -0
  135. package/cli/dist/utils/service-urls.js +112 -0
  136. package/cli/dist/utils/services.js +360 -0
  137. package/cli/dist/utils/shared-infra.js +45 -0
  138. package/cli/dist/utils/shared-platform-postgres.js +232 -0
  139. package/cli/dist/utils/single-flight.js +21 -0
  140. package/cli/dist/utils/smoke.js +401 -0
  141. package/cli/dist/utils/spinner.js +40 -0
  142. package/cli/dist/utils/stack-features.js +15 -0
  143. package/cli/dist/utils/stack-status.js +14 -0
  144. package/cli/dist/utils/startup-report.js +78 -0
  145. package/cli/dist/utils/status-message.js +21 -0
  146. package/cli/dist/utils/status-ports.js +33 -0
  147. package/cli/dist/utils/suggestions.js +63 -0
  148. package/cli/dist/utils/tar.js +46 -0
  149. package/cli/dist/utils/tdk-version.js +51 -0
  150. package/cli/dist/utils/terminal-layout.js +19 -0
  151. package/cli/dist/utils/tilt-events.js +194 -0
  152. package/cli/dist/utils/tilt-logs.js +61 -0
  153. package/cli/dist/utils/tilt-port-owner.js +63 -0
  154. package/cli/dist/utils/tilt-process.js +54 -0
  155. package/cli/dist/utils/tilt-resource-state.js +32 -0
  156. package/cli/dist/utils/tilt-startup.js +49 -0
  157. package/cli/dist/utils/tilt-unreachable-message.js +9 -0
  158. package/cli/dist/utils/tilt.js +104 -0
  159. package/cli/dist/utils/ui-keymap.js +129 -0
  160. package/cli/dist/utils/ui-service-state.js +34 -0
  161. package/cli/dist/utils/up-only.js +28 -0
  162. package/cli/dist/utils/up-readiness.js +118 -0
  163. package/cli/dist/utils/url-actions.js +103 -0
  164. package/cli/dist/utils/validation.js +62 -0
  165. package/cli/dist/utils/which.js +56 -0
  166. package/cli/dist/utils/windows-doctor.js +176 -0
  167. package/cli/dist-bundle/chunk-6EA4DGCY.js +2 -0
  168. package/cli/dist-bundle/chunk-BZ4H7MM4.js +3 -0
  169. package/cli/dist-bundle/chunk-QWYXYAX6.js +510 -0
  170. package/cli/dist-bundle/cli.js +2017 -0
  171. package/cli/dist-bundle/cold-preflight-MM46GFQA.js +2 -0
  172. package/cli/dist-bundle/devtools-ZUHXW33W.js +5 -0
  173. package/cli/dist-bundle/extension-fetch-J4FFH7TJ.js +2 -0
  174. package/cli/package.json +83 -0
  175. package/cli/shared-platform-engineering/docker-templates/bun-hoisted-symlink-fix.sh +25 -0
  176. package/cli/shared-platform-engineering/docker-templates/infisical-entrypoint.sh +466 -0
  177. package/cli/shared-platform-engineering/docker-templates/install-deps.sh +154 -0
  178. package/cli/shared-platform-engineering/docker-templates/prisma-bun-client-link-fix.sh +14 -0
  179. package/cli/shared-platform-engineering/docker-templates/prisma-normalize-client.sh +58 -0
  180. package/cli/templates/.tiltignore.hbs +72 -0
  181. package/cli/templates/TILT_RESOURCE_DEFAULTS.star.hbs +220 -0
  182. package/cli/templates/TILT_TECH_STACK.star.hbs +149 -0
  183. package/cli/templates/Tiltfile.hbs +381 -0
  184. package/cli/templates/spec.master.hbs +192 -0
  185. package/discovery/AGENTS.md +362 -0
  186. package/discovery/TILT_DISCOVERY.star +429 -0
  187. package/discovery/Tiltfile +58 -0
  188. package/discovery/config.star +265 -0
  189. package/discovery/constants.star +167 -0
  190. package/discovery/deterministic.star +213 -0
  191. package/discovery/discovery_daemon.star +193 -0
  192. package/discovery/discovery_orchestrator.star +492 -0
  193. package/discovery/filtering.star +7 -0
  194. package/discovery/identity-management-backend/service.yaml +26 -0
  195. package/discovery/identity-management-frontend/service.yaml +29 -0
  196. package/discovery/identity-sdk/service.yaml +9 -0
  197. package/discovery/incremental_discovery.star +215 -0
  198. package/discovery/indexing.star +9 -0
  199. package/discovery/json_manifest_scanner.star +57 -0
  200. package/discovery/libraries.star +48 -0
  201. package/discovery/loading.star +25 -0
  202. package/discovery/manifest/constants.star +106 -0
  203. package/discovery/manifest/loading.star +418 -0
  204. package/discovery/manifest/normalize.star +289 -0
  205. package/discovery/manifest/validation.star +110 -0
  206. package/discovery/normalization.star +13 -0
  207. package/discovery/registry.star +562 -0
  208. package/discovery/resource_snapshot.py +384 -0
  209. package/discovery/resource_snapshot.star +145 -0
  210. package/discovery/schemas.star +3 -0
  211. package/discovery/services/platform/cdc/debezium/nats-connector/service.yaml +9 -0
  212. package/discovery/services/platform/cdc/nats-http-bridge/service.yaml +9 -0
  213. package/discovery/services/platform/orchestrator/orchestrator-glue-backend/service.yaml +26 -0
  214. package/discovery/services/platform/synthetic-monitor/service.yaml +9 -0
  215. package/discovery/test_resource_snapshot.py +253 -0
  216. package/discovery/validation.star +80 -0
  217. package/discovery/versioning.star +3 -0
  218. package/engine/AGENTS.md +706 -0
  219. package/engine/README.md +31 -0
  220. package/engine/REFACTORING_MANIFEST_SYSTEM.md +974 -0
  221. package/engine/Tiltfile +86 -0
  222. package/engine/assets/docker/golden-layers.Dockerfile +204 -0
  223. package/engine/assets/docker/wake-gateway/Dockerfile +28 -0
  224. package/engine/assets/docker/wake-gateway/decide.test.ts +177 -0
  225. package/engine/assets/docker/wake-gateway/decide.ts +135 -0
  226. package/engine/assets/docker/wake-gateway/server.ts +363 -0
  227. package/engine/assets/scripts/cleanup-completed-migrator-images.sh +39 -0
  228. package/engine/assets/scripts/cleanup-tilt-images.sh +122 -0
  229. package/engine/assets/scripts/mac-m1-resource-monitor.sh +123 -0
  230. package/engine/config.star +5 -0
  231. package/engine/entrypoint.star +101 -0
  232. package/engine/lifecycle/orchestrator.star +263 -0
  233. package/engine/paths.star +719 -0
  234. package/engine/schemas/project-schema.json +147 -0
  235. package/engine/schemas/service-schema.json +537 -0
  236. package/engine/scripts/README.md +89 -0
  237. package/engine/scripts/build-and-publish-lib.sh +207 -0
  238. package/engine/scripts/check-lib-publish.sh +87 -0
  239. package/engine/scripts/debug-container.sh +265 -0
  240. package/engine/scripts/generate-manifest.sh +200 -0
  241. package/engine/spec.master +702 -0
  242. package/engine/spec.master.example +341 -0
  243. package/engine/topologies/README.md +33 -0
  244. package/engine/topologies/platform/docker/AGENTS.md +59 -0
  245. package/engine/topologies/platform/docker/auth/auth.star +207 -0
  246. package/engine/topologies/platform/docker/build/frontend_build_plan.star +65 -0
  247. package/engine/topologies/platform/docker/build/golden_image.star +37 -0
  248. package/engine/topologies/platform/docker/build/golden_image_build.star +144 -0
  249. package/engine/topologies/platform/docker/build/golden_image_constants.star +100 -0
  250. package/engine/topologies/platform/docker/build/golden_image_dockerfile.star +263 -0
  251. package/engine/topologies/platform/docker/compose/compose.star +637 -0
  252. package/engine/topologies/platform/docker/compose/compose_helpers.star +54 -0
  253. package/engine/topologies/platform/docker/compose/traefik_standalone.star +171 -0
  254. package/engine/topologies/platform/docker/config/bunignore.star +144 -0
  255. package/engine/topologies/platform/docker/config/dockerignore.star +152 -0
  256. package/engine/topologies/platform/docker/config/healthcheck.star +58 -0
  257. package/engine/topologies/platform/docker/constants.star +211 -0
  258. package/engine/topologies/platform/docker/dockerfile/dockerfile.star +56 -0
  259. package/engine/topologies/platform/docker/dockerfile/language_dockerfile.star +264 -0
  260. package/engine/topologies/platform/docker/generators/golden_docker_generator_v2.star +76 -0
  261. package/engine/topologies/platform/docker/index.star +40 -0
  262. package/engine/topologies/platform/docker/layers/bun_helpers.star +25 -0
  263. package/engine/topologies/platform/docker/layers/infisical/index.star +42 -0
  264. package/engine/topologies/platform/docker/layers/infisical/infisical_docker.star +264 -0
  265. package/engine/topologies/platform/docker/layers/l1_base_layers.star +89 -0
  266. package/engine/topologies/platform/docker/layers/l2_dependency_layers.star +147 -0
  267. package/engine/topologies/platform/docker/layers/l3_builder_layers.star +229 -0
  268. package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +282 -0
  269. package/engine/topologies/platform/docker/layers/prisma/constants.star +138 -0
  270. package/engine/topologies/platform/docker/layers/prisma/db_readiness.star +98 -0
  271. package/engine/topologies/platform/docker/layers/prisma/filesystem_setup.star +131 -0
  272. package/engine/topologies/platform/docker/layers/prisma/migrate_script.star +100 -0
  273. package/engine/topologies/platform/docker/layers/prisma/prisma_build.star +128 -0
  274. package/engine/topologies/platform/docker/layers/prisma/prisma_runtime.star +205 -0
  275. package/engine/topologies/platform/docker/layers/prisma/secret_resolution.star +121 -0
  276. package/engine/topologies/platform/docker/networking/api_path_constants.star +206 -0
  277. package/engine/topologies/platform/docker/networking/sablier_container_cycle.star +31 -0
  278. package/engine/topologies/platform/docker/networking/traefik.star +266 -0
  279. package/engine/topologies/platform/docker/networking/traefik_constants.star +148 -0
  280. package/engine/topologies/platform/docker/networking/traefik_helpers.star +162 -0
  281. package/engine/topologies/platform/docker/networking/traefik_static_routes.star +165 -0
  282. package/engine/topologies/platform/docker/secrets/env_secrets.star +74 -0
  283. package/engine/topologies/platform/docker/secrets/infisical.star +109 -0
  284. package/engine/topologies/platform/net/AGENTS.md +64 -0
  285. package/engine/topologies/platform/net/proxy.star +6 -0
  286. package/engine/topologies/platform/registries/local.star +6 -0
  287. package/engine/topologies/platform/registries/verdaccio_loader.star +20 -0
  288. package/engine/topologies/platform/security/AGENTS.md +49 -0
  289. package/engine/topologies/platform/security/secrets.star +241 -0
  290. package/engine/topologies/platform/state/AGENTS.md +64 -0
  291. package/engine/topologies/platform/state/relational.star +6 -0
  292. package/engine/topologies/tilt/common/AGENTS.md +59 -0
  293. package/engine/topologies/tilt/common/utils.star +409 -0
  294. package/engine/topologies/tilt/common/utils_debug.star +71 -0
  295. package/engine/topologies/tilt/common/utils_deterministic.star +170 -0
  296. package/engine/topologies/tilt/common/utils_docker_networks.star +54 -0
  297. package/engine/topologies/tilt/common/utils_env.star +92 -0
  298. package/engine/topologies/tilt/common/utils_output.star +99 -0
  299. package/engine/topologies/tilt/config/AGENTS.md +68 -0
  300. package/engine/topologies/tilt/config/defaults.star +5 -0
  301. package/engine/topologies/tilt/config/feature_flags.star +12 -0
  302. package/engine/topologies/tilt/config/global.star +57 -0
  303. package/engine/topologies/tilt/config/profiles.star +398 -0
  304. package/engine/topologies/tilt/generators/agents_md.star +64 -0
  305. package/engine/topologies/tilt/generators/api_gateway.star +147 -0
  306. package/engine/topologies/tilt/generators/index.star +126 -0
  307. package/engine/topologies/tilt/generators/infisical/README.md +424 -0
  308. package/engine/topologies/tilt/generators/infisical/examples.star +314 -0
  309. package/engine/topologies/tilt/generators/infisical/index.star +59 -0
  310. package/engine/topologies/tilt/generators/infisical/machine_identity.star +422 -0
  311. package/engine/topologies/tilt/generators/infisical/organization.star +536 -0
  312. package/engine/topologies/tilt/generators/infisical/path_manager.star +478 -0
  313. package/engine/topologies/tilt/generators/infisical/secrets_generator.star +422 -0
  314. package/engine/topologies/tilt/generators/nginx_conf.star +145 -0
  315. package/engine/topologies/tilt/generators/npmrc.star +132 -0
  316. package/engine/topologies/tilt/generators/tsconfig.star +25 -0
  317. package/engine/topologies/tilt/generators/typescript/backend_library_tsconfig.star +73 -0
  318. package/engine/topologies/tilt/generators/typescript/backend_tsconfig.star +137 -0
  319. package/engine/topologies/tilt/generators/typescript/common.star +9 -0
  320. package/engine/topologies/tilt/generators/typescript/frontend_library_tsconfig.star +78 -0
  321. package/engine/topologies/tilt/generators/typescript/frontend_tsconfig.star +140 -0
  322. package/engine/topologies/tilt/generators/typescript/include.star +25 -0
  323. package/engine/topologies/tilt/generators/typescript/playwright_config.star +42 -0
  324. package/engine/topologies/tilt/generators/typescript/prisma_config.star +51 -0
  325. package/engine/topologies/tilt/generators/validators.star +868 -0
  326. package/engine/topologies/tilt/generators/vite/backend.star +80 -0
  327. package/engine/topologies/tilt/generators/vite/frameworks/lit.star +92 -0
  328. package/engine/topologies/tilt/generators/vite/frameworks/preact.star +94 -0
  329. package/engine/topologies/tilt/generators/vite/frameworks/qwik.star +94 -0
  330. package/engine/topologies/tilt/generators/vite/frameworks/react.star +128 -0
  331. package/engine/topologies/tilt/generators/vite/frameworks/solid.star +94 -0
  332. package/engine/topologies/tilt/generators/vite/frameworks/svelte.star +94 -0
  333. package/engine/topologies/tilt/generators/vite/frameworks/vanilla.star +92 -0
  334. package/engine/topologies/tilt/generators/vite/frameworks/vue.star +94 -0
  335. package/engine/topologies/tilt/generators/vite/frontend.star +153 -0
  336. package/engine/topologies/tilt/generators/vite/generators.star +45 -0
  337. package/engine/topologies/tilt/generators/vite/helpers.star +256 -0
  338. package/engine/topologies/tilt/generators/vite/library.star +67 -0
  339. package/engine/topologies/tilt/generators/vite/sdk.star +75 -0
  340. package/engine/topologies/tilt/generators/vite/templates.star +460 -0
  341. package/engine/topologies/tilt/generators/vite_config.star +24 -0
  342. package/engine/topologies/tilt/manifest/AGENTS.md +61 -0
  343. package/engine/topologies/tilt/manifest/README.md +679 -0
  344. package/engine/topologies/tilt/manifest/__init__.star +220 -0
  345. package/engine/topologies/tilt/manifest/constants.star +262 -0
  346. package/engine/topologies/tilt/manifest/errors.star +268 -0
  347. package/engine/topologies/tilt/manifest/integration.star +348 -0
  348. package/engine/topologies/tilt/manifest/json_to_yaml.py +61 -0
  349. package/engine/topologies/tilt/manifest/loader.star +239 -0
  350. package/engine/topologies/tilt/manifest/mapper.star +229 -0
  351. package/engine/topologies/tilt/manifest/parser.star +490 -0
  352. package/engine/topologies/tilt/manifest/schema.star +502 -0
  353. package/engine/topologies/tilt/manifest/tests/test_integration.star +278 -0
  354. package/engine/topologies/tilt/manifest/tests/test_loader_parser.star +475 -0
  355. package/engine/topologies/tilt/manifest/tests/test_manifest.star +319 -0
  356. package/engine/topologies/tilt/manifest/tests/test_validator.star +472 -0
  357. package/engine/topologies/tilt/manifest/validator.star +744 -0
  358. package/engine/topologies/tilt/manifest/yaml_to_json.py +20 -0
  359. package/engine/topologies/tilt/resources/AGENTS.md +71 -0
  360. package/engine/topologies/tilt/resources/build_concurrency.star +56 -0
  361. package/engine/topologies/tilt/resources/conditions.star +5 -0
  362. package/engine/topologies/tilt/resources/databases.star +246 -0
  363. package/engine/topologies/tilt/resources/declaration.star +5 -0
  364. package/engine/topologies/tilt/resources/deps.star +5 -0
  365. package/engine/topologies/tilt/resources/infra-loader.star +504 -0
  366. package/engine/topologies/tilt/resources/libs.star +32 -0
  367. package/engine/topologies/tilt/resources/libs_discovery.star +104 -0
  368. package/engine/topologies/tilt/resources/libs_paths.star +81 -0
  369. package/engine/topologies/tilt/resources/libs_resource_definition.star +153 -0
  370. package/engine/topologies/tilt/resources/libs_setup.star +166 -0
  371. package/engine/topologies/tilt/resources/libs_tsconfig.star +39 -0
  372. package/engine/topologies/tilt/resources/orchestrator/apply.star +79 -0
  373. package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +864 -0
  374. package/engine/topologies/tilt/resources/orchestrator/apply_manifest_orchestration.star +90 -0
  375. package/engine/topologies/tilt/resources/orchestrator/apply_migrator_orchestration.star +150 -0
  376. package/engine/topologies/tilt/resources/orchestrator/apply_resource_validation.star +38 -0
  377. package/engine/topologies/tilt/resources/orchestrator/apply_runtime_flags.star +46 -0
  378. package/engine/topologies/tilt/resources/orchestrator/builders/typescript.star +193 -0
  379. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/AGENTS.md +75 -0
  380. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/index.star +23 -0
  381. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/resolver.star +136 -0
  382. package/engine/topologies/tilt/resources/orchestrator/generators/env.star +219 -0
  383. package/engine/topologies/tilt/resources/orchestrator/generators/frontend.star +172 -0
  384. package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +577 -0
  385. package/engine/topologies/tilt/resources/orchestrator/helpers.star +35 -0
  386. package/engine/topologies/tilt/resources/orchestrator.star +56 -0
  387. package/engine/topologies/tilt/resources/ordering.star +5 -0
  388. package/engine/topologies/tilt/resources/shared-platform-postgres.star +30 -0
  389. package/engine/topologies/tilt/resources/triggers.star +5 -0
  390. package/engine/topologies/tilt/resources/watchers.star +304 -0
  391. package/engine/where-things-live.star +719 -0
  392. package/examples/tdk-example/LICENSE +21 -0
  393. package/examples/tdk-example/README.md +23 -0
  394. package/examples/tdk-example/TILT_SERVICE_DEFAULTS.star +42 -0
  395. package/examples/tdk-example/TILT_TECH_STACK.star +67 -0
  396. package/examples/tdk-example/Tiltfile +25 -0
  397. package/examples/tdk-example/services/platform/messaging/docker-compose.yml +26 -0
  398. package/examples/tdk-example/services/shop/orders-api/package.json +20 -0
  399. package/examples/tdk-example/services/shop/orders-api/service.json +14 -0
  400. package/examples/tdk-example/services/shop/orders-api/src/index.ts +81 -0
  401. package/examples/tdk-example/services/shop/orders-app/index.html +12 -0
  402. package/examples/tdk-example/services/shop/orders-app/package.json +23 -0
  403. package/examples/tdk-example/services/shop/orders-app/public/.gitkeep +0 -0
  404. package/examples/tdk-example/services/shop/orders-app/service.json +9 -0
  405. package/examples/tdk-example/services/shop/orders-app/src/main.tsx +9 -0
  406. package/examples/tdk-example/services/shop/orders-app/src/orders.tsx +67 -0
  407. package/examples/tdk-example/services/shop/orders-app/src/style.css +15 -0
  408. package/examples/tdk-example/services/shop/orders-worker/package.json +18 -0
  409. package/examples/tdk-example/services/shop/orders-worker/service.json +13 -0
  410. package/examples/tdk-example/services/shop/orders-worker/src/index.ts +33 -0
  411. package/ext/Tiltfile +66 -0
  412. package/ext/ide-components/README.md +221 -0
  413. package/ext/ide-components/code_viewer/server.py +208 -0
  414. package/ext/ide-components/config_inspector/server.py +1052 -0
  415. package/ext/ide-components/file_browser/server.py +287 -0
  416. package/ext/ide-components/shared/config_service.py +471 -0
  417. package/ext/ide-components/shared/file_utils.py +300 -0
  418. package/ext/ide-components/shared/http_utils.py +234 -0
  419. package/ext/ide-components/shared/static/styles.css +1334 -0
  420. package/ext/ide-components/shared/syntax_highlighter.py +142 -0
  421. package/ext/ide-components/shared/template_engine.py +125 -0
  422. package/ext/ide-components/shared/templates/base.html +121 -0
  423. package/ext/ide-components/shared/test_config_service.py +328 -0
  424. package/ext/ide-components/shared/tilt_integration.py +160 -0
  425. package/ext/ui-enhancements/cron-status-server.sh +51 -0
  426. package/ext/ui-enhancements/cron-status-tracker.sh +148 -0
  427. package/ext/ui-enhancements/extension.yaml +36 -0
  428. package/ext/ui-enhancements/tiltfile.py +101 -0
  429. package/ext/ui-enhancements/ui/cron-jobs-tab.css +396 -0
  430. package/ext/ui-enhancements/ui/help-panel.css +279 -0
  431. package/ext/ui-enhancements/ui/icons.css +125 -0
  432. package/ext/ui-enhancements/ui/tooltips.css +114 -0
  433. package/package.json +94 -4
  434. package/shared-platform-engineering/docker-templates/bun-hoisted-symlink-fix.sh +25 -0
  435. package/shared-platform-engineering/docker-templates/infisical-entrypoint.sh +466 -0
  436. package/shared-platform-engineering/docker-templates/install-deps.sh +154 -0
  437. package/shared-platform-engineering/docker-templates/prisma-bun-client-link-fix.sh +14 -0
  438. package/shared-platform-engineering/docker-templates/prisma-normalize-client.sh +58 -0
  439. package/specs/specs/TILT_SERVICE_DEFAULTS.star +207 -0
  440. package/specs/specs/TILT_TECH_STACK.star +161 -0
@@ -0,0 +1,609 @@
1
+ // Copyright (c) 2026 Flisk Landscape contributors
2
+ // SPDX-License-Identifier: MIT
3
+ import { existsSync } from "node:fs";
4
+ import { connect } from "node:net";
5
+ import { join } from "node:path";
6
+ import chalk from "chalk";
7
+ import { Command } from "commander";
8
+ import { ensureProjectRuntimeAssets, generateMasterConfigs, ProjectConfigNotFoundError, verifyMasterConfigs, } from "../generator/template-engine.js";
9
+ import { DEVCONTAINER_DOCKER_FIX, detectHost, isContainerHost, WEBCONTAINER_UP_MESSAGE, } from "../utils/agent-host.js";
10
+ import { handleDryRun } from "../utils/command-helpers.js";
11
+ import { STANDARD_PORTS } from "../utils/constants.js";
12
+ import { getDeferredResourceNames, summarizeTiltBuildError } from "../utils/doctor-runtime.js";
13
+ import { completeEnvFile } from "../utils/env-validator.js";
14
+ import { errorFactories, handleTiltFailure, requireProjectRoot, runCommand, showError, showErrorAndExit, withTiltCheck, } from "../utils/errors.js";
15
+ import { ensureSmokeRecordsIgnored } from "../utils/file-helpers.js";
16
+ import { formatCount } from "../utils/formatting.js";
17
+ import { exportHostPortPlan, getHostPortPlan, writeSavedHostPortPlan, } from "../utils/host-port-config.js";
18
+ import { formatHostPortPlan } from "../utils/host-port-plan.js";
19
+ import { createJsonEmitter } from "../utils/json-output.js";
20
+ import { toMachineError } from "../utils/machine-output.js";
21
+ import { findProjectRoot, getPackageVersion } from "../utils/paths.js";
22
+ import { findAvailablePort } from "../utils/port-assignment.js";
23
+ import { formatPortFallbackNotice } from "../utils/port-fallback-notice.js";
24
+ import { isApiServiceType } from "../utils/resource-kind.js";
25
+ import { enforceSchemaVersionGate } from "../utils/schema-version-gate.js";
26
+ import { enforceServiceConfigGate, warnSchemaVersions } from "../utils/service-config-checks.js";
27
+ import { appendHealthPath, resolveSubdomainBases } from "../utils/service-urls.js";
28
+ import { discoverResourcesStrict, discoverResourcesWithProblems, discoverStacks, getResourcesForStack, stackExists, warnAboutSkippedFiles, } from "../utils/services.js";
29
+ import { buildSmokePlans, formatSmokeFailure, runSmokePlans, safeSmokeDeps, } from "../utils/smoke.js";
30
+ import { buildStartupReport, formatStartupReport, isStartupStalled, } from "../utils/startup-report.js";
31
+ import { evaluateTdkVersionFloor } from "../utils/tdk-version.js";
32
+ import { buildTiltUpArgs, runTilt } from "../utils/tilt.js";
33
+ import { classifyTiltPorts } from "../utils/tilt-port-owner.js";
34
+ import { stopTiltOnPort } from "../utils/tilt-process.js";
35
+ import { parseTiltPort, resolveTiltPort, secondUpAction, stopTiltForUp, } from "../utils/tilt-startup.js";
36
+ import { findUnknownServices, resolveOnlySelection } from "../utils/up-only.js";
37
+ import { tiltGetUiResources, waitForTiltResourcesReady } from "../utils/up-readiness.js";
38
+ import { enableDiscoveredStacks } from "./project.js";
39
+ export function formatUpSuccess(port, appUrls = []) {
40
+ return [
41
+ "Flisk is up.",
42
+ `Tilt UI: http://localhost:${port}`,
43
+ "App URLs:",
44
+ ...(appUrls.length > 0
45
+ ? appUrls.slice(0, 5).map((url) => ` ${url}`)
46
+ : [" run: flisk networks"]),
47
+ "Stop: flisk down",
48
+ ];
49
+ }
50
+ export function nativeWindowsUpRefusal(platform, allowNativeWindows) {
51
+ if (platform !== "win32" || allowNativeWindows === "1")
52
+ return null;
53
+ return "Landscape startup needs Ubuntu on WSL2. Native Windows is inspect-only.";
54
+ }
55
+ /** Why `flisk up` cannot work on this host, or null when it may proceed. Docker reachability is only probed in container hosts. */
56
+ export async function hostUpRefusal(host = detectHost(), dockerReachable = defaultDockerReachable) {
57
+ if (host.kind === "webcontainer")
58
+ return WEBCONTAINER_UP_MESSAGE;
59
+ if (isContainerHost(host.kind) && !(await dockerReachable()))
60
+ return DEVCONTAINER_DOCKER_FIX;
61
+ return null;
62
+ }
63
+ async function defaultDockerReachable() {
64
+ const { execFile } = await import("node:child_process");
65
+ return new Promise((resolve) => {
66
+ execFile("docker", ["ps"], { timeout: 10_000 }, (error) => resolve(!error));
67
+ });
68
+ }
69
+ /** Exit status for `flisk up` when generated files no longer match service.json / project.json. */
70
+ export const DRIFT_EXIT_CODE = 2;
71
+ /**
72
+ * Generated service files edited by hand. Only these block `flisk up`: when service.json itself changed, `flisk up` regenerates
73
+ * the outputs, so stale outputs are the normal edit-then-up loop and not drift.
74
+ */
75
+ export function driftReport(projectRoot, resources) {
76
+ let handEdited;
77
+ try {
78
+ ({ handEdited } = verifyMasterConfigs(projectRoot, resources
79
+ ? {
80
+ manifestPaths: resources.map((r) => r.configPath),
81
+ skipManifestValidation: true,
82
+ }
83
+ : undefined));
84
+ }
85
+ catch (error) {
86
+ // A project with no .tdk/project.json has no snapshots to compare. Anything else (a corrupt config) must not skip the gate.
87
+ if (error instanceof ProjectConfigNotFoundError)
88
+ return null;
89
+ throw error;
90
+ }
91
+ if (handEdited.length === 0)
92
+ return null;
93
+ return [
94
+ "Generated files were edited by hand and no longer match service.json:",
95
+ ...handEdited.map((file) => ` ${file}`),
96
+ "Run `flisk config regenerate` to discard the edits, or bypass with `flisk up --ignore-drift`.",
97
+ ];
98
+ }
99
+ /**
100
+ * Runs before Tilt is started: exits with DRIFT_EXIT_CODE on drift unless `ignoreDrift` is set. With `ignoreDrift` the
101
+ * warning is printed every time, whether or not anything drifted, because the check is skipped and cannot tell.
102
+ */
103
+ export function enforceDriftGate(projectRoot, options, exit = process.exit) {
104
+ if (options.ignoreDrift) {
105
+ console.warn(chalk.yellow("Warning: --ignore-drift set; generated files were not checked."));
106
+ return;
107
+ }
108
+ const drift = driftReport(projectRoot, options.resources);
109
+ if (!drift)
110
+ return;
111
+ options.onDrift?.(drift.join("\n"));
112
+ showError(drift.join("\n"));
113
+ exit(DRIFT_EXIT_CODE);
114
+ }
115
+ /**
116
+ * Runs before anything starts (also under --dry-run, like the drift gate): a project's `minTdkVersion` in
117
+ * .tdk/project.json that this CLI does not meet, or cannot read, exits with 1 and the same text as `flisk doctor`.
118
+ * `ignoreVersion` skips the check and says so. No minTdkVersion means no check.
119
+ */
120
+ export function enforceVersionFloor(projectRoot, options, currentVersion = getPackageVersion(), exit = process.exit) {
121
+ if (options.ignoreVersion) {
122
+ console.warn(chalk.yellow("Warning: --ignore-version set; minTdkVersion was not checked."));
123
+ return;
124
+ }
125
+ const floor = evaluateTdkVersionFloor(projectRoot, currentVersion);
126
+ if (floor.status === "none" || floor.status === "ok")
127
+ return;
128
+ options.onFail?.(`${floor.message}\n${floor.fix}`);
129
+ showError(`${floor.message}\n${floor.fix}`);
130
+ exit(1);
131
+ }
132
+ const STARTUP_FAILED = Symbol("startup-failed");
133
+ /**
134
+ * Waits for Tilt to exit, unless startup has already failed. A readiness failure reports and exits 1 at once: Tilt keeps
135
+ * running (`flisk down` stops it), so waiting for its exit would hang the command.
136
+ */
137
+ export async function waitForTiltUnlessStartupFailed(tiltRun, startupFailure, exit = process.exit) {
138
+ const outcome = await Promise.race([tiltRun, startupFailure.then(() => STARTUP_FAILED)]);
139
+ if (outcome === STARTUP_FAILED)
140
+ exit(1);
141
+ return outcome;
142
+ }
143
+ function waitForTiltUi(port, timeoutMs = 30_000) {
144
+ return new Promise((resolve) => {
145
+ const deadline = Date.now() + timeoutMs;
146
+ const attempt = () => {
147
+ const socket = connect({ host: "127.0.0.1", port });
148
+ let settled = false;
149
+ const finish = (ready) => {
150
+ if (settled)
151
+ return;
152
+ settled = true;
153
+ socket.destroy();
154
+ if (ready || Date.now() >= deadline)
155
+ resolve(ready);
156
+ else
157
+ setTimeout(attempt, 250);
158
+ };
159
+ socket.once("connect", () => finish(true));
160
+ socket.once("error", () => finish(false));
161
+ };
162
+ attempt();
163
+ });
164
+ }
165
+ export const upCommand = new Command("up")
166
+ .description("Start all services (optionally filtered by stack)")
167
+ .alias("deploy")
168
+ .argument("[stack-name]", "Name of the stack to start (optional - runs all if omitted)")
169
+ .option("-v, --verbose", "Enable verbose output", false)
170
+ .option("-q, --quiet", "Suppress non-essential output", false)
171
+ .option("--dry-run", "Show what would be started without starting", false)
172
+ .option("-f, --force", "Kill existing Tilt process before starting", false)
173
+ .option("--ignore-drift", "Start even if generated files differ from service.json", false)
174
+ .option("--ignore-version", "Start even if this flisk is older than minTdkVersion in .tdk/project.json", false)
175
+ .option("--only <services...>", "Start only these services plus what the Tiltfile enables for them (their dependsOn services and shared infrastructure). With a stack, names must belong to that stack; dependencies may cross stacks")
176
+ .option("--json", "Print one JSON object on stdout when the stack is ready or the command fails; implies --quiet", false)
177
+ .action(async (stackName, options) => {
178
+ const emit = options.json ? createJsonEmitter("UP_FAILED", "flisk up") : undefined;
179
+ if (options.json)
180
+ options.quiet = true;
181
+ const portSetting = parseTiltPort(process.env.TILT_PORT);
182
+ if (!portSetting.ok) {
183
+ emit?.({ ok: false }, [{ code: "INVALID_TILT_PORT", message: portSetting.message }]);
184
+ showErrorAndExit(portSetting.message);
185
+ }
186
+ const configuredTiltPort = portSetting.port;
187
+ // First, before the host/Docker checks below: an old CLI must stop with one clear line, not a half-working stack.
188
+ const versionRoot = findProjectRoot();
189
+ if (versionRoot) {
190
+ enforceVersionFloor(versionRoot, {
191
+ ignoreVersion: options.ignoreVersion,
192
+ onFail: (message) => emit?.({ ok: false }, [{ code: "TDK_VERSION_TOO_OLD", message }]),
193
+ });
194
+ }
195
+ const hostRefusal = options.dryRun ? null : await hostUpRefusal();
196
+ if (hostRefusal) {
197
+ emit?.({ ok: false }, [{ code: "HOST_UNSUPPORTED", message: hostRefusal }]);
198
+ showErrorAndExit(hostRefusal);
199
+ }
200
+ const platformRefusal = nativeWindowsUpRefusal(process.platform, process.env.TDK_ALLOW_NATIVE_WINDOWS);
201
+ if (platformRefusal)
202
+ showErrorAndExit(platformRefusal);
203
+ // An unknown schemaVersion is refused before the machine check, so --json can name the file even when Bun is missing.
204
+ const schemaRoot = findProjectRoot();
205
+ let initialDiscovery;
206
+ if (schemaRoot) {
207
+ try {
208
+ initialDiscovery = discoverResourcesWithProblems(schemaRoot);
209
+ warnAboutSkippedFiles(initialDiscovery.problems);
210
+ }
211
+ catch {
212
+ // A root that cannot be read is reported by the checks that run next.
213
+ }
214
+ if (initialDiscovery) {
215
+ enforceSchemaVersionGate(schemaRoot, {
216
+ resources: initialDiscovery.resources,
217
+ onInvalid: (message) => emit?.({ ok: false }, [{ code: "INVALID_SCHEMA_VERSION", message }]),
218
+ });
219
+ }
220
+ }
221
+ if (!options.dryRun) {
222
+ const { assertMachineReadyOrExit } = await import("../utils/cold-preflight.js");
223
+ await assertMachineReadyOrExit();
224
+ }
225
+ const action = async () => {
226
+ const foundRoot = options.dryRun ? requireProjectRoot() : findProjectRoot();
227
+ const projectRoot = foundRoot ?? process.cwd();
228
+ const discoveredResources = discoverResourcesStrict(foundRoot && foundRoot === schemaRoot ? initialDiscovery : undefined);
229
+ let discoveredStacks;
230
+ let discoveredStackNames = [];
231
+ if (!options.only || stackName) {
232
+ discoveredStacks = discoverStacks(discoveredResources);
233
+ discoveredStackNames = discoveredStacks.map((stack) => stack.name);
234
+ }
235
+ // Reject a bad request before anything below can write to the project (.env, runtime assets, .tdk/project.json).
236
+ if (options.only) {
237
+ if (stackName && !stackExists(stackName, discoveredResources)) {
238
+ const error = errorFactories.stackNotFound(stackName, discoveredStackNames);
239
+ emit?.({ ok: false }, [toMachineError(error).error]);
240
+ error.exit();
241
+ }
242
+ const candidates = stackName
243
+ ? getResourcesForStack(stackName, discoveredResources)
244
+ : discoveredResources;
245
+ const unknown = findUnknownServices(options.only, candidates);
246
+ if (unknown.length > 0) {
247
+ const validNames = candidates.map((service) => service.name);
248
+ const error = errorFactories.unknownServices(unknown, validNames);
249
+ emit?.({ ok: false }, [
250
+ {
251
+ code: "UNKNOWN_SERVICE",
252
+ message: error.message,
253
+ ...(error.suggestions.length > 0 ? { suggestions: error.suggestions } : {}),
254
+ },
255
+ ]);
256
+ error.exit();
257
+ }
258
+ }
259
+ // Also under --dry-run: the check only reads, and a dry run should show what a real run would refuse.
260
+ if (foundRoot) {
261
+ enforceDriftGate(foundRoot, {
262
+ ignoreDrift: options.ignoreDrift,
263
+ resources: discoveredResources,
264
+ onDrift: (message) => emit?.({ ok: false }, [{ code: "DRIFT_DETECTED", message }]),
265
+ });
266
+ }
267
+ // Duplicate names, circular dependsOn and invalid ports are refused before anything starts, dry run included.
268
+ if (foundRoot) {
269
+ enforceServiceConfigGate(foundRoot, {
270
+ resources: discoveredResources,
271
+ onInvalid: (message) => emit?.({ ok: false }, [{ code: "INVALID_SERVICE_CONFIG", message }]),
272
+ });
273
+ }
274
+ // A project without schemaVersion keeps working; say how to add it, but only where a person is reading.
275
+ if (foundRoot && !emit && !options.quiet) {
276
+ warnSchemaVersions(foundRoot, discoveredResources);
277
+ }
278
+ const hostPortPlan = await getHostPortPlan(projectRoot, {
279
+ inspectDocker: !options.dryRun,
280
+ });
281
+ if (!options.dryRun) {
282
+ // An older project's .env predates keys such as JWT_SECRET, which Compose now requires. Add what is missing (never
283
+ // changing an existing value) before anything starts. Only inside a real project, so a stray run never writes a .env.
284
+ if (foundRoot) {
285
+ const addedEnvKeys = completeEnvFile(projectRoot);
286
+ if (addedEnvKeys.length > 0 && !options.quiet) {
287
+ console.log(chalk.gray(`Added ${addedEnvKeys.join(", ")} to .env (generated; existing values unchanged)`));
288
+ }
289
+ }
290
+ // A project made by `flisk import` has .tdk/project.json but no generated files yet. Generate them rather than letting
291
+ // Tilt fail on a missing Tiltfile.
292
+ if (foundRoot && !existsSync(join(projectRoot, ".tdk", ".tdk-out", "Tiltfile"))) {
293
+ if (!options.quiet) {
294
+ console.log(chalk.gray("No generated Tiltfile yet; generating .tdk/.tdk-out/ ..."));
295
+ }
296
+ await generateMasterConfigs(projectRoot, { quiet: options.quiet });
297
+ }
298
+ const copiedAssets = ensureProjectRuntimeAssets(projectRoot);
299
+ if (copiedAssets.length > 0 && options.verbose && !options.quiet) {
300
+ console.log(chalk.gray(`Refreshed runtime assets: ${copiedAssets.join(", ")}`));
301
+ }
302
+ const newlyEnabledStacks = enableDiscoveredStacks(projectRoot, discoveredResources);
303
+ if (newlyEnabledStacks.length > 0 && !options.quiet) {
304
+ console.log(chalk.gray(`Added ${newlyEnabledStacks.join(", ")} to the pre_alpha phase in .tdk/project.json`));
305
+ }
306
+ }
307
+ let servicesToStart;
308
+ let stackDescription;
309
+ let focusServiceNames = [];
310
+ if (stackName) {
311
+ servicesToStart = getResourcesForStack(stackName, discoveredResources);
312
+ if (servicesToStart.length === 0) {
313
+ const error = errorFactories.stackNotFound(stackName, discoveredStackNames);
314
+ emit?.({ ok: false }, [toMachineError(error).error]);
315
+ error.exit();
316
+ }
317
+ focusServiceNames = servicesToStart.map((s) => s.name);
318
+ stackDescription = `stack "${stackName}"`;
319
+ }
320
+ else {
321
+ servicesToStart = discoveredResources;
322
+ const allStacks = discoveredStacks ?? discoverStacks(discoveredResources);
323
+ stackDescription = `all stacks (${formatCount(allStacks.length, "stack")}, ${formatCount(servicesToStart.length, "service")})`;
324
+ }
325
+ let dependencyNames = [];
326
+ if (options.only) {
327
+ // Dependencies come from the whole project, not just the named stack: dependsOn may cross stacks.
328
+ const selection = resolveOnlySelection(options.only, discoveredResources);
329
+ servicesToStart = selection.selected;
330
+ dependencyNames = selection.dependencies;
331
+ focusServiceNames = servicesToStart.map((s) => s.name);
332
+ stackDescription = `${formatCount(options.only.length, "requested service")}${dependencyNames.length > 0 ? ` plus ${dependencyNames.join(", ")}` : ""}`;
333
+ }
334
+ if (options.verbose && !options.quiet) {
335
+ console.log(chalk.gray(`Found ${formatCount(servicesToStart.length, "service")} in ${stackDescription}`));
336
+ }
337
+ const serviceNames = servicesToStart.map((s) => s.name);
338
+ if (!options.quiet) {
339
+ console.log(chalk.blue(`${options.dryRun ? "Would start" : "Starting"} ${formatCount(serviceNames.length, "service")} from ${stackDescription}...`));
340
+ for (const name of serviceNames) {
341
+ console.log(chalk.gray(` - ${name}`));
342
+ }
343
+ const { appBase, apiBase } = resolveSubdomainBases(hostPortPlan.ingressHttp);
344
+ const frontends = servicesToStart.filter((s) => s.config?.appType === "frontend");
345
+ const backends = servicesToStart.filter((s) => isApiServiceType(s.config?.appType));
346
+ if (frontends.length > 0) {
347
+ console.log(chalk.blue("\n🌍 Frontend URLs:"));
348
+ for (const svc of frontends) {
349
+ const basePath = svc.config?.basePath ?? `/${svc.name}`;
350
+ console.log(chalk.gray(` - ${svc.name}: ${appBase}${chalk.cyan(appendHealthPath(basePath))}`));
351
+ }
352
+ }
353
+ if (backends.length > 0) {
354
+ console.log(chalk.blue("\n🔧 Backend API URLs:"));
355
+ for (const svc of backends) {
356
+ const servicePathName = svc.name.replace(/-api$/, "");
357
+ const apiPath = svc.config?.apiPath ?? `/api/${servicePathName}`;
358
+ const sablier = svc.config?.sablier;
359
+ const deferredTag = sablier?.enable && sablier?.deferStart
360
+ ? chalk.dim(" (deferred — starts on first request)")
361
+ : "";
362
+ console.log(chalk.gray(` - ${svc.name}: ${apiBase}${chalk.cyan(appendHealthPath(apiPath))}${deferredTag}`));
363
+ }
364
+ }
365
+ }
366
+ const focusTargets = options.only ?? (stackName ? [stackName] : undefined);
367
+ const tiltArgs = buildTiltUpArgs(focusServiceNames, {
368
+ verbose: options.verbose,
369
+ quiet: options.quiet,
370
+ force: options.force,
371
+ focusTargets,
372
+ });
373
+ const dryRunCommand = focusTargets ? `tilt up ${tiltArgs.join(" ")}` : "tilt up";
374
+ if (!options.quiet) {
375
+ console.log(chalk.blue(formatHostPortPlan(hostPortPlan)));
376
+ for (const line of formatPortFallbackNotice(hostPortPlan))
377
+ console.log(chalk.yellow(line));
378
+ console.log(chalk.gray("Override with TDK_HTTP_PORT, TDK_HTTPS_PORT, or TDK_POSTGRES_PORT."));
379
+ }
380
+ if (emit && options.dryRun) {
381
+ emit({
382
+ ok: true,
383
+ dryRun: true,
384
+ stack: stackName ?? null,
385
+ services: serviceNames,
386
+ ...(options.only
387
+ ? { requested: options.only, declaredDependencies: dependencyNames }
388
+ : {}),
389
+ command: dryRunCommand,
390
+ });
391
+ return;
392
+ }
393
+ if (handleDryRun(options, "not starting services", dryRunCommand)) {
394
+ return;
395
+ }
396
+ exportHostPortPlan(hostPortPlan);
397
+ writeSavedHostPortPlan(projectRoot, hostPortPlan);
398
+ const basePort = STANDARD_PORTS.tiltUi;
399
+ const watchedPort = configuredTiltPort ?? basePort;
400
+ const candidatePorts = options.only ? [...new Set([basePort, watchedPort])] : [watchedPort];
401
+ const { running, foreign } = await classifyTiltPorts(candidatePorts, projectRoot, async (candidate) => (await tiltGetUiResources(candidate)) !== null);
402
+ if (foreign.length > 0 && configuredTiltPort !== undefined) {
403
+ const other = foreign[0];
404
+ const message = `TILT_PORT=${other?.port} is used by another project's Tilt (${other?.root}). Choose a free port, or run flisk down in that project.`;
405
+ emit?.({ ok: false }, [{ code: "TILT_PORT_IN_USE", message }]);
406
+ showErrorAndExit(message);
407
+ }
408
+ if (!options.quiet) {
409
+ for (const other of foreign) {
410
+ console.log(chalk.yellow(`⚠️ Tilt on port ${other.port} belongs to another project (${other.root}); this project will use another port.`));
411
+ }
412
+ }
413
+ // --force replaces this project's Tilt; it must never stop another project's.
414
+ const force = options.force && foreign.length === 0;
415
+ const decision = secondUpAction({
416
+ runningPorts: running,
417
+ force,
418
+ only: Boolean(options.only),
419
+ });
420
+ if (decision.action === "already-running") {
421
+ const message = `Environment is already running on port ${decision.ports.join(", ")}.`;
422
+ emit?.({
423
+ ok: true,
424
+ alreadyRunning: true,
425
+ tiltUrl: `http://localhost:${decision.ports[0]}`,
426
+ });
427
+ if (!options.quiet)
428
+ console.log(chalk.green(message));
429
+ return;
430
+ }
431
+ if (decision.action === "only-blocked") {
432
+ const message = `A Tilt is already running on port ${decision.ports.join(", ")}. --only cannot change a running stack's services: run \`flisk down\` first, or pass --force to replace it.`;
433
+ emit?.({ ok: false }, [{ code: "TILT_ALREADY_RUNNING", message }]);
434
+ showErrorAndExit(message);
435
+ }
436
+ if (options.only) {
437
+ for (const runningPort of running)
438
+ stopTiltOnPort(runningPort);
439
+ }
440
+ const resolution = await resolveTiltPort({
441
+ configuredPort: configuredTiltPort,
442
+ force,
443
+ basePort,
444
+ findAvailablePort,
445
+ });
446
+ const port = resolution.port;
447
+ if (resolution.autoSwitched && !options.quiet) {
448
+ console.log(chalk.yellow(`⚠️ Port ${basePort} is already in use`));
449
+ console.log(chalk.blue(`🔄 Auto-switching to port ${port}\n`));
450
+ }
451
+ process.env.TILT_PORT = port.toString();
452
+ await stopTiltForUp({ force, quiet: options.quiet, port }, {
453
+ stop: stopTiltOnPort,
454
+ log: (message) => console.log(chalk.yellow(message)),
455
+ wait: (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)),
456
+ });
457
+ if (!options.quiet) {
458
+ console.log(chalk.gray("\nRunning tilt up..."));
459
+ console.log(chalk.gray(`Using Tiltfile: .tdk/.tdk-out/Tiltfile`));
460
+ }
461
+ const tiltRun = runTilt("up", tiltArgs, {
462
+ verbose: options.verbose && !options.json,
463
+ quiet: options.quiet,
464
+ inheritStdio: !options.quiet, // Suppress tilt output in quiet mode
465
+ });
466
+ // Services that declare `smoke` are checked through the public URL once Tilt is up. A miss stops Tilt (containers stay for
467
+ // inspection; `flisk down` removes them) and fails the command.
468
+ const smokePlans = buildSmokePlans(servicesToStart, hostPortPlan.ingressHttp);
469
+ let smokeFailed = false;
470
+ let printedSuccess = false;
471
+ let startupFailed = false;
472
+ let signalStartupFailed = () => { };
473
+ const startupFailure = new Promise((resolve) => {
474
+ signalStartupFailed = resolve;
475
+ });
476
+ const successOutput = (async () => {
477
+ const uiReady = await waitForTiltUi(port);
478
+ // JSON consumers get success only after every non-deferred resource is built and running, not when the UI port opens.
479
+ let jsonReady = false;
480
+ let startedServices = serviceNames;
481
+ let startedDependencies = dependencyNames;
482
+ if (uiReady && emit) {
483
+ const deferred = getDeferredResourceNames(discoveredResources);
484
+ const readiness = await waitForTiltResourcesReady(port, {
485
+ deferred,
486
+ // Only what the caller named must be enabled. Dependencies are the Tiltfile's call (it skips some on purpose).
487
+ expected: options.only
488
+ ? options.only.filter((name) => !deferred.has(name))
489
+ : undefined,
490
+ });
491
+ if (readiness.ready) {
492
+ jsonReady = true;
493
+ if (options.only) {
494
+ // Report what Tilt actually enabled, not the service.json closure, which can differ from the Tiltfile's expansion.
495
+ const enabled = new Set(readiness.enabled);
496
+ const allNames = discoveredResources.map((r) => r.name);
497
+ startedServices = allNames.filter((name) => enabled.has(name));
498
+ startedDependencies = startedServices.filter((name) => !options.only.includes(name));
499
+ }
500
+ }
501
+ else {
502
+ startupFailed = true;
503
+ const detail = readiness.failures.map((f) => `${f.name}: ${f.message}`).join("; ");
504
+ emit({ ok: false, tiltUrl: `http://localhost:${port}`, failures: readiness.failures }, [
505
+ {
506
+ code: readiness.timedOut ? "UP_TIMEOUT" : "UP_RESOURCE_FAILED",
507
+ message: `${readiness.timedOut ? "Timed out waiting for resources" : "Resources failed"}${detail ? ` (${detail})` : ""}. Tilt is still running; inspect it or run: flisk down`,
508
+ },
509
+ ]);
510
+ }
511
+ }
512
+ // The UI port opening only means Tilt started. Say "up" once every resource is built and running, and otherwise name
513
+ // what failed and what it blocks.
514
+ if (uiReady && !emit) {
515
+ const deferred = getDeferredResourceNames(discoveredResources);
516
+ const dependsOn = Object.fromEntries(discoveredResources.map((r) => [r.name, r.config?.dependsOn ?? []]));
517
+ const readiness = await waitForTiltResourcesReady(port, {
518
+ deferred,
519
+ isStalled: (text) => isStartupStalled(text, dependsOn, deferred),
520
+ });
521
+ if (!readiness.ready) {
522
+ startupFailed = true;
523
+ const resourcesJson = await tiltGetUiResources(port);
524
+ const report = resourcesJson
525
+ ? buildStartupReport(resourcesJson, dependsOn, deferred)
526
+ : {
527
+ failed: readiness.failures.map((failure) => ({
528
+ name: failure.name,
529
+ message: summarizeTiltBuildError(failure.message),
530
+ })),
531
+ blocked: [],
532
+ starting: [],
533
+ };
534
+ const reportLines = formatStartupReport(report, readiness.timedOut);
535
+ if (reportLines.length > 0) {
536
+ showError(reportLines.join("\n"));
537
+ }
538
+ }
539
+ }
540
+ if (uiReady && !options.quiet && !startupFailed) {
541
+ for (const line of formatUpSuccess(port))
542
+ console.log(chalk.blue(line));
543
+ printedSuccess = true;
544
+ }
545
+ if (uiReady && smokePlans.length > 0 && (emit ? jsonReady : !startupFailed)) {
546
+ if (!options.quiet) {
547
+ console.log(chalk.gray(`Smoke check: ${smokePlans.map((p) => p.name).join(", ")}`));
548
+ }
549
+ // The records hold response bodies, so they must not be committable. Warn before writing them when the ignore
550
+ // entry could not be added.
551
+ const ignoreWarning = ensureSmokeRecordsIgnored(projectRoot);
552
+ if (ignoreWarning)
553
+ console.warn(chalk.yellow(ignoreWarning));
554
+ const results = await runSmokePlans(smokePlans, {
555
+ recordDir: join(projectRoot, ".tdk", "smoke"),
556
+ ...safeSmokeDeps(projectRoot, (message) => console.warn(chalk.yellow(message))),
557
+ });
558
+ for (const smokeResult of results) {
559
+ if (smokeResult.ok) {
560
+ if (!options.quiet)
561
+ console.log(chalk.green(`Smoke check passed: ${smokeResult.name}`));
562
+ }
563
+ else {
564
+ smokeFailed = true;
565
+ showError(formatSmokeFailure(smokeResult));
566
+ }
567
+ }
568
+ if (smokeFailed) {
569
+ stopTiltOnPort(port);
570
+ emit?.({ ok: false }, [
571
+ { code: "UP_SMOKE_FAILED", message: "A smoke check failed; Tilt was stopped" },
572
+ ]);
573
+ }
574
+ }
575
+ if (uiReady && jsonReady && !smokeFailed) {
576
+ emit?.({
577
+ ok: true,
578
+ stack: stackName ?? null,
579
+ services: startedServices,
580
+ ...(options.only ? { requested: options.only, dependencies: startedDependencies } : {}),
581
+ tiltUrl: `http://localhost:${port}`,
582
+ });
583
+ }
584
+ if (startupFailed)
585
+ signalStartupFailed();
586
+ })();
587
+ const result = await waitForTiltUnlessStartupFailed(tiltRun, startupFailure);
588
+ await successOutput;
589
+ if (smokeFailed) {
590
+ process.exit(1);
591
+ }
592
+ if (result.exitCode !== 0) {
593
+ handleTiltFailure("up", result.exitCode);
594
+ }
595
+ if (startupFailed && result.exitCode === 0) {
596
+ process.exit(1);
597
+ }
598
+ if (!options.quiet && result.exitCode === 0 && !printedSuccess) {
599
+ for (const line of formatUpSuccess(port))
600
+ console.log(chalk.blue(line));
601
+ }
602
+ };
603
+ if (options.dryRun) {
604
+ await runCommand(action);
605
+ }
606
+ else {
607
+ await withTiltCheck(action);
608
+ }
609
+ });