remove zod-validation-error from deps by merging. it started causing weird errors. OpenSource FTW

This commit is contained in:
Adam Matthiesen 2024-02-12 05:21:41 -08:00
parent d0f56a3ec4
commit 866541ae03
14 changed files with 172 additions and 3 deletions

View File

@ -5,7 +5,7 @@ import type { UserConfig } from "./types";
import ghostSitemap from "./src/integrations/sitemap";
import ghostRobots from "./src/integrations/robots-txt";
import { loadEnv } from 'vite';
import { fromZodError } from "zod-validation-error";
import { fromZodError } from "./src/utils/zod-validation/fromZodError.js";
import { addVirtualImport } from "./src/utils/add-virtual-import";
import { fileURLToPath } from "node:url";
import path from "node:path";

View File

@ -104,7 +104,6 @@
"satori-html": "^0.3.2",
"vite": "^5.0.12",
"vite-tsconfig-paths": "^4.2.2",
"zod": "^3.22.4",
"zod-validation-error": "^3.0.0"
"zod": "^3.22.4"
}
}

View File

@ -0,0 +1,22 @@
import * as zod from 'zod';
export class ValidationError extends Error {
name;
details;
constructor(message, options) {
super(message, options);
this.name = 'ZodValidationError';
this.details = getIssuesFromErrorOptions(options);
}
toString() {
return this.message;
}
}
function getIssuesFromErrorOptions(options) {
if (options) {
const cause = options.cause;
if (cause instanceof zod.ZodError) {
return cause.issues;
}
}
return [];
}

View File

@ -0,0 +1,5 @@
export const ISSUE_SEPARATOR = '; ';
export const MAX_ISSUES_IN_MESSAGE = 99;
export const PREFIX = 'Validation error';
export const PREFIX_SEPARATOR = ': ';
export const UNION_SEPARATOR = ', or ';

View File

@ -0,0 +1,10 @@
import { fromZodIssue } from './fromZodIssue';
export const errorMap = (issue, ctx) => {
const error = fromZodIssue({
...issue,
message: issue.message ?? ctx.defaultError,
});
return {
message: error.message,
};
};

View File

@ -0,0 +1,21 @@
import { ISSUE_SEPARATOR, MAX_ISSUES_IN_MESSAGE, PREFIX, PREFIX_SEPARATOR, UNION_SEPARATOR, } from './config';
import { getMessageFromZodIssue } from './fromZodIssue';
import { prefixMessage } from './prefixMessage';
import { ValidationError } from './ValidationError';
export function fromZodError(zodError, options = {}) {
const { maxIssuesInMessage = MAX_ISSUES_IN_MESSAGE, issueSeparator = ISSUE_SEPARATOR, unionSeparator = UNION_SEPARATOR, prefixSeparator = PREFIX_SEPARATOR, prefix = PREFIX, includePath = true, } = options;
const zodIssues = zodError.errors;
const reason = zodIssues.length === 0
? zodError.message
: zodIssues
.slice(0, maxIssuesInMessage)
.map((issue) => getMessageFromZodIssue({
issue,
issueSeparator,
unionSeparator,
includePath,
}))
.join(issueSeparator);
const message = prefixMessage(reason, prefix, prefixSeparator);
return new ValidationError(message, { cause: zodError });
}

View File

@ -0,0 +1,48 @@
import * as zod from 'zod';
import { ISSUE_SEPARATOR, PREFIX, PREFIX_SEPARATOR, UNION_SEPARATOR, } from './config';
import { prefixMessage } from './prefixMessage';
import { joinPath } from './utils/joinPath';
import { isNonEmptyArray } from './utils/NonEmptyArray';
import { ValidationError } from './ValidationError';
export function getMessageFromZodIssue(props) {
const { issue, issueSeparator, unionSeparator, includePath } = props;
if (issue.code === 'invalid_union') {
return issue.unionErrors
.reduce((acc, zodError) => {
const newIssues = zodError.issues
.map((issue) => getMessageFromZodIssue({
issue,
issueSeparator,
unionSeparator,
includePath,
}))
.join(issueSeparator);
if (!acc.includes(newIssues)) {
acc.push(newIssues);
}
return acc;
}, [])
.join(unionSeparator);
}
if (includePath && isNonEmptyArray(issue.path)) {
if (issue.path.length === 1) {
const identifier = issue.path[0];
if (typeof identifier === 'number') {
return `${issue.message} at index ${identifier}`;
}
}
return `${issue.message} at "${joinPath(issue.path)}"`;
}
return issue.message;
}
export function fromZodIssue(issue, options = {}) {
const { issueSeparator = ISSUE_SEPARATOR, unionSeparator = UNION_SEPARATOR, prefixSeparator = PREFIX_SEPARATOR, prefix = PREFIX, includePath = true, } = options;
const reason = getMessageFromZodIssue({
issue,
issueSeparator,
unionSeparator,
includePath,
});
const message = prefixMessage(reason, prefix, prefixSeparator);
return new ValidationError(message, { cause: new zod.ZodError([issue]) });
}

View File

@ -0,0 +1,7 @@
export { ValidationError } from './ValidationError';
export { isValidationError } from './isValidationError';
export { isValidationErrorLike } from './isValidationErrorLike';
export { errorMap } from './errorMap';
export { fromZodIssue, } from './fromZodIssue';
export { fromZodError, } from './fromZodError';
export { toValidationError } from './toValidationError';

View File

@ -0,0 +1,4 @@
import { ValidationError } from './ValidationError';
export function isValidationError(err) {
return err instanceof ValidationError;
}

View File

@ -0,0 +1,3 @@
export function isValidationErrorLike(err) {
return err instanceof Error && err.name === 'ZodValidationError';
}

View File

@ -0,0 +1,13 @@
import { PREFIX } from './config';
export function prefixMessage(message, prefix, prefixSeparator) {
if (prefix !== null) {
if (message.length > 0) {
return [prefix, message].join(prefixSeparator);
}
return prefix;
}
if (message.length > 0) {
return message;
}
return PREFIX;
}

View File

@ -0,0 +1,12 @@
import * as zod from 'zod';
import { fromZodError } from './fromZodError';
import { ValidationError } from './ValidationError';
export const toValidationError = (options = {}) => (err) => {
if (err instanceof zod.ZodError) {
return fromZodError(err, options);
}
if (err instanceof Error) {
return new ValidationError(err.message, { cause: err });
}
return new ValidationError('Unknown error');
};

View File

@ -0,0 +1,3 @@
export function isNonEmptyArray(value) {
return value.length !== 0;
}

View File

@ -0,0 +1,22 @@
const identifierRegex = /[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*/u;
export function joinPath(path) {
if (path.length === 1) {
return path[0].toString();
}
return path.reduce((acc, item) => {
if (typeof item === 'number') {
return acc + '[' + item.toString() + ']';
}
if (item.includes('"')) {
return acc + '["' + escapeQuotes(item) + '"]';
}
if (!identifierRegex.test(item)) {
return acc + '["' + item + '"]';
}
const separator = acc.length === 0 ? '' : '.';
return acc + separator + item;
}, '');
}
function escapeQuotes(str) {
return str.replace(/"/g, '\\"');
}