@naturalcycles/js-lib
Version:
Standard library for universal (browser + Node.js) javascript
53 lines (52 loc) • 1.87 kB
JavaScript
import { _assert } from '../error/assert.js';
import { AppError } from '../error/error.util.js';
import { _stringify } from '../string/stringify.js';
export function getZodValidationFunction(schema) {
return (input, opt) => {
_assert(!opt?.mutateInput, 'mutateInput=true is not yet supported with Zod');
return zSafeValidate(input, schema);
};
}
export function zIsValid(value, schema) {
const { success } = schema.safeParse(value);
return success;
}
export function zValidate(value, schema) {
const [err, data] = zSafeValidate(value, schema);
if (err)
throw err;
return data;
}
export function zSafeValidate(input, schema) {
const r = schema.safeParse(input);
if (r.success) {
return [null, r.data];
}
return [new ZodValidationError(r.error, input, schema), r.data ?? input];
}
export class ZodValidationError extends AppError {
constructor(zodError, value, schema) {
const message = createZodErrorMessage(zodError, schema, value);
// const message = z.prettifyError(zodError) // todo: consider adopting it instead
super(message, {}, { name: 'ZodValidationError' });
}
}
function createZodErrorMessage(err, schema, value) {
let objectTitle = schema.description;
if (typeof value === 'object' && value) {
const inputName = schema.description || value.constructor?.name;
const inputId = value['id'];
objectTitle = [inputName, inputId].filter(Boolean).join('.');
}
objectTitle ||= 'data';
return [
`Invalid ${objectTitle}`,
'',
'Input:',
_stringify(value),
err.issues.length > 1 ? `\n${err.issues.length} issues:` : '',
...err.issues.slice(0, 100).map(i => {
return [i.path.join('.'), i.message].filter(Boolean).join(': ');
}),
].join('\n');
}