@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,192 @@
|
|
|
1
|
+
import React, { useState } from "react"
|
|
2
|
+
import { Box, Text, useInput } from "ink"
|
|
3
|
+
import TextInput from "ink-text-input"
|
|
4
|
+
import { FlowSpinner } from "../components/FlowSpinner.js"
|
|
5
|
+
import { LogoWordmark } from "../components/LogoWordmark.js"
|
|
6
|
+
import { SelectField } from "../components/SelectField.js"
|
|
7
|
+
import { theme } from "../theme.js"
|
|
8
|
+
import type { ActiveFlowPrompt, FlowLogLine } from "./types.js"
|
|
9
|
+
|
|
10
|
+
const TASK_COL_WIDTH = 22
|
|
11
|
+
|
|
12
|
+
function flowLogLineProps(level: FlowLogLine["level"]): { color?: string; dimColor?: boolean } {
|
|
13
|
+
if (level === "plain") return { dimColor: true }
|
|
14
|
+
if (level === "warn") return { color: theme.warn }
|
|
15
|
+
if (level === "error") return { color: theme.error }
|
|
16
|
+
if (level === "success") return { color: theme.success }
|
|
17
|
+
return { color: theme.info }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function FlowLogoHeader(): React.ReactElement {
|
|
21
|
+
return <LogoWordmark />
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function FlowLogPane({ lines }: { lines: FlowLogLine[] }): React.ReactElement {
|
|
25
|
+
return (
|
|
26
|
+
<Box flexDirection="column" marginBottom={1}>
|
|
27
|
+
{lines.map((line, index) => (
|
|
28
|
+
<Text key={`${index}-${line.text.slice(0, 24)}`} {...flowLogLineProps(line.level)}>
|
|
29
|
+
{line.text}
|
|
30
|
+
</Text>
|
|
31
|
+
))}
|
|
32
|
+
</Box>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function FlowSpinnerLine({ message }: { message: string }): React.ReactElement {
|
|
37
|
+
return <FlowSpinner message={message} />
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface ConfirmPromptProps {
|
|
41
|
+
spec: Extract<ActiveFlowPrompt, { kind: "confirm" }>
|
|
42
|
+
onSubmit: (value: boolean) => void
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function ConfirmPrompt({ spec, onSubmit }: ConfirmPromptProps): React.ReactElement {
|
|
46
|
+
const [value, setValue] = useState(spec.initialValue)
|
|
47
|
+
|
|
48
|
+
useInput((input, key) => {
|
|
49
|
+
if (key.leftArrow || input === "h") setValue(false)
|
|
50
|
+
if (key.rightArrow || input === "l") setValue(true)
|
|
51
|
+
if (input === "y" || input === "Y") setValue(true)
|
|
52
|
+
if (input === "n" || input === "N") setValue(false)
|
|
53
|
+
if (key.return) onSubmit(value)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Box flexDirection="column">
|
|
58
|
+
<Text bold color={theme.brand}>
|
|
59
|
+
{spec.message}
|
|
60
|
+
</Text>
|
|
61
|
+
<Text>
|
|
62
|
+
{value ? (
|
|
63
|
+
<Text color={theme.success} bold>
|
|
64
|
+
Yes
|
|
65
|
+
</Text>
|
|
66
|
+
) : (
|
|
67
|
+
<Text>Yes</Text>
|
|
68
|
+
)}
|
|
69
|
+
<Text> / </Text>
|
|
70
|
+
{!value ? (
|
|
71
|
+
<Text color={theme.success} bold>
|
|
72
|
+
No
|
|
73
|
+
</Text>
|
|
74
|
+
) : (
|
|
75
|
+
<Text>No</Text>
|
|
76
|
+
)}
|
|
77
|
+
<Text dimColor> — y/n, ←/→, enter</Text>
|
|
78
|
+
</Text>
|
|
79
|
+
</Box>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface TextPromptProps {
|
|
84
|
+
spec: Extract<ActiveFlowPrompt, { kind: "text" }>
|
|
85
|
+
onSubmit: (value: string) => void
|
|
86
|
+
onCancel: () => void
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function TextPrompt({ spec, onSubmit, onCancel }: TextPromptProps): React.ReactElement {
|
|
90
|
+
const [value, setValue] = useState(spec.defaultValue ?? "")
|
|
91
|
+
const [error, setError] = useState<string | undefined>()
|
|
92
|
+
|
|
93
|
+
useInput((_input, key) => {
|
|
94
|
+
if (key.escape) onCancel()
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<Box flexDirection="column">
|
|
99
|
+
<Text bold color={theme.brand}>
|
|
100
|
+
{spec.message}
|
|
101
|
+
</Text>
|
|
102
|
+
<Box>
|
|
103
|
+
<Text color={theme.brand}>› </Text>
|
|
104
|
+
<TextInput
|
|
105
|
+
value={value}
|
|
106
|
+
{...(spec.placeholder !== undefined ? { placeholder: spec.placeholder } : {})}
|
|
107
|
+
onChange={setValue}
|
|
108
|
+
onSubmit={(submitted) => {
|
|
109
|
+
const err = spec.validate?.(submitted)
|
|
110
|
+
if (err) {
|
|
111
|
+
setError(err)
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
onSubmit(submitted)
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
</Box>
|
|
118
|
+
{error ? <Text color={theme.error}>{error}</Text> : null}
|
|
119
|
+
<Text dimColor>enter submit · esc cancel</Text>
|
|
120
|
+
</Box>
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface PasswordPromptProps {
|
|
125
|
+
spec: Extract<ActiveFlowPrompt, { kind: "password" }>
|
|
126
|
+
onSubmit: (value: string) => void
|
|
127
|
+
onCancel: () => void
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function PasswordPrompt({ spec, onSubmit, onCancel }: PasswordPromptProps): React.ReactElement {
|
|
131
|
+
const [value, setValue] = useState("")
|
|
132
|
+
|
|
133
|
+
useInput((_input, key) => {
|
|
134
|
+
if (key.escape) onCancel()
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<Box flexDirection="column">
|
|
139
|
+
<Text bold color={theme.brand}>
|
|
140
|
+
{spec.message}
|
|
141
|
+
</Text>
|
|
142
|
+
<Box>
|
|
143
|
+
<Text color={theme.brand}>› </Text>
|
|
144
|
+
<TextInput mask="*" value={value} onChange={setValue} onSubmit={onSubmit} />
|
|
145
|
+
</Box>
|
|
146
|
+
<Text dimColor>enter submit · esc cancel</Text>
|
|
147
|
+
</Box>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
interface SelectPromptProps {
|
|
152
|
+
spec: Extract<ActiveFlowPrompt, { kind: "select" }>
|
|
153
|
+
onSubmit: (value: string) => void
|
|
154
|
+
onCancel: () => void
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function SelectPrompt({ spec, onSubmit, onCancel }: SelectPromptProps): React.ReactElement {
|
|
158
|
+
return (
|
|
159
|
+
<SelectField
|
|
160
|
+
message={spec.message}
|
|
161
|
+
options={spec.options}
|
|
162
|
+
{...(spec.initialValue !== undefined ? { initialValue: spec.initialValue } : {})}
|
|
163
|
+
onSubmit={onSubmit}
|
|
164
|
+
onCancel={onCancel}
|
|
165
|
+
/>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function ActiveFlowPromptView({
|
|
170
|
+
prompt,
|
|
171
|
+
onSubmit,
|
|
172
|
+
onCancel,
|
|
173
|
+
}: {
|
|
174
|
+
prompt: ActiveFlowPrompt
|
|
175
|
+
onSubmit: (value: unknown) => void
|
|
176
|
+
onCancel: () => void
|
|
177
|
+
}): React.ReactElement {
|
|
178
|
+
switch (prompt.kind) {
|
|
179
|
+
case "confirm":
|
|
180
|
+
return <ConfirmPrompt spec={prompt} onSubmit={(v) => onSubmit(v)} />
|
|
181
|
+
case "text":
|
|
182
|
+
return <TextPrompt spec={prompt} onSubmit={(v) => onSubmit(v)} onCancel={onCancel} />
|
|
183
|
+
case "password":
|
|
184
|
+
return <PasswordPrompt spec={prompt} onSubmit={(v) => onSubmit(v)} onCancel={onCancel} />
|
|
185
|
+
case "select":
|
|
186
|
+
return <SelectPrompt spec={prompt} onSubmit={(v) => onSubmit(v)} onCancel={onCancel} />
|
|
187
|
+
default:
|
|
188
|
+
return <Text>Unsupported prompt</Text>
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export { TASK_COL_WIDTH }
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ReactNode } from "react"
|
|
2
|
+
import type { DevSelectOption } from "../runtime/dev-prompt-queue.js"
|
|
3
|
+
|
|
4
|
+
export type FlowLogLevel = "info" | "warn" | "error" | "success" | "plain"
|
|
5
|
+
|
|
6
|
+
export interface FlowLogLine {
|
|
7
|
+
level: FlowLogLevel
|
|
8
|
+
text: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type ActiveFlowPrompt =
|
|
12
|
+
| {
|
|
13
|
+
kind: "confirm"
|
|
14
|
+
message: string
|
|
15
|
+
initialValue: boolean
|
|
16
|
+
}
|
|
17
|
+
| {
|
|
18
|
+
kind: "text"
|
|
19
|
+
message: string
|
|
20
|
+
defaultValue?: string
|
|
21
|
+
placeholder?: string
|
|
22
|
+
validate?: (value: string) => string | undefined
|
|
23
|
+
}
|
|
24
|
+
| {
|
|
25
|
+
kind: "password"
|
|
26
|
+
message: string
|
|
27
|
+
}
|
|
28
|
+
| {
|
|
29
|
+
kind: "select"
|
|
30
|
+
message: string
|
|
31
|
+
options: DevSelectOption[]
|
|
32
|
+
initialValue?: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface FlowPromptHandle<T = unknown> {
|
|
36
|
+
resolve: (value: T) => void
|
|
37
|
+
reject: (err: Error) => void
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface FlowController {
|
|
41
|
+
appendLog(level: FlowLogLevel, text: string): void
|
|
42
|
+
appendPlain(text: string): void
|
|
43
|
+
setSpinner(message: string | null): void
|
|
44
|
+
waitForPrompt<T>(spec: ActiveFlowPrompt): Promise<T>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type FlowShellProps = {
|
|
48
|
+
controller: FlowController
|
|
49
|
+
children?: ReactNode
|
|
50
|
+
}
|
package/src/ui/index.ts
CHANGED
package/src/ui/messages.ts
CHANGED
|
@@ -1,27 +1,47 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getActiveFlowApi } from "./runtime/flow-session.js"
|
|
2
2
|
import { isInteractive } from "./interactive.js"
|
|
3
|
+
import { plainError, plainInfo, plainSuccess, plainWarn } from "./theme.js"
|
|
3
4
|
|
|
4
5
|
export const SUPATYPE_PREFIX = "[supatype]"
|
|
5
6
|
|
|
7
|
+
function writePlain(message = ""): void {
|
|
8
|
+
console.log(message)
|
|
9
|
+
}
|
|
10
|
+
|
|
6
11
|
export function info(message: string): void {
|
|
12
|
+
const api = getActiveFlowApi()
|
|
13
|
+
if (api) {
|
|
14
|
+
api.log.info(message)
|
|
15
|
+
return
|
|
16
|
+
}
|
|
7
17
|
if (isInteractive()) {
|
|
8
|
-
|
|
18
|
+
writePlain(plainInfo(message))
|
|
9
19
|
return
|
|
10
20
|
}
|
|
11
|
-
|
|
21
|
+
writePlain(`${SUPATYPE_PREFIX} ${message}`)
|
|
12
22
|
}
|
|
13
23
|
|
|
14
24
|
export function warn(message: string): void {
|
|
25
|
+
const api = getActiveFlowApi()
|
|
26
|
+
if (api) {
|
|
27
|
+
api.log.warn(message)
|
|
28
|
+
return
|
|
29
|
+
}
|
|
15
30
|
if (isInteractive()) {
|
|
16
|
-
|
|
31
|
+
writePlain(plainWarn(message))
|
|
17
32
|
return
|
|
18
33
|
}
|
|
19
34
|
console.warn(`${SUPATYPE_PREFIX} ${message}`)
|
|
20
35
|
}
|
|
21
36
|
|
|
22
37
|
export function error(message: string): void {
|
|
38
|
+
const api = getActiveFlowApi()
|
|
39
|
+
if (api) {
|
|
40
|
+
api.log.error(message)
|
|
41
|
+
return
|
|
42
|
+
}
|
|
23
43
|
if (isInteractive()) {
|
|
24
|
-
|
|
44
|
+
writePlain(plainError(message))
|
|
25
45
|
return
|
|
26
46
|
}
|
|
27
47
|
console.error(`${SUPATYPE_PREFIX} ${message}`)
|
|
@@ -29,15 +49,37 @@ export function error(message: string): void {
|
|
|
29
49
|
|
|
30
50
|
/** Unprefixed line (tables, diff output, blank lines). */
|
|
31
51
|
export function plain(message = ""): void {
|
|
32
|
-
|
|
52
|
+
const api = getActiveFlowApi()
|
|
53
|
+
if (api) {
|
|
54
|
+
if (message === "") {
|
|
55
|
+
api.note("")
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
api.note(message)
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
writePlain(message)
|
|
33
62
|
}
|
|
34
63
|
|
|
35
64
|
export function step(title: string): void {
|
|
36
|
-
|
|
65
|
+
plain(`\n${title}`)
|
|
37
66
|
}
|
|
38
67
|
|
|
39
68
|
export type FileAction = "created" | "updated" | "skipped" | "removed" | "wrote"
|
|
40
69
|
|
|
41
70
|
export function file(action: FileAction, rel: string): void {
|
|
42
|
-
|
|
71
|
+
plain(` ${action} ${rel}`)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function success(message: string): void {
|
|
75
|
+
const api = getActiveFlowApi()
|
|
76
|
+
if (api) {
|
|
77
|
+
api.log.success(message)
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
if (isInteractive()) {
|
|
81
|
+
writePlain(plainSuccess(message))
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
plain(`${SUPATYPE_PREFIX} ${message}`)
|
|
43
85
|
}
|
package/src/ui/progress.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Progress UI for one-shot commands — Ink spinner inside command chrome.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getActiveFlowApi } from "./runtime/flow-session.js"
|
|
2
6
|
import { isInteractive } from "./interactive.js"
|
|
3
7
|
import { info } from "./messages.js"
|
|
8
|
+
import { runCommandChrome } from "./runtime/command-chrome.js"
|
|
4
9
|
|
|
5
10
|
/**
|
|
6
|
-
*
|
|
11
|
+
* Show progress with the branded Ink spinner when command chrome is active
|
|
12
|
+
* (or mount chrome for a standalone spinner).
|
|
7
13
|
*/
|
|
8
14
|
export async function withSpinner<T>(
|
|
9
15
|
message: string,
|
|
@@ -15,7 +21,12 @@ export async function withSpinner<T>(
|
|
|
15
21
|
return task()
|
|
16
22
|
}
|
|
17
23
|
|
|
18
|
-
const
|
|
24
|
+
const api = getActiveFlowApi()
|
|
25
|
+
if (!api) {
|
|
26
|
+
return runCommandChrome(() => withSpinner(message, task, doneMessage))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const spinner = api.spinner()
|
|
19
30
|
spinner.start(message)
|
|
20
31
|
try {
|
|
21
32
|
const result = await task()
|
package/src/ui/prompts.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { SUPATYPE_ASCII_LOGO_WORDMARK, colorLogoLines } from "../dev-logo.js"
|
|
3
|
-
import { plain } from "./messages.js"
|
|
1
|
+
import { colorLogoLines, SUPATYPE_ASCII_LOGO_WORDMARK } from "../dev-logo.js"
|
|
4
2
|
import { isInteractive } from "./interactive.js"
|
|
3
|
+
import { plain } from "./messages.js"
|
|
4
|
+
import { CLACK_CANCEL, isCancel, p } from "./clack.js"
|
|
5
5
|
|
|
6
6
|
/** Print the coloured Supatype ASCII wordmark at the top of an interactive command. */
|
|
7
7
|
export function printLogo(): void {
|
|
@@ -11,17 +11,16 @@ export function printLogo(): void {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Unwrap a
|
|
14
|
+
* Unwrap a prompt result, exiting cleanly when the user cancels (Ctrl-C).
|
|
15
15
|
*/
|
|
16
|
-
export function ensureNotCancelled<T>(value: T |
|
|
17
|
-
if (
|
|
16
|
+
export function ensureNotCancelled<T>(value: T | typeof CLACK_CANCEL, cancelMessage = "Cancelled."): T {
|
|
17
|
+
if (isCancel(value)) {
|
|
18
18
|
p.cancel(cancelMessage)
|
|
19
|
-
process.exit(0)
|
|
20
19
|
}
|
|
21
20
|
return value as T
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
/** Single-line text input
|
|
23
|
+
/** Single-line text input (TTY only). */
|
|
25
24
|
export async function promptText(
|
|
26
25
|
message: string,
|
|
27
26
|
opts?: { defaultValue?: string; placeholder?: string },
|
|
@@ -37,4 +36,13 @@ export async function promptText(
|
|
|
37
36
|
return ensureNotCancelled(value).trim()
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
/** Masked password input (TTY only). */
|
|
40
|
+
export async function promptPassword(message: string): Promise<string> {
|
|
41
|
+
if (!isInteractive()) {
|
|
42
|
+
throw new Error(`Cannot prompt for "${message}" in non-interactive mode.`)
|
|
43
|
+
}
|
|
44
|
+
const value = await p.password({ message })
|
|
45
|
+
return ensureNotCancelled(value).trim()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { p, clack, isCancel, CLACK_CANCEL, runClackFlow } from "./clack.js"
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branded Ink chrome for one-shot CLI commands (push, diff, adopt, …).
|
|
3
|
+
* Reuses the flow shell: figlet logo, coloured log pane, ink-spinner, prompts.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Command } from "commander"
|
|
7
|
+
import type { ClackApi } from "../clack-api.js"
|
|
8
|
+
import { getActiveFlowApi } from "./flow-session.js"
|
|
9
|
+
import { runClackFlow } from "../clack.js"
|
|
10
|
+
import { isInteractive } from "../interactive.js"
|
|
11
|
+
import {
|
|
12
|
+
filterCommandLogLine,
|
|
13
|
+
formatConsoleArgs,
|
|
14
|
+
stripAnsi,
|
|
15
|
+
} from "../../dev-log-filter.js"
|
|
16
|
+
|
|
17
|
+
function patchConsoleForCommand(api: ClackApi): () => void {
|
|
18
|
+
const original = {
|
|
19
|
+
log: console.log,
|
|
20
|
+
warn: console.warn,
|
|
21
|
+
error: console.error,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const emitLine = (raw: string, stream: "log" | "warn" | "error"): void => {
|
|
25
|
+
if (!filterCommandLogLine(raw)) return
|
|
26
|
+
const t = stripAnsi(raw).trim()
|
|
27
|
+
if (!t) return
|
|
28
|
+
const stripped = t.replace(/^\[supatype\]\s*/, "")
|
|
29
|
+
|
|
30
|
+
if (stream === "error" || stripped.startsWith("✗")) {
|
|
31
|
+
api.log.error(stripped.replace(/^✗\s*/, ""))
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
if (stream === "warn" || stripped.startsWith("⚠")) {
|
|
35
|
+
api.log.warn(stripped.replace(/^⚠\s*/, ""))
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
if (stripped.startsWith("✓")) {
|
|
39
|
+
api.log.success(stripped.replace(/^✓\s*/, ""))
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
if (/\[supatype\]/.test(raw)) {
|
|
43
|
+
api.log.info(stripped)
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
api.note(t)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const wrap =
|
|
50
|
+
(stream: "log" | "warn" | "error") =>
|
|
51
|
+
(...args: unknown[]): void => {
|
|
52
|
+
for (const part of formatConsoleArgs(args).split(/\r?\n/)) {
|
|
53
|
+
emitLine(part, stream)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.log = wrap("log")
|
|
58
|
+
console.warn = wrap("warn")
|
|
59
|
+
console.error = wrap("error")
|
|
60
|
+
|
|
61
|
+
return () => {
|
|
62
|
+
console.log = original.log
|
|
63
|
+
console.warn = original.warn
|
|
64
|
+
console.error = original.error
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Run a command body inside the branded Ink shell (logo + logs + spinner).
|
|
70
|
+
* Falls back to plain stdout when not interactive.
|
|
71
|
+
*/
|
|
72
|
+
export async function runCommandChrome<T>(fn: () => Promise<T>): Promise<T> {
|
|
73
|
+
if (!isInteractive() || isCommandChromeActive()) {
|
|
74
|
+
return fn()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return runClackFlow(async (api) => {
|
|
78
|
+
const restore = patchConsoleForCommand(api)
|
|
79
|
+
try {
|
|
80
|
+
return await fn()
|
|
81
|
+
} finally {
|
|
82
|
+
restore()
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** True while `runCommandChrome` / `runClackFlow` is active. */
|
|
88
|
+
export function isCommandChromeActive(): boolean {
|
|
89
|
+
return getActiveFlowApi() !== null
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Commands that mount their own Ink UI — do not wrap with command chrome. */
|
|
93
|
+
const WIZARD_COMMAND_PATHS = new Set(["dev", "init", "link"])
|
|
94
|
+
|
|
95
|
+
/** Prefixes for subcommands that call `runClackFlow` internally. */
|
|
96
|
+
const WIZARD_COMMAND_PREFIXES = ["add "]
|
|
97
|
+
|
|
98
|
+
/** Long-running or stdio-inherit commands where chrome would fight subprocess output. */
|
|
99
|
+
const STREAMING_COMMAND_PATHS = new Set([
|
|
100
|
+
"logs",
|
|
101
|
+
"pg psql",
|
|
102
|
+
"functions serve",
|
|
103
|
+
"self-host compose logs",
|
|
104
|
+
])
|
|
105
|
+
|
|
106
|
+
type CommandWithAction = Command & {
|
|
107
|
+
parent?: Command | null
|
|
108
|
+
_actionHandler?: ((args: unknown) => unknown) | null
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Whether a registered command path should skip automatic command chrome. */
|
|
112
|
+
export function shouldExcludeCommandChrome(commandPath: string): boolean {
|
|
113
|
+
if (WIZARD_COMMAND_PATHS.has(commandPath)) return true
|
|
114
|
+
if (WIZARD_COMMAND_PREFIXES.some((prefix) => commandPath.startsWith(prefix))) return true
|
|
115
|
+
if (STREAMING_COMMAND_PATHS.has(commandPath)) return true
|
|
116
|
+
return false
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function commandPath(cmd: CommandWithAction, root: Command): string {
|
|
120
|
+
const segments: string[] = []
|
|
121
|
+
let current: CommandWithAction | null = cmd
|
|
122
|
+
while (current && current !== root) {
|
|
123
|
+
segments.unshift(current.name())
|
|
124
|
+
current = current.parent ?? null
|
|
125
|
+
}
|
|
126
|
+
return segments.join(" ")
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function wrapCommandAction(cmd: CommandWithAction, root: Command): void {
|
|
130
|
+
const path = commandPath(cmd, root)
|
|
131
|
+
const handler = cmd._actionHandler
|
|
132
|
+
if (!handler || shouldExcludeCommandChrome(path)) return
|
|
133
|
+
|
|
134
|
+
cmd._actionHandler = (args: unknown) =>
|
|
135
|
+
runCommandChrome(() => Promise.resolve(handler(args)))
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Wrap every leaf command action with branded Ink chrome (see exclusions above). */
|
|
139
|
+
export function wrapProgramActionsWithChrome(program: Command): void {
|
|
140
|
+
const walk = (cmd: CommandWithAction): void => {
|
|
141
|
+
wrapCommandAction(cmd, program)
|
|
142
|
+
for (const sub of cmd.commands) {
|
|
143
|
+
walk(sub as CommandWithAction)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
walk(program as CommandWithAction)
|
|
147
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Imperative prompt queue for the dev dashboard overlay.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { CLACK_CANCEL } from "./cancel.js"
|
|
6
|
+
|
|
7
|
+
export type DevPromptKind = "confirm" | "text" | "password" | "select"
|
|
8
|
+
|
|
9
|
+
export interface DevSelectOption<T extends string = string> {
|
|
10
|
+
value: T
|
|
11
|
+
label: string
|
|
12
|
+
hint?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DevPromptRequest<T = unknown> {
|
|
16
|
+
id: number
|
|
17
|
+
kind: DevPromptKind
|
|
18
|
+
message: string
|
|
19
|
+
initialValue?: string | boolean
|
|
20
|
+
defaultValue?: string
|
|
21
|
+
placeholder?: string
|
|
22
|
+
mask?: boolean
|
|
23
|
+
options?: DevSelectOption[]
|
|
24
|
+
validate?: (value: string) => string | undefined
|
|
25
|
+
resolve: (value: T | typeof CLACK_CANCEL) => void
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let nextId = 0
|
|
29
|
+
let active: DevPromptRequest | null = null
|
|
30
|
+
const waiters: DevPromptRequest[] = []
|
|
31
|
+
const listeners = new Set<() => void>()
|
|
32
|
+
|
|
33
|
+
function notify(): void {
|
|
34
|
+
for (const listener of listeners) listener()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function subscribeDevPrompts(listener: () => void): () => void {
|
|
38
|
+
listeners.add(listener)
|
|
39
|
+
return () => listeners.delete(listener)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function getActiveDevPrompt(): DevPromptRequest | null {
|
|
43
|
+
return active
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function enqueueDevPrompt<T>(spec: Omit<DevPromptRequest<T>, "id" | "resolve">): Promise<T | typeof CLACK_CANCEL> {
|
|
47
|
+
return new Promise((resolve) => {
|
|
48
|
+
const request: DevPromptRequest<T> = {
|
|
49
|
+
...spec,
|
|
50
|
+
id: nextId++,
|
|
51
|
+
resolve: resolve as DevPromptRequest["resolve"],
|
|
52
|
+
}
|
|
53
|
+
waiters.push(request as DevPromptRequest)
|
|
54
|
+
if (!active) {
|
|
55
|
+
active = waiters.shift() ?? null
|
|
56
|
+
}
|
|
57
|
+
notify()
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function resolveDevPrompt(value: unknown): void {
|
|
62
|
+
if (!active) return
|
|
63
|
+
const current = active
|
|
64
|
+
active = waiters.shift() ?? null
|
|
65
|
+
current.resolve(value)
|
|
66
|
+
notify()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function clearDevPromptQueue(): void {
|
|
70
|
+
while (active) {
|
|
71
|
+
active.resolve(CLACK_CANCEL)
|
|
72
|
+
active = waiters.shift() ?? null
|
|
73
|
+
}
|
|
74
|
+
for (const pending of waiters.splice(0)) {
|
|
75
|
+
pending.resolve(CLACK_CANCEL)
|
|
76
|
+
}
|
|
77
|
+
notify()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** @internal Tests */
|
|
81
|
+
export function resetDevPromptQueueForTests(): void {
|
|
82
|
+
clearDevPromptQueue()
|
|
83
|
+
nextId = 0
|
|
84
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ClackApi } from "../clack-api.js"
|
|
2
|
+
|
|
3
|
+
let activeFlowApi: ClackApi | null = null
|
|
4
|
+
|
|
5
|
+
export function setActiveFlowApi(api: ClackApi | null): void {
|
|
6
|
+
activeFlowApi = api
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getActiveFlowApi(): ClackApi | null {
|
|
10
|
+
return activeFlowApi
|
|
11
|
+
}
|