@supatype/cli 0.1.7 → 0.1.10

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 (414) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +125 -122
  3. package/.turbo/turbo-typecheck.log +1 -1
  4. package/LICENSE +202 -0
  5. package/deno.d.ts +1 -1
  6. package/dist/app/framework.js +1 -1
  7. package/dist/app/framework.js.map +1 -1
  8. package/dist/augmentation-generator.d.ts +1 -1
  9. package/dist/augmentation-generator.js +3 -3
  10. package/dist/augmentation-generator.js.map +1 -1
  11. package/dist/binary-cache.d.ts +30 -8
  12. package/dist/binary-cache.d.ts.map +1 -1
  13. package/dist/binary-cache.js +47 -35
  14. package/dist/binary-cache.js.map +1 -1
  15. package/dist/cache-pins.d.ts +1 -1
  16. package/dist/cache-pins.js +2 -2
  17. package/dist/cache-pins.js.map +1 -1
  18. package/dist/cli-artifacts.d.ts +32 -0
  19. package/dist/cli-artifacts.d.ts.map +1 -0
  20. package/dist/cli-artifacts.js +49 -0
  21. package/dist/cli-artifacts.js.map +1 -0
  22. package/dist/cli-install-method.d.ts +17 -1
  23. package/dist/cli-install-method.d.ts.map +1 -1
  24. package/dist/cli-install-method.js +32 -4
  25. package/dist/cli-install-method.js.map +1 -1
  26. package/dist/cli-package-version.d.ts +1 -1
  27. package/dist/cli-package-version.d.ts.map +1 -1
  28. package/dist/cli-package-version.js +6 -1
  29. package/dist/cli-package-version.js.map +1 -1
  30. package/dist/cli-standalone.d.ts +13 -4
  31. package/dist/cli-standalone.d.ts.map +1 -1
  32. package/dist/cli-standalone.js +86 -31
  33. package/dist/cli-standalone.js.map +1 -1
  34. package/dist/cli-version-embedded.d.ts +10 -0
  35. package/dist/cli-version-embedded.d.ts.map +1 -0
  36. package/dist/cli-version-embedded.js +13 -0
  37. package/dist/cli-version-embedded.js.map +1 -0
  38. package/dist/cli.js +1 -1
  39. package/dist/cli.js.map +1 -1
  40. package/dist/commands/add.js +4 -3
  41. package/dist/commands/add.js.map +1 -1
  42. package/dist/commands/admin.js +6 -6
  43. package/dist/commands/admin.js.map +1 -1
  44. package/dist/commands/adopt.js +1 -1
  45. package/dist/commands/adopt.js.map +1 -1
  46. package/dist/commands/app.js +2 -2
  47. package/dist/commands/app.js.map +1 -1
  48. package/dist/commands/cache.d.ts +1 -1
  49. package/dist/commands/cache.js +3 -3
  50. package/dist/commands/cache.js.map +1 -1
  51. package/dist/commands/db.d.ts +3 -3
  52. package/dist/commands/db.d.ts.map +1 -1
  53. package/dist/commands/db.js +12 -11
  54. package/dist/commands/db.js.map +1 -1
  55. package/dist/commands/deploy.d.ts +9 -9
  56. package/dist/commands/deploy.js +12 -12
  57. package/dist/commands/deploy.js.map +1 -1
  58. package/dist/commands/dev.d.ts +3 -3
  59. package/dist/commands/dev.js +17 -17
  60. package/dist/commands/dev.js.map +1 -1
  61. package/dist/commands/doctor.d.ts +1 -1
  62. package/dist/commands/doctor.js +3 -3
  63. package/dist/commands/doctor.js.map +1 -1
  64. package/dist/commands/engine.d.ts +1 -1
  65. package/dist/commands/engine.js +1 -1
  66. package/dist/commands/functions.d.ts.map +1 -1
  67. package/dist/commands/functions.js +8 -7
  68. package/dist/commands/functions.js.map +1 -1
  69. package/dist/commands/hooks.d.ts +2 -2
  70. package/dist/commands/hooks.js +4 -4
  71. package/dist/commands/hooks.js.map +1 -1
  72. package/dist/commands/init.js +28 -28
  73. package/dist/commands/init.js.map +1 -1
  74. package/dist/commands/internal.d.ts.map +1 -1
  75. package/dist/commands/internal.js +37 -0
  76. package/dist/commands/internal.js.map +1 -1
  77. package/dist/commands/login.d.ts +1 -1
  78. package/dist/commands/login.js +1 -1
  79. package/dist/commands/login.js.map +1 -1
  80. package/dist/commands/logs.d.ts +1 -1
  81. package/dist/commands/migrate.js +5 -5
  82. package/dist/commands/migrate.js.map +1 -1
  83. package/dist/commands/pg.d.ts +1 -1
  84. package/dist/commands/pg.js +1 -1
  85. package/dist/commands/plugins.js +1 -1
  86. package/dist/commands/plugins.js.map +1 -1
  87. package/dist/commands/pull.js +2 -2
  88. package/dist/commands/pull.js.map +1 -1
  89. package/dist/commands/push.js +3 -3
  90. package/dist/commands/push.js.map +1 -1
  91. package/dist/commands/self-host.d.ts +1 -1
  92. package/dist/commands/self-host.js +1 -1
  93. package/dist/commands/self-update.d.ts +2 -8
  94. package/dist/commands/self-update.d.ts.map +1 -1
  95. package/dist/commands/self-update.js +20 -12
  96. package/dist/commands/self-update.js.map +1 -1
  97. package/dist/commands/status.d.ts +1 -1
  98. package/dist/commands/update.d.ts +1 -1
  99. package/dist/commands/update.js +1 -1
  100. package/dist/config.d.ts +23 -1
  101. package/dist/config.d.ts.map +1 -1
  102. package/dist/config.js +37 -18
  103. package/dist/config.js.map +1 -1
  104. package/dist/db-preflight.d.ts +4 -4
  105. package/dist/db-preflight.js +14 -14
  106. package/dist/db-preflight.js.map +1 -1
  107. package/dist/dev-compose.d.ts +3 -3
  108. package/dist/dev-compose.js +27 -27
  109. package/dist/dev-compose.js.map +1 -1
  110. package/dist/dev-log-filter.d.ts +1 -1
  111. package/dist/dev-log-filter.d.ts.map +1 -1
  112. package/dist/dev-log-filter.js +1 -1
  113. package/dist/dev-log-filter.js.map +1 -1
  114. package/dist/dev-ports.d.ts +2 -2
  115. package/dist/dev-ports.d.ts.map +1 -1
  116. package/dist/dev-ports.js +2 -2
  117. package/dist/dev-ports.js.map +1 -1
  118. package/dist/dev-session.d.ts +5 -5
  119. package/dist/dev-session.d.ts.map +1 -1
  120. package/dist/dev-session.js +6 -6
  121. package/dist/dev-session.js.map +1 -1
  122. package/dist/dev-shutdown.d.ts +5 -5
  123. package/dist/dev-shutdown.d.ts.map +1 -1
  124. package/dist/dev-shutdown.js +7 -7
  125. package/dist/dev-shutdown.js.map +1 -1
  126. package/dist/dev-task-colors.d.ts +1 -1
  127. package/dist/dev-task-colors.d.ts.map +1 -1
  128. package/dist/dev-task-colors.js +1 -1
  129. package/dist/dev-task-colors.js.map +1 -1
  130. package/dist/docker-postgres.d.ts +5 -5
  131. package/dist/docker-postgres.d.ts.map +1 -1
  132. package/dist/docker-postgres.js +5 -5
  133. package/dist/docker-postgres.js.map +1 -1
  134. package/dist/docker-runtime.d.ts +2 -2
  135. package/dist/docker-runtime.d.ts.map +1 -1
  136. package/dist/docker-runtime.js +5 -5
  137. package/dist/docker-runtime.js.map +1 -1
  138. package/dist/engine-client.d.ts +1 -1
  139. package/dist/engine-client.js +3 -3
  140. package/dist/engine-client.js.map +1 -1
  141. package/dist/engine-push-output.js +1 -1
  142. package/dist/engine-push-output.js.map +1 -1
  143. package/dist/ensure-binary.d.ts.map +1 -1
  144. package/dist/ensure-binary.js +17 -0
  145. package/dist/ensure-binary.js.map +1 -1
  146. package/dist/ensure-component-binaries.js +1 -1
  147. package/dist/ensure-component-binaries.js.map +1 -1
  148. package/dist/env-file.d.ts +2 -2
  149. package/dist/env-file.d.ts.map +1 -1
  150. package/dist/env-file.js +1 -1
  151. package/dist/env-file.js.map +1 -1
  152. package/dist/field-masking-tier.d.ts +5 -5
  153. package/dist/field-masking-tier.d.ts.map +1 -1
  154. package/dist/field-masking-tier.js +6 -6
  155. package/dist/field-masking-tier.js.map +1 -1
  156. package/dist/functions-deno-types.d.ts +1 -1
  157. package/dist/functions-deno-types.d.ts.map +1 -1
  158. package/dist/functions-deno-types.js +3 -3
  159. package/dist/functions-deno-types.js.map +1 -1
  160. package/dist/functions-router-gen.js +1 -1
  161. package/dist/gitignore.d.ts +2 -2
  162. package/dist/gitignore.d.ts.map +1 -1
  163. package/dist/gitignore.js +3 -3
  164. package/dist/gitignore.js.map +1 -1
  165. package/dist/hook-upload.d.ts +1 -1
  166. package/dist/hook-upload.js +3 -3
  167. package/dist/hooks-generator.d.ts +1 -1
  168. package/dist/hooks-generator.js +9 -9
  169. package/dist/index.d.ts +1 -1
  170. package/dist/index.js +1 -1
  171. package/dist/init-project-detect.d.ts +1 -1
  172. package/dist/init-project-detect.d.ts.map +1 -1
  173. package/dist/init-project-detect.js +1 -1
  174. package/dist/init-project-detect.js.map +1 -1
  175. package/dist/link.d.ts +1 -1
  176. package/dist/link.d.ts.map +1 -1
  177. package/dist/local-secrets.d.ts +5 -5
  178. package/dist/local-secrets.js +5 -5
  179. package/dist/main.d.ts +2 -0
  180. package/dist/main.d.ts.map +1 -0
  181. package/dist/main.js +20 -0
  182. package/dist/main.js.map +1 -0
  183. package/dist/model-hooks.d.ts +3 -3
  184. package/dist/model-hooks.js +4 -4
  185. package/dist/pgbouncer-userlist.d.ts +1 -1
  186. package/dist/pgbouncer-userlist.d.ts.map +1 -1
  187. package/dist/pgbouncer-userlist.js +2 -2
  188. package/dist/pgbouncer-userlist.js.map +1 -1
  189. package/dist/postgres-ctl.d.ts +1 -1
  190. package/dist/postgres-ctl.js +4 -4
  191. package/dist/postgres-ctl.js.map +1 -1
  192. package/dist/process-manager.d.ts +2 -2
  193. package/dist/process-manager.d.ts.map +1 -1
  194. package/dist/process-manager.js +4 -4
  195. package/dist/process-manager.js.map +1 -1
  196. package/dist/project-config.d.ts +12 -12
  197. package/dist/project-config.d.ts.map +1 -1
  198. package/dist/project-config.js +9 -9
  199. package/dist/project-config.js.map +1 -1
  200. package/dist/pull-utils.d.ts +2 -2
  201. package/dist/pull-utils.d.ts.map +1 -1
  202. package/dist/pull-utils.js +4 -4
  203. package/dist/pull-utils.js.map +1 -1
  204. package/dist/realtime-launch.js +1 -1
  205. package/dist/realtime-launch.js.map +1 -1
  206. package/dist/release-pins.d.ts +1 -1
  207. package/dist/release-pins.js +2 -2
  208. package/dist/release-pins.js.map +1 -1
  209. package/dist/resolve-api-url.d.ts.map +1 -1
  210. package/dist/resolve-api-url.js +4 -3
  211. package/dist/resolve-api-url.js.map +1 -1
  212. package/dist/resolve-target.d.ts +1 -1
  213. package/dist/resolve-target.d.ts.map +1 -1
  214. package/dist/rest-cache-admin.js +2 -2
  215. package/dist/rest-cache-admin.js.map +1 -1
  216. package/dist/runtime-routes.d.ts +1 -1
  217. package/dist/runtime-routes.js +1 -1
  218. package/dist/schema-ast-v2.d.ts +3 -3
  219. package/dist/schema-ast-v2.d.ts.map +1 -1
  220. package/dist/schema-ast-v2.js +2 -2
  221. package/dist/schema-ast-v2.js.map +1 -1
  222. package/dist/schema-push-lock.js +3 -3
  223. package/dist/schema-push-lock.js.map +1 -1
  224. package/dist/scripts/postinstall.d.ts +1 -1
  225. package/dist/scripts/postinstall.js +1 -1
  226. package/dist/self-host-compose.d.ts +5 -5
  227. package/dist/self-host-compose.d.ts.map +1 -1
  228. package/dist/self-host-compose.js +24 -24
  229. package/dist/self-host-compose.js.map +1 -1
  230. package/dist/service-role-check.js +3 -3
  231. package/dist/service-role-check.js.map +1 -1
  232. package/dist/storage-provision.d.ts +1 -1
  233. package/dist/storage-provision.js +3 -3
  234. package/dist/storage-provision.js.map +1 -1
  235. package/dist/studio-dev-server.d.ts +1 -1
  236. package/dist/studio-dev-server.d.ts.map +1 -1
  237. package/dist/systemd.d.ts +1 -1
  238. package/dist/systemd.js +1 -1
  239. package/dist/target-client.js +1 -1
  240. package/dist/target-client.js.map +1 -1
  241. package/dist/tsx-runner.d.ts +12 -0
  242. package/dist/tsx-runner.d.ts.map +1 -1
  243. package/dist/tsx-runner.js +36 -2
  244. package/dist/tsx-runner.js.map +1 -1
  245. package/dist/type-extractor.js +27 -27
  246. package/dist/type-extractor.js.map +1 -1
  247. package/dist/type-resolver.js +1 -1
  248. package/dist/type-resolver.js.map +1 -1
  249. package/dist/ui/brand.d.ts +1 -1
  250. package/dist/ui/brand.js +1 -1
  251. package/dist/ui/components/LogoWordmark.d.ts +1 -1
  252. package/dist/ui/components/LogoWordmark.d.ts.map +1 -1
  253. package/dist/ui/components/LogoWordmark.js +1 -1
  254. package/dist/ui/components/LogoWordmark.js.map +1 -1
  255. package/dist/ui/components/SelectField.js +1 -1
  256. package/dist/ui/components/SelectField.js.map +1 -1
  257. package/dist/ui/confirm.d.ts +1 -1
  258. package/dist/ui/confirm.js +1 -1
  259. package/dist/ui/fatal.d.ts +1 -1
  260. package/dist/ui/fatal.d.ts.map +1 -1
  261. package/dist/ui/fatal.js +1 -1
  262. package/dist/ui/fatal.js.map +1 -1
  263. package/dist/ui/flows/prompt-fields.js +1 -1
  264. package/dist/ui/flows/prompt-fields.js.map +1 -1
  265. package/dist/ui/interactive.d.ts +1 -1
  266. package/dist/ui/interactive.d.ts.map +1 -1
  267. package/dist/ui/interactive.js +1 -1
  268. package/dist/ui/interactive.js.map +1 -1
  269. package/dist/ui/progress.d.ts +1 -1
  270. package/dist/ui/progress.js +1 -1
  271. package/dist/ui/runtime/command-chrome.js +1 -1
  272. package/dist/ui/runtime/command-chrome.js.map +1 -1
  273. package/dist/ui/runtime/run-clack-flow.js +1 -1
  274. package/dist/ui/runtime/run-clack-flow.js.map +1 -1
  275. package/dist/ui/runtime/stdin-after-ink.js +1 -1
  276. package/dist/ui/runtime/stdin-after-ink.js.map +1 -1
  277. package/dist/ui/theme.d.ts +1 -1
  278. package/dist/ui/theme.js +1 -1
  279. package/dist/valkey-sidecar.d.ts +1 -1
  280. package/dist/valkey-sidecar.d.ts.map +1 -1
  281. package/dist/valkey-sidecar.js +2 -2
  282. package/dist/valkey-sidecar.js.map +1 -1
  283. package/package.json +3 -2
  284. package/scripts/build-release-artifacts.sh +112 -0
  285. package/scripts/generate-homebrew-formula.mjs +47 -45
  286. package/scripts/mirror-deno-release.sh +1 -1
  287. package/src/TYPE-RESOLUTION.md +31 -31
  288. package/src/app/framework.ts +1 -1
  289. package/src/augmentation-generator.ts +3 -3
  290. package/src/binary-cache.ts +51 -36
  291. package/src/cache-pins.ts +2 -2
  292. package/src/cli-artifacts.ts +65 -0
  293. package/src/cli-install-method.ts +35 -4
  294. package/src/cli-package-version.ts +5 -1
  295. package/src/cli-standalone.ts +116 -34
  296. package/src/cli-version-embedded.ts +12 -0
  297. package/src/cli.ts +1 -1
  298. package/src/commands/add.ts +4 -3
  299. package/src/commands/admin.ts +6 -6
  300. package/src/commands/adopt.ts +1 -1
  301. package/src/commands/app.ts +2 -2
  302. package/src/commands/cache.ts +3 -3
  303. package/src/commands/db.ts +12 -11
  304. package/src/commands/deploy.ts +12 -12
  305. package/src/commands/dev.ts +19 -19
  306. package/src/commands/doctor.ts +3 -3
  307. package/src/commands/engine.ts +1 -1
  308. package/src/commands/functions.ts +8 -7
  309. package/src/commands/hooks.ts +6 -6
  310. package/src/commands/init.ts +28 -28
  311. package/src/commands/internal.ts +37 -0
  312. package/src/commands/login.ts +2 -2
  313. package/src/commands/logs.ts +1 -1
  314. package/src/commands/migrate.ts +5 -5
  315. package/src/commands/pg.ts +1 -1
  316. package/src/commands/plugins.ts +1 -1
  317. package/src/commands/pull.ts +2 -2
  318. package/src/commands/push.ts +3 -3
  319. package/src/commands/self-host.ts +1 -1
  320. package/src/commands/self-update.ts +23 -73
  321. package/src/commands/status.ts +1 -1
  322. package/src/commands/update.ts +1 -1
  323. package/src/config.ts +39 -18
  324. package/src/db-preflight.ts +15 -15
  325. package/src/dev-compose.ts +27 -27
  326. package/src/dev-log-filter.ts +1 -1
  327. package/src/dev-ports.ts +3 -3
  328. package/src/dev-session.ts +6 -6
  329. package/src/dev-shutdown.ts +8 -8
  330. package/src/dev-task-colors.ts +1 -1
  331. package/src/docker-postgres.ts +6 -6
  332. package/src/docker-runtime.ts +5 -5
  333. package/src/engine-client.ts +3 -3
  334. package/src/engine-push-output.ts +1 -1
  335. package/src/ensure-binary.ts +20 -0
  336. package/src/ensure-component-binaries.ts +1 -1
  337. package/src/env-file.ts +2 -2
  338. package/src/field-masking-tier.ts +6 -6
  339. package/src/functions-deno-types.ts +3 -3
  340. package/src/functions-router-gen.ts +1 -1
  341. package/src/gitignore.ts +3 -3
  342. package/src/hook-upload.ts +3 -3
  343. package/src/hooks-generator.ts +9 -9
  344. package/src/index.ts +1 -1
  345. package/src/init-project-detect.ts +1 -1
  346. package/src/link.ts +1 -1
  347. package/src/local-secrets.ts +5 -5
  348. package/src/main.ts +20 -0
  349. package/src/model-hooks.ts +4 -4
  350. package/src/pgbouncer-userlist.ts +2 -2
  351. package/src/postgres-ctl.ts +4 -4
  352. package/src/process-manager.ts +4 -4
  353. package/src/project-config.ts +16 -16
  354. package/src/pull-utils.ts +4 -4
  355. package/src/realtime-launch.ts +1 -1
  356. package/src/release-pins.ts +2 -2
  357. package/src/resolve-api-url.ts +4 -3
  358. package/src/resolve-target.ts +1 -1
  359. package/src/rest-cache-admin.ts +2 -2
  360. package/src/runtime-routes.ts +2 -2
  361. package/src/schema-ast-v2.ts +4 -4
  362. package/src/schema-push-lock.ts +3 -3
  363. package/src/scripts/postinstall.ts +1 -1
  364. package/src/self-host-compose.ts +25 -25
  365. package/src/service-role-check.ts +3 -3
  366. package/src/storage-provision.ts +3 -3
  367. package/src/studio-dev-server.ts +1 -1
  368. package/src/systemd.ts +1 -1
  369. package/src/target-client.ts +1 -1
  370. package/src/tsx-runner.ts +41 -2
  371. package/src/type-extractor.ts +27 -27
  372. package/src/type-resolver.ts +1 -1
  373. package/src/ui/README.md +1 -1
  374. package/src/ui/brand.ts +1 -1
  375. package/src/ui/components/LogoWordmark.tsx +1 -1
  376. package/src/ui/components/SelectField.tsx +1 -1
  377. package/src/ui/confirm.ts +1 -1
  378. package/src/ui/fatal.ts +1 -1
  379. package/src/ui/flows/prompt-fields.tsx +1 -1
  380. package/src/ui/interactive.ts +1 -1
  381. package/src/ui/progress.ts +1 -1
  382. package/src/ui/runtime/command-chrome.ts +1 -1
  383. package/src/ui/runtime/run-clack-flow.tsx +1 -1
  384. package/src/ui/runtime/stdin-after-ink.ts +1 -1
  385. package/src/ui/theme.ts +1 -1
  386. package/src/valkey-sidecar.ts +2 -2
  387. package/tests/access-composition.test.ts +6 -6
  388. package/tests/admin-studio-membership.test.ts +1 -1
  389. package/tests/api-schemas.test.ts +1 -1
  390. package/tests/archive-name-alias.test.ts +1 -1
  391. package/tests/cli-help.test.ts +8 -2
  392. package/tests/config-load-failure.test.ts +44 -0
  393. package/tests/db-preflight.test.ts +1 -1
  394. package/tests/doctor-render.test.ts +3 -3
  395. package/tests/doctor-service-role.test.ts +2 -2
  396. package/tests/engine-push-output.test.ts +1 -1
  397. package/tests/env-file.test.ts +3 -3
  398. package/tests/external-database-compose.test.ts +5 -5
  399. package/tests/external-database-config.test.ts +2 -2
  400. package/tests/field-masking-tier.test.ts +1 -1
  401. package/tests/homebrew-formula.test.ts +68 -26
  402. package/tests/hook-upload.test.ts +1 -1
  403. package/tests/hooks-generator.test.ts +1 -1
  404. package/tests/init.test.ts +2 -2
  405. package/tests/keys.test.ts +8 -2
  406. package/tests/local-secrets.test.ts +3 -3
  407. package/tests/model-hooks.test.ts +6 -6
  408. package/tests/runtime-contract.test.ts +2 -2
  409. package/tests/service-role-check.test.ts +3 -3
  410. package/tests/storage-provision.test.ts +1 -1
  411. package/tests/type-extractor.test.ts +2 -2
  412. package/tsconfig.tsbuildinfo +1 -1
  413. package/vitest.config.ts +7 -1
  414. package/scripts/build-release-bundle.mjs +0 -27
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Generate Formula/supatype.rb for the supatype/homebrew tap repo.
3
+ * Generate Formula/supatype.rb for the supatype/homebrew-tap repository.
4
4
  *
5
5
  * Usage:
6
- * node packages/cli/scripts/generate-homebrew-formula.mjs 0.1.5 /path/to/artifacts
6
+ * node packages/cli/scripts/generate-homebrew-formula.mjs 0.1.8 /path/to/artifacts
7
7
  *
8
- * Artifacts directory must contain:
9
- * supatype-cli-darwin-arm64
10
- * supatype-cli-darwin-amd64
11
- * supatype-cli-linux-arm64
12
- * supatype-cli-linux-amd64
8
+ * The artifacts directory is what build-release-artifacts.sh produced, so it holds the
9
+ * per-platform archives and the checksums.sha256 covering them. Hashes are read from that
10
+ * manifest rather than recomputed: the manifest is the signed record of what was published,
11
+ * and hashing the files again would let a formula disagree with the release it describes.
12
+ *
13
+ * Homebrew on Linux is glibc, so the -musl archives are not referenced here.
13
14
  *
14
15
  * Optional env:
15
- * HOMEBREW_FORMULA_OUT output path (default: ./Formula/supatype.rb relative to cwd)
16
+ * HOMEBREW_FORMULA_OUT: output path (default: ./Formula/supatype.rb relative to cwd)
16
17
  */
17
18
 
18
- import { createHash } from "node:crypto"
19
19
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
20
20
  import { dirname, join } from "node:path"
21
21
 
@@ -28,10 +28,6 @@ const PLATFORMS = [
28
28
 
29
29
  const CDN = "https://releases.supatype.com/cli"
30
30
 
31
- function sha256File(path) {
32
- return createHash("sha256").update(readFileSync(path)).digest("hex")
33
- }
34
-
35
31
  function usage() {
36
32
  console.error(`Usage: ${process.argv[1]} <version> <artifacts-dir>`)
37
33
  process.exit(1)
@@ -45,65 +41,68 @@ const outPath =
45
41
  process.env.HOMEBREW_FORMULA_OUT?.trim() ||
46
42
  join(process.cwd(), "Formula", "supatype.rb")
47
43
 
48
- const checksums = {}
44
+ const manifestPath = join(artifactsDir, "checksums.sha256")
45
+ if (!existsSync(manifestPath)) {
46
+ console.error(`Missing ${manifestPath}. Run build-release-artifacts.sh first.`)
47
+ process.exit(1)
48
+ }
49
+
50
+ // `<hash> <name>`, or `<hash> *<name>` when the publisher used binary mode.
51
+ const hashes = new Map()
52
+ for (const line of readFileSync(manifestPath, "utf8").split("\n")) {
53
+ const [hash, rawName] = line.trim().split(/\s+/)
54
+ if (hash && rawName) hashes.set(rawName.replace(/^\*/, ""), hash)
55
+ }
56
+
57
+ const archives = {}
49
58
  for (const { id } of PLATFORMS) {
50
- const file = join(artifactsDir, `supatype-cli-${id}`)
51
- if (!existsSync(file)) {
52
- console.error(`Missing artifact: ${file}`)
59
+ const name = `supatype-cli-${id}.tar.gz`
60
+ const hash = hashes.get(name)
61
+ if (!hash) {
62
+ console.error(`No checksum for ${name} in ${manifestPath}.`)
63
+ console.error(`Manifest lists: ${[...hashes.keys()].join(", ")}`)
53
64
  process.exit(1)
54
65
  }
55
- checksums[id] = sha256File(file)
66
+ archives[id] = { name, hash }
56
67
  }
57
68
 
58
- function urlBlock(os, arch, id) {
69
+ function urlBlock(arch, id) {
59
70
  const indent = " "
60
71
  const onArch = arch === "arm" ? "on_arm" : "on_intel"
61
72
  return `${indent}${onArch} do
62
- ${indent} url "${CDN}/v${version}/supatype-cli-${id}"
63
- ${indent} sha256 "${checksums[id]}"
73
+ ${indent} url "${CDN}/v${version}/${archives[id].name}"
74
+ ${indent} sha256 "${archives[id].hash}"
64
75
  ${indent}end`
65
76
  }
66
77
 
67
- const macBlocks = PLATFORMS.filter((p) => p.os === "macos")
68
- .map((p) => urlBlock(p.os, p.arch, p.id))
69
- .join("\n")
70
-
71
- const linuxBlocks = PLATFORMS.filter((p) => p.os === "linux")
72
- .map((p) => urlBlock(p.os, p.arch, p.id))
73
- .join("\n")
78
+ const blocksFor = (os) =>
79
+ PLATFORMS.filter((p) => p.os === os).map((p) => urlBlock(p.arch, p.id)).join("\n")
74
80
 
81
+ // Every archive holds one executable called `supatype`, whatever the archive is named, so the
82
+ // install step needs no per-platform knowledge. Homebrew unpacks the tarball before `install`
83
+ // runs, which is why this no longer renames a per-platform file.
75
84
  const formula = `# typed: false
76
85
  # frozen_string_literal: true
77
86
 
78
- # AUTO-GENERATED by packages/cli/scripts/generate-homebrew-formula.mjs do not edit manually.
79
- # Regenerate on each cli-v* release (supatype/.github/workflows/cli-release.yml supatype/homebrew).
87
+ # AUTO-GENERATED by packages/cli/scripts/generate-homebrew-formula.mjs: do not edit manually.
88
+ # Regenerated on each v* release by supatype/.github/workflows/cli-release.yml and pushed here.
80
89
 
81
90
  class Supatype < Formula
82
91
  desc "Type-first platform for PostgreSQL"
83
92
  homepage "https://supatype.com"
84
93
  version "${version}"
94
+ license "Apache-2.0"
85
95
 
86
96
  on_macos do
87
- ${macBlocks}
97
+ ${blocksFor("macos")}
88
98
  end
89
99
 
90
100
  on_linux do
91
- ${linuxBlocks}
101
+ ${blocksFor("linux")}
92
102
  end
93
103
 
94
104
  def install
95
- arch = if OS.mac?
96
- if Hardware::CPU.arm?
97
- "darwin-arm64"
98
- else
99
- "darwin-amd64"
100
- end
101
- elsif Hardware::CPU.arm?
102
- "linux-arm64"
103
- else
104
- "linux-amd64"
105
- end
106
- bin.install "supatype-cli-\#{arch}" => "supatype"
105
+ bin.install "supatype"
107
106
  end
108
107
 
109
108
  def post_install
@@ -118,4 +117,7 @@ end
118
117
 
119
118
  mkdirSync(dirname(outPath), { recursive: true })
120
119
  writeFileSync(outPath, formula, "utf8")
121
- console.log(`Wrote ${outPath}`)
120
+ console.log(`Wrote ${outPath} for v${version}`)
121
+ for (const { id } of PLATFORMS) {
122
+ console.log(` ${archives[id].name} ${archives[id].hash.slice(0, 16)}...`)
123
+ }
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # mirror-deno-release.sh Download official Deno release zips and rename to Supatype CDN layout.
2
+ # mirror-deno-release.sh: Download official Deno release zips and rename to Supatype CDN layout.
3
3
  #
4
4
  # Output binaries (cwd or $OUT_DIR):
5
5
  # deno-linux-amd64, deno-linux-arm64, deno-darwin-amd64, deno-darwin-arm64, deno-windows-amd64.exe
@@ -1,6 +1,6 @@
1
1
  # Type Resolution in the Schema Extractor
2
2
 
3
- `type-extractor.ts` converts TypeScript type definitions into `ExtractedSchemaAst` —
3
+ `type-extractor.ts` converts TypeScript type definitions into `ExtractedSchemaAst`,
4
4
  the JSON handed to the engine binary for SQL generation and client type output.
5
5
 
6
6
  This document explains how type names are resolved, what patterns are supported,
@@ -12,24 +12,24 @@ and how the three-tier fallback chain works.
12
12
 
13
13
  The extractor uses the TypeScript **parser only** (`ts.createSourceFile`), not the
14
14
  full type checker. This is fast and requires no `tsconfig.json`, but it means the
15
- extractor only sees raw source text it cannot evaluate what a type alias resolves to.
15
+ extractor only sees raw source text, it cannot evaluate what a type alias resolves to.
16
16
 
17
17
  The consequence is that any indirection breaks resolution:
18
18
 
19
19
  ```typescript
20
- // Works extractor sees "Optional" literally
20
+ // Works: extractor sees "Optional" literally
21
21
  type Post = Model<{ email: Optional<Email> }>
22
22
 
23
- // Previously broken extractor sees "Nullable", not "Optional"
23
+ // Previously broken: extractor sees "Nullable", not "Optional"
24
24
  type Nullable<T> = Optional<T>
25
25
  type Post = Model<{ email: Nullable<Email> }>
26
26
 
27
- // Previously broken import rename
27
+ // Previously broken: import rename
28
28
  import { Optional as Maybe } from "@supatype/types"
29
29
  type Post = Model<{ email: Maybe<Email> }>
30
30
  ```
31
31
 
32
- Failures were silent unknown types fell through to `{ kind: "text", pgType: "TEXT" }`
32
+ Failures were silent: unknown types fell through to `{ kind: "text", pgType: "TEXT" }`
33
33
  instead of throwing an error.
34
34
 
35
35
  ---
@@ -40,18 +40,18 @@ Every type name encountered in a field definition is resolved through three tier
40
40
  in order. The first tier to succeed wins. If all three fail, an error is thrown.
41
41
 
42
42
  ```
43
- Tier 1 syntactic switch instant inline primitives and modifiers by name
44
- Tier 2 alias registry instant user-defined type aliases, import renames
45
- Tier 3 TypeScript checker ~300ms† conditional types, mapped types
43
+ Tier 1: syntactic switch instant inline primitives and modifiers by name
44
+ Tier 2: alias registry instant user-defined type aliases, import renames
45
+ Tier 3: TypeScript checker ~300ms† conditional types, mapped types
46
46
  ```
47
47
 
48
- † Tier 3 is **lazy** the `ts.Program` and `TypeChecker` are only created the first
48
+ † Tier 3 is **lazy**, the `ts.Program` and `TypeChecker` are only created the first
49
49
  time a conditional or mapped type is encountered. Schemas that use only tiers 1 and 2
50
50
  pay no cost.
51
51
 
52
52
  ---
53
53
 
54
- ## Tier 1 Syntactic Switch
54
+ ## Tier 1: Syntactic Switch
55
55
 
56
56
  The existing behaviour. The extractor walks the type reference chain and matches
57
57
  names exactly against a hardcoded switch:
@@ -71,12 +71,12 @@ This covers all types used inline with their canonical names.
71
71
 
72
72
  ---
73
73
 
74
- ## Tier 2 Alias Registry
74
+ ## Tier 2: Alias Registry
75
75
 
76
76
  Built once at startup from all source files loaded by `loadSchemaSourceFiles`.
77
77
  Covers two sub-cases:
78
78
 
79
- ### 2a Type alias declarations
79
+ ### 2a: Type alias declarations
80
80
 
81
81
  Any `type X = ...` that is not a `Model<>` declaration is indexed by name:
82
82
 
@@ -103,7 +103,7 @@ type B = Optional<Email>
103
103
  Cycle detection via a `resolving: Set<string>` guard prevents infinite loops and
104
104
  throws a descriptive error instead.
105
105
 
106
- ### 2b Import renames
106
+ ### 2b: Import renames
107
107
 
108
108
  Explicit `as` renames in import statements are indexed per file:
109
109
 
@@ -123,17 +123,17 @@ the current file. `Maybe` becomes `Optional`, `MaybeNull` becomes `Nullable`
123
123
  into the source file set and their aliases are available in the registry.
124
124
 
125
125
  Only relative specifiers (`.`-prefixed) are followed. Bare specifiers and scoped
126
- packages (`@supatype/types`, `node_modules/*`) are not loaded their exported
126
+ packages (`@supatype/types`, `node_modules/*`) are not loaded, their exported
127
127
  names are already covered by the tier 1 switch.
128
128
 
129
129
  ---
130
130
 
131
- ## Tier 3 TypeScript Checker
131
+ ## Tier 3: TypeScript Checker
132
132
 
133
133
  Required for types that cannot be evaluated syntactically:
134
134
 
135
- - **Conditional types**: `T extends U ? A : B` requires evaluating the constraint
136
- - **Mapped types**: `{ [K in keyof T]: F<T[K]> }` requires enumerating `keyof T`
135
+ - **Conditional types**: `T extends U ? A : B`, requires evaluating the constraint
136
+ - **Mapped types**: `{ [K in keyof T]: F<T[K]> }`, requires enumerating `keyof T`
137
137
 
138
138
  ### How it works
139
139
 
@@ -147,7 +147,7 @@ Required for types that cannot be evaluated syntactically:
147
147
  3. `checker.getTypeAtLocation(programNode)` resolves the type fully.
148
148
 
149
149
  4. `checker.typeToString(type, ..., TypeFormatFlags.UseAliasDefinedOutsideCurrentScope)`
150
- converts it back to a string with **alias names preserved** so `Optional<Email>`
150
+ converts it back to a string with **alias names preserved**, so `Optional<Email>`
151
151
  stays as `Optional<Email>` rather than expanding to the underlying branded
152
152
  intersection type.
153
153
 
@@ -160,7 +160,7 @@ Required for types that cannot be evaluated syntactically:
160
160
 
161
161
  - A field type is directly a conditional or mapped expression
162
162
  - A tier 2 alias body contains a conditional or mapped type (detected by
163
- `needsChecker()` before text substitution is attempted the original node,
163
+ `needsChecker()` before text substitution is attempted, the original node,
164
164
  which has valid source positions, is passed to the checker instead)
165
165
  - The `Model<>` fields argument is a mapped type alias:
166
166
  ```typescript
@@ -175,40 +175,40 @@ Required for types that cannot be evaluated syntactically:
175
175
  ## What Is Supported
176
176
 
177
177
  ```typescript
178
- // Tier 1 inline, canonical names
178
+ // Tier 1: inline, canonical names
179
179
  email: Optional<Email>
180
180
  slug: Unique<Slug<"title">>
181
181
  id: PrimaryKey<UUID>
182
182
 
183
- // Tier 2a simple alias
183
+ // Tier 2a: simple alias
184
184
  type Nullable<T> = Optional<T>
185
185
  type UniqueSlug = Unique<Slug<"title">>
186
186
  email: Nullable<Email>
187
187
  slug: UniqueSlug
188
188
 
189
- // Tier 2a multi-hop
189
+ // Tier 2a: multi-hop
190
190
  type A = B
191
191
  type B = Nullable<Email>
192
192
  email: A
193
193
 
194
- // Tier 2b import rename of primitive
194
+ // Tier 2b: import rename of primitive
195
195
  import { Optional as Maybe } from "@supatype/types"
196
196
  email: Maybe<Email>
197
197
 
198
- // Tier 2b import rename of local alias
198
+ // Tier 2b: import rename of local alias
199
199
  import { Nullable as MaybeNull } from "./field-types"
200
200
  email: MaybeNull<Email>
201
201
 
202
- // Tier 2b cross-file alias (no rename)
202
+ // Tier 2b: cross-file alias (no rename)
203
203
  // helpers.ts: export type Nullable<T> = Optional<T>
204
204
  import { Nullable } from "./helpers"
205
205
  email: Nullable<Email>
206
206
 
207
- // Tier 3 conditional type
207
+ // Tier 3: conditional type
208
208
  type NullableStr<T> = T extends string ? Optional<T> : T
209
209
  email: NullableStr<Email>
210
210
 
211
- // Tier 3 mapped type as fields object
211
+ // Tier 3: mapped type as fields object
212
212
  type AllOptional<T> = { [K in keyof T]: Optional<T[K]> }
213
213
  type Post = Model<AllOptional<{ email: Email; name: Text }>>
214
214
  ```
@@ -225,10 +225,10 @@ import { SomeHelper } from "some-library"
225
225
  // symbols only available in node_modules (other than @supatype/types)
226
226
 
227
227
  // TypeScript utility types used as field types
228
- email: NonNullable<string> // error not a @supatype/types primitive
228
+ email: NonNullable<string> // error, not a @supatype/types primitive
229
229
 
230
230
  // Namespace-qualified names
231
- email: Types.Optional<Email> // error only identifier references are resolved
231
+ email: Types.Optional<Email> // error, only identifier references are resolved
232
232
  ```
233
233
 
234
234
  ---
@@ -290,5 +290,5 @@ type CheckerContext = {
290
290
  ## Adding a New Tier 1 Primitive
291
291
 
292
292
  When a new type is added to `@supatype/types`, add a `case` to the `switch` in
293
- `parseScalarType`. No other changes are needed tier 2 and tier 3 handle
293
+ `parseScalarType`. No other changes are needed, tier 2 and tier 3 handle
294
294
  aliases and compositions of it automatically.
@@ -41,7 +41,7 @@ const FRAMEWORK_DETECTION: Array<{ dep: string; framework: AppFramework }> = [
41
41
  { dep: "@remix-run/react", framework: "remix-spa" },
42
42
  { dep: "@sveltejs/kit", framework: "sveltekit" },
43
43
  { dep: "nuxt", framework: "nuxt" },
44
- // Vite last many frameworks use Vite under the hood
44
+ // Vite last: many frameworks use Vite under the hood
45
45
  { dep: "vite", framework: "vite" },
46
46
  ]
47
47
 
@@ -15,7 +15,7 @@ interface AstShape {
15
15
  * Shared with the hooks generator on purpose.
16
16
  *
17
17
  * A hook's `row` must be the same shape the client sees for that table, and two copies of this logic
18
- * would drift the client would gain a column type the hook handler did not, which is the failure
18
+ * would drift: the client would gain a column type the hook handler did not, which is the failure
19
19
  * mode this codebase has already paid for once.
20
20
  */
21
21
  export function resolveTableName(model: AstModel): string {
@@ -43,7 +43,7 @@ export function generateClientAugmentation(ast: unknown): string {
43
43
  .sort((a, b) => a.tableName.localeCompare(b.tableName))
44
44
 
45
45
  const lines: string[] = []
46
- lines.push("// Generated by supatype CLI do not edit manually.")
46
+ lines.push("// Generated by supatype CLI, do not edit manually.")
47
47
  lines.push("")
48
48
  lines.push("declare module \"@supatype/client\" {")
49
49
  lines.push(" interface SupatypeModels {")
@@ -104,7 +104,7 @@ function toTsType(meta: Record<string, unknown>): string {
104
104
  const required = meta["required"] === true
105
105
  const base = (() => {
106
106
  // A field that knows its own shape says so. Without this, everything stored as JSONB collapses
107
- // to `Record<string, unknown>` in the generated row so `Currency` would arrive as an opaque
107
+ // to `Record<string, unknown>` in the generated row, so `Currency` would arrive as an opaque
108
108
  // object rather than `{ amount: string; code: "USD" }`, and the schema's precision would be
109
109
  // lost exactly where a caller reads it.
110
110
  const declared = meta["tsType"]
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Binary cache manages supatype component binaries.
2
+ * Binary cache: manages supatype component binaries.
3
3
  *
4
4
  * Components: engine, server, postgres, deno, realtime.
5
5
  * Cache root: ~/.supatype/cache/{component}/{version}/
@@ -71,7 +71,7 @@ export function hasMeaningfulOverrides(config: SupatypeProjectConfig): boolean {
71
71
  return false
72
72
  }
73
73
 
74
- /** Lines for a startup banner non-empty override paths only. */
74
+ /** Lines for a startup banner, non-empty override paths only. */
75
75
  export function describeActiveOverrides(config: SupatypeProjectConfig): string[] {
76
76
  const o = config.overrides
77
77
  if (!o) return []
@@ -200,7 +200,7 @@ function binaryName(component: Component, version: string, platform: PlatformId)
200
200
  * Names a published archive may carry, most-canonical first.
201
201
  *
202
202
  * `supatype-postgres` published the Intel macOS archive as `darwin-x86_64` while every other platform
203
- * used `amd64` the spelling the CLI derives from `process.arch === "x64"`. Releases already on the CDN
203
+ * used `amd64`, the spelling the CLI derives from `process.arch === "x64"`. Releases already on the CDN
204
204
  * carry the old name, so both are accepted and the *signed* checksums manifest decides which exists.
205
205
  * Nothing is guessed: the URL and the hash always come from the same manifest entry.
206
206
  */
@@ -242,9 +242,9 @@ export function currentPlatform(): PlatformId {
242
242
  * Resolve the binary path for a component.
243
243
  *
244
244
  * Resolution order:
245
- * 1. config.overrides?.[component] local build path (must exist)
245
+ * 1. config.overrides?.[component]: local build path (must exist)
246
246
  * 2. Cached binary at ~/.supatype/cache/{component}/{version}/
247
- * 3. Throws caller should call download() first.
247
+ * 3. Throws, so the caller should call download() first.
248
248
  *
249
249
  * Hard error if any meaningful `overrides` entry is set while the project is linked to cloud
250
250
  * (`project.ref`, `.supatype/cloud.json`, or `.supatype/linked.json`).
@@ -352,7 +352,7 @@ async function acquireDownloadSlot(
352
352
 
353
353
  if (isDownloadInProgress(component, version)) {
354
354
  console.log(
355
- `[supatype] ${component} v${version} is downloading in another process waiting...`,
355
+ `[supatype] ${component} v${version} is downloading in another process, waiting...`,
356
356
  )
357
357
  const outcome = await waitForComponentDownload(component, version, isReady, (c) => {
358
358
  console.log(`[supatype] Still waiting for ${c} download...`)
@@ -364,7 +364,7 @@ async function acquireDownloadSlot(
364
364
  )
365
365
  }
366
366
  console.warn(
367
- `[supatype] ${component} v${version} download did not finish in the other process retrying.`,
367
+ `[supatype] ${component} v${version} download did not finish in the other process, retrying.`,
368
368
  )
369
369
  continue
370
370
  }
@@ -384,7 +384,7 @@ export async function download(
384
384
  ): Promise<string> {
385
385
  if (version === VERSION_PIN_LOCAL) {
386
386
  throw new Error(
387
- `cannot download CDN binary when version is "${VERSION_PIN_LOCAL}" set overrides.${component === "postgres" ? "postgres_dir" : component} or pin a semver`,
387
+ `cannot download CDN binary when version is "${VERSION_PIN_LOCAL}": set overrides.${component === "postgres" ? "postgres_dir" : component} or pin a semver`,
388
388
  )
389
389
  }
390
390
 
@@ -400,7 +400,7 @@ export async function download(
400
400
  return destPath
401
401
  }
402
402
  console.warn(
403
- `[supatype] ${component} v${version} cache invalid re-downloading (${destPath}).`,
403
+ `[supatype] ${component} v${version} cache invalid, re-downloading (${destPath}).`,
404
404
  )
405
405
  unlinkSync(destPath)
406
406
  }
@@ -461,7 +461,15 @@ export async function download(
461
461
  * Fetch checksums.sha256, optionally verify its minisign signature, and
462
462
  * return the expected SHA256 for `binaryFilename`.
463
463
  */
464
- async function fetchChecksums(
464
+ /**
465
+ * Fetch a checksums manifest and verify its minisign signature, returning the entry for one of
466
+ * `binaryFilenames`.
467
+ *
468
+ * Exported so the standalone CLI download path enforces the same rule as component downloads.
469
+ * It previously verified nothing at all, which made the CLI stricter about a postgres archive
470
+ * than about overwriting its own executable.
471
+ */
472
+ export async function fetchChecksums(
465
473
  checksumsUrl: string,
466
474
  minisigUrl: string,
467
475
  binaryFilenames: string | string[],
@@ -476,16 +484,16 @@ async function fetchChecksums(
476
484
  if (!pubKey) {
477
485
  // Fail closed: a missing public key means we cannot verify authenticity, only
478
486
  // integrity (SHA256). Published builds always embed the key, so this only
479
- // happens in source/contributor builds never silently downgrade.
487
+ // happens in source/contributor builds. Never silently downgrade.
480
488
  if (process.env["SUPATYPE_ALLOW_UNVERIFIED_DOWNLOADS"] === "1") {
481
489
  console.warn(
482
- "[supatype] \u26a0 SUPATYPE_ALLOW_UNVERIFIED_DOWNLOADS=1 no minisign public " +
490
+ "[supatype] \u26a0 SUPATYPE_ALLOW_UNVERIFIED_DOWNLOADS=1: no minisign public " +
483
491
  "key configured; verifying SHA256 only (authenticity NOT checked).",
484
492
  )
485
493
  return extractChecksum(checksumsText, binaryFilenames)
486
494
  }
487
495
  throw new Error(
488
- "No minisign public key configured cannot verify release authenticity.\n" +
496
+ "No minisign public key configured, so cannot verify release authenticity.\n" +
489
497
  "Published @supatype/cli builds embed the key automatically; if you are building " +
490
498
  "from source, set SUPATYPE_RELEASE_PUBLIC_KEY to the release public key, or set " +
491
499
  "SUPATYPE_ALLOW_UNVERIFIED_DOWNLOADS=1 to download with SHA256-only verification (unsafe).",
@@ -511,7 +519,7 @@ async function fetchChecksums(
511
519
  // ---------------------------------------------------------------------------
512
520
 
513
521
  /**
514
- * Ed25519 SPKI DER prefix wraps a raw 32-byte public key into the
522
+ * Ed25519 SPKI DER prefix, wraps a raw 32-byte public key into the
515
523
  * SubjectPublicKeyInfo structure that Node.js crypto.createPublicKey expects.
516
524
  *
517
525
  * Breakdown:
@@ -539,7 +547,7 @@ export function verifyMinisign(fileBytes: Buffer, sigFileContent: string, pubKey
539
547
 
540
548
  // Parse signature file:
541
549
  // line 0: untrusted comment
542
- // line 1: base64 sig bytes [2 algo][8 keyId][64 Ed25519 sig]
550
+ // line 1: base64 sig bytes: [2 algo][8 keyId][64 Ed25519 sig]
543
551
  // line 2: trusted comment
544
552
  // line 3: base64 global sig (over sig bytes + trusted comment)
545
553
  const sigLines = sigFileContent.trim().split("\n")
@@ -552,12 +560,12 @@ export function verifyMinisign(fileBytes: Buffer, sigFileContent: string, pubKey
552
560
  const signature = sigBytes.subarray(10, 74)
553
561
 
554
562
  // Both Ed25519 modes are supported:
555
- // "Ed" (0x45, 0x64) legacy: signature is over the raw file bytes.
556
- // "ED" (0x45, 0x44) prehashed: signature is over BLAKE2b-512(file).
563
+ // "Ed" (0x45, 0x64) legacy: signature is over the raw file bytes.
564
+ // "ED" (0x45, 0x44) prehashed: signature is over BLAKE2b-512(file).
557
565
  // Modern minisign (and our release pipeline) default to prehashed mode.
558
566
  if (algo[0] !== 0x45 || (algo[1] !== 0x64 && algo[1] !== 0x44)) {
559
567
  throw new Error(
560
- "Unsupported minisign algorithm expected Ed25519 ('Ed' legacy or 'ED' prehashed).\n" +
568
+ "Unsupported minisign algorithm, expected Ed25519 ('Ed' legacy or 'ED' prehashed).\n" +
561
569
  `Got: 0x${algo[0]?.toString(16)}${algo[1]?.toString(16)}`,
562
570
  )
563
571
  }
@@ -565,7 +573,7 @@ export function verifyMinisign(fileBytes: Buffer, sigFileContent: string, pubKey
565
573
 
566
574
  if (!sigKeyId.equals(pkKeyId)) {
567
575
  throw new Error(
568
- "Minisign key ID mismatch signature was produced with a different key.\n" +
576
+ "Minisign key ID mismatch: the signature was produced with a different key.\n" +
569
577
  "This could indicate a compromised release. Do not proceed.",
570
578
  )
571
579
  }
@@ -582,7 +590,7 @@ export function verifyMinisign(fileBytes: Buffer, sigFileContent: string, pubKey
582
590
  const valid = cryptoVerify(null, signedData, keyObject, signature)
583
591
  if (!valid) {
584
592
  throw new Error(
585
- "Minisign signature verification FAILED the checksum file may have been tampered with.\n" +
593
+ "Minisign signature verification FAILED: the checksum file may have been tampered with.\n" +
586
594
  "This could indicate a supply chain attack. Aborting download.",
587
595
  )
588
596
  }
@@ -590,14 +598,21 @@ export function verifyMinisign(fileBytes: Buffer, sigFileContent: string, pubKey
590
598
 
591
599
  /**
592
600
  * Extract the SHA256 hash for `filename` from a checksums.sha256 file.
593
- * Format: `<hash> <filename>` (sha256sum output, two spaces).
601
+ * Format: `<hash> <filename>` (sha256sum output, two spaces), or `<hash> *<filename>` when
602
+ * the publisher used binary mode.
603
+ *
604
+ * Exported so the standalone CLI download path parses the manifest the same way rather than
605
+ * carrying a second implementation.
594
606
  */
595
- function extractChecksum(checksumsText: string, filenames: string | string[]): ChecksumMatch {
607
+ export function extractChecksum(
608
+ checksumsText: string,
609
+ filenames: string | string[],
610
+ ): ChecksumMatch {
596
611
  const targets = (Array.isArray(filenames) ? filenames : [filenames]).map((f) => basename(f))
597
612
  for (const target of targets) {
598
613
  for (const line of checksumsText.split("\n")) {
599
614
  const parts = line.trim().split(/\s+/)
600
- if (parts.length >= 2 && parts[1] === target) {
615
+ if (parts.length >= 2 && parts[1]?.replace(/^\*/, "") === target) {
601
616
  return { filename: target, checksum: parts[0]! }
602
617
  }
603
618
  }
@@ -608,7 +623,7 @@ function extractChecksum(checksumsText: string, filenames: string | string[]): C
608
623
  )
609
624
  }
610
625
 
611
- /** Which published name matched, and its hash both from the same signed manifest entry. */
626
+ /** Which published name matched, and its hash, both from the same signed manifest entry. */
612
627
  export interface ChecksumMatch {
613
628
  filename: string
614
629
  checksum: string
@@ -690,9 +705,9 @@ export function validateArtifactFormat(
690
705
 
691
706
  /**
692
707
  * Per-component CDN artifact shapes:
693
- * engine, server, deno, realtime native executable (ELF / Mach-O / PE)
694
- * postgres (unix) .tar.gz (gzip)
695
- * postgres (windows) .zip
708
+ * engine, server, deno, realtime: native executable (ELF / Mach-O / PE)
709
+ * postgres (unix) .tar.gz (gzip)
710
+ * postgres (windows) .zip
696
711
  */
697
712
  function assertArtifactFormat(
698
713
  component: Component,
@@ -719,7 +734,7 @@ function assertGzipArchive(filePath: string): void {
719
734
  if (magic[0] !== 0x1f || magic[1] !== 0x8b) {
720
735
  throw new Error(
721
736
  "Downloaded postgres file is not a gzip archive (bad magic bytes). " +
722
- "The CDN object may be corrupt or cached HTML delete ~/.supatype/cache and retry.",
737
+ "The CDN object may be corrupt or cached HTML, so delete ~/.supatype/cache and retry.",
723
738
  )
724
739
  }
725
740
  } finally {
@@ -736,7 +751,7 @@ function assertZipArchive(filePath: string): void {
736
751
  if (magic[0] !== 0x50 || magic[1] !== 0x4b) {
737
752
  throw new Error(
738
753
  "Downloaded postgres file is not a zip archive (bad magic bytes). " +
739
- "The CDN object may be corrupt or cached HTML delete ~/.supatype/cache and retry.",
754
+ "The CDN object may be corrupt or cached HTML, so delete ~/.supatype/cache and retry.",
740
755
  )
741
756
  }
742
757
  } finally {
@@ -759,14 +774,14 @@ function assertNativeExecutable(
759
774
  if (goCArchive) {
760
775
  throw new Error(
761
776
  `Downloaded ${component} file is a Go static archive (c-archive), not an executable. ` +
762
- "The CDN object may be from a bad release build delete ~/.supatype/cache and retry.",
777
+ "The CDN object may be from a bad release build, so delete ~/.supatype/cache and retry.",
763
778
  )
764
779
  }
765
780
  if (platform.os === "windows") {
766
781
  if (magic[0] !== 0x4d || magic[1] !== 0x5a) {
767
782
  throw new Error(
768
783
  `Downloaded ${component} file is not a Windows PE executable (bad magic bytes). ` +
769
- "The CDN object may be corrupt or cached HTML delete ~/.supatype/cache and retry.",
784
+ "The CDN object may be corrupt or cached HTML, so delete ~/.supatype/cache and retry.",
770
785
  )
771
786
  }
772
787
  return
@@ -777,7 +792,7 @@ function assertNativeExecutable(
777
792
  if (!elf) {
778
793
  throw new Error(
779
794
  `Downloaded ${component} file is not an ELF executable (bad magic bytes). ` +
780
- "The CDN object may be corrupt or cached HTML delete ~/.supatype/cache and retry.",
795
+ "The CDN object may be corrupt or cached HTML, so delete ~/.supatype/cache and retry.",
781
796
  )
782
797
  }
783
798
  return
@@ -791,7 +806,7 @@ function assertNativeExecutable(
791
806
  if (!macho) {
792
807
  throw new Error(
793
808
  `Downloaded ${component} file is not a Mach-O executable (bad magic bytes). ` +
794
- "The CDN object may be corrupt or cached HTML delete ~/.supatype/cache and retry.",
809
+ "The CDN object may be corrupt or cached HTML, so delete ~/.supatype/cache and retry.",
795
810
  )
796
811
  }
797
812
  } finally {
@@ -837,7 +852,7 @@ async function withRetry<T>(fn: () => Promise<T>, attempts = 3): Promise<T> {
837
852
  // ---------------------------------------------------------------------------
838
853
 
839
854
  /**
840
- * On Windows, Git Bash represents paths as /c/Users/... convert to C:\Users\...
855
+ * On Windows, Git Bash represents paths as /c/Users/..., convert to C:\Users\...
841
856
  */
842
857
  export function normalisePlatformPath(p: string): string {
843
858
  let result = p
@@ -931,7 +946,7 @@ export async function fetchAllLatestVersions(): Promise<Partial<Record<Component
931
946
  */
932
947
  /**
933
948
  * Verify cached binaries for the current platform (used by integration CI).
934
- * Only checks components present in `versions` unpublished CDN components
949
+ * Only checks components present in `versions`; unpublished CDN components
935
950
  * (no latest.json yet) are skipped with a log so CI can land before first release.
936
951
  * Throws if a pinned component is missing from cache or fails format checks.
937
952
  */
@@ -944,7 +959,7 @@ export function verifyCachedBinaries(versions: Partial<ComponentVersions> | unde
944
959
  const version = versions[component]
945
960
  if (typeof version !== "string" || version.trim() === "") {
946
961
  console.log(
947
- `[supatype] skipping verify for ${component} (no version CDN latest.json not published yet)`,
962
+ `[supatype] skipping verify for ${component} (no version, CDN latest.json not published yet)`,
948
963
  )
949
964
  continue
950
965
  }