@schema-hub/zod-error-formatter
Version:
Simple and easy-to-understand zod error messages
77 lines • 2.87 kB
JavaScript
import { util } from 'zod/v4/core';
import { formatOneOfList, isParsedType } from '../list.js';
import { findValueByPath } from '../path.js';
function flattenAllIssues(errors) {
return errors.flatMap((issues) => {
return issues.flatMap((issue) => {
if (issue.code === 'invalid_union') {
return flattenAllIssues(issue.errors);
}
return issue;
});
});
}
function isSamePath(pathA, pathB) {
if (pathA.length !== pathB.length) {
return false;
}
return pathA.every((element, index) => {
return element === pathB[index];
});
}
function isSupportedIssueWithSamePath(issue, expectedPath) {
return ['invalid_type', 'invalid_value'].includes(issue.code) && isSamePath(issue.path, expectedPath);
}
function filterSupportedIssuesWithSamePath(issues, expectedPath) {
return issues.filter((issue) => {
return isSupportedIssueWithSamePath(issue, expectedPath);
});
}
function isPrimitive(value) {
return ['string', 'number', 'symbol', 'bigint', 'boolean', 'undefined'].includes(typeof value) || value === null;
}
function determineExpectedValue(issue) {
if (issue.code === 'invalid_type') {
return { type: issue.expected };
}
if (isPrimitive(issue.values[0])) {
return issue.values[0];
}
return JSON.stringify(issue.values);
}
function hasValue(values, expectedValue) {
return values.some((value) => {
if (isParsedType(value) && isParsedType(expectedValue)) {
return value.type === expectedValue.type;
}
return value === expectedValue;
});
}
function removeDuplicateListValues(values) {
const uniqueValues = [];
for (const value of values) {
if (!hasValue(uniqueValues, value)) {
uniqueValues.push(value);
}
}
return uniqueValues;
}
// eslint-disable-next-line max-statements -- no idea how to refactor right now
export function formatInvalidUnionIssueMessage(issue, input) {
const result = findValueByPath(input, issue.path);
if (result.found) {
const memberIssues = flattenAllIssues(issue.errors);
const supportedIssues = filterSupportedIssuesWithSamePath(memberIssues, []);
if (memberIssues.length === supportedIssues.length) {
const [firstIssue] = supportedIssues;
if (firstIssue !== undefined) {
const expectedValues = removeDuplicateListValues(supportedIssues.map(determineExpectedValue));
const receivedValue = util.getParsedType(result.value);
return `invalid value: expected ${formatOneOfList(expectedValues)}, but got ${receivedValue}`;
}
}
return 'invalid value doesn’t match expected union';
}
return `missing ${result.pathItemKind}`;
}
//# sourceMappingURL=invalid-union.js.map