feat: add command prompt context with middleware support
This commit is contained in:
parent
23ac09ff21
commit
32408c3cee
|
|
@ -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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,22 +1,41 @@
|
||||||
export { parseCommand } from './command-parse';
|
export { parseCommand } from "./command-parse";
|
||||||
export { parseCommandSchema } from './schema-parse';
|
export { parseCommandSchema } from "./schema-parse";
|
||||||
export { validateCommand, parseCommandWithSchema, applyCommandSchema } from './command-validate';
|
|
||||||
export {
|
export {
|
||||||
createCommandRegistry,
|
validateCommand,
|
||||||
registerCommand,
|
parseCommandWithSchema,
|
||||||
unregisterCommand,
|
applyCommandSchema,
|
||||||
hasCommand,
|
} from "./command-validate";
|
||||||
getCommand,
|
export {
|
||||||
runCommand,
|
createCommandRegistry,
|
||||||
runCommandParsed,
|
registerCommand,
|
||||||
createCommandRunnerContext,
|
unregisterCommand,
|
||||||
} from './command-registry';
|
hasCommand,
|
||||||
|
getCommand,
|
||||||
|
runCommand,
|
||||||
|
runCommandParsed,
|
||||||
|
createCommandRunnerContext,
|
||||||
|
} from "./command-registry";
|
||||||
export type {
|
export type {
|
||||||
Command,
|
Command,
|
||||||
CommandParamSchema,
|
CommandParamSchema,
|
||||||
CommandOptionSchema,
|
CommandOptionSchema,
|
||||||
CommandFlagSchema,
|
CommandFlagSchema,
|
||||||
CommandSchema,
|
CommandSchema,
|
||||||
} from './types';
|
} from "./types";
|
||||||
export type { CommandRunner, CommandDef, CommandResult, CommandRunnerHandler, CommandRunnerContext, PromptEvent, CommandRunnerEvents } from './command-runner';
|
export type {
|
||||||
export type { CommandRegistry, CommandRunnerContextExport } from './command-registry';
|
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";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue