@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
@@ -1,11 +1,73 @@
1
1
  import type { Command } from "commander"
2
- import { createInterface } from "node:readline"
2
+ import { join } from "node:path"
3
3
  import { loadConfig, loadSchemaAst } from "../config.js"
4
- import { connectionString, schemaPathFromProject } from "../project-config.js"
4
+ import { connectionString, projectRootFromConfig, schemaPathFromProject } from "../project-config.js"
5
5
  import { ensureEngine, engineRequest } from "../engine-client.js"
6
+ import { loadProjectLink } from "../link.js"
7
+ import {
8
+ resolveTarget,
9
+ targetSchemaDiff,
10
+ targetSchemaRollback,
11
+ targetListMigrations,
12
+ schemaPgSchema,
13
+ type SchemaRollbackResult,
14
+ } from "../resolve-target.js"
15
+ import {
16
+ restoreSchemaSourcesFromGz,
17
+ findOrphanSchemaFiles,
18
+ type SchemaSourcesManifest,
19
+ } from "../schema-sources.js"
20
+ import { confirm } from "../ui/confirm.js"
21
+ import { info, plain, warn } from "../ui/messages.js"
6
22
 
7
23
  export function registerMigrate(program: Command): void {
8
- // migrate apply all pending migrations
24
+ const migrations = program
25
+ .command("migrations")
26
+ .description("Migration history utilities")
27
+
28
+ migrations
29
+ .command("list")
30
+ .description("List applied migrations with schema snapshot metadata")
31
+ .option("--connection <url>", "Database connection URL (overrides config)")
32
+ .option("--env <name>", "Target environment when linked")
33
+ .option("--direct", "Use local engine subprocess (skip control plane)")
34
+ .action(async (opts: { connection?: string; env?: string; direct?: boolean }) => {
35
+ const cwd = process.cwd()
36
+ const link = loadProjectLink(cwd)
37
+ const useDirect = opts.direct || Boolean(opts.connection)
38
+
39
+ let target
40
+ if (link && !useDirect && !opts.connection) {
41
+ target = resolveTarget(cwd, { env: opts.env })
42
+ } else {
43
+ target = resolveTarget(cwd, {
44
+ env: opts.env,
45
+ direct: true,
46
+ connection: opts.connection,
47
+ })
48
+ }
49
+
50
+ const list = await targetListMigrations(target)
51
+ if (list.length === 0) {
52
+ info("No migrations applied.")
53
+ return
54
+ }
55
+
56
+ for (const m of list) {
57
+ const manifest = m.schemaSourcesManifest
58
+ const size =
59
+ manifest?.compressedBytes !== undefined
60
+ ? `${(manifest.compressedBytes / 1024).toFixed(1)} KB`
61
+ : "—"
62
+ const files = manifest?.fileCount ?? "—"
63
+ const author = manifest?.pushedBy ?? "—"
64
+ const rolled = m.rolledBack ? " (rolled back)" : ""
65
+ plain(
66
+ `${m.name}${rolled}\n applied: ${m.appliedAt} status: ${m.status}\n author: ${author} files: ${files} snapshot: ${size}`,
67
+ )
68
+ }
69
+ })
70
+
9
71
  program
10
72
  .command("migrate")
11
73
  .description("Apply pending migrations from the migration history")
@@ -20,28 +82,49 @@ export function registerMigrate(program: Command): void {
20
82
  schema: "public",
21
83
  action: "pending",
22
84
  })
23
- console.log(result.message ?? "Migrations applied.")
85
+ info(result.message ?? "Migrations applied.")
24
86
  })
25
87
 
26
- // rollback — undo the last applied migration
27
88
  program
28
89
  .command("rollback")
29
90
  .description("Roll back the last applied migration")
30
91
  .option("--connection <url>", "Database connection URL (overrides config)")
31
- .action(async (opts: { connection?: string }) => {
32
- const config = loadConfig()
33
- const connection = opts.connection ?? connectionString(config)
92
+ .option("--env <name>", "Target environment when linked")
93
+ .option("--direct", "Use local engine subprocess (skip control plane)")
94
+ .option("--sync-schema", "Restore schema source files from DB snapshot without prompting")
95
+ .option("--no-sync-schema", "Revert database only; do not restore schema files")
96
+ .action(async (opts: {
97
+ connection?: string
98
+ env?: string
99
+ direct?: boolean
100
+ syncSchema?: boolean
101
+ noSyncSchema?: boolean
102
+ }) => {
103
+ const cwd = process.cwd()
104
+ const config = loadConfig(cwd)
105
+ const pgSchema = schemaPgSchema(cwd)
106
+ const link = loadProjectLink(cwd)
107
+ const useDirect = opts.direct || Boolean(opts.connection)
34
108
 
35
- await ensureEngine()
36
- const result = await engineRequest<{ message?: string }>("/migrations", {
37
- database_url: connection,
38
- schema: "public",
39
- action: "rollback",
40
- })
41
- console.log(result.message ?? "Rolled back.")
109
+ let target
110
+ if (link && !useDirect && !opts.connection) {
111
+ target = resolveTarget(cwd, { env: opts.env })
112
+ } else {
113
+ target = resolveTarget(cwd, {
114
+ env: opts.env,
115
+ direct: true,
116
+ connection: opts.connection,
117
+ })
118
+ }
119
+
120
+ const result = await targetSchemaRollback(target, { schema: pgSchema })
121
+ info(result.message ?? "Rolled back.")
122
+
123
+ if (!opts.noSyncSchema) {
124
+ await offerSchemaRestore(cwd, config, target, result, pgSchema, opts.syncSchema ?? false)
125
+ }
42
126
  })
43
127
 
44
- // reset — drop all tables and re-apply from scratch
45
128
  program
46
129
  .command("reset")
47
130
  .description(
@@ -52,10 +135,11 @@ export function registerMigrate(program: Command): void {
52
135
  .action(async (opts: { yes?: boolean; connection?: string }) => {
53
136
  if (!opts.yes) {
54
137
  const confirmed = await confirm(
55
- "This will DROP all managed tables and re-apply the schema. Proceed? [y/N] ",
138
+ "This will DROP all managed tables and re-apply the schema. Proceed?",
139
+ { default: false },
56
140
  )
57
141
  if (!confirmed) {
58
- console.log("Aborted.")
142
+ plain("Aborted.")
59
143
  return
60
144
  }
61
145
  }
@@ -72,16 +156,72 @@ export function registerMigrate(program: Command): void {
72
156
  schema: "public",
73
157
  force: true,
74
158
  })
75
- console.log(result.message ?? "Reset complete.")
159
+ info(result.message ?? "Reset complete.")
76
160
  })
77
161
  }
78
162
 
79
- async function confirm(prompt: string): Promise<boolean> {
80
- const rl = createInterface({ input: process.stdin, output: process.stdout })
81
- return new Promise((resolve) => {
82
- rl.question(prompt, (answer) => {
83
- rl.close()
84
- resolve(answer.toLowerCase() === "y")
85
- })
86
- })
163
+ async function offerSchemaRestore(
164
+ cwd: string,
165
+ config: ReturnType<typeof loadConfig>,
166
+ target: ReturnType<typeof resolveTarget>,
167
+ result: SchemaRollbackResult,
168
+ pgSchema: string,
169
+ autoSync: boolean,
170
+ ): Promise<void> {
171
+ const manifest = result.schemaSourcesManifest as SchemaSourcesManifest | undefined
172
+ const gzB64 = result.schemaSourcesBase64
173
+
174
+ if (!gzB64 || !manifest) {
175
+ warn(
176
+ "No schema source snapshot on the restored migration (legacy push). Run `supatype pull` to draft from DB if needed.",
177
+ )
178
+ return
179
+ }
180
+
181
+ const ast = loadSchemaAst(schemaPathFromProject(config, cwd), cwd)
182
+ const diff = await targetSchemaDiff(target, ast, { schema: pgSchema })
183
+ const drift = (diff.operations ?? []).length > 0
184
+
185
+ if (!drift && !autoSync) {
186
+ info("Schema files match reverted database (no restore needed).")
187
+ return
188
+ }
189
+
190
+ const fileList = manifest.files.map((f) => f.path).join(", ")
191
+ const sizeKb = (manifest.compressedBytes / 1024).toFixed(1)
192
+ const label = result.restoredMigrationName ?? result.name
193
+
194
+ let proceed = autoSync
195
+ if (!proceed) {
196
+ proceed = await confirm(
197
+ `Restore ${manifest.fileCount} schema files from database snapshot (${sizeKb} KB)?\n ${fileList}`,
198
+ { default: true },
199
+ )
200
+ }
201
+
202
+ if (!proceed) {
203
+ info("Skipped schema file restore. Run `supatype diff` to review drift.")
204
+ return
205
+ }
206
+
207
+ const root = projectRootFromConfig(config, cwd)
208
+ const backupDir = join(cwd, ".supatype", "schema-backups", `${Date.now()}`)
209
+ const gz = Buffer.from(gzB64, "base64")
210
+ restoreSchemaSourcesFromGz(gz, manifest, root, { backupDir })
211
+
212
+ const manifestPaths = new Set(manifest.files.map((f) => f.path))
213
+ const orphans = findOrphanSchemaFiles(root, manifest.entryPoint, manifestPaths)
214
+ for (const orphan of orphans) {
215
+ warn(`${orphan} not in snapshot — review manually`)
216
+ }
217
+
218
+ info(`Restored schema files from migration ${label}.`)
219
+ info(`Backup saved to ${backupDir}`)
220
+
221
+ const postDiff = await targetSchemaDiff(target, ast, { schema: pgSchema })
222
+ if ((postDiff.operations ?? []).length === 0) {
223
+ info("Schema matches database after restore.")
224
+ } else {
225
+ info("Run `supatype diff` — schema may still differ from database.")
226
+ }
87
227
  }
@@ -11,6 +11,8 @@ import { homedir } from "node:os"
11
11
  import { join } from "node:path"
12
12
  import { loadConfig } from "../config.js"
13
13
  import { resolveBinary } from "../binary-cache.js"
14
+ import { confirm } from "../ui/confirm.js"
15
+ import { info, plain } from "../ui/messages.js"
14
16
  import {
15
17
  initdb,
16
18
  start as pgStart,
@@ -32,9 +34,7 @@ export function registerPg(program: Command): void {
32
34
  initdb(opts)
33
35
  pgStart(opts)
34
36
  await waitReady(opts, 10_000)
35
- console.log(
36
- `[supatype] Postgres started on port ${opts.port} (data: ${opts.dataDir})`,
37
- )
37
+ info(`Postgres started on port ${opts.port} (data: ${opts.dataDir})`)
38
38
  })
39
39
 
40
40
  // ── stop ─────────────────────────────────────────────────────────────────
@@ -44,7 +44,7 @@ export function registerPg(program: Command): void {
44
44
  const config = loadConfig()
45
45
  const opts = await pgOpts(config)
46
46
  pgStop(opts)
47
- console.log("[supatype] Postgres stopped.")
47
+ info("Postgres stopped.")
48
48
  })
49
49
 
50
50
  // ── reset ─────────────────────────────────────────────────────────────────
@@ -56,17 +56,12 @@ export function registerPg(program: Command): void {
56
56
  const pgOpts_ = await pgOpts(config)
57
57
 
58
58
  if (!opts.force) {
59
- const readline = await import("node:readline")
60
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
61
- const answer = await new Promise<string>((resolve) =>
62
- rl.question(
63
- `This will DELETE all data in ${pgOpts_.dataDir}. Continue? [y/N] `,
64
- resolve,
65
- ),
59
+ const ok = await confirm(
60
+ `This will DELETE all data in ${pgOpts_.dataDir}. Continue?`,
61
+ { default: false },
66
62
  )
67
- rl.close()
68
- if (answer.toLowerCase() !== "y") {
69
- console.log("Aborted.")
63
+ if (!ok) {
64
+ plain("Aborted.")
70
65
  return
71
66
  }
72
67
  }
@@ -74,13 +69,13 @@ export function registerPg(program: Command): void {
74
69
  pgStop(pgOpts_)
75
70
  if (existsSync(pgOpts_.dataDir)) {
76
71
  rmSync(pgOpts_.dataDir, { recursive: true, force: true })
77
- console.log(`[supatype] Data directory removed: ${pgOpts_.dataDir}`)
72
+ info(`Data directory removed: ${pgOpts_.dataDir}`)
78
73
  }
79
74
  mkdirSync(pgOpts_.dataDir, { recursive: true })
80
75
  initdb(pgOpts_)
81
76
  pgStart(pgOpts_)
82
77
  await waitReady(pgOpts_, 10_000)
83
- console.log("[supatype] Postgres reset and started.")
78
+ info("Postgres reset and started.")
84
79
  })
85
80
 
86
81
  // ── psql ─────────────────────────────────────────────────────────────────
@@ -118,9 +113,9 @@ async function pgOpts(
118
113
  const pgCacheDir = await (async () => {
119
114
  const override = config.overrides?.postgres_dir
120
115
  if (override) return join(override, "bin")
121
- const { cachePath, currentPlatform } = await import("../binary-cache.js")
116
+ const { cachePath, currentPlatform, resolveVersionFor } = await import("../binary-cache.js")
122
117
  const platform = currentPlatform()
123
- const version = config.versions.postgres
118
+ const version = await resolveVersionFor("postgres", config)
124
119
  return join(cachePath("postgres", version), `pg-${version}`, "bin")
125
120
  })()
126
121
 
@@ -2,6 +2,8 @@ import type { Command } from "commander"
2
2
  import { existsSync, readFileSync, mkdirSync, writeFileSync } from "node:fs"
3
3
  import { resolve, join } from "node:path"
4
4
  import { spawnSync } from "node:child_process"
5
+ import { error, info, plain, warn } from "../ui/messages.js"
6
+ import { nextSteps } from "../ui/next-steps.js"
5
7
 
6
8
  // ─── Registration ────────────────────────────────────────────────────────────
7
9
 
@@ -61,27 +63,30 @@ function listPlugins(cwd: string): void {
61
63
  const plugins = discoverInstalledPlugins(cwd)
62
64
 
63
65
  if (plugins.length === 0) {
64
- console.log("No Supatype plugins installed.")
65
- console.log("\nSearch for plugins: npx supatype plugins search <query>")
66
- console.log("Create a plugin: npx supatype plugins create")
66
+ info("No Supatype plugins installed.")
67
+ nextSteps("Try:", [
68
+ "Search for plugins: npx supatype plugins search <query>",
69
+ "Create a plugin: npx supatype plugins create",
70
+ ])
67
71
  return
68
72
  }
69
73
 
70
- console.log("Installed plugins:\n")
71
- console.log(` ${"Name".padEnd(35)} ${"Type".padEnd(14)} ${"Version".padEnd(12)} Status`)
72
- console.log(` ${"─".repeat(35)} ${"─".repeat(14)} ${"─".repeat(12)} ${"─".repeat(15)}`)
74
+ plain("Installed plugins:\n")
75
+ plain(` ${"Name".padEnd(35)} ${"Type".padEnd(14)} ${"Version".padEnd(12)} Status`)
76
+ plain(` ${"─".repeat(35)} ${"─".repeat(14)} ${"─".repeat(12)} ${"─".repeat(15)}`)
73
77
 
74
78
  for (const p of plugins) {
75
79
  const types = p.supatype?.types?.join(", ") ?? "unknown"
76
80
  const status = p.compatible ? "active" : "incompatible"
77
- console.log(` ${p.name.padEnd(35)} ${types.padEnd(14)} ${p.version.padEnd(12)} ${status}`)
81
+ plain(` ${p.name.padEnd(35)} ${types.padEnd(14)} ${p.version.padEnd(12)} ${status}`)
78
82
  }
79
83
  }
80
84
 
81
85
  // ─── Search ──────────────────────────────────────────────────────────────────
82
86
 
83
87
  async function searchPlugins(query: string): Promise<void> {
84
- console.log(`Searching npm for "${query}" supatype plugins...\n`)
88
+ info(`Searching npm for "${query}" supatype plugins...`)
89
+ plain()
85
90
 
86
91
  try {
87
92
  const searchUrl = `https://registry.npmjs.org/-/v1/search?text=supatype-plugin+${encodeURIComponent(query)}&size=20`
@@ -90,7 +95,7 @@ async function searchPlugins(query: string): Promise<void> {
90
95
  })
91
96
 
92
97
  if (!res.ok) {
93
- console.error(`Search failed: ${res.statusText}`)
98
+ error(`Search failed: ${res.statusText}`)
94
99
  return
95
100
  }
96
101
 
@@ -107,31 +112,33 @@ async function searchPlugins(query: string): Promise<void> {
107
112
  }
108
113
 
109
114
  if (data.objects.length === 0) {
110
- console.log("No plugins found.")
111
- console.log("\nTry a different search term, or create your own plugin:")
112
- console.log(" npx supatype plugins create")
115
+ info("No plugins found.")
116
+ nextSteps("Try:", [
117
+ "Try a different search term, or create your own plugin:",
118
+ " npx supatype plugins create",
119
+ ])
113
120
  return
114
121
  }
115
122
 
116
- console.log(` ${"Package".padEnd(40)} ${"Version".padEnd(12)} Description`)
117
- console.log(` ${"─".repeat(40)} ${"─".repeat(12)} ${"─".repeat(40)}`)
123
+ plain(` ${"Package".padEnd(40)} ${"Version".padEnd(12)} Description`)
124
+ plain(` ${"─".repeat(40)} ${"─".repeat(12)} ${"─".repeat(40)}`)
118
125
 
119
126
  for (const obj of data.objects) {
120
127
  const pkg = obj.package
121
128
  const desc = (pkg.description ?? "").slice(0, 50)
122
- console.log(` ${pkg.name.padEnd(40)} ${pkg.version.padEnd(12)} ${desc}`)
129
+ plain(` ${pkg.name.padEnd(40)} ${pkg.version.padEnd(12)} ${desc}`)
123
130
  }
124
131
 
125
- console.log(`\nInstall: npx supatype plugins add <package-name>`)
132
+ info("Install: npx supatype plugins add <package-name>")
126
133
  } catch (err) {
127
- console.error(`Error: ${err instanceof Error ? err.message : "unknown"}`)
134
+ error(`Error: ${err instanceof Error ? err.message : "unknown"}`)
128
135
  }
129
136
  }
130
137
 
131
138
  // ─── Add ─────────────────────────────────────────────────────────────────────
132
139
 
133
140
  function addPlugin(cwd: string, pkg: string): void {
134
- console.log(`Installing ${pkg}...`)
141
+ info(`Installing ${pkg}...`)
135
142
 
136
143
  // Detect package manager
137
144
  const pm = detectPackageManager(cwd)
@@ -145,7 +152,7 @@ function addPlugin(cwd: string, pkg: string): void {
145
152
  })
146
153
 
147
154
  if (result.status !== 0) {
148
- console.error(`Failed to install ${pkg}`)
155
+ error(`Failed to install ${pkg}`)
149
156
  process.exit(1)
150
157
  }
151
158
 
@@ -158,14 +165,14 @@ function addPlugin(cwd: string, pkg: string): void {
158
165
  if (supatype?.["pluginApi"] !== undefined) {
159
166
  const pluginApi = supatype["pluginApi"] as number
160
167
  if (pluginApi !== 1) {
161
- console.warn(`\nWarning: ${pkg} targets plugin API v${pluginApi}, current is v1.`)
162
- console.warn("The plugin may not work correctly.")
168
+ warn(`${pkg} targets plugin API v${pluginApi}, current is v1.`)
169
+ warn("The plugin may not work correctly.")
163
170
  }
164
171
  }
165
172
  }
166
173
 
167
- console.log(`\n${pkg} installed and registered.`)
168
- console.log("Run 'npx supatype plugins list' to see active plugins.")
174
+ info(`${pkg} installed and registered.`)
175
+ info("Run 'npx supatype plugins list' to see active plugins.")
169
176
  }
170
177
 
171
178
  // ─── Remove ──────────────────────────────────────────────────────────────────
@@ -177,12 +184,13 @@ function removePlugin(cwd: string, pkg: string): void {
177
184
  for (const file of schemaFiles) {
178
185
  const content = readFileSync(file, "utf8")
179
186
  if (content.includes(pkg)) {
180
- console.warn(`Warning: ${pkg} appears to be referenced in ${file}`)
181
- console.warn("Removing it may break your schema. Proceed with caution.\n")
187
+ warn(`${pkg} appears to be referenced in ${file}`)
188
+ warn("Removing it may break your schema. Proceed with caution.")
189
+ plain()
182
190
  }
183
191
  }
184
192
 
185
- console.log(`Removing ${pkg}...`)
193
+ info(`Removing ${pkg}...`)
186
194
 
187
195
  const pm = detectPackageManager(cwd)
188
196
  const removeCmd = pm === "pnpm" ? ["pnpm", "remove", pkg]
@@ -195,11 +203,11 @@ function removePlugin(cwd: string, pkg: string): void {
195
203
  })
196
204
 
197
205
  if (result.status !== 0) {
198
- console.error(`Failed to remove ${pkg}`)
206
+ error(`Failed to remove ${pkg}`)
199
207
  process.exit(1)
200
208
  }
201
209
 
202
- console.log(`${pkg} removed.`)
210
+ info(`${pkg} removed.`)
203
211
  }
204
212
 
205
213
  // ─── Create ──────────────────────────────────────────────────────────────────
@@ -207,7 +215,7 @@ function removePlugin(cwd: string, pkg: string): void {
207
215
  function createPlugin(cwd: string, opts: { type: string; name?: string }): void {
208
216
  const validTypes = ["field", "composite", "provider", "widget"]
209
217
  if (!validTypes.includes(opts.type)) {
210
- console.error(`Invalid plugin type "${opts.type}". Must be one of: ${validTypes.join(", ")}`)
218
+ error(`Invalid plugin type "${opts.type}". Must be one of: ${validTypes.join(", ")}`)
211
219
  process.exit(1)
212
220
  }
213
221
 
@@ -215,7 +223,7 @@ function createPlugin(cwd: string, opts: { type: string; name?: string }): void
215
223
  const pluginDir = resolve(cwd, name)
216
224
 
217
225
  if (existsSync(pluginDir)) {
218
- console.error(`Directory "${name}" already exists.`)
226
+ error(`Directory "${name}" already exists.`)
219
227
  process.exit(1)
220
228
  }
221
229
 
@@ -273,16 +281,17 @@ function createPlugin(cwd: string, opts: { type: string; name?: string }): void
273
281
  const sourceContent = generatePluginTemplate(opts.type, name)
274
282
  writeFileSync(join(pluginDir, "src/index.ts"), sourceContent, "utf8")
275
283
 
276
- console.log(`\nCreated plugin project: ${name}/\n`)
277
- console.log(" Files:")
278
- console.log(` ${name}/package.json`)
279
- console.log(` ${name}/tsconfig.json`)
280
- console.log(` ${name}/src/index.ts`)
281
- console.log(`\n Next steps:`)
282
- console.log(` cd ${name}`)
283
- console.log(` npm install`)
284
- console.log(` npm run build`)
285
- console.log(` npx supatype plugins validate`)
284
+ info(`Created plugin project: ${name}/`)
285
+ plain("\n Files:")
286
+ plain(` ${name}/package.json`)
287
+ plain(` ${name}/tsconfig.json`)
288
+ plain(` ${name}/src/index.ts`)
289
+ nextSteps("Next steps:", [
290
+ `cd ${name}`,
291
+ "npm install",
292
+ "npm run build",
293
+ "npx supatype plugins validate",
294
+ ])
286
295
  }
287
296
 
288
297
  function generatePluginTemplate(type: string, name: string): string {
@@ -375,7 +384,7 @@ function validatePlugins(cwd: string): void {
375
384
  const plugins = discoverInstalledPlugins(cwd)
376
385
 
377
386
  if (plugins.length === 0) {
378
- console.log("No plugins to validate.")
387
+ info("No plugins to validate.")
379
388
  return
380
389
  }
381
390
 
@@ -398,21 +407,21 @@ function validatePlugins(cwd: string): void {
398
407
  }
399
408
 
400
409
  if (issues.length === 0) {
401
- console.log(` ✓ ${p.name} — valid`)
410
+ plain(` ✓ ${p.name} — valid`)
402
411
  } else {
403
412
  hasErrors = true
404
- console.log(` ✗ ${p.name}`)
413
+ plain(` ✗ ${p.name}`)
405
414
  for (const issue of issues) {
406
- console.log(` - ${issue}`)
415
+ plain(` - ${issue}`)
407
416
  }
408
417
  }
409
418
  }
410
419
 
411
420
  if (hasErrors) {
412
- console.log("\nSome plugins have issues. Fix them before deploying.")
421
+ error("Some plugins have issues. Fix them before deploying.")
413
422
  process.exit(1)
414
423
  } else {
415
- console.log("\nAll plugins are valid.")
424
+ info("All plugins are valid.")
416
425
  }
417
426
  }
418
427
 
@@ -1,17 +1,46 @@
1
1
  import type { Command } from "commander"
2
- import { ensureEngine } from "../engine-client.js"
2
+ import { writeFileSync } from "node:fs"
3
+ import { loadConfig } from "../config.js"
4
+ import { schemaPathFromProject } from "../project-config.js"
5
+ import { ensureEngine, engineRequest } from "../engine-client.js"
6
+ import { resolveHostEngineDatabaseUrl } from "../dev-compose.js"
7
+ import { databaseStateToSchemaScaffold, type DatabaseStateJson } from "../pull-utils.js"
8
+ import { info, plain } from "../ui/messages.js"
3
9
 
4
10
  export function registerPull(program: Command): void {
5
11
  program
6
12
  .command("pull")
7
- .description(
8
- "Introspect an existing Postgres database (deprecated in type-first mode)",
9
- )
10
- .action(async () => {
13
+ .description("Scaffold schema/index.ts from live database introspection (draft — review before push)")
14
+ .option("--connection <url>", "Database connection URL (overrides config)")
15
+ .option("--out <path>", "Write scaffold to file (default: stdout)")
16
+ .option("--dry-run", "Print scaffold to stdout without writing files")
17
+ .action(async (opts: { connection?: string; out?: string; dryRun?: boolean }) => {
18
+ const cwd = process.cwd()
19
+ const config = loadConfig(cwd)
20
+ const connection = await resolveHostEngineDatabaseUrl(cwd, config, opts.connection)
21
+ const pgSchema = config.schema?.pg_schema ?? "public"
22
+
11
23
  await ensureEngine()
12
- throw new Error(
13
- "The legacy `supatype pull` schema generator has been removed.\n" +
14
- "Use type-based models with @supatype/types and run `supatype generate`.",
15
- )
24
+
25
+ info("Introspecting database...")
26
+ const state = await engineRequest<DatabaseStateJson>("/introspect", {
27
+ database_url: connection,
28
+ schema: pgSchema,
29
+ })
30
+
31
+ const scaffold = databaseStateToSchemaScaffold(state)
32
+ const defaultOut = schemaPathFromProject(config, cwd)
33
+
34
+ if (opts.dryRun || !opts.out) {
35
+ plain(scaffold)
36
+ if (!opts.dryRun && !opts.out) {
37
+ info("(draft printed to stdout — use --out to write a file)")
38
+ }
39
+ return
40
+ }
41
+
42
+ writeFileSync(opts.out ?? defaultOut, scaffold, "utf8")
43
+ info(`Wrote draft schema to ${opts.out ?? defaultOut}`)
44
+ info("Review access rules and relations, then run `supatype generate`.")
16
45
  })
17
46
  }