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

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 (309) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +203 -1
  3. package/.turbo/turbo-typecheck.log +1 -1
  4. package/dist/app-config.d.ts +7 -0
  5. package/dist/app-config.d.ts.map +1 -0
  6. package/dist/app-config.js +113 -0
  7. package/dist/app-config.js.map +1 -0
  8. package/dist/augmentation-generator.d.ts +2 -0
  9. package/dist/augmentation-generator.d.ts.map +1 -0
  10. package/dist/augmentation-generator.js +111 -0
  11. package/dist/augmentation-generator.js.map +1 -0
  12. package/dist/binary-cache.d.ts +89 -0
  13. package/dist/binary-cache.d.ts.map +1 -0
  14. package/dist/binary-cache.js +656 -0
  15. package/dist/binary-cache.js.map +1 -0
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/cli.js +13 -7
  18. package/dist/cli.js.map +1 -1
  19. package/dist/commands/admin.d.ts.map +1 -1
  20. package/dist/commands/admin.js +4 -3
  21. package/dist/commands/admin.js.map +1 -1
  22. package/dist/commands/app.d.ts.map +1 -1
  23. package/dist/commands/app.js +56 -209
  24. package/dist/commands/app.js.map +1 -1
  25. package/dist/commands/cache.d.ts +6 -0
  26. package/dist/commands/cache.d.ts.map +1 -0
  27. package/dist/commands/cache.js +105 -0
  28. package/dist/commands/cache.js.map +1 -0
  29. package/dist/commands/cloud.d.ts +12 -0
  30. package/dist/commands/cloud.d.ts.map +1 -1
  31. package/dist/commands/cloud.js +36 -46
  32. package/dist/commands/cloud.js.map +1 -1
  33. package/dist/commands/db.d.ts.map +1 -1
  34. package/dist/commands/db.js +47 -54
  35. package/dist/commands/db.js.map +1 -1
  36. package/dist/commands/deploy.d.ts +2 -1
  37. package/dist/commands/deploy.d.ts.map +1 -1
  38. package/dist/commands/deploy.js +92 -51
  39. package/dist/commands/deploy.js.map +1 -1
  40. package/dist/commands/dev.d.ts +11 -0
  41. package/dist/commands/dev.d.ts.map +1 -1
  42. package/dist/commands/dev.js +751 -384
  43. package/dist/commands/dev.js.map +1 -1
  44. package/dist/commands/diff.d.ts.map +1 -1
  45. package/dist/commands/diff.js +20 -15
  46. package/dist/commands/diff.js.map +1 -1
  47. package/dist/commands/engine.d.ts +1 -3
  48. package/dist/commands/engine.d.ts.map +1 -1
  49. package/dist/commands/engine.js +13 -85
  50. package/dist/commands/engine.js.map +1 -1
  51. package/dist/commands/functions.d.ts.map +1 -1
  52. package/dist/commands/functions.js +92 -105
  53. package/dist/commands/functions.js.map +1 -1
  54. package/dist/commands/generate.d.ts.map +1 -1
  55. package/dist/commands/generate.js +22 -12
  56. package/dist/commands/generate.js.map +1 -1
  57. package/dist/commands/init.d.ts +1 -1
  58. package/dist/commands/init.d.ts.map +1 -1
  59. package/dist/commands/init.js +124 -410
  60. package/dist/commands/init.js.map +1 -1
  61. package/dist/commands/migrate-from-v1.d.ts +5 -0
  62. package/dist/commands/migrate-from-v1.d.ts.map +1 -0
  63. package/dist/commands/migrate-from-v1.js +125 -0
  64. package/dist/commands/migrate-from-v1.js.map +1 -0
  65. package/dist/commands/migrate.d.ts.map +1 -1
  66. package/dist/commands/migrate.js +27 -23
  67. package/dist/commands/migrate.js.map +1 -1
  68. package/dist/commands/pg.d.ts +8 -0
  69. package/dist/commands/pg.d.ts.map +1 -0
  70. package/dist/commands/pg.js +102 -0
  71. package/dist/commands/pg.js.map +1 -0
  72. package/dist/commands/pull.d.ts.map +1 -1
  73. package/dist/commands/pull.js +5 -66
  74. package/dist/commands/pull.js.map +1 -1
  75. package/dist/commands/push.d.ts.map +1 -1
  76. package/dist/commands/push.js +99 -39
  77. package/dist/commands/push.js.map +1 -1
  78. package/dist/commands/seed.d.ts +2 -0
  79. package/dist/commands/seed.d.ts.map +1 -1
  80. package/dist/commands/seed.js +44 -11
  81. package/dist/commands/seed.js.map +1 -1
  82. package/dist/commands/self-host.d.ts +7 -1
  83. package/dist/commands/self-host.d.ts.map +1 -1
  84. package/dist/commands/self-host.js +272 -758
  85. package/dist/commands/self-host.js.map +1 -1
  86. package/dist/commands/self-update.d.ts +9 -0
  87. package/dist/commands/self-update.d.ts.map +1 -0
  88. package/dist/commands/self-update.js +33 -0
  89. package/dist/commands/self-update.js.map +1 -0
  90. package/dist/commands/status.d.ts.map +1 -1
  91. package/dist/commands/status.js +4 -3
  92. package/dist/commands/status.js.map +1 -1
  93. package/dist/commands/types.d.ts +3 -0
  94. package/dist/commands/types.d.ts.map +1 -0
  95. package/dist/commands/types.js +62 -0
  96. package/dist/commands/types.js.map +1 -0
  97. package/dist/commands/update.d.ts +7 -0
  98. package/dist/commands/update.d.ts.map +1 -0
  99. package/dist/commands/update.js +77 -0
  100. package/dist/commands/update.js.map +1 -0
  101. package/dist/components.d.ts +5 -0
  102. package/dist/components.d.ts.map +1 -0
  103. package/dist/components.js +3 -0
  104. package/dist/components.js.map +1 -0
  105. package/dist/config.d.ts +10 -51
  106. package/dist/config.d.ts.map +1 -1
  107. package/dist/config.js +101 -33
  108. package/dist/config.js.map +1 -1
  109. package/dist/docker-postgres.d.ts +39 -0
  110. package/dist/docker-postgres.d.ts.map +1 -0
  111. package/dist/docker-postgres.js +96 -0
  112. package/dist/docker-postgres.js.map +1 -0
  113. package/dist/engine-client.d.ts +67 -0
  114. package/dist/engine-client.d.ts.map +1 -0
  115. package/dist/engine-client.js +156 -0
  116. package/dist/engine-client.js.map +1 -0
  117. package/dist/ensure-binary.d.ts +7 -0
  118. package/dist/ensure-binary.d.ts.map +1 -0
  119. package/dist/ensure-binary.js +17 -0
  120. package/dist/ensure-binary.js.map +1 -0
  121. package/dist/functions-router-gen.d.ts +14 -0
  122. package/dist/functions-router-gen.d.ts.map +1 -0
  123. package/dist/functions-router-gen.js +199 -0
  124. package/dist/functions-router-gen.js.map +1 -0
  125. package/dist/index.d.ts +4 -5
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +2 -3
  128. package/dist/index.js.map +1 -1
  129. package/dist/kong-config.d.ts +21 -0
  130. package/dist/kong-config.d.ts.map +1 -0
  131. package/dist/kong-config.js +60 -0
  132. package/dist/kong-config.js.map +1 -0
  133. package/dist/local-gateway.d.ts +7 -0
  134. package/dist/local-gateway.d.ts.map +1 -0
  135. package/dist/local-gateway.js +9 -0
  136. package/dist/local-gateway.js.map +1 -0
  137. package/dist/local-storage.d.ts +8 -0
  138. package/dist/local-storage.d.ts.map +1 -0
  139. package/dist/local-storage.js +14 -0
  140. package/dist/local-storage.js.map +1 -0
  141. package/dist/pgbouncer-userlist.d.ts +5 -0
  142. package/dist/pgbouncer-userlist.d.ts.map +1 -0
  143. package/dist/pgbouncer-userlist.js +14 -0
  144. package/dist/pgbouncer-userlist.js.map +1 -0
  145. package/dist/postgres-ctl.d.ts +44 -0
  146. package/dist/postgres-ctl.d.ts.map +1 -0
  147. package/dist/postgres-ctl.js +137 -0
  148. package/dist/postgres-ctl.js.map +1 -0
  149. package/dist/process-manager.d.ts +41 -0
  150. package/dist/process-manager.d.ts.map +1 -0
  151. package/dist/process-manager.js +120 -0
  152. package/dist/process-manager.js.map +1 -0
  153. package/dist/project-config.d.ts +215 -0
  154. package/dist/project-config.d.ts.map +1 -0
  155. package/dist/project-config.js +145 -0
  156. package/dist/project-config.js.map +1 -0
  157. package/dist/pull-utils.d.ts +15 -0
  158. package/dist/pull-utils.d.ts.map +1 -1
  159. package/dist/pull-utils.js +12 -0
  160. package/dist/pull-utils.js.map +1 -1
  161. package/dist/release-pins.d.ts +7 -0
  162. package/dist/release-pins.d.ts.map +1 -0
  163. package/dist/release-pins.js +27 -0
  164. package/dist/release-pins.js.map +1 -0
  165. package/dist/release-public-key.d.ts +8 -0
  166. package/dist/release-public-key.d.ts.map +1 -0
  167. package/dist/release-public-key.js +13 -0
  168. package/dist/release-public-key.js.map +1 -0
  169. package/dist/runtime-routes.d.ts +25 -0
  170. package/dist/runtime-routes.d.ts.map +1 -0
  171. package/dist/runtime-routes.js +189 -0
  172. package/dist/runtime-routes.js.map +1 -0
  173. package/dist/scripts/postinstall.d.ts +5 -6
  174. package/dist/scripts/postinstall.d.ts.map +1 -1
  175. package/dist/scripts/postinstall.js +36 -20
  176. package/dist/scripts/postinstall.js.map +1 -1
  177. package/dist/self-host-compose.d.ts +14 -0
  178. package/dist/self-host-compose.d.ts.map +1 -0
  179. package/dist/self-host-compose.js +236 -0
  180. package/dist/self-host-compose.js.map +1 -0
  181. package/dist/storage-provision.d.ts +24 -0
  182. package/dist/storage-provision.d.ts.map +1 -0
  183. package/dist/storage-provision.js +44 -0
  184. package/dist/storage-provision.js.map +1 -0
  185. package/dist/systemd.d.ts +26 -0
  186. package/dist/systemd.d.ts.map +1 -0
  187. package/dist/systemd.js +102 -0
  188. package/dist/systemd.js.map +1 -0
  189. package/dist/tsx-runner.d.ts.map +1 -1
  190. package/dist/tsx-runner.js +9 -2
  191. package/dist/tsx-runner.js.map +1 -1
  192. package/dist/type-extractor.d.ts +31 -0
  193. package/dist/type-extractor.d.ts.map +1 -0
  194. package/dist/type-extractor.js +876 -0
  195. package/dist/type-extractor.js.map +1 -0
  196. package/package.json +4 -3
  197. package/releases/deno/VERSION +1 -0
  198. package/scripts/mirror-deno-release.sh +76 -0
  199. package/src/app-config.ts +128 -0
  200. package/src/augmentation-generator.ts +126 -0
  201. package/src/binary-cache.ts +802 -0
  202. package/src/cli.ts +13 -8
  203. package/src/commands/admin.ts +4 -3
  204. package/src/commands/app.ts +67 -231
  205. package/src/commands/cache.ts +117 -0
  206. package/src/commands/cloud.ts +46 -57
  207. package/src/commands/db.ts +54 -63
  208. package/src/commands/deploy.ts +110 -61
  209. package/src/commands/dev.ts +930 -405
  210. package/src/commands/diff.ts +21 -29
  211. package/src/commands/engine.ts +13 -116
  212. package/src/commands/functions.ts +97 -115
  213. package/src/commands/generate.ts +23 -10
  214. package/src/commands/init.ts +136 -414
  215. package/src/commands/migrate-from-v1.ts +131 -0
  216. package/src/commands/migrate.ts +27 -23
  217. package/src/commands/pg.ts +133 -0
  218. package/src/commands/pull.ts +6 -85
  219. package/src/commands/push.ts +128 -59
  220. package/src/commands/seed.ts +54 -12
  221. package/src/commands/self-host.ts +312 -880
  222. package/src/commands/self-update.ts +45 -0
  223. package/src/commands/status.ts +4 -3
  224. package/src/commands/types.ts +76 -0
  225. package/src/commands/update.ts +92 -0
  226. package/src/components.ts +6 -0
  227. package/src/config.ts +127 -94
  228. package/src/docker-postgres.ts +138 -0
  229. package/src/engine-client.ts +231 -0
  230. package/src/ensure-binary.ts +28 -0
  231. package/src/functions-router-gen.ts +224 -0
  232. package/src/index.ts +4 -12
  233. package/src/kong-config.ts +78 -0
  234. package/src/local-gateway.ts +9 -0
  235. package/src/local-storage.ts +14 -0
  236. package/src/pgbouncer-userlist.ts +15 -0
  237. package/src/postgres-ctl.ts +171 -0
  238. package/src/process-manager.ts +151 -0
  239. package/src/project-config.ts +353 -0
  240. package/src/pull-utils.ts +24 -0
  241. package/src/release-pins.ts +31 -0
  242. package/src/release-public-key.ts +12 -0
  243. package/src/runtime-routes.ts +216 -0
  244. package/src/scripts/postinstall.ts +36 -25
  245. package/src/self-host-compose.ts +257 -0
  246. package/src/storage-provision.ts +58 -0
  247. package/src/systemd.ts +137 -0
  248. package/src/tsx-runner.ts +11 -1
  249. package/src/type-extractor.ts +1016 -0
  250. package/tests/app-command.test.ts +54 -0
  251. package/tests/augmentation-generator.test.ts +59 -0
  252. package/tests/binary-cache-cloud-overrides.test.ts +123 -0
  253. package/tests/cached-artifact-format.test.ts +84 -0
  254. package/tests/cli-help.test.ts +40 -14
  255. package/tests/config.test.ts +140 -37
  256. package/tests/engine-distribution.test.ts +3 -3
  257. package/tests/ensure-binary.test.ts +59 -0
  258. package/tests/init.test.ts +28 -86
  259. package/tests/migrate-from-v1.test.ts +29 -0
  260. package/tests/pg-spawn-env.test.ts +18 -0
  261. package/tests/postgres-archive-tag.test.ts +9 -0
  262. package/tests/pull-utils.test.ts +36 -1
  263. package/tests/release-pins.test.ts +28 -0
  264. package/tests/runtime-contract.test.ts +236 -0
  265. package/tests/seed-discover.test.ts +31 -0
  266. package/tests/tsconfig.json +9 -0
  267. package/tests/type-extractor.test.ts +401 -0
  268. package/tsconfig.tsbuildinfo +1 -1
  269. package/vitest.config.ts +12 -0
  270. package/dist/engine/cache.d.ts +0 -37
  271. package/dist/engine/cache.d.ts.map +0 -1
  272. package/dist/engine/cache.js +0 -121
  273. package/dist/engine/cache.js.map +0 -1
  274. package/dist/engine/download.d.ts +0 -19
  275. package/dist/engine/download.d.ts.map +0 -1
  276. package/dist/engine/download.js +0 -108
  277. package/dist/engine/download.js.map +0 -1
  278. package/dist/engine/platform.d.ts +0 -24
  279. package/dist/engine/platform.d.ts.map +0 -1
  280. package/dist/engine/platform.js +0 -50
  281. package/dist/engine/platform.js.map +0 -1
  282. package/dist/engine/resolve.d.ts +0 -37
  283. package/dist/engine/resolve.d.ts.map +0 -1
  284. package/dist/engine/resolve.js +0 -133
  285. package/dist/engine/resolve.js.map +0 -1
  286. package/dist/engine/update-notify.d.ts +0 -11
  287. package/dist/engine/update-notify.d.ts.map +0 -1
  288. package/dist/engine/update-notify.js +0 -43
  289. package/dist/engine/update-notify.js.map +0 -1
  290. package/dist/engine/verify.d.ts +0 -50
  291. package/dist/engine/verify.d.ts.map +0 -1
  292. package/dist/engine/verify.js +0 -161
  293. package/dist/engine/verify.js.map +0 -1
  294. package/dist/engine-version.d.ts +0 -35
  295. package/dist/engine-version.d.ts.map +0 -1
  296. package/dist/engine-version.js +0 -35
  297. package/dist/engine-version.js.map +0 -1
  298. package/dist/engine.d.ts +0 -34
  299. package/dist/engine.d.ts.map +0 -1
  300. package/dist/engine.js +0 -76
  301. package/dist/engine.js.map +0 -1
  302. package/src/engine/cache.ts +0 -135
  303. package/src/engine/download.ts +0 -143
  304. package/src/engine/platform.ts +0 -66
  305. package/src/engine/resolve.ts +0 -197
  306. package/src/engine/update-notify.ts +0 -50
  307. package/src/engine/verify.ts +0 -206
  308. package/src/engine-version.ts +0 -39
  309. package/src/engine.ts +0 -99
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Release pins read from files under packages/cli/releases/.
3
+ * CI (deno-releases workflow) uses the same paths — bump only releases/deno/VERSION.
4
+ */
5
+
6
+ import { readFileSync } from "node:fs"
7
+ import { dirname, join } from "node:path"
8
+ import { fileURLToPath } from "node:url"
9
+
10
+ const CLI_PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..")
11
+
12
+ function readPinFile(...segments: string[]): string {
13
+ const path = join(CLI_PACKAGE_ROOT, "releases", ...segments)
14
+ let raw: string
15
+ try {
16
+ raw = readFileSync(path, "utf8")
17
+ } catch {
18
+ throw new Error(
19
+ `Missing release pin file: ${path}\n` +
20
+ "Expected packages/cli/releases/… — reinstall @supatype/cli or build from the monorepo.",
21
+ )
22
+ }
23
+ const version = raw.trim()
24
+ if (!/^\d+\.\d+\.\d+/.test(version)) {
25
+ throw new Error(`Invalid pin in ${path}: expected semver like 2.2.0, got ${JSON.stringify(raw)}`)
26
+ }
27
+ return version
28
+ }
29
+
30
+ /** Pinned Deno runtime for edge functions (also published to CDN under /deno/v{version}/). */
31
+ export const DENO_RELEASE_PIN = readPinFile("deno", "VERSION")
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Minisign public key for CDN release verification.
3
+ * Populated at publish via scripts/embed-release-pubkey.mjs (MINISIGN_PUBLIC_KEY secret),
4
+ * or overridden at runtime with SUPATYPE_RELEASE_PUBLIC_KEY.
5
+ */
6
+ export const EMBEDDED_RELEASE_PUBLIC_KEY = "untrusted comment: minisign public key DE133E99689AE71D\nRWQd55pomT4T3t+5FLZZ6+h0DoHrtiuU9RBUHHm9BcFHeGRvW7BXxBCr"
7
+
8
+ export function releasePublicKey(): string {
9
+ const fromEnv = process.env["SUPATYPE_RELEASE_PUBLIC_KEY"]?.trim()
10
+ if (fromEnv) return fromEnv
11
+ return EMBEDDED_RELEASE_PUBLIC_KEY.trim()
12
+ }
@@ -0,0 +1,216 @@
1
+ export interface RuntimeRoute {
2
+ name: string
3
+ serviceName: string
4
+ serviceUrl: string
5
+ paths: string[]
6
+ stripPath?: boolean
7
+ protocols?: string[]
8
+ engineProtected?: boolean
9
+ }
10
+
11
+ export interface RuntimeRouteOptions {
12
+ appUpstream?: string
13
+ staticAppServiceUrl?: string
14
+ /** Compose self-host: supatype-server container (functions proxy). */
15
+ functionsServiceUrl?: string
16
+ /**
17
+ * Self-host Compose: Kong forwards API traffic to supatype-server (unified gateway),
18
+ * which proxies to internal services — same model as `supatype dev`.
19
+ */
20
+ unifiedGateway?: boolean
21
+ }
22
+
23
+ const SERVER_GATEWAY = "http://server:9999"
24
+
25
+ /**
26
+ * Kong routes when self-host uses supatype-server as the single API gateway.
27
+ */
28
+ function runtimeRouteSpecUnified(): RuntimeRoute[] {
29
+ return [
30
+ {
31
+ name: "rest-v1",
32
+ serviceName: "supatype-server-rest",
33
+ serviceUrl: SERVER_GATEWAY,
34
+ paths: ["/rest/v1/"],
35
+ stripPath: false,
36
+ },
37
+ {
38
+ name: "auth-v1",
39
+ serviceName: "supatype-server-auth",
40
+ serviceUrl: SERVER_GATEWAY,
41
+ paths: ["/auth/v1/"],
42
+ stripPath: false,
43
+ },
44
+ {
45
+ name: "admin-v1",
46
+ serviceName: "supatype-server-admin",
47
+ serviceUrl: SERVER_GATEWAY,
48
+ paths: ["/admin/v1/"],
49
+ stripPath: false,
50
+ },
51
+ {
52
+ name: "storage-v1",
53
+ serviceName: "supatype-server-storage",
54
+ serviceUrl: SERVER_GATEWAY,
55
+ paths: ["/storage/v1/"],
56
+ stripPath: false,
57
+ },
58
+ {
59
+ name: "realtime-v1",
60
+ serviceName: "supatype-server-realtime",
61
+ serviceUrl: SERVER_GATEWAY,
62
+ paths: ["/realtime/v1/"],
63
+ stripPath: false,
64
+ protocols: ["http", "https", "ws", "wss"],
65
+ },
66
+ {
67
+ name: "functions-v1",
68
+ serviceName: "supatype-server-functions",
69
+ serviceUrl: SERVER_GATEWAY,
70
+ paths: ["/functions/v1/"],
71
+ stripPath: false,
72
+ },
73
+ {
74
+ name: "graphql-v1",
75
+ serviceName: "supatype-server-graphql",
76
+ serviceUrl: SERVER_GATEWAY,
77
+ paths: ["/graphql/v1/"],
78
+ stripPath: false,
79
+ },
80
+ {
81
+ name: "studio-config-route",
82
+ serviceName: "supatype-server-studio-config",
83
+ serviceUrl: SERVER_GATEWAY,
84
+ paths: ["/studio-config"],
85
+ stripPath: false,
86
+ },
87
+ {
88
+ name: "sql-route",
89
+ serviceName: "supatype-server-sql",
90
+ serviceUrl: SERVER_GATEWAY,
91
+ paths: ["/sql"],
92
+ stripPath: false,
93
+ },
94
+ {
95
+ name: "studio",
96
+ serviceName: "studio",
97
+ serviceUrl: "http://studio:3002",
98
+ paths: ["/studio/"],
99
+ stripPath: true,
100
+ },
101
+ {
102
+ name: "app-root",
103
+ serviceName: "supatype-server-app",
104
+ serviceUrl: SERVER_GATEWAY,
105
+ paths: ["/"],
106
+ stripPath: false,
107
+ },
108
+ ]
109
+ }
110
+
111
+ /**
112
+ * Legacy split-stack routes (PostgREST/storage/realtime directly from Kong).
113
+ * Kept for tests or explicit opt-out only — self-host uses unifiedGateway.
114
+ */
115
+ function runtimeRouteSpecSplit(opts: RuntimeRouteOptions): RuntimeRoute[] {
116
+ const routes: RuntimeRoute[] = [
117
+ {
118
+ name: "rest-v1",
119
+ serviceName: "rest-v1",
120
+ serviceUrl: "http://postgrest:3000",
121
+ paths: ["/rest/v1/"],
122
+ stripPath: true,
123
+ },
124
+ {
125
+ name: "auth-v1",
126
+ serviceName: "auth-v1",
127
+ serviceUrl: "http://server:9999",
128
+ paths: ["/auth/v1/"],
129
+ stripPath: true,
130
+ },
131
+ {
132
+ name: "admin-v1",
133
+ serviceName: "admin-v1",
134
+ serviceUrl: "http://server:9999",
135
+ paths: ["/admin/v1/"],
136
+ stripPath: false,
137
+ },
138
+ {
139
+ name: "storage-v1",
140
+ serviceName: "storage-v1",
141
+ serviceUrl: "http://storage:5000",
142
+ paths: ["/storage/v1/"],
143
+ stripPath: true,
144
+ },
145
+ {
146
+ name: "realtime-v1",
147
+ serviceName: "realtime-v1",
148
+ serviceUrl: "http://realtime:4000",
149
+ paths: ["/realtime/v1/"],
150
+ stripPath: true,
151
+ protocols: ["http", "https", "ws", "wss"],
152
+ },
153
+ {
154
+ name: "functions-v1",
155
+ serviceName: "functions-v1",
156
+ serviceUrl: opts.functionsServiceUrl?.trim() || "http://server:9999",
157
+ paths: ["/functions/v1/"],
158
+ stripPath: false,
159
+ },
160
+ {
161
+ name: "studio",
162
+ serviceName: "studio",
163
+ serviceUrl: "http://studio:3002",
164
+ paths: ["/studio/"],
165
+ stripPath: true,
166
+ },
167
+ {
168
+ name: "studio-config-route",
169
+ serviceName: "engine-studio-config",
170
+ serviceUrl: "http://engine:7500",
171
+ paths: ["/studio-config"],
172
+ engineProtected: true,
173
+ },
174
+ {
175
+ name: "sql-route",
176
+ serviceName: "engine-sql",
177
+ serviceUrl: "http://engine:7500",
178
+ paths: ["/sql"],
179
+ engineProtected: true,
180
+ },
181
+ ]
182
+
183
+ const staticServiceUrl = opts.staticAppServiceUrl?.trim()
184
+ if (staticServiceUrl && staticServiceUrl.length > 0) {
185
+ routes.push({
186
+ name: "app-root",
187
+ serviceName: "app-root",
188
+ serviceUrl: staticServiceUrl,
189
+ paths: ["/"],
190
+ stripPath: false,
191
+ })
192
+ return routes
193
+ }
194
+
195
+ if (opts.appUpstream && opts.appUpstream.trim().length > 0) {
196
+ routes.push({
197
+ name: "app-root",
198
+ serviceName: "app-root",
199
+ serviceUrl: opts.appUpstream.trim(),
200
+ paths: ["/"],
201
+ stripPath: false,
202
+ })
203
+ }
204
+
205
+ return routes
206
+ }
207
+
208
+ /**
209
+ * Shared route contract used by local/self-host renderers.
210
+ */
211
+ export function runtimeRouteSpec(opts: RuntimeRouteOptions = {}): RuntimeRoute[] {
212
+ if (opts.unifiedGateway) {
213
+ return runtimeRouteSpecUnified()
214
+ }
215
+ return runtimeRouteSpecSplit(opts)
216
+ }
@@ -1,40 +1,51 @@
1
1
  /**
2
- * Postinstall script — downloads the correct engine binary for the current
3
- * platform and caches it at ~/.supatype/engine/{version}/supatype-engine[.exe].
2
+ * Postinstall script — downloads component binaries on first install.
4
3
  *
5
- * Pattern: same as Prisma, esbuild, SWC, Turbo.
4
+ * Components: supatype-engine, supatype-server, supatype-pg (Postgres), deno.
5
+ * Binaries are cached in ~/.supatype/cache/{component}/{version}/.
6
6
  *
7
- * The binary is verified via:
8
- * 1. Minisign signature on checksums.sha256 (proves checksum file is authentic)
9
- * 2. SHA256 checksum of binary (proves binary matches signed checksum)
7
+ * Failures are non-fatal: an installation message is printed and the user
8
+ * can run `supatype update` manually to retry.
10
9
  */
11
10
 
12
- import { ENGINE_VERSION } from "../engine-version.js"
13
- import { detectPlatform } from "../engine/platform.js"
14
- import { hasCachedBinary } from "../engine/cache.js"
15
- import { resolveEngine } from "../engine/resolve.js"
11
+ import { download, currentPlatform, fetchAllLatestVersions, type Component } from "../binary-cache.js"
16
12
 
17
- async function main(): Promise<void> {
18
- const platform = detectPlatform()
13
+ async function main() {
14
+ const platform = currentPlatform()
19
15
 
20
- // Skip if already cached at the right version
21
- if (hasCachedBinary(ENGINE_VERSION, platform)) {
22
- console.log(`[supatype] Engine v${ENGINE_VERSION} already cached.`)
16
+ let versions: Record<Component, string>
17
+ try {
18
+ console.log("[supatype] Fetching latest component versions...")
19
+ versions = await fetchAllLatestVersions()
20
+ } catch (err) {
21
+ console.error(`[supatype] Failed to fetch latest versions: ${(err as Error).message}`)
22
+ console.error("[supatype] Run 'supatype update' to download component binaries.")
23
23
  return
24
24
  }
25
25
 
26
- console.log(
27
- `[supatype] Downloading engine v${ENGINE_VERSION} for ${platform.os}-${platform.arch}...`,
28
- )
26
+ console.log(`[supatype] Downloading component binaries for ${platform.os}/${platform.arch}...`)
29
27
 
30
- const result = await resolveEngine(ENGINE_VERSION)
31
- console.log(`[supatype] Engine installed at ${result.binaryPath}`)
28
+ const components = Object.entries(versions) as [Component, string][]
29
+
30
+ let anyFailed = false
31
+ for (const [component, version] of components) {
32
+ try {
33
+ await download(component, version, platform)
34
+ } catch (err) {
35
+ console.error(`[supatype] Failed to download ${component} v${version}: ${(err as Error).message}`)
36
+ anyFailed = true
37
+ }
38
+ }
39
+
40
+ if (anyFailed) {
41
+ console.error("[supatype] Some downloads failed. Run 'supatype update' to retry.")
42
+ } else {
43
+ console.log("[supatype] All component binaries downloaded successfully.")
44
+ }
32
45
  }
33
46
 
34
47
  main().catch((err) => {
35
- console.error("[supatype] Engine download failed:", err.message)
36
- console.error(
37
- "[supatype] You can still use the CLI — the engine will be downloaded on first use.",
38
- )
39
- // Don't exit(1) — let npm install succeed even if binary download fails.
48
+ // Non-fatal postinstall failures should not break npm install.
49
+ console.error("[supatype] Postinstall failed:", err)
50
+ process.exit(0)
40
51
  })
@@ -0,0 +1,257 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs"
2
+ import { dirname, join, relative, resolve } from "node:path"
3
+ import { spawnSync } from "node:child_process"
4
+ import type { SupatypeProjectConfig } from "./project-config.js"
5
+ import { buildKongDeclarative } from "./kong-config.js"
6
+
7
+ export interface SelfHostComposePaths {
8
+ dir: string
9
+ composePath: string
10
+ kongPath: string
11
+ nginxPath: string
12
+ }
13
+
14
+ export function selfHostComposePaths(cwd: string): SelfHostComposePaths {
15
+ const dir = resolve(cwd, ".supatype", "self-host")
16
+ return {
17
+ dir,
18
+ composePath: join(dir, "docker-compose.yml"),
19
+ kongPath: join(dir, "kong.yml"),
20
+ nginxPath: join(dir, "nginx.conf"),
21
+ }
22
+ }
23
+
24
+ export function appUpstreamForCompose(config: SupatypeProjectConfig): string | undefined {
25
+ if (config.app.mode !== "proxy") return undefined
26
+ const upstream = config.app.upstream?.trim()
27
+ return upstream && upstream.length > 0 ? upstream : undefined
28
+ }
29
+
30
+ export function staticDirForCompose(config: SupatypeProjectConfig): string | undefined {
31
+ if (config.app.mode !== "static") return undefined
32
+ const dir = config.app.static_dir?.trim()
33
+ return dir && dir.length > 0 ? dir : "./public"
34
+ }
35
+
36
+ function projectMountPath(cwd: string): string {
37
+ const composeDir = resolve(cwd, ".supatype", "self-host")
38
+ let rel = relative(composeDir, resolve(cwd)).replace(/\\/g, "/")
39
+ if (!rel.startsWith(".") && !rel.startsWith("/")) {
40
+ rel = `./${rel}`
41
+ }
42
+ return rel || "../.."
43
+ }
44
+
45
+ function serverAppEnvForCompose(config: SupatypeProjectConfig): string {
46
+ const mode = config.app.mode ?? "none"
47
+ const lines = [` SUPATYPE_APP_MODE: ${mode}`]
48
+ if (mode === "static") {
49
+ const dir = staticDirForCompose(config) ?? "./public"
50
+ lines.push(` SUPATYPE_APP_STATIC_DIR: /project/${dir.replace(/^\.\//, "")}`)
51
+ } else if (mode === "proxy" && config.app.upstream?.trim()) {
52
+ lines.push(` SUPATYPE_APP_UPSTREAM: ${config.app.upstream.trim()}`)
53
+ }
54
+ return lines.join("\n")
55
+ }
56
+
57
+ export function renderSelfHostCompose(config: SupatypeProjectConfig, cwd: string = process.cwd()): string {
58
+ const projectMount = projectMountPath(cwd)
59
+ const appEnv = serverAppEnvForCompose(config)
60
+
61
+ return `# Generated by supatype self-host compose
62
+ # Kong → supatype-server (unified gateway) → internal PostgREST / storage / etc.
63
+ services:
64
+ db:
65
+ image: \${SUPATYPE_POSTGRES_IMAGE:-supatype/postgres:17-latest}
66
+ environment:
67
+ POSTGRES_USER: \${POSTGRES_USER:-supatype_admin}
68
+ POSTGRES_PASSWORD: \${POSTGRES_PASSWORD:-postgres}
69
+ POSTGRES_DB: \${POSTGRES_DB:-supatype}
70
+ ports:
71
+ - "5432:5432"
72
+ volumes:
73
+ - db-data:/var/lib/postgresql/data
74
+ healthcheck:
75
+ test: ["CMD-SHELL", "pg_isready -U \${POSTGRES_USER:-supatype_admin}"]
76
+ interval: 5s
77
+ timeout: 5s
78
+ retries: 20
79
+
80
+ postgrest:
81
+ image: postgrest/postgrest:v12.2.8
82
+ expose:
83
+ - "3000"
84
+ environment:
85
+ PGRST_DB_URI: postgresql://\${POSTGRES_USER:-supatype_admin}:\${POSTGRES_PASSWORD:-postgres}@db:5432/\${POSTGRES_DB:-supatype}
86
+ PGRST_DB_SCHEMA: "public, supatype"
87
+ PGRST_DB_ANON_ROLE: anon
88
+ PGRST_JWT_SECRET: \${JWT_SECRET:-super-secret-jwt-token-change-in-production}
89
+ PGRST_DB_EXTRA_SEARCH_PATH: public,extensions
90
+ PGRST_DB_POOL: 3
91
+ depends_on:
92
+ db:
93
+ condition: service_healthy
94
+
95
+ storage:
96
+ image: \${SUPATYPE_STORAGE_IMAGE:-supatype/storage:latest}
97
+ expose:
98
+ - "5000"
99
+ environment:
100
+ PORT: 5000
101
+ DATABASE_URL: "postgresql://\${POSTGRES_USER:-supatype_admin}:\${POSTGRES_PASSWORD:-postgres}@db:5432/\${POSTGRES_DB:-supatype}"
102
+ JWT_SECRET: \${JWT_SECRET:-super-secret-jwt-token-change-in-production}
103
+ S3_ENDPOINT: http://minio:9000
104
+ S3_REGION: us-east-1
105
+ S3_ACCESS_KEY: supatype
106
+ S3_SECRET_KEY: supatype-secret
107
+ S3_FORCE_PATH_STYLE: "true"
108
+ depends_on:
109
+ db:
110
+ condition: service_healthy
111
+
112
+ functions-worker:
113
+ image: \${SUPATYPE_FUNCTIONS_WORKER_IMAGE:-supatype/functions-worker:latest}
114
+ expose:
115
+ - "8001"
116
+ volumes:
117
+ - ${projectMount}:/project:ro
118
+ environment:
119
+ SUPATYPE_FUNCTIONS_ROOT: /project/functions
120
+ SUPATYPE_DENO_FUNCTIONS_DIR: /project/functions
121
+ PORT: "8001"
122
+ SUPATYPE_URL: \${API_EXTERNAL_URL:-http://localhost:18473}
123
+ SUPATYPE_ANON_KEY: \${ANON_KEY:-}
124
+ SUPATYPE_SERVICE_ROLE_KEY: \${SERVICE_ROLE_KEY:-}
125
+ depends_on:
126
+ db:
127
+ condition: service_healthy
128
+
129
+ server:
130
+ image: \${SUPATYPE_SERVER_IMAGE:-\${SUPATYPE_AUTH_IMAGE:-supatype/server:latest}}
131
+ ports:
132
+ - "9999:9999"
133
+ volumes:
134
+ - ${projectMount}:/project:ro
135
+ working_dir: /project
136
+ environment:
137
+ SUPATYPE_MODE: standalone
138
+ SUPATYPE_MANIFEST_PATH: /project/.supatype/manifest.json
139
+ SUPATYPE_ADMIN_CONFIG_PATH: /project/.supatype/admin-config.json
140
+ SUPATYPE_API_CONFIG_PATH: /project/.supatype/api-config.json
141
+ SUPATYPE_POSTGREST_URL: http://postgrest:3000
142
+ SUPATYPE_GRAPHQL_URL: http://postgrest:3000
143
+ SUPATYPE_STORAGE_URL: http://storage:5000
144
+ SUPATYPE_URL: \${API_EXTERNAL_URL:-http://localhost:18473}
145
+ SUPATYPE_ANON_KEY: \${ANON_KEY:-}
146
+ SUPATYPE_SERVICE_ROLE_KEY: \${SERVICE_ROLE_KEY:-}
147
+ SUPATYPE_SQL_DATABASE_URL: "postgresql://\${POSTGRES_USER:-supatype_admin}:\${POSTGRES_PASSWORD:-postgres}@db:5432/\${POSTGRES_DB:-supatype}"
148
+ SUPATYPE_DENO_FUNCTIONS_DIR: /project/functions
149
+ SUPATYPE_FUNCTIONS_WORKER_URL: http://functions-worker:8001
150
+ ${appEnv}
151
+ GOTRUE_API_HOST: 0.0.0.0
152
+ GOTRUE_API_PORT: 9999
153
+ API_EXTERNAL_URL: \${API_EXTERNAL_URL:-http://localhost:18473}
154
+ GOTRUE_API_EXTERNAL_URL: \${API_EXTERNAL_URL:-http://localhost:18473}
155
+ GOTRUE_DB_DRIVER: postgres
156
+ GOTRUE_DB_DATABASE_URL: "postgres://\${POSTGRES_USER:-supatype_admin}:\${POSTGRES_PASSWORD:-postgres}@db:5432/\${POSTGRES_DB:-supatype}?search_path=auth"
157
+ GOTRUE_SITE_URL: \${SITE_URL:-http://localhost:3000}
158
+ GOTRUE_JWT_SECRET: \${JWT_SECRET:-super-secret-jwt-token-change-in-production}
159
+ GOTRUE_JWT_EXP: 3600
160
+ GOTRUE_JWT_AUD: authenticated
161
+ GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated
162
+ GOTRUE_JWT_ADMIN_ROLES: service_role,supatype_admin
163
+ GOTRUE_MAILER_AUTOCONFIRM: \${GOTRUE_MAILER_AUTOCONFIRM:-true}
164
+ GOTRUE_DISABLE_SIGNUP: \${DISABLE_SIGNUP:-false}
165
+ depends_on:
166
+ db:
167
+ condition: service_healthy
168
+ postgrest:
169
+ condition: service_started
170
+ storage:
171
+ condition: service_started
172
+ functions-worker:
173
+ condition: service_started
174
+
175
+ minio:
176
+ image: minio/minio:RELEASE.2024-11-07T00-52-20Z
177
+ command: server /data --console-address ":9001"
178
+ environment:
179
+ MINIO_ROOT_USER: supatype
180
+ MINIO_ROOT_PASSWORD: supatype-secret
181
+ ports:
182
+ - "9000:9000"
183
+ - "9001:9001"
184
+ volumes:
185
+ - minio-data:/data
186
+
187
+ studio:
188
+ image: \${SUPATYPE_STUDIO_IMAGE:-supatype/studio:latest}
189
+ expose:
190
+ - "3002"
191
+
192
+ kong:
193
+ image: kong:3.6
194
+ environment:
195
+ KONG_DATABASE: "off"
196
+ KONG_DECLARATIVE_CONFIG: /etc/kong/kong.yml
197
+ KONG_PROXY_ACCESS_LOG: /dev/stdout
198
+ KONG_ADMIN_ACCESS_LOG: /dev/stdout
199
+ KONG_PROXY_ERROR_LOG: /dev/stderr
200
+ KONG_ADMIN_ERROR_LOG: /dev/stderr
201
+ volumes:
202
+ - ./kong.yml:/etc/kong/kong.yml:ro
203
+ ports:
204
+ - "18473:8000"
205
+ depends_on:
206
+ - server
207
+ - studio
208
+
209
+ volumes:
210
+ db-data:
211
+ minio-data:
212
+ `
213
+ }
214
+
215
+ function ensureComposeManifest(cwd: string): void {
216
+ const manifestPath = join(cwd, ".supatype", "manifest.json")
217
+ if (existsSync(manifestPath)) return
218
+ mkdirSync(dirname(manifestPath), { recursive: true })
219
+ const manifest = {
220
+ schema: "public",
221
+ postgrest_url: "http://postgrest:3000",
222
+ storage_url: "http://storage:5000",
223
+ realtime_enabled: true,
224
+ functions_enabled: false,
225
+ }
226
+ writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8")
227
+ }
228
+
229
+ export function writeSelfHostCompose(cwd: string, config: SupatypeProjectConfig): SelfHostComposePaths {
230
+ const paths = selfHostComposePaths(cwd)
231
+ mkdirSync(paths.dir, { recursive: true })
232
+ ensureComposeManifest(cwd)
233
+ writeFileSync(paths.composePath, renderSelfHostCompose(config, cwd), "utf8")
234
+ writeFileSync(
235
+ paths.kongPath,
236
+ buildKongDeclarative({
237
+ unifiedGateway: true,
238
+ }),
239
+ "utf8",
240
+ )
241
+ return paths
242
+ }
243
+
244
+ export function runDockerCompose(composePath: string, args: string[], projectRoot: string = process.cwd()): number {
245
+ const envFile = resolve(projectRoot, ".env")
246
+ const composeArgs = ["compose", "-f", composePath]
247
+ if (existsSync(envFile)) {
248
+ composeArgs.push("--env-file", envFile)
249
+ }
250
+ composeArgs.push(...args)
251
+ const result = spawnSync(
252
+ "docker",
253
+ composeArgs,
254
+ { stdio: "inherit", cwd: dirname(composePath) },
255
+ )
256
+ return result.status ?? 1
257
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Provision storage buckets declared in a schema AST via the storage server API.
3
+ *
4
+ * The storage server is the authority on bucket existence — going through the API
5
+ * ensures it creates any backing resources (directories, S3 buckets, etc.).
6
+ * Buckets already registered return 409 Conflict, which is treated as success.
7
+ */
8
+
9
+ export interface BucketSpec {
10
+ id: string
11
+ public: boolean
12
+ allowed_mime_types?: string[] | null
13
+ file_size_limit?: number | null
14
+ access_mode?: "public" | "private" | "custom"
15
+ s3_bucket_policy?: string | null
16
+ }
17
+
18
+ /**
19
+ * Ensure all declared buckets exist in the storage server.
20
+ *
21
+ * @param storageApiUrl Base URL of the storage API, e.g. "http://localhost:54321/storage/v1"
22
+ * @param serviceRoleKey A service_role JWT for the storage server
23
+ * @param buckets Buckets to provision (from the resolved AST)
24
+ */
25
+ export async function provisionBuckets(
26
+ storageApiUrl: string,
27
+ serviceRoleKey: string,
28
+ buckets: BucketSpec[],
29
+ ): Promise<void> {
30
+ const base = storageApiUrl.replace(/\/$/, "")
31
+ const headers = {
32
+ "Authorization": `Bearer ${serviceRoleKey}`,
33
+ "Content-Type": "application/json",
34
+ }
35
+
36
+ for (const bucket of buckets) {
37
+ const body = JSON.stringify({
38
+ id: bucket.id,
39
+ name: bucket.id,
40
+ public: bucket.public,
41
+ ...(bucket.allowed_mime_types != null && { allowed_mime_types: bucket.allowed_mime_types }),
42
+ ...(bucket.file_size_limit != null && { file_size_limit: bucket.file_size_limit }),
43
+ ...(bucket.access_mode != null && { access_mode: bucket.access_mode }),
44
+ ...(bucket.s3_bucket_policy != null &&
45
+ bucket.s3_bucket_policy !== "" && { s3_bucket_policy: bucket.s3_bucket_policy }),
46
+ })
47
+
48
+ const res = await fetch(`${base}/bucket`, { method: "POST", headers, body })
49
+ .catch(() => null)
50
+
51
+ if (res === null) continue // server not reachable — skip silently
52
+ if (res.status === 409) continue // already exists — fine
53
+ if (!res.ok) {
54
+ const msg = await res.text().catch(() => res.statusText)
55
+ console.warn(`[storage] Failed to provision bucket "${bucket.id}": ${msg}`)
56
+ }
57
+ }
58
+ }