| import { util } from "./helpers/util.js"; |
| export const ZodIssueCode = util.arrayToEnum([ |
| "invalid_type", |
| "invalid_literal", |
| "custom", |
| "invalid_union", |
| "invalid_union_discriminator", |
| "invalid_enum_value", |
| "unrecognized_keys", |
| "invalid_arguments", |
| "invalid_return_type", |
| "invalid_date", |
| "invalid_string", |
| "too_small", |
| "too_big", |
| "invalid_intersection_types", |
| "not_multiple_of", |
| "not_finite", |
| ]); |
| export const quotelessJson = (obj) => { |
| const json = JSON.stringify(obj, null, 2); |
| return json.replace(/"([^"]+)":/g, "$1:"); |
| }; |
| export class ZodError extends Error { |
| get errors() { |
| return this.issues; |
| } |
| constructor(issues) { |
| super(); |
| this.issues = []; |
| this.addIssue = (sub) => { |
| this.issues = [...this.issues, sub]; |
| }; |
| this.addIssues = (subs = []) => { |
| this.issues = [...this.issues, ...subs]; |
| }; |
| const actualProto = new.target.prototype; |
| if (Object.setPrototypeOf) { |
| // eslint-disable-next-line ban/ban |
| Object.setPrototypeOf(this, actualProto); |
| } |
| else { |
| this.__proto__ = actualProto; |
| } |
| this.name = "ZodError"; |
| this.issues = issues; |
| } |
| format(_mapper) { |
| const mapper = _mapper || |
| function (issue) { |
| return issue.message; |
| }; |
| const fieldErrors = { _errors: [] }; |
| const processError = (error) => { |
| for (const issue of error.issues) { |
| if (issue.code === "invalid_union") { |
| issue.unionErrors.map(processError); |
| } |
| else if (issue.code === "invalid_return_type") { |
| processError(issue.returnTypeError); |
| } |
| else if (issue.code === "invalid_arguments") { |
| processError(issue.argumentsError); |
| } |
| else if (issue.path.length === 0) { |
| fieldErrors._errors.push(mapper(issue)); |
| } |
| else { |
| let curr = fieldErrors; |
| let i = 0; |
| while (i < issue.path.length) { |
| const el = issue.path[i]; |
| const terminal = i === issue.path.length - 1; |
| if (!terminal) { |
| curr[el] = curr[el] || { _errors: [] }; |
| // if (typeof el === "string") { |
| // curr[el] = curr[el] || { _errors: [] }; |
| // } else if (typeof el === "number") { |
| // const errorArray: any = []; |
| // errorArray._errors = []; |
| // curr[el] = curr[el] || errorArray; |
| // } |
| } |
| else { |
| curr[el] = curr[el] || { _errors: [] }; |
| curr[el]._errors.push(mapper(issue)); |
| } |
| curr = curr[el]; |
| i++; |
| } |
| } |
| } |
| }; |
| processError(this); |
| return fieldErrors; |
| } |
| static assert(value) { |
| if (!(value instanceof ZodError)) { |
| throw new Error(`Not a ZodError: ${value}`); |
| } |
| } |
| toString() { |
| return this.message; |
| } |
| get message() { |
| return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2); |
| } |
| get isEmpty() { |
| return this.issues.length === 0; |
| } |
| flatten(mapper = (issue) => issue.message) { |
| const fieldErrors = {}; |
| const formErrors = []; |
| for (const sub of this.issues) { |
| if (sub.path.length > 0) { |
| const firstEl = sub.path[0]; |
| fieldErrors[firstEl] = fieldErrors[firstEl] || []; |
| fieldErrors[firstEl].push(mapper(sub)); |
| } |
| else { |
| formErrors.push(mapper(sub)); |
| } |
| } |
| return { formErrors, fieldErrors }; |
| } |
| get formErrors() { |
| return this.flatten(); |
| } |
| } |
| ZodError.create = (issues) => { |
| const error = new ZodError(issues); |
| return error; |
| }; |