// engine/schema-parity-auditor/zod-scanner.ts — Extracts optional fields from register-*.ts files
import { readFile } from 'node:fs/promises';
import { glob } from 'glob';
/**
 * Matches optional Zod fields: `fieldName: z.TYPE[...]?.optional()`
 * Captures: [fullMatch, fieldName, zodType]
 */
const OPTIONAL_FIELD_RE = /(\w+):\s*(z\.\w+)[^,\n]*\.optional\(\)/g;
/**
 * Matches tool registration: server.registerTool('tool_name', ...)
 * Captures: [fullMatch, toolName]
 */
const TOOL_NAME_RE = /server\.registerTool\(\s*['"]([^'"]+)['"]/;
/**
 * Scans all register-*.ts files under srcToolsDir and returns
 * a list of fields that are marked .optional() in their Zod schema.
 */
export async function scanZodOptionalFields(projectPath) {
    const pattern = `${projectPath}/src/tools/register-*.ts`;
    const files = await glob(pattern);
    const results = await Promise.all(files.map((file) => extractOptionalFieldsFromFile(file)));
    return results.flat();
}
async function extractOptionalFieldsFromFile(filePath) {
    const content = await readFile(filePath, 'utf-8');
    return parseOptionalFields(content, filePath);
}
/**
 * Parses a register-*.ts file content and extracts optional field definitions.
 * Exported for unit testing.
 */
export function parseOptionalFields(content, filePath) {
    const fields = [];
    // Split content into per-tool blocks by finding registerTool calls
    const toolBlocks = splitIntoToolBlocks(content);
    for (const block of toolBlocks) {
        const toolNameMatch = TOOL_NAME_RE.exec(block);
        const toolName = toolNameMatch?.[1] ?? 'unknown';
        // Reset lastIndex since we re-use the regex
        OPTIONAL_FIELD_RE.lastIndex = 0;
        let match;
        while ((match = OPTIONAL_FIELD_RE.exec(block)) !== null) {
            const fieldName = match[1];
            const zodType = match[2] ?? 'z.unknown';
            if (fieldName !== undefined) {
                fields.push({ registerFile: filePath, toolName, fieldName, zodType });
            }
        }
    }
    return fields;
}
/**
 * Splits file content into sections, one per tool registration block.
 * This is a best-effort split — tools are separated by registerTool calls.
 */
function splitIntoToolBlocks(content) {
    const parts = content.split(/(?=server\.registerTool\()/);
    return parts.length > 0 ? parts : [content];
}
//# sourceMappingURL=zod-scanner.js.map