@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
@@ -7,9 +7,11 @@ interface CloudConfig {
7
7
  apiUrl: string
8
8
  token: string
9
9
  projectSlug?: string
10
+ /** Organisation UUID — required for schema routes (`X-Org-Id`). */
11
+ orgId?: string
10
12
  }
11
13
 
12
- function loadCloudConfig(cwd: string): CloudConfig | null {
14
+ export function loadCloudConfig(cwd: string): CloudConfig | null {
13
15
  const configPath = resolve(cwd, ".supatype/cloud.json")
14
16
  if (!existsSync(configPath)) return null
15
17
  return JSON.parse(readFileSync(configPath, "utf8")) as CloudConfig
@@ -25,12 +27,16 @@ function saveCloudConfig(cwd: string, config: CloudConfig): void {
25
27
  }
26
28
 
27
29
  async function cloudFetch<T>(config: CloudConfig, method: string, path: string, body?: unknown): Promise<T> {
30
+ const headers: Record<string, string> = {
31
+ "Content-Type": "application/json",
32
+ Authorization: `Bearer ${config.token}`,
33
+ }
34
+ if (config.orgId) {
35
+ headers["X-Org-Id"] = config.orgId
36
+ }
28
37
  const res = await fetch(`${config.apiUrl}/api/v1${path}`, {
29
38
  method,
30
- headers: {
31
- "Content-Type": "application/json",
32
- Authorization: `Bearer ${config.token}`,
33
- },
39
+ headers,
34
40
  ...(body !== undefined ? { body: JSON.stringify(body) } : {}),
35
41
  })
36
42
 
@@ -41,6 +47,50 @@ async function cloudFetch<T>(config: CloudConfig, method: string, path: string,
41
47
  return json.data as T
42
48
  }
43
49
 
50
+ /** True when `.supatype/cloud.json` exists with a linked project slug. */
51
+ export function isCloudLinked(cwd: string): boolean {
52
+ const cfg = loadCloudConfig(cwd)
53
+ return Boolean(cfg?.projectSlug && cfg.token)
54
+ }
55
+
56
+ /**
57
+ * Push schema AST to the linked cloud project (`POST /api/v1/projects/:ref/schema/push`).
58
+ * Credentials stay server-side; only AST is sent.
59
+ */
60
+ export async function pushSchemaToLinkedProject(cwd: string, opts?: { force?: boolean }): Promise<void> {
61
+ const config = loadCloudConfig(cwd)
62
+ if (!config?.projectSlug) {
63
+ console.error("Not linked to a cloud project. Run: supatype link")
64
+ process.exit(1)
65
+ }
66
+ if (!config.orgId) {
67
+ console.error(
68
+ "Missing orgId in .supatype/cloud.json. Re-run: supatype link --project <slug> (after cloud login).",
69
+ )
70
+ process.exit(1)
71
+ }
72
+
73
+ const { loadConfig: loadAppConfig, loadSchemaAst } = await import("../config.js")
74
+ const { schemaPathFromProject } = await import("../project-config.js")
75
+
76
+ const appConfig = loadAppConfig(cwd)
77
+ const ast = loadSchemaAst(schemaPathFromProject(appConfig, cwd), cwd)
78
+
79
+ console.log(`Pushing schema to cloud project ${config.projectSlug}...`)
80
+
81
+ const result = await cloudFetch<{ message?: string }>(config, "POST", `/projects/${config.projectSlug}/schema/push`, {
82
+ ast,
83
+ force: opts?.force ?? true,
84
+ })
85
+
86
+ console.log(result.message ?? "Schema push completed.")
87
+ }
88
+
89
+ /** @deprecated Use pushSchemaToLinkedProject — kept for deploy command alias */
90
+ export async function deploySchemaToLinkedProject(cwd: string, _environment: string): Promise<void> {
91
+ await pushSchemaToLinkedProject(cwd)
92
+ }
93
+
44
94
  function prompt(question: string): Promise<string> {
45
95
  const rl = createInterface({ input: process.stdin, output: process.stdout })
46
96
  return new Promise((resolve) => {
@@ -59,7 +109,7 @@ export function registerCloud(program: Command): void {
59
109
  .command("link")
60
110
  .description("Link this local project to a Supatype cloud project")
61
111
  .option("--project <slug>", "Project slug to link to")
62
- .option("--api-url <url>", "Control plane API URL", "https://api.supatype.io")
112
+ .option("--api-url <url>", "Control plane API URL", "https://api.supatype.com")
63
113
  .option("--token <token>", "Authentication token")
64
114
  .action(async (opts: { project?: string; apiUrl: string; token?: string }) => {
65
115
  const cwd = process.cwd()
@@ -73,9 +123,10 @@ export function registerCloud(program: Command): void {
73
123
 
74
124
  if (opts.project) {
75
125
  config.projectSlug = opts.project
126
+ const one = await cloudFetch<{ slug: string; orgId: string }>(config, "GET", `/projects/${opts.project}`)
127
+ config.orgId = one.orgId
76
128
  } else {
77
- // List projects and let user choose
78
- const projects = await cloudFetch<Array<{ slug: string; name: string; status: string; tier: string }>>(
129
+ const projects = await cloudFetch<Array<{ slug: string; name: string; status: string; tier: string; orgId: string }>>(
79
130
  config, "GET", "/projects",
80
131
  )
81
132
  if (projects.length === 0) {
@@ -94,7 +145,9 @@ export function registerCloud(program: Command): void {
94
145
  console.error("Invalid selection.")
95
146
  process.exit(1)
96
147
  }
97
- config.projectSlug = projects[idx]!.slug
148
+ const picked = projects[idx]!
149
+ config.projectSlug = picked.slug
150
+ config.orgId = picked.orgId
98
151
  }
99
152
 
100
153
  saveCloudConfig(cwd, config)
@@ -102,60 +155,6 @@ export function registerCloud(program: Command): void {
102
155
  console.log(`Config saved to .supatype/cloud.json\n`)
103
156
  })
104
157
 
105
- // ── Deploy ─────────────────────────────────────────────────────────────────
106
- program
107
- .command("deploy")
108
- .description("Deploy schema to the linked cloud project")
109
- .option("--environment <name>", "Target environment", "production")
110
- .action(async (opts: { environment: string }) => {
111
- const cwd = process.cwd()
112
- const config = loadCloudConfig(cwd)
113
- if (!config?.projectSlug) {
114
- console.error("Not linked to a cloud project. Run: supatype link")
115
- process.exit(1)
116
- }
117
-
118
- console.log(`Deploying to ${config.projectSlug} (${opts.environment})...`)
119
-
120
- // Load schema AST
121
- const { loadConfig: loadAppConfig, loadSchemaAst } = await import("../config.js")
122
- const { ensureEngine, invokeEngine } = await import("../engine.js")
123
-
124
- const appConfig = loadAppConfig(cwd)
125
- const ast = loadSchemaAst(appConfig.schema, cwd)
126
-
127
- // Generate migration SQL locally using the engine
128
- await ensureEngine()
129
- const migrateResult = invokeEngine(
130
- ["migrate", "--format", "sql"],
131
- JSON.stringify(ast),
132
- )
133
- if (migrateResult.exitCode !== 0) {
134
- console.error("Failed to generate migration:", migrateResult.stderr || migrateResult.stdout)
135
- process.exit(1)
136
- }
137
-
138
- const { createHash } = await import("node:crypto")
139
- const schemaHash = createHash("sha256").update(JSON.stringify(ast)).digest("hex").slice(0, 16)
140
-
141
- const deployment = await cloudFetch<{
142
- id: string; status: string; errorMessage?: string
143
- }>(config, "POST", `/projects/${config.projectSlug}/deploy`, {
144
- environment: opts.environment,
145
- schemaHash,
146
- migrationSql: migrateResult.stdout,
147
- })
148
-
149
- if (deployment.status === "success") {
150
- console.log(`\nDeployment successful (${deployment.id})`)
151
- } else if (deployment.status === "failed") {
152
- console.error(`\nDeployment failed: ${deployment.errorMessage}`)
153
- process.exit(1)
154
- } else {
155
- console.log(`\nDeployment ${deployment.status} (${deployment.id})`)
156
- }
157
- })
158
-
159
158
  // ── Projects ───────────────────────────────────────────────────────────────
160
159
  const projectsCmd = program
161
160
  .command("projects")
@@ -315,7 +314,7 @@ function getCloudConfigOrExit(): CloudConfig {
315
314
  let config = loadCloudConfig(cwd)
316
315
  if (!config) {
317
316
  const token = process.env["SUPATYPE_TOKEN"]
318
- const apiUrl = process.env["SUPATYPE_API_URL"] ?? "https://api.supatype.io"
317
+ const apiUrl = process.env["SUPATYPE_API_URL"] ?? "https://api.supatype.com"
319
318
  if (!token) {
320
319
  console.error("Not connected to Supatype Cloud. Run: supatype link, or set SUPATYPE_TOKEN.")
321
320
  process.exit(1)
@@ -6,6 +6,8 @@
6
6
 
7
7
  import type { Command } from "commander"
8
8
  import { loadConfig } from "../config.js"
9
+ import { connectionString } from "../project-config.js"
10
+ import { loadCloudConfig } from "./cloud.js"
9
11
 
10
12
  export function registerDb(program: Command): void {
11
13
  const db = program
@@ -21,16 +23,13 @@ export function registerDb(program: Command): void {
21
23
  .action(async (opts: { transaction?: boolean; env?: string }) => {
22
24
  const cwd = process.cwd()
23
25
  const config = loadConfig(cwd)
26
+ const cloudCfg = loadCloudConfig(cwd)
27
+ const localConn = connectionString(config)
24
28
 
25
- // The connection string is stored in the project config or fetched from cloud
26
- if (config.connection) {
27
- if (opts.transaction) {
28
- // Convert session URL to transaction pool URL (port 6432)
29
- const txUrl = config.connection.replace(/:5432\//, ":6432/")
30
- console.log(txUrl)
31
- } else {
32
- console.log(config.connection)
33
- }
29
+ // If no cloud project linked, show the local connection string.
30
+ if (!cloudCfg?.projectSlug) {
31
+ const connStr = opts.transaction ? localConn.replace(/:5432\//, ":6432/") : localConn
32
+ console.log(connStr)
34
33
  console.log()
35
34
  console.log("Session mode (port 5432): for interactive tools (psql, DataGrip, TablePlus)")
36
35
  console.log("Transaction mode (port 6432): for application servers and serverless functions")
@@ -38,58 +37,49 @@ export function registerDb(program: Command): void {
38
37
  }
39
38
 
40
39
  // If linked to a cloud project, fetch from the API
41
- if (config.projectRef) {
42
- const apiUrl = config.apiUrl || "https://api.supatype.io"
43
- const envName = opts.env || "production"
44
-
45
- try {
46
- const res = await fetch(
47
- `${apiUrl}/platform/v1/projects/${config.projectRef}/environments`,
48
- {
49
- headers: {
50
- Authorization: `Bearer ${config.accessToken || process.env["SUPATYPE_ACCESS_TOKEN"] || ""}`,
51
- },
40
+ const apiUrl = cloudCfg.apiUrl || "https://api.supatype.com"
41
+ const token = cloudCfg.token || process.env["SUPATYPE_ACCESS_TOKEN"] || ""
42
+ const envName = opts.env || "production"
43
+
44
+ try {
45
+ const res = await fetch(
46
+ `${apiUrl}/platform/v1/projects/${cloudCfg.projectSlug}/environments`,
47
+ {
48
+ headers: {
49
+ Authorization: `Bearer ${token}`,
52
50
  },
53
- )
54
-
55
- if (!res.ok) {
56
- console.error(`Failed to fetch project info: ${res.status}`)
57
- process.exitCode = 1
58
- return
59
- }
60
-
61
- const { data } = (await res.json()) as { data: Array<{ name: string; databaseUrl?: string }> }
62
- const env = data.find((e) => e.name === envName)
63
-
64
- if (!env) {
65
- console.error(`Environment "${envName}" not found`)
66
- process.exitCode = 1
67
- return
68
- }
69
-
70
- const connStr = env.databaseUrl || "Connection string not available"
71
- if (opts.transaction) {
72
- console.log(connStr.replace(/:5432\//, ":6432/"))
73
- } else {
74
- console.log(connStr)
75
- }
76
-
77
- console.log()
78
- console.log("Session mode (port 5432): for interactive tools (psql, DataGrip, TablePlus)")
79
- console.log("Transaction mode (port 6432): for application servers and serverless functions")
80
- } catch (err) {
81
- console.error("Failed to fetch connection string:", (err as Error).message)
51
+ },
52
+ )
53
+
54
+ if (!res.ok) {
55
+ console.error(`Failed to fetch project info: ${res.status}`)
82
56
  process.exitCode = 1
57
+ return
83
58
  }
84
- return
85
- }
86
59
 
87
- console.error(
88
- "No connection configured. Either:\n" +
89
- " • Set 'connection' in supatype.config.ts\n" +
90
- " • Link to a cloud project: npx supatype link --project <ref>",
91
- )
92
- process.exitCode = 1
60
+ const { data } = (await res.json()) as { data: Array<{ name: string; databaseUrl?: string }> }
61
+ const env = data.find((e) => e.name === envName)
62
+
63
+ if (!env) {
64
+ console.error(`Environment "${envName}" not found`)
65
+ process.exitCode = 1
66
+ return
67
+ }
68
+
69
+ const connStr = env.databaseUrl || "Connection string not available"
70
+ if (opts.transaction) {
71
+ console.log(connStr.replace(/:5432\//, ":6432/"))
72
+ } else {
73
+ console.log(connStr)
74
+ }
75
+
76
+ console.log()
77
+ console.log("Session mode (port 5432): for interactive tools (psql, DataGrip, TablePlus)")
78
+ console.log("Transaction mode (port 6432): for application servers and serverless functions")
79
+ } catch (err) {
80
+ console.error("Failed to fetch connection string:", (err as Error).message)
81
+ process.exitCode = 1
82
+ }
93
83
  })
94
84
 
95
85
  // supatype db reset-password
@@ -99,24 +89,25 @@ export function registerDb(program: Command): void {
99
89
  .option("--env <name>", "Environment name", "production")
100
90
  .action(async (opts: { env?: string }) => {
101
91
  const cwd = process.cwd()
102
- const config = loadConfig(cwd)
92
+ const cloudCfg = loadCloudConfig(cwd)
103
93
 
104
- if (!config.projectRef) {
105
- console.error("Not linked to a cloud project. Run: npx supatype link --project <ref>")
94
+ if (!cloudCfg?.projectSlug) {
95
+ console.error("Not linked to a cloud project. Run: supatype link --project <ref>")
106
96
  process.exitCode = 1
107
97
  return
108
98
  }
109
99
 
110
- const apiUrl = config.apiUrl || "https://api.supatype.io"
100
+ const apiUrl = cloudCfg.apiUrl || "https://api.supatype.com"
101
+ const token = cloudCfg.token || process.env["SUPATYPE_ACCESS_TOKEN"] || ""
111
102
  const envName = opts.env || "production"
112
103
 
113
104
  try {
114
105
  const res = await fetch(
115
- `${apiUrl}/platform/v1/projects/${config.projectRef}/environments/${envName}/reset-db-password`,
106
+ `${apiUrl}/platform/v1/projects/${cloudCfg.projectSlug}/environments/${envName}/reset-db-password`,
116
107
  {
117
108
  method: "POST",
118
109
  headers: {
119
- Authorization: `Bearer ${config.accessToken || process.env["SUPATYPE_ACCESS_TOKEN"] || ""}`,
110
+ Authorization: `Bearer ${token}`,
120
111
  "Content-Type": "application/json",
121
112
  },
122
113
  },
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Deploy commands:
3
- * supatype deploy — push schema + build & deploy static site
3
+ * supatype deploy — Supatype Cloud by default (linked via supatype link), else platform projectRef; use --local for engine + DB
4
+ * supatype deploy --local — push schema via local engine + optional static app to .supatype/static
4
5
  * supatype deploy --app-only — only build & deploy the static site
5
6
  * supatype deploy --schema-only — only push schema changes
6
7
  * supatype deploy --skip-build — deploy existing build output (no build step)
@@ -14,7 +15,9 @@ import type { Command } from "commander"
14
15
  import { existsSync, readdirSync, statSync, createReadStream } from "node:fs"
15
16
  import { join } from "node:path"
16
17
  import { loadConfig, loadSchemaAst } from "../config.js"
17
- import { ensureEngine, invokeEngine } from "../engine.js"
18
+ import { connectionString, schemaPathFromProject } from "../project-config.js"
19
+ import { deploySchemaToLinkedProject, loadCloudConfig, pushSchemaToLinkedProject } from "./cloud.js"
20
+ import { ensureEngine, engineRequest, type DiffResult } from "../engine-client.js"
18
21
  import { resolveAppConfig, validateStaticMode, validateBuildOutput, detectPackageManager } from "../app/framework.js"
19
22
  import { TIER_LIMITS, type Tier } from "./deploy-types.js"
20
23
  import { spawnSync } from "node:child_process"
@@ -22,13 +25,19 @@ import { spawnSync } from "node:child_process"
22
25
  export function registerDeploy(program: Command): void {
23
26
  const deploy = program
24
27
  .command("deploy")
25
- .description("Build and deploy your application")
28
+ .description(
29
+ "Deploy schema and app — Supatype Cloud by default when linked (`supatype link`); pass --local for engine + your database",
30
+ )
31
+ .option("--local", "Use local schema engine and database_url from config (skip cloud control plane)")
32
+ .option("--environment <name>", "Cloud environment when using linked project", "production")
26
33
  .option("--app-only", "Skip schema push, only deploy the static site")
27
34
  .option("--schema-only", "Skip app build, only push schema changes")
28
35
  .option("--skip-build", "Deploy existing build output without building")
29
36
  .option("--preview", "Deploy to a temporary preview URL")
30
37
  .option("--yes", "Skip confirmation prompts")
31
38
  .action(async (opts: {
39
+ local?: boolean
40
+ environment?: string
32
41
  appOnly?: boolean
33
42
  schemaOnly?: boolean
34
43
  skipBuild?: boolean
@@ -37,54 +46,77 @@ export function registerDeploy(program: Command): void {
37
46
  }) => {
38
47
  const cwd = process.cwd()
39
48
  const config = loadConfig(cwd)
40
-
41
- // Step 1: Schema push (unless --app-only or --skip-build)
42
- if (!opts.appOnly && !opts.skipBuild) {
43
- console.log("=== Schema Push ===")
44
- await ensureEngine()
45
-
46
- const ast = loadSchemaAst(config.schema, cwd)
47
- const diffResult = invokeEngine(
48
- ["diff", "--connection", config.connection, "--format", "json"],
49
- JSON.stringify(ast),
50
- )
51
- if (diffResult.exitCode !== 0) {
52
- console.error("Schema diff failed:", diffResult.stderr || diffResult.stdout)
53
- process.exit(1)
49
+ const cloudCfg = loadCloudConfig(cwd)
50
+
51
+ let schemaDone = false
52
+
53
+ // Default: cloud — .supatype/cloud.json → control plane schema deploy
54
+ if (
55
+ !opts.local &&
56
+ cloudCfg?.projectSlug &&
57
+ !opts.appOnly &&
58
+ !opts.skipBuild
59
+ ) {
60
+ await deploySchemaToLinkedProject(cwd, opts.environment ?? "production")
61
+ schemaDone = true
62
+ if (opts.schemaOnly) {
63
+ return
54
64
  }
65
+ }
55
66
 
56
- const diff = JSON.parse(diffResult.stdout)
57
- const ops = diff.operations ?? []
67
+ // Step 1: Schema push (unless --app-only or --skip-build, or already done via cloud.json)
68
+ if (!opts.appOnly && !opts.skipBuild && !schemaDone) {
69
+ const ast = loadSchemaAst(schemaPathFromProject(config, cwd), cwd)
58
70
 
59
- if (ops.length > 0) {
60
- console.log(`${ops.length} schema change(s) to apply.`)
61
- const migrateResult = invokeEngine(
62
- ["migrate", "--connection", config.connection],
63
- JSON.stringify(ast),
64
- )
65
- if (migrateResult.exitCode !== 0) {
66
- console.error("Migration failed:", migrateResult.stderr)
67
- process.exit(1)
71
+ if (opts.local) {
72
+ console.log("=== Schema Push (local) ===")
73
+ await ensureEngine()
74
+
75
+ const diff = await engineRequest<DiffResult>("/diff", {
76
+ ast,
77
+ database_url: connectionString(config),
78
+ schema: "public",
79
+ })
80
+
81
+ const ops = diff.operations ?? []
82
+
83
+ if (ops.length > 0) {
84
+ console.log(`${ops.length} schema change(s) to apply.`)
85
+ await engineRequest("/push", {
86
+ ast,
87
+ database_url: connectionString(config),
88
+ schema: "public",
89
+ force: true,
90
+ })
91
+ console.log("Schema changes applied.")
92
+ } else {
93
+ console.log("Schema is up to date.")
68
94
  }
69
- console.log("Schema changes applied.")
95
+ } else if (cloudCfg?.projectSlug) {
96
+ console.log("=== Schema Push (cloud) ===")
97
+ await pushSchemaToLinkedProject(cwd, { force: opts.yes ?? true })
70
98
  } else {
71
- console.log("Schema is up to date.")
99
+ console.error(
100
+ "Not linked to Supatype Cloud. Run: supatype link\n" +
101
+ "Or deploy against your own database: supatype deploy --local",
102
+ )
103
+ process.exit(1)
72
104
  }
73
105
  }
74
106
 
75
107
  // Step 2: App build & deploy (unless --schema-only)
76
108
  if (!opts.schemaOnly) {
77
- if (!config.app) {
109
+ if (!config.build) {
78
110
  if (opts.appOnly) {
79
- console.error("No app configuration found in supatype.config.ts")
111
+ console.error("No build section found in supatype.config.ts")
80
112
  process.exit(1)
81
113
  }
82
- // No app config — just skip app deployment silently
114
+ // No build config — skip app deployment silently
83
115
  return
84
116
  }
85
117
 
86
118
  console.log("\n=== App Build & Deploy ===")
87
- const appConfig = resolveAppConfig(config.app, cwd)
119
+ const appConfig = resolveAppConfig(config.build, cwd)
88
120
 
89
121
  // Validate static mode
90
122
  const staticError = validateStaticMode(appConfig.framework, appConfig.directory)
@@ -107,10 +139,10 @@ export function registerDeploy(program: Command): void {
107
139
  }
108
140
 
109
141
  // Inject Supatype URLs if project is linked
110
- if (config.projectRef) {
111
- buildEnv["NEXT_PUBLIC_SUPATYPE_URL"] = config.apiUrl || `https://${config.projectRef}.supatype.io`
112
- buildEnv["VITE_SUPATYPE_URL"] = buildEnv["NEXT_PUBLIC_SUPATYPE_URL"]
113
- buildEnv["PUBLIC_SUPATYPE_URL"] = buildEnv["NEXT_PUBLIC_SUPATYPE_URL"]
142
+ if (cloudCfg?.projectSlug) {
143
+ buildEnv["NEXT_PUBLIC_SUPATYPE_URL"] = cloudCfg.apiUrl || `https://${cloudCfg.projectSlug}.supatype.dev`
144
+ buildEnv["VITE_SUPATYPE_URL"] = buildEnv["NEXT_PUBLIC_SUPATYPE_URL"]!
145
+ buildEnv["PUBLIC_SUPATYPE_URL"] = buildEnv["NEXT_PUBLIC_SUPATYPE_URL"]!
114
146
  // NEVER inject service_role key — only anon key is safe for client-side
115
147
  }
116
148
 
@@ -151,20 +183,22 @@ export function registerDeploy(program: Command): void {
151
183
  process.exit(1)
152
184
  }
153
185
 
154
- // Deploy
155
- if (config.projectRef) {
156
- // Cloud deployment — upload to API
157
- await deployToCloud(config, appConfig.outputDirectory, opts.preview ?? false)
186
+ // Deploy (--local never uploads to cloud, even if linked)
187
+ if (cloudCfg?.projectSlug && !opts.local) {
188
+ await deployToCloud(
189
+ { projectRef: cloudCfg.projectSlug, apiUrl: cloudCfg.apiUrl, accessToken: cloudCfg.token },
190
+ appConfig.outputDirectory,
191
+ opts.preview ?? false,
192
+ )
158
193
  } else {
159
- // Self-host — copy to serving directory
160
194
  deploySelfHost(appConfig.outputDirectory, cwd)
161
195
  }
162
196
 
163
197
  console.log("\nDeployment complete!")
164
- if (config.projectRef) {
198
+ if (cloudCfg?.projectSlug && !opts.local) {
165
199
  const url = opts.preview
166
- ? `https://preview-${Date.now().toString(36)}.${config.projectRef}.supatype.io`
167
- : `https://${config.projectRef}.supatype.io`
200
+ ? `https://preview-${Date.now().toString(36)}.${cloudCfg.projectSlug}.supatype.dev`
201
+ : `https://${cloudCfg.projectSlug}.supatype.dev`
168
202
  console.log(`URL: ${url}`)
169
203
  }
170
204
  }
@@ -175,16 +209,16 @@ export function registerDeploy(program: Command): void {
175
209
  .command("rollback")
176
210
  .description("Roll back to the previous static site deployment")
177
211
  .action(async () => {
178
- const config = loadConfig(process.cwd())
179
- if (!config.projectRef) {
212
+ const cloudCfg = loadCloudConfig(process.cwd())
213
+ if (!cloudCfg?.projectSlug) {
180
214
  console.error("Not linked to a cloud project. Rollback is only available for cloud deployments.")
181
215
  process.exit(1)
182
216
  }
183
217
 
184
- const apiUrl = config.apiUrl || "https://api.supatype.io"
185
- const token = config.accessToken || process.env["SUPATYPE_ACCESS_TOKEN"] || ""
218
+ const apiUrl = cloudCfg.apiUrl || "https://api.supatype.com"
219
+ const token = cloudCfg.token || process.env["SUPATYPE_ACCESS_TOKEN"] || ""
186
220
 
187
- const res = await fetch(`${apiUrl}/platform/v1/projects/${config.projectRef}/deployments/rollback`, {
221
+ const res = await fetch(`${apiUrl}/platform/v1/projects/${cloudCfg.projectSlug}/deployments/rollback`, {
188
222
  method: "POST",
189
223
  headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
190
224
  })
@@ -204,16 +238,16 @@ export function registerDeploy(program: Command): void {
204
238
  .command("status")
205
239
  .description("Show current deployment status")
206
240
  .action(async () => {
207
- const config = loadConfig(process.cwd())
208
- if (!config.projectRef) {
241
+ const cloudCfg = loadCloudConfig(process.cwd())
242
+ if (!cloudCfg?.projectSlug) {
209
243
  console.error("Not linked to a cloud project.")
210
244
  process.exit(1)
211
245
  }
212
246
 
213
- const apiUrl = config.apiUrl || "https://api.supatype.io"
214
- const token = config.accessToken || process.env["SUPATYPE_ACCESS_TOKEN"] || ""
247
+ const apiUrl = cloudCfg.apiUrl || "https://api.supatype.com"
248
+ const token = cloudCfg.token || process.env["SUPATYPE_ACCESS_TOKEN"] || ""
215
249
 
216
- const res = await fetch(`${apiUrl}/platform/v1/projects/${config.projectRef}/deployments/current`, {
250
+ const res = await fetch(`${apiUrl}/platform/v1/projects/${cloudCfg.projectSlug}/deployments/current`, {
217
251
  headers: { Authorization: `Bearer ${token}` },
218
252
  })
219
253
 
@@ -244,17 +278,17 @@ export function registerDeploy(program: Command): void {
244
278
  .command("logs [version]")
245
279
  .description("Show build logs for a deployment")
246
280
  .action(async (version?: string) => {
247
- const config = loadConfig(process.cwd())
248
- if (!config.projectRef) {
281
+ const cloudCfg = loadCloudConfig(process.cwd())
282
+ if (!cloudCfg?.projectSlug) {
249
283
  console.error("Not linked to a cloud project.")
250
284
  process.exit(1)
251
285
  }
252
286
 
253
- const apiUrl = config.apiUrl || "https://api.supatype.io"
254
- const token = config.accessToken || process.env["SUPATYPE_ACCESS_TOKEN"] || ""
287
+ const apiUrl = cloudCfg.apiUrl || "https://api.supatype.com"
288
+ const token = cloudCfg.token || process.env["SUPATYPE_ACCESS_TOKEN"] || ""
255
289
 
256
290
  const versionPath = version ? `/${version}` : "/current"
257
- const res = await fetch(`${apiUrl}/platform/v1/projects/${config.projectRef}/deployments${versionPath}/logs`, {
291
+ const res = await fetch(`${apiUrl}/platform/v1/projects/${cloudCfg.projectSlug}/deployments${versionPath}/logs`, {
258
292
  headers: { Authorization: `Bearer ${token}` },
259
293
  })
260
294
 
@@ -273,7 +307,7 @@ async function deployToCloud(
273
307
  outputDir: string,
274
308
  isPreview: boolean,
275
309
  ): Promise<void> {
276
- const apiUrl = config.apiUrl || "https://api.supatype.io"
310
+ const apiUrl = config.apiUrl || "https://api.supatype.com"
277
311
  const token = config.accessToken || process.env["SUPATYPE_ACCESS_TOKEN"] || ""
278
312
 
279
313
  console.log("Uploading build artifacts...")