datahaven/test/utils/input.ts
Facundo Farall 4c7a64fc39
fix: 🚨 Add error in TS for missing awaits (#81)
<!-- 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>
2025-05-19 22:28:43 +00:00

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)
}
}
});
};