"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Json5 = exports.Json = exports.LooseRecord = exports.LooseArray = void 0;
const tslib_1 = require("tslib");
const json5_1 = tslib_1.__importDefault(require("json5"));
const zod_1 = require("zod");
/**
 * Works like `z.array()`, but drops wrong elements instead of invalidating the whole array.
 *
 * **Important**: non-array inputs are still invalid.
 * Use `LooseArray(...).catch([])` to handle it.
 *
 * @param Elem Schema for array elements
 * @param onError Callback for errors
 * @returns Schema for array
 */
function LooseArray(Elem, { onError } = {}) {
    if (!onError) {
        // Avoid error-related computations inside the loop
        return zod_1.z.array(zod_1.z.any()).transform((input) => {
            const output = [];
            for (const x of input) {
                const parsed = Elem.safeParse(x);
                if (parsed.success) {
                    output.push(parsed.data);
                }
            }
            return output;
        });
    }
    return zod_1.z.array(zod_1.z.any()).transform((input) => {
        const output = [];
        const issues = [];
        for (let idx = 0; idx < input.length; idx += 1) {
            const x = input[idx];
            const parsed = Elem.safeParse(x);
            if (parsed.success) {
                output.push(parsed.data);
                continue;
            }
            for (const issue of parsed.error.issues) {
                issue.path.unshift(idx);
                issues.push(issue);
            }
        }
        if (issues.length) {
            const error = new zod_1.z.ZodError(issues);
            onError({ error, input });
        }
        return output;
    });
}
exports.LooseArray = LooseArray;
/**
 * Works like `z.record()`, but drops wrong elements instead of invalidating the whole record.
 *
 * **Important**: non-record inputs other are still invalid.
 * Use `LooseRecord(...).catch({})` to handle it.
 *
 * @param Elem Schema for record values
 * @param onError Callback for errors
 * @returns Schema for record
 */
function LooseRecord(Elem, { onError } = {}) {
    if (!onError) {
        // Avoid error-related computations inside the loop
        return zod_1.z.record(zod_1.z.any()).transform((input) => {
            const output = {};
            for (const [key, val] of Object.entries(input)) {
                const parsed = Elem.safeParse(val);
                if (parsed.success) {
                    output[key] = parsed.data;
                }
            }
            return output;
        });
    }
    return zod_1.z.record(zod_1.z.any()).transform((input) => {
        const output = {};
        const issues = [];
        for (const [key, val] of Object.entries(input)) {
            const parsed = Elem.safeParse(val);
            if (parsed.success) {
                output[key] = parsed.data;
                continue;
            }
            for (const issue of parsed.error.issues) {
                issue.path.unshift(key);
                issues.push(issue);
            }
        }
        if (issues.length) {
            const error = new zod_1.z.ZodError(issues);
            onError({ error, input });
        }
        return output;
    });
}
exports.LooseRecord = LooseRecord;
exports.Json = zod_1.z.string().transform((str, ctx) => {
    try {
        return JSON.parse(str);
    }
    catch (e) {
        ctx.addIssue({ code: 'custom', message: 'Invalid JSON' });
        return zod_1.z.NEVER;
    }
});
exports.Json5 = zod_1.z.string().transform((str, ctx) => {
    try {
        return json5_1.default.parse(str);
    }
    catch (e) {
        ctx.addIssue({ code: 'custom', message: 'Invalid JSON5' });
        return zod_1.z.NEVER;
    }
});
//# sourceMappingURL=schema-utils.js.map