@supatype/cli 0.1.1 → 0.1.3
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.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +126 -99
- package/.turbo/turbo-typecheck.log +2 -2
- package/dist/binary-cache.d.ts +2 -0
- package/dist/binary-cache.d.ts.map +1 -1
- package/dist/binary-cache.js +36 -0
- package/dist/binary-cache.js.map +1 -1
- package/dist/binary-download-lock.d.ts +12 -0
- package/dist/binary-download-lock.d.ts.map +1 -0
- package/dist/binary-download-lock.js +106 -0
- package/dist/binary-download-lock.js.map +1 -0
- package/dist/cli-package-version.d.ts +3 -0
- package/dist/cli-package-version.d.ts.map +1 -0
- package/dist/cli-package-version.js +15 -0
- package/dist/cli-package-version.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +5 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/add.js +25 -19
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/admin.d.ts +12 -0
- package/dist/commands/admin.d.ts.map +1 -1
- package/dist/commands/admin.js +116 -26
- package/dist/commands/admin.js.map +1 -1
- package/dist/commands/cache.d.ts +1 -1
- package/dist/commands/cache.d.ts.map +1 -1
- package/dist/commands/cache.js +98 -5
- package/dist/commands/cache.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +26 -22
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.d.ts +3 -4
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +296 -121
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/link-helpers.d.ts.map +1 -1
- package/dist/commands/link-helpers.js +26 -25
- package/dist/commands/link-helpers.js.map +1 -1
- package/dist/compose-local-server-image.d.ts +13 -0
- package/dist/compose-local-server-image.d.ts.map +1 -0
- package/dist/compose-local-server-image.js +57 -0
- package/dist/compose-local-server-image.js.map +1 -0
- package/dist/compose-rename.d.ts.map +1 -1
- package/dist/compose-rename.js +5 -8
- package/dist/compose-rename.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -1
- package/dist/config.js.map +1 -1
- package/dist/dev-compose.d.ts.map +1 -1
- package/dist/dev-compose.js +113 -56
- package/dist/dev-compose.js.map +1 -1
- package/dist/dev-log-bus.d.ts +5 -0
- package/dist/dev-log-bus.d.ts.map +1 -1
- package/dist/dev-log-bus.js +16 -0
- package/dist/dev-log-bus.js.map +1 -1
- package/dist/dev-log-filter.d.ts +4 -0
- package/dist/dev-log-filter.d.ts.map +1 -1
- package/dist/dev-log-filter.js +52 -0
- package/dist/dev-log-filter.js.map +1 -1
- package/dist/dev-ports.d.ts.map +1 -1
- package/dist/dev-ports.js +19 -12
- package/dist/dev-ports.js.map +1 -1
- package/dist/dev-ready-panel.d.ts +21 -0
- package/dist/dev-ready-panel.d.ts.map +1 -0
- package/dist/dev-ready-panel.js +67 -0
- package/dist/dev-ready-panel.js.map +1 -0
- package/dist/dev-session-lock.d.ts.map +1 -1
- package/dist/dev-session-lock.js +5 -8
- package/dist/dev-session-lock.js.map +1 -1
- package/dist/dev-session.d.ts +18 -5
- package/dist/dev-session.d.ts.map +1 -1
- package/dist/dev-session.js +91 -18
- package/dist/dev-session.js.map +1 -1
- package/dist/dev-shutdown.d.ts +2 -0
- package/dist/dev-shutdown.d.ts.map +1 -1
- package/dist/dev-shutdown.js +29 -15
- package/dist/dev-shutdown.js.map +1 -1
- package/dist/dev-task-colors.d.ts +3 -1
- package/dist/dev-task-colors.d.ts.map +1 -1
- package/dist/dev-task-colors.js +23 -3
- package/dist/dev-task-colors.js.map +1 -1
- package/dist/docker-runtime.js +1 -1
- package/dist/docker-runtime.js.map +1 -1
- package/dist/engine-push-output.d.ts +1 -0
- package/dist/engine-push-output.d.ts.map +1 -1
- package/dist/engine-push-output.js +4 -1
- package/dist/engine-push-output.js.map +1 -1
- package/dist/ensure-binary.d.ts.map +1 -1
- package/dist/ensure-binary.js +14 -2
- package/dist/ensure-binary.js.map +1 -1
- package/dist/ensure-component-binaries.d.ts +17 -0
- package/dist/ensure-component-binaries.d.ts.map +1 -0
- package/dist/ensure-component-binaries.js +45 -0
- package/dist/ensure-component-binaries.js.map +1 -0
- package/dist/ensure-dev-api-config.d.ts +3 -0
- package/dist/ensure-dev-api-config.d.ts.map +1 -0
- package/dist/ensure-dev-api-config.js +17 -0
- package/dist/ensure-dev-api-config.js.map +1 -0
- package/dist/init-dependency-versions.d.ts +13 -0
- package/dist/init-dependency-versions.d.ts.map +1 -0
- package/dist/init-dependency-versions.js +53 -0
- package/dist/init-dependency-versions.js.map +1 -0
- package/dist/init-package-json.d.ts +21 -0
- package/dist/init-package-json.d.ts.map +1 -0
- package/dist/init-package-json.js +46 -0
- package/dist/init-package-json.js.map +1 -0
- package/dist/init-project-detect.d.ts +14 -0
- package/dist/init-project-detect.d.ts.map +1 -0
- package/dist/init-project-detect.js +89 -0
- package/dist/init-project-detect.js.map +1 -0
- package/dist/postgres-ctl.d.ts.map +1 -1
- package/dist/postgres-ctl.js +2 -1
- package/dist/postgres-ctl.js.map +1 -1
- package/dist/required-host-components.d.ts +11 -0
- package/dist/required-host-components.d.ts.map +1 -0
- package/dist/required-host-components.js +25 -0
- package/dist/required-host-components.js.map +1 -0
- package/dist/resolve-api-url.d.ts +6 -0
- package/dist/resolve-api-url.d.ts.map +1 -0
- package/dist/resolve-api-url.js +39 -0
- package/dist/resolve-api-url.js.map +1 -0
- package/dist/rest-cache-admin.d.ts +33 -0
- package/dist/rest-cache-admin.d.ts.map +1 -0
- package/dist/rest-cache-admin.js +96 -0
- package/dist/rest-cache-admin.js.map +1 -0
- package/dist/scripts/postinstall.d.ts +4 -6
- package/dist/scripts/postinstall.d.ts.map +1 -1
- package/dist/scripts/postinstall.js +8 -41
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/self-host-compose.d.ts.map +1 -1
- package/dist/self-host-compose.js +23 -13
- package/dist/self-host-compose.js.map +1 -1
- package/dist/studio-dev-server.d.ts +4 -2
- package/dist/studio-dev-server.d.ts.map +1 -1
- package/dist/studio-dev-server.js +3 -2
- package/dist/studio-dev-server.js.map +1 -1
- package/dist/ui/brand.d.ts +2 -5
- package/dist/ui/brand.d.ts.map +1 -1
- package/dist/ui/brand.js +2 -7
- package/dist/ui/brand.js.map +1 -1
- package/dist/ui/clack-api.d.ts +44 -0
- package/dist/ui/clack-api.d.ts.map +1 -0
- package/dist/ui/clack-api.js +76 -0
- package/dist/ui/clack-api.js.map +1 -0
- package/dist/ui/clack.d.ts +14 -0
- package/dist/ui/clack.d.ts.map +1 -0
- package/dist/ui/clack.js +147 -0
- package/dist/ui/clack.js.map +1 -0
- package/dist/ui/components/FlowSpinner.d.ts +5 -0
- package/dist/ui/components/FlowSpinner.d.ts.map +1 -0
- package/dist/ui/components/FlowSpinner.js +8 -0
- package/dist/ui/components/FlowSpinner.js.map +1 -0
- package/dist/ui/components/LogoWordmark.d.ts +9 -0
- package/dist/ui/components/LogoWordmark.d.ts.map +1 -0
- package/dist/ui/components/LogoWordmark.js +17 -0
- package/dist/ui/components/LogoWordmark.js.map +1 -0
- package/dist/ui/components/PromptPanel.d.ts +5 -0
- package/dist/ui/components/PromptPanel.d.ts.map +1 -0
- package/dist/ui/components/PromptPanel.js +7 -0
- package/dist/ui/components/PromptPanel.js.map +1 -0
- package/dist/ui/components/SelectField.d.ts +11 -0
- package/dist/ui/components/SelectField.d.ts.map +1 -0
- package/dist/ui/components/SelectField.js +19 -0
- package/dist/ui/components/SelectField.js.map +1 -0
- package/dist/ui/confirm.d.ts +2 -1
- package/dist/ui/confirm.d.ts.map +1 -1
- package/dist/ui/confirm.js +4 -4
- package/dist/ui/confirm.js.map +1 -1
- package/dist/ui/dev/DevDashboard.d.ts +8 -0
- package/dist/ui/dev/DevDashboard.d.ts.map +1 -0
- package/dist/ui/dev/DevDashboard.js +158 -0
- package/dist/ui/dev/DevDashboard.js.map +1 -0
- package/dist/ui/dev/DevReadyPanelView.d.ts +8 -0
- package/dist/ui/dev/DevReadyPanelView.d.ts.map +1 -0
- package/dist/ui/dev/DevReadyPanelView.js +48 -0
- package/dist/ui/dev/DevReadyPanelView.js.map +1 -0
- package/dist/ui/fatal.d.ts.map +1 -1
- package/dist/ui/fatal.js +5 -11
- package/dist/ui/fatal.js.map +1 -1
- package/dist/ui/flows/FlowApp.d.ts +8 -0
- package/dist/ui/flows/FlowApp.d.ts.map +1 -0
- package/dist/ui/flows/FlowApp.js +44 -0
- package/dist/ui/flows/FlowApp.js.map +1 -0
- package/dist/ui/flows/prompt-fields.d.ts +48 -0
- package/dist/ui/flows/prompt-fields.d.ts.map +1 -0
- package/dist/ui/flows/prompt-fields.js +92 -0
- package/dist/ui/flows/prompt-fields.js.map +1 -0
- package/dist/ui/flows/types.d.ts +41 -0
- package/dist/ui/flows/types.d.ts.map +1 -0
- package/dist/ui/flows/types.js +2 -0
- package/dist/ui/flows/types.js.map +1 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -1
- package/dist/ui/messages.d.ts +1 -0
- package/dist/ui/messages.d.ts.map +1 -1
- package/dist/ui/messages.js +48 -8
- package/dist/ui/messages.js.map +1 -1
- package/dist/ui/progress.d.ts +5 -1
- package/dist/ui/progress.d.ts.map +1 -1
- package/dist/ui/progress.js +12 -3
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/prompts.d.ts +7 -5
- package/dist/ui/prompts.d.ts.map +1 -1
- package/dist/ui/prompts.js +15 -8
- package/dist/ui/prompts.js.map +1 -1
- package/dist/ui/runtime/cancel.d.ts +4 -0
- package/dist/ui/runtime/cancel.d.ts.map +1 -0
- package/dist/ui/runtime/cancel.js +6 -0
- package/dist/ui/runtime/cancel.js.map +1 -0
- package/dist/ui/runtime/command-chrome.d.ts +17 -0
- package/dist/ui/runtime/command-chrome.d.ts.map +1 -0
- package/dist/ui/runtime/command-chrome.js +123 -0
- package/dist/ui/runtime/command-chrome.js.map +1 -0
- package/dist/ui/runtime/dev-prompt-queue.d.ts +30 -0
- package/dist/ui/runtime/dev-prompt-queue.d.ts.map +1 -0
- package/dist/ui/runtime/dev-prompt-queue.js +57 -0
- package/dist/ui/runtime/dev-prompt-queue.js.map +1 -0
- package/dist/ui/runtime/flow-session.d.ts +4 -0
- package/dist/ui/runtime/flow-session.d.ts.map +1 -0
- package/dist/ui/runtime/flow-session.js +8 -0
- package/dist/ui/runtime/flow-session.js.map +1 -0
- package/dist/ui/runtime/run-clack-flow.d.ts +5 -0
- package/dist/ui/runtime/run-clack-flow.d.ts.map +1 -0
- package/dist/ui/runtime/run-clack-flow.js +46 -0
- package/dist/ui/runtime/run-clack-flow.js.map +1 -0
- package/dist/ui/runtime/stdin-after-ink.d.ts +3 -0
- package/dist/ui/runtime/stdin-after-ink.d.ts.map +1 -0
- package/dist/ui/runtime/stdin-after-ink.js +16 -0
- package/dist/ui/runtime/stdin-after-ink.js.map +1 -0
- package/dist/ui/theme.d.ts +24 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +34 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/valkey-sidecar.d.ts +17 -0
- package/dist/valkey-sidecar.d.ts.map +1 -0
- package/dist/valkey-sidecar.js +94 -0
- package/dist/valkey-sidecar.js.map +1 -0
- package/package.json +9 -3
- package/src/binary-cache.ts +61 -0
- package/src/binary-download-lock.ts +124 -0
- package/src/cli-package-version.ts +15 -0
- package/src/cli.ts +6 -2
- package/src/commands/add.ts +26 -19
- package/src/commands/admin.ts +156 -29
- package/src/commands/cache.ts +105 -5
- package/src/commands/dev.ts +26 -21
- package/src/commands/init.ts +473 -247
- package/src/commands/link-helpers.ts +30 -29
- package/src/compose-local-server-image.ts +68 -0
- package/src/compose-rename.ts +5 -8
- package/src/config.ts +13 -1
- package/src/dev-compose.ts +139 -54
- package/src/dev-log-bus.ts +20 -0
- package/src/dev-log-filter.ts +42 -0
- package/src/dev-ports.ts +22 -11
- package/src/dev-ready-panel.ts +80 -0
- package/src/dev-session-lock.ts +5 -8
- package/src/dev-session.ts +98 -18
- package/src/dev-shutdown.ts +29 -17
- package/src/dev-task-colors.ts +22 -3
- package/src/docker-runtime.ts +1 -1
- package/src/engine-push-output.ts +5 -1
- package/src/ensure-binary.ts +21 -1
- package/src/ensure-component-binaries.ts +71 -0
- package/src/ensure-dev-api-config.ts +18 -0
- package/src/init-dependency-versions.ts +69 -0
- package/src/init-package-json.ts +63 -0
- package/src/init-project-detect.ts +99 -0
- package/src/postgres-ctl.ts +2 -1
- package/src/required-host-components.ts +37 -0
- package/src/resolve-api-url.ts +43 -0
- package/src/rest-cache-admin.ts +135 -0
- package/src/scripts/postinstall.ts +9 -46
- package/src/self-host-compose.ts +22 -12
- package/src/studio-dev-server.ts +5 -4
- package/src/ui/README.md +13 -9
- package/src/ui/brand.ts +2 -8
- package/src/ui/clack-api.ts +123 -0
- package/src/ui/clack.ts +153 -0
- package/src/ui/components/FlowSpinner.tsx +15 -0
- package/src/ui/components/LogoWordmark.tsx +36 -0
- package/src/ui/components/PromptPanel.tsx +17 -0
- package/src/ui/components/SelectField.tsx +58 -0
- package/src/ui/confirm.ts +5 -4
- package/src/ui/dev/DevDashboard.tsx +223 -0
- package/src/ui/dev/DevReadyPanelView.tsx +134 -0
- package/src/ui/fatal.ts +5 -10
- package/src/ui/flows/FlowApp.tsx +69 -0
- package/src/ui/flows/prompt-fields.tsx +198 -0
- package/src/ui/flows/types.ts +50 -0
- package/src/ui/index.ts +1 -1
- package/src/ui/messages.ts +50 -8
- package/src/ui/progress.ts +14 -3
- package/src/ui/prompts.ts +17 -9
- package/src/ui/runtime/cancel.ts +6 -0
- package/src/ui/runtime/command-chrome.ts +147 -0
- package/src/ui/runtime/dev-prompt-queue.ts +84 -0
- package/src/ui/runtime/flow-session.ts +11 -0
- package/src/ui/runtime/run-clack-flow.tsx +65 -0
- package/src/ui/runtime/stdin-after-ink.ts +18 -0
- package/src/ui/theme.ts +41 -0
- package/src/valkey-sidecar.ts +126 -0
- package/tests/admin-ensure.test.ts +80 -0
- package/tests/binary-cache-cloud-overrides.test.ts +2 -2
- package/tests/binary-download-lock.test.ts +41 -0
- package/tests/cli-help.test.ts +7 -4
- package/tests/cli-package-version.test.ts +15 -0
- package/tests/command-chrome-coverage.test.ts +149 -0
- package/tests/command-chrome-wrap.test.ts +51 -0
- package/tests/config.test.ts +27 -4
- package/tests/dev-ready-panel.test.ts +37 -0
- package/tests/dev-ui.test.ts +42 -2
- package/tests/docker-runtime.test.ts +9 -20
- package/tests/ensure-dev-api-config.test.ts +22 -0
- package/tests/init-dependency-versions.test.ts +62 -0
- package/tests/init-package-json.test.ts +18 -0
- package/tests/init-project-detect.test.ts +53 -0
- package/tests/init.test.ts +30 -3
- package/tests/required-host-components.test.ts +51 -0
- package/tests/resolve-api-url.test.ts +23 -0
- package/tests/rest-cache-admin.test.ts +28 -0
- package/tests/runtime-contract.test.ts +12 -3
- package/tests/stdin-after-ink.test.ts +8 -0
- package/tests/tsconfig.json +8 -2
- package/tests/ui-confirm.test.ts +13 -9
- package/tests/ui-messages.test.ts +4 -18
- package/tsconfig.json +1 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +3 -0
- package/dist/dev-tui.d.ts +0 -24
- package/dist/dev-tui.d.ts.map +0 -1
- package/dist/dev-tui.js +0 -188
- package/dist/dev-tui.js.map +0 -1
- package/src/dev-tui.ts +0 -232
package/src/dev-ports.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* availability so multiple projects and port collisions are surfaced clearly.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import { CLACK_CANCEL, isCancel, p } from "./ui/clack.js"
|
|
8
8
|
import { COMPOSE_DEV_KONG_PORT } from "./project-config.js"
|
|
9
9
|
import { isPortInUse } from "./postgres-ctl.js"
|
|
10
10
|
import { readEnvInt, upsertEnvFile } from "./env-file.js"
|
|
@@ -119,7 +119,7 @@ export async function promptKongPortChoice(): Promise<number> {
|
|
|
119
119
|
},
|
|
120
120
|
})
|
|
121
121
|
|
|
122
|
-
if (
|
|
122
|
+
if (isCancel(value)) {
|
|
123
123
|
p.cancel("Cancelled.")
|
|
124
124
|
process.exit(0)
|
|
125
125
|
}
|
|
@@ -154,7 +154,7 @@ async function promptPortConflictWithoutPersist(
|
|
|
154
154
|
],
|
|
155
155
|
})
|
|
156
156
|
|
|
157
|
-
if (
|
|
157
|
+
if (isCancel(choice) || choice === "cancel") {
|
|
158
158
|
p.cancel("Cancelled.")
|
|
159
159
|
process.exit(0)
|
|
160
160
|
}
|
|
@@ -171,7 +171,7 @@ async function promptPortConflictWithoutPersist(
|
|
|
171
171
|
},
|
|
172
172
|
})
|
|
173
173
|
|
|
174
|
-
if (
|
|
174
|
+
if (isCancel(custom)) {
|
|
175
175
|
p.cancel("Cancelled.")
|
|
176
176
|
process.exit(0)
|
|
177
177
|
}
|
|
@@ -194,19 +194,30 @@ async function promptPortConflictWithoutPersist(
|
|
|
194
194
|
|
|
195
195
|
const COMPOSE_DEV_DB_PORT = 54329
|
|
196
196
|
|
|
197
|
+
function devDbConnectionUrl(port: number): string {
|
|
198
|
+
return `postgresql://supatype_admin:postgres@localhost:${port}/supatype?sslmode=disable`
|
|
199
|
+
}
|
|
200
|
+
|
|
197
201
|
export async function ensureDevDbPort(cwd: string): Promise<number> {
|
|
198
202
|
const persisted = readEnvInt(cwd, "SUPATYPE_DEV_DB_PORT")
|
|
203
|
+
|
|
204
|
+
const persist = (port: number): number => {
|
|
205
|
+
upsertEnvFile(cwd, {
|
|
206
|
+
SUPATYPE_DEV_DB_PORT: String(port),
|
|
207
|
+
DATABASE_URL: devDbConnectionUrl(port),
|
|
208
|
+
})
|
|
209
|
+
return port
|
|
210
|
+
}
|
|
211
|
+
|
|
199
212
|
if (persisted !== null) {
|
|
200
213
|
if (!(await isPortInUse(persisted))) return persisted
|
|
201
214
|
const next = await findNextFreePort(persisted + 1)
|
|
202
|
-
|
|
203
|
-
SUPATYPE_DEV_DB_PORT: String(next),
|
|
204
|
-
DATABASE_URL: `postgresql://supatype_admin:postgres@localhost:${next}/supatype?sslmode=disable`,
|
|
205
|
-
})
|
|
206
|
-
return next
|
|
215
|
+
return persist(next)
|
|
207
216
|
}
|
|
208
217
|
|
|
209
218
|
let port = COMPOSE_DEV_DB_PORT
|
|
210
|
-
|
|
211
|
-
|
|
219
|
+
if (await isPortInUse(port)) {
|
|
220
|
+
port = await findNextFreePort(port + 1)
|
|
221
|
+
}
|
|
222
|
+
return persist(port)
|
|
212
223
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pinned service URLs + dev keys for the Ink dashboard.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { appendStackOutput, getActiveDevSession } from "./dev-session.js"
|
|
6
|
+
|
|
7
|
+
export interface DevServiceLink {
|
|
8
|
+
label: string
|
|
9
|
+
url: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface DevReadyPanel {
|
|
13
|
+
title: string
|
|
14
|
+
links: DevServiceLink[]
|
|
15
|
+
anonKey?: string
|
|
16
|
+
serviceRoleKey?: string
|
|
17
|
+
hints?: string[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Ink row budget for DevReadyPanelView (border, title, links, hints, keys, margin). */
|
|
21
|
+
export function devReadyPanelRowCount(panel: DevReadyPanel): number {
|
|
22
|
+
let rows = 2 // round border top + bottom
|
|
23
|
+
rows += 1 // title
|
|
24
|
+
rows += panel.links.length
|
|
25
|
+
for (const hint of panel.hints ?? []) {
|
|
26
|
+
if (hint.trim()) rows += 1
|
|
27
|
+
}
|
|
28
|
+
if (panel.anonKey) {
|
|
29
|
+
rows += 1 // "API keys (local dev)"
|
|
30
|
+
rows += 1 // anon
|
|
31
|
+
if (panel.serviceRoleKey) rows += 1 // service_role
|
|
32
|
+
}
|
|
33
|
+
rows += 1 // marginBottom on panel box
|
|
34
|
+
return rows
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Shorter panel when the terminal is too small for every service row. */
|
|
38
|
+
export function devReadyPanelCompactRowCount(panel: DevReadyPanel): number {
|
|
39
|
+
let rows = 2 // border
|
|
40
|
+
rows += 1 // title
|
|
41
|
+
rows += 2 // gateway + studio summary
|
|
42
|
+
for (const hint of panel.hints ?? []) {
|
|
43
|
+
if (hint.trim()) rows += 1
|
|
44
|
+
}
|
|
45
|
+
if (panel.anonKey) {
|
|
46
|
+
rows += 1
|
|
47
|
+
rows += 1
|
|
48
|
+
if (panel.serviceRoleKey) rows += 1
|
|
49
|
+
}
|
|
50
|
+
rows += 1 // marginBottom
|
|
51
|
+
return rows
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function formatStreamBlock(panel: DevReadyPanel): string {
|
|
55
|
+
const lines = [`[supatype] ${panel.title}`]
|
|
56
|
+
for (const link of panel.links) {
|
|
57
|
+
lines.push(` ${link.label.padEnd(16)} ${link.url}`)
|
|
58
|
+
}
|
|
59
|
+
for (const hint of panel.hints ?? []) {
|
|
60
|
+
lines.push(` ${hint}`)
|
|
61
|
+
}
|
|
62
|
+
if (panel.anonKey) {
|
|
63
|
+
lines.push(" API keys (local dev only):")
|
|
64
|
+
lines.push(` anon key ${panel.anonKey}`)
|
|
65
|
+
lines.push(` service_role ${panel.serviceRoleKey ?? ""}`)
|
|
66
|
+
}
|
|
67
|
+
lines.push(" Press Ctrl+C to stop.")
|
|
68
|
+
return lines.join("\n")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Pin links in the TUI or print the classic block in stream mode. */
|
|
72
|
+
export function publishDevReady(panel: DevReadyPanel): void {
|
|
73
|
+
const session = getActiveDevSession()
|
|
74
|
+
if (session?.isTui()) {
|
|
75
|
+
session.bus.setReadyPanel(panel)
|
|
76
|
+
appendStackOutput("Services running.", "log")
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
console.log(formatStreamBlock(panel))
|
|
80
|
+
}
|
package/src/dev-session-lock.ts
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs"
|
|
7
7
|
import { join, resolve } from "node:path"
|
|
8
8
|
import { spawnSync } from "node:child_process"
|
|
9
|
-
import * as p from "@clack/prompts"
|
|
10
9
|
import { runDockerCompose } from "./self-host-compose.js"
|
|
10
|
+
import { confirm as uiConfirm } from "./ui/confirm.js"
|
|
11
|
+
import { success, warn } from "./ui/messages.js"
|
|
11
12
|
import { isInteractive } from "./ui/interactive.js"
|
|
12
|
-
import { warn } from "./ui/messages.js"
|
|
13
13
|
|
|
14
14
|
const LOCK_VERSION = 1 as const
|
|
15
15
|
|
|
@@ -81,12 +81,9 @@ export async function recoverStaleDevSession(cwd: string): Promise<void> {
|
|
|
81
81
|
return
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
const stop = await
|
|
85
|
-
message: `${message}\n\nStop the orphaned stack before starting?`,
|
|
86
|
-
initialValue: true,
|
|
87
|
-
})
|
|
84
|
+
const stop = await uiConfirm(`${message}\n\nStop the orphaned stack before starting?`, { default: true })
|
|
88
85
|
|
|
89
|
-
if (
|
|
86
|
+
if (!stop) {
|
|
90
87
|
warn(`Leaving "${lock.composeProject}" running.`)
|
|
91
88
|
return
|
|
92
89
|
}
|
|
@@ -94,7 +91,7 @@ export async function recoverStaleDevSession(cwd: string): Promise<void> {
|
|
|
94
91
|
const status = runDockerCompose(lock.composePath, ["down"], cwd, lock.composeProject, { quiet: true })
|
|
95
92
|
if (status === 0) {
|
|
96
93
|
clearDevSessionLock(cwd)
|
|
97
|
-
|
|
94
|
+
success(`Stopped orphaned stack "${lock.composeProject}".`)
|
|
98
95
|
} else {
|
|
99
96
|
warn(`Could not stop "${lock.composeProject}" (exit ${status}).`)
|
|
100
97
|
}
|
package/src/dev-session.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `supatype dev` output session —
|
|
2
|
+
* `supatype dev` output session — Ink dashboard (default) or interleaved stream mode.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { render, type Instance } from "ink"
|
|
6
|
+
import React from "react"
|
|
5
7
|
import type { ProcessOptions } from "./process-manager.js"
|
|
6
|
-
import { filterDevSubprocessLine, formatConsoleArgs } from "./dev-log-filter.js"
|
|
8
|
+
import { filterDevSubprocessLine, filterStackLogLine, formatConsoleArgs } from "./dev-log-filter.js"
|
|
7
9
|
import { DevLogBus, type DevLogLevel } from "./dev-log-bus.js"
|
|
8
|
-
import {
|
|
10
|
+
import { DevDashboard } from "./ui/dev/DevDashboard.js"
|
|
11
|
+
import { ensureDevShutdownHooks } from "./dev-shutdown.js"
|
|
12
|
+
import { clearDevPromptQueue } from "./ui/runtime/dev-prompt-queue.js"
|
|
9
13
|
|
|
10
14
|
export type DevUiMode = "tui" | "stream"
|
|
11
15
|
|
|
@@ -18,26 +22,74 @@ export function resolveDevUiMode(streamFlag: boolean): DevUiMode {
|
|
|
18
22
|
let activeSession: DevSession | null = null
|
|
19
23
|
|
|
20
24
|
export function beginDevSession(mode: DevUiMode): DevSession {
|
|
25
|
+
ensureDevShutdownHooks()
|
|
21
26
|
activeSession?.stop()
|
|
22
27
|
activeSession = new DevSession(mode)
|
|
28
|
+
if (activeSession.isTui()) {
|
|
29
|
+
activeSession.enableConsoleCapture(false)
|
|
30
|
+
activeSession.startInk()
|
|
31
|
+
}
|
|
23
32
|
return activeSession
|
|
24
33
|
}
|
|
25
34
|
|
|
26
|
-
/**
|
|
35
|
+
/** @deprecated Ink starts in beginDevSession — kept for callers that invoke late. */
|
|
27
36
|
export function startDevSession(): void {
|
|
28
|
-
activeSession?.
|
|
37
|
+
activeSession?.startInk()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isDevTuiActive(): boolean {
|
|
41
|
+
return activeSession?.isInkMounted() ?? false
|
|
29
42
|
}
|
|
30
43
|
|
|
31
44
|
export function endDevSession(): void {
|
|
45
|
+
clearDevPromptQueue()
|
|
32
46
|
activeSession?.stop()
|
|
33
47
|
activeSession = null
|
|
34
48
|
}
|
|
35
49
|
|
|
50
|
+
/** @deprecated Dev prompts render inside the Ink dashboard — no suspend needed. */
|
|
51
|
+
export function suspendDevSessionForPrompt(): void {
|
|
52
|
+
prepareStdinForInteractivePrompt()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function prepareStdinForInteractivePrompt(): void {
|
|
56
|
+
if (!process.stdin.isTTY) return
|
|
57
|
+
process.stdin.setRawMode(false)
|
|
58
|
+
process.stdin.resume()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** @deprecated Dev prompts render inside the Ink dashboard — no resume needed. */
|
|
62
|
+
export function resumeDevSessionAfterPrompt(): void {
|
|
63
|
+
// no-op — prompts are Ink overlays
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** @deprecated Use Ink overlay prompts — runs fn without tearing down the dashboard. */
|
|
67
|
+
export async function withDevSessionSuspended<T>(fn: () => Promise<T>): Promise<T> {
|
|
68
|
+
return fn()
|
|
69
|
+
}
|
|
70
|
+
|
|
36
71
|
export function getActiveDevSession(): DevSession | null {
|
|
37
72
|
return activeSession
|
|
38
73
|
}
|
|
39
74
|
|
|
40
|
-
|
|
75
|
+
export function appendStackOutput(
|
|
76
|
+
text: string | null | undefined,
|
|
77
|
+
level: DevLogLevel = "log",
|
|
78
|
+
): void {
|
|
79
|
+
if (text == null || text.trim() === "") return
|
|
80
|
+
const session = getActiveDevSession()
|
|
81
|
+
for (const line of text.split(/\r?\n/)) {
|
|
82
|
+
if (line.trim() === "") continue
|
|
83
|
+
if (session?.isTui() && !filterStackLogLine(line)) continue
|
|
84
|
+
if (session?.isConsoleCaptured()) {
|
|
85
|
+
session.bus.append("stack", line, level)
|
|
86
|
+
continue
|
|
87
|
+
}
|
|
88
|
+
const write = level === "warn" ? console.warn : level === "error" ? console.error : console.log
|
|
89
|
+
write(`[supatype] ${line}`)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
41
93
|
export function appendDevTaskLog(
|
|
42
94
|
taskId: string,
|
|
43
95
|
taskTitle: string,
|
|
@@ -58,8 +110,9 @@ export function appendDevTaskLog(
|
|
|
58
110
|
export class DevSession {
|
|
59
111
|
readonly bus = new DevLogBus()
|
|
60
112
|
readonly mode: DevUiMode
|
|
61
|
-
private
|
|
113
|
+
private ink: Instance | null = null
|
|
62
114
|
private restoreConsole: (() => void) | null = null
|
|
115
|
+
private consoleCaptured = false
|
|
63
116
|
|
|
64
117
|
constructor(mode: DevUiMode) {
|
|
65
118
|
this.mode = mode
|
|
@@ -69,18 +122,37 @@ export class DevSession {
|
|
|
69
122
|
return this.mode === "tui"
|
|
70
123
|
}
|
|
71
124
|
|
|
72
|
-
|
|
73
|
-
|
|
125
|
+
isInkMounted(): boolean {
|
|
126
|
+
return this.ink !== null
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
isConsoleCaptured(): boolean {
|
|
130
|
+
return this.consoleCaptured
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
needsPromptSuspend(): boolean {
|
|
134
|
+
return false
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
enableConsoleCapture(_tee: boolean): void {
|
|
138
|
+
if (!this.isTui() || this.consoleCaptured) return
|
|
74
139
|
this.restoreConsole = patchConsole(this.bus)
|
|
75
|
-
this.
|
|
76
|
-
|
|
140
|
+
this.consoleCaptured = true
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
startInk(): void {
|
|
144
|
+
if (!this.isTui() || this.ink) return
|
|
145
|
+
this.ink = render(React.createElement(DevDashboard, { bus: this.bus }))
|
|
77
146
|
}
|
|
78
147
|
|
|
79
148
|
stop(): void {
|
|
80
|
-
this.
|
|
81
|
-
this.
|
|
82
|
-
this.restoreConsole
|
|
83
|
-
|
|
149
|
+
this.ink?.unmount()
|
|
150
|
+
this.ink = null
|
|
151
|
+
if (this.restoreConsole) {
|
|
152
|
+
this.restoreConsole()
|
|
153
|
+
this.restoreConsole = null
|
|
154
|
+
this.consoleCaptured = false
|
|
155
|
+
}
|
|
84
156
|
}
|
|
85
157
|
}
|
|
86
158
|
|
|
@@ -105,6 +177,14 @@ export function enhanceProcessOptions(label: string, opts: ProcessOptions): Proc
|
|
|
105
177
|
}
|
|
106
178
|
}
|
|
107
179
|
|
|
180
|
+
function appendFilteredStackLine(bus: DevLogBus, line: string, level: DevLogLevel): void {
|
|
181
|
+
for (const part of line.split(/\r?\n/)) {
|
|
182
|
+
if (!part.trim()) continue
|
|
183
|
+
if (!filterStackLogLine(part)) continue
|
|
184
|
+
bus.append("stack", part, level)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
108
188
|
function patchConsole(bus: DevLogBus): () => void {
|
|
109
189
|
const original = {
|
|
110
190
|
log: console.log,
|
|
@@ -113,13 +193,13 @@ function patchConsole(bus: DevLogBus): () => void {
|
|
|
113
193
|
}
|
|
114
194
|
|
|
115
195
|
console.log = (...args: unknown[]) => {
|
|
116
|
-
bus
|
|
196
|
+
appendFilteredStackLine(bus, formatConsoleArgs(args), "log")
|
|
117
197
|
}
|
|
118
198
|
console.warn = (...args: unknown[]) => {
|
|
119
|
-
bus
|
|
199
|
+
appendFilteredStackLine(bus, formatConsoleArgs(args), "warn")
|
|
120
200
|
}
|
|
121
201
|
console.error = (...args: unknown[]) => {
|
|
122
|
-
bus
|
|
202
|
+
appendFilteredStackLine(bus, formatConsoleArgs(args), "error")
|
|
123
203
|
}
|
|
124
204
|
|
|
125
205
|
return () => {
|
package/src/dev-shutdown.ts
CHANGED
|
@@ -21,8 +21,28 @@ let shuttingDown = false
|
|
|
21
21
|
let shutdownCompleted = false
|
|
22
22
|
let forceQuitRequested = false
|
|
23
23
|
let hooksRegistered = false
|
|
24
|
+
let ignoreSigintUntil = 0
|
|
25
|
+
|
|
26
|
+
/** SIGINT/SIGTERM hooks — call as soon as `supatype dev` starts (before compose is up). */
|
|
27
|
+
export function ensureDevShutdownHooks(): void {
|
|
28
|
+
if (hooksRegistered) return
|
|
29
|
+
hooksRegistered = true
|
|
30
|
+
|
|
31
|
+
process.on("SIGINT", onSignal)
|
|
32
|
+
process.on("SIGTERM", onSignal)
|
|
33
|
+
if (process.platform === "win32") {
|
|
34
|
+
process.on("SIGBREAK", onSignal)
|
|
35
|
+
}
|
|
36
|
+
process.on("exit", onProcessExit)
|
|
37
|
+
|
|
38
|
+
if (process.stdin.isTTY) {
|
|
39
|
+
process.stdin.on("end", onStdinClose)
|
|
40
|
+
process.stdin.on("close", onStdinClose)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
24
43
|
|
|
25
44
|
function onSignal(): void {
|
|
45
|
+
if (Date.now() < ignoreSigintUntil) return
|
|
26
46
|
void runDevShutdown()
|
|
27
47
|
}
|
|
28
48
|
|
|
@@ -66,25 +86,12 @@ export function registerDevShutdown(
|
|
|
66
86
|
shutdownWork = work
|
|
67
87
|
composeFallback = opts?.compose ?? null
|
|
68
88
|
shutdownCwd = opts?.cwd ?? opts?.compose?.cwd ?? null
|
|
69
|
-
|
|
70
|
-
if (hooksRegistered) return
|
|
71
|
-
hooksRegistered = true
|
|
72
|
-
|
|
73
|
-
process.on("SIGINT", onSignal)
|
|
74
|
-
process.on("SIGTERM", onSignal)
|
|
75
|
-
if (process.platform === "win32") {
|
|
76
|
-
process.on("SIGBREAK", onSignal)
|
|
77
|
-
}
|
|
78
|
-
process.on("exit", onProcessExit)
|
|
79
|
-
|
|
80
|
-
if (process.stdin.isTTY) {
|
|
81
|
-
process.stdin.on("end", onStdinClose)
|
|
82
|
-
process.stdin.on("close", onStdinClose)
|
|
83
|
-
}
|
|
89
|
+
ensureDevShutdownHooks()
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
/** TUI Ctrl+C — do not re-emit SIGINT (avoids double-fire on Windows raw mode). */
|
|
87
93
|
export function requestDevShutdown(): void {
|
|
94
|
+
ignoreSigintUntil = Date.now() + 400
|
|
88
95
|
void runDevShutdown()
|
|
89
96
|
}
|
|
90
97
|
|
|
@@ -101,6 +108,7 @@ export function resetDevShutdownForTests(): void {
|
|
|
101
108
|
shutdownCompleted = false
|
|
102
109
|
forceQuitRequested = false
|
|
103
110
|
hooksRegistered = false
|
|
111
|
+
ignoreSigintUntil = 0
|
|
104
112
|
}
|
|
105
113
|
|
|
106
114
|
async function runDevShutdown(): Promise<void> {
|
|
@@ -125,8 +133,12 @@ async function runDevShutdown(): Promise<void> {
|
|
|
125
133
|
|
|
126
134
|
try {
|
|
127
135
|
endDevSession()
|
|
128
|
-
process.
|
|
129
|
-
|
|
136
|
+
process.stderr.write("\n[supatype] Shutting down…\n")
|
|
137
|
+
if (!shutdownWork) {
|
|
138
|
+
if (shutdownCwd) clearDevSessionLock(shutdownCwd)
|
|
139
|
+
process.exit(130)
|
|
140
|
+
}
|
|
141
|
+
await shutdownWork()
|
|
130
142
|
shutdownCompleted = true
|
|
131
143
|
if (shutdownCwd) clearDevSessionLock(shutdownCwd)
|
|
132
144
|
process.exit(0)
|
package/src/dev-task-colors.ts
CHANGED
|
@@ -41,7 +41,26 @@ export function colorizeLogLine(taskId: string, line: string): string {
|
|
|
41
41
|
return `${base}${line}${RESET}`
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
/** Ink colour names for React components (parallel to ANSI taskColor). */
|
|
45
|
+
export function taskInkColor(taskId: string): string {
|
|
46
|
+
switch (taskId) {
|
|
47
|
+
case "stack":
|
|
48
|
+
return "magenta"
|
|
49
|
+
case "app":
|
|
50
|
+
return "green"
|
|
51
|
+
case "studio":
|
|
52
|
+
return "cyan"
|
|
53
|
+
case "server":
|
|
54
|
+
return "green"
|
|
55
|
+
case "postgrest":
|
|
56
|
+
return "blue"
|
|
57
|
+
default:
|
|
58
|
+
return "white"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function logInkColor(taskId: string, line: string): string {
|
|
63
|
+
if (line.startsWith("✗ ")) return "red"
|
|
64
|
+
if (line.startsWith("⚠ ")) return "yellow"
|
|
65
|
+
return taskInkColor(taskId)
|
|
47
66
|
}
|
package/src/docker-runtime.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { platform } from "node:os"
|
|
|
7
7
|
import { endDevSession, getActiveDevSession } from "./dev-session.js"
|
|
8
8
|
import { isInteractive } from "./ui/interactive.js"
|
|
9
9
|
import { error, plain } from "./ui/messages.js"
|
|
10
|
-
import {
|
|
10
|
+
import { p, printLogo } from "./ui/prompts.js"
|
|
11
11
|
|
|
12
12
|
export type DockerDaemonProbe =
|
|
13
13
|
| { ok: true }
|
|
@@ -59,6 +59,10 @@ export function formatEnginePushMessage(result: EnginePushResult): string {
|
|
|
59
59
|
const COMPOSE_PROGRESS_LINE =
|
|
60
60
|
/^Container\s+.+\s+(Running|Waiting|Healthy|Created|Starting|Started|Exited|Stopped)\s*$/i
|
|
61
61
|
|
|
62
|
+
export function isComposeProgressLine(line: string): boolean {
|
|
63
|
+
return COMPOSE_PROGRESS_LINE.test(line.trim())
|
|
64
|
+
}
|
|
65
|
+
|
|
62
66
|
/** Drop docker compose progress noise; keep engine JSON and real errors. */
|
|
63
67
|
export function filterComposeNoise(output: string): string {
|
|
64
68
|
return output
|
|
@@ -67,7 +71,7 @@ export function filterComposeNoise(output: string): string {
|
|
|
67
71
|
.filter((line) => {
|
|
68
72
|
const t = line.trim()
|
|
69
73
|
if (!t) return false
|
|
70
|
-
if (
|
|
74
|
+
if (isComposeProgressLine(t)) return false
|
|
71
75
|
return true
|
|
72
76
|
})
|
|
73
77
|
.join("\n")
|
package/src/ensure-binary.ts
CHANGED
|
@@ -7,8 +7,10 @@ import {
|
|
|
7
7
|
download,
|
|
8
8
|
currentPlatform,
|
|
9
9
|
resolveVersionFor,
|
|
10
|
+
isCachedBinaryReady,
|
|
10
11
|
type Component,
|
|
11
12
|
} from "./binary-cache.js"
|
|
13
|
+
import { isDownloadInProgress, waitForComponentDownload } from "./binary-download-lock.js"
|
|
12
14
|
import type { SupatypeProjectConfig } from "./project-config.js"
|
|
13
15
|
|
|
14
16
|
export async function ensureBinary(
|
|
@@ -24,5 +26,23 @@ export async function ensureBinary(
|
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
const version = await resolveVersionFor(component, config)
|
|
30
|
+
const platform = currentPlatform()
|
|
31
|
+
|
|
32
|
+
if (isDownloadInProgress(component, version)) {
|
|
33
|
+
console.log(`[supatype] Waiting for in-progress ${component} download...`)
|
|
34
|
+
const outcome = await waitForComponentDownload(
|
|
35
|
+
component,
|
|
36
|
+
version,
|
|
37
|
+
() => isCachedBinaryReady(component, version, platform),
|
|
38
|
+
(c) => {
|
|
39
|
+
console.log(`[supatype] Still waiting for ${c}...`)
|
|
40
|
+
},
|
|
41
|
+
)
|
|
42
|
+
if (outcome === "ready") {
|
|
43
|
+
return resolveBinary(component, config)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return download(component, version, platform)
|
|
28
48
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensure CDN component binaries are cached when the host CLI needs them.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { ensureBinary } from "./ensure-binary.js"
|
|
6
|
+
import type { Component } from "./components.js"
|
|
7
|
+
import type { SupatypeProjectConfig } from "./project-config.js"
|
|
8
|
+
import {
|
|
9
|
+
describeRequiredHostComponents,
|
|
10
|
+
requiredHostComponents,
|
|
11
|
+
} from "./required-host-components.js"
|
|
12
|
+
import { resolveRuntimeProvider } from "./project-config.js"
|
|
13
|
+
import { error, info, warn } from "./ui/messages.js"
|
|
14
|
+
|
|
15
|
+
export interface ComponentBinaryFailure {
|
|
16
|
+
component: Component
|
|
17
|
+
message: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface EnsureComponentBinariesResult {
|
|
21
|
+
ok: boolean
|
|
22
|
+
failures: ComponentBinaryFailure[]
|
|
23
|
+
skipped: boolean
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function ensureComponentBinaries(
|
|
27
|
+
config: SupatypeProjectConfig,
|
|
28
|
+
cwd: string = process.cwd(),
|
|
29
|
+
): Promise<EnsureComponentBinariesResult> {
|
|
30
|
+
const components = requiredHostComponents(config, cwd)
|
|
31
|
+
const provider = resolveRuntimeProvider(config)
|
|
32
|
+
|
|
33
|
+
if (components.length === 0) {
|
|
34
|
+
return { ok: true, failures: [], skipped: true }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const list = describeRequiredHostComponents(components)
|
|
38
|
+
if (provider === "docker") {
|
|
39
|
+
info(
|
|
40
|
+
`Preparing host CLI tools (${list}) — Compose still runs Postgres and the API stack.`,
|
|
41
|
+
)
|
|
42
|
+
} else {
|
|
43
|
+
info(`Preparing local runtime components (${list})…`)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const failures: ComponentBinaryFailure[] = []
|
|
47
|
+
|
|
48
|
+
for (const component of components) {
|
|
49
|
+
try {
|
|
50
|
+
await ensureBinary(component, config)
|
|
51
|
+
info(`${component} ready.`)
|
|
52
|
+
} catch (err) {
|
|
53
|
+
const message = err instanceof Error ? err.message : String(err)
|
|
54
|
+
failures.push({ component, message })
|
|
55
|
+
error(`Could not prepare ${component}: ${message}`)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return { ok: failures.length === 0, failures, skipped: false }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function reportComponentBinaryFailures(failures: ComponentBinaryFailure[]): void {
|
|
63
|
+
if (failures.length === 0) return
|
|
64
|
+
|
|
65
|
+
warn("Some component binaries are still missing.")
|
|
66
|
+
for (const { component, message } of failures) {
|
|
67
|
+
warn(` ${component}: ${message}`)
|
|
68
|
+
}
|
|
69
|
+
warn("Run manually from your project directory: supatype update")
|
|
70
|
+
warn("If downloads keep failing, check your network or try again in a few minutes.")
|
|
71
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync } from "node:fs"
|
|
2
|
+
import { dirname, join } from "node:path"
|
|
3
|
+
|
|
4
|
+
const TEMPLATE_REL = join("config", "api-config.json")
|
|
5
|
+
const TARGET_REL = join(".supatype", "api-config.json")
|
|
6
|
+
|
|
7
|
+
/** Copy committed `config/api-config.json` when `.supatype/api-config.json` is missing. */
|
|
8
|
+
export function ensureDevApiConfig(cwd: string): boolean {
|
|
9
|
+
const target = join(cwd, TARGET_REL)
|
|
10
|
+
if (existsSync(target)) return false
|
|
11
|
+
|
|
12
|
+
const template = join(cwd, TEMPLATE_REL)
|
|
13
|
+
if (!existsSync(template)) return false
|
|
14
|
+
|
|
15
|
+
mkdirSync(dirname(target), { recursive: true })
|
|
16
|
+
copyFileSync(template, target)
|
|
17
|
+
return true
|
|
18
|
+
}
|