MCP validate tool
This commit is contained in:
parent
0e5033414b
commit
e4a91d9386
@ -3,6 +3,11 @@ import type { ComponentRegistry } from "../registry.js";
|
|||||||
interface ValidateInput { component: string; schema?: string; props?: Record<string, unknown>; parts?: string[]; }
|
interface ValidateInput { component: string; schema?: string; props?: Record<string, unknown>; parts?: string[]; }
|
||||||
interface ValidateResult { valid: boolean; errors: 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. */
|
/** Validates props against schema and/or checks required parts are present. */
|
||||||
export function handleValidate(registry: ComponentRegistry, input: ValidateInput): ValidateResult {
|
export function handleValidate(registry: ComponentRegistry, input: ValidateInput): ValidateResult {
|
||||||
const comp = registry.getComponent(input.component);
|
const comp = registry.getComponent(input.component);
|
||||||
@ -16,8 +21,7 @@ export function handleValidate(registry: ComponentRegistry, input: ValidateInput
|
|||||||
if (!schema) {
|
if (!schema) {
|
||||||
errors.push(`Schema "${input.schema}" not found on ${comp.meta.name}`);
|
errors.push(`Schema "${input.schema}" not found on ${comp.meta.name}`);
|
||||||
} else {
|
} else {
|
||||||
// schema is a Zod schema — call safeParse
|
const zSchema = schema as ZodSchema;
|
||||||
const zSchema = schema as { safeParse: (data: unknown) => { success: boolean; error?: { issues: Array<{ message: string; path: (string | number)[] }> } } };
|
|
||||||
const result = zSchema.safeParse(input.props);
|
const result = zSchema.safeParse(input.props);
|
||||||
if (!result.success && result.error) {
|
if (!result.success && result.error) {
|
||||||
for (const issue of result.error.issues) {
|
for (const issue of result.error.issues) {
|
||||||
|
|||||||
43
packages/mcp/tests/tools/validate.test.ts
Normal file
43
packages/mcp/tests/tools/validate.test.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
import { handleValidate } from "../../src/tools/validate.js";
|
||||||
|
import { ComponentRegistry } from "../../src/registry.js";
|
||||||
|
|
||||||
|
describe("pettyui.validate", () => {
|
||||||
|
const registry = new ComponentRegistry();
|
||||||
|
|
||||||
|
it("validates correct props", () => {
|
||||||
|
const result = handleValidate(registry, { component: "Dialog", schema: "dialogRoot", props: { open: true, modal: false } });
|
||||||
|
expect(result.valid).toBe(true);
|
||||||
|
expect(result.errors).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects invalid props", () => {
|
||||||
|
const result = handleValidate(registry, { component: "Dialog", schema: "dialogRoot", props: { open: "yes" } });
|
||||||
|
expect(result.valid).toBe(false);
|
||||||
|
expect(result.errors.length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("validates empty props", () => {
|
||||||
|
const result = handleValidate(registry, { component: "Dialog", schema: "dialogRoot", props: {} });
|
||||||
|
expect(result.valid).toBe(true);
|
||||||
|
expect(result.errors).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("checks required parts present — missing Title", () => {
|
||||||
|
const result = handleValidate(registry, { component: "Dialog", parts: ["Root", "Content"] });
|
||||||
|
expect(result.valid).toBe(false);
|
||||||
|
expect(result.errors).toContain("Missing required part: Title");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("passes when all required parts provided", () => {
|
||||||
|
const result = handleValidate(registry, { component: "Dialog", parts: ["Root", "Content", "Title"] });
|
||||||
|
expect(result.valid).toBe(true);
|
||||||
|
expect(result.errors).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns error for unknown component", () => {
|
||||||
|
const result = handleValidate(registry, { component: "FakeComponent" });
|
||||||
|
expect(result.valid).toBe(false);
|
||||||
|
expect(result.errors).toContain('Component "FakeComponent" not found');
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user