@supatype/cli 0.1.0-alpha.6 → 0.1.0-alpha.8

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 (350) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +208 -1
  3. package/.turbo/turbo-typecheck.log +1 -1
  4. package/dist/app/proxy-dev-app.d.ts +13 -0
  5. package/dist/app/proxy-dev-app.d.ts.map +1 -0
  6. package/dist/app/proxy-dev-app.js +53 -0
  7. package/dist/app/proxy-dev-app.js.map +1 -0
  8. package/dist/app-config.d.ts +7 -0
  9. package/dist/app-config.d.ts.map +1 -0
  10. package/dist/app-config.js +113 -0
  11. package/dist/app-config.js.map +1 -0
  12. package/dist/augmentation-generator.d.ts +2 -0
  13. package/dist/augmentation-generator.d.ts.map +1 -0
  14. package/dist/augmentation-generator.js +111 -0
  15. package/dist/augmentation-generator.js.map +1 -0
  16. package/dist/binary-cache.d.ts +94 -0
  17. package/dist/binary-cache.d.ts.map +1 -0
  18. package/dist/binary-cache.js +669 -0
  19. package/dist/binary-cache.js.map +1 -0
  20. package/dist/cli.d.ts.map +1 -1
  21. package/dist/cli.js +13 -7
  22. package/dist/cli.js.map +1 -1
  23. package/dist/commands/admin.d.ts.map +1 -1
  24. package/dist/commands/admin.js +4 -3
  25. package/dist/commands/admin.js.map +1 -1
  26. package/dist/commands/app.d.ts.map +1 -1
  27. package/dist/commands/app.js +56 -209
  28. package/dist/commands/app.js.map +1 -1
  29. package/dist/commands/cache.d.ts +6 -0
  30. package/dist/commands/cache.d.ts.map +1 -0
  31. package/dist/commands/cache.js +105 -0
  32. package/dist/commands/cache.js.map +1 -0
  33. package/dist/commands/cloud.d.ts +20 -0
  34. package/dist/commands/cloud.d.ts.map +1 -1
  35. package/dist/commands/cloud.js +50 -52
  36. package/dist/commands/cloud.js.map +1 -1
  37. package/dist/commands/db.d.ts.map +1 -1
  38. package/dist/commands/db.js +47 -54
  39. package/dist/commands/db.js.map +1 -1
  40. package/dist/commands/deploy.d.ts +2 -1
  41. package/dist/commands/deploy.d.ts.map +1 -1
  42. package/dist/commands/deploy.js +79 -52
  43. package/dist/commands/deploy.js.map +1 -1
  44. package/dist/commands/dev.d.ts +11 -0
  45. package/dist/commands/dev.d.ts.map +1 -1
  46. package/dist/commands/dev.js +759 -385
  47. package/dist/commands/dev.js.map +1 -1
  48. package/dist/commands/diff.d.ts.map +1 -1
  49. package/dist/commands/diff.js +30 -15
  50. package/dist/commands/diff.js.map +1 -1
  51. package/dist/commands/engine.d.ts +1 -3
  52. package/dist/commands/engine.d.ts.map +1 -1
  53. package/dist/commands/engine.js +13 -85
  54. package/dist/commands/engine.js.map +1 -1
  55. package/dist/commands/functions.d.ts.map +1 -1
  56. package/dist/commands/functions.js +92 -105
  57. package/dist/commands/functions.js.map +1 -1
  58. package/dist/commands/generate.d.ts.map +1 -1
  59. package/dist/commands/generate.js +22 -12
  60. package/dist/commands/generate.js.map +1 -1
  61. package/dist/commands/init.d.ts +1 -1
  62. package/dist/commands/init.d.ts.map +1 -1
  63. package/dist/commands/init.js +137 -410
  64. package/dist/commands/init.js.map +1 -1
  65. package/dist/commands/migrate-from-v1.d.ts +5 -0
  66. package/dist/commands/migrate-from-v1.d.ts.map +1 -0
  67. package/dist/commands/migrate-from-v1.js +125 -0
  68. package/dist/commands/migrate-from-v1.js.map +1 -0
  69. package/dist/commands/migrate.d.ts.map +1 -1
  70. package/dist/commands/migrate.js +27 -23
  71. package/dist/commands/migrate.js.map +1 -1
  72. package/dist/commands/pg.d.ts +8 -0
  73. package/dist/commands/pg.d.ts.map +1 -0
  74. package/dist/commands/pg.js +102 -0
  75. package/dist/commands/pg.js.map +1 -0
  76. package/dist/commands/pull.d.ts.map +1 -1
  77. package/dist/commands/pull.js +5 -66
  78. package/dist/commands/pull.js.map +1 -1
  79. package/dist/commands/push.d.ts.map +1 -1
  80. package/dist/commands/push.js +128 -38
  81. package/dist/commands/push.js.map +1 -1
  82. package/dist/commands/seed.d.ts +2 -0
  83. package/dist/commands/seed.d.ts.map +1 -1
  84. package/dist/commands/seed.js +44 -11
  85. package/dist/commands/seed.js.map +1 -1
  86. package/dist/commands/self-host.d.ts +7 -1
  87. package/dist/commands/self-host.d.ts.map +1 -1
  88. package/dist/commands/self-host.js +272 -758
  89. package/dist/commands/self-host.js.map +1 -1
  90. package/dist/commands/self-update.d.ts +9 -0
  91. package/dist/commands/self-update.d.ts.map +1 -0
  92. package/dist/commands/self-update.js +33 -0
  93. package/dist/commands/self-update.js.map +1 -0
  94. package/dist/commands/status.d.ts.map +1 -1
  95. package/dist/commands/status.js +4 -3
  96. package/dist/commands/status.js.map +1 -1
  97. package/dist/commands/types.d.ts +3 -0
  98. package/dist/commands/types.d.ts.map +1 -0
  99. package/dist/commands/types.js +62 -0
  100. package/dist/commands/types.js.map +1 -0
  101. package/dist/commands/update.d.ts +7 -0
  102. package/dist/commands/update.d.ts.map +1 -0
  103. package/dist/commands/update.js +93 -0
  104. package/dist/commands/update.js.map +1 -0
  105. package/dist/components.d.ts +5 -0
  106. package/dist/components.d.ts.map +1 -0
  107. package/dist/components.js +3 -0
  108. package/dist/components.js.map +1 -0
  109. package/dist/config.d.ts +10 -51
  110. package/dist/config.d.ts.map +1 -1
  111. package/dist/config.js +101 -33
  112. package/dist/config.js.map +1 -1
  113. package/dist/dev-compose.d.ts +17 -0
  114. package/dist/dev-compose.d.ts.map +1 -0
  115. package/dist/dev-compose.js +374 -0
  116. package/dist/dev-compose.js.map +1 -0
  117. package/dist/diff-output.d.ts +4 -0
  118. package/dist/diff-output.d.ts.map +1 -0
  119. package/dist/diff-output.js +12 -0
  120. package/dist/diff-output.js.map +1 -0
  121. package/dist/docker-postgres.d.ts +57 -0
  122. package/dist/docker-postgres.d.ts.map +1 -0
  123. package/dist/docker-postgres.js +208 -0
  124. package/dist/docker-postgres.js.map +1 -0
  125. package/dist/engine-client.d.ts +69 -0
  126. package/dist/engine-client.d.ts.map +1 -0
  127. package/dist/engine-client.js +157 -0
  128. package/dist/engine-client.js.map +1 -0
  129. package/dist/ensure-binary.d.ts +7 -0
  130. package/dist/ensure-binary.d.ts.map +1 -0
  131. package/dist/ensure-binary.js +17 -0
  132. package/dist/ensure-binary.js.map +1 -0
  133. package/dist/functions-router-gen.d.ts +14 -0
  134. package/dist/functions-router-gen.d.ts.map +1 -0
  135. package/dist/functions-router-gen.js +199 -0
  136. package/dist/functions-router-gen.js.map +1 -0
  137. package/dist/index.d.ts +4 -5
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/index.js +2 -3
  140. package/dist/index.js.map +1 -1
  141. package/dist/kong-config.d.ts +25 -0
  142. package/dist/kong-config.d.ts.map +1 -0
  143. package/dist/kong-config.js +71 -0
  144. package/dist/kong-config.js.map +1 -0
  145. package/dist/local-gateway.d.ts +7 -0
  146. package/dist/local-gateway.d.ts.map +1 -0
  147. package/dist/local-gateway.js +9 -0
  148. package/dist/local-gateway.js.map +1 -0
  149. package/dist/local-storage.d.ts +8 -0
  150. package/dist/local-storage.d.ts.map +1 -0
  151. package/dist/local-storage.js +14 -0
  152. package/dist/local-storage.js.map +1 -0
  153. package/dist/pgbouncer-userlist.d.ts +5 -0
  154. package/dist/pgbouncer-userlist.d.ts.map +1 -0
  155. package/dist/pgbouncer-userlist.js +14 -0
  156. package/dist/pgbouncer-userlist.js.map +1 -0
  157. package/dist/postgres-ctl.d.ts +44 -0
  158. package/dist/postgres-ctl.d.ts.map +1 -0
  159. package/dist/postgres-ctl.js +137 -0
  160. package/dist/postgres-ctl.js.map +1 -0
  161. package/dist/process-manager.d.ts +43 -0
  162. package/dist/process-manager.d.ts.map +1 -0
  163. package/dist/process-manager.js +135 -0
  164. package/dist/process-manager.js.map +1 -0
  165. package/dist/project-config.d.ts +235 -0
  166. package/dist/project-config.d.ts.map +1 -0
  167. package/dist/project-config.js +160 -0
  168. package/dist/project-config.js.map +1 -0
  169. package/dist/pull-utils.d.ts +15 -0
  170. package/dist/pull-utils.d.ts.map +1 -1
  171. package/dist/pull-utils.js +12 -0
  172. package/dist/pull-utils.js.map +1 -1
  173. package/dist/release-pins.d.ts +7 -0
  174. package/dist/release-pins.d.ts.map +1 -0
  175. package/dist/release-pins.js +27 -0
  176. package/dist/release-pins.js.map +1 -0
  177. package/dist/release-public-key.d.ts +8 -0
  178. package/dist/release-public-key.d.ts.map +1 -0
  179. package/dist/release-public-key.js +13 -0
  180. package/dist/release-public-key.js.map +1 -0
  181. package/dist/runtime-routes.d.ts +34 -0
  182. package/dist/runtime-routes.d.ts.map +1 -0
  183. package/dist/runtime-routes.js +252 -0
  184. package/dist/runtime-routes.js.map +1 -0
  185. package/dist/schema-ast-v2.d.ts +127 -0
  186. package/dist/schema-ast-v2.d.ts.map +1 -0
  187. package/dist/schema-ast-v2.js +226 -0
  188. package/dist/schema-ast-v2.js.map +1 -0
  189. package/dist/scripts/postinstall.d.ts +5 -6
  190. package/dist/scripts/postinstall.d.ts.map +1 -1
  191. package/dist/scripts/postinstall.js +36 -20
  192. package/dist/scripts/postinstall.js.map +1 -1
  193. package/dist/self-host-compose.d.ts +22 -0
  194. package/dist/self-host-compose.d.ts.map +1 -0
  195. package/dist/self-host-compose.js +347 -0
  196. package/dist/self-host-compose.js.map +1 -0
  197. package/dist/storage-provision.d.ts +24 -0
  198. package/dist/storage-provision.d.ts.map +1 -0
  199. package/dist/storage-provision.js +44 -0
  200. package/dist/storage-provision.js.map +1 -0
  201. package/dist/studio-admin-roles.d.ts +7 -0
  202. package/dist/studio-admin-roles.d.ts.map +1 -0
  203. package/dist/studio-admin-roles.js +14 -0
  204. package/dist/studio-admin-roles.js.map +1 -0
  205. package/dist/studio-dev-server.d.ts +22 -0
  206. package/dist/studio-dev-server.d.ts.map +1 -0
  207. package/dist/studio-dev-server.js +28 -0
  208. package/dist/studio-dev-server.js.map +1 -0
  209. package/dist/systemd.d.ts +26 -0
  210. package/dist/systemd.d.ts.map +1 -0
  211. package/dist/systemd.js +102 -0
  212. package/dist/systemd.js.map +1 -0
  213. package/dist/tsx-runner.d.ts.map +1 -1
  214. package/dist/tsx-runner.js +9 -2
  215. package/dist/tsx-runner.js.map +1 -1
  216. package/dist/type-extractor.d.ts +4 -0
  217. package/dist/type-extractor.d.ts.map +1 -0
  218. package/dist/type-extractor.js +1213 -0
  219. package/dist/type-extractor.js.map +1 -0
  220. package/dist/type-resolver.d.ts +33 -0
  221. package/dist/type-resolver.d.ts.map +1 -0
  222. package/dist/type-resolver.js +338 -0
  223. package/dist/type-resolver.js.map +1 -0
  224. package/package.json +4 -3
  225. package/releases/deno/VERSION +1 -0
  226. package/scripts/mirror-deno-release.sh +76 -0
  227. package/src/TYPE-RESOLUTION.md +294 -0
  228. package/src/app/proxy-dev-app.ts +67 -0
  229. package/src/app-config.ts +128 -0
  230. package/src/augmentation-generator.ts +126 -0
  231. package/src/binary-cache.ts +822 -0
  232. package/src/cli.ts +13 -8
  233. package/src/commands/admin.ts +4 -3
  234. package/src/commands/app.ts +67 -231
  235. package/src/commands/cache.ts +117 -0
  236. package/src/commands/cloud.ts +63 -64
  237. package/src/commands/db.ts +54 -63
  238. package/src/commands/deploy.ts +96 -62
  239. package/src/commands/dev.ts +933 -405
  240. package/src/commands/diff.ts +31 -29
  241. package/src/commands/engine.ts +13 -116
  242. package/src/commands/functions.ts +97 -115
  243. package/src/commands/generate.ts +23 -10
  244. package/src/commands/init.ts +149 -414
  245. package/src/commands/migrate-from-v1.ts +131 -0
  246. package/src/commands/migrate.ts +27 -23
  247. package/src/commands/pg.ts +133 -0
  248. package/src/commands/pull.ts +6 -85
  249. package/src/commands/push.ts +161 -56
  250. package/src/commands/seed.ts +54 -12
  251. package/src/commands/self-host.ts +312 -880
  252. package/src/commands/self-update.ts +45 -0
  253. package/src/commands/status.ts +4 -3
  254. package/src/commands/types.ts +76 -0
  255. package/src/commands/update.ts +109 -0
  256. package/src/components.ts +6 -0
  257. package/src/config.ts +127 -94
  258. package/src/dev-compose.ts +455 -0
  259. package/src/diff-output.ts +12 -0
  260. package/src/docker-postgres.ts +295 -0
  261. package/src/engine-client.ts +236 -0
  262. package/src/ensure-binary.ts +28 -0
  263. package/src/functions-router-gen.ts +224 -0
  264. package/src/index.ts +4 -12
  265. package/src/kong-config.ts +93 -0
  266. package/src/local-gateway.ts +9 -0
  267. package/src/local-storage.ts +14 -0
  268. package/src/pgbouncer-userlist.ts +15 -0
  269. package/src/postgres-ctl.ts +171 -0
  270. package/src/process-manager.ts +168 -0
  271. package/src/project-config.ts +386 -0
  272. package/src/pull-utils.ts +24 -0
  273. package/src/release-pins.ts +31 -0
  274. package/src/release-public-key.ts +12 -0
  275. package/src/runtime-routes.ts +291 -0
  276. package/src/schema-ast-v2.ts +324 -0
  277. package/src/scripts/postinstall.ts +36 -25
  278. package/src/self-host-compose.ts +389 -0
  279. package/src/storage-provision.ts +58 -0
  280. package/src/studio-admin-roles.ts +16 -0
  281. package/src/studio-dev-server.ts +53 -0
  282. package/src/systemd.ts +137 -0
  283. package/src/tsx-runner.ts +11 -1
  284. package/src/type-extractor.ts +1479 -0
  285. package/src/type-resolver.ts +457 -0
  286. package/tests/app-command.test.ts +54 -0
  287. package/tests/augmentation-generator.test.ts +59 -0
  288. package/tests/binary-cache-cloud-overrides.test.ts +123 -0
  289. package/tests/cached-artifact-format.test.ts +84 -0
  290. package/tests/cli-help.test.ts +40 -14
  291. package/tests/config.test.ts +171 -37
  292. package/tests/docker-postgres.test.ts +39 -0
  293. package/tests/engine-distribution.test.ts +3 -3
  294. package/tests/ensure-binary.test.ts +59 -0
  295. package/tests/init.test.ts +28 -86
  296. package/tests/migrate-from-v1.test.ts +29 -0
  297. package/tests/normalize-admin-config.test.ts +48 -0
  298. package/tests/pg-spawn-env.test.ts +18 -0
  299. package/tests/postgres-archive-tag.test.ts +9 -0
  300. package/tests/proxy-dev-app.test.ts +33 -0
  301. package/tests/pull-utils.test.ts +36 -1
  302. package/tests/release-pins.test.ts +28 -0
  303. package/tests/runtime-contract.test.ts +351 -0
  304. package/tests/seed-discover.test.ts +31 -0
  305. package/tests/studio-admin-roles.test.ts +27 -0
  306. package/tests/tsconfig.json +9 -0
  307. package/tests/type-extractor.test.ts +985 -0
  308. package/tests/type-resolver.test.ts +59 -0
  309. package/tsconfig.tsbuildinfo +1 -1
  310. package/vitest.config.ts +12 -0
  311. package/dist/engine/cache.d.ts +0 -37
  312. package/dist/engine/cache.d.ts.map +0 -1
  313. package/dist/engine/cache.js +0 -121
  314. package/dist/engine/cache.js.map +0 -1
  315. package/dist/engine/download.d.ts +0 -19
  316. package/dist/engine/download.d.ts.map +0 -1
  317. package/dist/engine/download.js +0 -108
  318. package/dist/engine/download.js.map +0 -1
  319. package/dist/engine/platform.d.ts +0 -24
  320. package/dist/engine/platform.d.ts.map +0 -1
  321. package/dist/engine/platform.js +0 -50
  322. package/dist/engine/platform.js.map +0 -1
  323. package/dist/engine/resolve.d.ts +0 -37
  324. package/dist/engine/resolve.d.ts.map +0 -1
  325. package/dist/engine/resolve.js +0 -133
  326. package/dist/engine/resolve.js.map +0 -1
  327. package/dist/engine/update-notify.d.ts +0 -11
  328. package/dist/engine/update-notify.d.ts.map +0 -1
  329. package/dist/engine/update-notify.js +0 -43
  330. package/dist/engine/update-notify.js.map +0 -1
  331. package/dist/engine/verify.d.ts +0 -50
  332. package/dist/engine/verify.d.ts.map +0 -1
  333. package/dist/engine/verify.js +0 -161
  334. package/dist/engine/verify.js.map +0 -1
  335. package/dist/engine-version.d.ts +0 -35
  336. package/dist/engine-version.d.ts.map +0 -1
  337. package/dist/engine-version.js +0 -35
  338. package/dist/engine-version.js.map +0 -1
  339. package/dist/engine.d.ts +0 -34
  340. package/dist/engine.d.ts.map +0 -1
  341. package/dist/engine.js +0 -76
  342. package/dist/engine.js.map +0 -1
  343. package/src/engine/cache.ts +0 -135
  344. package/src/engine/download.ts +0 -143
  345. package/src/engine/platform.ts +0 -66
  346. package/src/engine/resolve.ts +0 -197
  347. package/src/engine/update-notify.ts +0 -50
  348. package/src/engine/verify.ts +0 -206
  349. package/src/engine-version.ts +0 -39
  350. package/src/engine.ts +0 -99
@@ -1,17 +1,19 @@
1
1
  import type { Command } from "commander"
2
+ import { mkdirSync, writeFileSync } from "node:fs"
2
3
  import { createInterface } from "node:readline"
4
+ import { join } from "node:path"
3
5
  import { loadConfig, loadSchemaAst } from "../config.js"
4
- import { ensureEngine, invokeEngine } from "../engine.js"
6
+ import { connectionString, resolveRuntimeProvider, schemaPathFromProject, serverBaseUrl } from "../project-config.js"
7
+ import { isCloudLinked, pushSchemaToLinkedProject } from "./cloud.js"
8
+ import { ensureEngine, engineRequest, type DiffResult, type Operation } from "../engine-client.js"
9
+ import { printDiffWarnings } from "../diff-output.js"
10
+ import { signJwt } from "../jwt.js"
11
+ import { provisionBuckets } from "../storage-provision.js"
5
12
  import { promptFirstAdminUser } from "./admin.js"
6
- interface DiffResult {
7
- operations: Operation[]
8
- }
13
+ import { withAdminRoles } from "../studio-admin-roles.js"
14
+ import type { SupatypeProjectConfig } from "../project-config.js"
9
15
 
10
- interface Operation {
11
- kind: string
12
- risk: "safe" | "cautious" | "destructive"
13
- description: string
14
- }
16
+ const DEV_JWT_SECRET = "super-secret-jwt-token-with-at-least-32-characters-long"
15
17
 
16
18
  export function registerPush(program: Command): void {
17
19
  program
@@ -23,89 +25,183 @@ export function registerPush(program: Command): void {
23
25
  .option("--connection <url>", "Database connection URL (overrides config)")
24
26
  .action(async (opts: { yes?: boolean; connection?: string }) => {
25
27
  const cwd = process.cwd()
28
+
29
+ if (isCloudLinked(cwd)) {
30
+ if (opts.connection) {
31
+ console.error("--connection is not allowed when linked to a cloud project (credentials stay server-side).")
32
+ process.exit(1)
33
+ }
34
+ await pushSchemaToLinkedProject(cwd, { force: opts.yes ?? true })
35
+ return
36
+ }
37
+
26
38
  const config = loadConfig(cwd)
27
- const connection = opts.connection ?? config.connection
39
+
40
+ // Docker provider: the compose Postgres isn't published to the host, so
41
+ // apply the schema through the in-compose schema-engine (unless the user
42
+ // gave an explicit --connection to a reachable database).
43
+ if (!opts.connection && resolveRuntimeProvider(config) === "docker") {
44
+ const { pushSchemaDocker } = await import("../dev-compose.js")
45
+ await pushSchemaDocker(cwd, config)
46
+ return
47
+ }
48
+
49
+ const connection = opts.connection ?? connectionString(config)
28
50
 
29
51
  await ensureEngine()
30
52
 
31
53
  console.log("Loading schema...")
32
- const ast = loadSchemaAst(config.schema, cwd)
54
+ const ast = loadSchemaAst(schemaPathFromProject(config, cwd), cwd)
33
55
 
34
- // Validate configured providers before diffing
35
56
  console.log("Diffing against database...")
36
- const diffResult = invokeEngine(
37
- ["diff", "--connection", connection, "--format", "json"],
38
- JSON.stringify(ast),
39
- )
40
- if (diffResult.exitCode !== 0) {
41
- console.error(diffResult.stderr || diffResult.stdout)
42
- process.exit(1)
43
- }
57
+ const diff = await engineRequest<DiffResult>("/diff", {
58
+ ast,
59
+ database_url: connection,
60
+ schema: "public",
61
+ })
44
62
 
45
- const diff = JSON.parse(diffResult.stdout) as DiffResult
46
63
  const ops = diff.operations ?? []
64
+ printDiffWarnings(diff)
47
65
 
48
66
  if (ops.length === 0) {
49
- console.log("Schema is up to date. Nothing to push.")
50
- return
51
- }
52
-
53
- printDiff(ops)
67
+ console.log(
68
+ "Schema matches the database (no DDL). Syncing Studio metadata...",
69
+ )
70
+ } else {
71
+ printDiff(ops)
54
72
 
55
- const destructive = ops.filter((o) => o.risk === "destructive")
56
- if (destructive.length > 0 && !opts.yes) {
57
- const confirmed = await confirm(
58
- `\n${destructive.length} destructive operation(s) above. Proceed? [y/N] `,
73
+ const risky = ops.filter(
74
+ (o) => o.risk === "cautious" || o.risk === "destructive" || o.risk === "warn" || o.risk === "danger",
59
75
  )
60
- if (!confirmed) {
61
- console.log("Aborted.")
62
- return
76
+ if (risky.length > 0 && !opts.yes) {
77
+ const confirmed = await confirm(
78
+ `\n${risky.length} risky operation(s) above (type changes or data loss). Proceed? [y/N] `,
79
+ )
80
+ if (!confirmed) {
81
+ console.log("Aborted.")
82
+ return
83
+ }
63
84
  }
64
85
  }
65
86
 
66
- console.log("\nApplying migration...")
67
- const migrateResult = invokeEngine(
68
- ["migrate", "--connection", connection],
69
- JSON.stringify(ast),
70
- )
71
- if (migrateResult.exitCode !== 0) {
72
- console.error(migrateResult.stderr || migrateResult.stdout)
73
- process.exit(1)
87
+ console.log(ops.length > 0 ? "\nApplying migration..." : "\nSyncing with engine...")
88
+ const pushResult = await engineRequest<{
89
+ message?: string
90
+ status?: string
91
+ admin_refreshed?: boolean
92
+ }>("/push", {
93
+ ast,
94
+ database_url: connection,
95
+ schema: "public",
96
+ force: true,
97
+ })
98
+ if (pushResult.status === "up_to_date") {
99
+ console.log(
100
+ pushResult.admin_refreshed
101
+ ? "Database schema unchanged — Studio metadata synced."
102
+ : "Schema is up to date.",
103
+ )
104
+ } else {
105
+ console.log(pushResult.message ?? "Migration applied.")
74
106
  }
75
- console.log(migrateResult.stdout || "Migration applied.")
76
107
 
77
- // After migration, check if this is the first push and offer to create an
108
+ await writeLocalAdminConfig(ast, config)
109
+
110
+ // After a DDL migration, check if this is the first push and offer to create an
78
111
  // admin user if none exist (Gap Appendices task 48).
79
- await promptFirstAdminUser(connection)
112
+ if (ops.length > 0) {
113
+ await promptFirstAdminUser(connection)
114
+ }
115
+
116
+ // Provision storage buckets declared in the schema.
117
+ const baseUrl = serverBaseUrl(config)
118
+ const serviceRoleKey =
119
+ process.env["SUPATYPE_SERVICE_ROLE_KEY"] ??
120
+ (config.server.mode === "dev"
121
+ ? signJwt({ role: "service_role", iss: "supatype", iat: Math.floor(Date.now() / 1000) }, DEV_JWT_SECRET)
122
+ : undefined)
123
+
124
+ if (baseUrl && serviceRoleKey) {
125
+ const parsedAst = await engineRequest<{
126
+ storageBuckets?: Array<{
127
+ id: string
128
+ public: boolean
129
+ accessMode?: "public" | "private" | "custom"
130
+ allowedMimeTypes?: string[]
131
+ fileSizeLimit?: number
132
+ s3BucketPolicy?: string
133
+ }>
134
+ }>("/parse", { ast })
135
+ const buckets = (parsedAst.storageBuckets ?? []).map((b) => ({
136
+ id: b.id,
137
+ public: b.public,
138
+ ...(b.accessMode !== undefined && { access_mode: b.accessMode }),
139
+ ...(b.allowedMimeTypes != null && { allowed_mime_types: b.allowedMimeTypes }),
140
+ ...(b.fileSizeLimit != null && { file_size_limit: b.fileSizeLimit }),
141
+ ...(b.s3BucketPolicy != null &&
142
+ b.s3BucketPolicy !== "" && { s3_bucket_policy: b.s3BucketPolicy }),
143
+ }))
144
+ if (buckets.length > 0) {
145
+ console.log("Provisioning storage buckets...")
146
+ await provisionBuckets(`${baseUrl}/storage/v1`, serviceRoleKey, buckets)
147
+ }
148
+ }
80
149
 
81
150
  if (config.output?.types ?? config.output?.client) {
82
151
  console.log("Generating types...")
83
- const genArgs = ["generate", "--connection", connection]
84
- if (config.output?.types) genArgs.push("--types", config.output.types)
85
- if (config.output?.client) genArgs.push("--client", config.output.client)
152
+ const genBody: Record<string, unknown> = { ast, lang: "typescript" }
153
+ if (config.output?.types) genBody["types_path"] = config.output.types
154
+ if (config.output?.client) genBody["client_path"] = config.output.client
86
155
 
87
- const genResult = invokeEngine(genArgs, JSON.stringify(ast))
88
- if (genResult.exitCode !== 0) {
89
- console.error(genResult.stderr || genResult.stdout)
90
- process.exit(1)
91
- }
92
- console.log(genResult.stdout || "Types generated.")
156
+ const genResult = await engineRequest<{ code?: string; message?: string }>("/generate", genBody)
157
+ console.log(genResult.message ?? "Types generated.")
93
158
  }
94
159
 
95
- console.log("\nDone.")
160
+ const studioBase = baseUrl?.replace(/\/$/, "") ?? ""
161
+ if (studioBase) {
162
+ console.log(`\nStudio: ${studioBase}/studio/ — sign in with the admin user you created.`)
163
+ } else {
164
+ console.log("\nDone.")
165
+ }
96
166
  })
97
167
  }
98
168
 
99
169
  function printDiff(ops: Operation[]): void {
100
- const symbol: Record<Operation["risk"], string> = {
170
+ const symbol: Record<string, string> = {
101
171
  safe: "+",
172
+ warn: "~",
102
173
  cautious: "~",
174
+ danger: "!",
103
175
  destructive: "!",
104
176
  }
105
177
  console.log(`\n${ops.length} change(s) planned:\n`)
106
178
  for (const op of ops) {
107
- console.log(` [${symbol[op.risk]}] ${op.description}`)
179
+ const riskKey = op.risk ?? "safe"
180
+ const s = symbol[riskKey] ?? "?"
181
+ const label = op.warning ?? op.description ?? formatOperation(op)
182
+ console.log(` [${s}] ${label}`)
183
+ }
184
+ }
185
+
186
+ function formatOperation(op: Operation): string {
187
+ if (typeof op.description === "string" && op.description.trim().length > 0) {
188
+ return op.description
189
+ }
190
+
191
+ const kind = typeof op.kind === "string" ? op.kind : "operation"
192
+ const raw = op as unknown as Record<string, unknown>
193
+ const table = raw["table"]
194
+ const column = raw["column"]
195
+
196
+ if (typeof table === "string" && typeof column === "string") {
197
+ return `${kind} ${table}.${column}`
108
198
  }
199
+ if (typeof table === "string") {
200
+ return `${kind} ${table}`
201
+ }
202
+
203
+ // Last resort: show operation kind with compact payload.
204
+ return `${kind} ${JSON.stringify(op)}`
109
205
  }
110
206
 
111
207
  async function confirm(prompt: string): Promise<boolean> {
@@ -117,3 +213,12 @@ async function confirm(prompt: string): Promise<boolean> {
117
213
  })
118
214
  })
119
215
  }
216
+
217
+ /** Write `.supatype/admin-config.json` for local Studio (same layout as `supatype dev`). */
218
+ async function writeLocalAdminConfig(ast: unknown, config: SupatypeProjectConfig): Promise<void> {
219
+ const cwd = process.cwd()
220
+ const dir = join(cwd, ".supatype")
221
+ mkdirSync(dir, { recursive: true })
222
+ const admin = withAdminRoles(await engineRequest<unknown>("/admin", { ast }), config)
223
+ writeFileSync(join(dir, "admin-config.json"), `${JSON.stringify(admin, null, 2)}\n`)
224
+ }
@@ -1,26 +1,68 @@
1
1
  import type { Command } from "commander"
2
- import { existsSync } from "node:fs"
3
- import { resolve } from "node:path"
2
+ import { existsSync, readdirSync } from "node:fs"
3
+ import { join, resolve } from "node:path"
4
+ import { isLinkedToCloudProject } from "../binary-cache.js"
5
+ import { loadConfig } from "../config.js"
6
+ import { projectRootFromConfig } from "../project-config.js"
4
7
  import { runTsFile } from "../tsx-runner.js"
5
8
 
9
+ const SEED_EXT = /\.(ts|mts|tsx)$/
10
+
11
+ /** Seed entries under `seeds/`, sorted by filename (Phase 10.6 C19). */
12
+ export function discoverSeedsDir(cwd: string, seedsDir: string): string[] {
13
+ if (!existsSync(seedsDir)) return []
14
+ const names = readdirSync(seedsDir).filter((n) => SEED_EXT.test(n))
15
+ names.sort((a, b) => a.localeCompare(b))
16
+ return names.map((n) => join(seedsDir, n))
17
+ }
18
+
6
19
  export function registerSeed(program: Command): void {
7
20
  program
8
21
  .command("seed [file]")
9
- .description("Run seed.ts (or a custom seed file) against the database")
10
- .action((file?: string) => {
22
+ .description(
23
+ "Run database seeds: optional single file; else all seeds/*.ts (alphabetical); else seed.ts",
24
+ )
25
+ .option(
26
+ "--force",
27
+ "Allow running when the project is linked to Supatype Cloud (dangerous)",
28
+ false,
29
+ )
30
+ .action(async (file: string | undefined, opts: { force: boolean }) => {
11
31
  const cwd = process.cwd()
12
- const seedFile = resolve(cwd, file ?? "seed.ts")
13
-
14
- if (!existsSync(seedFile)) {
15
- console.error(`Seed file not found: ${seedFile}`)
32
+ const config = loadConfig(cwd)
33
+ if (isLinkedToCloudProject(cwd, config) && !opts.force) {
34
+ console.error(
35
+ "[supatype] This project is linked to Supatype Cloud. Refusing to run seeds locally.\n" +
36
+ " Pass --force only if you intend to target this linked project (advanced).",
37
+ )
16
38
  process.exit(1)
17
39
  }
18
40
 
19
- console.log(`Running ${seedFile}...`)
20
- const result = runTsFile(seedFile, { cwd, stdio: "inherit" })
41
+ const root = projectRootFromConfig(config, cwd)
42
+ const seedsDir = join(root, "seeds")
43
+
44
+ let paths: string[]
45
+ if (file !== undefined && file.trim() !== "") {
46
+ paths = [resolve(cwd, file)]
47
+ } else {
48
+ paths = discoverSeedsDir(cwd, seedsDir)
49
+ if (paths.length === 0) {
50
+ paths = [resolve(root, "seed.ts")]
51
+ }
52
+ }
53
+
54
+ const missing = paths.filter((p) => !existsSync(p))
55
+ if (missing.length > 0) {
56
+ console.error(`Seed file(s) not found:\n ${missing.join("\n ")}`)
57
+ process.exit(1)
58
+ }
21
59
 
22
- if (result.exitCode !== 0) {
23
- process.exit(result.exitCode)
60
+ for (const seedFile of paths) {
61
+ console.log(`[supatype] Running ${seedFile}...`)
62
+ const result = runTsFile(seedFile, { cwd, stdio: "inherit" })
63
+ if (result.exitCode !== 0) {
64
+ process.exit(result.exitCode)
65
+ }
24
66
  }
25
67
  })
26
68
  }