@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
@@ -0,0 +1,351 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"
3
+ import { join } from "node:path"
4
+ import { tmpdir } from "node:os"
5
+ import { runtimeRouteSpec } from "../src/runtime-routes.js"
6
+ import { buildKongDeclarative } from "../src/kong-config.js"
7
+ import { renderSelfHostCompose, writeSelfHostCompose } from "../src/self-host-compose.js"
8
+ import { updateAppConfigInProject } from "../src/app-config.js"
9
+ import type { SupatypeProjectConfig } from "../src/project-config.js"
10
+ import { DENO_RELEASE_PIN } from "../src/release-pins.js"
11
+
12
+ const baseConfig: SupatypeProjectConfig = {
13
+ project: { name: "acme" },
14
+ database: { provider: "docker" },
15
+ server: { mode: "dev" },
16
+ app: { mode: "none" },
17
+ versions: {
18
+ engine: "0.4.2",
19
+ server: "0.1.0",
20
+ postgres: "17.2",
21
+ deno: DENO_RELEASE_PIN,
22
+ },
23
+ }
24
+
25
+ describe("runtime contract", () => {
26
+ it("includes core route families", () => {
27
+ const paths = runtimeRouteSpec().flatMap((r) => r.paths)
28
+ for (const path of ["/rest/v1/", "/auth/v1/", "/storage/v1/", "/realtime/v1/", "/functions/v1/", "/graphql/v1"]) {
29
+ expect(paths).toContain(path)
30
+ }
31
+ })
32
+
33
+ it("renders app root route when upstream is provided", () => {
34
+ const paths = runtimeRouteSpec({ appUpstream: "http://app:3000" }).flatMap((r) => r.paths)
35
+ expect(paths).toContain("/")
36
+ })
37
+
38
+ it("renders app root route for static service URL", () => {
39
+ const paths = runtimeRouteSpec({ staticAppServiceUrl: "http://static-app:8080" }).flatMap((r) => r.paths)
40
+ expect(paths).toContain("/")
41
+ })
42
+
43
+ it("self-host kong uses unified supatype-server gateway", () => {
44
+ const kong = buildKongDeclarative({ unifiedGateway: true })
45
+ expect(kong).toContain("http://server:9999")
46
+ expect(kong).toContain("/rest/v1/")
47
+ expect(kong).toContain("/auth/v1/")
48
+ expect(kong).toContain("/storage/v1/")
49
+ expect(kong).toContain("/realtime/v1/")
50
+ expect(kong).toContain("/functions/v1/")
51
+ expect(kong).toContain("http://postgrest:3000/rpc/graphql")
52
+ expect(kong).toContain("Content-Profile:graphql_public")
53
+ expect(kong).not.toContain("http://storage:5000")
54
+ })
55
+
56
+ it("self-host kong routes studio auth and proxy to supatype-server before static studio", () => {
57
+ const kong = buildKongDeclarative({ unifiedGateway: true })
58
+ const studioAuthIdx = kong.indexOf("/studio/auth/")
59
+ const studioProxyIdx = kong.indexOf("/studio/proxy/")
60
+ const studioStaticIdx = kong.lastIndexOf("/studio/")
61
+ expect(studioAuthIdx).toBeGreaterThan(-1)
62
+ expect(studioProxyIdx).toBeGreaterThan(-1)
63
+ expect(studioAuthIdx).toBeLessThan(studioStaticIdx)
64
+ expect(studioProxyIdx).toBeLessThan(studioStaticIdx)
65
+ expect(kong).toContain("name: supatype-server-studio-auth")
66
+ expect(kong).toContain("name: supatype-server-studio-proxy")
67
+ })
68
+
69
+ it("self-host kong proxies exact /studio to studio UI", () => {
70
+ const kong = buildKongDeclarative({ unifiedGateway: true })
71
+ expect(kong).toContain("name: studio-exact")
72
+ expect(kong).toContain("~/studio$")
73
+ expect(kong).not.toContain("name: redirect")
74
+ })
75
+
76
+ it("kong declarative output contains route contract paths", () => {
77
+ const kong = buildKongDeclarative({ appUpstream: "http://app:3000" })
78
+ expect(kong).toContain("/rest/v1/")
79
+ expect(kong).toContain("/auth/v1/")
80
+ expect(kong).toContain("/storage/v1/")
81
+ expect(kong).toContain("/realtime/v1/")
82
+ expect(kong).toContain("/functions/v1/")
83
+ expect(kong).toContain("- /")
84
+ })
85
+
86
+ it("self-host compose render is deterministic for same config", () => {
87
+ const first = renderSelfHostCompose({ ...baseConfig, app: { mode: "proxy", upstream: "http://app:3000" } })
88
+ const second = renderSelfHostCompose({ ...baseConfig, app: { mode: "proxy", upstream: "http://app:3000" } })
89
+ expect(first).toBe(second)
90
+ })
91
+
92
+ it("self-host compose does not inject a synthetic app-proxy service", () => {
93
+ const compose = renderSelfHostCompose({ ...baseConfig, app: { mode: "proxy", upstream: "http://app:3000" } })
94
+ expect(compose).not.toContain("ghcr.io/supatype/app-proxy")
95
+ expect(compose).not.toContain("\n app:\n")
96
+ })
97
+
98
+ it("self-host compose configures static app on supatype-server", () => {
99
+ const compose = renderSelfHostCompose({ ...baseConfig, app: { mode: "static", static_dir: "./public" } })
100
+ expect(compose).toContain('SUPATYPE_APP_MODE: static')
101
+ expect(compose).toContain("SUPATYPE_APP_STATIC_DIR: /project/public")
102
+ expect(compose).not.toContain("static-app:")
103
+ })
104
+
105
+ it("self-host compose includes schema-engine tools profile", () => {
106
+ const compose = renderSelfHostCompose(baseConfig)
107
+ expect(compose).toContain("\n schema-engine:\n")
108
+ expect(compose).toContain('profiles: ["tools"]')
109
+ expect(compose).toContain("supatype/schema-engine:latest")
110
+ })
111
+
112
+ it("self-host compose mounts project root at /project (project-directory relative)", () => {
113
+ const compose = renderSelfHostCompose(baseConfig)
114
+ expect(compose).toContain("- .:/project")
115
+ expect(compose).not.toMatch(/- \.\.\/\.\.:\/project/)
116
+ })
117
+
118
+ it("self-host compose mounts kong.yml from .supatype/self-host (project-directory relative)", () => {
119
+ const compose = renderSelfHostCompose(baseConfig)
120
+ expect(compose).toContain("- .supatype/self-host/kong.yml:/etc/kong/kong.yml:ro")
121
+ expect(compose).not.toContain("- ./kong.yml:/etc/kong/kong.yml:ro")
122
+ })
123
+
124
+ it("devLocal compose omits host-published db and server ports", () => {
125
+ const compose = renderSelfHostCompose(baseConfig, process.cwd(), { devLocal: true })
126
+ expect(compose).not.toContain('"5432:5432"')
127
+ expect(compose).not.toContain('"9999:9999"')
128
+ expect(compose).toContain("${SUPATYPE_KONG_PORT:-18473}:8000")
129
+ expect(compose).not.toContain("SUPATYPE_DEV_DB_PORT")
130
+ })
131
+
132
+ it("devLocal compose publishes db to host when overrides.engine is set", () => {
133
+ const compose = renderSelfHostCompose(
134
+ { ...baseConfig, overrides: { engine: "/tmp/supatype-engine" } },
135
+ process.cwd(),
136
+ { devLocal: true },
137
+ )
138
+ expect(compose).toContain("127.0.0.1:${SUPATYPE_DEV_DB_PORT:-54329}:5432")
139
+ expect(compose).not.toContain('"5432:5432"')
140
+ })
141
+
142
+ it("devLocal proxy upstream rewrites localhost to host.docker.internal", () => {
143
+ const compose = renderSelfHostCompose(
144
+ { ...baseConfig, app: { mode: "proxy", upstream: "http://127.0.0.1:4321" } },
145
+ process.cwd(),
146
+ { devLocal: true },
147
+ )
148
+ expect(compose).toContain("SUPATYPE_APP_UPSTREAM: http://host.docker.internal:4321")
149
+ })
150
+
151
+ it("devLocal compose omits studio container when overrides.studio is set", () => {
152
+ const compose = renderSelfHostCompose(
153
+ { ...baseConfig, overrides: { studio: "../supatype/packages/studio" } },
154
+ process.cwd(),
155
+ { devLocal: true },
156
+ )
157
+ expect(compose).not.toContain("\n studio:\n")
158
+ expect(compose).not.toContain("depends_on:\n - server\n - studio")
159
+ })
160
+
161
+ it("devLocal kong routes studio to host Vite when overrides.studio is set", () => {
162
+ const dir = mkdtempSync(join(tmpdir(), "supatype-studio-host-"))
163
+ try {
164
+ writeSelfHostCompose(
165
+ dir,
166
+ { ...baseConfig, overrides: { studio: "../supatype/packages/studio" } },
167
+ { devLocal: true },
168
+ )
169
+ const kong = readFileSync(join(dir, ".supatype", "self-host", "kong.yml"), "utf8")
170
+ expect(kong).toContain("http://host.docker.internal:3002")
171
+ expect(kong).not.toContain("http://studio:3002")
172
+ expect(kong).toContain("strip_path: false")
173
+ } finally {
174
+ rmSync(dir, { recursive: true, force: true })
175
+ }
176
+ })
177
+
178
+ it("devLocal compose enables STUDIO_OPEN_DEV on supatype-server", () => {
179
+ const compose = renderSelfHostCompose(baseConfig, process.cwd(), { devLocal: true })
180
+ expect(compose).toContain('STUDIO_OPEN_DEV: "1"')
181
+ })
182
+
183
+ it("production self-host compose does not enable STUDIO_OPEN_DEV", () => {
184
+ const compose = renderSelfHostCompose(baseConfig)
185
+ expect(compose).not.toContain("STUDIO_OPEN_DEV")
186
+ })
187
+
188
+ it("self-host studio SUPATYPE_CLOUD_JSON omits serviceRoleKey", () => {
189
+ const compose = renderSelfHostCompose(baseConfig)
190
+ const match = compose.match(/SUPATYPE_CLOUD_JSON: '([^']+)'/)
191
+ expect(match).not.toBeNull()
192
+ const parsed = JSON.parse(match![1]!) as Record<string, unknown>
193
+ expect(parsed).toHaveProperty("url")
194
+ expect(parsed).toHaveProperty("anonKey")
195
+ expect(parsed).not.toHaveProperty("serviceRoleKey")
196
+ })
197
+
198
+ it("self-host compose runs per-project functions-worker and proxies via server", () => {
199
+ const compose = renderSelfHostCompose(baseConfig)
200
+ expect(compose).toContain("\n functions-worker:\n")
201
+ expect(compose).toContain("SUPATYPE_FUNCTIONS_WORKER_URL: http://functions-worker:8001")
202
+ expect(compose).toContain("SUPATYPE_FUNCTIONS_ROOT: /project/functions")
203
+ expect(compose).not.toContain("deploy/functions")
204
+ expect(compose).not.toContain("supatype-functions")
205
+ })
206
+
207
+ it("app config updater writes proxy mode intent", () => {
208
+ const dir = mkdtempSync(join(tmpdir(), "supatype-app-config-"))
209
+ try {
210
+ const configPath = join(dir, "supatype.config.ts")
211
+ writeFileSync(
212
+ configPath,
213
+ `export default {
214
+ project: { name: "x" },
215
+ database: { provider: "docker" },
216
+ server: { mode: "dev" },
217
+ app: {
218
+ mode: "none",
219
+ // mode: "static", static_dir: "./dist",
220
+ // mode: "proxy", upstream: "http://localhost:3000",
221
+ },
222
+ versions: { engine: "0", server: "0", postgres: "0", deno: "0" },
223
+ }
224
+ `,
225
+ "utf8",
226
+ )
227
+ updateAppConfigInProject(dir, { mode: "proxy", upstream: "http://localhost:7777" })
228
+ const next = readFileSync(configPath, "utf8")
229
+ expect(next).toContain(`mode: "proxy"`)
230
+ expect(next).toContain(`upstream: "http://localhost:7777"`)
231
+ } finally {
232
+ rmSync(dir, { recursive: true, force: true })
233
+ }
234
+ })
235
+
236
+ it("app config updater handles defineConfig wrappers", () => {
237
+ const dir = mkdtempSync(join(tmpdir(), "supatype-app-config-"))
238
+ try {
239
+ const configPath = join(dir, "supatype.config.ts")
240
+ writeFileSync(
241
+ configPath,
242
+ `import { defineConfig } from "@supatype/cli"
243
+
244
+ export default defineConfig({
245
+ project: { name: "x" },
246
+ database: { provider: "docker" },
247
+ server: { mode: "dev" },
248
+ app: { mode: "none" },
249
+ versions: { engine: "0", server: "0", postgres: "0", deno: "0" },
250
+ })
251
+ `,
252
+ "utf8",
253
+ )
254
+ updateAppConfigInProject(dir, { mode: "static", staticDir: "./site" })
255
+ const next = readFileSync(configPath, "utf8")
256
+ expect(next).toContain(`mode: "static"`)
257
+ expect(next).toContain(`static_dir: "./site"`)
258
+ } finally {
259
+ rmSync(dir, { recursive: true, force: true })
260
+ }
261
+ })
262
+
263
+ it("app config updater inserts app block when missing", () => {
264
+ const dir = mkdtempSync(join(tmpdir(), "supatype-app-config-"))
265
+ try {
266
+ const configPath = join(dir, "supatype.config.ts")
267
+ writeFileSync(
268
+ configPath,
269
+ `export default {
270
+ project: { name: "x" },
271
+ database: { provider: "docker" },
272
+ server: { mode: "dev" },
273
+ versions: { engine: "0", server: "0", postgres: "0", deno: "0" },
274
+ }
275
+ `,
276
+ "utf8",
277
+ )
278
+ updateAppConfigInProject(dir, { mode: "none" })
279
+ const next = readFileSync(configPath, "utf8")
280
+ expect(next).toContain("app:")
281
+ expect(next).toContain(`mode: "none"`)
282
+ } finally {
283
+ rmSync(dir, { recursive: true, force: true })
284
+ }
285
+ })
286
+
287
+ it("app config updater preserves unrelated app keys", () => {
288
+ const dir = mkdtempSync(join(tmpdir(), "supatype-app-config-"))
289
+ try {
290
+ const configPath = join(dir, "supatype.config.ts")
291
+ writeFileSync(
292
+ configPath,
293
+ `export default {
294
+ project: { name: "x" },
295
+ database: { provider: "docker" },
296
+ server: { mode: "dev" },
297
+ app: {
298
+ mode: "proxy",
299
+ upstream: "http://localhost:3000",
300
+ headers: { "x-feature": "on" },
301
+ },
302
+ versions: { engine: "0", server: "0", postgres: "0", deno: "0" },
303
+ }
304
+ `,
305
+ "utf8",
306
+ )
307
+ updateAppConfigInProject(dir, { mode: "proxy", upstream: "http://localhost:8080" })
308
+ const next = readFileSync(configPath, "utf8")
309
+ expect(next).toContain(`upstream: "http://localhost:8080"`)
310
+ expect(next).toContain(`headers`)
311
+ expect(next).toContain(`"x-feature"`)
312
+ } finally {
313
+ rmSync(dir, { recursive: true, force: true })
314
+ }
315
+ })
316
+
317
+ it("writes self-host compose artifacts under .supatype/self-host", () => {
318
+ const dir = mkdtempSync(join(tmpdir(), "supatype-compose-"))
319
+ try {
320
+ const out = writeSelfHostCompose(dir, { ...baseConfig, app: { mode: "none" } })
321
+ expect(out.composePath).toContain(".supatype")
322
+ expect(readFileSync(out.composePath, "utf8")).toContain("services:")
323
+ expect(readFileSync(out.kongPath, "utf8")).toContain("/rest/v1/")
324
+ const compose = readFileSync(out.composePath, "utf8")
325
+ expect(compose).toContain("${SUPATYPE_POSTGRES_IMAGE:-supatype/postgres:latest}")
326
+ expect(compose).toContain("${SUPATYPE_SERVER_IMAGE:-${SUPATYPE_AUTH_IMAGE:-supatype/server:latest}}")
327
+ expect(compose).toContain("${SUPATYPE_STORAGE_IMAGE:-supatype/storage:latest}")
328
+ expect(compose).toContain("${SUPATYPE_STUDIO_IMAGE:-supatype/studio:latest}")
329
+ expect(compose).toContain("SUPATYPE_POSTGREST_URL: http://postgrest:3000")
330
+ expect(compose).toContain("unified gateway")
331
+ const kong = readFileSync(out.kongPath, "utf8")
332
+ expect(kong).toContain("http://server:9999")
333
+ expect(kong).toContain("http://postgrest:3000/rpc/graphql")
334
+ expect(kong).toContain("Content-Profile:graphql_public")
335
+ } finally {
336
+ rmSync(dir, { recursive: true, force: true })
337
+ }
338
+ })
339
+
340
+ it("writes default manifest when missing for compose", () => {
341
+ const dir = mkdtempSync(join(tmpdir(), "supatype-manifest-"))
342
+ try {
343
+ writeSelfHostCompose(dir, { ...baseConfig, app: { mode: "none" } })
344
+ const manifest = readFileSync(join(dir, ".supatype", "manifest.json"), "utf8")
345
+ expect(manifest).toContain("postgrest_url")
346
+ expect(manifest).toContain("http://postgrest:3000")
347
+ } finally {
348
+ rmSync(dir, { recursive: true, force: true })
349
+ }
350
+ })
351
+ })
@@ -0,0 +1,31 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest"
2
+ import { mkdirSync, writeFileSync, rmSync } from "node:fs"
3
+ import { join } from "node:path"
4
+ import { tmpdir } from "node:os"
5
+ import { discoverSeedsDir } from "../src/commands/seed.js"
6
+
7
+ let tmp: string
8
+ beforeEach(() => {
9
+ tmp = join(tmpdir(), `supatype-seed-${Date.now()}`)
10
+ mkdirSync(join(tmp, "seeds"), { recursive: true })
11
+ })
12
+ afterEach(() => {
13
+ rmSync(tmp, { recursive: true, force: true })
14
+ })
15
+
16
+ describe("discoverSeedsDir", () => {
17
+ it("returns sorted paths for seeds/*.ts", () => {
18
+ writeFileSync(join(tmp, "seeds", "z_first.ts"), "//")
19
+ writeFileSync(join(tmp, "seeds", "a_second.ts"), "//")
20
+ const paths = discoverSeedsDir(tmp, join(tmp, "seeds"))
21
+ expect(paths.map((p) => p.replace(/\\/g, "/"))).toEqual([
22
+ join(tmp, "seeds", "a_second.ts").replace(/\\/g, "/"),
23
+ join(tmp, "seeds", "z_first.ts").replace(/\\/g, "/"),
24
+ ])
25
+ })
26
+
27
+ it("returns empty when seeds dir missing", () => {
28
+ const empty = join(tmp, "no-seeds")
29
+ expect(discoverSeedsDir(tmp, empty)).toEqual([])
30
+ })
31
+ })
@@ -0,0 +1,27 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import { DEFAULT_STUDIO_ADMIN_ROLES, studioAdminRoles, withAdminRoles } from "../src/studio-admin-roles.js"
3
+ import type { SupatypeProjectConfig } from "../src/project-config.js"
4
+
5
+ const baseConfig: SupatypeProjectConfig = {
6
+ project: { name: "acme" },
7
+ database: { provider: "docker" },
8
+ server: { mode: "dev" },
9
+ app: { mode: "none" },
10
+ versions: { engine: "0", server: "0", postgres: "0", deno: "0" },
11
+ }
12
+
13
+ describe("studioAdminRoles", () => {
14
+ it("returns defaults when admin.roles is omitted", () => {
15
+ expect(studioAdminRoles(baseConfig)).toEqual([...DEFAULT_STUDIO_ADMIN_ROLES])
16
+ })
17
+
18
+ it("uses admin.roles from config when set", () => {
19
+ const roles = studioAdminRoles({ ...baseConfig, admin: { roles: ["custom_admin"] } })
20
+ expect(roles).toEqual(["custom_admin"])
21
+ })
22
+
23
+ it("merges adminRoles into engine admin JSON", () => {
24
+ const merged = withAdminRoles({ models: [] }, { ...baseConfig, admin: { roles: ["ops"] } })
25
+ expect(merged).toEqual({ models: [], adminRoles: ["ops"] })
26
+ })
27
+ })
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": true,
5
+ "composite": false,
6
+ "rootDir": ".."
7
+ },
8
+ "include": ["./**/*.ts"]
9
+ }