import REPL from './repl'; import { Entity } from './entity'; import { CodedError } from './errors'; import { ExecOptions } from './execOptions'; import { UsageModel } from '../core/usage-error'; import { Tab } from '../webapp/tab'; import { Block } from '../webapp/models/block'; import { StreamableFactory } from './streamable'; import * as Yargs from 'yargs-parser'; /** * A command `KResponse` can be any supported `Entity` type * */ export type KResponse = Entity; export default KResponse; /** * "top-level", meaning the user hit enter in the CLI, * "click-handler", meaning that the user clicked on a UI element * "nested", meaning that some evaluator uses the repl in its internal implementation * */ export declare enum ExecType { TopLevel = 0, ClickHandler = 1, Nested = 2, Rerun = 3 } export type ViewTransformer = (args: EvaluatorArgs, response: T) => Promise | void | Promise; export interface CommandOptions extends CapabilityRequirements { /** does this command accept no arguments of any sort (neither positional nor optional)? */ noArgs?: boolean; /** Semicolon-expand the command line? Default: true */ semiExpand?: boolean; usage?: UsageModel; flags?: YargsParserFlags; hidden?: boolean; incognito?: 'popup'[]; viewName?: string; /** * Desired window title; this only pertains to situations where the * command execution will result in opening a new window specific to * the execution of the command. You may either provide a fixed * title (the `string` case), or a function that returns the title * to use for the given arguments. */ title?: string | ((argv: string[]) => string); width?: number; height?: number; /** is this an interior node ("directory", versus a leaf-node with a command handler */ isDirectory?: boolean; listen?: CommandListener; docs?: string; synonymFor?: Command; hide?: boolean; override?: CommandHandler; plugin?: string; okOptions?: string[]; /** controller wants to handle redirect */ noCoreRedirect?: boolean; /** model to view transformer */ viewTransformer?: ViewTransformer; /** * Is the command experimental? e.g. initial release, lack of test coverage * */ isExperimental?: boolean; /** * Is the command only want to show output and hide input? * */ outputOnly?: boolean; /** When this command is being replayed, prefer to re-execute if possible */ preferReExecute?: boolean; } export interface Event { tab?: Tab; command?: string; route?: string; plugin?: string; isIntention?: boolean; error?: string; options?: string[]; execType?: ExecType; isDrilldown?: boolean; } export interface ParsedOptions { _?: string[]; [key: string]: any; } /** * This information represents a command line, but split out in * various useful ways. * */ export interface CommandLine { /** * the raw command string, as given by the user */ command: string; /** the result of a whitespace split applied to the `command` string * that pays attention to backslash escaping and quotations */ argv: string[]; /** * the residual of `argv` without `parsedOptions` */ argvNoOptions: string[]; /** * pipeline stages, e.g. if command='a b --foo|c', the pipeStages=[['a','b, '--foo'],'c'] */ pipeStages: { prefix?: string; stages: string[][]; redirect?: string; redirector?: '>' | '>>' | '2>&1' | '>&' | '>>&'; }; /** * the dash options parsed out in a way that pays attention to n-ary * options such as `--option key value` */ parsedOptions: Options; } /** * The full set of data passed to a command handler * */ export interface EvaluatorArgs extends CommandLine { /** * The tab context in which the command was initiated */ tab: Tab; REPL: REPL; /** * Optional command channel options that one command can use to * influence the execution of another. */ execOptions: ExecOptions; /** * Commands can use this to stream output to the UI, rather than * using the normal request-response interaction between the REPL * and the command. */ createOutputStream: StreamableFactory; /** * Same as createOutputStream, but for stderr */ createErrorStream: StreamableFactory; /** * EXPERT MODE: The REPL block in which this command was initiated * (rarely used, but useful for more complex UI extensions) */ block: Block | boolean; /** * EXPERT MODE: The REPL block that will house the *subsequent* * command execution (rarely used, but useful for more complex UI * extensions) */ nextBlock: HTMLElement; } /** base command handler */ export type CommandHandler = (args: EvaluatorArgs) => T | Promise; /** command handler when overriding commands from other plugins */ export type CommandOverrideHandler = (args: EvaluatorArgs, underlyingHandler: CommandHandler) => T | Promise; /** * Evaluator * */ export interface Evaluator { eval: CommandHandler; } export interface CommandBase { route: string; plugin?: string; options?: CommandOptions; } type CommandKey = string; interface CommandKeyMap { [key: string]: Command; } export interface Disambiguator { [key: string]: CommandBase[]; } export interface Command extends CommandBase { $: CommandHandler; key: CommandKey; parent: Command; children?: CommandKeyMap; synonyms?: CommandKeyMap; } /** a command tree rooted by a command */ export type CommandTree = Command; export interface CapabilityRequirements { needsUI?: boolean; requiresLocal?: boolean; noAuthOk?: boolean | string[]; fullscreen?: boolean; } export type OnSuccess = (args: { tab: Tab; type: ExecType; command: string; isDrilldown: boolean; parsedOptions: ParsedOptions; }) => void; export type OnError = (command: string, tab: Tab, type: ExecType, err: CodedError) => CodedError; export interface CommandHandlerWithEvents extends Evaluator { subtree: Command; route: string; options: CommandOptions; success: OnSuccess; error: OnError; } export declare function isCommandHandlerWithEvents(evaluator: Evaluator): evaluator is CommandHandlerWithEvents; export type CommandTreeResolution = boolean | CommandHandlerWithEvents | CodedError; export interface YargsParserFlags { configuration?: Partial; array?: string[]; boolean?: string[]; string?: string[]; narg?: Record; alias?: Record; } /** a catch all handler is presented with an offer to handle a given argv */ export type CatchAllOffer = (argv: string[]) => boolean; export interface CatchAllHandler extends Command { prio: number; plugin: string; offer: CatchAllOffer; eval: CommandHandler; } /** * The registrar.listen API * */ type CommandListener = (route: string, handler: CommandHandler, options?: CommandOptions) => Command; export interface CommandRegistrar { find: (route: string, fromPlugin?: string, noOverride?: boolean) => Promise>; listen: CommandListener; override: (route: string, fromPlugin: string, handler: CommandOverrideHandler, options?: CommandOptions) => Promise>; synonym: (route: string, handler: CommandHandler, master: Command, options?: CommandOptions) => void; subtree: (route: string, options: CommandOptions) => Command; subtreeSynonym: (route: string, masterTree: Command, options?: CommandOptions) => void; catchall: (offer: CatchAllOffer, handler: CommandHandler, prio: number, options?: CommandOptions) => void; }