@supatype/cli 0.1.1 → 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 +114 -90
- 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.map +1 -1
- package/dist/commands/admin.js +22 -6
- 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 +238 -168
- 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/dev-compose.d.ts.map +1 -1
- package/dist/dev-compose.js +111 -54
- 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.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 +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.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/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 +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 +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 +24 -6
- package/src/commands/cache.ts +105 -5
- package/src/commands/dev.ts +26 -21
- package/src/commands/init.ts +124 -45
- 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/dev-compose.ts +136 -51
- package/src/dev-log-bus.ts +18 -0
- package/src/dev-log-filter.ts +42 -0
- package/src/dev-ports.ts +22 -11
- package/src/dev-ready-panel.ts +63 -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/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 +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/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-ready-panel.test.ts +20 -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.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
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin REST cache API client for CLI commands.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { readEnvValue } from "./env-file.js"
|
|
6
|
+
import { resolveProjectApiUrl } from "./resolve-api-url.js"
|
|
7
|
+
|
|
8
|
+
export interface RestCacheEntrySummary {
|
|
9
|
+
key: string
|
|
10
|
+
table?: string
|
|
11
|
+
scope?: string
|
|
12
|
+
method?: string
|
|
13
|
+
path?: string
|
|
14
|
+
raw_query?: string
|
|
15
|
+
ttl_seconds: number
|
|
16
|
+
size_bytes: number
|
|
17
|
+
cached_at?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface RestCacheListResponse {
|
|
21
|
+
entries: RestCacheEntrySummary[]
|
|
22
|
+
cursor: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface RestCacheDetail extends RestCacheEntrySummary {
|
|
26
|
+
status_code: number
|
|
27
|
+
content_type?: string
|
|
28
|
+
body_preview?: string
|
|
29
|
+
body_json?: unknown
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function serviceRoleKey(cwd: string): string {
|
|
33
|
+
const key =
|
|
34
|
+
readEnvValue(cwd, "SUPATYPE_SERVICE_ROLE_KEY", "").trim() ||
|
|
35
|
+
readEnvValue(cwd, "SERVICE_ROLE_KEY", "").trim()
|
|
36
|
+
if (!key) {
|
|
37
|
+
throw new Error("SERVICE_ROLE_KEY not found in .env — run supatype dev or supatype keys")
|
|
38
|
+
}
|
|
39
|
+
return key.trim()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function adminHeaders(cwd: string): Record<string, string> {
|
|
43
|
+
const key = serviceRoleKey(cwd)
|
|
44
|
+
return {
|
|
45
|
+
Authorization: `Bearer ${key}`,
|
|
46
|
+
apikey: key,
|
|
47
|
+
"Content-Type": "application/json",
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function formatCacheApiError(
|
|
52
|
+
operation: string,
|
|
53
|
+
status: number,
|
|
54
|
+
body: string,
|
|
55
|
+
baseUrl: string,
|
|
56
|
+
): string {
|
|
57
|
+
const trimmed = body.trim()
|
|
58
|
+
if (status === 404) {
|
|
59
|
+
return (
|
|
60
|
+
`${operation} failed (404): ${trimmed || "not found"}\n` +
|
|
61
|
+
` API: ${baseUrl}/admin/v1/cache\n` +
|
|
62
|
+
" Start the stack with `supatype dev`, or check SUPATYPE_URL / PUBLIC_SUPATYPE_URL in .env."
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
if (status === 403 && trimmed.includes("rest_cache_not_available")) {
|
|
66
|
+
return "REST server cache is not available on this plan or deployment."
|
|
67
|
+
}
|
|
68
|
+
if (status === 503 && trimmed.includes("valkey")) {
|
|
69
|
+
return "Valkey is not configured — server-side REST cache requires Valkey (supatype dev with docker)."
|
|
70
|
+
}
|
|
71
|
+
return `${operation} failed (${status}): ${trimmed || "(empty body)"}`
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function normalizeListResponse(data: RestCacheListResponse): RestCacheListResponse {
|
|
75
|
+
return {
|
|
76
|
+
entries: data.entries ?? [],
|
|
77
|
+
cursor: data.cursor ?? "0",
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function listRestCacheEntries(
|
|
82
|
+
cwd: string,
|
|
83
|
+
opts?: { table?: string | undefined; cursor?: string | undefined; limit?: number | undefined },
|
|
84
|
+
): Promise<RestCacheListResponse> {
|
|
85
|
+
const baseUrl = resolveProjectApiUrl(cwd)
|
|
86
|
+
const params = new URLSearchParams()
|
|
87
|
+
if (opts?.table) params.set("table", opts.table)
|
|
88
|
+
if (opts?.cursor) params.set("cursor", opts.cursor)
|
|
89
|
+
if (opts?.limit !== undefined) params.set("limit", String(opts.limit))
|
|
90
|
+
const qs = params.toString()
|
|
91
|
+
const url = `${baseUrl}/admin/v1/cache${qs ? `?${qs}` : ""}`
|
|
92
|
+
const res = await fetch(url, { headers: adminHeaders(cwd) })
|
|
93
|
+
if (!res.ok) {
|
|
94
|
+
const body = await res.text()
|
|
95
|
+
throw new Error(formatCacheApiError("list cache", res.status, body, baseUrl))
|
|
96
|
+
}
|
|
97
|
+
const data = (await res.json()) as RestCacheListResponse
|
|
98
|
+
return normalizeListResponse(data)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function getRestCacheEntry(cwd: string, key: string): Promise<RestCacheDetail> {
|
|
102
|
+
const baseUrl = resolveProjectApiUrl(cwd)
|
|
103
|
+
const enc = Buffer.from(key, "utf8").toString("base64url")
|
|
104
|
+
const url = `${baseUrl}/admin/v1/cache/entries/${encodeURIComponent(enc)}`
|
|
105
|
+
const res = await fetch(url, { headers: adminHeaders(cwd) })
|
|
106
|
+
if (!res.ok) {
|
|
107
|
+
const body = await res.text()
|
|
108
|
+
throw new Error(formatCacheApiError("get cache entry", res.status, body, baseUrl))
|
|
109
|
+
}
|
|
110
|
+
return res.json() as Promise<RestCacheDetail>
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export async function deleteRestCacheEntry(cwd: string, key: string): Promise<void> {
|
|
114
|
+
const baseUrl = resolveProjectApiUrl(cwd)
|
|
115
|
+
const enc = Buffer.from(key, "utf8").toString("base64url")
|
|
116
|
+
const url = `${baseUrl}/admin/v1/cache/entries/${encodeURIComponent(enc)}`
|
|
117
|
+
const res = await fetch(url, { method: "DELETE", headers: adminHeaders(cwd) })
|
|
118
|
+
if (!res.ok) {
|
|
119
|
+
const body = await res.text()
|
|
120
|
+
throw new Error(formatCacheApiError("delete cache entry", res.status, body, baseUrl))
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function flushRestCache(cwd: string, table?: string): Promise<void> {
|
|
125
|
+
const baseUrl = resolveProjectApiUrl(cwd)
|
|
126
|
+
const params = new URLSearchParams()
|
|
127
|
+
if (table) params.set("table", table)
|
|
128
|
+
const qs = params.toString()
|
|
129
|
+
const url = `${baseUrl}/admin/v1/cache${qs ? `?${qs}` : ""}`
|
|
130
|
+
const res = await fetch(url, { method: "DELETE", headers: adminHeaders(cwd) })
|
|
131
|
+
if (!res.ok) {
|
|
132
|
+
const body = await res.text()
|
|
133
|
+
throw new Error(formatCacheApiError("flush cache", res.status, body, baseUrl))
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -1,57 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Postinstall script —
|
|
2
|
+
* Postinstall script — @supatype/cli global/project install.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Failures are non-fatal: an installation message is printed and the user
|
|
8
|
-
* can run `supatype update` manually to retry.
|
|
4
|
+
* Host binaries (engine, server, postgres, deno) are downloaded on demand:
|
|
5
|
+
* - native provider: first supatype dev / supatype update
|
|
6
|
+
* - docker provider: Compose images on first supatype dev
|
|
9
7
|
*/
|
|
10
8
|
|
|
11
|
-
import { download, currentPlatform, fetchAllLatestVersions, type Component } from "../binary-cache.js"
|
|
12
|
-
|
|
13
9
|
async function main() {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
versions = await fetchAllLatestVersions()
|
|
20
|
-
} catch (err) {
|
|
21
|
-
console.error(`[supatype] Failed to fetch latest versions: ${(err as Error).message}`)
|
|
22
|
-
console.error("[supatype] Run 'supatype update' to download component binaries.")
|
|
23
|
-
return
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
console.log(`[supatype] Downloading component binaries for ${platform.os}/${platform.arch}...`)
|
|
27
|
-
|
|
28
|
-
const components = Object.entries(versions) as [Component, string][]
|
|
29
|
-
|
|
30
|
-
let anyFailed = false
|
|
31
|
-
for (const [component, version] of components) {
|
|
32
|
-
try {
|
|
33
|
-
await download(component, version, platform)
|
|
34
|
-
} catch (err) {
|
|
35
|
-
console.error(`[supatype] Failed to download ${component} v${version}: ${(err as Error).message}`)
|
|
36
|
-
anyFailed = true
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (anyFailed) {
|
|
41
|
-
// npm hides postinstall output unless --foreground-scripts, so don't rely on
|
|
42
|
-
// this being seen: the CLI re-attempts the download (with retry) on first use.
|
|
43
|
-
console.error(
|
|
44
|
-
"[supatype] Some component binaries failed to download. " +
|
|
45
|
-
"They will be re-downloaded automatically on first use; " +
|
|
46
|
-
"run 'supatype update' to retry now.",
|
|
47
|
-
)
|
|
48
|
-
} else {
|
|
49
|
-
console.log("[supatype] All component binaries downloaded successfully.")
|
|
50
|
-
}
|
|
10
|
+
console.log(
|
|
11
|
+
"[supatype] CLI installed. " +
|
|
12
|
+
"Runtime components download automatically on first use " +
|
|
13
|
+
"(supatype dev or supatype update).",
|
|
14
|
+
)
|
|
51
15
|
}
|
|
52
16
|
|
|
53
17
|
main().catch((err) => {
|
|
54
|
-
// Non-fatal — postinstall failures should not break npm install.
|
|
55
18
|
console.error("[supatype] Postinstall failed:", err)
|
|
56
19
|
process.exit(0)
|
|
57
20
|
})
|
package/src/self-host-compose.ts
CHANGED
|
@@ -292,9 +292,7 @@ ${studioService}
|
|
|
292
292
|
? ` - "80:8000"
|
|
293
293
|
- "443:8443"`
|
|
294
294
|
: ` - "\${SUPATYPE_KONG_PORT:-18473}:8000"`
|
|
295
|
-
const
|
|
296
|
-
const valkeyBlock = tlsEnabled
|
|
297
|
-
? `
|
|
295
|
+
const valkeyBlock = `
|
|
298
296
|
valkey:
|
|
299
297
|
image: \${SUPATYPE_VALKEY_IMAGE:-valkey/valkey:8-alpine}
|
|
300
298
|
command: ["valkey-server", "--appendonly", "yes"]
|
|
@@ -303,23 +301,18 @@ ${studioService}
|
|
|
303
301
|
volumes:
|
|
304
302
|
- valkey-data:/data
|
|
305
303
|
`
|
|
306
|
-
|
|
304
|
+
const kongValkeyDepends = "\n - valkey"
|
|
307
305
|
const tlsHintComment = tlsEnabled
|
|
308
306
|
? ""
|
|
309
307
|
: ` # HTTPS is off. To enable automatic TLS (Let's Encrypt) for production, set in supatype.config.ts:
|
|
310
308
|
# server: { mode: "standalone", domain: "your.domain", tls: { email: "you@example.com" } }
|
|
311
309
|
# then re-run \`supatype self-host compose up -d\`. Kong publishes :80/:443 and provisions certs automatically.
|
|
312
310
|
`
|
|
313
|
-
const volumesBlock =
|
|
314
|
-
? `volumes:
|
|
311
|
+
const volumesBlock = `volumes:
|
|
315
312
|
db-data:
|
|
316
313
|
minio-data:
|
|
317
314
|
valkey-data:
|
|
318
315
|
`
|
|
319
|
-
: `volumes:
|
|
320
|
-
db-data:
|
|
321
|
-
minio-data:
|
|
322
|
-
`
|
|
323
316
|
|
|
324
317
|
return `# Generated by supatype self-host compose
|
|
325
318
|
# Kong → supatype-server (unified gateway) → internal PostgREST / storage / etc.
|
|
@@ -431,6 +424,7 @@ ${serverPorts} volumes:
|
|
|
431
424
|
SUPATYPE_DENO_FUNCTIONS_DIR: /project/functions
|
|
432
425
|
SUPATYPE_FUNCTIONS_WORKER_URL: http://functions-worker:8001
|
|
433
426
|
SUPATYPE_CONTROL_PLANE_URL: http://control-plane:8080
|
|
427
|
+
SUPATYPE_VALKEY_ADDR: valkey:6379
|
|
434
428
|
${appEnv}
|
|
435
429
|
GOTRUE_API_HOST: 0.0.0.0
|
|
436
430
|
GOTRUE_API_PORT: 9999
|
|
@@ -450,6 +444,8 @@ ${devLocal ? " STUDIO_OPEN_DEV: \"1\"\n" : ""}
|
|
|
450
444
|
depends_on:
|
|
451
445
|
db:
|
|
452
446
|
condition: service_healthy
|
|
447
|
+
valkey:
|
|
448
|
+
condition: service_started
|
|
453
449
|
postgrest:
|
|
454
450
|
condition: service_started
|
|
455
451
|
storage:
|
|
@@ -492,7 +488,7 @@ ${kongTlsEnv} volumes:
|
|
|
492
488
|
ports:
|
|
493
489
|
${kongPorts}
|
|
494
490
|
depends_on:
|
|
495
|
-
${kongDependsOn}${
|
|
491
|
+
${kongDependsOn}${kongValkeyDepends}
|
|
496
492
|
|
|
497
493
|
${volumesBlock}`
|
|
498
494
|
}
|
|
@@ -594,7 +590,21 @@ export function runDockerCompose(
|
|
|
594
590
|
? { ...process.env, COMPOSE_PROGRESS: "quiet" }
|
|
595
591
|
: process.env
|
|
596
592
|
const stdio = options?.quiet ? "pipe" : "inherit"
|
|
597
|
-
const result = spawnSync("docker", composeArgs, {
|
|
593
|
+
const result = spawnSync("docker", composeArgs, {
|
|
594
|
+
stdio,
|
|
595
|
+
cwd: projectRoot,
|
|
596
|
+
env,
|
|
597
|
+
...(options?.quiet ? { encoding: "utf8" as const } : {}),
|
|
598
|
+
})
|
|
599
|
+
if (options?.quiet && result.status !== 0) {
|
|
600
|
+
const detail = [result.stderr, result.stdout]
|
|
601
|
+
.filter((s): s is string => typeof s === "string" && s.trim() !== "")
|
|
602
|
+
.join("\n")
|
|
603
|
+
.trim()
|
|
604
|
+
if (detail) {
|
|
605
|
+
console.error(`[supatype] docker compose: ${detail}`)
|
|
606
|
+
}
|
|
607
|
+
}
|
|
598
608
|
return result.status ?? 1
|
|
599
609
|
}
|
|
600
610
|
|
package/src/studio-dev-server.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { existsSync } from "node:fs"
|
|
|
2
2
|
import { join, resolve } from "node:path"
|
|
3
3
|
import { ProcessManager } from "./process-manager.js"
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/** Vite dev server port when `overrides.studio` is set. */
|
|
6
|
+
export const STUDIO_DEV_PORT = 3002
|
|
6
7
|
|
|
7
8
|
export interface StudioDevServerOptions {
|
|
8
9
|
cwd: string
|
|
@@ -15,8 +16,8 @@ export interface StudioDevServerOptions {
|
|
|
15
16
|
*/
|
|
16
17
|
proxyTarget: string
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
19
|
+
* Browser API base URL. Must match the Vite dev origin (`http://localhost:3002`)
|
|
20
|
+
* so fetches hit the Vite proxy (SUPATYPE_PROXY_TARGET) and avoid CORS.
|
|
20
21
|
*/
|
|
21
22
|
viteSupatypeUrl: string
|
|
22
23
|
/** Vite `base` — `/studio/` when behind Kong at `/studio/`; `/` for native dev on :3002. */
|
|
@@ -35,7 +36,7 @@ export function startStudioViteDevServer(opts: StudioDevServerOptions): ProcessM
|
|
|
35
36
|
const basePath = opts.basePath ?? "/"
|
|
36
37
|
return new ProcessManager(
|
|
37
38
|
process.execPath,
|
|
38
|
-
[viteJs, "--port", String(
|
|
39
|
+
[viteJs, "--port", String(STUDIO_DEV_PORT), "--strictPort", "--host"],
|
|
39
40
|
{
|
|
40
41
|
label: "studio",
|
|
41
42
|
pidDir: opts.pidDir,
|
package/src/ui/README.md
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
# CLI terminal UI (`packages/cli/src/ui/`)
|
|
2
2
|
|
|
3
|
-
Shared
|
|
3
|
+
Shared Ink-based design system for the Supatype CLI.
|
|
4
4
|
|
|
5
5
|
| Module | Use for |
|
|
6
6
|
|--------|---------|
|
|
7
|
-
| `
|
|
8
|
-
| `
|
|
9
|
-
| `
|
|
10
|
-
| `
|
|
11
|
-
| `
|
|
7
|
+
| `theme.ts` | Brand + semantic colours (Ink + plain ANSI) |
|
|
8
|
+
| `messages.ts` | `info` / `warn` / `error` / `success`, `file`, `step`, `plain` |
|
|
9
|
+
| `fatal.ts` | `fatalError`, `reportCliFatal` |
|
|
10
|
+
| `confirm.ts` | Yes/no prompts (Ink overlay in dev, Ink flow in TTY) |
|
|
11
|
+
| `progress.ts` | `withSpinner` + `runCommandChrome` for one-shot commands |
|
|
12
|
+
| `runtime/command-chrome.ts` | Ink shell (logo, logs, spinner) — applied globally via `wrapProgramActionsWithChrome` in `cli.ts` |
|
|
13
|
+
| `prompts.ts` | Logo, `promptText`, `promptPassword`, `ensureNotCancelled` |
|
|
14
|
+
| `clack.ts` | Clack-compatible `p.*` API + `runClackFlow()` for wizards |
|
|
15
|
+
| `flows/` | Ink flow shell + prompt fields |
|
|
16
|
+
| `dev/DevDashboard.tsx` | `supatype dev` task list + log pane + prompt overlay |
|
|
12
17
|
| `next-steps.ts` | Bulleted follow-up commands |
|
|
13
|
-
| `brand.ts` | ANSI colours + logo styling (shared with dev TUI) |
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
**Convention:** interactive wizards use `runClackFlow(async (p) => …)` (`init`, `link`, `add domain`); one-shot commands get branded chrome automatically in `cli.ts` via `wrapProgramActionsWithChrome`. **`supatype dev`** keeps a persistent Ink dashboard (excluded from auto-wrap).
|
|
16
20
|
|
|
17
|
-
**
|
|
21
|
+
**Plain profile:** when `!isInteractive()` (CI, pipes), helpers fall back to `[supatype]`-prefixed lines.
|
package/src/ui/brand.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared ANSI styling for Supatype CLI output and the dev TUI.
|
|
3
|
+
* @deprecated Prefer `theme.ts` for new code — re-exports kept for dev-logo / task colors.
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
|
-
export
|
|
6
|
-
export const DIM = "\x1b[2m"
|
|
7
|
-
export const BOLD = "\x1b[1m"
|
|
8
|
-
export const BRAND_COLOR = "\x1b[35m"
|
|
9
|
-
|
|
10
|
-
export function brandStyle(text: string): string {
|
|
11
|
-
return `${BRAND_COLOR}${BOLD}${text}${RESET}`
|
|
12
|
-
}
|
|
6
|
+
export { BOLD, BRAND_COLOR, brandStyle, DIM, RESET } from "./theme.js"
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { FlowController } from "./flows/types.js"
|
|
2
|
+
import type { DevSelectOption } from "./runtime/dev-prompt-queue.js"
|
|
3
|
+
import { CLACK_CANCEL } from "./runtime/cancel.js"
|
|
4
|
+
|
|
5
|
+
export interface ClackTextOptions {
|
|
6
|
+
message: string
|
|
7
|
+
defaultValue?: string
|
|
8
|
+
placeholder?: string
|
|
9
|
+
validate?: (value: string) => string | undefined
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ClackSelectOptions<T extends string = string> {
|
|
13
|
+
message: string
|
|
14
|
+
options: DevSelectOption<T>[]
|
|
15
|
+
initialValue?: T
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ClackConfirmOptions {
|
|
19
|
+
message: string
|
|
20
|
+
initialValue?: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ClackPasswordOptions {
|
|
24
|
+
message: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ClackSpinner {
|
|
28
|
+
start(message: string): void
|
|
29
|
+
stop(message: string): void
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ClackApi {
|
|
33
|
+
intro(message: string): void
|
|
34
|
+
outro(message: string): void
|
|
35
|
+
note(message: string): void
|
|
36
|
+
cancel(message: string): never
|
|
37
|
+
text(options: ClackTextOptions): Promise<string | typeof CLACK_CANCEL>
|
|
38
|
+
password(options: ClackPasswordOptions): Promise<string | typeof CLACK_CANCEL>
|
|
39
|
+
select<T extends string>(options: ClackSelectOptions<T>): Promise<T | typeof CLACK_CANCEL>
|
|
40
|
+
confirm(options: ClackConfirmOptions): Promise<boolean | typeof CLACK_CANCEL>
|
|
41
|
+
spinner(): ClackSpinner
|
|
42
|
+
log: {
|
|
43
|
+
info(message: string): void
|
|
44
|
+
warn(message: string): void
|
|
45
|
+
error(message: string): void
|
|
46
|
+
success(message: string): void
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function createClackApi(controller: FlowController): ClackApi {
|
|
51
|
+
return {
|
|
52
|
+
intro(message) {
|
|
53
|
+
controller.appendLog("plain", message)
|
|
54
|
+
},
|
|
55
|
+
outro(message) {
|
|
56
|
+
controller.appendLog("success", message)
|
|
57
|
+
},
|
|
58
|
+
note(message) {
|
|
59
|
+
for (const line of message.split("\n")) {
|
|
60
|
+
if (line.trim()) controller.appendPlain(line)
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
cancel(message): never {
|
|
64
|
+
controller.appendLog("warn", message)
|
|
65
|
+
process.exit(0)
|
|
66
|
+
},
|
|
67
|
+
async text(options) {
|
|
68
|
+
return controller.waitForPrompt<string>({
|
|
69
|
+
kind: "text",
|
|
70
|
+
message: options.message,
|
|
71
|
+
...(options.defaultValue !== undefined ? { defaultValue: options.defaultValue } : {}),
|
|
72
|
+
...(options.placeholder !== undefined ? { placeholder: options.placeholder } : {}),
|
|
73
|
+
...(options.validate !== undefined ? { validate: options.validate } : {}),
|
|
74
|
+
})
|
|
75
|
+
},
|
|
76
|
+
async password(options) {
|
|
77
|
+
return controller.waitForPrompt<string>({
|
|
78
|
+
kind: "password",
|
|
79
|
+
message: options.message,
|
|
80
|
+
})
|
|
81
|
+
},
|
|
82
|
+
async select<T extends string>(options: ClackSelectOptions<T>) {
|
|
83
|
+
return controller.waitForPrompt<T>({
|
|
84
|
+
kind: "select",
|
|
85
|
+
message: options.message,
|
|
86
|
+
options: options.options,
|
|
87
|
+
...(options.initialValue !== undefined ? { initialValue: options.initialValue } : {}),
|
|
88
|
+
})
|
|
89
|
+
},
|
|
90
|
+
async confirm(options) {
|
|
91
|
+
return controller.waitForPrompt<boolean>({
|
|
92
|
+
kind: "confirm",
|
|
93
|
+
message: options.message,
|
|
94
|
+
initialValue: options.initialValue ?? false,
|
|
95
|
+
})
|
|
96
|
+
},
|
|
97
|
+
spinner() {
|
|
98
|
+
return {
|
|
99
|
+
start(message: string) {
|
|
100
|
+
controller.setSpinner(message)
|
|
101
|
+
},
|
|
102
|
+
stop(message: string) {
|
|
103
|
+
controller.setSpinner(null)
|
|
104
|
+
controller.appendLog("success", message)
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
log: {
|
|
109
|
+
info(message) {
|
|
110
|
+
controller.appendLog("info", message)
|
|
111
|
+
},
|
|
112
|
+
warn(message) {
|
|
113
|
+
controller.appendLog("warn", message)
|
|
114
|
+
},
|
|
115
|
+
error(message) {
|
|
116
|
+
controller.appendLog("error", message)
|
|
117
|
+
},
|
|
118
|
+
success(message) {
|
|
119
|
+
controller.appendLog("success", message)
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
}
|
package/src/ui/clack.ts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clack-compatible prompt API backed by Ink.
|
|
3
|
+
* Use inside `runClackFlow()` for multi-step wizards, or via `confirm()` / `promptText()` helpers.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { getActiveDevSession } from "../dev-session.js"
|
|
7
|
+
import { createClackApi, type ClackApi } from "./clack-api.js"
|
|
8
|
+
import { isInteractive } from "./interactive.js"
|
|
9
|
+
import { CLACK_CANCEL, isCancel } from "./runtime/cancel.js"
|
|
10
|
+
import { enqueueDevPrompt } from "./runtime/dev-prompt-queue.js"
|
|
11
|
+
import { runClackFlow as mountClackFlow } from "./runtime/run-clack-flow.js"
|
|
12
|
+
import type { DevSelectOption } from "./runtime/dev-prompt-queue.js"
|
|
13
|
+
|
|
14
|
+
export { CLACK_CANCEL, isCancel }
|
|
15
|
+
export type { ClackApi } from "./clack-api.js"
|
|
16
|
+
|
|
17
|
+
import { getActiveFlowApi, setActiveFlowApi } from "./runtime/flow-session.js"
|
|
18
|
+
|
|
19
|
+
function inDevTui(): boolean {
|
|
20
|
+
const session = getActiveDevSession()
|
|
21
|
+
return Boolean(session?.isTui() && session.isInkMounted())
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function devOrFlow<T>(
|
|
25
|
+
spec: Parameters<typeof enqueueDevPrompt>[0],
|
|
26
|
+
flowFn: (api: ClackApi) => Promise<T>,
|
|
27
|
+
): Promise<T | typeof CLACK_CANCEL> {
|
|
28
|
+
if (inDevTui()) {
|
|
29
|
+
return enqueueDevPrompt(spec) as Promise<T | typeof CLACK_CANCEL>
|
|
30
|
+
}
|
|
31
|
+
const api = getActiveFlowApi()
|
|
32
|
+
if (api) {
|
|
33
|
+
return flowFn(api)
|
|
34
|
+
}
|
|
35
|
+
return mountClackFlow(async (flowApi) => flowFn(flowApi))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function runClackFlow<T>(run: (api: ClackApi) => Promise<T>): Promise<T> {
|
|
39
|
+
return mountClackFlow(async (api) => {
|
|
40
|
+
setActiveFlowApi(api)
|
|
41
|
+
try {
|
|
42
|
+
return await run(api)
|
|
43
|
+
} finally {
|
|
44
|
+
setActiveFlowApi(null)
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { getActiveFlowApi } from "./runtime/flow-session.js"
|
|
50
|
+
|
|
51
|
+
export const p: ClackApi = {
|
|
52
|
+
intro(message) {
|
|
53
|
+
const api = getActiveFlowApi()
|
|
54
|
+
if (api) api.intro(message)
|
|
55
|
+
else console.log(`\n${message}\n`)
|
|
56
|
+
},
|
|
57
|
+
outro(message) {
|
|
58
|
+
const api = getActiveFlowApi()
|
|
59
|
+
if (api) api.outro(message)
|
|
60
|
+
else console.log(`\n${message}\n`)
|
|
61
|
+
},
|
|
62
|
+
note(message) {
|
|
63
|
+
const api = getActiveFlowApi()
|
|
64
|
+
if (api) api.note(message)
|
|
65
|
+
else {
|
|
66
|
+
for (const line of message.split("\n")) {
|
|
67
|
+
if (line.trim()) console.log(` ${line}`)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
cancel(message): never {
|
|
72
|
+
const api = getActiveFlowApi()
|
|
73
|
+
if (api) {
|
|
74
|
+
api.cancel(message)
|
|
75
|
+
}
|
|
76
|
+
console.log(message)
|
|
77
|
+
process.exit(0)
|
|
78
|
+
},
|
|
79
|
+
async text(options) {
|
|
80
|
+
return devOrFlow(
|
|
81
|
+
{
|
|
82
|
+
kind: "text",
|
|
83
|
+
message: options.message,
|
|
84
|
+
...(options.defaultValue !== undefined ? { defaultValue: options.defaultValue } : {}),
|
|
85
|
+
...(options.placeholder !== undefined ? { placeholder: options.placeholder } : {}),
|
|
86
|
+
...(options.validate !== undefined ? { validate: options.validate } : {}),
|
|
87
|
+
},
|
|
88
|
+
(api) => api.text(options),
|
|
89
|
+
)
|
|
90
|
+
},
|
|
91
|
+
async password(options) {
|
|
92
|
+
return devOrFlow({ kind: "password", message: options.message }, (api) => api.password(options))
|
|
93
|
+
},
|
|
94
|
+
async select<T extends string>(options: { message: string; options: DevSelectOption<T>[]; initialValue?: T }) {
|
|
95
|
+
return devOrFlow(
|
|
96
|
+
{
|
|
97
|
+
kind: "select",
|
|
98
|
+
message: options.message,
|
|
99
|
+
options: options.options,
|
|
100
|
+
...(options.initialValue !== undefined ? { initialValue: options.initialValue as string | boolean } : {}),
|
|
101
|
+
},
|
|
102
|
+
(api) => api.select(options),
|
|
103
|
+
)
|
|
104
|
+
},
|
|
105
|
+
async confirm(options) {
|
|
106
|
+
return devOrFlow(
|
|
107
|
+
{
|
|
108
|
+
kind: "confirm",
|
|
109
|
+
message: options.message,
|
|
110
|
+
initialValue: options.initialValue ?? false,
|
|
111
|
+
},
|
|
112
|
+
(api) => api.confirm(options),
|
|
113
|
+
)
|
|
114
|
+
},
|
|
115
|
+
spinner() {
|
|
116
|
+
const api = getActiveFlowApi()
|
|
117
|
+
if (api) return api.spinner()
|
|
118
|
+
return {
|
|
119
|
+
start(message: string) {
|
|
120
|
+
console.log(`${message}...`)
|
|
121
|
+
},
|
|
122
|
+
stop(message: string) {
|
|
123
|
+
console.log(message)
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
log: {
|
|
128
|
+
info(message) {
|
|
129
|
+
const api = getActiveFlowApi()
|
|
130
|
+
if (api) api.log.info(message)
|
|
131
|
+
else if (isInteractive()) console.log(message)
|
|
132
|
+
else console.log(`[supatype] ${message}`)
|
|
133
|
+
},
|
|
134
|
+
warn(message) {
|
|
135
|
+
const api = getActiveFlowApi()
|
|
136
|
+
if (api) api.log.warn(message)
|
|
137
|
+
else console.warn(`[supatype] ${message}`)
|
|
138
|
+
},
|
|
139
|
+
error(message) {
|
|
140
|
+
const api = getActiveFlowApi()
|
|
141
|
+
if (api) api.log.error(message)
|
|
142
|
+
else console.error(`[supatype] ${message}`)
|
|
143
|
+
},
|
|
144
|
+
success(message) {
|
|
145
|
+
const api = getActiveFlowApi()
|
|
146
|
+
if (api) api.log.success(message)
|
|
147
|
+
else console.log(`[supatype] ${message}`)
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** @deprecated Use `p` from this module inside `runClackFlow`. */
|
|
153
|
+
export { p as clack }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { Box, Text } from "ink"
|
|
3
|
+
import Spinner from "ink-spinner"
|
|
4
|
+
import { theme } from "../theme.js"
|
|
5
|
+
|
|
6
|
+
export function FlowSpinner({ message }: { message: string }): React.ReactElement {
|
|
7
|
+
return (
|
|
8
|
+
<Box marginBottom={1}>
|
|
9
|
+
<Text color={theme.brand}>
|
|
10
|
+
<Spinner type="dots" />
|
|
11
|
+
{` ${message}`}
|
|
12
|
+
</Text>
|
|
13
|
+
</Box>
|
|
14
|
+
)
|
|
15
|
+
}
|