PettyUI/packages/mcp/src/tools/validate.ts
2026-03-29 23:50:58 +07:00

46 lines
1.7 KiB
TypeScript

import type { ComponentRegistry } from "../registry.js";
interface ValidateInput { component: string; schema?: string; props?: Record<string, unknown>; parts?: string[]; }
interface ValidateResult { valid: boolean; errors: string[]; }
interface ZodParseIssue { message: string; path: (string | number)[]; }
interface ZodParseError { issues: ZodParseIssue[]; }
interface ZodParseResult { success: boolean; error?: ZodParseError; }
interface ZodSchema { safeParse(data: unknown): ZodParseResult; }
/** Validates props against schema and/or checks required parts are present. */
export function handleValidate(registry: ComponentRegistry, input: ValidateInput): ValidateResult {
const comp = registry.getComponent(input.component);
if (!comp) return { valid: false, errors: [`Component "${input.component}" not found`] };
const errors: string[] = [];
// Validate props against named schema
if (input.props !== undefined && input.schema) {
const schema = comp.schemas[input.schema];
if (!schema) {
errors.push(`Schema "${input.schema}" not found on ${comp.meta.name}`);
} else {
const zSchema = schema as ZodSchema;
const result = zSchema.safeParse(input.props);
if (!result.success && result.error) {
for (const issue of result.error.issues) {
const pathStr = issue.path.length > 0 ? ` at "${issue.path.join(".")}"` : "";
errors.push(`${issue.message}${pathStr}`);
}
}
}
}
// Check required parts
if (input.parts !== undefined) {
for (const required of comp.meta.requiredParts) {
if (!input.parts.includes(required)) {
errors.push(`Missing required part: ${required}`);
}
}
}
return { valid: errors.length === 0, errors };
}