feat: add command prompt context with middleware support

This commit is contained in:
hyper 2026-04-23 14:22:17 +08:00
parent 23ac09ff21
commit 32408c3cee
2 changed files with 132 additions and 20 deletions

View File

@ -0,0 +1,93 @@
import { createMiddlewareChain } from "../middleware";
import { PromptValidator } from "./command-runner";
import { CommandSchema } from "./types";
export interface PromptDef<TArgs extends any[]> {
schema: CommandSchema;
hint?: string;
}
export interface PromptCall<TArgs extends any[] = unknown[], TRes = unknown> {
def: PromptDef<TArgs>;
player?: string;
validator: PromptValidator<TRes, TArgs>;
resolve(res: TRes): void;
reject(reason: string): void;
promise: Promise<TRes>;
}
export type PromptTryResult =
| {
ok: false;
reason: string;
}
| {
ok: true;
};
export function createPromptContext() {
const map = new Map<string, PromptCall>();
const handleCall = createMiddlewareChain(async (call: PromptCall) => {
const key = call.player ?? "global";
const existing = map.get(key);
if (existing) {
existing.reject("Prompt cancelled");
}
map.set(key, call);
try {
await call.promise;
} finally {
if (map.get(key) === call) map.delete(key);
}
});
function tryCommit<TArgs extends any[]>(
player: string,
...args: TArgs
): PromptTryResult {
const call = map.get(player);
if (!call) return { ok: false, reason: "No Prompt" };
try {
const res = call.validator(...args);
call.resolve(res);
return { ok: true };
} catch (reason) {
if (typeof reason === "string") return { ok: false, reason };
throw reason;
}
}
function cancel(player: string, reason = "Prompt Cancelled") {
map.get(player)?.reject(reason);
}
function prompt<TArgs extends any[], TRes>(
def: PromptDef<TArgs>,
validator: PromptValidator<TRes, TArgs>,
player?: string,
) {
const promise = new Promise((resolve, reject) => {
const call = {
def,
player,
validator,
resolve,
reject,
promise,
} as PromptCall<unknown[], unknown>;
handleCall.execute(call);
});
return promise;
}
return {
prompt,
tryCommit,
cancel,
handleCall,
};
}

View File

@ -1,6 +1,10 @@
export { parseCommand } from './command-parse';
export { parseCommandSchema } from './schema-parse';
export { validateCommand, parseCommandWithSchema, applyCommandSchema } from './command-validate';
export { parseCommand } from "./command-parse";
export { parseCommandSchema } from "./schema-parse";
export {
validateCommand,
parseCommandWithSchema,
applyCommandSchema,
} from "./command-validate";
export {
createCommandRegistry,
registerCommand,
@ -10,13 +14,28 @@ export {
runCommand,
runCommandParsed,
createCommandRunnerContext,
} from './command-registry';
} from "./command-registry";
export type {
Command,
CommandParamSchema,
CommandOptionSchema,
CommandFlagSchema,
CommandSchema,
} from './types';
export type { CommandRunner, CommandDef, CommandResult, CommandRunnerHandler, CommandRunnerContext, PromptEvent, CommandRunnerEvents } from './command-runner';
export type { CommandRegistry, CommandRunnerContextExport } from './command-registry';
} from "./types";
export type {
CommandRunner,
CommandDef,
CommandResult,
CommandRunnerHandler,
CommandRunnerContext,
PromptEvent,
CommandRunnerEvents,
} from "./command-runner";
export type {
CommandRegistry,
CommandRunnerContextExport,
} from "./command-registry";
export type { PromptDef, PromptTryResult, PromptCall } from "./command-prompt";
export { createPromptContext } from "./command-prompt";