| import { getErrorMap } from "../errors.js"; |
| import defaultErrorMap from "../locales/en.js"; |
| export const makeIssue = (params) => { |
| const { data, path, errorMaps, issueData } = params; |
| const fullPath = [...path, ...(issueData.path || [])]; |
| const fullIssue = { |
| ...issueData, |
| path: fullPath, |
| }; |
| if (issueData.message !== undefined) { |
| return { |
| ...issueData, |
| path: fullPath, |
| message: issueData.message, |
| }; |
| } |
| let errorMessage = ""; |
| const maps = errorMaps |
| .filter((m) => !!m) |
| .slice() |
| .reverse(); |
| for (const map of maps) { |
| errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message; |
| } |
| return { |
| ...issueData, |
| path: fullPath, |
| message: errorMessage, |
| }; |
| }; |
| export const EMPTY_PATH = []; |
| export function addIssueToContext(ctx, issueData) { |
| const overrideMap = getErrorMap(); |
| const issue = makeIssue({ |
| issueData: issueData, |
| data: ctx.data, |
| path: ctx.path, |
| errorMaps: [ |
| ctx.common.contextualErrorMap, // contextual error map is first priority |
| ctx.schemaErrorMap, // then schema-bound map if available |
| overrideMap, // then global override map |
| overrideMap === defaultErrorMap ? undefined : defaultErrorMap, // then global default map |
| ].filter((x) => !!x), |
| }); |
| ctx.common.issues.push(issue); |
| } |
| export class ParseStatus { |
| constructor() { |
| this.value = "valid"; |
| } |
| dirty() { |
| if (this.value === "valid") |
| this.value = "dirty"; |
| } |
| abort() { |
| if (this.value !== "aborted") |
| this.value = "aborted"; |
| } |
| static mergeArray(status, results) { |
| const arrayValue = []; |
| for (const s of results) { |
| if (s.status === "aborted") |
| return INVALID; |
| if (s.status === "dirty") |
| status.dirty(); |
| arrayValue.push(s.value); |
| } |
| return { status: status.value, value: arrayValue }; |
| } |
| static async mergeObjectAsync(status, pairs) { |
| const syncPairs = []; |
| for (const pair of pairs) { |
| const key = await pair.key; |
| const value = await pair.value; |
| syncPairs.push({ |
| key, |
| value, |
| }); |
| } |
| return ParseStatus.mergeObjectSync(status, syncPairs); |
| } |
| static mergeObjectSync(status, pairs) { |
| const finalObject = {}; |
| for (const pair of pairs) { |
| const { key, value } = pair; |
| if (key.status === "aborted") |
| return INVALID; |
| if (value.status === "aborted") |
| return INVALID; |
| if (key.status === "dirty") |
| status.dirty(); |
| if (value.status === "dirty") |
| status.dirty(); |
| if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) { |
| finalObject[key.value] = value.value; |
| } |
| } |
| return { status: status.value, value: finalObject }; |
| } |
| } |
| export const INVALID = Object.freeze({ |
| status: "aborted", |
| }); |
| export const DIRTY = (value) => ({ status: "dirty", value }); |
| export const OK = (value) => ({ status: "valid", value }); |
| export const isAborted = (x) => x.status === "aborted"; |
| export const isDirty = (x) => x.status === "dirty"; |
| export const isValid = (x) => x.status === "valid"; |
| export const isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise; |