feat: add command runner and registry
This commit is contained in:
@@ -20,6 +20,9 @@ export { createRule, dispatchCommand } from './core/rule';
|
||||
export type { Command, CommandSchema, CommandParamSchema, CommandOptionSchema, CommandFlagSchema } from './utils/command';
|
||||
export { parseCommand, parseCommandSchema, validateCommand, parseCommandWithSchema, applyCommandSchema } from './utils/command';
|
||||
|
||||
export type { CommandRunner, CommandRunnerHandler, CommandRegistry, CommandRunnerContext } from './utils/command';
|
||||
export { createCommandRegistry, registerCommand, unregisterCommand, hasCommand, getCommand, runCommand, createCommandRunnerContext } from './utils/command';
|
||||
|
||||
export type { Entity, EntityAccessor } from './utils/entity';
|
||||
export { createEntityCollection } from './utils/entity';
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
import type { Command } from './types.js';
|
||||
import type { CommandRunner, CommandRunnerContext as RunnerContext } from './command-runner.js';
|
||||
import { parseCommand } from './command-parse.js';
|
||||
import { applyCommandSchema } from './command-apply.js';
|
||||
|
||||
export type CommandRegistry<TContext> = Map<string, CommandRunner<TContext, unknown>>;
|
||||
|
||||
export function createCommandRegistry<TContext>(): CommandRegistry<TContext> {
|
||||
return new Map();
|
||||
}
|
||||
|
||||
export function registerCommand<TContext, TResult>(
|
||||
registry: CommandRegistry<TContext>,
|
||||
runner: CommandRunner<TContext, TResult>
|
||||
): void {
|
||||
registry.set(runner.schema.name, runner as CommandRunner<TContext, unknown>);
|
||||
}
|
||||
|
||||
export function unregisterCommand<TContext>(
|
||||
registry: CommandRegistry<TContext>,
|
||||
name: string
|
||||
): void {
|
||||
registry.delete(name);
|
||||
}
|
||||
|
||||
export function hasCommand<TContext>(
|
||||
registry: CommandRegistry<TContext>,
|
||||
name: string
|
||||
): boolean {
|
||||
return registry.has(name);
|
||||
}
|
||||
|
||||
export function getCommand<TContext>(
|
||||
registry: CommandRegistry<TContext>,
|
||||
name: string
|
||||
): CommandRunner<TContext, unknown> | undefined {
|
||||
return registry.get(name);
|
||||
}
|
||||
|
||||
async function executeWithRunnerContext<TContext>(
|
||||
registry: CommandRegistry<TContext>,
|
||||
context: TContext,
|
||||
runner: CommandRunner<TContext, unknown>,
|
||||
command: Command
|
||||
): Promise<{ success: true; result: unknown } | { success: false; error: string }> {
|
||||
const runnerCtx: RunnerContext<TContext> = {
|
||||
context,
|
||||
run: (input: string) => runCommand(registry, context, input),
|
||||
runParsed: (cmd: Command) => runCommandParsed(registry, context, cmd),
|
||||
};
|
||||
try {
|
||||
const result = await runner.run.call(runnerCtx, command);
|
||||
return { success: true, result };
|
||||
} catch (e) {
|
||||
const error = e as Error;
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
}
|
||||
|
||||
export async function runCommand<TContext>(
|
||||
registry: CommandRegistry<TContext>,
|
||||
context: TContext,
|
||||
input: string
|
||||
): Promise<{ success: true; result: unknown } | { success: false; error: string }> {
|
||||
const command = parseCommand(input);
|
||||
return await runCommandParsed(registry, context, command);
|
||||
}
|
||||
|
||||
export async function runCommandParsed<TContext>(
|
||||
registry: CommandRegistry<TContext>,
|
||||
context: TContext,
|
||||
command: Command
|
||||
): Promise<{ success: true; result: unknown } | { success: false; error: string }> {
|
||||
const runner = registry.get(command.name);
|
||||
if (!runner) {
|
||||
return { success: false, error: `Unknown command: ${command.name}` };
|
||||
}
|
||||
|
||||
const validationResult = applyCommandSchema(command, runner.schema);
|
||||
if (!validationResult.valid) {
|
||||
return { success: false, error: validationResult.errors.join('; ') };
|
||||
}
|
||||
|
||||
return await executeWithRunnerContext(registry, context, runner, validationResult.command);
|
||||
}
|
||||
|
||||
export type CommandRunnerContext<TContext> = RunnerContext<TContext> & {
|
||||
registry: CommandRegistry<TContext>;
|
||||
};
|
||||
|
||||
export function createCommandRunnerContext<TContext>(
|
||||
registry: CommandRegistry<TContext>,
|
||||
context: TContext
|
||||
): CommandRunnerContext<TContext> {
|
||||
return {
|
||||
registry,
|
||||
context,
|
||||
run: (input: string) => runCommand(registry, context, input),
|
||||
runParsed: (command: Command) => runCommandParsed(registry, context, command),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { Command, CommandSchema } from './types.js';
|
||||
|
||||
export type CommandRunnerContext<TContext> = {
|
||||
context: TContext;
|
||||
run: (input: string) => Promise<{ success: true; result: unknown } | { success: false; error: string }>;
|
||||
runParsed: (command: Command) => Promise<{ success: true; result: unknown } | { success: false; error: string }>;
|
||||
};
|
||||
|
||||
export type CommandRunnerHandler<TContext, TResult> = (
|
||||
this: CommandRunnerContext<TContext>,
|
||||
command: Command
|
||||
) => Promise<TResult>;
|
||||
|
||||
export type CommandRunner<TContext, TResult = unknown> = {
|
||||
schema: CommandSchema;
|
||||
run: CommandRunnerHandler<TContext, TResult>;
|
||||
};
|
||||
@@ -1,6 +1,16 @@
|
||||
export { parseCommand } from './command-parse';
|
||||
export { parseCommand } from './command-parse';
|
||||
export { parseCommandSchema } from './schema-parse';
|
||||
export { validateCommand, parseCommandWithSchema, applyCommandSchema } from './command-validate';
|
||||
export {
|
||||
createCommandRegistry,
|
||||
registerCommand,
|
||||
unregisterCommand,
|
||||
hasCommand,
|
||||
getCommand,
|
||||
runCommand,
|
||||
runCommandParsed,
|
||||
createCommandRunnerContext,
|
||||
} from './command-registry';
|
||||
export type {
|
||||
Command,
|
||||
CommandParamSchema,
|
||||
@@ -8,3 +18,5 @@ export type {
|
||||
CommandFlagSchema,
|
||||
CommandSchema,
|
||||
} from './types';
|
||||
export type { CommandRunner, CommandRunnerHandler } from './command-runner';
|
||||
export type { CommandRegistry, CommandRunnerContext } from './command-registry';
|
||||
|
||||
Reference in New Issue
Block a user