All files / src/middleware zodValidation.ts

100% Statements 40/40
81.25% Branches 13/16
100% Functions 1/1
100% Lines 40/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61  2x                         2x 17x 17x 17x 17x 17x 17x 17x 17x 17x   17x 17x   17x 6x   6x   6x 1x 6x 4x 4x 4x 5x 1x 1x 3x 3x 1x 1x 1x   6x 6x   17x 3x 9x 9x 3x 3x 17x 17x    
import type { WSListenCallback } from '../PerfectWS.js';
import { PerfectWSError } from '../PerfectWSError.js';
 
type ZodSchema = {
    safeParse(data: unknown): { success: boolean; data?: unknown; error?: { issues: Array<{ path: Array<string | number>; message: string; }>; }; };
};
 
export interface ValidationOptions {
    stripUnknown?: boolean;
    abortEarly?: boolean;
    customErrorMessage?: string;
    errorCode?: string;
}
 
export function validateWithZod(
    schema: ZodSchema,
    options: ValidationOptions = {}
): WSListenCallback {
    const {
        stripUnknown = false,
        abortEarly = true,
        customErrorMessage,
        errorCode = 'validationError'
    } = options;
 
    return (data: any) => {
        const result = schema.safeParse(data);
 
        if (!result.success) {
            const errors = result.error?.issues || [];
 
            let errorMessage: string;
 
            if (customErrorMessage) {
                errorMessage = customErrorMessage;
            } else if (abortEarly && errors.length > 0) {
                const firstError = errors[0];
                const path = firstError.path.join('.');
                errorMessage = path ? `${path}: ${firstError.message}` : firstError.message;
            } else {
                errorMessage = errors
                    .map(err => {
                        const path = err.path.join('.');
                        return path ? `${path}: ${err.message}` : err.message;
                    })
                    .join(', ');
            }
 
            throw new PerfectWSError(errorMessage, errorCode);
        }
 
        if (stripUnknown && result.data) {
            for (const key in data) {
                delete data[key];
            }
            Object.assign(data, result.data);
        }
    };
}