znv
Version:
Parse your environment with Zod schemas
63 lines • 2.94 kB
JavaScript
import { ZodError, ZodIssueCode } from "zod";
// Even though we also have our own formatter, we pass a custom error map to
// Zod's `.parse()` for two reasons:
// - to ensure that no other consumer of zod in the codebase has set a default
// error map that might override our formatting
// - to return slightly friendlier error messages in some common scenarios.
export const errorMap = (issue, ctx) => {
if (issue.code === ZodIssueCode.invalid_type &&
issue.received === "undefined") {
return { message: "This field is required." };
}
return { message: ctx.defaultError };
};
const indent = (str, amt) => `${" ".repeat(amt)}${str}`;
export function makeDefaultReporter(formatters) {
const reporter = (errors, schemas) => reportErrors(errors, schemas, formatters);
return reporter;
}
export function reportErrors(errors, schemas, { formatVarName = String, formatObjKey = String, formatReceivedValue = String, formatDefaultValue = String, formatHeader = String, } = {}) {
const formattedErrors = errors.map(({ key, receivedValue, error, defaultUsed, defaultValue }) => {
let title = `[${formatVarName(key)}]:`;
const desc = schemas[key]?.description;
if (desc) {
title += ` ${desc}`;
}
const message = [title];
if (error instanceof ZodError) {
const { formErrors, fieldErrors } = error.flatten();
for (const fe of formErrors)
message.push(indent(fe, 2));
const fieldErrorEntries = Object.entries(fieldErrors);
if (fieldErrorEntries.length > 0) {
message.push(indent("Errors on object keys:", 2));
for (const [objKey, keyErrors] of fieldErrorEntries) {
message.push(indent(`[${formatObjKey(objKey)}]:`, 4));
if (keyErrors) {
for (const fe of keyErrors)
message.push(indent(fe, 6));
}
}
}
}
else if (error instanceof Error) {
message.push(...error.message.split("\n").map((l) => indent(l, 2)));
}
else {
message.push(...JSON.stringify(error, undefined, 2)
.split("\n")
.map((l) => indent(l, 2)));
}
message.push(indent(`(received ${formatReceivedValue(receivedValue === undefined
? "undefined"
: JSON.stringify(receivedValue))})`, 2));
if (defaultUsed) {
message.push(indent(`(used default of ${formatDefaultValue(defaultValue === undefined
? "undefined"
: JSON.stringify(defaultValue))})`, 2));
}
return message.map((l) => indent(l, 2)).join("\n");
});
return `${formatHeader("Errors found while parsing environment:")}\n${formattedErrors.join("\n\n")}\n`;
}
//# sourceMappingURL=reporter.js.map