refactor: change PromptEvent reject/resolve to cancel/tryCommit

This commit is contained in:
hyper
2026-04-02 19:08:14 +08:00
parent a766050773
commit c886e904a8
5 changed files with 155 additions and 33 deletions
+32 -16
View File
@@ -45,8 +45,8 @@ export type CommandRunnerContextExport<TContext> = CommandRunnerContext<TContext
registry: CommandRegistry<TContext>;
promptQueue: AsyncQueue<PromptEvent>;
_activePrompt: PromptEvent | null;
_resolvePrompt: (command: Command) => void;
_rejectPrompt: (error: Error) => void;
_tryCommit: (command: Command) => string | null;
_cancel: (reason?: string) => void;
_pendingInput: string | null;
};
@@ -66,25 +66,41 @@ export function createCommandRunnerContext<TContext>(
let activePrompt: PromptEvent | null = null;
const resolvePrompt = (command: Command) => {
const tryCommit = (command: Command) => {
if (activePrompt) {
activePrompt.resolve(command);
const result = activePrompt.tryCommit(command);
if (result === null) {
activePrompt = null;
}
return result;
}
return 'No active prompt';
};
const cancel = (reason?: string) => {
if (activePrompt) {
activePrompt.cancel(reason);
activePrompt = null;
}
};
const rejectPrompt = (error: Error) => {
if (activePrompt) {
activePrompt.reject(error);
activePrompt = null;
}
};
const prompt = (schema: Parameters<CommandRunnerContext<TContext>['prompt']>[0]): Promise<Command> => {
const prompt = (
schema: CommandSchema | string,
validator?: (command: Command) => string | null
): Promise<Command> => {
const resolvedSchema = typeof schema === 'string' ? parseCommandSchema(schema) : schema;
return new Promise((resolve, reject) => {
activePrompt = { schema: resolvedSchema, resolve, reject };
const event: PromptEvent = { schema: resolvedSchema, resolve, reject };
const tryCommit = (command: Command) => {
const error = validator?.(command);
if (error) return error;
resolve(command);
return null;
};
const cancel = (reason?: string) => {
reject(new Error(reason ?? 'Cancelled'));
};
activePrompt = { schema: resolvedSchema, tryCommit, cancel };
const event: PromptEvent = { schema: resolvedSchema, tryCommit, cancel };
for (const listener of listeners) {
listener(event);
}
@@ -100,8 +116,8 @@ export function createCommandRunnerContext<TContext>(
on,
off,
_activePrompt: null,
_resolvePrompt: resolvePrompt,
_rejectPrompt: rejectPrompt,
_tryCommit: tryCommit,
_cancel: cancel,
_pendingInput: null,
promptQueue: null!
};
+9 -3
View File
@@ -2,8 +2,14 @@ import type { Command, CommandSchema } from './types';
export type PromptEvent = {
schema: CommandSchema;
resolve: (command: Command) => void;
reject: (error: Error) => void;
/**
* 尝试提交命令
* @returns null - 验证成功,Promise 已 resolve
* @returns string - 验证失败,返回错误消息,Promise 未 resolve
*/
tryCommit: (command: Command) => string | null;
/** 取消 promptPromise 被 reject */
cancel: (reason?: string) => void;
};
export type CommandRunnerEvents = {
@@ -22,7 +28,7 @@ export type CommandRunnerContext<TContext> = {
context: TContext;
run: <T=unknown>(input: string) => Promise<CommandResult<T>>;
runParsed: (command: Command) => Promise<{ success: true; result: unknown } | { success: false; error: string }>;
prompt: (schema: CommandSchema | string) => Promise<Command>;
prompt: (schema: CommandSchema | string, validator?: (command: Command) => string | null) => Promise<Command>;
on: <T extends keyof CommandRunnerEvents>(event: T, listener: (e: CommandRunnerEvents[T]) => void) => void;
off: <T extends keyof CommandRunnerEvents>(event: T, listener: (e: CommandRunnerEvents[T]) => void) => void;
};