@supatype/cli 0.1.0-alpha.9 → 0.1.1

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 (407) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/.turbo/turbo-test.log +285 -69
  3. package/.turbo/turbo-typecheck.log +1 -1
  4. package/assets/supatype-logo-wordmark.ascii.txt +6 -0
  5. package/bin/dev-entry.ts +2 -1
  6. package/dist/app/framework.js +1 -3
  7. package/dist/app/framework.js.map +1 -1
  8. package/dist/app/proxy-dev-app.d.ts +14 -0
  9. package/dist/app/proxy-dev-app.d.ts.map +1 -1
  10. package/dist/app/proxy-dev-app.js +110 -6
  11. package/dist/app/proxy-dev-app.js.map +1 -1
  12. package/dist/app-config.d.ts +10 -0
  13. package/dist/app-config.d.ts.map +1 -1
  14. package/dist/app-config.js +72 -0
  15. package/dist/app-config.js.map +1 -1
  16. package/dist/assets/supatype-logo-wordmark.ascii.txt +6 -0
  17. package/dist/binary-cache.d.ts +19 -7
  18. package/dist/binary-cache.d.ts.map +1 -1
  19. package/dist/binary-cache.js +92 -46
  20. package/dist/binary-cache.js.map +1 -1
  21. package/dist/cli.d.ts +1 -1
  22. package/dist/cli.d.ts.map +1 -1
  23. package/dist/cli.js +17 -2
  24. package/dist/cli.js.map +1 -1
  25. package/dist/commands/add.d.ts +3 -0
  26. package/dist/commands/add.d.ts.map +1 -0
  27. package/dist/commands/add.js +86 -0
  28. package/dist/commands/add.js.map +1 -0
  29. package/dist/commands/admin.d.ts +28 -1
  30. package/dist/commands/admin.d.ts.map +1 -1
  31. package/dist/commands/admin.js +297 -149
  32. package/dist/commands/admin.js.map +1 -1
  33. package/dist/commands/adopt.d.ts +3 -0
  34. package/dist/commands/adopt.d.ts.map +1 -0
  35. package/dist/commands/adopt.js +55 -0
  36. package/dist/commands/adopt.js.map +1 -0
  37. package/dist/commands/app.d.ts.map +1 -1
  38. package/dist/commands/app.js +20 -17
  39. package/dist/commands/app.js.map +1 -1
  40. package/dist/commands/cache.d.ts.map +1 -1
  41. package/dist/commands/cache.js +11 -10
  42. package/dist/commands/cache.js.map +1 -1
  43. package/dist/commands/cloud.d.ts +4 -9
  44. package/dist/commands/cloud.d.ts.map +1 -1
  45. package/dist/commands/cloud.js +75 -125
  46. package/dist/commands/cloud.js.map +1 -1
  47. package/dist/commands/db.d.ts.map +1 -1
  48. package/dist/commands/db.js +37 -58
  49. package/dist/commands/db.js.map +1 -1
  50. package/dist/commands/deploy.d.ts.map +1 -1
  51. package/dist/commands/deploy.js +140 -96
  52. package/dist/commands/deploy.js.map +1 -1
  53. package/dist/commands/dev.d.ts.map +1 -1
  54. package/dist/commands/dev.js +74 -39
  55. package/dist/commands/dev.js.map +1 -1
  56. package/dist/commands/diff.d.ts.map +1 -1
  57. package/dist/commands/diff.js +39 -39
  58. package/dist/commands/diff.js.map +1 -1
  59. package/dist/commands/doctor.d.ts +3 -0
  60. package/dist/commands/doctor.d.ts.map +1 -0
  61. package/dist/commands/doctor.js +78 -0
  62. package/dist/commands/doctor.js.map +1 -0
  63. package/dist/commands/engine.d.ts.map +1 -1
  64. package/dist/commands/engine.js +5 -4
  65. package/dist/commands/engine.js.map +1 -1
  66. package/dist/commands/functions.d.ts.map +1 -1
  67. package/dist/commands/functions.js +172 -119
  68. package/dist/commands/functions.js.map +1 -1
  69. package/dist/commands/generate.d.ts.map +1 -1
  70. package/dist/commands/generate.js +5 -4
  71. package/dist/commands/generate.js.map +1 -1
  72. package/dist/commands/init.d.ts +35 -1
  73. package/dist/commands/init.d.ts.map +1 -1
  74. package/dist/commands/init.js +883 -107
  75. package/dist/commands/init.js.map +1 -1
  76. package/dist/commands/introspect.d.ts +3 -0
  77. package/dist/commands/introspect.d.ts.map +1 -0
  78. package/dist/commands/introspect.js +35 -0
  79. package/dist/commands/introspect.js.map +1 -0
  80. package/dist/commands/keys.d.ts +15 -1
  81. package/dist/commands/keys.d.ts.map +1 -1
  82. package/dist/commands/keys.js +46 -10
  83. package/dist/commands/keys.js.map +1 -1
  84. package/dist/commands/link-helpers.d.ts +15 -0
  85. package/dist/commands/link-helpers.d.ts.map +1 -0
  86. package/dist/commands/link-helpers.js +225 -0
  87. package/dist/commands/link-helpers.js.map +1 -0
  88. package/dist/commands/logs.d.ts.map +1 -1
  89. package/dist/commands/logs.js +5 -4
  90. package/dist/commands/logs.js.map +1 -1
  91. package/dist/commands/migrate-from-v1.d.ts.map +1 -1
  92. package/dist/commands/migrate-from-v1.js +3 -2
  93. package/dist/commands/migrate-from-v1.js.map +1 -1
  94. package/dist/commands/migrate.d.ts.map +1 -1
  95. package/dist/commands/migrate.js +119 -26
  96. package/dist/commands/migrate.js.map +1 -1
  97. package/dist/commands/pg.d.ts.map +1 -1
  98. package/dist/commands/pg.js +11 -12
  99. package/dist/commands/pg.js.map +1 -1
  100. package/dist/commands/plugins.d.ts.map +1 -1
  101. package/dist/commands/plugins.js +55 -46
  102. package/dist/commands/plugins.js.map +1 -1
  103. package/dist/commands/pull.d.ts.map +1 -1
  104. package/dist/commands/pull.js +33 -5
  105. package/dist/commands/pull.js.map +1 -1
  106. package/dist/commands/push.d.ts.map +1 -1
  107. package/dist/commands/push.js +111 -138
  108. package/dist/commands/push.js.map +1 -1
  109. package/dist/commands/seed.d.ts.map +1 -1
  110. package/dist/commands/seed.js +4 -3
  111. package/dist/commands/seed.js.map +1 -1
  112. package/dist/commands/self-host.d.ts +2 -2
  113. package/dist/commands/self-host.d.ts.map +1 -1
  114. package/dist/commands/self-host.js +65 -50
  115. package/dist/commands/self-host.js.map +1 -1
  116. package/dist/commands/self-update.d.ts.map +1 -1
  117. package/dist/commands/self-update.js +3 -2
  118. package/dist/commands/self-update.js.map +1 -1
  119. package/dist/commands/status.d.ts +1 -1
  120. package/dist/commands/status.d.ts.map +1 -1
  121. package/dist/commands/status.js +95 -29
  122. package/dist/commands/status.js.map +1 -1
  123. package/dist/commands/types.d.ts.map +1 -1
  124. package/dist/commands/types.js +3 -2
  125. package/dist/commands/types.js.map +1 -1
  126. package/dist/commands/update.d.ts.map +1 -1
  127. package/dist/commands/update.js +54 -21
  128. package/dist/commands/update.js.map +1 -1
  129. package/dist/compose-rename.d.ts +10 -0
  130. package/dist/compose-rename.d.ts.map +1 -0
  131. package/dist/compose-rename.js +67 -0
  132. package/dist/compose-rename.js.map +1 -0
  133. package/dist/config.d.ts +2 -1
  134. package/dist/config.d.ts.map +1 -1
  135. package/dist/config.js.map +1 -1
  136. package/dist/dev-compose.d.ts +26 -0
  137. package/dist/dev-compose.d.ts.map +1 -1
  138. package/dist/dev-compose.js +357 -79
  139. package/dist/dev-compose.js.map +1 -1
  140. package/dist/dev-log-bus.d.ts +30 -0
  141. package/dist/dev-log-bus.d.ts.map +1 -0
  142. package/dist/dev-log-bus.js +87 -0
  143. package/dist/dev-log-bus.js.map +1 -0
  144. package/dist/dev-log-filter.d.ts +10 -0
  145. package/dist/dev-log-filter.d.ts.map +1 -0
  146. package/dist/dev-log-filter.js +36 -0
  147. package/dist/dev-log-filter.js.map +1 -0
  148. package/dist/dev-logo.d.ts +12 -0
  149. package/dist/dev-logo.d.ts.map +1 -0
  150. package/dist/dev-logo.js +56 -0
  151. package/dist/dev-logo.js.map +1 -0
  152. package/dist/dev-ports.d.ts +27 -0
  153. package/dist/dev-ports.d.ts.map +1 -0
  154. package/dist/dev-ports.js +171 -0
  155. package/dist/dev-ports.js.map +1 -0
  156. package/dist/dev-session-lock.d.ts +25 -0
  157. package/dist/dev-session-lock.d.ts.map +1 -0
  158. package/dist/dev-session-lock.js +81 -0
  159. package/dist/dev-session-lock.js.map +1 -0
  160. package/dist/dev-session.d.ts +26 -0
  161. package/dist/dev-session.d.ts.map +1 -0
  162. package/dist/dev-session.js +106 -0
  163. package/dist/dev-session.js.map +1 -0
  164. package/dist/dev-shutdown.d.ts +25 -0
  165. package/dist/dev-shutdown.d.ts.map +1 -0
  166. package/dist/dev-shutdown.js +114 -0
  167. package/dist/dev-shutdown.js.map +1 -0
  168. package/dist/dev-task-colors.d.ts +13 -0
  169. package/dist/dev-task-colors.d.ts.map +1 -0
  170. package/dist/dev-task-colors.js +43 -0
  171. package/dist/dev-task-colors.js.map +1 -0
  172. package/dist/dev-tui.d.ts +24 -0
  173. package/dist/dev-tui.d.ts.map +1 -0
  174. package/dist/dev-tui.js +188 -0
  175. package/dist/dev-tui.js.map +1 -0
  176. package/dist/diff-output.d.ts +5 -1
  177. package/dist/diff-output.d.ts.map +1 -1
  178. package/dist/diff-output.js +69 -0
  179. package/dist/diff-output.js.map +1 -1
  180. package/dist/docker-runtime.d.ts +30 -0
  181. package/dist/docker-runtime.d.ts.map +1 -0
  182. package/dist/docker-runtime.js +118 -0
  183. package/dist/docker-runtime.js.map +1 -0
  184. package/dist/engine-client.d.ts +10 -1
  185. package/dist/engine-client.d.ts.map +1 -1
  186. package/dist/engine-client.js +76 -17
  187. package/dist/engine-client.js.map +1 -1
  188. package/dist/engine-push-output.d.ts +17 -0
  189. package/dist/engine-push-output.d.ts.map +1 -0
  190. package/dist/engine-push-output.js +64 -0
  191. package/dist/engine-push-output.js.map +1 -0
  192. package/dist/ensure-binary.js +2 -2
  193. package/dist/ensure-binary.js.map +1 -1
  194. package/dist/env-file.d.ts +5 -0
  195. package/dist/env-file.d.ts.map +1 -0
  196. package/dist/env-file.js +33 -0
  197. package/dist/env-file.js.map +1 -0
  198. package/dist/gitignore.d.ts +8 -0
  199. package/dist/gitignore.d.ts.map +1 -0
  200. package/dist/gitignore.js +41 -0
  201. package/dist/gitignore.js.map +1 -0
  202. package/dist/kong-config.d.ts +9 -0
  203. package/dist/kong-config.d.ts.map +1 -1
  204. package/dist/kong-config.js +18 -1
  205. package/dist/kong-config.js.map +1 -1
  206. package/dist/link.d.ts +66 -0
  207. package/dist/link.d.ts.map +1 -0
  208. package/dist/link.js +160 -0
  209. package/dist/link.js.map +1 -0
  210. package/dist/process-manager.d.ts +8 -0
  211. package/dist/process-manager.d.ts.map +1 -1
  212. package/dist/process-manager.js +53 -9
  213. package/dist/process-manager.js.map +1 -1
  214. package/dist/project-config.d.ts +30 -3
  215. package/dist/project-config.d.ts.map +1 -1
  216. package/dist/project-config.js +37 -4
  217. package/dist/project-config.js.map +1 -1
  218. package/dist/prompts.d.ts +3 -0
  219. package/dist/prompts.d.ts.map +1 -0
  220. package/dist/prompts.js +3 -0
  221. package/dist/prompts.js.map +1 -0
  222. package/dist/pull-utils.d.ts +50 -14
  223. package/dist/pull-utils.d.ts.map +1 -1
  224. package/dist/pull-utils.js +152 -12
  225. package/dist/pull-utils.js.map +1 -1
  226. package/dist/resolve-target.d.ts +86 -0
  227. package/dist/resolve-target.d.ts.map +1 -0
  228. package/dist/resolve-target.js +291 -0
  229. package/dist/resolve-target.js.map +1 -0
  230. package/dist/restore-system-relation-targets.d.ts +3 -0
  231. package/dist/restore-system-relation-targets.d.ts.map +1 -0
  232. package/dist/restore-system-relation-targets.js +45 -0
  233. package/dist/restore-system-relation-targets.js.map +1 -0
  234. package/dist/runtime-routes.d.ts.map +1 -1
  235. package/dist/runtime-routes.js +7 -0
  236. package/dist/runtime-routes.js.map +1 -1
  237. package/dist/schema-ast-v2.d.ts +1 -1
  238. package/dist/schema-ast-v2.d.ts.map +1 -1
  239. package/dist/schema-ast-v2.js +2 -2
  240. package/dist/schema-ast-v2.js.map +1 -1
  241. package/dist/schema-sources.d.ts +40 -0
  242. package/dist/schema-sources.d.ts.map +1 -0
  243. package/dist/schema-sources.js +183 -0
  244. package/dist/schema-sources.js.map +1 -0
  245. package/dist/scripts/postinstall.js +5 -1
  246. package/dist/scripts/postinstall.js.map +1 -1
  247. package/dist/self-host-compose.d.ts +37 -1
  248. package/dist/self-host-compose.d.ts.map +1 -1
  249. package/dist/self-host-compose.js +234 -43
  250. package/dist/self-host-compose.js.map +1 -1
  251. package/dist/storage-provision.d.ts +4 -0
  252. package/dist/storage-provision.d.ts.map +1 -1
  253. package/dist/storage-provision.js +24 -2
  254. package/dist/storage-provision.js.map +1 -1
  255. package/dist/supatype-eval-1781522769253.d.mts +2 -0
  256. package/dist/supatype-eval-1781522769253.d.mts.map +1 -0
  257. package/dist/supatype-eval-1781522769253.mjs +3 -0
  258. package/dist/supatype-eval-1781522769253.mjs.map +1 -0
  259. package/dist/systemd.js +2 -2
  260. package/dist/systemd.js.map +1 -1
  261. package/dist/target-client.d.ts +10 -0
  262. package/dist/target-client.d.ts.map +1 -0
  263. package/dist/target-client.js +22 -0
  264. package/dist/target-client.js.map +1 -0
  265. package/dist/type-extractor.d.ts +11 -0
  266. package/dist/type-extractor.d.ts.map +1 -1
  267. package/dist/type-extractor.js +95 -8
  268. package/dist/type-extractor.js.map +1 -1
  269. package/dist/ui/brand.d.ts +9 -0
  270. package/dist/ui/brand.d.ts.map +1 -0
  271. package/dist/ui/brand.js +11 -0
  272. package/dist/ui/brand.js.map +1 -0
  273. package/dist/ui/confirm.d.ts +12 -0
  274. package/dist/ui/confirm.d.ts.map +1 -0
  275. package/dist/ui/confirm.js +28 -0
  276. package/dist/ui/confirm.js.map +1 -0
  277. package/dist/ui/fatal.d.ts +10 -0
  278. package/dist/ui/fatal.d.ts.map +1 -0
  279. package/dist/ui/fatal.js +34 -0
  280. package/dist/ui/fatal.js.map +1 -0
  281. package/dist/ui/index.d.ts +9 -0
  282. package/dist/ui/index.d.ts.map +1 -0
  283. package/dist/ui/index.js +9 -0
  284. package/dist/ui/index.js.map +1 -0
  285. package/dist/ui/interactive.d.ts +3 -0
  286. package/dist/ui/interactive.d.ts.map +1 -0
  287. package/dist/ui/interactive.js +5 -0
  288. package/dist/ui/interactive.js.map +1 -0
  289. package/dist/ui/messages.d.ts +10 -0
  290. package/dist/ui/messages.d.ts.map +1 -0
  291. package/dist/ui/messages.js +35 -0
  292. package/dist/ui/messages.js.map +1 -0
  293. package/dist/ui/next-steps.d.ts +3 -0
  294. package/dist/ui/next-steps.d.ts.map +1 -0
  295. package/dist/ui/next-steps.js +10 -0
  296. package/dist/ui/next-steps.js.map +1 -0
  297. package/dist/ui/progress.d.ts +5 -0
  298. package/dist/ui/progress.d.ts.map +1 -0
  299. package/dist/ui/progress.js +24 -0
  300. package/dist/ui/progress.js.map +1 -0
  301. package/dist/ui/prompts.d.ts +14 -0
  302. package/dist/ui/prompts.d.ts.map +1 -0
  303. package/dist/ui/prompts.js +34 -0
  304. package/dist/ui/prompts.js.map +1 -0
  305. package/package.json +5 -2
  306. package/src/app/framework.ts +1 -3
  307. package/src/app/proxy-dev-app.ts +114 -6
  308. package/src/app-config.ts +80 -0
  309. package/src/binary-cache.ts +102 -52
  310. package/src/cli.ts +16 -2
  311. package/src/commands/add.ts +97 -0
  312. package/src/commands/admin.ts +381 -190
  313. package/src/commands/adopt.ts +82 -0
  314. package/src/commands/app.ts +20 -17
  315. package/src/commands/cache.ts +11 -10
  316. package/src/commands/cloud.ts +91 -142
  317. package/src/commands/db.ts +40 -63
  318. package/src/commands/deploy.ts +186 -126
  319. package/src/commands/dev.ts +98 -55
  320. package/src/commands/diff.ts +52 -43
  321. package/src/commands/doctor.ts +103 -0
  322. package/src/commands/engine.ts +5 -4
  323. package/src/commands/functions.ts +187 -123
  324. package/src/commands/generate.ts +5 -4
  325. package/src/commands/init.ts +1087 -104
  326. package/src/commands/introspect.ts +48 -0
  327. package/src/commands/keys.ts +56 -14
  328. package/src/commands/link-helpers.ts +273 -0
  329. package/src/commands/logs.ts +5 -4
  330. package/src/commands/migrate-from-v1.ts +3 -2
  331. package/src/commands/migrate.ts +167 -27
  332. package/src/commands/pg.ts +13 -18
  333. package/src/commands/plugins.ts +55 -46
  334. package/src/commands/pull.ts +38 -9
  335. package/src/commands/push.ts +148 -175
  336. package/src/commands/seed.ts +5 -4
  337. package/src/commands/self-host.ts +85 -54
  338. package/src/commands/self-update.ts +3 -2
  339. package/src/commands/status.ts +102 -33
  340. package/src/commands/types.ts +3 -2
  341. package/src/commands/update.ts +59 -23
  342. package/src/compose-rename.ts +76 -0
  343. package/src/config.ts +2 -1
  344. package/src/dev-compose.ts +462 -76
  345. package/src/dev-log-bus.ts +101 -0
  346. package/src/dev-log-filter.ts +32 -0
  347. package/src/dev-logo.ts +61 -0
  348. package/src/dev-ports.ts +212 -0
  349. package/src/dev-session-lock.ts +101 -0
  350. package/src/dev-session.ts +130 -0
  351. package/src/dev-shutdown.ts +147 -0
  352. package/src/dev-task-colors.ts +47 -0
  353. package/src/dev-tui.ts +232 -0
  354. package/src/diff-output.ts +79 -1
  355. package/src/docker-runtime.ts +151 -0
  356. package/src/engine-client.ts +81 -17
  357. package/src/engine-push-output.ts +75 -0
  358. package/src/ensure-binary.ts +2 -2
  359. package/src/env-file.ts +37 -0
  360. package/src/gitignore.ts +48 -0
  361. package/src/kong-config.ts +24 -1
  362. package/src/link.ts +243 -0
  363. package/src/process-manager.ts +66 -10
  364. package/src/project-config.ts +62 -7
  365. package/src/prompts.ts +2 -0
  366. package/src/pull-utils.ts +217 -23
  367. package/src/resolve-target.ts +419 -0
  368. package/src/restore-system-relation-targets.ts +45 -0
  369. package/src/runtime-routes.ts +7 -0
  370. package/src/schema-ast-v2.ts +2 -1
  371. package/src/schema-sources.ts +248 -0
  372. package/src/scripts/postinstall.ts +7 -1
  373. package/src/self-host-compose.ts +262 -46
  374. package/src/storage-provision.ts +33 -1
  375. package/src/supatype-eval-1781522769253.mts +1 -0
  376. package/src/systemd.ts +2 -2
  377. package/src/target-client.ts +40 -0
  378. package/src/type-extractor.ts +124 -11
  379. package/src/ui/README.md +17 -0
  380. package/src/ui/brand.ts +12 -0
  381. package/src/ui/confirm.ts +38 -0
  382. package/src/ui/fatal.ts +43 -0
  383. package/src/ui/index.ts +8 -0
  384. package/src/ui/interactive.ts +4 -0
  385. package/src/ui/messages.ts +43 -0
  386. package/src/ui/next-steps.ts +10 -0
  387. package/src/ui/progress.ts +28 -0
  388. package/src/ui/prompts.ts +40 -0
  389. package/tests/admin-ensure.test.ts +59 -0
  390. package/tests/cli-help.test.ts +27 -2
  391. package/tests/config.test.ts +29 -2
  392. package/tests/dev-ports.test.ts +41 -0
  393. package/tests/dev-session-lock.test.ts +54 -0
  394. package/tests/dev-ui.test.ts +162 -0
  395. package/tests/docker-runtime.test.ts +236 -0
  396. package/tests/engine-push-output.test.ts +67 -0
  397. package/tests/init.test.ts +197 -18
  398. package/tests/link.test.ts +148 -0
  399. package/tests/minisign.test.ts +102 -0
  400. package/tests/proxy-dev-app.test.ts +45 -1
  401. package/tests/pull-utils.test.ts +5 -4
  402. package/tests/runtime-contract.test.ts +186 -2
  403. package/tests/schema-sources.test.ts +119 -0
  404. package/tests/storage-provision.test.ts +100 -0
  405. package/tests/ui-confirm.test.ts +41 -0
  406. package/tests/ui-messages.test.ts +66 -0
  407. package/tsconfig.tsbuildinfo +1 -1
@@ -13,21 +13,25 @@ import { mkdirSync, writeFileSync, unlinkSync, existsSync, readdirSync } from "n
13
13
  import { tmpdir, homedir } from "node:os"
14
14
  import { join } from "node:path"
15
15
  import { loadConfig } from "./config.js"
16
- import { resolveBinary, currentPlatform, cachePath } from "./binary-cache.js"
16
+ import { currentPlatform, cachePath } from "./binary-cache.js"
17
+ import { ensureBinary } from "./ensure-binary.js"
17
18
 
18
19
  // ---------------------------------------------------------------------------
19
20
  // Types (kept for backward compatibility with existing callers)
20
21
  // ---------------------------------------------------------------------------
21
22
 
22
23
  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
24
  type?: string
25
+ kind?: string
27
26
  description?: string
28
27
  risk?: "safe" | "warn" | "danger" | "cautious" | "destructive"
29
28
  warning?: string
30
29
  sql?: string
30
+ table?: string
31
+ column?: string
32
+ constraint?: string
33
+ index_name?: string
34
+ index?: { fields?: string[]; name?: string; unique?: boolean }
31
35
  }
32
36
 
33
37
  export interface DiffResult {
@@ -83,10 +87,16 @@ async function getEngineBin(): Promise<string> {
83
87
 
84
88
  try {
85
89
  const config = loadConfig(cwd)
86
- _engineBin = await resolveBinary("engine", config)
90
+ // Download-on-miss (with retry) so a fresh machine or a failed postinstall
91
+ // self-heals on first use instead of silently skipping type/admin refresh.
92
+ _engineBin = await ensureBinary("engine", config)
87
93
  return _engineBin
88
- } catch {
89
- // No valid project config fall through to default cache path.
94
+ } catch (err) {
95
+ // A real download/verification failure must surface, not fall back to a
96
+ // possibly-stale cached binary from a different version.
97
+ const message = err instanceof Error ? err.message : String(err)
98
+ if (message.includes("Failed to download")) throw err
99
+ // Otherwise (no valid project config) fall through to default cache scan.
90
100
  }
91
101
 
92
102
  // No config found — scan the cache for any available engine binary.
@@ -146,24 +156,40 @@ export async function engineRequest<T = unknown>(
146
156
  ): Promise<T> {
147
157
  const bin = await getEngineBin()
148
158
 
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
159
  const tmpDir = join(tmpdir(), "supatype-engine")
153
160
  mkdirSync(tmpDir, { recursive: true })
161
+ const cleanup: string[] = []
154
162
  const reqFile = join(tmpDir, `req-${Date.now()}.json`)
155
163
  const inputPayload = body["ast"] !== undefined ? body["ast"] : body
156
164
  writeFileSync(reqFile, JSON.stringify(inputPayload))
165
+ cleanup.push(reqFile)
166
+
167
+ let gzPath: string | undefined
168
+ let manifestPath: string | undefined
169
+ if (typeof body["schema_sources_gz_base64"] === "string") {
170
+ gzPath = join(tmpDir, `sources-${Date.now()}.gz`)
171
+ writeFileSync(gzPath, Buffer.from(body["schema_sources_gz_base64"], "base64"))
172
+ cleanup.push(gzPath)
173
+ }
174
+ if (body["schema_sources_manifest"] !== undefined) {
175
+ manifestPath = join(tmpDir, `manifest-${Date.now()}.json`)
176
+ writeFileSync(manifestPath, JSON.stringify(body["schema_sources_manifest"]))
177
+ cleanup.push(manifestPath)
178
+ }
157
179
 
158
- const args = endpointToArgs(endpoint, body, reqFile)
180
+ const args = endpointToArgs(endpoint, body, reqFile, {
181
+ ...(gzPath !== undefined ? { gzPath } : {}),
182
+ ...(manifestPath !== undefined ? { manifestPath } : {}),
183
+ })
159
184
 
160
185
  const result = spawnSync(bin, args, {
161
186
  encoding: "utf8",
162
187
  cwd: process.cwd(),
163
188
  })
164
189
 
165
- // Clean up temp file.
166
- try { unlinkSync(reqFile) } catch { /* ignore */ }
190
+ for (const f of cleanup) {
191
+ try { unlinkSync(f) } catch { /* ignore */ }
192
+ }
167
193
 
168
194
  if (result.status !== 0) {
169
195
  const stderr = result.stderr?.trim() || "(no output)"
@@ -195,6 +221,7 @@ function endpointToArgs(
195
221
  endpoint: string,
196
222
  body: Record<string, unknown>,
197
223
  reqFile: string,
224
+ sources?: { gzPath?: string; manifestPath?: string },
198
225
  ): string[] {
199
226
  const dbUrl = (body["database_url"] as string | undefined) ?? ""
200
227
  const schema = (body["schema"] as string | undefined) ?? "public"
@@ -206,8 +233,26 @@ function endpointToArgs(
206
233
  case "/diff":
207
234
  return ["diff", "--input", reqFile, "--database-url", dbUrl, "--schema", schema]
208
235
 
209
- case "/push":
210
- return ["push", "--input", reqFile, "--database-url", dbUrl, "--schema", schema, ...force, ...nonInteractive]
236
+ case "/push": {
237
+ const sourceArgs: string[] = []
238
+ if (sources?.gzPath) sourceArgs.push("--schema-sources-gz", sources.gzPath)
239
+ if (sources?.manifestPath) sourceArgs.push("--schema-sources-manifest", sources.manifestPath)
240
+ return [
241
+ "push",
242
+ "--input",
243
+ reqFile,
244
+ "--database-url",
245
+ dbUrl,
246
+ "--schema",
247
+ schema,
248
+ ...force,
249
+ ...nonInteractive,
250
+ ...sourceArgs,
251
+ ]
252
+ }
253
+
254
+ case "/rollback":
255
+ return ["rollback", "--database-url", dbUrl, "--schema", schema]
211
256
 
212
257
  case "/parse":
213
258
  return ["parse", "--input", reqFile]
@@ -220,6 +265,18 @@ function endpointToArgs(
220
265
  case "/introspect":
221
266
  return ["introspect", "--database-url", dbUrl, "--schema", schema]
222
267
 
268
+ case "/doctor": {
269
+ const strict = body["strict"] ? ["--strict"] : []
270
+ const noCache = body["no_cache"] ? ["--no-cache"] : []
271
+ return ["doctor", "--input", reqFile, "--database-url", dbUrl, "--schema", schema, ...strict, ...noCache]
272
+ }
273
+
274
+ case "/adopt": {
275
+ const yes = body["yes"] ? ["--yes"] : []
276
+ const noCache = body["no_cache"] ? ["--no-cache"] : []
277
+ return ["adopt", "--input", reqFile, "--database-url", dbUrl, "--schema", schema, ...yes, ...noCache]
278
+ }
279
+
223
280
  case "/validate":
224
281
  return ["validate", "--input", reqFile]
225
282
 
@@ -227,9 +284,16 @@ function endpointToArgs(
227
284
  return ["admin", "--input", reqFile]
228
285
 
229
286
  default:
230
- if (endpoint.startsWith("/migrations")) {
287
+ if (endpoint === "/migrations" || endpoint.startsWith("/migrations")) {
231
288
  const action = (body["action"] as string | undefined) ?? "list"
232
- return ["migrations", action, "--database-url", dbUrl]
289
+ if (action === "rollback") {
290
+ return ["rollback", "--database-url", dbUrl, "--schema", schema]
291
+ }
292
+ const name = body["name"] as string | undefined
293
+ if (name) {
294
+ return ["migrations", "--database-url", dbUrl, "--name", name]
295
+ }
296
+ return ["migrations", "--database-url", dbUrl]
233
297
  }
234
298
  return [endpoint.replace(/^\//, ""), "--input", reqFile]
235
299
  }
@@ -0,0 +1,75 @@
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 parseEngineJsonOutput<T>(output: string): T | 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 T
22
+ } catch {
23
+ /* try next line */
24
+ }
25
+ }
26
+
27
+ if (trimmed.startsWith("{")) {
28
+ try {
29
+ return JSON.parse(trimmed) as T
30
+ } catch {
31
+ return null
32
+ }
33
+ }
34
+
35
+ return null
36
+ }
37
+
38
+ export function parseEnginePushOutput(output: string): EnginePushResult | null {
39
+ return parseEngineJsonOutput<EnginePushResult>(output)
40
+ }
41
+
42
+ /** Human-readable one-liner for successful push (matches `supatype push` tone). */
43
+ export function formatEnginePushMessage(result: EnginePushResult): string {
44
+ if (result.status === "up_to_date") {
45
+ if (result.admin_refreshed) {
46
+ return "Schema up to date — Studio metadata synced."
47
+ }
48
+ return "Schema up to date."
49
+ }
50
+
51
+ const ops = result.operations
52
+ if (typeof ops === "number" && ops > 0) {
53
+ return `Applied ${ops} operation(s).`
54
+ }
55
+
56
+ return result.message?.trim() || "Schema applied."
57
+ }
58
+
59
+ const COMPOSE_PROGRESS_LINE =
60
+ /^Container\s+.+\s+(Running|Waiting|Healthy|Created|Starting|Started|Exited|Stopped)\s*$/i
61
+
62
+ /** Drop docker compose progress noise; keep engine JSON and real errors. */
63
+ export function filterComposeNoise(output: string): string {
64
+ return output
65
+ .split(/\r?\n/)
66
+ .map((line) => line.trimEnd())
67
+ .filter((line) => {
68
+ const t = line.trim()
69
+ if (!t) return false
70
+ if (COMPOSE_PROGRESS_LINE.test(t)) return false
71
+ return true
72
+ })
73
+ .join("\n")
74
+ .trim()
75
+ }
@@ -6,7 +6,7 @@ import {
6
6
  resolveBinary,
7
7
  download,
8
8
  currentPlatform,
9
- versionFor,
9
+ resolveVersionFor,
10
10
  type Component,
11
11
  } from "./binary-cache.js"
12
12
  import type { SupatypeProjectConfig } from "./project-config.js"
@@ -24,5 +24,5 @@ export async function ensureBinary(
24
24
  }
25
25
  }
26
26
 
27
- return download(component, versionFor(component, config), currentPlatform())
27
+ return download(component, await resolveVersionFor(component, config), currentPlatform())
28
28
  }
@@ -0,0 +1,37 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs"
2
+ import { join } from "node:path"
3
+
4
+ /** Merge key/value updates into a project `.env` without dropping unrelated lines. */
5
+ export function upsertEnvFile(
6
+ cwd: string,
7
+ updates: Record<string, string>,
8
+ removeKeys: readonly string[] = [],
9
+ ): void {
10
+ const envPath = join(cwd, ".env")
11
+ const existing = existsSync(envPath) ? readFileSync(envPath, "utf8") : ""
12
+ const keys = new Set([...Object.keys(updates), ...removeKeys])
13
+ const kept = existing
14
+ .split("\n")
15
+ .filter((line) => {
16
+ const key = line.split("=")[0]?.trim()
17
+ return key && line.includes("=") && !keys.has(key)
18
+ })
19
+ const merged = [...kept, ...Object.entries(updates).map(([key, value]) => `${key}=${value}`)]
20
+ writeFileSync(envPath, `${merged.join("\n").trimEnd()}\n`, "utf8")
21
+ }
22
+
23
+ export function readEnvValue(cwd: string, key: string, fallback: string): string {
24
+ const envPath = join(cwd, ".env")
25
+ if (existsSync(envPath)) {
26
+ const m = readFileSync(envPath, "utf8").match(new RegExp(`^${key}=(.+)$`, "m"))
27
+ if (m?.[1]) return m[1].trim()
28
+ }
29
+ return fallback
30
+ }
31
+
32
+ export function readEnvInt(cwd: string, key: string): number | null {
33
+ const raw = readEnvValue(cwd, key, "")
34
+ if (!raw) return null
35
+ const port = Number(raw)
36
+ return Number.isInteger(port) && port > 0 && port <= 65535 ? port : null
37
+ }
@@ -0,0 +1,48 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs"
2
+ import { resolve } from "node:path"
3
+
4
+ export const SUPATYPE_GITIGNORE_MARKER = "# Supatype — local runtime (contains secrets in link.json)"
5
+ export const SUPATYPE_GITIGNORE_BLOCK = `${SUPATYPE_GITIGNORE_MARKER}
6
+ .env
7
+ .supatype/
8
+ supatype.local.config.ts
9
+ supatype.local.config.js
10
+ supatype.local.config.mjs
11
+ `
12
+
13
+ export function isSupatypeGitignored(cwd: string): boolean {
14
+ const gitignorePath = resolve(cwd, ".gitignore")
15
+ if (!existsSync(gitignorePath)) return false
16
+ const content = readFileSync(gitignorePath, "utf8")
17
+ return /\.supatype\/?(\/|\s|$)/m.test(content) || content.includes(".supatype/")
18
+ }
19
+
20
+ export function ensureSupatypeGitignore(cwd: string, opts?: { silent?: boolean }): boolean {
21
+ const gitignorePath = resolve(cwd, ".gitignore")
22
+ if (isSupatypeGitignored(cwd)) return true
23
+
24
+ if (existsSync(gitignorePath)) {
25
+ const content = readFileSync(gitignorePath, "utf8")
26
+ const next = content.endsWith("\n") ? content : `${content}\n`
27
+ writeFileSync(gitignorePath, `${next}\n${SUPATYPE_GITIGNORE_BLOCK}`, "utf8")
28
+ } else {
29
+ writeFileSync(
30
+ gitignorePath,
31
+ `.env\nnode_modules/\ndist/\n${SUPATYPE_GITIGNORE_BLOCK}`,
32
+ "utf8",
33
+ )
34
+ }
35
+
36
+ if (!opts?.silent) {
37
+ console.warn("Added .supatype/ to .gitignore (link.json contains secrets — never commit).")
38
+ }
39
+ return true
40
+ }
41
+
42
+ export function warnIfLinkNotGitignored(cwd: string): void {
43
+ if (isSupatypeGitignored(cwd)) return
44
+ console.warn(
45
+ "\n⚠ Warning: .supatype/ is not in .gitignore — link.json contains tokens and must not be committed.",
46
+ )
47
+ console.warn(" Run with link --fix-gitignore to append the Supatype block.\n")
48
+ }
@@ -18,6 +18,11 @@ export interface KongDeclarativeOptions {
18
18
  studioServiceUrl?: string | undefined
19
19
  /** See {@link RuntimeRouteOptions.studioStripPath}. */
20
20
  studioStripPath?: boolean | undefined
21
+ /**
22
+ * When set, append a global Kong `acme` plugin (Let's Encrypt) with Redis/Valkey
23
+ * storage so the self-host gateway provisions and renews TLS automatically.
24
+ */
25
+ acme?: { email: string; domain: string; redisHost: string } | undefined
21
26
  }
22
27
 
23
28
  /** Escape a string for use inside YAML double quotes. */
@@ -85,9 +90,27 @@ ${route.paths.map((path) => ` - ${path}`).join("\n")}
85
90
  ${protocols}${routePlugins}${graphqlPlugins}`
86
91
  }).join("\n")
87
92
 
93
+ const acme = opts.acme
94
+ const pluginsBlock = acme
95
+ ? `
96
+ plugins:
97
+ - name: acme
98
+ config:
99
+ account_email: ${yamlQuotedString(acme.email)}
100
+ tos_accepted: true
101
+ domains:
102
+ - ${yamlQuotedString(acme.domain)}
103
+ storage: redis
104
+ storage_config:
105
+ redis:
106
+ host: ${yamlQuotedString(acme.redisHost)}
107
+ port: 6379
108
+ `
109
+ : ""
110
+
88
111
  return `_format_version: "3.0"
89
112
  ${consumersBlock}
90
113
  services:
91
114
  ${servicesBlock}
92
- `
115
+ ${pluginsBlock}`
93
116
  }
package/src/link.ts ADDED
@@ -0,0 +1,243 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
2
+ import { resolve } from "node:path"
3
+ import { warn } from "./ui/messages.js"
4
+
5
+ export const LINK_VERSION = 1 as const
6
+ export const LINK_FILE = ".supatype/link.json"
7
+ export const LEGACY_CLOUD_FILE = ".supatype/cloud.json"
8
+ export const LEGACY_LINKED_FILE = ".supatype/linked.json"
9
+
10
+ export type ProjectLinkKind = "cloud" | "self-host" | "local"
11
+
12
+ export interface EnvironmentTarget {
13
+ name: string
14
+ apiUrl: string
15
+ token?: string
16
+ linkedAt: string
17
+ }
18
+
19
+ export interface ProjectLink {
20
+ version: typeof LINK_VERSION
21
+ kind: ProjectLinkKind
22
+ projectRef: string
23
+ defaultEnvironment: string
24
+ token?: string
25
+ orgId?: string | undefined
26
+ cloudApiUrl?: string
27
+ linkedAt: string
28
+ environments: Record<string, EnvironmentTarget>
29
+ }
30
+
31
+ export interface LocalEnvironment {
32
+ target: "local"
33
+ apiUrl: string
34
+ databaseUrl: string
35
+ projectRef: string
36
+ kongPort: number
37
+ provider: "docker" | "native"
38
+ }
39
+
40
+ export interface BranchContext {
41
+ mode: "branch"
42
+ branchId: string
43
+ apiUrl: string
44
+ token?: string | undefined
45
+ }
46
+
47
+ interface LegacyCloudFile {
48
+ apiUrl?: string
49
+ token?: string
50
+ projectSlug?: string
51
+ orgId?: string
52
+ }
53
+
54
+ interface LegacyLinkedFile {
55
+ ref?: string
56
+ orgId?: string
57
+ }
58
+
59
+ export function writeLocalEnvironment(cwd: string, env: LocalEnvironment): void {
60
+ const dir = resolve(cwd, ".supatype")
61
+ mkdirSync(dir, { recursive: true })
62
+ writeFileSync(resolve(dir, "environment.json"), `${JSON.stringify(env, null, 2)}\n`, "utf8")
63
+ }
64
+
65
+ export function loadLocalEnvironment(cwd: string): LocalEnvironment | null {
66
+ const path = resolve(cwd, ".supatype/environment.json")
67
+ if (!existsSync(path)) return null
68
+ return JSON.parse(readFileSync(path, "utf8")) as LocalEnvironment
69
+ }
70
+
71
+ export function linkPath(cwd: string): string {
72
+ return resolve(cwd, LINK_FILE)
73
+ }
74
+
75
+ export function loadProjectLink(cwd: string): ProjectLink | null {
76
+ migrateLegacyLinkFiles(cwd)
77
+ const path = linkPath(cwd)
78
+ if (!existsSync(path)) return null
79
+ return JSON.parse(readFileSync(path, "utf8")) as ProjectLink
80
+ }
81
+
82
+ export function saveProjectLink(cwd: string, link: ProjectLink): void {
83
+ const dir = resolve(cwd, ".supatype")
84
+ mkdirSync(dir, { recursive: true })
85
+ writeFileSync(linkPath(cwd), `${JSON.stringify(link, null, 2)}\n`, "utf8")
86
+ }
87
+
88
+ export function isProjectLinked(cwd: string): boolean {
89
+ const link = loadProjectLink(cwd)
90
+ return Boolean(link?.projectRef && Object.keys(link.environments).length > 0)
91
+ }
92
+
93
+ export function resolveEnvironmentName(link: ProjectLink, envFlag?: string): string {
94
+ if (envFlag?.trim()) return envFlag.trim()
95
+ return link.defaultEnvironment || "production"
96
+ }
97
+
98
+ export function getEnvironmentTarget(link: ProjectLink, envName: string): EnvironmentTarget | null {
99
+ return link.environments[envName] ?? null
100
+ }
101
+
102
+ export function resolveEnvironmentToken(link: ProjectLink, env: EnvironmentTarget): string | undefined {
103
+ return env.token ?? link.token
104
+ }
105
+
106
+ let migrationWarned = false
107
+
108
+ /** Merge legacy cloud.json + linked.json into link.json once. */
109
+ export function migrateLegacyLinkFiles(cwd: string): void {
110
+ const target = linkPath(cwd)
111
+ if (existsSync(target)) return
112
+
113
+ const cloudPath = resolve(cwd, LEGACY_CLOUD_FILE)
114
+ const linkedPath = resolve(cwd, LEGACY_LINKED_FILE)
115
+ const hasCloud = existsSync(cloudPath)
116
+ const hasLinked = existsSync(linkedPath)
117
+ if (!hasCloud && !hasLinked) return
118
+
119
+ let cloud: LegacyCloudFile | null = null
120
+ let linked: LegacyLinkedFile | null = null
121
+
122
+ if (hasCloud) {
123
+ cloud = JSON.parse(readFileSync(cloudPath, "utf8")) as LegacyCloudFile
124
+ }
125
+ if (hasLinked) {
126
+ linked = JSON.parse(readFileSync(linkedPath, "utf8")) as LegacyLinkedFile
127
+ }
128
+
129
+ const projectRef = cloud?.projectSlug ?? linked?.ref
130
+ if (!projectRef || !cloud?.token) {
131
+ return
132
+ }
133
+
134
+ const now = new Date().toISOString()
135
+ const link: ProjectLink = {
136
+ version: LINK_VERSION,
137
+ kind: "cloud",
138
+ projectRef,
139
+ defaultEnvironment: "production",
140
+ token: cloud.token,
141
+ cloudApiUrl: cloud.apiUrl ?? "https://api.supatype.com",
142
+ linkedAt: now,
143
+ environments: {
144
+ production: {
145
+ name: "production",
146
+ apiUrl: cloud.apiUrl ?? "https://api.supatype.com",
147
+ linkedAt: now,
148
+ },
149
+ },
150
+ ...(cloud.orgId !== undefined
151
+ ? { orgId: cloud.orgId }
152
+ : linked?.orgId !== undefined
153
+ ? { orgId: linked.orgId }
154
+ : {}),
155
+ }
156
+
157
+ saveProjectLink(cwd, link)
158
+
159
+ if (!migrationWarned) {
160
+ migrationWarned = true
161
+ warn(
162
+ "Migrated .supatype/cloud.json → .supatype/link.json (legacy files kept; remove manually when ready).",
163
+ )
164
+ }
165
+ }
166
+
167
+ export function createSelfHostLink(params: {
168
+ projectRef: string
169
+ apiUrl: string
170
+ token: string
171
+ envName?: string
172
+ existing?: ProjectLink | null
173
+ }): ProjectLink {
174
+ const envName = params.envName ?? "production"
175
+ const now = new Date().toISOString()
176
+ const env: EnvironmentTarget = {
177
+ name: envName,
178
+ apiUrl: params.apiUrl.replace(/\/$/, ""),
179
+ token: params.token,
180
+ linkedAt: now,
181
+ }
182
+
183
+ if (params.existing) {
184
+ return {
185
+ ...params.existing,
186
+ kind: params.existing.kind === "cloud" ? "self-host" : params.existing.kind,
187
+ projectRef: params.projectRef,
188
+ defaultEnvironment: params.existing.defaultEnvironment || envName,
189
+ linkedAt: now,
190
+ environments: {
191
+ ...params.existing.environments,
192
+ [envName]: env,
193
+ },
194
+ }
195
+ }
196
+
197
+ return {
198
+ version: LINK_VERSION,
199
+ kind: "self-host",
200
+ projectRef: params.projectRef,
201
+ defaultEnvironment: envName,
202
+ token: params.token,
203
+ linkedAt: now,
204
+ environments: { [envName]: env },
205
+ }
206
+ }
207
+
208
+ export function createCloudLink(params: {
209
+ projectRef: string
210
+ cloudApiUrl: string
211
+ token: string
212
+ orgId?: string | undefined
213
+ environments?: Array<{ name: string; apiUrl: string }>
214
+ existing?: ProjectLink | null
215
+ }): ProjectLink {
216
+ const now = new Date().toISOString()
217
+ const envMap: Record<string, EnvironmentTarget> = {}
218
+ const envs = params.environments?.length
219
+ ? params.environments
220
+ : [{ name: "production", apiUrl: params.cloudApiUrl }]
221
+
222
+ for (const e of envs) {
223
+ envMap[e.name] = {
224
+ name: e.name,
225
+ apiUrl: e.apiUrl.replace(/\/$/, ""),
226
+ linkedAt: now,
227
+ }
228
+ }
229
+
230
+ return {
231
+ version: LINK_VERSION,
232
+ kind: "cloud",
233
+ projectRef: params.projectRef,
234
+ defaultEnvironment: "production",
235
+ token: params.token,
236
+ cloudApiUrl: params.cloudApiUrl.replace(/\/$/, ""),
237
+ linkedAt: now,
238
+ environments: params.existing
239
+ ? { ...params.existing.environments, ...envMap }
240
+ : envMap,
241
+ ...(params.orgId !== undefined ? { orgId: params.orgId } : {}),
242
+ }
243
+ }