@flisk-sh/flisk 0.0.0-stage → 1.3.190

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-CLCUIDBH.js +510 -0
  170. package/cli/dist-bundle/cli.js +2017 -0
  171. package/cli/dist-bundle/cold-preflight-SY26O2IG.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,637 @@
1
+ # Copyright (c) 2026 Flisk contributors
2
+ # SPDX-License-Identifier: MIT
3
+ # =============================================================================
4
+ # 🐳 TILT SDK - DOCKER COMPOSE GENERATORS (modular)
5
+ # =============================================================================
6
+ # Path: .tilt/topologies/platform/docker/compose.star
7
+ # Purpose: docker-compose generation helpers extracted from .tilt/providers/docker.star
8
+ # =============================================================================
9
+
10
+ # === INLINED CONSTANTS for pure extension loading ===
11
+ BASE_PORT_FRONTEND = 3000
12
+ BASE_PORT_BACKEND = 4000
13
+ # The nginx frontend runtime layer always serves on 80: L4_generate_frontend_runtime
14
+ # emits a fixed `EXPOSE 80` and the generated nginx.conf has a fixed `listen 80`.
15
+ NGINX_CONTAINER_PORT = 80
16
+ HEALTH_CHECK_PATH = "/health"
17
+ NO_HTTP_HEALTHCHECK = " healthcheck:\n disable: true\n"
18
+ OUTPUT = struct(AUTOGENERATED_FOLDER = ".autogenerated")
19
+ # === END INLINED CONSTANTS ===
20
+
21
+
22
+ load("./compose_helpers.star", "compose_build_config")
23
+ load("../networking/traefik.star", "get_frontend_traefik_labels", "get_backend_traefik_labels")
24
+ load("../networking/api_path_constants.star", "get_api_path_for_domain", "get_frontend_base_path")
25
+ load("../secrets/infisical.star", "get_infisical_environment_vars")
26
+ load("../secrets/env_secrets.star", "get_secret_environment_lines")
27
+ load("../auth/auth.star", "AuthConfig")
28
+
29
+ load("../constants.star", "PlatformDockerConstants")
30
+ load("../config/healthcheck.star", "DOCKER_HEALTHCHECK", "compose_healthcheck_timing")
31
+
32
+ # Load project name for dynamic host naming
33
+ # Use TDK_PROJECT_ROOT env var set by Tilt, fallback to current directory
34
+ def _load_project_name():
35
+ project_root = os.environ.get('TDK_PROJECT_ROOT', '')
36
+ project_json_path = '.tdk/project.json'
37
+ if project_root:
38
+ project_json_path = project_root + '/' + project_json_path
39
+
40
+ if os.path.exists(project_json_path):
41
+ _project_json = read_json(project_json_path)
42
+ return _project_json.get('project', {}).get('name', 'tdk-project')
43
+ return 'tdk-project'
44
+
45
+ _PROJECT_NAME = _load_project_name()
46
+
47
+
48
+ def _compute_env_file_rel_path(resource_path, full_resource_path, env_filename):
49
+ """
50
+ Compute the relative path from compose file location to env file.
51
+
52
+ The compose file is at: resource_path + '/' + OUTPUT.AUTOGENERATED_FOLDER/docker-compose.app.autogenerated.yml'
53
+ The env file is at: full_resource_path + '/' + OUTPUT.AUTOGENERATED_FOLDER + '/' + env_filename
54
+
55
+ Args:
56
+ resource_path: The domain/service group path (e.g., 'services/product/users' or 'services/platform')
57
+ full_resource_path: The actual service path (e.g., 'services/product/users/user-management-backend' or 'shared-platform-engineering/my-lib/infra')
58
+ env_filename: The env file name (e.g., '.env.frontend.autogenerated' or '.env.backend.autogenerated')
59
+
60
+ Returns:
61
+ Relative path from compose file to env file
62
+ """
63
+ # Count how many levels deep the compose file is
64
+ # resource_path like 'services/product/users' has 3 parts
65
+ # compose file is at resource_path + '/' + OUTPUT.AUTOGENERATED_FOLDER + '/', so we need len(parts) + 1 levels of ../
66
+ resource_path_parts = resource_path.split('/')
67
+ num_dotdots = len(resource_path_parts) + 1 # +1 for the autogenerated directory
68
+
69
+ # Build the dotdot prefix
70
+ dotdot_prefix = '/'.join(['..'] * num_dotdots)
71
+
72
+ # The env file is at full_resource_path + '/' + OUTPUT.AUTOGENERATED_FOLDER + '/' + env_filename
73
+ return dotdot_prefix + '/' + full_resource_path + '/' + OUTPUT.AUTOGENERATED_FOLDER + '/' + env_filename
74
+
75
+ # =============================================================================
76
+ # 🚦 FRONTEND / BACKEND ENTRIES
77
+ # =============================================================================
78
+
79
+ def generate_frontend_compose(resource_path, resource_name, res, manifest=None):
80
+ """Generate frontend docker-compose entry with Traefik routing."""
81
+ res_name = res['name']
82
+ image_name = PlatformDockerConstants.app_image_name(resource_name, res_name)
83
+ stack = manifest.get('stack', resource_name) if manifest else resource_name
84
+
85
+ target_path = res.get('target_path', manifest.get('target_path', '/usr/share/nginx/html'))
86
+ use_nginx = 'nginx' in target_path or target_path == '/usr/share/nginx/html'
87
+ # The manifest `port` is the Vite dev-server port. These compose entries always
88
+ # build the `production` target, so for an nginx runtime the port inside the
89
+ # container is 80, not the dev port. Using the dev port here made the container
90
+ # healthcheck probe a port nothing listens on, which left the container marked
91
+ # unhealthy -- and Traefik's Docker provider skips unhealthy containers, so the
92
+ # router was never registered and every request 404'd.
93
+ port = NGINX_CONTAINER_PORT if use_nginx else manifest.get('port', BASE_PORT_FRONTEND)
94
+
95
+ # Base path for routing on {project}.localhost. Shared with the Vite config and
96
+ # PUBLIC_URL generators -- see get_frontend_base_path for why they must agree.
97
+ base_path = get_frontend_base_path(manifest, res_name)
98
+
99
+ traefik_cfg = manifest.get('traefik', {}) if manifest else {}
100
+ traefik_host = traefik_cfg.get('host')
101
+ # Use custom dockerfile from manifest if specified, otherwise use autogenerated default
102
+ dockerfile_path = res.get('dockerfile', OUTPUT.AUTOGENERATED_FOLDER + '/Dockerfile.app.autogenerated')
103
+ # Handle flat service structure (e.g., services/product/identity-management-frontend) vs nested (services/product/domain/service)
104
+ # Detect flat structure: services/product/{service} (3 path parts after root)
105
+ # vs nested: services/product/{domain}/{service} (4+ path parts)
106
+ full_resource_path = res.get('_resource_path', resource_path + '/' + res_name)
107
+ path_parts = full_resource_path.split('/')
108
+ # If path is like services/product/xxx (3 parts), it's flat - use path directly
109
+ # If path is like services/product/domain/xxx (4 parts), it's nested - use standard construction
110
+ if len(path_parts) <= 3:
111
+ # Flat structure: resource_path already includes res_name
112
+ build_config = compose_build_config(full_resource_path, '', dockerfile_path, 'production')
113
+ else:
114
+ # Nested structure: use resource_path and res_name separately
115
+ build_config = compose_build_config(resource_path, res_name, dockerfile_path, 'production')
116
+
117
+ # Calculate correct relative path to env_file from compose file location
118
+ # The compose file is at: resource_path + '/' + OUTPUT.AUTOGENERATED_FOLDER/docker-compose.app.autogenerated.yml'
119
+ # The env file is at: full_resource_path + '/' + OUTPUT.AUTOGENERATED_FOLDER/.env.frontend.autogenerated'
120
+ env_file_rel_path = _compute_env_file_rel_path(resource_path, full_resource_path, '.env.frontend.autogenerated')
121
+
122
+ traefik_labels = get_frontend_traefik_labels(
123
+ res_name,
124
+ stack,
125
+ base_path,
126
+ port,
127
+ traefik_host=traefik_host,
128
+ manifest=manifest,
129
+ )
130
+
131
+ return """ {res_name}:
132
+ image: {image_name}
133
+ init: true
134
+ {build_config}
135
+ <<: *frontend-memory-limit
136
+ env_file:
137
+ - {env_file_rel_path}
138
+ environment:
139
+ - VITE_APP_ENV=development
140
+ labels:
141
+ {traefik_labels}
142
+ networks:
143
+ - {network_traefik_public}
144
+ - {network_backend}
145
+ healthcheck:
146
+ test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://127.0.0.1:{port}"]
147
+ {healthcheck_timing}""".format(
148
+ res_name=res_name,
149
+ image_name=image_name,
150
+ build_config=build_config,
151
+ env_file_rel_path=env_file_rel_path,
152
+ traefik_labels=traefik_labels,
153
+ port=port,
154
+ network_traefik_public=PlatformDockerConstants.NETWORK_TRAEFIK_PUBLIC,
155
+ network_backend=PlatformDockerConstants.NETWORK_BACKEND,
156
+ healthcheck_timing=compose_healthcheck_timing(DOCKER_HEALTHCHECK["frontend_start_period_seconds"]),
157
+ )
158
+
159
+
160
+ def _generate_single_backend_entry(resource_path, resource_name, res, manifest, instance_id=None):
161
+ """
162
+ Generate a single backend docker-compose entry.
163
+ """
164
+ res_name = res['name']
165
+ stack = manifest.get('stack', resource_name) if manifest else resource_name
166
+
167
+ # Get full service path from resource (for cross-root service support)
168
+ full_resource_path = res.get('_resource_path', resource_path + '/' + res_name)
169
+
170
+ # Calculate correct relative path to env_file from compose file location
171
+ env_file_rel_path = _compute_env_file_rel_path(resource_path, full_resource_path, '.env.backend.autogenerated')
172
+
173
+ internal_port = manifest.get('port', BASE_PORT_BACKEND) if manifest else BASE_PORT_BACKEND
174
+ dev_port = internal_port
175
+ # Use PROJECT_NAME from PlatformDockerConstants for portable database naming
176
+ _db_prefix = PlatformDockerConstants.PROJECT_NAME + "_"
177
+ db_name = manifest.get('databaseName', _db_prefix + stack) if manifest else _db_prefix + stack
178
+
179
+ # Compute database URLs using centralized constants
180
+ db_url_for_tilt = PlatformDockerConstants.get_database_url_for_env(db_name)
181
+ db_url_with_fallback = PlatformDockerConstants.get_compose_env_database_url(db_name)
182
+
183
+ health_path = manifest.get('healthCheckPath', HEALTH_CHECK_PATH) if manifest else HEALTH_CHECK_PATH
184
+ # A bring-your-own service without healthCheckPath may not serve HTTP. None means no HTTP probe: no Traefik health check labels.
185
+ if manifest and manifest.get('appType') == 'bring-your-own' and not manifest.get('healthCheckPath'):
186
+ health_path = None
187
+
188
+ traefik_cfg = manifest.get('traefik', {}) if manifest else {}
189
+ traefik_host = traefik_cfg.get('host', stack + '.backend.' + _PROJECT_NAME + '.local')
190
+ # ALPHA: Use proper API v1 path with -management suffix via api_path_constants
191
+ # Old default: '/api/' + stack
192
+ # New default: get_api_path_for_domain → /api/v1/{stack}-management
193
+ traefik_path = traefik_cfg.get('pathPrefix', get_api_path_for_domain(stack, manifest))
194
+
195
+ nats_cfg = manifest.get('nats', {}) if manifest else {}
196
+ nats_queue = nats_cfg.get('queueGroup', stack + '_backend_svc')
197
+ nats_url = PlatformDockerConstants.NATS_URL
198
+
199
+ # Auth configuration: one shared builder keeps this identical to the generated env file (see AuthConfig.from_manifest).
200
+ auth_config = AuthConfig.from_manifest(manifest)
201
+
202
+ auth_env = AuthConfig.generate_docker_compose_auth_env(auth_config)
203
+ # secrets.required / secrets.optional, read from the project .env by Compose (empty with TDK_SECRET_PROVIDER=infisical)
204
+ secrets_env = get_secret_environment_lines(manifest, res_name)
205
+
206
+ # Use .autogenerated/Dockerfile.app.autogenerated by default for build config (primary only)
207
+ if manifest and manifest.get('appType') == 'bring-your-own':
208
+ if manifest.get('image'):
209
+ build_config = ""
210
+ else:
211
+ # A BYO Dockerfile copies paths relative to the service directory
212
+ # (for example, `COPY app.py .`). Build with that directory as the
213
+ # context instead of the project root used by generated Flisk apps.
214
+ context_prefix = '/'.join(['..'] * (len(resource_path.split('/')) + 1))
215
+ build_context = context_prefix + '/' + full_resource_path
216
+ # `buildContext` (relative to the service directory) moves the context
217
+ # to the source tree an imported Dockerfile lives in; `dockerfile` is then
218
+ # relative to that context, as in Compose.
219
+ custom_context = manifest.get('buildContext')
220
+ if custom_context and custom_context != '.':
221
+ build_context = build_context + '/' + custom_context
222
+ dockerfile = manifest.get('dockerfile', 'Dockerfile')
223
+ if dockerfile.startswith('./'):
224
+ dockerfile = dockerfile[2:]
225
+ build_config = """ build:
226
+ context: {build_context}
227
+ dockerfile: {dockerfile}""".format(
228
+ build_context=build_context,
229
+ dockerfile=dockerfile,
230
+ )
231
+ else:
232
+ build_config = compose_build_config(resource_path, res_name)
233
+
234
+ # REMOVED: External port exposure - all services accessed via Traefik only
235
+ # Services are available at {project}.localhost/api/v1/{service}
236
+ # Inside the Docker network a service listens on its own port (manifest.port, passed to it as PORT), for service-to-service calls
237
+ ports_section = "" # No external ports - Traefik-only access
238
+
239
+ # Determine service name based on instance
240
+ if instance_id:
241
+ # Replica instance: add instance suffix
242
+ resource_entry_name = res_name + '-' + str(instance_id)
243
+ instance_label = str(instance_id)
244
+ # Replicas should reuse the already-built image; avoid per-replica builds
245
+ build_config = ""
246
+ else:
247
+ # Primary instance
248
+ resource_entry_name = res_name
249
+ instance_label = '0'
250
+
251
+ # All instances share the same Traefik service for load balancing
252
+ traefik_resource_name = res_name # LB service name (shared)
253
+
254
+ # Workers have no HTTP server: they consume from NATS and exit-on-crash. Giving
255
+ # them a Traefik route advertises an endpoint that can never answer, and giving
256
+ # them an HTTP healthcheck marks a perfectly healthy worker as unhealthy forever.
257
+ is_worker = manifest.get('appType') == 'worker' if manifest else False
258
+ is_byo = manifest.get('appType') == 'bring-your-own' if manifest else False
259
+ is_proxy_disabled_byo = (
260
+ is_byo and not manifest.get('exposeViaProxy', True)
261
+ ) if manifest else False
262
+
263
+ # One-shot jobs (migrations, seeders) must not be restarted after they exit 0, so a
264
+ # bring-your-own resource can choose its Compose restart policy. Default is unchanged.
265
+ restart_policy = 'unless-stopped'
266
+ if is_byo and manifest.get('restart') in ['no', 'on-failure', 'unless-stopped', 'always']:
267
+ restart_policy = manifest.get('restart')
268
+ restart_policy = '"no"' if restart_policy == 'no' else restart_policy
269
+
270
+ # No HTTP server means no HTTP probe. Disable explicitly: the image HEALTHCHECK would otherwise probe a port nothing listens on.
271
+ no_http_healthcheck_section = NO_HTTP_HEALTHCHECK if (is_worker or health_path == None) else ""
272
+ # Backends with a health path get it in the env, so the shared golden image's HEALTHCHECK can probe it.
273
+ health_env = " - TDK_HEALTH_PATH={}\n".format(health_path) if health_path else ""
274
+ # An agent with files durability keeps its session checkpoints in a named volume. The volume is declared at the top of the
275
+ # generated file (generate_app_compose_from_entries reads the marker line below), so flisk down keeps it.
276
+ agent_env = ""
277
+ agent_volume_section = ""
278
+ if manifest and type(manifest.get('agent')) == 'dict':
279
+ agent_durability = manifest['agent'].get('durability', 'files')
280
+ agent_env = " - AGENT_DURABILITY={}\n".format(agent_durability)
281
+ if agent_durability == 'files':
282
+ agent_volume = res_name + '-agent-state'
283
+ agent_env += " - AGENT_STATE_DIR=/var/lib/tdk-agent\n"
284
+ agent_volume_section = " # tdk-agent-volume: {vol}\n volumes:\n - {vol}:/var/lib/tdk-agent\n".format(vol=agent_volume)
285
+
286
+ if is_worker or is_proxy_disabled_byo:
287
+ traefik_labels = ' - "traefik.enable=false"'
288
+ healthcheck_section = no_http_healthcheck_section
289
+ else:
290
+ # Traefik's load-balancer check can be overridden separately in service.json
291
+ # (`traefik.healthCheck`); it defaults to the container check's path.
292
+ traefik_health_path = traefik_cfg.get('healthCheck') or health_path
293
+ traefik_labels = get_backend_traefik_labels(
294
+ resource_entry_name=resource_entry_name,
295
+ traefik_host=traefik_host,
296
+ traefik_path=traefik_path,
297
+ traefik_resource_name=traefik_resource_name,
298
+ internal_port=internal_port,
299
+ health_path=traefik_health_path,
300
+ manifest=manifest,
301
+ )
302
+ # BYO images may not contain curl. Traefik uses its own HTTP health
303
+ # check labels above, so don't mark an otherwise healthy container
304
+ # unhealthy because the image lacks a command Flisk cannot require.
305
+ healthcheck_section = no_http_healthcheck_section if no_http_healthcheck_section else "" if is_byo else """ healthcheck:
306
+ test: ["CMD", "curl", "-f", "--max-time", "5", "http://localhost:{internal_port}{health_path}"]
307
+ """.format(internal_port=internal_port, health_path=health_path) + compose_healthcheck_timing()
308
+ infisical_env = get_infisical_environment_vars(as_array=True, resource_name=res_name)
309
+
310
+ # Build auth environment variables section using centralized auth utilities
311
+
312
+ return """
313
+ {resource_entry_name}:
314
+ image: {image_name}
315
+ init: true
316
+ restart: {restart_policy}
317
+ {build_config}
318
+ {ports_section}
319
+ env_file:
320
+ - {env_file_rel_path}
321
+ environment:
322
+ {infisical_env}
323
+ - RESOURCE_NAME={stack}
324
+ - PORT={port_anchor}
325
+ {health_env}{agent_env} - INSTANCE_ID={instance_label}
326
+ - NATS_QUEUE_GROUP={nats_queue}
327
+ - TILT_DATABASE_URL={db_url_for_tilt}
328
+ - TILT_NATS_URL={nats_url}
329
+ - NODE_ENV=development
330
+ - DATABASE_URL={db_url_for_tilt}
331
+ # Per-project escape hatch: set AUTO_MIGRATE=false in the project root .env
332
+ # to skip Prisma auto-migration at container boot (e.g. while diagnosing a
333
+ # migration/CLI issue) without touching the generator or any service code.
334
+ - AUTO_MIGRATE=${{AUTO_MIGRATE:-true}}
335
+ {auth_env}{secrets_env}
336
+ {agent_volume_section} labels:
337
+ {traefik_labels}
338
+ networks:
339
+ - {network_traefik_public}
340
+ - {network_backend}
341
+ - {network_database}
342
+ - {network_infisical}
343
+ {healthcheck_section} # Note: depends_on removed - Tilt manages service startup order
344
+ deploy:
345
+ resources:
346
+ limits:
347
+ cpus: '0.5'
348
+ memory: 512M
349
+ reservations:
350
+ cpus: '0.2'
351
+ memory: 256M
352
+ """.format(
353
+ resource_entry_name=resource_entry_name,
354
+ res_name=res_name,
355
+ resource_name=resource_name,
356
+ image_name=(
357
+ manifest.get('image')
358
+ if manifest and manifest.get('appType') == 'bring-your-own' and manifest.get('image')
359
+ else PlatformDockerConstants.app_image_name(resource_name, res_name)
360
+ ),
361
+ build_config=build_config,
362
+ ports_section=ports_section,
363
+ env_file_rel_path=env_file_rel_path,
364
+ stack=stack,
365
+ internal_port=internal_port,
366
+ port_anchor=internal_port,
367
+ restart_policy=restart_policy,
368
+ dev_port=dev_port,
369
+ db_name=db_name,
370
+ db_url_for_tilt=db_url_for_tilt,
371
+ db_url_with_fallback=db_url_with_fallback,
372
+ instance_label=instance_label,
373
+ health_path=health_path,
374
+ traefik_host=traefik_host,
375
+ traefik_path=traefik_path,
376
+ traefik_resource_name=traefik_resource_name,
377
+ nats_queue=nats_queue,
378
+ nats_url=nats_url,
379
+ traefik_labels=traefik_labels,
380
+ healthcheck_section=healthcheck_section,
381
+ health_env=health_env,
382
+ agent_env=agent_env,
383
+ agent_volume_section=agent_volume_section,
384
+ infisical_env=infisical_env,
385
+ auth_env=auth_env,
386
+ secrets_env=secrets_env,
387
+ network_traefik_public=PlatformDockerConstants.NETWORK_TRAEFIK_PUBLIC,
388
+ network_backend=PlatformDockerConstants.NETWORK_BACKEND,
389
+ network_database=PlatformDockerConstants.NETWORK_DATABASE,
390
+ network_infisical=PlatformDockerConstants.NETWORK_INFISICAL,
391
+ )
392
+
393
+
394
+ def generate_backend_compose_entry(resource_path, resource_name, res, manifest=None):
395
+ """
396
+ Generate backend docker-compose entries with TRUE multi-replica support.
397
+ """
398
+ replicas = manifest.get('replicas', 1) if manifest else 1
399
+
400
+ if replicas <= 1:
401
+ # Single instance - simple case
402
+ return _generate_single_backend_entry(resource_path, resource_name, res, manifest, instance_id=None)
403
+
404
+ # Multi-replica: generate separate service entries
405
+ entries = []
406
+
407
+ # Primary instance (gets the port mapping)
408
+ entries.append(_generate_single_backend_entry(resource_path, resource_name, res, manifest, instance_id=None))
409
+
410
+ # Additional replicas (numbered, expose only)
411
+ for i in range(1, replicas):
412
+ entries.append(_generate_single_backend_entry(resource_path, resource_name, res, manifest, instance_id=i))
413
+
414
+ return ''.join(entries)
415
+
416
+
417
+ def _generate_port_anchors(resource_entries):
418
+ """Extract unique ports and generate YAML anchors for them."""
419
+ backend_port = None
420
+ frontend_port = None
421
+ sdk_port = None
422
+ has_backend = False
423
+ has_sdk = False
424
+ has_frontend = False
425
+
426
+ for entry in resource_entries:
427
+ # Check if this is an SDK (ends with -sdk)
428
+ if "-sdk:" in entry or entry.strip().startswith("identity-sdk:"):
429
+ has_sdk = True
430
+ # Extract SDK port from entry
431
+ if "loadbalancer.server.port=" in entry:
432
+ for line in entry.split("\n"):
433
+ if "loadbalancer.server.port=" in line:
434
+ # Safe parsing without try/except
435
+ port_str = line.split("loadbalancer.server.port=")[-1].split('"')[0]
436
+ if port_str.isdigit():
437
+ sdk_port = int(port_str)
438
+ break
439
+ # Check if this is a frontend (has frontend-memory-limit but not SDK)
440
+ elif "<<: *frontend-memory-limit" in entry and not ("-sdk:" in entry or entry.strip().startswith("identity-sdk:")):
441
+ has_frontend = True
442
+ # Extract frontend port from entry
443
+ if "loadbalancer.server.port=" in entry:
444
+ for line in entry.split("\n"):
445
+ if "loadbalancer.server.port=" in line:
446
+ # Safe parsing without try/except
447
+ port_str = line.split("loadbalancer.server.port=")[-1].split('"')[0]
448
+ if port_str.isdigit():
449
+ frontend_port = int(port_str)
450
+ break
451
+ # Check if this is a backend (has a port, not frontend, not SDK)
452
+ # Backend entries have "healthcheck:" section with backend port
453
+ elif "healthcheck:" in entry and "<<: *frontend-memory-limit" not in entry and not ("-sdk:" in entry or entry.strip().startswith("identity-sdk:")):
454
+ has_backend = True
455
+ # Extract backend port from entry
456
+ if "loadbalancer.server.port=" in entry:
457
+ for line in entry.split("\n"):
458
+ if "loadbalancer.server.port=" in line:
459
+ # Safe parsing without try/except
460
+ port_str = line.split("loadbalancer.server.port=")[-1].split('"')[0]
461
+ if port_str.isdigit():
462
+ backend_port = int(port_str)
463
+ break
464
+
465
+ # Build anchors - use extracted port or fall back to default
466
+ anchors = []
467
+ anchors.append("x-backend-port: &backend-port {}".format(backend_port if backend_port else BASE_PORT_BACKEND))
468
+ if has_frontend and frontend_port:
469
+ anchors.append("x-frontend-port: &frontend-port {}".format(frontend_port))
470
+ if has_sdk and sdk_port:
471
+ anchors.append("x-sdk-port: &sdk-port {}".format(sdk_port))
472
+
473
+ return "\n".join(anchors)
474
+
475
+
476
+ def generate_app_compose_from_entries(resource_path, resource_entries, write_fn=None):
477
+ """Generate docker-compose.app.autogenerated.yml from service entries with port anchors.
478
+
479
+ Args:
480
+ resource_path: Path to the resource directory
481
+ resource_entries: List of docker-compose entries for services
482
+ write_fn: Optional write function for file output
483
+
484
+ Returns:
485
+ str: Generated docker-compose YAML content
486
+ """
487
+
488
+ # Generate port anchors
489
+ port_anchors = _generate_port_anchors(resource_entries)
490
+
491
+ header = """###############################################################################
492
+ # 🛑 CRITICAL: SYSTEM-GENERATED FILE - DO NOT MODIFY DIRECTLY
493
+ #
494
+ # ANY MANUAL CHANGES MADE TO THIS FILE WILL BE WIPED ON THE NEXT 'tilt up'.
495
+ # Generation Source: .tilt/topologies/platform/docker/index.star
496
+ ###############################################################################
497
+
498
+ # =============================================================================
499
+ # PORT DEFINITIONS - Change these to change ports everywhere
500
+ # =============================================================================
501
+ {port_anchors}
502
+
503
+ # =============================================================================
504
+ # MEMORY LIMITS
505
+ # =============================================================================
506
+ x-nix-any-m1-arm64-memory-limit: &nix-any-m1-arm64-memory-limit
507
+ deploy:
508
+ resources:
509
+ limits:
510
+ memory: 192M
511
+ reservations:
512
+ memory: 64M
513
+
514
+ x-frontend-memory-limit: &frontend-memory-limit
515
+ deploy:
516
+ resources:
517
+ limits:
518
+ memory: 64M
519
+ cpus: '0.15'
520
+ reservations:
521
+ memory: 32M
522
+
523
+ services:
524
+ """.format(port_anchors=port_anchors)
525
+
526
+ # Named volumes used by services (agent session state) must be declared at the top level. Services mark them with a
527
+ # "# tdk-agent-volume: <name>" line, so the declaration follows the services without a separate registry.
528
+ volume_names = []
529
+ for entry in resource_entries:
530
+ for line in entry.split("\n"):
531
+ if line.strip().startswith("# tdk-agent-volume: "):
532
+ name = line.strip()[len("# tdk-agent-volume: "):]
533
+ # Replicas of one agent repeat the marker; Compose rejects a duplicate key under volumes:.
534
+ if name not in volume_names:
535
+ volume_names.append(name)
536
+ volumes_section = ""
537
+ if volume_names:
538
+ volumes_section = "\nvolumes:\n" + "".join([" {}:\n".format(name) for name in volume_names])
539
+
540
+ footer = """
541
+ networks:
542
+ {network_traefik_public}:
543
+ external: true
544
+ {network_backend}:
545
+ external: true
546
+ {network_database}:
547
+ external: true
548
+ {network_infisical}:
549
+ external: true
550
+ {volumes_section}""".format(
551
+ network_traefik_public=PlatformDockerConstants.NETWORK_TRAEFIK_PUBLIC,
552
+ network_backend=PlatformDockerConstants.NETWORK_BACKEND,
553
+ network_database=PlatformDockerConstants.NETWORK_DATABASE,
554
+ network_infisical=PlatformDockerConstants.NETWORK_INFISICAL,
555
+ volumes_section=volumes_section,
556
+ )
557
+
558
+ content = header + "\n".join(resource_entries) + footer
559
+
560
+ if write_fn:
561
+ compose_path = resource_path + '/' + OUTPUT.AUTOGENERATED_FOLDER + '/docker-compose.app.autogenerated.yml'
562
+ write_fn(compose_path, content)
563
+
564
+ return content
565
+
566
+
567
+ def generate_migrator_compose(resource_path, resource_name, dockerfile_path=None, write_fn=None):
568
+ """Generate docker-compose for database migrators.
569
+
570
+ Args:
571
+ resource_path: Path to the resource directory
572
+ resource_name: Name of the resource
573
+ dockerfile_path: Optional path to Dockerfile
574
+ write_fn: Optional write function for file output
575
+
576
+ Returns:
577
+ str: Generated docker-compose YAML content
578
+ """
579
+ migrator_name = resource_name + '-db-migrator'
580
+ image_name = PlatformDockerConstants.migrator_image_name(resource_name)
581
+
582
+ # Use PROJECT_NAME from PlatformDockerConstants for portable database naming
583
+ db_name = PlatformDockerConstants.PROJECT_NAME + '_' + resource_name
584
+ default_db_url = PlatformDockerConstants.get_database_url_for_env(db_name)
585
+
586
+ dockerfile_ref = dockerfile_path if dockerfile_path else resource_path + "/" + OUTPUT.AUTOGENERATED_FOLDER + "/Dockerfile.migrator.autogenerated"
587
+ infisical_env = get_infisical_environment_vars(as_array=False)
588
+
589
+ content = """###############################################################################
590
+ # 🛑 CRITICAL: SYSTEM-GENERATED FILE - DO NOT MODIFY DIRECTLY
591
+ # Generation Source: .tilt/topologies/platform/docker/index.star
592
+ ###############################################################################
593
+ # 🔐 Infisical Zero-Code Integration Enabled
594
+ # 🗃️ Database Virtualization: Connects to shared PostgreSQL instance
595
+ services:
596
+ {migrator_name}:
597
+ image: {image_name}
598
+ build:
599
+ context: ../../../.
600
+ dockerfile: {dockerfile_ref}
601
+ target: migrator
602
+ environment:
603
+ {infisical_env}
604
+ RESOURCE_NAME: {resource_name}
605
+ TILT_DATABASE_URL: "{default_db_url}"
606
+ DATABASE_URL: ${{DATABASE_URL:-{default_db_url}}}
607
+ networks:
608
+ - {network_database}
609
+ - {network_backend}
610
+ - {network_infisical}
611
+ restart: "no"
612
+
613
+ networks:
614
+ {network_database}:
615
+ external: true
616
+ {network_backend}:
617
+ external: true
618
+ {network_infisical}:
619
+ external: true
620
+ """.format(
621
+ migrator_name=migrator_name,
622
+ image_name=image_name,
623
+ resource_path=resource_path,
624
+ dockerfile_ref=dockerfile_ref,
625
+ resource_name=resource_name,
626
+ db_name=db_name,
627
+ default_db_url=default_db_url,
628
+ infisical_env=infisical_env,
629
+ network_database=PlatformDockerConstants.NETWORK_DATABASE,
630
+ network_backend=PlatformDockerConstants.NETWORK_BACKEND,
631
+ network_infisical=PlatformDockerConstants.NETWORK_INFISICAL,
632
+ )
633
+
634
+ if write_fn:
635
+ write_fn(resource_path + '/' + OUTPUT.AUTOGENERATED_FOLDER + '/docker-compose.migrator.autogenerated.yml', content)
636
+
637
+ return content