react-command-flow
Version:
A beautiful interactive CLI-style command interface for React apps
337 lines (336 loc) • 12.5 kB
TypeScript
/**
* Type definitions for React Command Flow
*/
/**
* Session data that persists throughout command execution
* Keys are either field names or step indices (step0, step1, etc.)
*/
export interface SessionData {
[key: string]: any;
}
/**
* Configuration for a single step in a command flow
*/
export interface CommandStep {
/**
* Text displayed at the start of the step
* Can be a static string or a function that receives session data and callbacks
*/
intro?: string | ((sessionData: SessionData, callbacks?: CallbackTriggers) => string | Promise<string>);
/**
* Text displayed at the end of the step (after user input or auto-advance)
* Can be a static string or a function that receives input, session data, and callbacks
*/
outro?: string | ((input: string, sessionData: SessionData, callbacks?: CallbackTriggers) => string | Promise<string>);
/**
* Prompt text asking for user input
* Can be a static string or a function that receives session data and callbacks
* If omitted and skipToNext is true, step will auto-advance
*/
prompt?: string | ((sessionData: SessionData, callbacks?: CallbackTriggers) => string | Promise<string>);
/**
* Field name to store the user's input in sessionData
* If provided, input will be stored as sessionData[field]
* If omitted, input is stored as sessionData[`step${index}`]
*/
field?: string;
/**
* Handler function called when user submits input for this step
* Return value should be an object that will be merged into sessionData
* Can be async for API calls or delayed processing
*
* Note: For display output, use the `outro` property instead
*
* @param input - The user's input string (null for auto-advance steps)
* @param sessionData - Current session data
* @param callbacks - Callback trigger functions
* @returns Object to merge into sessionData, or empty object
*/
onStep?: (input: string, sessionData: SessionData, callbacks?: CallbackTriggers) => Record<string, any> | Promise<Record<string, any>>;
/**
* Validation function to check user input before processing
* Return true/false for simple validation, or a string error message for custom errors
*
* @param input - The user's input string
* @param sessionData - Current session data
* @param callbacks - Callback trigger functions
* @returns true if valid, false or error message string if invalid
*/
validate?: (input: string, sessionData: SessionData, callbacks?: CallbackTriggers) => boolean | string | Promise<boolean | string>;
/**
* Custom validation error message
* Shown when validate returns false
* Can be a static string or function
*/
validationMessage?: string | ((input: string, sessionData: SessionData, callbacks?: CallbackTriggers) => string);
/**
* Redirect to another command after this step completes
* Return the command name to redirect to
*
* @param input - The user's input for this step
* @param sessionData - Current session data
* @param callbacks - Callback trigger functions
* @returns Name of the command to redirect to
*/
redirect?: (input: string, sessionData: SessionData, callbacks?: CallbackTriggers) => string;
/**
* If true, this step will auto-advance without waiting for user input
* Useful for displaying information or processing data between prompts
*/
skipToNext?: boolean;
/**
* Dynamically skip this step based on session data.
* If the function returns true, the step is skipped entirely
* and the engine advances to the next step.
*
* @param sessionData - Current session data
* @returns true to skip this step, false to execute normally
*/
skipIf?: (sessionData: SessionData) => boolean | Promise<boolean>;
}
/**
* Configuration for a complete command
*/
export interface Command {
/**
* Description of the command (shown in help menu)
*/
description?: string;
/**
* Text displayed when the command starts (before any steps)
* Can be a static string or a function that receives session data and callbacks
*/
intro?: string | ((sessionData: SessionData, callbacks?: CallbackTriggers) => string | Promise<string>);
/**
* Text displayed when the command completes (after all steps)
* Can be a static string or a function that receives session data and callbacks
*/
outro?: string | ((sessionData: SessionData, callbacks?: CallbackTriggers) => string | Promise<string>);
/**
* Array of steps that make up the command flow
* Steps are executed in order
* Can be empty for simple commands with just intro/outro
*/
steps?: CommandStep[];
/**
* Handler function called when all steps complete
* Return value is displayed as output
* Can be async for final API calls or data processing
*
* @param sessionData - Complete session data from all steps
* @param callbacks - Callback trigger functions
* @returns Final output text to display
*/
onComplete?: (sessionData: SessionData, callbacks?: CallbackTriggers) => any | Promise<any>;
/**
* Redirect to another command after completion
* Return the command name to redirect to
*
* @param sessionData - Complete session data
* @param callbacks - Callback trigger functions
* @returns Name of the command to redirect to
*/
redirect?: (sessionData: SessionData, callbacks?: CallbackTriggers) => string;
}
/**
* Collection of all available commands
* Key is the command name, value is the command configuration
*/
export interface Commands {
[commandName: string]: Command;
}
/**
* Custom translations for UI text
*/
export interface Translations {
unknownCommand?: string;
typeHelpForHelp?: string;
availableCommands?: string;
noDescription?: string;
validationError?: string;
loading?: string;
[key: string]: string | undefined;
}
/**
* Theme configuration for terminal styling
*/
export interface Theme {
fontFamily?: string;
fontSize?: string;
backgroundColor?: string;
textColor?: string;
promptColor?: string;
inputColor?: string;
outputColor?: string;
errorColor?: string;
successColor?: string;
[key: string]: string | undefined;
}
/**
* Custom callback function that can be triggered from within commands
*/
export interface CustomCallback {
(data: any, context: CallbackContext): any | Promise<any>;
}
/**
* Context information passed to custom callbacks
*/
export interface CallbackContext {
commandName: string;
sessionData: SessionData;
timestamp: string;
engine?: any;
}
/**
* Collection of custom callbacks that can be triggered from commands
*/
export interface CustomCallbacks {
[callbackName: string]: CustomCallback;
}
/**
* Callback trigger functions injected into commands
* These allow commands to invoke registered callbacks
*/
export interface CallbackTriggers {
/**
* Fire a callback (fire and forget)
* @param callbackName - Name of the callback to trigger
* @param data - Data to pass to the callback
*/
fire: (callbackName: string, data?: any) => Promise<any>;
/**
* Call a callback and await the response
* @param callbackName - Name of the callback to trigger
* @param data - Data to pass to the callback
*/
call: (callbackName: string, data?: any) => Promise<any>;
/**
* Fire multiple callbacks in sequence
* @param callbackNames - Array of callback names
* @param data - Data to pass to each callback
*/
fireMultiple: (callbackNames: string[], data?: any) => Promise<any[]>;
/**
* Conditionally fire a callback
* @param condition - Whether to fire the callback
* @param callbackName - Name of the callback to trigger
* @param data - Data to pass to the callback
*/
fireIf: (condition: boolean, callbackName: string, data?: any) => Promise<any>;
/**
* Fire a callback with transformed data
* @param callbackName - Name of the callback to trigger
* @param dataTransformer - Function or value to transform data
*/
fireWith: (callbackName: string, dataTransformer: any | ((context: CallbackContext) => any)) => Promise<any>;
}
/**
* Props for the CommandLine component
*/
export interface CommandLineProps {
/**
* Commands configuration object
*/
commands: Commands;
/**
* Custom translations for UI text
*/
translations?: Translations;
/**
* Theme configuration for styling
*/
theme?: Theme;
/**
* Delay for system output in milliseconds (default: 800)
*/
outputDelay?: number;
/**
* Delay before prompt appears after output in milliseconds (default: 300)
*/
promptDelay?: number;
/**
* Typing speed in milliseconds between characters (default: 300)
*/
typingSpeed?: number;
/**
* Height of the terminal container (default: "500px")
*/
height?: string;
/**
* Whether to display the terminal (default: true)
*/
display?: boolean;
/**
* Opacity of the terminal (default: 1)
*/
opacity?: number;
/**
* CSS transition string (default: "opacity 0.3s ease, height 0.6s ease")
*/
transition?: string;
/**
* Prompt label character (default: ">")
*/
promptLabel?: string;
/**
* Custom callbacks that can be triggered from within command steps
* Each callback receives data and context information
*/
callbacks?: CustomCallbacks;
/**
* Called when a command completes execution
* @param commandName - Name of the completed command
* @param sessionData - Final session data from the command
*/
onCommandComplete?: (commandName: string, sessionData: SessionData) => void;
/**
* Called when a command session begins — i.e. the user typed a command
* that has prompted steps and the engine has set up the first prompt.
* Fires once per command session, NOT once per step (use `onStepStart` for
* per-step events). Does not fire for commands without prompts (e.g. `help`)
* since those complete synchronously without entering a session.
*
* @param commandName - Name of the command that just started
* @param sessionData - Initial session data
*/
onCommandStart?: (commandName: string, sessionData: SessionData) => void;
/**
* Called when the user aborts an in-progress command via `exit` or one of
* its aliases (`cancel`, `quit`, `ώπα`). Semantically: "I'm quitting this
* command".
*
* Always fires when the exit keyword is recognized — the session always
* ends in this case.
*
* @param commandName - Name of the command that was active at abort time
* @param sessionData - Session data at the time of abort
*/
onCommandAbort?: (commandName: string, sessionData: SessionData) => void;
/**
* Called when the user types `back` (or `πίσω`) inside a command flow.
* Semantically: "go back" — a navigation action.
*
* Fires on EVERY back keystroke regardless of what happens next:
* - back at first step + non-empty redirect chain (re-enters parent umbrella)
* - back at first step + empty chain (ends the session)
* - back mid-flow (pops one step, session continues)
*
* @param commandName - Name of the command that was active when back was pressed
* @param sessionData - Session data at the time of the back action
*/
onCommandBack?: (commandName: string, sessionData: SessionData) => void;
/**
* Called when a step starts execution
* @param commandName - Name of the command
* @param stepIndex - Index of the step that started
* @param sessionData - Current session data
*/
onStepStart?: (commandName: string, stepIndex: number, sessionData: SessionData) => void;
/**
* Called when a step completes execution
* @param commandName - Name of the command
* @param stepIndex - Index of the step that completed
* @param sessionData - Current session data
*/
onStepComplete?: (commandName: string, stepIndex: number, sessionData: SessionData) => void;
}