caique
API reference

caique/inquirer

Every export of caique/inquirer, with its signature and doc comment: usePrefix, useKeypress, createPrompt, Separator, AbortPromptError, CancelPromptError and 19 more, plus 10 types.

import { usePrefix, useKeypress, createPrompt, … } from 'caique/inquirer';

Functions

createPrompt

Turn a render function into a prompt.

Two lines, because the interesting half is runPrompt and the only thing this one adds is the call site — captured now rather than at the throw, since the error a render function gets for returning nothing names the file createPrompt was called from.

function createPrompt<Value, Config>(view: ViewFunction<Value, Config>): Prompt<Value, Config>;
ParameterType
viewViewFunction<Value, Config>

Returns Prompt<Value, Config>

getDefaultKeybindings

INQUIRER_KEYBINDINGS split on whitespace or commas, lowercased, unknown names dropped and duplicates collapsed — so 'vim emacs unknown vim' is ['vim', 'emacs'].

function getDefaultKeybindings(): Keybinding[];

Returns Keybinding[]

getDefaultTheme

The defaults with the environment's keybindings folded in, read fresh on every call.

function getDefaultTheme(): Theme;

Returns Theme

makeTheme

Merge any number of partial themes over the defaults, last one winning per leaf.

null and undefined entries are dropped rather than merged, because a prompt passes config.theme straight through and a caller who set no theme passes undefined.

function makeTheme<Extension = object>(...themes: readonly (PartialTheme<Extension> | undefined)[]): Theme & Extension;
ParameterType
themesreadonly (PartialTheme<Extension> | undefined)[]

Returns Theme & Extension

useEffect

A side effect, queued when its dependency array changes and cleaned up before it re-runs.

The comparison is Object.is per element, like the incumbent's, so a useRef handed back as a dependency is stable and an object literal is not.

function useEffect(cb: (rl: PromptReadline) => Cleanup, depArray: readonly unknown[]): void;
ParameterType
cb(rl: PromptReadline) => Cleanup
depArrayreadonly unknown[]

Returns void

useKeypress

Register a keypress handler for as long as the prompt is rendering.

ignore rather than only removeListener, because readline emits every keypress in one data event synchronously: a handler removed during that burst would still be called for the keys already queued behind the one that settled the prompt. Two graded cases — "after the prompt is done" and "after the prompt is aborted" — are that exact race.

function useKeypress(userHandler: (event: KeypressEvent, rl: PromptReadline) => void | Promise<void>): void;
ParameterType
userHandler(event: KeypressEvent, rl: PromptReadline) => void | Promise<void>

Returns void

useMemo

A memoised value.

Compared with !== rather than Object.is, and by length first, exactly as upstream does it — a drop-in that quietly tightened the comparison would recompute where the incumbent does not, and the graded case counts the calls.

function useMemo<Value>(fn: () => Value, dependencies: readonly unknown[]): Value;
ParameterType
fn() => Value
dependenciesreadonly unknown[]

Returns Value

usePrefix

The prefix a prompt draws, and the spinner that replaces it while the prompt is loading.

The 300 ms delay before the spinner appears is not decoration: it is what stops a prompt that resolves quickly from flickering a frame of spinner on its way past, and the graded case advances fake timers by exactly delay + interval to see the first frame.

function usePrefix({ status, theme }: {
    status?: Status;
    theme?: PartialTheme;
}): string;
ParameterType
{ status, theme }{ status?: Status; theme?: PartialTheme; }

Returns string

useRef

A box that survives re-renders. One useState slot holding an object that never changes. The no-argument form, for a box a later render fills — useRef<Timeout | undefined>().

function useRef<Value>(value: Value): {
    current: Value;
};

function useRef<Value>(value?: Value): {
    current: Value | undefined;
};
ParameterType
valueValue

Returns { current: Value; }

useState

State that survives a re-render, addressed by call order.

The setter accepts a value or a reducer, and does nothing at all when the next value is Object.is-equal to the current one — which is why setValue(NaN) on a NaN state does not re-render, and why a reducer returning its argument is free. The no-argument form, for state a later keypress fills.

function useState<Value>(defaultValue: NotFunction<Value> | (() => Value)): [Value, SetState<Value>];

function useState<Value>(defaultValue?: NotFunction<Value> | (() => Value)): [Value | undefined, SetState<Value | undefined>];
ParameterType
defaultValueNotFunction<Value> | (() => Value)

Returns [Value, SetState<Value>]

Classes

AbortPromptError

Thrown when the AbortSignal handed to a prompt aborts.

class AbortPromptError extends Error {
    name: string;
    message: string;
    constructor(options?: {
        cause?: unknown;
    });
}

CancelPromptError

Thrown when a caller calls .cancel() on the returned promise.

class CancelPromptError extends Error {
    name: string;
    message: string;
}

ExitPromptError

Thrown when the process is going away under the prompt — Ctrl-C, or a signalled exit.

class ExitPromptError extends Error {
    name: string;
}

HookError

Thrown when a hook is called outside a prompt render, where there is no store to read.

class HookError extends Error {
    name: string;
}

Separator

A non-choice in a list of choices.

isSeparator is a duck type rather than an instanceof check, and deliberately so: a caller who built { type: 'separator', separator: '----' } by hand — or who has two copies of the package in their tree — must still have it recognised. One of the three graded cases is exactly that object literal.

class Separator {
    readonly separator: string;
    readonly type = "separator";
    constructor(separator?: string);
    /** Whether `choice` is a separator — by shape, never by class. */
    static isSeparator(choice: unknown): choice is Separator;
}

ValidationError

Thrown when a hook is called correctly but handed something it cannot use.

class ValidationError extends Error {
    name: string;
}

Constants

defaultTheme

The incumbent's defaults, byte for byte where a byte is observable.

styleText is node:util's, which is the whole colour dependency: roundel owns colour for caique's own widgets, and reaching for it here would put a second policy on a subpath whose job is to behave like somebody else's package.

const defaultTheme: Theme;

isBackspaceKey

Backspace.

const isBackspaceKey: (key: KeypressEvent) => boolean;

isDownKey

The down arrow always; j under vim; Ctrl-N under emacs.

const isDownKey: (key: KeypressEvent, keybindings?: readonly Keybinding[]) => boolean;

isEnterKey

Enter, under either name readline gives it.

const isEnterKey: (key: KeypressEvent) => boolean;

isNumberKey

A digit. name is a single character for these, so a substring test is the whole test.

const isNumberKey: (key: KeypressEvent) => boolean;

isShiftKey

Whether shift was held. Returns the flag itself, so an absent flag reads as false.

const isShiftKey: (key: KeypressEvent) => boolean;

isSpaceKey

The space bar.

const isSpaceKey: (key: KeypressEvent) => boolean;

isTabKey

Tab.

const isTabKey: (key: KeypressEvent) => boolean;

isUpKey

The up arrow always; k under vim; Ctrl-P under emacs. Nothing else, ever.

const isUpKey: (key: KeypressEvent, keybindings?: readonly Keybinding[]) => boolean;

Interfaces

Context

The streams and lifetime a caller may hand a prompt.

interface Context {
    input?: NodeJS.ReadableStream;
    output?: NodeJS.WritableStream;
    clearPromptOnDone?: boolean;
    signal?: AbortSignal;
}

KeypressEvent

What node:readline hands a keypress listener. Widened to what the predicates read.

interface KeypressEvent {
    name: string;
    ctrl?: boolean;
    shift?: boolean;
    meta?: boolean;
    sequence?: string;
}

Theme

The whole theme, as a prompt sees it after makeTheme has merged the defaults in.

interface Theme {
    prefix: ThemePrefix;
    spinner: ThemeSpinner;
    keybindings: Keybinding[];
    style: ThemeStyle;
}

Types

CancelablePromise

The promise a prompt returns: cancellable, so a caller can take the question back.

type CancelablePromise<Value> = Promise<Value> & {
    cancel: () => void;
};

Keybinding

The two named keybinding sets the incumbent understands. Anything else is ignored.

type Keybinding = 'emacs' | 'vim';

PartialTheme

What a caller may hand makeTheme: any subset, nested.

type PartialTheme<Extension = object> = Partial<Omit<Theme, 'style' | 'spinner'>> & {
    spinner?: Partial<ThemeSpinner>;
    style?: Partial<ThemeStyle>;
} & Partial<Extension>;

Prompt

A prompt, ready to be called with its config.

type Prompt<Value, Config> = (config: Config, context?: Context) => CancelablePromise<Value>;

SetState

The setter useState returns: a new value, or a reducer over the current one.

type SetState<Value> = (newValue: NotFunction<Value> | ((current: Value) => Value)) => void;

Status

The lifecycle a prompt reports through theme.prefix. Open, so a caller may add states.

type Status = 'loading' | 'idle' | 'done' | (string & {});

ViewFunction

What a render function returns: one string, or a body and a line below the cursor.

type ViewFunction<Value, Config> = (config: Config, done: (value: Value) => void) => string | [string, string | undefined];

On this page