@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.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +121 -86
- 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 +28 -1
- package/dist/commands/admin.d.ts.map +1 -1
- package/dist/commands/admin.js +290 -112
- 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 +28 -22
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/init.d.ts +8 -4
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +278 -139
- 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/commands/push.js +3 -3
- package/dist/commands/push.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 +10 -0
- package/dist/compose-rename.d.ts.map +1 -0
- package/dist/compose-rename.js +64 -0
- package/dist/compose-rename.js.map +1 -0
- package/dist/dev-compose.d.ts.map +1 -1
- package/dist/dev-compose.js +138 -97
- 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 +14 -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 +27 -0
- package/dist/dev-ports.d.ts.map +1 -0
- package/dist/dev-ports.js +178 -0
- package/dist/dev-ports.js.map +1 -0
- package/dist/dev-ready-panel.d.ts +19 -0
- package/dist/dev-ready-panel.d.ts.map +1 -0
- package/dist/dev-ready-panel.js +49 -0
- package/dist/dev-ready-panel.js.map +1 -0
- package/dist/dev-session-lock.d.ts +25 -0
- package/dist/dev-session-lock.d.ts.map +1 -0
- package/dist/dev-session-lock.js +78 -0
- package/dist/dev-session-lock.js.map +1 -0
- 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 +20 -2
- package/dist/dev-shutdown.d.ts.map +1 -1
- package/dist/dev-shutdown.js +88 -10
- 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/env-file.d.ts +5 -0
- package/dist/env-file.d.ts.map +1 -0
- package/dist/env-file.js +33 -0
- package/dist/env-file.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/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 +24 -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 +151 -0
- package/dist/ui/dev/DevDashboard.js.map +1 -0
- package/dist/ui/dev/DevReadyPanelView.d.ts +7 -0
- package/dist/ui/dev/DevReadyPanelView.d.ts.map +1 -0
- package/dist/ui/dev/DevReadyPanelView.js +29 -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 +42 -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 +88 -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 +34 -0
- package/dist/ui/runtime/run-clack-flow.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 +11 -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 +380 -137
- package/src/commands/cache.ts +105 -5
- package/src/commands/dev.ts +29 -21
- package/src/commands/init.ts +217 -46
- package/src/commands/link-helpers.ts +30 -29
- package/src/commands/push.ts +3 -3
- package/src/compose-local-server-image.ts +68 -0
- package/src/compose-rename.ts +73 -0
- package/src/dev-compose.ts +175 -96
- package/src/dev-log-bus.ts +18 -0
- package/src/dev-log-filter.ts +42 -0
- package/src/dev-ports.ts +223 -0
- package/src/dev-ready-panel.ts +63 -0
- package/src/dev-session-lock.ts +98 -0
- package/src/dev-session.ts +98 -18
- package/src/dev-shutdown.ts +114 -9
- 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/env-file.ts +37 -0
- package/src/init-dependency-versions.ts +69 -0
- package/src/init-package-json.ts +63 -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 +23 -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 +213 -0
- package/src/ui/dev/DevReadyPanelView.tsx +67 -0
- package/src/ui/fatal.ts +5 -10
- package/src/ui/flows/FlowApp.tsx +67 -0
- package/src/ui/flows/prompt-fields.tsx +192 -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 +52 -0
- package/src/ui/theme.ts +41 -0
- package/src/valkey-sidecar.ts +126 -0
- package/tests/admin-ensure.test.ts +59 -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 +8 -4
- package/tests/dev-ports.test.ts +41 -0
- package/tests/dev-ready-panel.test.ts +20 -0
- package/tests/dev-session-lock.test.ts +54 -0
- package/tests/dev-ui.test.ts +66 -3
- 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.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/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/commands/init.ts
CHANGED
|
@@ -1,36 +1,25 @@
|
|
|
1
1
|
import type { Command } from "commander"
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
|
|
3
|
-
import { resolve, join,
|
|
4
|
-
import { fileURLToPath } from "node:url"
|
|
3
|
+
import { resolve, join, basename } from "node:path"
|
|
5
4
|
import { spawnSync } from "node:child_process"
|
|
6
|
-
import
|
|
5
|
+
import { p, runClackFlow } from "../ui/clack.js"
|
|
7
6
|
import { ensureNotCancelled, printLogo } from "../ui/prompts.js"
|
|
8
7
|
import { generateAndWriteKeys } from "./keys.js"
|
|
9
8
|
import { file, error, info, plain, warn } from "../ui/messages.js"
|
|
10
9
|
import { nextSteps } from "../ui/next-steps.js"
|
|
11
10
|
import { probeDockerDaemon, reportDockerUnavailable } from "../docker-runtime.js"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
function cliPackageVersion(): string {
|
|
27
|
-
try {
|
|
28
|
-
const pkg = JSON.parse(readFileSync(CLI_PACKAGE_JSON, "utf8")) as { version?: string }
|
|
29
|
-
return pkg.version ?? "0.1.0"
|
|
30
|
-
} catch {
|
|
31
|
-
return "0.1.0"
|
|
32
|
-
}
|
|
33
|
-
}
|
|
11
|
+
import { loadConfig } from "../config.js"
|
|
12
|
+
import {
|
|
13
|
+
ensureComponentBinaries,
|
|
14
|
+
reportComponentBinaryFailures,
|
|
15
|
+
} from "../ensure-component-binaries.js"
|
|
16
|
+
import { mergeSupatypePackageJson } from "../init-package-json.js"
|
|
17
|
+
import { cliPackageVersion } from "../cli-package-version.js"
|
|
18
|
+
import {
|
|
19
|
+
initDependencyVersionsFallback,
|
|
20
|
+
resolveInitDependencyVersions,
|
|
21
|
+
type InitDependencyVersions,
|
|
22
|
+
} from "../init-dependency-versions.js"
|
|
34
23
|
|
|
35
24
|
// ─── Options model ─────────────────────────────────────────────────────────--
|
|
36
25
|
|
|
@@ -52,6 +41,8 @@ export interface ScaffoldOptions {
|
|
|
52
41
|
projectName: string
|
|
53
42
|
/** Local development runtime (docker recommended). */
|
|
54
43
|
provider: "docker" | "native"
|
|
44
|
+
/** Host Kong port when provider is docker (unique per project). */
|
|
45
|
+
kongPort?: number
|
|
55
46
|
productionTarget: ProductionTarget
|
|
56
47
|
domain?: string
|
|
57
48
|
/** ACME contact email for Let's Encrypt HTTPS (self-host + domain). */
|
|
@@ -64,6 +55,9 @@ export interface ScaffoldOptions {
|
|
|
64
55
|
/** Object storage when deployed to production. */
|
|
65
56
|
storageProduction: "local" | "s3"
|
|
66
57
|
helloFunction: boolean
|
|
58
|
+
/** When set, written to .env for first dev/push to create the admin panel user. */
|
|
59
|
+
adminEmail?: string
|
|
60
|
+
adminPassword?: string
|
|
67
61
|
}
|
|
68
62
|
|
|
69
63
|
type StorageProvider = ScaffoldOptions["storageLocal"]
|
|
@@ -126,6 +120,9 @@ interface InitCliOptions {
|
|
|
126
120
|
defaults?: boolean
|
|
127
121
|
install: boolean
|
|
128
122
|
keys: boolean
|
|
123
|
+
adminEmail?: string
|
|
124
|
+
adminPassword?: string
|
|
125
|
+
admin?: boolean
|
|
129
126
|
}
|
|
130
127
|
|
|
131
128
|
export function registerInit(program: Command): void {
|
|
@@ -140,6 +137,9 @@ export function registerInit(program: Command): void {
|
|
|
140
137
|
.option("-y, --defaults", "Skip all prompts and use sensible defaults")
|
|
141
138
|
.option("--no-install", "Do not run the package manager install step")
|
|
142
139
|
.option("--no-keys", "Do not generate ANON_KEY / SERVICE_ROLE_KEY")
|
|
140
|
+
.option("--admin-email <email>", "First admin panel user email (written to .env)")
|
|
141
|
+
.option("--admin-password <password>", "First admin panel user password (written to .env)")
|
|
142
|
+
.option("--no-admin", "Do not configure a first admin user")
|
|
143
143
|
.action(async (name: string | undefined, opts: InitCliOptions) => {
|
|
144
144
|
const dir = name ? resolve(process.cwd(), name) : process.cwd()
|
|
145
145
|
|
|
@@ -164,6 +164,23 @@ export function registerInit(program: Command): void {
|
|
|
164
164
|
install: true,
|
|
165
165
|
generateKeys: true,
|
|
166
166
|
}
|
|
167
|
+
if (result.provider === "docker") {
|
|
168
|
+
const { findNextFreePort } = await import("../dev-ports.js")
|
|
169
|
+
const { COMPOSE_DEV_KONG_PORT } = await import("../project-config.js")
|
|
170
|
+
result.kongPort = await findNextFreePort(COMPOSE_DEV_KONG_PORT)
|
|
171
|
+
}
|
|
172
|
+
if (!opts.admin && opts.adminEmail && opts.adminPassword) {
|
|
173
|
+
result.adminEmail = opts.adminEmail
|
|
174
|
+
result.adminPassword = opts.adminPassword
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (opts.admin === false) {
|
|
179
|
+
delete result.adminEmail
|
|
180
|
+
delete result.adminPassword
|
|
181
|
+
} else if (opts.adminEmail && opts.adminPassword) {
|
|
182
|
+
result.adminEmail = opts.adminEmail
|
|
183
|
+
result.adminPassword = opts.adminPassword
|
|
167
184
|
}
|
|
168
185
|
|
|
169
186
|
// CLI flags override wizard / default action choices.
|
|
@@ -172,9 +189,23 @@ export function registerInit(program: Command): void {
|
|
|
172
189
|
|
|
173
190
|
if (name) mkdirSync(dir, { recursive: true })
|
|
174
191
|
|
|
175
|
-
|
|
192
|
+
const deps = await resolveInitDependencyVersions()
|
|
193
|
+
const runningCli = cliPackageVersion()
|
|
194
|
+
if (deps.cli !== runningCli || deps.types !== runningCli) {
|
|
195
|
+
info(
|
|
196
|
+
`Using published npm versions: @supatype/cli ^${deps.cli}, @supatype/types ^${deps.types}`,
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
scaffold(dir, result, deps)
|
|
201
|
+
|
|
202
|
+
const installOk = doInstall ? runInstall(dir, result.packageManager) : true
|
|
203
|
+
|
|
204
|
+
const binariesReady = installOk ? await ensureInitBinaries(dir) : false
|
|
205
|
+
if (doInstall && !installOk) {
|
|
206
|
+
warn("Skipping component binary check until dependencies install successfully.")
|
|
207
|
+
}
|
|
176
208
|
|
|
177
|
-
if (doInstall) runInstall(dir, result.packageManager)
|
|
178
209
|
const keysGenerated = doKeys ? writeKeys(dir) : false
|
|
179
210
|
|
|
180
211
|
warnDockerUnavailableForProvider(result.provider)
|
|
@@ -182,8 +213,9 @@ export function registerInit(program: Command): void {
|
|
|
182
213
|
printNextSteps({
|
|
183
214
|
name,
|
|
184
215
|
result,
|
|
185
|
-
installed: doInstall,
|
|
216
|
+
installed: doInstall && installOk,
|
|
186
217
|
keysGenerated,
|
|
218
|
+
binariesReady,
|
|
187
219
|
})
|
|
188
220
|
})
|
|
189
221
|
}
|
|
@@ -194,6 +226,7 @@ async function runWizard(
|
|
|
194
226
|
defaultName: string,
|
|
195
227
|
defaultTarget: ProductionTarget,
|
|
196
228
|
): Promise<WizardResult> {
|
|
229
|
+
return runClackFlow(async () => {
|
|
197
230
|
p.intro("Create a new Supatype project")
|
|
198
231
|
|
|
199
232
|
const projectName = ensureNotCancelled(
|
|
@@ -262,6 +295,12 @@ async function runWizard(
|
|
|
262
295
|
}),
|
|
263
296
|
)
|
|
264
297
|
|
|
298
|
+
let kongPort: number | undefined
|
|
299
|
+
if (provider === "docker") {
|
|
300
|
+
const { promptKongPortChoice } = await import("../dev-ports.js")
|
|
301
|
+
kongPort = await promptKongPortChoice()
|
|
302
|
+
}
|
|
303
|
+
|
|
265
304
|
const schemaPath = ensureNotCancelled(
|
|
266
305
|
await p.text({
|
|
267
306
|
message: "Where should your schema live?",
|
|
@@ -322,11 +361,43 @@ async function runWizard(
|
|
|
322
361
|
}),
|
|
323
362
|
)
|
|
324
363
|
|
|
364
|
+
let adminEmail: string | undefined
|
|
365
|
+
let adminPassword: string | undefined
|
|
366
|
+
const createAdmin = ensureNotCancelled(
|
|
367
|
+
await p.confirm({
|
|
368
|
+
message: "Create an admin user for /admin?",
|
|
369
|
+
initialValue: true,
|
|
370
|
+
}),
|
|
371
|
+
)
|
|
372
|
+
if (createAdmin) {
|
|
373
|
+
adminEmail =
|
|
374
|
+
ensureNotCancelled(
|
|
375
|
+
await p.text({
|
|
376
|
+
message: "Admin email",
|
|
377
|
+
placeholder: "you@example.com",
|
|
378
|
+
defaultValue: "",
|
|
379
|
+
}),
|
|
380
|
+
).trim() || undefined
|
|
381
|
+
if (adminEmail) {
|
|
382
|
+
adminPassword =
|
|
383
|
+
ensureNotCancelled(
|
|
384
|
+
await p.text({
|
|
385
|
+
message: "Admin password (min 8 chars)",
|
|
386
|
+
defaultValue: "",
|
|
387
|
+
}),
|
|
388
|
+
).trim() || undefined
|
|
389
|
+
if (adminPassword && adminPassword.length < 8) {
|
|
390
|
+
adminPassword = undefined
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
325
395
|
p.outro("Setting up your project...")
|
|
326
396
|
|
|
327
397
|
return {
|
|
328
398
|
projectName,
|
|
329
399
|
provider,
|
|
400
|
+
...(kongPort !== undefined ? { kongPort } : {}),
|
|
330
401
|
productionTarget,
|
|
331
402
|
...(domain !== undefined ? { domain } : {}),
|
|
332
403
|
...(tlsEmail !== undefined ? { tlsEmail } : {}),
|
|
@@ -339,7 +410,9 @@ async function runWizard(
|
|
|
339
410
|
packageManager,
|
|
340
411
|
install,
|
|
341
412
|
generateKeys,
|
|
413
|
+
...(adminEmail && adminPassword ? { adminEmail, adminPassword } : {}),
|
|
342
414
|
}
|
|
415
|
+
})
|
|
343
416
|
}
|
|
344
417
|
|
|
345
418
|
async function promptApp(): Promise<ScaffoldAppOptions> {
|
|
@@ -418,7 +491,7 @@ function detectInvokingPackageManager(): PackageManager {
|
|
|
418
491
|
return "npm"
|
|
419
492
|
}
|
|
420
493
|
|
|
421
|
-
function runInstall(dir: string, pm: PackageManager):
|
|
494
|
+
function runInstall(dir: string, pm: PackageManager): boolean {
|
|
422
495
|
info(`Installing dependencies with ${pm}...`)
|
|
423
496
|
const res = spawnSync(pm, ["install"], {
|
|
424
497
|
cwd: dir,
|
|
@@ -427,6 +500,29 @@ function runInstall(dir: string, pm: PackageManager): void {
|
|
|
427
500
|
})
|
|
428
501
|
if (res.status !== 0 || res.error) {
|
|
429
502
|
warn(`Dependency install did not complete (run "${pm} install" manually).`)
|
|
503
|
+
return false
|
|
504
|
+
}
|
|
505
|
+
return true
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
async function ensureInitBinaries(dir: string): Promise<boolean> {
|
|
509
|
+
const previousCwd = process.cwd()
|
|
510
|
+
try {
|
|
511
|
+
process.chdir(dir)
|
|
512
|
+
const config = loadConfig(dir)
|
|
513
|
+
const result = await ensureComponentBinaries(config, dir)
|
|
514
|
+
if (!result.ok) {
|
|
515
|
+
reportComponentBinaryFailures(result.failures)
|
|
516
|
+
return false
|
|
517
|
+
}
|
|
518
|
+
return true
|
|
519
|
+
} catch (err) {
|
|
520
|
+
const message = err instanceof Error ? err.message : String(err)
|
|
521
|
+
warn(`Could not verify component binaries: ${message}`)
|
|
522
|
+
warn("Run manually from your project directory: supatype update")
|
|
523
|
+
return false
|
|
524
|
+
} finally {
|
|
525
|
+
process.chdir(previousCwd)
|
|
430
526
|
}
|
|
431
527
|
}
|
|
432
528
|
|
|
@@ -441,7 +537,11 @@ function writeKeys(dir: string): boolean {
|
|
|
441
537
|
|
|
442
538
|
// ─── Scaffold ──────────────────────────────────────────────────────────────--
|
|
443
539
|
|
|
444
|
-
function scaffold(
|
|
540
|
+
export function scaffold(
|
|
541
|
+
dir: string,
|
|
542
|
+
optsOrName: ScaffoldOptions | string,
|
|
543
|
+
deps: InitDependencyVersions = initDependencyVersionsFallback(),
|
|
544
|
+
): void {
|
|
445
545
|
const opts =
|
|
446
546
|
typeof optsOrName === "string" ? defaultScaffoldOptions(optsOrName) : optsOrName
|
|
447
547
|
const write = (rel: string, content: string) => {
|
|
@@ -453,9 +553,17 @@ function scaffold(dir: string, optsOrName: ScaffoldOptions | string): void {
|
|
|
453
553
|
|
|
454
554
|
const pkgPath = join(dir, "package.json")
|
|
455
555
|
if (!existsSync(pkgPath)) {
|
|
456
|
-
write("package.json", packageJsonTemplate(opts,
|
|
556
|
+
write("package.json", packageJsonTemplate(opts, deps))
|
|
457
557
|
} else {
|
|
458
|
-
|
|
558
|
+
try {
|
|
559
|
+
const existing = JSON.parse(readFileSync(pkgPath, "utf8")) as Record<string, unknown>
|
|
560
|
+
const merged = mergeSupatypePackageJson(existing, opts, deps)
|
|
561
|
+
writeFileSync(pkgPath, `${JSON.stringify(merged, null, 2)}\n`, "utf8")
|
|
562
|
+
file("updated", "package.json (added Supatype dependencies)")
|
|
563
|
+
} catch {
|
|
564
|
+
warn("Could not merge into package.json — add @supatype/cli and @supatype/types manually.")
|
|
565
|
+
file("skipped", "package.json (invalid JSON)")
|
|
566
|
+
}
|
|
459
567
|
}
|
|
460
568
|
|
|
461
569
|
write("supatype.config.ts", tsConfigTemplate(opts))
|
|
@@ -498,8 +606,13 @@ function scaffoldAppAssets(
|
|
|
498
606
|
|
|
499
607
|
if (opts.app.mode === "static") {
|
|
500
608
|
const staticRel = staticDirRelative(opts.app.staticDir)
|
|
609
|
+
if (opts.app.viteDevUrl && opts.productionTarget !== "later") {
|
|
610
|
+
write("dist/index.html", holding)
|
|
611
|
+
scaffoldVite(opts, write, holding)
|
|
612
|
+
return
|
|
613
|
+
}
|
|
501
614
|
write(`${staticRel}/index.html`, holding)
|
|
502
|
-
if (
|
|
615
|
+
if (opts.app.viteDevUrl) scaffoldVite(opts, write, holding)
|
|
503
616
|
return
|
|
504
617
|
}
|
|
505
618
|
|
|
@@ -542,7 +655,7 @@ function scaffoldHelloFunction(
|
|
|
542
655
|
|
|
543
656
|
// ─── Templates ───────────────────────────────────────────────────────────────
|
|
544
657
|
|
|
545
|
-
function packageJsonTemplate(opts: ScaffoldOptions,
|
|
658
|
+
function packageJsonTemplate(opts: ScaffoldOptions, deps: InitDependencyVersions): string {
|
|
546
659
|
const scripts: string[] = [
|
|
547
660
|
` "dev": "supatype dev"`,
|
|
548
661
|
` "push": "supatype push"`,
|
|
@@ -566,8 +679,8 @@ function packageJsonTemplate(opts: ScaffoldOptions, cliVersion: string): string
|
|
|
566
679
|
${scripts.join(",\n")}
|
|
567
680
|
},
|
|
568
681
|
"dependencies": {
|
|
569
|
-
"@supatype/cli": "^${
|
|
570
|
-
"@supatype/types": "^${
|
|
682
|
+
"@supatype/cli": "^${deps.cli}",
|
|
683
|
+
"@supatype/types": "^${deps.types}"
|
|
571
684
|
},
|
|
572
685
|
"devDependencies": {
|
|
573
686
|
${devDeps.join(",\n")}
|
|
@@ -634,20 +747,49 @@ function localConfigTemplate(app: ScaffoldAppOptions): string {
|
|
|
634
747
|
`const localConfig: Partial<SupatypeConfig> = {`,
|
|
635
748
|
` server: { mode: "dev" },`,
|
|
636
749
|
]
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
lines.push(
|
|
640
|
-
lines.push(` upstream: "${app.upstream ?? "http://localhost:3000"}",`)
|
|
641
|
-
lines.push(` start: "${app.start ?? "dev"}",`)
|
|
642
|
-
if (app.viteDevUrl) lines.push(` vite_dev_url: "${app.viteDevUrl}",`)
|
|
643
|
-
lines.push(` },`)
|
|
750
|
+
const localApp = localDevAppConfigLines(app)
|
|
751
|
+
if (localApp.length > 0) {
|
|
752
|
+
lines.push(...localApp)
|
|
644
753
|
}
|
|
645
754
|
lines.push(`}`, ``, `export default localConfig`, ``)
|
|
646
755
|
return lines.join("\n")
|
|
647
756
|
}
|
|
648
757
|
|
|
758
|
+
/** App block for supatype.local.config.ts (proxy + Vite during local dev). */
|
|
759
|
+
function localDevAppConfigLines(app: ScaffoldAppOptions): string[] {
|
|
760
|
+
if (app.mode === "proxy") {
|
|
761
|
+
return [
|
|
762
|
+
` app: {`,
|
|
763
|
+
` mode: "proxy",`,
|
|
764
|
+
` upstream: "${app.upstream ?? "http://localhost:3000"}",`,
|
|
765
|
+
` start: "${app.start ?? "dev"}",`,
|
|
766
|
+
...(app.viteDevUrl ? [` vite_dev_url: "${app.viteDevUrl}",`] : []),
|
|
767
|
+
` },`,
|
|
768
|
+
]
|
|
769
|
+
}
|
|
770
|
+
if (app.viteDevUrl) {
|
|
771
|
+
return [
|
|
772
|
+
` app: {`,
|
|
773
|
+
` mode: "proxy",`,
|
|
774
|
+
` upstream: "${app.viteDevUrl}",`,
|
|
775
|
+
` start: "vite",`,
|
|
776
|
+
` vite_dev_url: "${app.viteDevUrl}",`,
|
|
777
|
+
` },`,
|
|
778
|
+
]
|
|
779
|
+
}
|
|
780
|
+
return []
|
|
781
|
+
}
|
|
782
|
+
|
|
649
783
|
function appConfigLines(app: ScaffoldAppOptions, productionTarget: ProductionTarget): string[] {
|
|
650
784
|
if (app.mode === "static") {
|
|
785
|
+
if (productionTarget !== "later" && app.viteDevUrl) {
|
|
786
|
+
return [
|
|
787
|
+
` app: {`,
|
|
788
|
+
` mode: "static",`,
|
|
789
|
+
` static_dir: "./dist", // production build output`,
|
|
790
|
+
` },`,
|
|
791
|
+
]
|
|
792
|
+
}
|
|
651
793
|
const out = [
|
|
652
794
|
` app: {`,
|
|
653
795
|
` mode: "static",`,
|
|
@@ -707,7 +849,7 @@ function holdingPageTemplate(projectName: string): string {
|
|
|
707
849
|
<meta charset="UTF-8" />
|
|
708
850
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
709
851
|
<title>${name} — Supatype</title>
|
|
710
|
-
<meta name="description" content="A Supatype project. Define your types — we generate your
|
|
852
|
+
<meta name="description" content="A Supatype project. Define your types — we generate your platform." />
|
|
711
853
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
712
854
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
713
855
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
|
@@ -842,6 +984,8 @@ export default defineConfig({
|
|
|
842
984
|
host: "127.0.0.1",
|
|
843
985
|
port: ${port},
|
|
844
986
|
strictPort: true,
|
|
987
|
+
// Docker Compose app proxy reaches the host as host.docker.internal.
|
|
988
|
+
allowedHosts: ["127.0.0.1", "localhost", "host.docker.internal"],
|
|
845
989
|
},
|
|
846
990
|
})
|
|
847
991
|
`
|
|
@@ -910,9 +1054,27 @@ SERVICE_ROLE_KEY=`)
|
|
|
910
1054
|
sections.push(`# Site URL (used by GoTrue for email redirects)
|
|
911
1055
|
SITE_URL=http://localhost:3000`)
|
|
912
1056
|
|
|
1057
|
+
if (opts.provider === "docker" && opts.kongPort !== undefined) {
|
|
1058
|
+
const apiUrl = `http://localhost:${opts.kongPort}`
|
|
1059
|
+
sections.push(
|
|
1060
|
+
`# Local API gateway (Kong) — unique per project so multiple stacks can run concurrently
|
|
1061
|
+
SUPATYPE_KONG_PORT=${opts.kongPort}
|
|
1062
|
+
PUBLIC_SUPATYPE_URL=${apiUrl}
|
|
1063
|
+
API_EXTERNAL_URL=${apiUrl}`,
|
|
1064
|
+
)
|
|
1065
|
+
}
|
|
1066
|
+
|
|
913
1067
|
sections.push(emailEnvSection(opts.email, opts.projectName))
|
|
914
1068
|
sections.push(storageEnvSections(opts.storageLocal, opts.storageProduction))
|
|
915
1069
|
|
|
1070
|
+
if (opts.adminEmail && opts.adminPassword) {
|
|
1071
|
+
sections.push(
|
|
1072
|
+
`# First admin for /admin — consumed on first supatype dev or push (password removed after use)
|
|
1073
|
+
SUPATYPE_ADMIN_EMAIL=${opts.adminEmail}
|
|
1074
|
+
SUPATYPE_ADMIN_PASSWORD=${opts.adminPassword}`,
|
|
1075
|
+
)
|
|
1076
|
+
}
|
|
1077
|
+
|
|
916
1078
|
sections.push(
|
|
917
1079
|
`# Self-host compose uses the same DATABASE_URL when Postgres is published on localhost:5432`,
|
|
918
1080
|
)
|
|
@@ -1100,14 +1262,23 @@ function printNextSteps(args: {
|
|
|
1100
1262
|
result: WizardResult
|
|
1101
1263
|
installed: boolean
|
|
1102
1264
|
keysGenerated: boolean
|
|
1265
|
+
binariesReady: boolean
|
|
1103
1266
|
}): void {
|
|
1104
|
-
const { name, result, installed, keysGenerated } = args
|
|
1267
|
+
const { name, result, installed, keysGenerated, binariesReady } = args
|
|
1105
1268
|
const steps: string[] = []
|
|
1106
1269
|
if (name) steps.push(`cd ${name}`)
|
|
1107
1270
|
if (!installed) steps.push(`${result.packageManager} install`)
|
|
1271
|
+
if (!binariesReady) steps.push("supatype update # download component binaries")
|
|
1108
1272
|
if (!keysGenerated) steps.push("supatype keys")
|
|
1109
|
-
|
|
1273
|
+
const kongHint =
|
|
1274
|
+
result.provider === "docker" && result.kongPort !== undefined
|
|
1275
|
+
? `supatype dev # Docker Compose stack (Kong :${result.kongPort})`
|
|
1276
|
+
: "supatype dev # Docker Compose stack (Kong :18473)"
|
|
1277
|
+
steps.push(kongHint)
|
|
1110
1278
|
steps.push("supatype push # apply schema + generate types")
|
|
1279
|
+
if (result.adminEmail) {
|
|
1280
|
+
steps.push(" # first admin user is created on dev or push")
|
|
1281
|
+
}
|
|
1111
1282
|
if (result.helloFunction) {
|
|
1112
1283
|
steps.push("supatype functions serve # run edge functions locally")
|
|
1113
1284
|
}
|
|
@@ -12,7 +12,7 @@ import { targetFetch } from "../target-client.js"
|
|
|
12
12
|
import { error, info, plain } from "../ui/messages.js"
|
|
13
13
|
import { nextSteps } from "../ui/next-steps.js"
|
|
14
14
|
import { isInteractive } from "../ui/interactive.js"
|
|
15
|
-
import { ensureNotCancelled,
|
|
15
|
+
import { ensureNotCancelled, p, runClackFlow } from "../ui/prompts.js"
|
|
16
16
|
|
|
17
17
|
function resolveLinkToken(opts: {
|
|
18
18
|
token?: string
|
|
@@ -145,35 +145,36 @@ export async function runLinkAction(opts: {
|
|
|
145
145
|
let url = opts.url
|
|
146
146
|
|
|
147
147
|
if (isInteractive() && !project && !url) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}),
|
|
158
|
-
)
|
|
159
|
-
if (targetKind === "cloud") {
|
|
160
|
-
project = ensureNotCancelled(
|
|
161
|
-
await p.text({
|
|
162
|
-
message: "Cloud project slug",
|
|
163
|
-
placeholder: projectRef,
|
|
164
|
-
defaultValue: projectRef,
|
|
148
|
+
await runClackFlow(async () => {
|
|
149
|
+
p.intro("Link this project")
|
|
150
|
+
const targetKind = ensureNotCancelled(
|
|
151
|
+
await p.select<"cloud" | "self-host">({
|
|
152
|
+
message: "Link target",
|
|
153
|
+
options: [
|
|
154
|
+
{ value: "cloud", label: "Supatype Cloud", hint: "managed project on supatype.com" },
|
|
155
|
+
{ value: "self-host", label: "Self-host", hint: "your Kong gateway URL" },
|
|
156
|
+
],
|
|
165
157
|
}),
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
158
|
+
)
|
|
159
|
+
if (targetKind === "cloud") {
|
|
160
|
+
project = ensureNotCancelled(
|
|
161
|
+
await p.text({
|
|
162
|
+
message: "Cloud project slug",
|
|
163
|
+
placeholder: projectRef,
|
|
164
|
+
defaultValue: projectRef,
|
|
165
|
+
}),
|
|
166
|
+
).trim()
|
|
167
|
+
} else {
|
|
168
|
+
url = ensureNotCancelled(
|
|
169
|
+
await p.text({
|
|
170
|
+
message: "Kong gateway URL",
|
|
171
|
+
placeholder: "https://api.example.com",
|
|
172
|
+
defaultValue: "http://localhost:18473",
|
|
173
|
+
}),
|
|
174
|
+
).trim()
|
|
175
|
+
}
|
|
176
|
+
p.outro("Linking...")
|
|
177
|
+
})
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
const token = resolveLinkToken(opts)
|
package/src/commands/push.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { printDiffOperations, printDiffWarnings } from "../diff-output.js"
|
|
|
8
8
|
import { signJwt } from "../jwt.js"
|
|
9
9
|
import { provisionBucketsFromAst } from "../storage-provision.js"
|
|
10
10
|
import type { ExtractedSchemaAstV2 } from "../schema-ast-v2.js"
|
|
11
|
-
import {
|
|
11
|
+
import { ensureFirstAdminUser } from "./admin.js"
|
|
12
12
|
import { withAdminRoles } from "../studio-admin-roles.js"
|
|
13
13
|
import { restoreSystemRelationTargets } from "../restore-system-relation-targets.js"
|
|
14
14
|
import type { SupatypeProjectConfig } from "../project-config.js"
|
|
@@ -145,8 +145,8 @@ async function pushViaTarget(
|
|
|
145
145
|
|
|
146
146
|
if (target.mode === "direct" || target.mode === "local") {
|
|
147
147
|
await writeLocalAdminConfig(ast, config)
|
|
148
|
-
if (
|
|
149
|
-
await
|
|
148
|
+
if (target.databaseUrl) {
|
|
149
|
+
await ensureFirstAdminUser(target.databaseUrl, { cwd })
|
|
150
150
|
}
|
|
151
151
|
await generateTypesLocal(ast, config)
|
|
152
152
|
await provisionLocalStorage(ast, config)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { existsSync } from "node:fs"
|
|
2
|
+
import { dirname, isAbsolute, join, resolve } from "node:path"
|
|
3
|
+
import { spawnSync } from "node:child_process"
|
|
4
|
+
import { VERSION_PIN_LOCAL } from "./binary-cache.js"
|
|
5
|
+
import { appendStackOutput, getActiveDevSession } from "./dev-session.js"
|
|
6
|
+
import { requireDockerDaemon } from "./docker-runtime.js"
|
|
7
|
+
import type { SupatypeProjectConfig } from "./project-config.js"
|
|
8
|
+
|
|
9
|
+
/** Docker tag for compose dev when `versions.server` is `local`. */
|
|
10
|
+
export const LOCAL_SERVER_DOCKER_IMAGE = "supatype/server:local-dev"
|
|
11
|
+
|
|
12
|
+
/** Find the server repo root (directory containing `Dockerfile`) from an overrides.server binary path. */
|
|
13
|
+
export function resolveServerSourceRoot(serverOverride: string, cwd: string): string | null {
|
|
14
|
+
const binaryPath = isAbsolute(serverOverride) ? serverOverride : resolve(cwd, serverOverride)
|
|
15
|
+
let dir = dirname(binaryPath)
|
|
16
|
+
for (let depth = 0; depth < 5; depth++) {
|
|
17
|
+
if (existsSync(join(dir, "Dockerfile"))) return dir
|
|
18
|
+
const parent = dirname(dir)
|
|
19
|
+
if (parent === dir) break
|
|
20
|
+
dir = parent
|
|
21
|
+
}
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* When `versions.server` is `local`, build a Linux server image from the source tree
|
|
27
|
+
* next to `overrides.server` so compose dev matches the contributor's binary.
|
|
28
|
+
*/
|
|
29
|
+
export async function ensureLocalServerDockerImage(
|
|
30
|
+
cwd: string,
|
|
31
|
+
config: SupatypeProjectConfig,
|
|
32
|
+
brand?: { intro?: string },
|
|
33
|
+
): Promise<string | undefined> {
|
|
34
|
+
if (config.versions?.server !== VERSION_PIN_LOCAL) return undefined
|
|
35
|
+
|
|
36
|
+
const override = config.overrides?.server?.trim()
|
|
37
|
+
if (!override) return undefined
|
|
38
|
+
|
|
39
|
+
const root = resolveServerSourceRoot(override, cwd)
|
|
40
|
+
if (!root) {
|
|
41
|
+
console.warn(
|
|
42
|
+
`[supatype] ⚠ versions.server is "local" but no Dockerfile found near ${override}. ` +
|
|
43
|
+
"Compose will use the default supatype/server:latest image.",
|
|
44
|
+
)
|
|
45
|
+
return undefined
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
requireDockerDaemon(brand?.intro ? { brand: { intro: brand.intro } } : undefined)
|
|
49
|
+
const dockerfile = join(root, "Dockerfile")
|
|
50
|
+
console.log(`[supatype] Building local server Docker image from ${root}…`)
|
|
51
|
+
const result = spawnSync(
|
|
52
|
+
"docker",
|
|
53
|
+
["build", "--progress=plain", "-t", LOCAL_SERVER_DOCKER_IMAGE, "-f", dockerfile, root],
|
|
54
|
+
{ encoding: "utf8", stdio: "pipe" },
|
|
55
|
+
)
|
|
56
|
+
const tui = getActiveDevSession()?.isTui() ?? false
|
|
57
|
+
if (!tui) {
|
|
58
|
+
appendStackOutput(result.stdout, "log")
|
|
59
|
+
appendStackOutput(result.stderr, result.status === 0 ? "log" : "error")
|
|
60
|
+
} else if (result.status !== 0) {
|
|
61
|
+
appendStackOutput(result.stderr || result.stdout || "docker build failed", "error")
|
|
62
|
+
}
|
|
63
|
+
if (result.status !== 0) {
|
|
64
|
+
throw new Error(`docker build failed for local server (exit ${result.status ?? "unknown"})`)
|
|
65
|
+
}
|
|
66
|
+
console.log(`[supatype] Local server image ready: ${LOCAL_SERVER_DOCKER_IMAGE}`)
|
|
67
|
+
return LOCAL_SERVER_DOCKER_IMAGE
|
|
68
|
+
}
|