@supatype/cli 0.1.0-alpha.10

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 (416) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-test.log +221 -0
  3. package/.turbo/turbo-typecheck.log +4 -0
  4. package/assets/supatype-logo-wordmark.ascii.txt +6 -0
  5. package/bin/dev-entry.ts +2 -0
  6. package/bin/supatype.js +5 -0
  7. package/dist/app/framework.d.ts +44 -0
  8. package/dist/app/framework.d.ts.map +1 -0
  9. package/dist/app/framework.js +200 -0
  10. package/dist/app/framework.js.map +1 -0
  11. package/dist/app/proxy-dev-app.d.ts +13 -0
  12. package/dist/app/proxy-dev-app.d.ts.map +1 -0
  13. package/dist/app/proxy-dev-app.js +54 -0
  14. package/dist/app/proxy-dev-app.js.map +1 -0
  15. package/dist/app-config.d.ts +7 -0
  16. package/dist/app-config.d.ts.map +1 -0
  17. package/dist/app-config.js +113 -0
  18. package/dist/app-config.js.map +1 -0
  19. package/dist/assets/supatype-logo-wordmark.ascii.txt +6 -0
  20. package/dist/augmentation-generator.d.ts +2 -0
  21. package/dist/augmentation-generator.d.ts.map +1 -0
  22. package/dist/augmentation-generator.js +111 -0
  23. package/dist/augmentation-generator.js.map +1 -0
  24. package/dist/binary-cache.d.ts +98 -0
  25. package/dist/binary-cache.d.ts.map +1 -0
  26. package/dist/binary-cache.js +687 -0
  27. package/dist/binary-cache.js.map +1 -0
  28. package/dist/cli.d.ts +2 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +61 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/commands/admin.d.ts +4 -0
  33. package/dist/commands/admin.d.ts.map +1 -0
  34. package/dist/commands/admin.js +271 -0
  35. package/dist/commands/admin.js.map +1 -0
  36. package/dist/commands/app.d.ts +3 -0
  37. package/dist/commands/app.d.ts.map +1 -0
  38. package/dist/commands/app.js +82 -0
  39. package/dist/commands/app.js.map +1 -0
  40. package/dist/commands/cache.d.ts +6 -0
  41. package/dist/commands/cache.d.ts.map +1 -0
  42. package/dist/commands/cache.js +105 -0
  43. package/dist/commands/cache.js.map +1 -0
  44. package/dist/commands/cloud.d.ts +23 -0
  45. package/dist/commands/cloud.d.ts.map +1 -0
  46. package/dist/commands/cloud.js +254 -0
  47. package/dist/commands/cloud.js.map +1 -0
  48. package/dist/commands/db.d.ts +8 -0
  49. package/dist/commands/db.d.ts.map +1 -0
  50. package/dist/commands/db.js +116 -0
  51. package/dist/commands/db.js.map +1 -0
  52. package/dist/commands/deploy-types.d.ts +14 -0
  53. package/dist/commands/deploy-types.d.ts.map +1 -0
  54. package/dist/commands/deploy-types.js +38 -0
  55. package/dist/commands/deploy-types.js.map +1 -0
  56. package/dist/commands/deploy.d.ts +15 -0
  57. package/dist/commands/deploy.d.ts.map +1 -0
  58. package/dist/commands/deploy.js +322 -0
  59. package/dist/commands/deploy.js.map +1 -0
  60. package/dist/commands/dev.d.ts +14 -0
  61. package/dist/commands/dev.d.ts.map +1 -0
  62. package/dist/commands/dev.js +806 -0
  63. package/dist/commands/dev.js.map +1 -0
  64. package/dist/commands/diff.d.ts +3 -0
  65. package/dist/commands/diff.d.ts.map +1 -0
  66. package/dist/commands/diff.js +54 -0
  67. package/dist/commands/diff.js.map +1 -0
  68. package/dist/commands/engine.d.ts +7 -0
  69. package/dist/commands/engine.d.ts.map +1 -0
  70. package/dist/commands/engine.js +27 -0
  71. package/dist/commands/engine.js.map +1 -0
  72. package/dist/commands/functions.d.ts +3 -0
  73. package/dist/commands/functions.d.ts.map +1 -0
  74. package/dist/commands/functions.js +749 -0
  75. package/dist/commands/functions.js.map +1 -0
  76. package/dist/commands/generate.d.ts +3 -0
  77. package/dist/commands/generate.d.ts.map +1 -0
  78. package/dist/commands/generate.js +38 -0
  79. package/dist/commands/generate.js.map +1 -0
  80. package/dist/commands/init.d.ts +7 -0
  81. package/dist/commands/init.d.ts.map +1 -0
  82. package/dist/commands/init.js +228 -0
  83. package/dist/commands/init.js.map +1 -0
  84. package/dist/commands/keys.d.ts +4 -0
  85. package/dist/commands/keys.d.ts.map +1 -0
  86. package/dist/commands/keys.js +57 -0
  87. package/dist/commands/keys.js.map +1 -0
  88. package/dist/commands/logs.d.ts +6 -0
  89. package/dist/commands/logs.d.ts.map +1 -0
  90. package/dist/commands/logs.js +52 -0
  91. package/dist/commands/logs.js.map +1 -0
  92. package/dist/commands/migrate-from-v1.d.ts +5 -0
  93. package/dist/commands/migrate-from-v1.d.ts.map +1 -0
  94. package/dist/commands/migrate-from-v1.js +125 -0
  95. package/dist/commands/migrate-from-v1.js.map +1 -0
  96. package/dist/commands/migrate.d.ts +3 -0
  97. package/dist/commands/migrate.d.ts.map +1 -0
  98. package/dist/commands/migrate.js +75 -0
  99. package/dist/commands/migrate.js.map +1 -0
  100. package/dist/commands/pg.d.ts +8 -0
  101. package/dist/commands/pg.d.ts.map +1 -0
  102. package/dist/commands/pg.js +102 -0
  103. package/dist/commands/pg.js.map +1 -0
  104. package/dist/commands/plugins.d.ts +3 -0
  105. package/dist/commands/plugins.d.ts.map +1 -0
  106. package/dist/commands/plugins.js +431 -0
  107. package/dist/commands/plugins.js.map +1 -0
  108. package/dist/commands/pull.d.ts +3 -0
  109. package/dist/commands/pull.d.ts.map +1 -0
  110. package/dist/commands/pull.js +12 -0
  111. package/dist/commands/pull.js.map +1 -0
  112. package/dist/commands/push.d.ts +3 -0
  113. package/dist/commands/push.d.ts.map +1 -0
  114. package/dist/commands/push.js +179 -0
  115. package/dist/commands/push.js.map +1 -0
  116. package/dist/commands/seed.d.ts +5 -0
  117. package/dist/commands/seed.d.ts.map +1 -0
  118. package/dist/commands/seed.js +55 -0
  119. package/dist/commands/seed.js.map +1 -0
  120. package/dist/commands/self-host.d.ts +9 -0
  121. package/dist/commands/self-host.d.ts.map +1 -0
  122. package/dist/commands/self-host.js +310 -0
  123. package/dist/commands/self-host.js.map +1 -0
  124. package/dist/commands/self-update.d.ts +9 -0
  125. package/dist/commands/self-update.d.ts.map +1 -0
  126. package/dist/commands/self-update.js +33 -0
  127. package/dist/commands/self-update.js.map +1 -0
  128. package/dist/commands/status.d.ts +6 -0
  129. package/dist/commands/status.d.ts.map +1 -0
  130. package/dist/commands/status.js +70 -0
  131. package/dist/commands/status.js.map +1 -0
  132. package/dist/commands/types.d.ts +3 -0
  133. package/dist/commands/types.d.ts.map +1 -0
  134. package/dist/commands/types.js +62 -0
  135. package/dist/commands/types.js.map +1 -0
  136. package/dist/commands/update.d.ts +7 -0
  137. package/dist/commands/update.d.ts.map +1 -0
  138. package/dist/commands/update.js +118 -0
  139. package/dist/commands/update.js.map +1 -0
  140. package/dist/components.d.ts +5 -0
  141. package/dist/components.d.ts.map +1 -0
  142. package/dist/components.js +3 -0
  143. package/dist/components.js.map +1 -0
  144. package/dist/config.d.ts +65 -0
  145. package/dist/config.d.ts.map +1 -0
  146. package/dist/config.js +134 -0
  147. package/dist/config.js.map +1 -0
  148. package/dist/dev-compose.d.ts +19 -0
  149. package/dist/dev-compose.d.ts.map +1 -0
  150. package/dist/dev-compose.js +468 -0
  151. package/dist/dev-compose.js.map +1 -0
  152. package/dist/dev-log-bus.d.ts +30 -0
  153. package/dist/dev-log-bus.d.ts.map +1 -0
  154. package/dist/dev-log-bus.js +87 -0
  155. package/dist/dev-log-bus.js.map +1 -0
  156. package/dist/dev-log-filter.d.ts +10 -0
  157. package/dist/dev-log-filter.d.ts.map +1 -0
  158. package/dist/dev-log-filter.js +36 -0
  159. package/dist/dev-log-filter.js.map +1 -0
  160. package/dist/dev-logo.d.ts +12 -0
  161. package/dist/dev-logo.d.ts.map +1 -0
  162. package/dist/dev-logo.js +57 -0
  163. package/dist/dev-logo.js.map +1 -0
  164. package/dist/dev-session.d.ts +26 -0
  165. package/dist/dev-session.d.ts.map +1 -0
  166. package/dist/dev-session.js +106 -0
  167. package/dist/dev-session.js.map +1 -0
  168. package/dist/dev-shutdown.d.ts +9 -0
  169. package/dist/dev-shutdown.d.ts.map +1 -0
  170. package/dist/dev-shutdown.js +50 -0
  171. package/dist/dev-shutdown.js.map +1 -0
  172. package/dist/dev-task-colors.d.ts +14 -0
  173. package/dist/dev-task-colors.d.ts.map +1 -0
  174. package/dist/dev-task-colors.js +44 -0
  175. package/dist/dev-task-colors.js.map +1 -0
  176. package/dist/dev-tui.d.ts +24 -0
  177. package/dist/dev-tui.d.ts.map +1 -0
  178. package/dist/dev-tui.js +188 -0
  179. package/dist/dev-tui.js.map +1 -0
  180. package/dist/diff-output.d.ts +4 -0
  181. package/dist/diff-output.d.ts.map +1 -0
  182. package/dist/diff-output.js +12 -0
  183. package/dist/diff-output.js.map +1 -0
  184. package/dist/docker-postgres.d.ts +57 -0
  185. package/dist/docker-postgres.d.ts.map +1 -0
  186. package/dist/docker-postgres.js +208 -0
  187. package/dist/docker-postgres.js.map +1 -0
  188. package/dist/engine-client.d.ts +69 -0
  189. package/dist/engine-client.d.ts.map +1 -0
  190. package/dist/engine-client.js +157 -0
  191. package/dist/engine-client.js.map +1 -0
  192. package/dist/engine-push-output.d.ts +16 -0
  193. package/dist/engine-push-output.d.ts.map +1 -0
  194. package/dist/engine-push-output.js +61 -0
  195. package/dist/engine-push-output.js.map +1 -0
  196. package/dist/ensure-binary.d.ts +7 -0
  197. package/dist/ensure-binary.d.ts.map +1 -0
  198. package/dist/ensure-binary.js +17 -0
  199. package/dist/ensure-binary.js.map +1 -0
  200. package/dist/functions-router-gen.d.ts +14 -0
  201. package/dist/functions-router-gen.d.ts.map +1 -0
  202. package/dist/functions-router-gen.js +199 -0
  203. package/dist/functions-router-gen.js.map +1 -0
  204. package/dist/index.d.ts +11 -0
  205. package/dist/index.d.ts.map +1 -0
  206. package/dist/index.js +9 -0
  207. package/dist/index.js.map +1 -0
  208. package/dist/jwt.d.ts +3 -0
  209. package/dist/jwt.d.ts.map +1 -0
  210. package/dist/jwt.js +13 -0
  211. package/dist/jwt.js.map +1 -0
  212. package/dist/kong-config.d.ts +25 -0
  213. package/dist/kong-config.d.ts.map +1 -0
  214. package/dist/kong-config.js +71 -0
  215. package/dist/kong-config.js.map +1 -0
  216. package/dist/local-gateway.d.ts +7 -0
  217. package/dist/local-gateway.d.ts.map +1 -0
  218. package/dist/local-gateway.js +9 -0
  219. package/dist/local-gateway.js.map +1 -0
  220. package/dist/local-storage.d.ts +8 -0
  221. package/dist/local-storage.d.ts.map +1 -0
  222. package/dist/local-storage.js +14 -0
  223. package/dist/local-storage.js.map +1 -0
  224. package/dist/pgbouncer-userlist.d.ts +5 -0
  225. package/dist/pgbouncer-userlist.d.ts.map +1 -0
  226. package/dist/pgbouncer-userlist.js +14 -0
  227. package/dist/pgbouncer-userlist.js.map +1 -0
  228. package/dist/postgres-ctl.d.ts +44 -0
  229. package/dist/postgres-ctl.d.ts.map +1 -0
  230. package/dist/postgres-ctl.js +137 -0
  231. package/dist/postgres-ctl.js.map +1 -0
  232. package/dist/process-manager.d.ts +49 -0
  233. package/dist/process-manager.d.ts.map +1 -0
  234. package/dist/process-manager.js +177 -0
  235. package/dist/process-manager.js.map +1 -0
  236. package/dist/project-config.d.ts +238 -0
  237. package/dist/project-config.d.ts.map +1 -0
  238. package/dist/project-config.js +159 -0
  239. package/dist/project-config.js.map +1 -0
  240. package/dist/pull-utils.d.ts +31 -0
  241. package/dist/pull-utils.d.ts.map +1 -0
  242. package/dist/pull-utils.js +77 -0
  243. package/dist/pull-utils.js.map +1 -0
  244. package/dist/release-pins.d.ts +7 -0
  245. package/dist/release-pins.d.ts.map +1 -0
  246. package/dist/release-pins.js +27 -0
  247. package/dist/release-pins.js.map +1 -0
  248. package/dist/release-public-key.d.ts +8 -0
  249. package/dist/release-public-key.d.ts.map +1 -0
  250. package/dist/release-public-key.js +13 -0
  251. package/dist/release-public-key.js.map +1 -0
  252. package/dist/restore-system-relation-targets.d.ts +3 -0
  253. package/dist/restore-system-relation-targets.d.ts.map +1 -0
  254. package/dist/restore-system-relation-targets.js +45 -0
  255. package/dist/restore-system-relation-targets.js.map +1 -0
  256. package/dist/runtime-routes.d.ts +34 -0
  257. package/dist/runtime-routes.d.ts.map +1 -0
  258. package/dist/runtime-routes.js +252 -0
  259. package/dist/runtime-routes.js.map +1 -0
  260. package/dist/schema-ast-v2.d.ts +127 -0
  261. package/dist/schema-ast-v2.d.ts.map +1 -0
  262. package/dist/schema-ast-v2.js +226 -0
  263. package/dist/schema-ast-v2.js.map +1 -0
  264. package/dist/scripts/postinstall.d.ts +11 -0
  265. package/dist/scripts/postinstall.d.ts.map +1 -0
  266. package/dist/scripts/postinstall.js +47 -0
  267. package/dist/scripts/postinstall.js.map +1 -0
  268. package/dist/seed.d.ts +8 -0
  269. package/dist/seed.d.ts.map +1 -0
  270. package/dist/seed.js +32 -0
  271. package/dist/seed.js.map +1 -0
  272. package/dist/self-host-compose.d.ts +43 -0
  273. package/dist/self-host-compose.d.ts.map +1 -0
  274. package/dist/self-host-compose.js +400 -0
  275. package/dist/self-host-compose.js.map +1 -0
  276. package/dist/storage-provision.d.ts +24 -0
  277. package/dist/storage-provision.d.ts.map +1 -0
  278. package/dist/storage-provision.js +44 -0
  279. package/dist/storage-provision.js.map +1 -0
  280. package/dist/studio-admin-roles.d.ts +7 -0
  281. package/dist/studio-admin-roles.d.ts.map +1 -0
  282. package/dist/studio-admin-roles.js +14 -0
  283. package/dist/studio-admin-roles.js.map +1 -0
  284. package/dist/studio-dev-server.d.ts +22 -0
  285. package/dist/studio-dev-server.d.ts.map +1 -0
  286. package/dist/studio-dev-server.js +28 -0
  287. package/dist/studio-dev-server.js.map +1 -0
  288. package/dist/supatype-eval-1781522769253.d.mts +2 -0
  289. package/dist/supatype-eval-1781522769253.d.mts.map +1 -0
  290. package/dist/supatype-eval-1781522769253.mjs +3 -0
  291. package/dist/supatype-eval-1781522769253.mjs.map +1 -0
  292. package/dist/systemd.d.ts +26 -0
  293. package/dist/systemd.d.ts.map +1 -0
  294. package/dist/systemd.js +102 -0
  295. package/dist/systemd.js.map +1 -0
  296. package/dist/tsx-runner.d.ts +18 -0
  297. package/dist/tsx-runner.d.ts.map +1 -0
  298. package/dist/tsx-runner.js +69 -0
  299. package/dist/tsx-runner.js.map +1 -0
  300. package/dist/type-extractor.d.ts +4 -0
  301. package/dist/type-extractor.d.ts.map +1 -0
  302. package/dist/type-extractor.js +1213 -0
  303. package/dist/type-extractor.js.map +1 -0
  304. package/dist/type-resolver.d.ts +33 -0
  305. package/dist/type-resolver.d.ts.map +1 -0
  306. package/dist/type-resolver.js +338 -0
  307. package/dist/type-resolver.js.map +1 -0
  308. package/package.json +41 -0
  309. package/releases/deno/VERSION +1 -0
  310. package/scripts/mirror-deno-release.sh +76 -0
  311. package/src/TYPE-RESOLUTION.md +294 -0
  312. package/src/app/framework.ts +249 -0
  313. package/src/app/proxy-dev-app.ts +68 -0
  314. package/src/app-config.ts +128 -0
  315. package/src/augmentation-generator.ts +126 -0
  316. package/src/binary-cache.ts +845 -0
  317. package/src/cli.ts +63 -0
  318. package/src/commands/admin.ts +372 -0
  319. package/src/commands/app.ts +97 -0
  320. package/src/commands/cache.ts +117 -0
  321. package/src/commands/cloud.ts +325 -0
  322. package/src/commands/db.ts +136 -0
  323. package/src/commands/deploy-types.ts +49 -0
  324. package/src/commands/deploy.ts +400 -0
  325. package/src/commands/dev.ts +1009 -0
  326. package/src/commands/diff.ts +63 -0
  327. package/src/commands/engine.ts +30 -0
  328. package/src/commands/functions.ts +901 -0
  329. package/src/commands/generate.ts +44 -0
  330. package/src/commands/init.ts +253 -0
  331. package/src/commands/keys.ts +66 -0
  332. package/src/commands/logs.ts +58 -0
  333. package/src/commands/migrate-from-v1.ts +131 -0
  334. package/src/commands/migrate.ts +87 -0
  335. package/src/commands/pg.ts +133 -0
  336. package/src/commands/plugins.ts +508 -0
  337. package/src/commands/pull.ts +17 -0
  338. package/src/commands/push.ts +226 -0
  339. package/src/commands/seed.ts +68 -0
  340. package/src/commands/self-host.ts +364 -0
  341. package/src/commands/self-update.ts +45 -0
  342. package/src/commands/status.ts +84 -0
  343. package/src/commands/types.ts +76 -0
  344. package/src/commands/update.ts +136 -0
  345. package/src/components.ts +6 -0
  346. package/src/config.ts +223 -0
  347. package/src/dev-compose.ts +583 -0
  348. package/src/dev-log-bus.ts +101 -0
  349. package/src/dev-log-filter.ts +32 -0
  350. package/src/dev-logo.ts +62 -0
  351. package/src/dev-session.ts +130 -0
  352. package/src/dev-shutdown.ts +54 -0
  353. package/src/dev-task-colors.ts +47 -0
  354. package/src/dev-tui.ts +232 -0
  355. package/src/diff-output.ts +12 -0
  356. package/src/docker-postgres.ts +295 -0
  357. package/src/engine-client.ts +236 -0
  358. package/src/engine-push-output.ts +71 -0
  359. package/src/ensure-binary.ts +28 -0
  360. package/src/functions-router-gen.ts +224 -0
  361. package/src/index.ts +11 -0
  362. package/src/jwt.ts +14 -0
  363. package/src/kong-config.ts +93 -0
  364. package/src/local-gateway.ts +9 -0
  365. package/src/local-storage.ts +14 -0
  366. package/src/pgbouncer-userlist.ts +15 -0
  367. package/src/postgres-ctl.ts +171 -0
  368. package/src/process-manager.ts +220 -0
  369. package/src/project-config.ts +388 -0
  370. package/src/pull-utils.ts +81 -0
  371. package/src/release-pins.ts +31 -0
  372. package/src/release-public-key.ts +12 -0
  373. package/src/restore-system-relation-targets.ts +45 -0
  374. package/src/runtime-routes.ts +291 -0
  375. package/src/schema-ast-v2.ts +324 -0
  376. package/src/scripts/postinstall.ts +51 -0
  377. package/src/seed.ts +43 -0
  378. package/src/self-host-compose.ts +452 -0
  379. package/src/storage-provision.ts +58 -0
  380. package/src/studio-admin-roles.ts +16 -0
  381. package/src/studio-dev-server.ts +53 -0
  382. package/src/supatype-eval-1781522769253.mts +1 -0
  383. package/src/systemd.ts +137 -0
  384. package/src/tsx-runner.ts +89 -0
  385. package/src/type-extractor.ts +1479 -0
  386. package/src/type-resolver.ts +457 -0
  387. package/tests/app-command.test.ts +54 -0
  388. package/tests/augmentation-generator.test.ts +59 -0
  389. package/tests/binary-cache-cloud-overrides.test.ts +123 -0
  390. package/tests/cached-artifact-format.test.ts +84 -0
  391. package/tests/cli-help.test.ts +133 -0
  392. package/tests/config.test.ts +252 -0
  393. package/tests/dev-ui.test.ts +139 -0
  394. package/tests/docker-postgres.test.ts +39 -0
  395. package/tests/engine-distribution.test.ts +418 -0
  396. package/tests/engine-push-output.test.ts +67 -0
  397. package/tests/ensure-binary.test.ts +59 -0
  398. package/tests/init.test.ts +127 -0
  399. package/tests/keys.test.ts +160 -0
  400. package/tests/migrate-from-v1.test.ts +29 -0
  401. package/tests/normalize-admin-config.test.ts +48 -0
  402. package/tests/pg-spawn-env.test.ts +18 -0
  403. package/tests/postgres-archive-tag.test.ts +9 -0
  404. package/tests/proxy-dev-app.test.ts +33 -0
  405. package/tests/pull-utils.test.ts +150 -0
  406. package/tests/release-pins.test.ts +28 -0
  407. package/tests/runtime-contract.test.ts +370 -0
  408. package/tests/seed-discover.test.ts +31 -0
  409. package/tests/studio-admin-roles.test.ts +27 -0
  410. package/tests/tsconfig.json +9 -0
  411. package/tests/tsx-runner.test.ts +66 -0
  412. package/tests/type-extractor.test.ts +985 -0
  413. package/tests/type-resolver.test.ts +59 -0
  414. package/tsconfig.json +10 -0
  415. package/tsconfig.tsbuildinfo +1 -0
  416. package/vitest.config.ts +12 -0
@@ -0,0 +1,295 @@
1
+ /**
2
+ * docker-postgres — manage a supatype/postgres Docker container for local dev.
3
+ *
4
+ * Used by `supatype dev` when database.provider = "docker".
5
+ * The container is named supatype-{projectName} and persists data in a
6
+ * named Docker volume (supatype-{projectName}-data) across restarts.
7
+ */
8
+
9
+ import { spawnSync } from "node:child_process"
10
+
11
+ export interface DockerPgOptions {
12
+ /** Docker image to run. Defaults to supatype/postgres:latest. */
13
+ image: string
14
+ /** Project name — used to derive the container and volume names. */
15
+ projectName: string
16
+ /** Host port to bind to container's 5432. */
17
+ port: number
18
+ /** Superuser password (dev only). Defaults to "postgres". */
19
+ password?: string
20
+ }
21
+
22
+ const PG_USER = "supatype_admin"
23
+ /** Must match `dockerPgStart` default `POSTGRES_PASSWORD`. */
24
+ const DEFAULT_DEV_PASSWORD = "postgres"
25
+
26
+ function dockerPgPsql(
27
+ name: string,
28
+ db: string,
29
+ sql: string,
30
+ password = DEFAULT_DEV_PASSWORD,
31
+ ) {
32
+ return spawnSync(
33
+ "docker",
34
+ [
35
+ "exec",
36
+ "-e", `PGPASSWORD=${password}`,
37
+ name,
38
+ "psql", "--no-password", "-U", PG_USER, "-d", db, "-tAc", sql,
39
+ ],
40
+ { encoding: "utf8", stdio: "pipe" },
41
+ )
42
+ }
43
+
44
+ /** Derived container name for a project. */
45
+ export function containerName(projectName: string): string {
46
+ return `supatype-${projectName}`
47
+ }
48
+
49
+ /**
50
+ * Start the supatype/postgres Docker container.
51
+ * Removes any stopped container with the same name before starting.
52
+ * Throws if `docker run` exits non-zero.
53
+ */
54
+ export function dockerPgStart(opts: DockerPgOptions): void {
55
+ const { image, projectName, port, password = "postgres" } = opts
56
+ const name = containerName(projectName)
57
+ const volume = `${name}-data`
58
+
59
+ // Remove any stopped container from a previous session.
60
+ spawnSync("docker", ["rm", "-f", name], { encoding: "utf8" })
61
+
62
+ const result = spawnSync(
63
+ "docker",
64
+ [
65
+ "run", "-d",
66
+ "--name", name,
67
+ "-e", `POSTGRES_USER=${PG_USER}`,
68
+ "-e", `POSTGRES_PASSWORD=${password}`,
69
+ "-e", `POSTGRES_DB=${projectName}`,
70
+ "-p", `${port}:5432`,
71
+ "-v", `${volume}:/var/lib/postgresql/data`,
72
+ image,
73
+ ],
74
+ { encoding: "utf8", stdio: "pipe" },
75
+ )
76
+
77
+ if (result.status !== 0) {
78
+ const detail = (result.stderr ?? result.stdout ?? "").trim()
79
+ throw new Error(
80
+ `Failed to start Docker container "${name}".\n` +
81
+ (detail ? ` docker: ${detail}\n` : "") +
82
+ ` Is Docker running? docker info`,
83
+ )
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Stop the container (fast — does not remove it or the data volume).
89
+ * Safe to call even if the container is not running.
90
+ */
91
+ export function dockerPgStop(projectName: string): void {
92
+ spawnSync("docker", ["stop", containerName(projectName)], { encoding: "utf8" })
93
+ }
94
+
95
+ function dockerPgLogsTail(name: string, tail = 120): string {
96
+ const logs = spawnSync(
97
+ "docker",
98
+ ["logs", "--tail", String(tail), name],
99
+ { encoding: "utf8" },
100
+ )
101
+ return `${logs.stdout ?? ""}${logs.stderr ?? ""}`
102
+ }
103
+
104
+ function dockerPgHealthStatus(name: string): string | undefined {
105
+ const inspect = spawnSync(
106
+ "docker",
107
+ ["inspect", "-f", "{{if .State.Health}}{{.State.Health.Status}}{{end}}", name],
108
+ { encoding: "utf8", stdio: "pipe" },
109
+ )
110
+ if (inspect.status !== 0) return undefined
111
+ const status = inspect.stdout?.trim()
112
+ return status === "" ? undefined : status
113
+ }
114
+
115
+ /** True when the final post-init Postgres process is accepting connections. */
116
+ export function dockerPgPostInitServing(logs: string): boolean {
117
+ const ready = "database system is ready to accept connections"
118
+ const lastReady = logs.lastIndexOf(ready)
119
+ if (lastReady === -1) return false
120
+
121
+ const initDone = logs.lastIndexOf("PostgreSQL init process complete")
122
+ if (initDone === -1) {
123
+ // Reused data volume — this run did not re-run entrypoint init.
124
+ return true
125
+ }
126
+ return initDone < lastReady
127
+ }
128
+
129
+ function migrateStillRunning(logs: string): boolean {
130
+ return /99-supatype-migrate\.sh: running .+\.sql/.test(logs)
131
+ }
132
+
133
+ function psqlTruthy(stdout: string | undefined): boolean {
134
+ const v = (stdout ?? "").replace(/\r/g, "").trim().toLowerCase()
135
+ return v === "t" || v === "true"
136
+ }
137
+
138
+ const ANON_ROLE_SQL = "SELECT EXISTS (SELECT FROM pg_roles WHERE rolname = 'anon')"
139
+
140
+ function dockerPgHasAnonRole(
141
+ name: string,
142
+ projectName: string,
143
+ password = DEFAULT_DEV_PASSWORD,
144
+ ): boolean {
145
+ for (const db of [projectName, "postgres"]) {
146
+ const result = dockerPgPsql(name, db, ANON_ROLE_SQL, password)
147
+ if (result.status === 0 && psqlTruthy(result.stdout)) return true
148
+ }
149
+ return false
150
+ }
151
+
152
+ function dockerPgExecReady(name: string): boolean {
153
+ const ready = spawnSync(
154
+ "docker",
155
+ ["exec", name, "pg_isready", "-U", PG_USER, "-q"],
156
+ { encoding: "utf8", stdio: "pipe" },
157
+ )
158
+ return ready.status === 0
159
+ }
160
+
161
+ /**
162
+ * Poll until Postgres accepts connections and the image entrypoint init has
163
+ * finished (anon/authenticated/service_role come from supatype-postgres
164
+ * migrations/db/init-scripts/00000000000000-initial-schema.sql via migrate.sh).
165
+ */
166
+ export async function dockerPgWaitReady(
167
+ projectName: string,
168
+ timeoutMs = 180_000,
169
+ password = DEFAULT_DEV_PASSWORD,
170
+ ): Promise<void> {
171
+ const name = containerName(projectName)
172
+ const deadline = Date.now() + timeoutMs
173
+ let servingWithoutAnonMs = 0
174
+ let lastPsqlDetail = ""
175
+
176
+ while (Date.now() < deadline) {
177
+ const health = dockerPgHealthStatus(name)
178
+ const logs = dockerPgLogsTail(name)
179
+ const serving =
180
+ health === "healthy" ||
181
+ dockerPgPostInitServing(logs) ||
182
+ dockerPgExecReady(name)
183
+
184
+ if (serving && !migrateStillRunning(logs)) {
185
+ if (dockerPgHasAnonRole(name, projectName, password)) return
186
+
187
+ const probe = dockerPgPsql(name, projectName, ANON_ROLE_SQL, password)
188
+ lastPsqlDetail = [
189
+ probe.status !== 0 ? `psql exit ${probe.status}` : "",
190
+ probe.stderr?.trim(),
191
+ probe.stdout?.trim() ? `stdout=${probe.stdout.trim()}` : "",
192
+ ]
193
+ .filter(Boolean)
194
+ .join("; ")
195
+
196
+ const reusedVolume =
197
+ logs.includes("database system is ready to accept connections") &&
198
+ !logs.includes("PostgreSQL init process complete")
199
+
200
+ if (reusedVolume) {
201
+ servingWithoutAnonMs += 500
202
+ if (servingWithoutAnonMs >= 5_000) throw staleVolumeError(name)
203
+ } else {
204
+ servingWithoutAnonMs = 0
205
+ }
206
+ } else {
207
+ servingWithoutAnonMs = 0
208
+ }
209
+
210
+ await sleep(500)
211
+ }
212
+
213
+ const logs = dockerPgLogsTail(name, 80)
214
+ throw new Error(
215
+ `Docker Postgres "${name}" did not finish image init within ${timeoutMs}ms.\n` +
216
+ " API roles (anon, authenticated, service_role) are created by the supatype/postgres\n" +
217
+ " entrypoint (99-supatype-migrate.sh), not by the CLI.\n" +
218
+ " If you upgraded the image, remove the stale volume:\n" +
219
+ ` docker volume rm ${name}-data\n` +
220
+ (lastPsqlDetail ? ` Last anon probe: ${lastPsqlDetail}\n` : "") +
221
+ (logs ? ` logs (tail):\n${indent(logs)}\n` : ""),
222
+ )
223
+ }
224
+
225
+ function staleVolumeError(name: string): Error {
226
+ return new Error(
227
+ `Docker Postgres "${name}" is up but API roles are missing.\n` +
228
+ " The data volume was initialised without supatype/postgres migrations (stale or wrong image).\n" +
229
+ " Remove the volume so first-boot 99-supatype-migrate.sh runs again:\n" +
230
+ ` docker volume rm ${name}-data`,
231
+ )
232
+ }
233
+
234
+ /** Connection string for the Docker container (local dev credentials). */
235
+ export function dockerDbUrl(projectName: string, port: number, password = DEFAULT_DEV_PASSWORD): string {
236
+ // Host → published port. sqlx/libpq "prefer" can mis-handle SSL on some hosts (e.g. Docker Desktop on Windows).
237
+ return `postgres://${PG_USER}:${password}@127.0.0.1:${port}/${projectName}?sslmode=disable`
238
+ }
239
+
240
+ /**
241
+ * DB URL for processes sharing the Postgres container network namespace
242
+ * (supatype-server migrate in a one-shot container). Uses loopback inside the
243
+ * container where pg_hba grants trust — avoids host-published-port SCRAM/SSL issues.
244
+ */
245
+ export function dockerPgLoopbackDbUrl(projectName: string, password = DEFAULT_DEV_PASSWORD): string {
246
+ return `postgres://${PG_USER}:${password}@127.0.0.1:5432/${projectName}?sslmode=disable`
247
+ }
248
+
249
+ /**
250
+ * Published Hub tag for local dev when CDN server version is not on Docker Hub yet.
251
+ * Keep in sync with tests/integration/scripts/compose-smoke.sh.
252
+ */
253
+ export const DEFAULT_SERVER_DOCKER_IMAGE = "supatype/server:latest"
254
+
255
+ /**
256
+ * Run `supatype-server migrate` on the Postgres container network (loopback trust).
257
+ * Used on Windows + database.provider docker — host-published :5432 breaks libpq TLS there.
258
+ */
259
+ export function runGotrueMigrationsViaDocker(
260
+ pgContainerName: string,
261
+ serverImage: string,
262
+ migrateEnv: Record<string, string>,
263
+ ): void {
264
+ const envArgs = Object.entries(migrateEnv).flatMap(([k, v]) => ["-e", `${k}=${v}`])
265
+ const result = spawnSync(
266
+ "docker",
267
+ [
268
+ "run", "--rm",
269
+ "--network", `container:${pgContainerName}`,
270
+ ...envArgs,
271
+ serverImage,
272
+ "migrate",
273
+ ],
274
+ { encoding: "utf8", stdio: "pipe" },
275
+ )
276
+ if (result.status !== 0) {
277
+ const detail = (result.stderr ?? result.stdout ?? "").trim()
278
+ throw new Error(
279
+ `GoTrue migrations failed in Docker (exit ${result.status ?? "unknown"})` +
280
+ (detail ? `:\n${detail}` : ""),
281
+ )
282
+ }
283
+ }
284
+
285
+ function sleep(ms: number): Promise<void> {
286
+ return new Promise((resolve) => setTimeout(resolve, ms))
287
+ }
288
+
289
+ function indent(s: string): string {
290
+ return s
291
+ .trimEnd()
292
+ .split("\n")
293
+ .map((l) => ` ${l}`)
294
+ .join("\n")
295
+ }
@@ -0,0 +1,236 @@
1
+ /**
2
+ * engine-client.ts — subprocess-based engine invocation.
3
+ *
4
+ * Replaces the former HTTP-based engine client (Docker container API).
5
+ * All callers use the same interface; only the transport changed.
6
+ *
7
+ * The engine binary reads a request JSON file passed via --request-file and
8
+ * writes a response JSON to stdout.
9
+ */
10
+
11
+ import { spawnSync } from "node:child_process"
12
+ import { mkdirSync, writeFileSync, unlinkSync, existsSync, readdirSync } from "node:fs"
13
+ import { tmpdir, homedir } from "node:os"
14
+ import { join } from "node:path"
15
+ import { loadConfig } from "./config.js"
16
+ import { resolveBinary, currentPlatform, cachePath } from "./binary-cache.js"
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Types (kept for backward compatibility with existing callers)
20
+ // ---------------------------------------------------------------------------
21
+
22
+ export interface Operation {
23
+ kind: "create_table" | "alter_table" | "drop_table" | "create_index" | "drop_index" |
24
+ "create_policy" | "drop_policy" | "add_column" | "drop_column" | "alter_column" |
25
+ "recreate_column"
26
+ type?: string
27
+ description?: string
28
+ risk?: "safe" | "warn" | "danger" | "cautious" | "destructive"
29
+ warning?: string
30
+ sql?: string
31
+ }
32
+
33
+ export interface DiffResult {
34
+ operations: Operation[]
35
+ warnings?: string[]
36
+ summary?: string
37
+ }
38
+
39
+ export interface IntrospectResult {
40
+ models: Array<{
41
+ name: string
42
+ table: string
43
+ columns: Array<{
44
+ name: string
45
+ type: string
46
+ nullable: boolean
47
+ default?: string
48
+ primaryKey?: boolean
49
+ unique?: boolean
50
+ references?: { table: string; column: string }
51
+ }>
52
+ }>
53
+ }
54
+
55
+ export interface EngineResult<T = unknown> {
56
+ ok: boolean
57
+ data: T
58
+ message?: string
59
+ error?: string
60
+ }
61
+
62
+ export class EngineError extends Error {
63
+ constructor(
64
+ message: string,
65
+ public readonly endpoint: string,
66
+ public readonly exitCode: number | null,
67
+ ) {
68
+ super(message)
69
+ this.name = "EngineError"
70
+ }
71
+ }
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // Engine binary resolution
75
+ // ---------------------------------------------------------------------------
76
+
77
+ let _engineBin: string | null = null
78
+
79
+ async function getEngineBin(): Promise<string> {
80
+ if (_engineBin) return _engineBin
81
+
82
+ const cwd = process.cwd()
83
+
84
+ try {
85
+ const config = loadConfig(cwd)
86
+ _engineBin = await resolveBinary("engine", config)
87
+ return _engineBin
88
+ } catch {
89
+ // No valid project config — fall through to default cache path.
90
+ }
91
+
92
+ // No config found — scan the cache for any available engine binary.
93
+ const platform = currentPlatform()
94
+ const engineCacheDir = join(homedir(), ".supatype", "cache", "engine")
95
+ try {
96
+ const cachedVersions = readdirSync(engineCacheDir).sort()
97
+ for (const version of cachedVersions.reverse()) {
98
+ const bin = join(cachePath("engine", version), `supatype-engine-${platform.os}-${platform.arch}`)
99
+ if (existsSync(bin)) {
100
+ _engineBin = bin
101
+ return _engineBin
102
+ }
103
+ }
104
+ } catch { /* cache dir doesn't exist */ }
105
+
106
+ throw new Error(
107
+ "Engine binary not found. Run: supatype update",
108
+ )
109
+ }
110
+
111
+ // ---------------------------------------------------------------------------
112
+ // Public API
113
+ // ---------------------------------------------------------------------------
114
+
115
+ /** Verify the engine binary is accessible. Throws if not found. */
116
+ export async function ensureEngine(): Promise<void> {
117
+ await getEngineBin()
118
+ }
119
+
120
+ /** Check if the engine can be invoked. Returns true/false. */
121
+ export async function engineHealth(): Promise<boolean> {
122
+ try {
123
+ const bin = await getEngineBin()
124
+ const result = spawnSync(bin, ["--version"], { encoding: "utf8" })
125
+ return result.status === 0
126
+ } catch {
127
+ return false
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Invoke the engine and return a typed result.
133
+ *
134
+ * The endpoint maps to a subcommand:
135
+ * /diff → engine diff
136
+ * /push → engine push
137
+ * /generate → engine generate
138
+ * /migrations → engine migrations
139
+ * /introspect → engine introspect
140
+ * /validate → engine validate
141
+ * /admin → engine admin (admin-config JSON on stdout)
142
+ */
143
+ export async function engineRequest<T = unknown>(
144
+ endpoint: string,
145
+ body: Record<string, unknown>,
146
+ ): Promise<T> {
147
+ const bin = await getEngineBin()
148
+
149
+ // Write request to a temp file.
150
+ // For CLI-mode endpoints the engine reads the input file as a raw SchemaAst,
151
+ // so we extract the `ast` field when present, otherwise write the full body.
152
+ const tmpDir = join(tmpdir(), "supatype-engine")
153
+ mkdirSync(tmpDir, { recursive: true })
154
+ const reqFile = join(tmpDir, `req-${Date.now()}.json`)
155
+ const inputPayload = body["ast"] !== undefined ? body["ast"] : body
156
+ writeFileSync(reqFile, JSON.stringify(inputPayload))
157
+
158
+ const args = endpointToArgs(endpoint, body, reqFile)
159
+
160
+ const result = spawnSync(bin, args, {
161
+ encoding: "utf8",
162
+ cwd: process.cwd(),
163
+ })
164
+
165
+ // Clean up temp file.
166
+ try { unlinkSync(reqFile) } catch { /* ignore */ }
167
+
168
+ if (result.status !== 0) {
169
+ const stderr = result.stderr?.trim() || "(no output)"
170
+ throw new EngineError(
171
+ `Engine ${endpoint} failed (exit ${result.status}): ${stderr}`,
172
+ endpoint,
173
+ result.status,
174
+ )
175
+ }
176
+
177
+ if (!result.stdout?.trim()) {
178
+ // Some subcommands print nothing on success.
179
+ return {} as T
180
+ }
181
+
182
+ try {
183
+ return JSON.parse(result.stdout) as T
184
+ } catch {
185
+ // Non-JSON stdout — return as message.
186
+ return { message: result.stdout.trim() } as T
187
+ }
188
+ }
189
+
190
+ // ---------------------------------------------------------------------------
191
+ // Endpoint → CLI args mapping
192
+ // ---------------------------------------------------------------------------
193
+
194
+ function endpointToArgs(
195
+ endpoint: string,
196
+ body: Record<string, unknown>,
197
+ reqFile: string,
198
+ ): string[] {
199
+ const dbUrl = (body["database_url"] as string | undefined) ?? ""
200
+ const schema = (body["schema"] as string | undefined) ?? "public"
201
+ const force = body["force"] ? ["--force"] : []
202
+ const nonInteractive =
203
+ body["non_interactive"] === true || body["force"] === true ? ["--non-interactive"] : []
204
+
205
+ switch (endpoint) {
206
+ case "/diff":
207
+ return ["diff", "--input", reqFile, "--database-url", dbUrl, "--schema", schema]
208
+
209
+ case "/push":
210
+ return ["push", "--input", reqFile, "--database-url", dbUrl, "--schema", schema, ...force, ...nonInteractive]
211
+
212
+ case "/parse":
213
+ return ["parse", "--input", reqFile]
214
+
215
+ case "/generate": {
216
+ const lang = (body["lang"] as string | undefined) ?? "typescript"
217
+ return ["generate", "--input", reqFile, "--lang", lang]
218
+ }
219
+
220
+ case "/introspect":
221
+ return ["introspect", "--database-url", dbUrl, "--schema", schema]
222
+
223
+ case "/validate":
224
+ return ["validate", "--input", reqFile]
225
+
226
+ case "/admin":
227
+ return ["admin", "--input", reqFile]
228
+
229
+ default:
230
+ if (endpoint.startsWith("/migrations")) {
231
+ const action = (body["action"] as string | undefined) ?? "list"
232
+ return ["migrations", action, "--database-url", dbUrl]
233
+ }
234
+ return [endpoint.replace(/^\//, ""), "--input", reqFile]
235
+ }
236
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Parse and format schema-engine push output (compose subprocess or HTTP).
3
+ */
4
+
5
+ export interface EnginePushResult {
6
+ status?: string
7
+ operations?: number
8
+ admin_refreshed?: boolean
9
+ message?: string
10
+ }
11
+
12
+ /** Extract the engine JSON object from mixed docker compose stdout/stderr. */
13
+ export function parseEnginePushOutput(output: string): EnginePushResult | null {
14
+ const trimmed = output.trim()
15
+ if (!trimmed) return null
16
+
17
+ for (const line of trimmed.split(/\r?\n/)) {
18
+ const candidate = line.trim()
19
+ if (!candidate.startsWith("{") || !candidate.endsWith("}")) continue
20
+ try {
21
+ return JSON.parse(candidate) as EnginePushResult
22
+ } catch {
23
+ /* try next line */
24
+ }
25
+ }
26
+
27
+ if (trimmed.startsWith("{")) {
28
+ try {
29
+ return JSON.parse(trimmed) as EnginePushResult
30
+ } catch {
31
+ return null
32
+ }
33
+ }
34
+
35
+ return null
36
+ }
37
+
38
+ /** Human-readable one-liner for successful push (matches `supatype push` tone). */
39
+ export function formatEnginePushMessage(result: EnginePushResult): string {
40
+ if (result.status === "up_to_date") {
41
+ if (result.admin_refreshed) {
42
+ return "Schema up to date — Studio metadata synced."
43
+ }
44
+ return "Schema up to date."
45
+ }
46
+
47
+ const ops = result.operations
48
+ if (typeof ops === "number" && ops > 0) {
49
+ return `Applied ${ops} operation(s).`
50
+ }
51
+
52
+ return result.message?.trim() || "Schema applied."
53
+ }
54
+
55
+ const COMPOSE_PROGRESS_LINE =
56
+ /^Container\s+.+\s+(Running|Waiting|Healthy|Created|Starting|Started|Exited|Stopped)\s*$/i
57
+
58
+ /** Drop docker compose progress noise; keep engine JSON and real errors. */
59
+ export function filterComposeNoise(output: string): string {
60
+ return output
61
+ .split(/\r?\n/)
62
+ .map((line) => line.trimEnd())
63
+ .filter((line) => {
64
+ const t = line.trim()
65
+ if (!t) return false
66
+ if (COMPOSE_PROGRESS_LINE.test(t)) return false
67
+ return true
68
+ })
69
+ .join("\n")
70
+ .trim()
71
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Resolve component binaries, downloading from the CDN when not cached.
3
+ */
4
+
5
+ import {
6
+ resolveBinary,
7
+ download,
8
+ currentPlatform,
9
+ resolveVersionFor,
10
+ type Component,
11
+ } from "./binary-cache.js"
12
+ import type { SupatypeProjectConfig } from "./project-config.js"
13
+
14
+ export async function ensureBinary(
15
+ component: Component,
16
+ config: SupatypeProjectConfig,
17
+ ): Promise<string> {
18
+ try {
19
+ return await resolveBinary(component, config)
20
+ } catch (err) {
21
+ const message = err instanceof Error ? err.message : String(err)
22
+ if (!message.includes("not found in cache")) {
23
+ throw err
24
+ }
25
+ }
26
+
27
+ return download(component, await resolveVersionFor(component, config), currentPlatform())
28
+ }