mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-23 09:18:21 +00:00
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Documentation** - Added detailed IDE configuration recommendations for Rust, Solidity, and TypeScript in the README to enhance developer experience. - **Chores** - Updated Biome configuration files and package dependencies to the latest schema and version. - Refined code formatting, linting, and import organization settings for consistency across the project. - **Refactor** - Reordered import statements in multiple files for improved readability. - Simplified function signatures and ensured proper async handling in utility scripts. - **Bug Fixes** - Ensured proper completion of asynchronous operations in shell utility functions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Gonza Montiel <gonzamontiel@users.noreply.github.com>
98 lines
2.2 KiB
TypeScript
98 lines
2.2 KiB
TypeScript
import {
|
|
createPrompt,
|
|
isEnterKey,
|
|
makeTheme,
|
|
type Status,
|
|
type Theme,
|
|
useEffect,
|
|
useKeypress,
|
|
usePrefix,
|
|
useState
|
|
} from "@inquirer/core";
|
|
import type { PartialDeep } from "@inquirer/type";
|
|
import chalk from "chalk";
|
|
|
|
type TimeoutConfirmConfig = {
|
|
message: string;
|
|
default?: boolean;
|
|
timeoutMs: number;
|
|
theme?: PartialDeep<Theme>;
|
|
};
|
|
|
|
export const timeoutConfirm = createPrompt<boolean, TimeoutConfirmConfig>((cfg, done) => {
|
|
const [status, setStatus] = useState<Status>("loading");
|
|
const [input, setInput] = useState("");
|
|
const [left, setLeft] = useState(cfg.timeoutMs);
|
|
|
|
const theme = makeTheme(cfg.theme);
|
|
const prefix = usePrefix({ status, theme });
|
|
|
|
useEffect(() => {
|
|
const startTime = Date.now();
|
|
const id = setInterval(() => {
|
|
const elapsed = Date.now() - startTime;
|
|
const newLeft = Math.max(0, cfg.timeoutMs - elapsed);
|
|
|
|
setLeft(newLeft);
|
|
|
|
if (newLeft <= 0) {
|
|
setStatus("done");
|
|
clearInterval(id);
|
|
done(cfg.default ?? true);
|
|
}
|
|
}, 500);
|
|
|
|
return () => clearInterval(id);
|
|
}, []);
|
|
|
|
const finish = () => {
|
|
const val = /^(y|yes)$/i.test(input)
|
|
? true
|
|
: /^(n|no)$/i.test(input)
|
|
? false
|
|
: (cfg.default ?? true);
|
|
setStatus("done");
|
|
done(val);
|
|
};
|
|
|
|
useKeypress((key, rl) => {
|
|
if (isEnterKey(key)) finish();
|
|
else setInput(rl.line);
|
|
});
|
|
|
|
const defaultBadge = theme.style.defaultAnswer(cfg.default === false ? "y/N" : "Y/n");
|
|
|
|
const main = `${prefix} ${theme.style.message(cfg.message, status)} \
|
|
${defaultBadge} ${input}`;
|
|
const border = chalk.yellow("=".repeat(80));
|
|
const hint = theme.style.help(
|
|
chalk.magenta(
|
|
`⏱ Will default to ${chalk.bold(cfg.default ? "YES" : "NO")} in ${chalk.bold((left / 1000).toFixed(0))}s`
|
|
)
|
|
);
|
|
|
|
return `${border}
|
|
${hint}
|
|
${main}
|
|
${border}`;
|
|
});
|
|
|
|
export const confirmWithTimeout = async (
|
|
question: string,
|
|
defaultValue: boolean,
|
|
timeoutSeconds: number
|
|
) => {
|
|
await Bun.sleep(50); //debounce
|
|
|
|
return timeoutConfirm({
|
|
message: question,
|
|
default: defaultValue,
|
|
timeoutMs: timeoutSeconds * 1000,
|
|
theme: {
|
|
style: {
|
|
message: (text: string) => chalk.cyan(text),
|
|
answer: (text: string) => chalk.green(text)
|
|
}
|
|
}
|
|
});
|
|
};
|