@supatype/cli 0.1.0 → 0.1.2

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 (331) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +121 -86
  3. package/.turbo/turbo-typecheck.log +2 -2
  4. package/dist/binary-cache.d.ts +2 -0
  5. package/dist/binary-cache.d.ts.map +1 -1
  6. package/dist/binary-cache.js +36 -0
  7. package/dist/binary-cache.js.map +1 -1
  8. package/dist/binary-download-lock.d.ts +12 -0
  9. package/dist/binary-download-lock.d.ts.map +1 -0
  10. package/dist/binary-download-lock.js +106 -0
  11. package/dist/binary-download-lock.js.map +1 -0
  12. package/dist/cli-package-version.d.ts +3 -0
  13. package/dist/cli-package-version.d.ts.map +1 -0
  14. package/dist/cli-package-version.js +15 -0
  15. package/dist/cli-package-version.js.map +1 -0
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/cli.js +5 -2
  18. package/dist/cli.js.map +1 -1
  19. package/dist/commands/add.js +25 -19
  20. package/dist/commands/add.js.map +1 -1
  21. package/dist/commands/admin.d.ts +28 -1
  22. package/dist/commands/admin.d.ts.map +1 -1
  23. package/dist/commands/admin.js +290 -112
  24. package/dist/commands/admin.js.map +1 -1
  25. package/dist/commands/cache.d.ts +1 -1
  26. package/dist/commands/cache.d.ts.map +1 -1
  27. package/dist/commands/cache.js +98 -5
  28. package/dist/commands/cache.js.map +1 -1
  29. package/dist/commands/dev.d.ts.map +1 -1
  30. package/dist/commands/dev.js +28 -22
  31. package/dist/commands/dev.js.map +1 -1
  32. package/dist/commands/init.d.ts +8 -4
  33. package/dist/commands/init.d.ts.map +1 -1
  34. package/dist/commands/init.js +278 -139
  35. package/dist/commands/init.js.map +1 -1
  36. package/dist/commands/link-helpers.d.ts.map +1 -1
  37. package/dist/commands/link-helpers.js +26 -25
  38. package/dist/commands/link-helpers.js.map +1 -1
  39. package/dist/commands/push.js +3 -3
  40. package/dist/commands/push.js.map +1 -1
  41. package/dist/compose-local-server-image.d.ts +13 -0
  42. package/dist/compose-local-server-image.d.ts.map +1 -0
  43. package/dist/compose-local-server-image.js +57 -0
  44. package/dist/compose-local-server-image.js.map +1 -0
  45. package/dist/compose-rename.d.ts +10 -0
  46. package/dist/compose-rename.d.ts.map +1 -0
  47. package/dist/compose-rename.js +64 -0
  48. package/dist/compose-rename.js.map +1 -0
  49. package/dist/dev-compose.d.ts.map +1 -1
  50. package/dist/dev-compose.js +138 -97
  51. package/dist/dev-compose.js.map +1 -1
  52. package/dist/dev-log-bus.d.ts +5 -0
  53. package/dist/dev-log-bus.d.ts.map +1 -1
  54. package/dist/dev-log-bus.js +14 -0
  55. package/dist/dev-log-bus.js.map +1 -1
  56. package/dist/dev-log-filter.d.ts +4 -0
  57. package/dist/dev-log-filter.d.ts.map +1 -1
  58. package/dist/dev-log-filter.js +52 -0
  59. package/dist/dev-log-filter.js.map +1 -1
  60. package/dist/dev-ports.d.ts +27 -0
  61. package/dist/dev-ports.d.ts.map +1 -0
  62. package/dist/dev-ports.js +178 -0
  63. package/dist/dev-ports.js.map +1 -0
  64. package/dist/dev-ready-panel.d.ts +19 -0
  65. package/dist/dev-ready-panel.d.ts.map +1 -0
  66. package/dist/dev-ready-panel.js +49 -0
  67. package/dist/dev-ready-panel.js.map +1 -0
  68. package/dist/dev-session-lock.d.ts +25 -0
  69. package/dist/dev-session-lock.d.ts.map +1 -0
  70. package/dist/dev-session-lock.js +78 -0
  71. package/dist/dev-session-lock.js.map +1 -0
  72. package/dist/dev-session.d.ts +18 -5
  73. package/dist/dev-session.d.ts.map +1 -1
  74. package/dist/dev-session.js +91 -18
  75. package/dist/dev-session.js.map +1 -1
  76. package/dist/dev-shutdown.d.ts +20 -2
  77. package/dist/dev-shutdown.d.ts.map +1 -1
  78. package/dist/dev-shutdown.js +88 -10
  79. package/dist/dev-shutdown.js.map +1 -1
  80. package/dist/dev-task-colors.d.ts +3 -1
  81. package/dist/dev-task-colors.d.ts.map +1 -1
  82. package/dist/dev-task-colors.js +23 -3
  83. package/dist/dev-task-colors.js.map +1 -1
  84. package/dist/docker-runtime.js +1 -1
  85. package/dist/docker-runtime.js.map +1 -1
  86. package/dist/engine-push-output.d.ts +1 -0
  87. package/dist/engine-push-output.d.ts.map +1 -1
  88. package/dist/engine-push-output.js +4 -1
  89. package/dist/engine-push-output.js.map +1 -1
  90. package/dist/ensure-binary.d.ts.map +1 -1
  91. package/dist/ensure-binary.js +14 -2
  92. package/dist/ensure-binary.js.map +1 -1
  93. package/dist/ensure-component-binaries.d.ts +17 -0
  94. package/dist/ensure-component-binaries.d.ts.map +1 -0
  95. package/dist/ensure-component-binaries.js +45 -0
  96. package/dist/ensure-component-binaries.js.map +1 -0
  97. package/dist/ensure-dev-api-config.d.ts +3 -0
  98. package/dist/ensure-dev-api-config.d.ts.map +1 -0
  99. package/dist/ensure-dev-api-config.js +17 -0
  100. package/dist/ensure-dev-api-config.js.map +1 -0
  101. package/dist/env-file.d.ts +5 -0
  102. package/dist/env-file.d.ts.map +1 -0
  103. package/dist/env-file.js +33 -0
  104. package/dist/env-file.js.map +1 -0
  105. package/dist/init-dependency-versions.d.ts +13 -0
  106. package/dist/init-dependency-versions.d.ts.map +1 -0
  107. package/dist/init-dependency-versions.js +53 -0
  108. package/dist/init-dependency-versions.js.map +1 -0
  109. package/dist/init-package-json.d.ts +21 -0
  110. package/dist/init-package-json.d.ts.map +1 -0
  111. package/dist/init-package-json.js +46 -0
  112. package/dist/init-package-json.js.map +1 -0
  113. package/dist/postgres-ctl.d.ts.map +1 -1
  114. package/dist/postgres-ctl.js +2 -1
  115. package/dist/postgres-ctl.js.map +1 -1
  116. package/dist/required-host-components.d.ts +11 -0
  117. package/dist/required-host-components.d.ts.map +1 -0
  118. package/dist/required-host-components.js +25 -0
  119. package/dist/required-host-components.js.map +1 -0
  120. package/dist/resolve-api-url.d.ts +6 -0
  121. package/dist/resolve-api-url.d.ts.map +1 -0
  122. package/dist/resolve-api-url.js +39 -0
  123. package/dist/resolve-api-url.js.map +1 -0
  124. package/dist/rest-cache-admin.d.ts +33 -0
  125. package/dist/rest-cache-admin.d.ts.map +1 -0
  126. package/dist/rest-cache-admin.js +96 -0
  127. package/dist/rest-cache-admin.js.map +1 -0
  128. package/dist/scripts/postinstall.d.ts +4 -6
  129. package/dist/scripts/postinstall.d.ts.map +1 -1
  130. package/dist/scripts/postinstall.js +8 -41
  131. package/dist/scripts/postinstall.js.map +1 -1
  132. package/dist/self-host-compose.d.ts.map +1 -1
  133. package/dist/self-host-compose.js +24 -13
  134. package/dist/self-host-compose.js.map +1 -1
  135. package/dist/studio-dev-server.d.ts +4 -2
  136. package/dist/studio-dev-server.d.ts.map +1 -1
  137. package/dist/studio-dev-server.js +3 -2
  138. package/dist/studio-dev-server.js.map +1 -1
  139. package/dist/ui/brand.d.ts +2 -5
  140. package/dist/ui/brand.d.ts.map +1 -1
  141. package/dist/ui/brand.js +2 -7
  142. package/dist/ui/brand.js.map +1 -1
  143. package/dist/ui/clack-api.d.ts +44 -0
  144. package/dist/ui/clack-api.d.ts.map +1 -0
  145. package/dist/ui/clack-api.js +76 -0
  146. package/dist/ui/clack-api.js.map +1 -0
  147. package/dist/ui/clack.d.ts +14 -0
  148. package/dist/ui/clack.d.ts.map +1 -0
  149. package/dist/ui/clack.js +147 -0
  150. package/dist/ui/clack.js.map +1 -0
  151. package/dist/ui/components/FlowSpinner.d.ts +5 -0
  152. package/dist/ui/components/FlowSpinner.d.ts.map +1 -0
  153. package/dist/ui/components/FlowSpinner.js +8 -0
  154. package/dist/ui/components/FlowSpinner.js.map +1 -0
  155. package/dist/ui/components/LogoWordmark.d.ts +9 -0
  156. package/dist/ui/components/LogoWordmark.d.ts.map +1 -0
  157. package/dist/ui/components/LogoWordmark.js +17 -0
  158. package/dist/ui/components/LogoWordmark.js.map +1 -0
  159. package/dist/ui/components/PromptPanel.d.ts +5 -0
  160. package/dist/ui/components/PromptPanel.d.ts.map +1 -0
  161. package/dist/ui/components/PromptPanel.js +7 -0
  162. package/dist/ui/components/PromptPanel.js.map +1 -0
  163. package/dist/ui/components/SelectField.d.ts +11 -0
  164. package/dist/ui/components/SelectField.d.ts.map +1 -0
  165. package/dist/ui/components/SelectField.js +19 -0
  166. package/dist/ui/components/SelectField.js.map +1 -0
  167. package/dist/ui/confirm.d.ts +2 -1
  168. package/dist/ui/confirm.d.ts.map +1 -1
  169. package/dist/ui/confirm.js +4 -4
  170. package/dist/ui/confirm.js.map +1 -1
  171. package/dist/ui/dev/DevDashboard.d.ts +8 -0
  172. package/dist/ui/dev/DevDashboard.d.ts.map +1 -0
  173. package/dist/ui/dev/DevDashboard.js +151 -0
  174. package/dist/ui/dev/DevDashboard.js.map +1 -0
  175. package/dist/ui/dev/DevReadyPanelView.d.ts +7 -0
  176. package/dist/ui/dev/DevReadyPanelView.d.ts.map +1 -0
  177. package/dist/ui/dev/DevReadyPanelView.js +29 -0
  178. package/dist/ui/dev/DevReadyPanelView.js.map +1 -0
  179. package/dist/ui/fatal.d.ts.map +1 -1
  180. package/dist/ui/fatal.js +5 -11
  181. package/dist/ui/fatal.js.map +1 -1
  182. package/dist/ui/flows/FlowApp.d.ts +8 -0
  183. package/dist/ui/flows/FlowApp.d.ts.map +1 -0
  184. package/dist/ui/flows/FlowApp.js +42 -0
  185. package/dist/ui/flows/FlowApp.js.map +1 -0
  186. package/dist/ui/flows/prompt-fields.d.ts +48 -0
  187. package/dist/ui/flows/prompt-fields.d.ts.map +1 -0
  188. package/dist/ui/flows/prompt-fields.js +88 -0
  189. package/dist/ui/flows/prompt-fields.js.map +1 -0
  190. package/dist/ui/flows/types.d.ts +41 -0
  191. package/dist/ui/flows/types.d.ts.map +1 -0
  192. package/dist/ui/flows/types.js +2 -0
  193. package/dist/ui/flows/types.js.map +1 -0
  194. package/dist/ui/index.d.ts +1 -1
  195. package/dist/ui/index.js +1 -1
  196. package/dist/ui/messages.d.ts +1 -0
  197. package/dist/ui/messages.d.ts.map +1 -1
  198. package/dist/ui/messages.js +48 -8
  199. package/dist/ui/messages.js.map +1 -1
  200. package/dist/ui/progress.d.ts +5 -1
  201. package/dist/ui/progress.d.ts.map +1 -1
  202. package/dist/ui/progress.js +12 -3
  203. package/dist/ui/progress.js.map +1 -1
  204. package/dist/ui/prompts.d.ts +7 -5
  205. package/dist/ui/prompts.d.ts.map +1 -1
  206. package/dist/ui/prompts.js +15 -8
  207. package/dist/ui/prompts.js.map +1 -1
  208. package/dist/ui/runtime/cancel.d.ts +4 -0
  209. package/dist/ui/runtime/cancel.d.ts.map +1 -0
  210. package/dist/ui/runtime/cancel.js +6 -0
  211. package/dist/ui/runtime/cancel.js.map +1 -0
  212. package/dist/ui/runtime/command-chrome.d.ts +17 -0
  213. package/dist/ui/runtime/command-chrome.d.ts.map +1 -0
  214. package/dist/ui/runtime/command-chrome.js +123 -0
  215. package/dist/ui/runtime/command-chrome.js.map +1 -0
  216. package/dist/ui/runtime/dev-prompt-queue.d.ts +30 -0
  217. package/dist/ui/runtime/dev-prompt-queue.d.ts.map +1 -0
  218. package/dist/ui/runtime/dev-prompt-queue.js +57 -0
  219. package/dist/ui/runtime/dev-prompt-queue.js.map +1 -0
  220. package/dist/ui/runtime/flow-session.d.ts +4 -0
  221. package/dist/ui/runtime/flow-session.d.ts.map +1 -0
  222. package/dist/ui/runtime/flow-session.js +8 -0
  223. package/dist/ui/runtime/flow-session.js.map +1 -0
  224. package/dist/ui/runtime/run-clack-flow.d.ts +5 -0
  225. package/dist/ui/runtime/run-clack-flow.d.ts.map +1 -0
  226. package/dist/ui/runtime/run-clack-flow.js +34 -0
  227. package/dist/ui/runtime/run-clack-flow.js.map +1 -0
  228. package/dist/ui/theme.d.ts +24 -0
  229. package/dist/ui/theme.d.ts.map +1 -0
  230. package/dist/ui/theme.js +34 -0
  231. package/dist/ui/theme.js.map +1 -0
  232. package/dist/valkey-sidecar.d.ts +17 -0
  233. package/dist/valkey-sidecar.d.ts.map +1 -0
  234. package/dist/valkey-sidecar.js +94 -0
  235. package/dist/valkey-sidecar.js.map +1 -0
  236. package/package.json +11 -3
  237. package/src/binary-cache.ts +61 -0
  238. package/src/binary-download-lock.ts +124 -0
  239. package/src/cli-package-version.ts +15 -0
  240. package/src/cli.ts +6 -2
  241. package/src/commands/add.ts +26 -19
  242. package/src/commands/admin.ts +380 -137
  243. package/src/commands/cache.ts +105 -5
  244. package/src/commands/dev.ts +29 -21
  245. package/src/commands/init.ts +217 -46
  246. package/src/commands/link-helpers.ts +30 -29
  247. package/src/commands/push.ts +3 -3
  248. package/src/compose-local-server-image.ts +68 -0
  249. package/src/compose-rename.ts +73 -0
  250. package/src/dev-compose.ts +175 -96
  251. package/src/dev-log-bus.ts +18 -0
  252. package/src/dev-log-filter.ts +42 -0
  253. package/src/dev-ports.ts +223 -0
  254. package/src/dev-ready-panel.ts +63 -0
  255. package/src/dev-session-lock.ts +98 -0
  256. package/src/dev-session.ts +98 -18
  257. package/src/dev-shutdown.ts +114 -9
  258. package/src/dev-task-colors.ts +22 -3
  259. package/src/docker-runtime.ts +1 -1
  260. package/src/engine-push-output.ts +5 -1
  261. package/src/ensure-binary.ts +21 -1
  262. package/src/ensure-component-binaries.ts +71 -0
  263. package/src/ensure-dev-api-config.ts +18 -0
  264. package/src/env-file.ts +37 -0
  265. package/src/init-dependency-versions.ts +69 -0
  266. package/src/init-package-json.ts +63 -0
  267. package/src/postgres-ctl.ts +2 -1
  268. package/src/required-host-components.ts +37 -0
  269. package/src/resolve-api-url.ts +43 -0
  270. package/src/rest-cache-admin.ts +135 -0
  271. package/src/scripts/postinstall.ts +9 -46
  272. package/src/self-host-compose.ts +23 -12
  273. package/src/studio-dev-server.ts +5 -4
  274. package/src/ui/README.md +13 -9
  275. package/src/ui/brand.ts +2 -8
  276. package/src/ui/clack-api.ts +123 -0
  277. package/src/ui/clack.ts +153 -0
  278. package/src/ui/components/FlowSpinner.tsx +15 -0
  279. package/src/ui/components/LogoWordmark.tsx +36 -0
  280. package/src/ui/components/PromptPanel.tsx +17 -0
  281. package/src/ui/components/SelectField.tsx +58 -0
  282. package/src/ui/confirm.ts +5 -4
  283. package/src/ui/dev/DevDashboard.tsx +213 -0
  284. package/src/ui/dev/DevReadyPanelView.tsx +67 -0
  285. package/src/ui/fatal.ts +5 -10
  286. package/src/ui/flows/FlowApp.tsx +67 -0
  287. package/src/ui/flows/prompt-fields.tsx +192 -0
  288. package/src/ui/flows/types.ts +50 -0
  289. package/src/ui/index.ts +1 -1
  290. package/src/ui/messages.ts +50 -8
  291. package/src/ui/progress.ts +14 -3
  292. package/src/ui/prompts.ts +17 -9
  293. package/src/ui/runtime/cancel.ts +6 -0
  294. package/src/ui/runtime/command-chrome.ts +147 -0
  295. package/src/ui/runtime/dev-prompt-queue.ts +84 -0
  296. package/src/ui/runtime/flow-session.ts +11 -0
  297. package/src/ui/runtime/run-clack-flow.tsx +52 -0
  298. package/src/ui/theme.ts +41 -0
  299. package/src/valkey-sidecar.ts +126 -0
  300. package/tests/admin-ensure.test.ts +59 -0
  301. package/tests/binary-cache-cloud-overrides.test.ts +2 -2
  302. package/tests/binary-download-lock.test.ts +41 -0
  303. package/tests/cli-help.test.ts +7 -4
  304. package/tests/cli-package-version.test.ts +15 -0
  305. package/tests/command-chrome-coverage.test.ts +149 -0
  306. package/tests/command-chrome-wrap.test.ts +51 -0
  307. package/tests/config.test.ts +8 -4
  308. package/tests/dev-ports.test.ts +41 -0
  309. package/tests/dev-ready-panel.test.ts +20 -0
  310. package/tests/dev-session-lock.test.ts +54 -0
  311. package/tests/dev-ui.test.ts +66 -3
  312. package/tests/docker-runtime.test.ts +9 -20
  313. package/tests/ensure-dev-api-config.test.ts +22 -0
  314. package/tests/init-dependency-versions.test.ts +62 -0
  315. package/tests/init-package-json.test.ts +18 -0
  316. package/tests/init.test.ts +30 -3
  317. package/tests/required-host-components.test.ts +51 -0
  318. package/tests/resolve-api-url.test.ts +23 -0
  319. package/tests/rest-cache-admin.test.ts +28 -0
  320. package/tests/runtime-contract.test.ts +12 -3
  321. package/tests/tsconfig.json +8 -2
  322. package/tests/ui-confirm.test.ts +13 -9
  323. package/tests/ui-messages.test.ts +4 -18
  324. package/tsconfig.json +1 -0
  325. package/tsconfig.tsbuildinfo +1 -1
  326. package/vitest.config.ts +3 -0
  327. package/dist/dev-tui.d.ts +0 -24
  328. package/dist/dev-tui.d.ts.map +0 -1
  329. package/dist/dev-tui.js +0 -188
  330. package/dist/dev-tui.js.map +0 -1
  331. package/src/dev-tui.ts +0 -232
@@ -1,27 +1,17 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
- import { resolve, join, dirname, basename } from "node:path";
3
- import { fileURLToPath } from "node:url";
2
+ import { resolve, join, basename } from "node:path";
4
3
  import { spawnSync } from "node:child_process";
5
- import * as p from "@clack/prompts";
4
+ import { p, runClackFlow } from "../ui/clack.js";
6
5
  import { ensureNotCancelled, printLogo } from "../ui/prompts.js";
7
6
  import { generateAndWriteKeys } from "./keys.js";
8
7
  import { file, error, info, plain, warn } from "../ui/messages.js";
9
8
  import { nextSteps } from "../ui/next-steps.js";
10
9
  import { probeDockerDaemon, reportDockerUnavailable } from "../docker-runtime.js";
11
- export { scaffold };
12
- // ─── Markers used by `supatype app add / remove` (app.ts) ────────────────────
13
- export const APP_COMPOSE_MARKER = " # ─── App service (run: supatype app add) ───";
14
- export const KONG_APP_MARKER = " # ─── App fallback route (run: supatype app add) ───";
15
- const CLI_PACKAGE_JSON = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "package.json");
16
- function cliPackageVersion() {
17
- try {
18
- const pkg = JSON.parse(readFileSync(CLI_PACKAGE_JSON, "utf8"));
19
- return pkg.version ?? "0.1.0";
20
- }
21
- catch {
22
- return "0.1.0";
23
- }
24
- }
10
+ import { loadConfig } from "../config.js";
11
+ import { ensureComponentBinaries, reportComponentBinaryFailures, } from "../ensure-component-binaries.js";
12
+ import { mergeSupatypePackageJson } from "../init-package-json.js";
13
+ import { cliPackageVersion } from "../cli-package-version.js";
14
+ import { initDependencyVersionsFallback, resolveInitDependencyVersions, } from "../init-dependency-versions.js";
25
15
  const STORAGE_PROVIDER_OPTIONS = [
26
16
  { value: "local", label: "Local", hint: "storage you host yourself (MinIO)" },
27
17
  { value: "s3", label: "S3", hint: "external bucket (AWS S3 or compatible)" },
@@ -63,6 +53,9 @@ export function registerInit(program) {
63
53
  .option("-y, --defaults", "Skip all prompts and use sensible defaults")
64
54
  .option("--no-install", "Do not run the package manager install step")
65
55
  .option("--no-keys", "Do not generate ANON_KEY / SERVICE_ROLE_KEY")
56
+ .option("--admin-email <email>", "First admin panel user email (written to .env)")
57
+ .option("--admin-password <password>", "First admin panel user password (written to .env)")
58
+ .option("--no-admin", "Do not configure a first admin user")
66
59
  .action(async (name, opts) => {
67
60
  const dir = name ? resolve(process.cwd(), name) : process.cwd();
68
61
  if (name && existsSync(dir)) {
@@ -84,132 +77,191 @@ export function registerInit(program) {
84
77
  install: true,
85
78
  generateKeys: true,
86
79
  };
80
+ if (result.provider === "docker") {
81
+ const { findNextFreePort } = await import("../dev-ports.js");
82
+ const { COMPOSE_DEV_KONG_PORT } = await import("../project-config.js");
83
+ result.kongPort = await findNextFreePort(COMPOSE_DEV_KONG_PORT);
84
+ }
85
+ if (!opts.admin && opts.adminEmail && opts.adminPassword) {
86
+ result.adminEmail = opts.adminEmail;
87
+ result.adminPassword = opts.adminPassword;
88
+ }
89
+ }
90
+ if (opts.admin === false) {
91
+ delete result.adminEmail;
92
+ delete result.adminPassword;
93
+ }
94
+ else if (opts.adminEmail && opts.adminPassword) {
95
+ result.adminEmail = opts.adminEmail;
96
+ result.adminPassword = opts.adminPassword;
87
97
  }
88
98
  // CLI flags override wizard / default action choices.
89
99
  const doInstall = opts.install !== false && result.install;
90
100
  const doKeys = opts.keys !== false && result.generateKeys;
91
101
  if (name)
92
102
  mkdirSync(dir, { recursive: true });
93
- scaffold(dir, result);
94
- if (doInstall)
95
- runInstall(dir, result.packageManager);
103
+ const deps = await resolveInitDependencyVersions();
104
+ const runningCli = cliPackageVersion();
105
+ if (deps.cli !== runningCli || deps.types !== runningCli) {
106
+ info(`Using published npm versions: @supatype/cli ^${deps.cli}, @supatype/types ^${deps.types}`);
107
+ }
108
+ scaffold(dir, result, deps);
109
+ const installOk = doInstall ? runInstall(dir, result.packageManager) : true;
110
+ const binariesReady = installOk ? await ensureInitBinaries(dir) : false;
111
+ if (doInstall && !installOk) {
112
+ warn("Skipping component binary check until dependencies install successfully.");
113
+ }
96
114
  const keysGenerated = doKeys ? writeKeys(dir) : false;
97
115
  warnDockerUnavailableForProvider(result.provider);
98
116
  printNextSteps({
99
117
  name,
100
118
  result,
101
- installed: doInstall,
119
+ installed: doInstall && installOk,
102
120
  keysGenerated,
121
+ binariesReady,
103
122
  });
104
123
  });
105
124
  }
106
125
  // ─── Wizard ──────────────────────────────────────────────────────────────────
107
126
  async function runWizard(defaultName, defaultTarget) {
108
- p.intro("Create a new Supatype project");
109
- const projectName = ensureNotCancelled(await p.text({
110
- message: "Project name",
111
- defaultValue: defaultName,
112
- placeholder: defaultName,
113
- })).trim() || defaultName;
114
- const packageManager = ensureNotCancelled(await p.select({
115
- message: "Package manager",
116
- initialValue: detectInvokingPackageManager(),
117
- options: [
118
- { value: "npm", label: "npm" },
119
- { value: "pnpm", label: "pnpm" },
120
- { value: "yarn", label: "yarn" },
121
- { value: "bun", label: "bun" },
122
- ],
123
- }));
124
- const productionTarget = ensureNotCancelled(await p.select({
125
- message: "Where will this run in production?",
126
- initialValue: defaultTarget,
127
- options: [
128
- { value: "cloud", label: "Supatype Cloud", hint: "managed; deploy via supatype link" },
129
- { value: "self-host", label: "Self-host", hint: "your own server with TLS" },
130
- { value: "later", label: "Decide later", hint: "local development only for now" },
131
- ],
132
- }));
133
- let domain;
134
- let tlsEmail;
135
- if (productionTarget === "self-host") {
136
- domain = ensureNotCancelled(await p.text({
137
- message: "Production domain for ACME TLS (optional, can set later)",
138
- placeholder: "api.example.com",
139
- defaultValue: "",
140
- })).trim();
141
- if (domain) {
142
- tlsEmail =
127
+ return runClackFlow(async () => {
128
+ p.intro("Create a new Supatype project");
129
+ const projectName = ensureNotCancelled(await p.text({
130
+ message: "Project name",
131
+ defaultValue: defaultName,
132
+ placeholder: defaultName,
133
+ })).trim() || defaultName;
134
+ const packageManager = ensureNotCancelled(await p.select({
135
+ message: "Package manager",
136
+ initialValue: detectInvokingPackageManager(),
137
+ options: [
138
+ { value: "npm", label: "npm" },
139
+ { value: "pnpm", label: "pnpm" },
140
+ { value: "yarn", label: "yarn" },
141
+ { value: "bun", label: "bun" },
142
+ ],
143
+ }));
144
+ const productionTarget = ensureNotCancelled(await p.select({
145
+ message: "Where will this run in production?",
146
+ initialValue: defaultTarget,
147
+ options: [
148
+ { value: "cloud", label: "Supatype Cloud", hint: "managed; deploy via supatype link" },
149
+ { value: "self-host", label: "Self-host", hint: "your own server with TLS" },
150
+ { value: "later", label: "Decide later", hint: "local development only for now" },
151
+ ],
152
+ }));
153
+ let domain;
154
+ let tlsEmail;
155
+ if (productionTarget === "self-host") {
156
+ domain = ensureNotCancelled(await p.text({
157
+ message: "Production domain for ACME TLS (optional, can set later)",
158
+ placeholder: "api.example.com",
159
+ defaultValue: "",
160
+ })).trim();
161
+ if (domain) {
162
+ tlsEmail =
163
+ ensureNotCancelled(await p.text({
164
+ message: "Email for Let's Encrypt (HTTPS) certificates",
165
+ placeholder: "you@example.com",
166
+ defaultValue: "",
167
+ })).trim() || undefined;
168
+ }
169
+ }
170
+ const provider = ensureNotCancelled(await p.select({
171
+ message: "How should Postgres and the server run for local development?",
172
+ initialValue: "docker",
173
+ options: [
174
+ { value: "docker", label: "Docker", hint: "Docker Compose stack (recommended)" },
175
+ { value: "native", label: "Native", hint: "host Postgres + server binaries, no Docker" },
176
+ ],
177
+ }));
178
+ let kongPort;
179
+ if (provider === "docker") {
180
+ const { promptKongPortChoice } = await import("../dev-ports.js");
181
+ kongPort = await promptKongPortChoice();
182
+ }
183
+ const schemaPath = ensureNotCancelled(await p.text({
184
+ message: "Where should your schema live?",
185
+ defaultValue: "schema/index.ts",
186
+ placeholder: "schema/index.ts",
187
+ })).trim() || "schema/index.ts";
188
+ const app = await promptApp();
189
+ const email = ensureNotCancelled(await p.select({
190
+ message: "Email provider",
191
+ initialValue: "console",
192
+ options: [
193
+ { value: "console", label: "console", hint: "log emails to the terminal (dev)" },
194
+ { value: "smtp", label: "SMTP" },
195
+ { value: "resend", label: "Resend" },
196
+ { value: "ses", label: "Amazon SES" },
197
+ ],
198
+ }));
199
+ const storageLocal = ensureNotCancelled(await p.select({
200
+ message: "Local storage (for development)?",
201
+ initialValue: "local",
202
+ options: STORAGE_PROVIDER_OPTIONS,
203
+ }));
204
+ const storageProduction = ensureNotCancelled(await p.select({
205
+ message: "Production storage?",
206
+ initialValue: "local",
207
+ options: STORAGE_PROVIDER_OPTIONS,
208
+ }));
209
+ const helloFunction = ensureNotCancelled(await p.confirm({
210
+ message: "Create a hello-world edge function?",
211
+ initialValue: false,
212
+ }));
213
+ const install = ensureNotCancelled(await p.confirm({
214
+ message: `Install dependencies with ${packageManager} now?`,
215
+ initialValue: true,
216
+ }));
217
+ const generateKeys = ensureNotCancelled(await p.confirm({
218
+ message: "Generate ANON_KEY and SERVICE_ROLE_KEY now?",
219
+ initialValue: true,
220
+ }));
221
+ let adminEmail;
222
+ let adminPassword;
223
+ const createAdmin = ensureNotCancelled(await p.confirm({
224
+ message: "Create an admin user for /admin?",
225
+ initialValue: true,
226
+ }));
227
+ if (createAdmin) {
228
+ adminEmail =
143
229
  ensureNotCancelled(await p.text({
144
- message: "Email for Let's Encrypt (HTTPS) certificates",
230
+ message: "Admin email",
145
231
  placeholder: "you@example.com",
146
232
  defaultValue: "",
147
233
  })).trim() || undefined;
234
+ if (adminEmail) {
235
+ adminPassword =
236
+ ensureNotCancelled(await p.text({
237
+ message: "Admin password (min 8 chars)",
238
+ defaultValue: "",
239
+ })).trim() || undefined;
240
+ if (adminPassword && adminPassword.length < 8) {
241
+ adminPassword = undefined;
242
+ }
243
+ }
148
244
  }
149
- }
150
- const provider = ensureNotCancelled(await p.select({
151
- message: "How should Postgres and the server run for local development?",
152
- initialValue: "docker",
153
- options: [
154
- { value: "docker", label: "Docker", hint: "Docker Compose stack (recommended)" },
155
- { value: "native", label: "Native", hint: "host Postgres + server binaries, no Docker" },
156
- ],
157
- }));
158
- const schemaPath = ensureNotCancelled(await p.text({
159
- message: "Where should your schema live?",
160
- defaultValue: "schema/index.ts",
161
- placeholder: "schema/index.ts",
162
- })).trim() || "schema/index.ts";
163
- const app = await promptApp();
164
- const email = ensureNotCancelled(await p.select({
165
- message: "Email provider",
166
- initialValue: "console",
167
- options: [
168
- { value: "console", label: "console", hint: "log emails to the terminal (dev)" },
169
- { value: "smtp", label: "SMTP" },
170
- { value: "resend", label: "Resend" },
171
- { value: "ses", label: "Amazon SES" },
172
- ],
173
- }));
174
- const storageLocal = ensureNotCancelled(await p.select({
175
- message: "Local storage (for development)?",
176
- initialValue: "local",
177
- options: STORAGE_PROVIDER_OPTIONS,
178
- }));
179
- const storageProduction = ensureNotCancelled(await p.select({
180
- message: "Production storage?",
181
- initialValue: "local",
182
- options: STORAGE_PROVIDER_OPTIONS,
183
- }));
184
- const helloFunction = ensureNotCancelled(await p.confirm({
185
- message: "Create a hello-world edge function?",
186
- initialValue: false,
187
- }));
188
- const install = ensureNotCancelled(await p.confirm({
189
- message: `Install dependencies with ${packageManager} now?`,
190
- initialValue: true,
191
- }));
192
- const generateKeys = ensureNotCancelled(await p.confirm({
193
- message: "Generate ANON_KEY and SERVICE_ROLE_KEY now?",
194
- initialValue: true,
195
- }));
196
- p.outro("Setting up your project...");
197
- return {
198
- projectName,
199
- provider,
200
- productionTarget,
201
- ...(domain !== undefined ? { domain } : {}),
202
- ...(tlsEmail !== undefined ? { tlsEmail } : {}),
203
- schemaPath,
204
- app,
205
- email,
206
- storageLocal,
207
- storageProduction,
208
- helloFunction,
209
- packageManager,
210
- install,
211
- generateKeys,
212
- };
245
+ p.outro("Setting up your project...");
246
+ return {
247
+ projectName,
248
+ provider,
249
+ ...(kongPort !== undefined ? { kongPort } : {}),
250
+ productionTarget,
251
+ ...(domain !== undefined ? { domain } : {}),
252
+ ...(tlsEmail !== undefined ? { tlsEmail } : {}),
253
+ schemaPath,
254
+ app,
255
+ email,
256
+ storageLocal,
257
+ storageProduction,
258
+ helloFunction,
259
+ packageManager,
260
+ install,
261
+ generateKeys,
262
+ ...(adminEmail && adminPassword ? { adminEmail, adminPassword } : {}),
263
+ };
264
+ });
213
265
  }
214
266
  async function promptApp() {
215
267
  const mode = ensureNotCancelled(await p.select({
@@ -279,6 +331,30 @@ function runInstall(dir, pm) {
279
331
  });
280
332
  if (res.status !== 0 || res.error) {
281
333
  warn(`Dependency install did not complete (run "${pm} install" manually).`);
334
+ return false;
335
+ }
336
+ return true;
337
+ }
338
+ async function ensureInitBinaries(dir) {
339
+ const previousCwd = process.cwd();
340
+ try {
341
+ process.chdir(dir);
342
+ const config = loadConfig(dir);
343
+ const result = await ensureComponentBinaries(config, dir);
344
+ if (!result.ok) {
345
+ reportComponentBinaryFailures(result.failures);
346
+ return false;
347
+ }
348
+ return true;
349
+ }
350
+ catch (err) {
351
+ const message = err instanceof Error ? err.message : String(err);
352
+ warn(`Could not verify component binaries: ${message}`);
353
+ warn("Run manually from your project directory: supatype update");
354
+ return false;
355
+ }
356
+ finally {
357
+ process.chdir(previousCwd);
282
358
  }
283
359
  }
284
360
  function writeKeys(dir) {
@@ -290,7 +366,7 @@ function writeKeys(dir) {
290
366
  return true;
291
367
  }
292
368
  // ─── Scaffold ──────────────────────────────────────────────────────────────--
293
- function scaffold(dir, optsOrName) {
369
+ export function scaffold(dir, optsOrName, deps = initDependencyVersionsFallback()) {
294
370
  const opts = typeof optsOrName === "string" ? defaultScaffoldOptions(optsOrName) : optsOrName;
295
371
  const write = (rel, content) => {
296
372
  const full = join(dir, rel);
@@ -300,10 +376,19 @@ function scaffold(dir, optsOrName) {
300
376
  };
301
377
  const pkgPath = join(dir, "package.json");
302
378
  if (!existsSync(pkgPath)) {
303
- write("package.json", packageJsonTemplate(opts, cliPackageVersion()));
379
+ write("package.json", packageJsonTemplate(opts, deps));
304
380
  }
305
381
  else {
306
- file("skipped", "package.json (already exists)");
382
+ try {
383
+ const existing = JSON.parse(readFileSync(pkgPath, "utf8"));
384
+ const merged = mergeSupatypePackageJson(existing, opts, deps);
385
+ writeFileSync(pkgPath, `${JSON.stringify(merged, null, 2)}\n`, "utf8");
386
+ file("updated", "package.json (added Supatype dependencies)");
387
+ }
388
+ catch {
389
+ warn("Could not merge into package.json — add @supatype/cli and @supatype/types manually.");
390
+ file("skipped", "package.json (invalid JSON)");
391
+ }
307
392
  }
308
393
  write("supatype.config.ts", tsConfigTemplate(opts));
309
394
  if (opts.productionTarget !== "later") {
@@ -340,8 +425,13 @@ function scaffoldAppAssets(opts, write) {
340
425
  const hasVite = Boolean(opts.app.viteDevUrl);
341
426
  if (opts.app.mode === "static") {
342
427
  const staticRel = staticDirRelative(opts.app.staticDir);
428
+ if (opts.app.viteDevUrl && opts.productionTarget !== "later") {
429
+ write("dist/index.html", holding);
430
+ scaffoldVite(opts, write, holding);
431
+ return;
432
+ }
343
433
  write(`${staticRel}/index.html`, holding);
344
- if (hasVite)
434
+ if (opts.app.viteDevUrl)
345
435
  scaffoldVite(opts, write, holding);
346
436
  return;
347
437
  }
@@ -373,7 +463,7 @@ function scaffoldHelloFunction(dir, write) {
373
463
  }
374
464
  }
375
465
  // ─── Templates ───────────────────────────────────────────────────────────────
376
- function packageJsonTemplate(opts, cliVersion) {
466
+ function packageJsonTemplate(opts, deps) {
377
467
  const scripts = [
378
468
  ` "dev": "supatype dev"`,
379
469
  ` "push": "supatype push"`,
@@ -397,8 +487,8 @@ function packageJsonTemplate(opts, cliVersion) {
397
487
  ${scripts.join(",\n")}
398
488
  },
399
489
  "dependencies": {
400
- "@supatype/cli": "^${cliVersion}",
401
- "@supatype/types": "^${cliVersion}"
490
+ "@supatype/cli": "^${deps.cli}",
491
+ "@supatype/types": "^${deps.types}"
402
492
  },
403
493
  "devDependencies": {
404
494
  ${devDeps.join(",\n")}
@@ -460,20 +550,47 @@ function localConfigTemplate(app) {
460
550
  `const localConfig: Partial<SupatypeConfig> = {`,
461
551
  ` server: { mode: "dev" },`,
462
552
  ];
463
- if (app.mode === "proxy") {
464
- lines.push(` app: {`);
465
- lines.push(` mode: "proxy",`);
466
- lines.push(` upstream: "${app.upstream ?? "http://localhost:3000"}",`);
467
- lines.push(` start: "${app.start ?? "dev"}",`);
468
- if (app.viteDevUrl)
469
- lines.push(` vite_dev_url: "${app.viteDevUrl}",`);
470
- lines.push(` },`);
553
+ const localApp = localDevAppConfigLines(app);
554
+ if (localApp.length > 0) {
555
+ lines.push(...localApp);
471
556
  }
472
557
  lines.push(`}`, ``, `export default localConfig`, ``);
473
558
  return lines.join("\n");
474
559
  }
560
+ /** App block for supatype.local.config.ts (proxy + Vite during local dev). */
561
+ function localDevAppConfigLines(app) {
562
+ if (app.mode === "proxy") {
563
+ return [
564
+ ` app: {`,
565
+ ` mode: "proxy",`,
566
+ ` upstream: "${app.upstream ?? "http://localhost:3000"}",`,
567
+ ` start: "${app.start ?? "dev"}",`,
568
+ ...(app.viteDevUrl ? [` vite_dev_url: "${app.viteDevUrl}",`] : []),
569
+ ` },`,
570
+ ];
571
+ }
572
+ if (app.viteDevUrl) {
573
+ return [
574
+ ` app: {`,
575
+ ` mode: "proxy",`,
576
+ ` upstream: "${app.viteDevUrl}",`,
577
+ ` start: "vite",`,
578
+ ` vite_dev_url: "${app.viteDevUrl}",`,
579
+ ` },`,
580
+ ];
581
+ }
582
+ return [];
583
+ }
475
584
  function appConfigLines(app, productionTarget) {
476
585
  if (app.mode === "static") {
586
+ if (productionTarget !== "later" && app.viteDevUrl) {
587
+ return [
588
+ ` app: {`,
589
+ ` mode: "static",`,
590
+ ` static_dir: "./dist", // production build output`,
591
+ ` },`,
592
+ ];
593
+ }
477
594
  const out = [
478
595
  ` app: {`,
479
596
  ` mode: "static",`,
@@ -532,7 +649,7 @@ function holdingPageTemplate(projectName) {
532
649
  <meta charset="UTF-8" />
533
650
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
534
651
  <title>${name} — Supatype</title>
535
- <meta name="description" content="A Supatype project. Define your types — we generate your backend." />
652
+ <meta name="description" content="A Supatype project. Define your types — we generate your platform." />
536
653
  <link rel="preconnect" href="https://fonts.googleapis.com" />
537
654
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
538
655
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
@@ -667,6 +784,8 @@ export default defineConfig({
667
784
  host: "127.0.0.1",
668
785
  port: ${port},
669
786
  strictPort: true,
787
+ // Docker Compose app proxy reaches the host as host.docker.internal.
788
+ allowedHosts: ["127.0.0.1", "localhost", "host.docker.internal"],
670
789
  },
671
790
  })
672
791
  `;
@@ -728,8 +847,20 @@ ANON_KEY=
728
847
  SERVICE_ROLE_KEY=`);
729
848
  sections.push(`# Site URL (used by GoTrue for email redirects)
730
849
  SITE_URL=http://localhost:3000`);
850
+ if (opts.provider === "docker" && opts.kongPort !== undefined) {
851
+ const apiUrl = `http://localhost:${opts.kongPort}`;
852
+ sections.push(`# Local API gateway (Kong) — unique per project so multiple stacks can run concurrently
853
+ SUPATYPE_KONG_PORT=${opts.kongPort}
854
+ PUBLIC_SUPATYPE_URL=${apiUrl}
855
+ API_EXTERNAL_URL=${apiUrl}`);
856
+ }
731
857
  sections.push(emailEnvSection(opts.email, opts.projectName));
732
858
  sections.push(storageEnvSections(opts.storageLocal, opts.storageProduction));
859
+ if (opts.adminEmail && opts.adminPassword) {
860
+ sections.push(`# First admin for /admin — consumed on first supatype dev or push (password removed after use)
861
+ SUPATYPE_ADMIN_EMAIL=${opts.adminEmail}
862
+ SUPATYPE_ADMIN_PASSWORD=${opts.adminPassword}`);
863
+ }
733
864
  sections.push(`# Self-host compose uses the same DATABASE_URL when Postgres is published on localhost:5432`);
734
865
  return sections.join("\n\n") + "\n";
735
866
  }
@@ -893,16 +1024,24 @@ function warnDockerUnavailableForProvider(provider) {
893
1024
  plain();
894
1025
  }
895
1026
  function printNextSteps(args) {
896
- const { name, result, installed, keysGenerated } = args;
1027
+ const { name, result, installed, keysGenerated, binariesReady } = args;
897
1028
  const steps = [];
898
1029
  if (name)
899
1030
  steps.push(`cd ${name}`);
900
1031
  if (!installed)
901
1032
  steps.push(`${result.packageManager} install`);
1033
+ if (!binariesReady)
1034
+ steps.push("supatype update # download component binaries");
902
1035
  if (!keysGenerated)
903
1036
  steps.push("supatype keys");
904
- steps.push("supatype dev # Docker Compose stack (Kong :18473)");
1037
+ const kongHint = result.provider === "docker" && result.kongPort !== undefined
1038
+ ? `supatype dev # Docker Compose stack (Kong :${result.kongPort})`
1039
+ : "supatype dev # Docker Compose stack (Kong :18473)";
1040
+ steps.push(kongHint);
905
1041
  steps.push("supatype push # apply schema + generate types");
1042
+ if (result.adminEmail) {
1043
+ steps.push(" # first admin user is created on dev or push");
1044
+ }
906
1045
  if (result.helloFunction) {
907
1046
  steps.push("supatype functions serve # run edge functions locally");
908
1047
  }