@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
@@ -0,0 +1,48 @@
1
+ import type { Command } from "commander"
2
+ import { writeFileSync } from "node:fs"
3
+ import { loadProjectLink } from "../link.js"
4
+ import { resolveTarget, targetSchemaIntrospect, schemaPgSchema } from "../resolve-target.js"
5
+ import type { DatabaseStateJson } from "../pull-utils.js"
6
+ import { printIntrospectSummary } from "../pull-utils.js"
7
+ import { info, plain } from "../ui/messages.js"
8
+
9
+ export function registerIntrospect(program: Command): void {
10
+ program
11
+ .command("introspect")
12
+ .description("Introspect the live Postgres database (JSON or summary)")
13
+ .option("--connection <url>", "Database connection URL (overrides config)")
14
+ .option("--env <name>", "Target environment when linked")
15
+ .option("--direct", "Use local engine subprocess")
16
+ .option("--json", "Output full DatabaseState JSON")
17
+ .option("--out <path>", "Write JSON output to a file")
18
+ .action(async (opts: {
19
+ connection?: string
20
+ env?: string
21
+ direct?: boolean
22
+ json?: boolean
23
+ out?: string
24
+ }) => {
25
+ const cwd = process.cwd()
26
+ const pgSchema = schemaPgSchema(cwd)
27
+
28
+ const linked = loadProjectLink(cwd)
29
+ const target = linked && !opts.direct && !opts.connection
30
+ ? resolveTarget(cwd, { env: opts.env })
31
+ : resolveTarget(cwd, { env: opts.env, direct: true, connection: opts.connection })
32
+
33
+ const state = (await targetSchemaIntrospect(target, { schema: pgSchema })) as DatabaseStateJson
34
+
35
+ if (opts.out) {
36
+ writeFileSync(opts.out, JSON.stringify(state, null, 2), "utf8")
37
+ info(`Wrote introspection to ${opts.out}`)
38
+ return
39
+ }
40
+
41
+ if (opts.json) {
42
+ plain(JSON.stringify(state, null, 2))
43
+ return
44
+ }
45
+
46
+ printIntrospectSummary(state)
47
+ })
48
+ }
@@ -1,7 +1,8 @@
1
1
  import type { Command } from "commander"
2
- import { readFileSync, existsSync } from "node:fs"
2
+ import { readFileSync, existsSync, writeFileSync } from "node:fs"
3
3
  import { resolve } from "node:path"
4
4
  import { signJwt } from "../jwt.js"
5
+ import { error, plain } from "../ui/messages.js"
5
6
 
6
7
  export function registerKeys(program: Command): void {
7
8
  program
@@ -12,15 +13,13 @@ export function registerKeys(program: Command): void {
12
13
  .action((opts: { secret?: string; expYears: string }) => {
13
14
  const secret = opts.secret ?? resolveSecret()
14
15
  if (!secret) {
15
- console.error(
16
- "Error: JWT_SECRET not found. Set it in .env or pass --secret <value>",
17
- )
16
+ error("JWT_SECRET not found. Set it in .env or pass --secret <value>")
18
17
  process.exit(1)
19
18
  }
20
19
 
21
20
  const expYears = parseInt(opts.expYears, 10)
22
21
  if (isNaN(expYears) || expYears < 1) {
23
- console.error("Error: --exp-years must be a positive integer")
22
+ error("--exp-years must be a positive integer")
24
23
  process.exit(1)
25
24
  }
26
25
 
@@ -30,24 +29,67 @@ export function registerKeys(program: Command): void {
30
29
  const anonKey = signJwt({ iss: "supatype", role: "anon", iat: now, exp }, secret)
31
30
  const serviceKey = signJwt({ iss: "supatype", role: "service_role", iat: now, exp }, secret)
32
31
 
33
- console.log("\nGenerated keys (valid for", expYears, "years):\n")
34
- console.log("ANON_KEY=" + anonKey)
35
- console.log("SERVICE_ROLE_KEY=" + serviceKey)
36
- console.log(
37
- "\nAdd these to your .env file. Do not commit .env to source control.",
38
- )
32
+ plain(`\nGenerated keys (valid for ${expYears} years):\n`)
33
+ plain("ANON_KEY=" + anonKey)
34
+ plain("SERVICE_ROLE_KEY=" + serviceKey)
35
+ plain("\nAdd these to your .env file. Do not commit .env to source control.")
39
36
  })
40
37
  }
41
38
 
42
39
  // ─── Helpers ─────────────────────────────────────────────────────────────────
43
40
 
44
- export function resolveSecret(): string | undefined {
41
+ /** Mint a long-lived anon + service_role JWT pair from a secret. */
42
+ export function signKeyPair(
43
+ secret: string,
44
+ expYears = 10,
45
+ ): { anonKey: string; serviceKey: string } {
46
+ const now = Math.floor(Date.now() / 1000)
47
+ const exp = now + expYears * 365 * 24 * 60 * 60
48
+ return {
49
+ anonKey: signJwt({ iss: "supatype", role: "anon", iat: now, exp }, secret),
50
+ serviceKey: signJwt({ iss: "supatype", role: "service_role", iat: now, exp }, secret),
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Generate keys from the JWT_SECRET found in `dir`'s .env (or env var) and
56
+ * rewrite the ANON_KEY / SERVICE_ROLE_KEY lines in that .env file in place.
57
+ * Returns the minted pair, or null if no secret could be resolved.
58
+ */
59
+ export function generateAndWriteKeys(
60
+ dir: string,
61
+ expYears = 10,
62
+ ): { anonKey: string; serviceKey: string } | null {
63
+ const secret = resolveSecret(dir)
64
+ if (!secret) return null
65
+
66
+ const { anonKey, serviceKey } = signKeyPair(secret, expYears)
67
+
68
+ const envPath = resolve(dir, ".env")
69
+ if (existsSync(envPath)) {
70
+ let content = readFileSync(envPath, "utf8")
71
+ content = upsertEnvVar(content, "ANON_KEY", anonKey)
72
+ content = upsertEnvVar(content, "SERVICE_ROLE_KEY", serviceKey)
73
+ writeFileSync(envPath, content, "utf8")
74
+ }
75
+
76
+ return { anonKey, serviceKey }
77
+ }
78
+
79
+ function upsertEnvVar(content: string, key: string, value: string): string {
80
+ const re = new RegExp(`^${key}=.*$`, "m")
81
+ if (re.test(content)) return content.replace(re, `${key}=${value}`)
82
+ const sep = content.endsWith("\n") || content.length === 0 ? "" : "\n"
83
+ return `${content}${sep}${key}=${value}\n`
84
+ }
85
+
86
+ export function resolveSecret(dir: string = process.cwd()): string | undefined {
45
87
  // 1. Check environment variable
46
88
  const fromEnv = process.env["JWT_SECRET"]
47
89
  if (fromEnv) return fromEnv
48
90
 
49
- // 2. Parse .env file in cwd
50
- const envPath = resolve(process.cwd(), ".env")
91
+ // 2. Parse .env file in the target directory
92
+ const envPath = resolve(dir, ".env")
51
93
  if (!existsSync(envPath)) return undefined
52
94
 
53
95
  try {
@@ -0,0 +1,273 @@
1
+ import type { Command } from "commander"
2
+ import { loadConfig } from "../config.js"
3
+ import {
4
+ createCloudLink,
5
+ createSelfHostLink,
6
+ loadProjectLink,
7
+ saveProjectLink,
8
+ type ProjectLink,
9
+ } from "../link.js"
10
+ import { ensureSupatypeGitignore, warnIfLinkNotGitignored } from "../gitignore.js"
11
+ import { targetFetch } from "../target-client.js"
12
+ import { error, info, plain } from "../ui/messages.js"
13
+ import { nextSteps } from "../ui/next-steps.js"
14
+ import { isInteractive } from "../ui/interactive.js"
15
+ import { ensureNotCancelled, printLogo, clack as p } from "../ui/prompts.js"
16
+
17
+ function resolveLinkToken(opts: {
18
+ token?: string
19
+ serviceRoleKey?: string
20
+ }): string | undefined {
21
+ return (
22
+ opts.token ??
23
+ opts.serviceRoleKey ??
24
+ process.env["SUPATYPE_ACCESS_TOKEN"] ??
25
+ process.env["SUPATYPE_TOKEN"] ??
26
+ process.env["SERVICE_ROLE_KEY"]
27
+ )
28
+ }
29
+
30
+ async function probeSelfHostLink(apiUrl: string, projectRef: string, token: string): Promise<void> {
31
+ await targetFetch(apiUrl, "/platform/v1", {
32
+ method: "GET",
33
+ path: `/projects/${projectRef}/status`,
34
+ token,
35
+ })
36
+ }
37
+
38
+ export function registerEnvs(program: Command): void {
39
+ const envs = program.command("envs").description("Manage linked deployment environments")
40
+
41
+ envs
42
+ .command("list")
43
+ .description("List linked environments")
44
+ .action(() => {
45
+ const cwd = process.cwd()
46
+ const link = loadProjectLink(cwd)
47
+ if (!link) {
48
+ info("Not linked. Run: supatype link")
49
+ return
50
+ }
51
+ plain(`\nProject: ${link.projectRef} (${link.kind})`)
52
+ plain(`Default: ${link.defaultEnvironment}\n`)
53
+ for (const [name, env] of Object.entries(link.environments)) {
54
+ const mark = name === link.defaultEnvironment ? " *" : " "
55
+ plain(`${mark} ${name.padEnd(14)} ${env.apiUrl}`)
56
+ }
57
+ plain()
58
+ })
59
+
60
+ envs
61
+ .command("use <name>")
62
+ .description("Set the default environment")
63
+ .action((name: string) => {
64
+ const cwd = process.cwd()
65
+ const link = loadProjectLink(cwd)
66
+ if (!link?.environments[name]) {
67
+ error(`Environment "${name}" is not linked.`)
68
+ process.exit(1)
69
+ }
70
+ link.defaultEnvironment = name
71
+ saveProjectLink(cwd, link)
72
+ info(`Default environment set to "${name}".`)
73
+ })
74
+
75
+ envs
76
+ .command("create <name>")
77
+ .description("Create a cloud environment (staging/preview)")
78
+ .action(async (name: string) => {
79
+ const cwd = process.cwd()
80
+ const link = loadProjectLink(cwd)
81
+ if (!link || link.kind !== "cloud") {
82
+ error("Cloud link required. Run: supatype link --project <slug>")
83
+ process.exit(1)
84
+ }
85
+ if (!link.token || !link.cloudApiUrl) {
86
+ error("Missing cloud credentials in link.json")
87
+ process.exit(1)
88
+ }
89
+ const bodyName = name === "staging" || name === "preview" ? name : "staging"
90
+ await targetFetch(link.cloudApiUrl, "/api/v1", {
91
+ method: "POST",
92
+ path: `/projects/${link.projectRef}/environments`,
93
+ body: { name: bodyName },
94
+ token: link.token,
95
+ orgId: link.orgId,
96
+ })
97
+ const envsList = await targetFetch<Array<{ name: string; apiUrl: string }>>(
98
+ link.cloudApiUrl,
99
+ "/api/v1",
100
+ {
101
+ method: "GET",
102
+ path: `/projects/${link.projectRef}/environments`,
103
+ token: link.token,
104
+ orgId: link.orgId,
105
+ },
106
+ )
107
+ const updated = createCloudLink({
108
+ projectRef: link.projectRef,
109
+ cloudApiUrl: link.cloudApiUrl,
110
+ token: link.token,
111
+ environments: envsList.map((e) => ({ name: e.name, apiUrl: e.apiUrl })),
112
+ existing: link,
113
+ ...(link.orgId !== undefined ? { orgId: link.orgId } : {}),
114
+ })
115
+ saveProjectLink(cwd, updated)
116
+ info(`Environment "${bodyName}" created.`)
117
+ })
118
+ }
119
+
120
+ export function registerLinkOptions(linkCmd: Command): void {
121
+ linkCmd
122
+ .option("--project <slug>", "Cloud project slug")
123
+ .option("--url <url>", "Self-host or local Kong URL")
124
+ .option("--api-url <url>", "Cloud control plane API URL", "https://api.supatype.com")
125
+ .option("--token <token>", "Access token (cloud PAT or self-host SERVICE_ROLE_KEY)")
126
+ .option("--service-role-key <key>", "Deprecated alias for --token on self-host")
127
+ .option("--env <name>", "Environment name (default: production)", "production")
128
+ .option("--fix-gitignore", "Append .supatype/ to .gitignore if missing")
129
+ }
130
+
131
+ export async function runLinkAction(opts: {
132
+ project?: string
133
+ url?: string
134
+ apiUrl: string
135
+ token?: string
136
+ serviceRoleKey?: string
137
+ env?: string
138
+ fixGitignore?: boolean
139
+ }): Promise<void> {
140
+ const cwd = process.cwd()
141
+ const config = loadConfig(cwd)
142
+ const projectRef = config.project?.name ?? "project"
143
+ const envName = opts.env ?? "production"
144
+ let project = opts.project
145
+ let url = opts.url
146
+
147
+ if (isInteractive() && !project && !url) {
148
+ printLogo()
149
+ p.intro("Link this project")
150
+ const targetKind = ensureNotCancelled(
151
+ await p.select<"cloud" | "self-host">({
152
+ message: "Link target",
153
+ options: [
154
+ { value: "cloud", label: "Supatype Cloud", hint: "managed project on supatype.com" },
155
+ { value: "self-host", label: "Self-host", hint: "your Kong gateway URL" },
156
+ ],
157
+ }),
158
+ )
159
+ if (targetKind === "cloud") {
160
+ project = ensureNotCancelled(
161
+ await p.text({
162
+ message: "Cloud project slug",
163
+ placeholder: projectRef,
164
+ defaultValue: projectRef,
165
+ }),
166
+ ).trim()
167
+ } else {
168
+ url = ensureNotCancelled(
169
+ await p.text({
170
+ message: "Kong gateway URL",
171
+ placeholder: "https://api.example.com",
172
+ defaultValue: "http://localhost:18473",
173
+ }),
174
+ ).trim()
175
+ }
176
+ p.outro("Linking...")
177
+ }
178
+
179
+ const token = resolveLinkToken(opts)
180
+
181
+ if (opts.fixGitignore) {
182
+ ensureSupatypeGitignore(cwd)
183
+ } else {
184
+ warnIfLinkNotGitignored(cwd)
185
+ }
186
+
187
+ const existing = loadProjectLink(cwd)
188
+
189
+ if (url) {
190
+ if (!token) {
191
+ error("Authentication required. Pass --token $SERVICE_ROLE_KEY")
192
+ process.exit(1)
193
+ }
194
+ const apiUrl = url.replace(/\/$/, "")
195
+ await probeSelfHostLink(apiUrl, projectRef, token)
196
+ const link = createSelfHostLink({
197
+ projectRef,
198
+ apiUrl,
199
+ token,
200
+ envName,
201
+ existing,
202
+ })
203
+ saveProjectLink(cwd, link)
204
+ info(`Linked to self-host environment "${envName}" at ${apiUrl}`)
205
+ nextSteps("Next steps:", [
206
+ "supatype push --env " + envName,
207
+ "supatype deploy",
208
+ ])
209
+ return
210
+ }
211
+
212
+ if (!token) {
213
+ error("Authentication required. Set SUPATYPE_ACCESS_TOKEN or pass --token.")
214
+ process.exit(1)
215
+ }
216
+
217
+ const cloudApiUrl = opts.apiUrl.replace(/\/$/, "")
218
+
219
+ if (project) {
220
+ const one = await targetFetch<{ slug: string; orgId: string }>(cloudApiUrl, "/api/v1", {
221
+ method: "GET",
222
+ path: `/projects/${project}`,
223
+ token,
224
+ })
225
+ let environments: Array<{ name: string; apiUrl: string }> = [
226
+ { name: "production", apiUrl: cloudApiUrl },
227
+ ]
228
+ try {
229
+ const listed = await targetFetch<Array<{ name: string; apiUrl: string }>>(
230
+ cloudApiUrl,
231
+ "/api/v1",
232
+ {
233
+ method: "GET",
234
+ path: `/projects/${project}/environments`,
235
+ token,
236
+ orgId: one.orgId,
237
+ },
238
+ )
239
+ if (listed.length > 0) {
240
+ environments = listed.map((e) => ({ name: e.name, apiUrl: e.apiUrl }))
241
+ }
242
+ } catch {
243
+ // environments optional on older control planes
244
+ }
245
+ const link = createCloudLink({
246
+ projectRef: project,
247
+ cloudApiUrl,
248
+ token,
249
+ orgId: one.orgId,
250
+ environments,
251
+ existing,
252
+ })
253
+ saveProjectLink(cwd, link)
254
+ info(`Linked to cloud project: ${project}`)
255
+ nextSteps("Next steps:", [
256
+ "supatype push --env production",
257
+ "supatype deploy",
258
+ ])
259
+ return
260
+ }
261
+
262
+ error("Specify --project <slug> for cloud or --url <kong-url> for self-host.")
263
+ process.exit(1)
264
+ }
265
+
266
+ export function getLinkOrExit(cwd: string): ProjectLink {
267
+ const link = loadProjectLink(cwd)
268
+ if (!link) {
269
+ error("Not linked. Run: supatype link")
270
+ process.exit(1)
271
+ }
272
+ return link
273
+ }
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import type { Command } from "commander"
5
5
  import { spawn } from "node:child_process"
6
+ import { error } from "../ui/messages.js"
6
7
 
7
8
  const SERVICES = ["postgres", "postgrest", "gotrue", "kong", "minio", "realtime", "studio"]
8
9
 
@@ -19,8 +20,8 @@ export function registerLogs(program: Command): void {
19
20
  : SERVICES.map((s) => `supatype-${s}`)
20
21
 
21
22
  if (opts.service && !SERVICES.includes(opts.service)) {
22
- console.error(`Unknown service: ${opts.service}`)
23
- console.error(`Available: ${SERVICES.join(", ")}`)
23
+ error(`Unknown service: ${opts.service}`)
24
+ error(`Available: ${SERVICES.join(", ")}`)
24
25
  process.exit(1)
25
26
  }
26
27
 
@@ -39,7 +40,7 @@ export function registerLogs(program: Command): void {
39
40
 
40
41
  const child = spawn("docker", containerArgs, { stdio: "inherit" })
41
42
  child.on("error", () => {
42
- console.error("Docker not found. Ensure Docker is installed and running.")
43
+ error("Docker not found. Ensure Docker is installed and running.")
43
44
  process.exit(1)
44
45
  })
45
46
  return
@@ -51,7 +52,7 @@ export function registerLogs(program: Command): void {
51
52
  cwd: process.cwd(),
52
53
  })
53
54
  child.on("error", () => {
54
- console.error("Docker not found. Ensure Docker is installed and running.")
55
+ error("Docker not found. Ensure Docker is installed and running.")
55
56
  process.exit(1)
56
57
  })
57
58
  })
@@ -4,6 +4,7 @@ import { basename, dirname, extname, join, resolve } from "node:path"
4
4
  import ts from "typescript"
5
5
  import { loadConfig } from "../config.js"
6
6
  import { schemaPathFromProject } from "../project-config.js"
7
+ import { info } from "../ui/messages.js"
7
8
 
8
9
  export function registerMigrateFromV1(program: Command): void {
9
10
  program
@@ -29,9 +30,9 @@ export function registerMigrateFromV1(program: Command): void {
29
30
  : join(dirname(schemaPath), basename(schemaPath).replace(extname(schemaPath), ".v2.ts"))
30
31
 
31
32
  writeFileSync(outPath, output, "utf8")
32
- console.log(`v2 schema written to ${outPath}`)
33
+ info(`v2 schema written to ${outPath}`)
33
34
  if (!opts.write) {
34
- console.log("Review TODO comments and replace unknown mappings before using this file in production.")
35
+ info("Review TODO comments and replace unknown mappings before using this file in production.")
35
36
  }
36
37
  })
37
38
  }