@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,84 @@
1
+ import { afterEach, describe, expect, it } from "vitest"
2
+ import { mkdtempSync, writeFileSync, rmSync } from "node:fs"
3
+ import { join } from "node:path"
4
+ import { tmpdir } from "node:os"
5
+ import {
6
+ validateArtifactFormat,
7
+ type Component,
8
+ type PlatformId,
9
+ } from "../src/binary-cache.js"
10
+
11
+ function writeMagic(name: string, bytes: number[]): string {
12
+ const dir = mkdtempSync(join(tmpdir(), "supatype-artifact-"))
13
+ const path = join(dir, name)
14
+ writeFileSync(path, Buffer.from(bytes))
15
+ return path
16
+ }
17
+
18
+ function expectValid(component: Component, path: string, platform: PlatformId): void {
19
+ expect(() => validateArtifactFormat(component, path, platform)).not.toThrow()
20
+ }
21
+
22
+ function expectInvalid(component: Component, path: string, platform: PlatformId): void {
23
+ expect(() => validateArtifactFormat(component, path, platform)).toThrow()
24
+ }
25
+
26
+ describe("validateArtifactFormat", () => {
27
+ const paths: string[] = []
28
+
29
+ afterEach(() => {
30
+ for (const p of paths) {
31
+ try {
32
+ rmSync(join(p, ".."), { recursive: true, force: true })
33
+ } catch {
34
+ /* ignore */
35
+ }
36
+ }
37
+ paths.length = 0
38
+ })
39
+
40
+ it("accepts ELF for engine/server/deno on linux", () => {
41
+ const linux: PlatformId = { os: "linux", arch: "amd64" }
42
+ for (const component of ["engine", "server", "deno"] as const) {
43
+ const p = writeMagic(component, [0x7f, 0x45, 0x4c, 0x46, 0, 0, 0, 0])
44
+ paths.push(p)
45
+ expectValid(component, p, linux)
46
+ }
47
+ })
48
+
49
+ it("accepts Mach-O for engine on darwin", () => {
50
+ const p = writeMagic("engine", [0xcf, 0xfa, 0xed, 0xfe, 0, 0, 0, 0])
51
+ paths.push(p)
52
+ expectValid("engine", p, { os: "darwin", arch: "arm64" })
53
+ })
54
+
55
+ it("accepts PE for deno on windows", () => {
56
+ const p = writeMagic("deno.exe", [0x4d, 0x5a, 0x90, 0x00, 0, 0, 0, 0])
57
+ paths.push(p)
58
+ expectValid("deno", p, { os: "windows", arch: "amd64" })
59
+ })
60
+
61
+ it("rejects Go c-archive for server on linux", () => {
62
+ const p = writeMagic("server", [0x21, 0x3c, 0x61, 0x72, 0, 0, 0, 0])
63
+ paths.push(p)
64
+ expectInvalid("server", p, { os: "linux", arch: "amd64" })
65
+ })
66
+
67
+ it("accepts gzip for postgres on linux", () => {
68
+ const p = writeMagic("pg.tar.gz", [0x1f, 0x8b, 0x08, 0x00, 0, 0, 0, 0])
69
+ paths.push(p)
70
+ expectValid("postgres", p, { os: "linux", arch: "amd64" })
71
+ })
72
+
73
+ it("accepts zip for postgres on windows", () => {
74
+ const p = writeMagic("pg.zip", [0x50, 0x4b, 0x03, 0x04, 0, 0, 0, 0])
75
+ paths.push(p)
76
+ expectValid("postgres", p, { os: "windows", arch: "amd64" })
77
+ })
78
+
79
+ it("rejects gzip postgres artifact on windows", () => {
80
+ const p = writeMagic("pg.tar.gz", [0x1f, 0x8b, 0x08, 0x00, 0, 0, 0, 0])
81
+ paths.push(p)
82
+ expectInvalid("postgres", p, { os: "windows", arch: "amd64" })
83
+ })
84
+ })
@@ -27,7 +27,22 @@ describe("CLI binary (requires built dist/)", () => {
27
27
  it("--help lists all top-level commands", () => {
28
28
  const { stdout, exitCode } = runCli(["--help"])
29
29
  expect(exitCode).toBe(0)
30
- const commands = ["init", "dev", "push", "diff", "pull", "generate", "migrate", "rollback", "reset", "seed", "keys", "app", "self-host"]
30
+ const commands = [
31
+ "init",
32
+ "dev",
33
+ "push",
34
+ "diff",
35
+ "pull",
36
+ "generate",
37
+ "migrate",
38
+ "rollback",
39
+ "reset",
40
+ "seed",
41
+ "keys",
42
+ "app",
43
+ "self-host",
44
+ "self-update",
45
+ ]
31
46
  for (const cmd of commands) {
32
47
  expect(stdout, `Expected '${cmd}' in --help output`).toContain(cmd)
33
48
  }
@@ -39,6 +54,12 @@ describe("CLI binary (requires built dist/)", () => {
39
54
  expect(stdout.trim()).toMatch(/^\d+\.\d+\.\d+/)
40
55
  })
41
56
 
57
+ it("self-update --help describes the command", () => {
58
+ const { stdout, exitCode } = runCli(["self-update", "--help"])
59
+ expect(exitCode).toBe(0)
60
+ expect(stdout.toLowerCase()).toMatch(/npm|update/)
61
+ })
62
+
42
63
  it("init --help describes the init command", () => {
43
64
  const { stdout, exitCode } = runCli(["init", "--help"])
44
65
  expect(exitCode).toBe(0)
@@ -58,10 +79,10 @@ describe("CLI binary (requires built dist/)", () => {
58
79
  expect(stdout).toContain("dry run")
59
80
  })
60
81
 
61
- it("pull --help shows --output option", () => {
82
+ it("pull --help describes deprecated pull command", () => {
62
83
  const { stdout, exitCode } = runCli(["pull", "--help"])
63
84
  expect(exitCode).toBe(0)
64
- expect(stdout).toContain("--output")
85
+ expect(stdout).toContain("deprecated")
65
86
  })
66
87
 
67
88
  it("reset --help shows --yes flag", () => {
@@ -77,27 +98,32 @@ describe("CLI binary (requires built dist/)", () => {
77
98
  expect(stdout).toContain("remove")
78
99
  })
79
100
 
80
- it("app add --help shows --dockerfile and --port options", () => {
101
+ it("app add --help shows --static and --port options", () => {
81
102
  const { stdout, exitCode } = runCli(["app", "add", "--help"])
82
103
  expect(exitCode).toBe(0)
83
- expect(stdout).toContain("--dockerfile")
104
+ expect(stdout).toContain("--static")
84
105
  expect(stdout).toContain("--port")
85
106
  })
86
107
 
87
- it("self-host --help describes the self-host command", () => {
108
+ it("self-host --help shows compose only (legacy commands hidden)", () => {
88
109
  const { stdout, exitCode } = runCli(["self-host", "--help"])
89
110
  expect(exitCode).toBe(0)
90
- expect(stdout).toContain("setup")
91
- expect(stdout).toContain("status")
92
- expect(stdout).toContain("logs")
93
- expect(stdout).toContain("backup")
94
- expect(stdout).toContain("update")
111
+ const commandsSection = stdout.split("Commands:")[1] ?? ""
112
+ expect(commandsSection).toContain("compose")
113
+ expect(commandsSection).not.toContain("install-service")
114
+ expect(commandsSection).not.toContain("native")
115
+ expect(commandsSection).not.toContain("backup")
116
+ expect(stdout).not.toContain("--output-dir")
95
117
  })
96
118
 
97
- it("self-host setup --help shows --domain option", () => {
98
- const { stdout, exitCode } = runCli(["self-host", "setup", "--help"])
119
+ it("self-host compose --help shows compose subcommands", () => {
120
+ const { stdout, exitCode } = runCli(["self-host", "compose", "--help"])
99
121
  expect(exitCode).toBe(0)
100
- expect(stdout).toContain("--domain")
122
+ expect(stdout).toContain("render")
123
+ expect(stdout).toContain("up")
124
+ expect(stdout).toContain("down")
125
+ expect(stdout).toContain("status")
126
+ expect(stdout).toContain("logs")
101
127
  })
102
128
 
103
129
  it("unknown command exits non-zero", () => {
@@ -3,13 +3,26 @@ import { mkdirSync, rmSync, writeFileSync } from "node:fs"
3
3
  import { join } from "node:path"
4
4
  import { tmpdir } from "node:os"
5
5
  import { defineConfig, loadConfig } from "../src/config.js"
6
- import type { DefinatypeConfig } from "../src/config.js"
6
+ import { mergeProjectConfig, resolveRuntimeProvider, type SupatypeProjectConfig } from "../src/project-config.js"
7
+ import { DENO_RELEASE_PIN } from "../src/release-pins.js"
7
8
 
8
9
  let counter = 0
9
10
  let tmpDir: string
10
11
 
12
+ const minimalProject = (name: string): SupatypeProjectConfig => ({
13
+ project: { name },
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
+
11
25
  beforeEach(() => {
12
- // Counter prevents timestamp collisions when tests run in rapid succession
13
26
  tmpDir = join(tmpdir(), `dt-config-test-${Date.now()}-${++counter}`)
14
27
  mkdirSync(tmpDir, { recursive: true })
15
28
  })
@@ -20,17 +33,18 @@ afterEach(() => {
20
33
 
21
34
  describe("defineConfig()", () => {
22
35
  it("returns its argument unchanged (identity helper for type inference)", () => {
23
- const cfg: DefinatypeConfig = {
36
+ const cfg = defineConfig({
37
+ ...minimalProject("test"),
24
38
  connection: "postgresql://localhost/test",
25
- schema: "./schema/index.ts",
26
- }
39
+ schema: { path: "./schema/index.ts" },
40
+ })
27
41
  expect(defineConfig(cfg)).toBe(cfg)
28
42
  })
29
43
 
30
44
  it("preserves optional output field", () => {
31
45
  const cfg = defineConfig({
32
- connection: "postgresql://localhost/test",
33
- schema: "./schema/index.ts",
46
+ ...minimalProject("test"),
47
+ schema: { path: "./schema/index.ts" },
34
48
  output: { types: "./src/types.d.ts", client: "./src/client.ts" },
35
49
  })
36
50
  expect(cfg.output?.types).toBe("./src/types.d.ts")
@@ -40,62 +54,83 @@ describe("defineConfig()", () => {
40
54
 
41
55
  describe("loadConfig()", () => {
42
56
  it("throws when no config file exists in the directory", () => {
43
- expect(() => loadConfig(tmpDir)).toThrow(/No supatype.config.ts found/)
57
+ expect(() => loadConfig(tmpDir)).toThrow(/No supatype.config.ts/)
44
58
  })
45
59
 
46
60
  it("loads a valid supatype.config.ts (plain export default, no package imports)", () => {
47
- // Note: avoid importing @supatype/cli inside the temp config —
48
- // the temp dir is outside the monorepo and can't resolve workspace packages.
61
+ const body = {
62
+ ...minimalProject("mydb"),
63
+ connection: "postgresql://localhost/mydb",
64
+ schema: { path: "./schema/index.ts" },
65
+ }
49
66
  writeFileSync(
50
67
  join(tmpDir, "supatype.config.ts"),
51
- `export default {
52
- connection: "postgresql://localhost/mydb",
53
- schema: "./schema/index.ts",
54
- }
68
+ `export default ${JSON.stringify(body)}
55
69
  `,
56
70
  )
57
71
  const cfg = loadConfig(tmpDir)
58
72
  expect(cfg.connection).toBe("postgresql://localhost/mydb")
59
- expect(cfg.schema).toBe("./schema/index.ts")
73
+ expect(cfg.schema?.path).toBe("./schema/index.ts")
60
74
  })
61
75
 
62
- it("loads a supatype.config.js (plain ESM)", () => {
76
+ it("normalizes shorthand schema string to { path, pg_schema }", () => {
63
77
  writeFileSync(
64
- join(tmpDir, "supatype.config.js"),
65
- `export default {
66
- connection: "postgresql://localhost/jsdb",
67
- schema: "./schema/index.ts",
68
- }
78
+ join(tmpDir, "supatype.config.ts"),
79
+ `export default ${JSON.stringify({
80
+ ...minimalProject("x"),
81
+ schema: "./schema/index.ts",
82
+ })}
69
83
  `,
70
84
  )
71
85
  const cfg = loadConfig(tmpDir)
72
- expect(cfg.connection).toBe("postgresql://localhost/jsdb")
86
+ expect(cfg.schema?.path).toBe("./schema/index.ts")
87
+ expect(cfg.schema?.pg_schema).toBe("public")
73
88
  })
74
89
 
75
- it("throws if config is missing the schema field", () => {
90
+ it("loads a supatype.config.js (plain ESM)", () => {
76
91
  writeFileSync(
77
- join(tmpDir, "supatype.config.ts"),
78
- `export default { connection: "postgresql://localhost/test" }`,
92
+ join(tmpDir, "supatype.config.js"),
93
+ `export default ${JSON.stringify({
94
+ ...minimalProject("jsdb"),
95
+ connection: "postgresql://localhost/jsdb",
96
+ schema: { path: "./schema/index.ts" },
97
+ })}
98
+ `,
79
99
  )
80
- expect(() => loadConfig(tmpDir)).toThrow(/must export/)
100
+ const cfg = loadConfig(tmpDir)
101
+ expect(cfg.connection).toBe("postgresql://localhost/jsdb")
81
102
  })
82
103
 
83
- it("throws if config is missing the connection field", () => {
104
+ it("throws if config is missing the versions section", () => {
84
105
  writeFileSync(
85
106
  join(tmpDir, "supatype.config.ts"),
86
- `export default { schema: "./schema/index.ts" }`,
107
+ `export default {
108
+ project: { name: "t" },
109
+ database: { provider: "docker" },
110
+ server: { mode: "dev" },
111
+ app: { mode: "none" },
112
+ schema: { path: "./schema/index.ts" },
113
+ }`,
87
114
  )
88
- expect(() => loadConfig(tmpDir)).toThrow(/must export/)
115
+ expect(() => loadConfig(tmpDir)).toThrow(/versions/)
89
116
  })
90
117
 
91
118
  it("prefers supatype.config.ts over supatype.config.js when both exist", () => {
92
119
  writeFileSync(
93
120
  join(tmpDir, "supatype.config.ts"),
94
- `export default { connection: "postgresql://localhost/from-ts", schema: "./schema/index.ts" }`,
121
+ `export default ${JSON.stringify({
122
+ ...minimalProject("from-ts"),
123
+ connection: "postgresql://localhost/from-ts",
124
+ schema: { path: "./schema/index.ts" },
125
+ })}`,
95
126
  )
96
127
  writeFileSync(
97
128
  join(tmpDir, "supatype.config.js"),
98
- `export default { connection: "postgresql://localhost/from-js", schema: "./schema/index.ts" }`,
129
+ `export default ${JSON.stringify({
130
+ ...minimalProject("from-js"),
131
+ connection: "postgresql://localhost/from-js",
132
+ schema: { path: "./schema/index.ts" },
133
+ })}`,
99
134
  )
100
135
  const cfg = loadConfig(tmpDir)
101
136
  expect(cfg.connection).toContain("from-ts")
@@ -104,14 +139,113 @@ describe("loadConfig()", () => {
104
139
  it("supports optional output field in config", () => {
105
140
  writeFileSync(
106
141
  join(tmpDir, "supatype.config.ts"),
107
- `export default {
108
- connection: "postgresql://localhost/test",
109
- schema: "./schema/index.ts",
110
- output: { types: "./src/types.d.ts" },
111
- }
112
- `,
142
+ `export default ${JSON.stringify({
143
+ ...minimalProject("t"),
144
+ schema: { path: "./schema/index.ts" },
145
+ output: { types: "./src/types.d.ts" },
146
+ })}`,
113
147
  )
114
148
  const cfg = loadConfig(tmpDir)
115
149
  expect(cfg.output?.types).toBe("./src/types.d.ts")
116
150
  })
151
+
152
+ it("merges supatype.local.config.ts over base", () => {
153
+ writeFileSync(
154
+ join(tmpDir, "supatype.config.ts"),
155
+ `export default ${JSON.stringify({
156
+ ...minimalProject("base"),
157
+ schema: { path: "./a.ts" },
158
+ versions: {
159
+ engine: "0.4.0",
160
+ server: "0.1.0",
161
+ postgres: "17",
162
+ deno: "2.2.0",
163
+ },
164
+ })}`,
165
+ )
166
+ writeFileSync(
167
+ join(tmpDir, "supatype.local.config.ts"),
168
+ `export default ${JSON.stringify({
169
+ versions: {
170
+ engine: "0.4.2",
171
+ server: "0.1.0",
172
+ postgres: "17",
173
+ deno: "2.2.0",
174
+ },
175
+ })}`,
176
+ )
177
+ const cfg = loadConfig(tmpDir)
178
+ expect(cfg.versions.engine).toBe("0.4.2")
179
+ expect(cfg.schema?.path).toBe("./a.ts")
180
+ })
181
+ })
182
+
183
+ describe("resolveRuntimeProvider()", () => {
184
+ it("prefers top-level provider over database.provider", () => {
185
+ const cfg = defineConfig({
186
+ ...minimalProject("p"),
187
+ provider: "docker",
188
+ database: { provider: "native" },
189
+ })
190
+ expect(resolveRuntimeProvider(cfg)).toBe("docker")
191
+ })
192
+
193
+ it("falls back to database.provider then native", () => {
194
+ expect(resolveRuntimeProvider(defineConfig({ ...minimalProject("p"), database: { provider: "docker" } }))).toBe(
195
+ "docker",
196
+ )
197
+ expect(resolveRuntimeProvider(defineConfig({ ...minimalProject("p"), database: { provider: "native" } }))).toBe(
198
+ "native",
199
+ )
200
+ })
201
+ })
202
+
203
+ describe("mergeProjectConfig()", () => {
204
+ it("deep-merges email.smtp between base and local", () => {
205
+ const base = defineConfig({
206
+ ...minimalProject("p"),
207
+ email: { provider: "smtp", smtp: { host: "h1", port: 587, user: "u0" } },
208
+ })
209
+ const merged = mergeProjectConfig(base, { email: { smtp: { host: "h2", pass: "x" } } })
210
+ expect(merged.email?.provider).toBe("smtp")
211
+ expect(merged.email?.smtp?.host).toBe("h2")
212
+ expect(merged.email?.smtp?.port).toBe(587)
213
+ expect(merged.email?.smtp?.user).toBe("u0")
214
+ expect(merged.email?.smtp?.pass).toBe("x")
215
+ })
216
+
217
+ it("merges send_email_hook fields from local", () => {
218
+ const base = defineConfig({
219
+ ...minimalProject("p"),
220
+ email: { provider: "console", send_email_hook: true, send_email_hook_uri: "http://old/hook" },
221
+ })
222
+ const merged = mergeProjectConfig(base, {
223
+ email: { send_email_hook_secrets: "v1,whsec_customsecret0000000000000000" },
224
+ })
225
+ expect(merged.email?.send_email_hook).toBe(true)
226
+ expect(merged.email?.send_email_hook_uri).toBe("http://old/hook")
227
+ expect(merged.email?.send_email_hook_secrets).toBe("v1,whsec_customsecret0000000000000000")
228
+ })
229
+
230
+ it("overrides app.vite_dev_url from local", () => {
231
+ const base = defineConfig({
232
+ ...minimalProject("p"),
233
+ app: { mode: "static", static_dir: "./dist", vite_dev_url: "http://127.0.0.1:1111" },
234
+ })
235
+ const merged = mergeProjectConfig(base, { app: { vite_dev_url: "http://127.0.0.1:5173" } })
236
+ expect(merged.app?.vite_dev_url).toBe("http://127.0.0.1:5173")
237
+ })
238
+
239
+ it("merges app.start for proxy dev script override", () => {
240
+ const base = defineConfig({
241
+ ...minimalProject("p"),
242
+ app: { mode: "static", static_dir: "./dist" },
243
+ })
244
+ const merged = mergeProjectConfig(base, {
245
+ app: { mode: "proxy", upstream: "http://127.0.0.1:4321", start: "dev:site" },
246
+ })
247
+ expect(merged.app.mode).toBe("proxy")
248
+ expect(merged.app.start).toBe("dev:site")
249
+ expect(merged.app.static_dir).toBe("./dist")
250
+ })
117
251
  })
@@ -0,0 +1,39 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import {
3
+ containerName,
4
+ dockerPgLoopbackDbUrl,
5
+ dockerPgPostInitServing,
6
+ } from "../src/docker-postgres.js"
7
+
8
+ describe("docker-postgres", () => {
9
+ it("derives container name from project name", () => {
10
+ expect(containerName("supatype-integration")).toBe("supatype-supatype-integration")
11
+ })
12
+
13
+ it("detects post-init serving after first-boot init", () => {
14
+ const logs = [
15
+ "PostgreSQL init process complete; ready for start up.",
16
+ "database system is ready to accept connections",
17
+ ].join("\n")
18
+ expect(dockerPgPostInitServing(logs)).toBe(true)
19
+ })
20
+
21
+ it("detects post-init serving on reused volume (no init banner this run)", () => {
22
+ const logs = "database system is ready to accept connections\n"
23
+ expect(dockerPgPostInitServing(logs)).toBe(true)
24
+ })
25
+
26
+ it("builds loopback DB URL for in-container migrate", () => {
27
+ expect(dockerPgLoopbackDbUrl("my-project")).toBe(
28
+ "postgres://supatype_admin:postgres@127.0.0.1:5432/my-project?sslmode=disable",
29
+ )
30
+ })
31
+
32
+ it("rejects ready line before init complete on first boot", () => {
33
+ const logs = [
34
+ "database system is ready to accept connections",
35
+ "PostgreSQL init process complete; ready for start up.",
36
+ ].join("\n")
37
+ expect(dockerPgPostInitServing(logs)).toBe(false)
38
+ })
39
+ })
@@ -59,12 +59,12 @@ describe("CDN URL construction", () => {
59
59
  const { getCdnUrl } = await import("../src/engine/platform.js")
60
60
 
61
61
  const url = getCdnUrl(
62
- "https://releases.supatype.io/engine",
62
+ "https://releases.supatype.com/engine",
63
63
  "0.1.0-alpha.1",
64
64
  "supatype-engine-0.1.0-alpha.1-linux-x64",
65
65
  )
66
66
  expect(url).toBe(
67
- "https://releases.supatype.io/engine/v0.1.0-alpha.1/supatype-engine-0.1.0-alpha.1-linux-x64",
67
+ "https://releases.supatype.com/engine/v0.1.0-alpha.1/supatype-engine-0.1.0-alpha.1-linux-x64",
68
68
  )
69
69
  })
70
70
  })
@@ -329,7 +329,7 @@ describe("Engine version constants", () => {
329
329
  } = await import("../src/engine-version.js")
330
330
 
331
331
  expect(ENGINE_VERSION).toMatch(/^\d+\.\d+\.\d+/)
332
- expect(CDN_BASE_URL).toBe("https://releases.supatype.io/engine")
332
+ expect(CDN_BASE_URL).toBe("https://releases.supatype.com/engine")
333
333
  expect(ENGINE_RELEASES_REPO).toBe("supatype/engine-releases")
334
334
  expect(GITHUB_RELEASES_FALLBACK_URL).toContain("github.com")
335
335
  })
@@ -0,0 +1,59 @@
1
+ import { describe, expect, it, vi, beforeEach, afterEach } from "vitest"
2
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"
3
+ import type { SupatypeProjectConfig } from "../src/project-config.js"
4
+ import * as binaryCache from "../src/binary-cache.js"
5
+ import { ensureBinary } from "../src/ensure-binary.js"
6
+
7
+ const TEST_VERSION = "9.9.9"
8
+
9
+ const config = (): SupatypeProjectConfig => ({
10
+ project: { name: "test" },
11
+ database: { provider: "native" },
12
+ server: { mode: "dev" },
13
+ app: { mode: "none" },
14
+ versions: {
15
+ engine: "0.4.2",
16
+ server: "0.1.0",
17
+ postgres: "17.2",
18
+ deno: TEST_VERSION,
19
+ },
20
+ })
21
+
22
+ beforeEach(() => {
23
+ const dir = binaryCache.cachePath("deno", TEST_VERSION)
24
+ if (existsSync(dir)) {
25
+ rmSync(dir, { recursive: true, force: true })
26
+ }
27
+ mkdirSync(dir, { recursive: true })
28
+ })
29
+
30
+ afterEach(() => {
31
+ vi.restoreAllMocks()
32
+ const dir = binaryCache.cachePath("deno", TEST_VERSION)
33
+ if (existsSync(dir)) {
34
+ rmSync(dir, { recursive: true, force: true })
35
+ }
36
+ })
37
+
38
+ describe("ensureBinary", () => {
39
+ it("returns cached path without calling download", async () => {
40
+ const platform = binaryCache.currentPlatform()
41
+ const path = binaryCache.cachedBinaryPath("deno", TEST_VERSION, platform)
42
+ writeFileSync(path, "stub", { mode: 0o755 })
43
+
44
+ const downloadSpy = vi.spyOn(binaryCache, "download")
45
+ const resolved = await ensureBinary("deno", config())
46
+ expect(resolved).toBe(path)
47
+ expect(downloadSpy).not.toHaveBeenCalled()
48
+ })
49
+
50
+ it("downloads on cache miss", async () => {
51
+ const platform = binaryCache.currentPlatform()
52
+ const expected = binaryCache.cachedBinaryPath("deno", TEST_VERSION, platform)
53
+ const downloadSpy = vi.spyOn(binaryCache, "download").mockResolvedValue(expected)
54
+
55
+ const path = await ensureBinary("deno", config())
56
+ expect(path).toBe(expected)
57
+ expect(downloadSpy).toHaveBeenCalledWith("deno", TEST_VERSION, platform)
58
+ })
59
+ })