refactor: api changes

This commit is contained in:
hypercross 2026-04-06 11:07:11 +08:00
parent 21b91edc1a
commit b3ff589aa5
5 changed files with 10 additions and 14 deletions

View File

@ -15,7 +15,7 @@ export interface IGameContext<TState extends Record<string, unknown> = {} > {
produceAsync(fn: (draft: TState) => void): Promise<void>; produceAsync(fn: (draft: TState) => void): Promise<void>;
run<T>(input: string): Promise<CommandResult<T>>; run<T>(input: string): Promise<CommandResult<T>>;
runParsed<T>(command: Command): Promise<CommandResult<T>>; runParsed<T>(command: Command): Promise<CommandResult<T>>;
prompt<T>(schema: CommandSchema | string, validator: PromptValidator<T>, currentPlayer?: string | null): Promise<T>; prompt: <TResult,TArgs extends any[]=any[]>(schema: CommandSchema | string, validator: PromptValidator<TResult,TArgs>, currentPlayer?: string | null) => Promise<TResult>;
addInterruption(promise: Promise<void>): void; addInterruption(promise: Promise<void>): void;
// test only // test only

View File

@ -187,8 +187,7 @@ async function handleCheckFullBoard(game: BoopGame, turnPlayer: PlayerType){
const partId = await game.prompt( const partId = await game.prompt(
'choose <player> <row:number> <col:number>', 'choose <player> <row:number> <col:number>',
(command) => { (player: PlayerType, row: number, col: number) => {
const [player, row, col] = command.params as [PlayerType, number, number];
if (player !== turnPlayer) { if (player !== turnPlayer) {
throw `Invalid player: ${player}. Expected ${turnPlayer}.`; throw `Invalid player: ${player}. Expected ${turnPlayer}.`;
} }
@ -220,8 +219,7 @@ const checkFullBoard = registry.register({
async function handleTurn(game: BoopGame, turnPlayer: PlayerType) { async function handleTurn(game: BoopGame, turnPlayer: PlayerType) {
const {row, col, type} = await game.prompt( const {row, col, type} = await game.prompt(
'play <player> <row:number> <col:number> [type:string]', 'play <player> <row:number> <col:number> [type:string]',
(command) => { (player: PlayerType, row: number, col: number, type?: PieceType) => {
const [player, row, col, type] = command.params as [PlayerType, number, number, PieceType?];
const pieceType = type === 'cat' ? 'cat' : 'kitten'; const pieceType = type === 'cat' ? 'cat' : 'kitten';
if (player !== turnPlayer) { if (player !== turnPlayer) {

View File

@ -60,9 +60,7 @@ const turn = registry.register({
async run(game: TicTacToeGame, turnPlayer: PlayerType, turnNumber: number) { async run(game: TicTacToeGame, turnPlayer: PlayerType, turnNumber: number) {
const {player, row, col} = await game.prompt( const {player, row, col} = await game.prompt(
'play <player> <row:number> <col:number>', 'play <player> <row:number> <col:number>',
(command) => { (player: string, row: number, col: number) => {
const [player, row, col] = command.params as [PlayerType, number, number];
if (player !== turnPlayer) { if (player !== turnPlayer) {
throw `Invalid player: ${player}. Expected ${turnPlayer}.`; throw `Invalid player: ${player}. Expected ${turnPlayer}.`;
} else if (!isValidMove(row, col)) { } else if (!isValidMove(row, col)) {

View File

@ -147,11 +147,11 @@ export function createCommandRunnerContext<TContext>(
} }
}; };
const prompt = <T>( const prompt = <TResult,TArgs extends any[]=any[]>(
schema: CommandSchema | string, schema: CommandSchema | string,
validator: PromptValidator<T>, validator: PromptValidator<TResult,TArgs>,
currentPlayer?: string | null currentPlayer?: string | null
): Promise<T> => { ): Promise<TResult> => {
const resolvedSchema = typeof schema === 'string' ? parseCommandSchema(schema) : schema; const resolvedSchema = typeof schema === 'string' ? parseCommandSchema(schema) : schema;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const tryCommit = (commandOrInput: Command | string) => { const tryCommit = (commandOrInput: Command | string) => {
@ -161,7 +161,7 @@ export function createCommandRunnerContext<TContext>(
return schemaResult.errors.join('; '); return schemaResult.errors.join('; ');
} }
try{ try{
const result = validator(schemaResult.command); const result = validator(...schemaResult.command.params as TArgs);
resolve(result); resolve(result);
return null; return null;
}catch(e){ }catch(e){

View File

@ -31,13 +31,13 @@ export type CommandResult<T=unknown> = {
error: string; error: string;
} }
export type PromptValidator<T> = (command: Command) => T; export type PromptValidator<TResult,TArgs extends any[]=any[]> = (...params: TArgs) => TResult;
export type CommandRunnerContext<TContext> = { export type CommandRunnerContext<TContext> = {
context: TContext; context: TContext;
run: <T=unknown>(input: string) => Promise<CommandResult<T>>; run: <T=unknown>(input: string) => Promise<CommandResult<T>>;
runParsed: <T=unknown>(command: Command) => Promise<CommandResult<T>>; runParsed: <T=unknown>(command: Command) => Promise<CommandResult<T>>;
prompt: <T>(schema: CommandSchema | string, validator: PromptValidator<T>, currentPlayer?: string | null) => Promise<T>; prompt: <TResult,TArgs extends any[]=any[]>(schema: CommandSchema | string, validator: PromptValidator<TResult,TArgs>, currentPlayer?: string | null) => Promise<TResult>;
on: <T extends keyof CommandRunnerEvents>(event: T, listener: (e: CommandRunnerEvents[T]) => void) => void; 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; off: <T extends keyof CommandRunnerEvents>(event: T, listener: (e: CommandRunnerEvents[T]) => void) => void;
}; };