refactor: prompt validation
This commit is contained in:
parent
af9254603a
commit
9e2947a8d6
|
|
@ -10,6 +10,7 @@ import {
|
|||
registerCommand
|
||||
} from "@/utils/command";
|
||||
import type { GameModule } from './game-host';
|
||||
import {PromptValidator} from "@/utils/command/command-runner";
|
||||
|
||||
export interface IGameContext<TState extends Record<string, unknown> = {} > {
|
||||
get value(): TState;
|
||||
|
|
@ -17,7 +18,7 @@ export interface IGameContext<TState extends Record<string, unknown> = {} > {
|
|||
produceAsync(fn: (draft: TState) => void): Promise<void>;
|
||||
run<T>(input: string): Promise<CommandResult<T>>;
|
||||
runParsed<T>(command: Command): Promise<CommandResult<T>>;
|
||||
prompt(schema: CommandSchema | string, validator?: (command: Command) => string | null, currentPlayer?: string | null): Promise<Command>;
|
||||
prompt<T>(schema: CommandSchema | string, validator: PromptValidator<T>, currentPlayer?: string | null): Promise<T>;
|
||||
addInterruption(promise: Promise<void>): void;
|
||||
|
||||
// test only
|
||||
|
|
@ -82,32 +83,6 @@ export function createGameCommandRegistry<TState extends Record<string, unknown>
|
|||
return createCommandRegistry<IGameContext<TState>>();
|
||||
}
|
||||
|
||||
type CmdFunc<TState extends Record<string, unknown> = {}> = (this: IGameContext<TState>, ...args: any[]) => Promise<unknown>;
|
||||
|
||||
export function registerGameCommand<TState extends Record<string, unknown> = {}, TFunc extends CmdFunc<TState> = CmdFunc<TState>>(
|
||||
registry: CommandRegistry<IGameContext<TState>>,
|
||||
schema: CommandSchema | string,
|
||||
run: TFunc
|
||||
) {
|
||||
const parsedSchema = typeof schema === 'string' ? parseCommandSchema(schema) : schema;
|
||||
registerCommand(registry, {
|
||||
schema: parsedSchema,
|
||||
async run(this: CommandRunnerContext<IGameContext<TState>>, command: Command){
|
||||
const params = command.params;
|
||||
return await run.call(this.context, ...params);
|
||||
},
|
||||
});
|
||||
|
||||
return function(game: IGameContext<TState>, ...args: Parameters<TFunc>){
|
||||
return game.runParsed({
|
||||
options: {},
|
||||
params: args,
|
||||
flags: {},
|
||||
name: parsedSchema.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { GameHost, createGameHost } from './game-host';
|
||||
export type { GameHostStatus, GameModule } from './game-host';
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
// Core types
|
||||
export type { IGameContext } from './core/game';
|
||||
export { createGameContext, createGameCommandRegistry, registerGameCommand } from './core/game';
|
||||
export { createGameContext, createGameCommandRegistry } from './core/game';
|
||||
|
||||
export type { GameHost, GameHostStatus, GameModule } from './core/game';
|
||||
export { createGameHost, createGameModule } from './core/game';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
import type { Command, CommandSchema } from './types';
|
||||
import type {CommandResult, CommandRunner, CommandRunnerContext, CommandRunnerEvents, PromptEvent} from './command-runner';
|
||||
import type {
|
||||
CommandResult,
|
||||
CommandRunner,
|
||||
CommandRunnerContext,
|
||||
CommandRunnerEvents,
|
||||
PromptEvent,
|
||||
PromptValidator
|
||||
} from './command-runner';
|
||||
import { parseCommand } from './command-parse';
|
||||
import { applyCommandSchema } from './command-validate';
|
||||
import { parseCommandSchema } from './schema-parse';
|
||||
|
|
@ -129,11 +136,11 @@ export function createCommandRunnerContext<TContext>(
|
|||
}
|
||||
};
|
||||
|
||||
const prompt = (
|
||||
const prompt = <T>(
|
||||
schema: CommandSchema | string,
|
||||
validator?: (command: Command) => string | null,
|
||||
validator: PromptValidator<T>,
|
||||
currentPlayer?: string | null
|
||||
): Promise<Command> => {
|
||||
): Promise<T> => {
|
||||
const resolvedSchema = typeof schema === 'string' ? parseCommandSchema(schema) : schema;
|
||||
return new Promise((resolve, reject) => {
|
||||
const tryCommit = (commandOrInput: Command | string) => {
|
||||
|
|
@ -142,10 +149,16 @@ export function createCommandRunnerContext<TContext>(
|
|||
if (!schemaResult.valid) {
|
||||
return schemaResult.errors.join('; ');
|
||||
}
|
||||
const error = validator?.(schemaResult.command);
|
||||
if (error) return error;
|
||||
resolve(schemaResult.command);
|
||||
try{
|
||||
const result = validator(schemaResult.command);
|
||||
resolve(result);
|
||||
return null;
|
||||
}catch(e){
|
||||
if(e instanceof Error)
|
||||
return e.message;
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
const cancel = (reason?: string) => {
|
||||
activePrompt = null;
|
||||
|
|
|
|||
|
|
@ -31,11 +31,13 @@ export type CommandResult<T=unknown> = {
|
|||
error: string;
|
||||
}
|
||||
|
||||
export type PromptValidator<T> = (command: Command) => T;
|
||||
|
||||
export type CommandRunnerContext<TContext> = {
|
||||
context: TContext;
|
||||
run: <T=unknown>(input: string) => Promise<CommandResult<T>>;
|
||||
runParsed: <T=unknown>(command: Command) => Promise<CommandResult<T>>;
|
||||
prompt: (schema: CommandSchema | string, validator?: (command: Command) => string | null, currentPlayer?: string | null) => Promise<Command>;
|
||||
prompt: <T>(schema: CommandSchema | string, validator: PromptValidator<T>, currentPlayer?: string | null) => Promise<T>;
|
||||
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;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue