46 lines
1.7 KiB
TypeScript
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 };
|
|
}
|