import {MutableSignal, mutableSignal} from "@/utils/mutable-signal"; import { Command, CommandRegistry, CommandRunnerContext, CommandRunnerContextExport, CommandSchema, createCommandRegistry, createCommandRunnerContext, parseCommandSchema, registerCommand } from "@/utils/command"; export interface IGameContext = {} > { state: MutableSignal; commands: CommandRunnerContextExport>; } export function createGameContext = {} >( commandRegistry: CommandRegistry>, initialState?: TState | (() => TState) ): IGameContext { const stateValue = typeof initialState === 'function' ? initialState() : initialState ?? {} as TState; const state = mutableSignal(stateValue); const commands = createCommandRunnerContext(commandRegistry, state); return { state, commands }; } /** * so that we can do `import * as tictactoe from './tic-tac-toe.ts';\n\n createGameContextFromModule(tictactoe);` * @param module */ export function createGameContextFromModule = {} >( module: { registry: CommandRegistry>, createInitialState: () => TState }, ): IGameContext { return createGameContext(module.registry, module.createInitialState); } export function createGameCommandRegistry = {} >() { const registry = createCommandRegistry>(); return { registry, add( schema: CommandSchema | string, run: (this: CommandRunnerContext>, command: Command) => Promise ){ createGameCommand(registry, schema, run); return this; } } } export function createGameCommand = {} , TResult = unknown>( registry: CommandRegistry>, schema: CommandSchema | string, run: (this: CommandRunnerContext>, command: Command) => Promise ) { registerCommand(registry, { schema: typeof schema === 'string' ? parseCommandSchema(schema) : schema, run, }); } export { GameHost, createGameHost } from './game-host'; export type { GameHostStatus, GameHostOptions } from './game-host';