Thin MongoDB ODM built for Standard Schema
mongodb zod deno
at main 3.4 kB view raw
1import type { z } from "@zod/zod"; 2 3// Type for Zod validation issues 4type ValidationIssue = z.ZodIssue; 5 6/** 7 * Base error class for all Nozzle errors 8 */ 9export class NozzleError extends Error { 10 constructor(message: string) { 11 super(message); 12 this.name = this.constructor.name; 13 // Maintains proper stack trace for where error was thrown (only available on V8) 14 if (Error.captureStackTrace) { 15 Error.captureStackTrace(this, this.constructor); 16 } 17 } 18} 19 20/** 21 * Validation error with structured issue details 22 * Thrown when data fails schema validation 23 */ 24export class ValidationError extends NozzleError { 25 public readonly issues: ValidationIssue[]; 26 public readonly operation: "insert" | "update" | "replace"; 27 28 constructor( 29 issues: ValidationIssue[], 30 operation: "insert" | "update" | "replace", 31 ) { 32 const message = ValidationError.formatIssues(issues); 33 super(`Validation failed on ${operation}: ${message}`); 34 this.issues = issues; 35 this.operation = operation; 36 } 37 38 private static formatIssues(issues: ValidationIssue[]): string { 39 return issues.map((issue) => { 40 const path = issue.path.join("."); 41 return `${path || "root"}: ${issue.message}`; 42 }).join("; "); 43 } 44 45 /** 46 * Get validation errors grouped by field 47 */ 48 public getFieldErrors(): Record<string, string[]> { 49 const fieldErrors: Record<string, string[]> = {}; 50 for (const issue of this.issues) { 51 const field = issue.path.join(".") || "root"; 52 if (!fieldErrors[field]) { 53 fieldErrors[field] = []; 54 } 55 fieldErrors[field].push(issue.message); 56 } 57 return fieldErrors; 58 } 59} 60 61/** 62 * Connection error 63 * Thrown when database connection fails or is not established 64 */ 65export class ConnectionError extends NozzleError { 66 public readonly uri?: string; 67 68 constructor(message: string, uri?: string) { 69 super(message); 70 this.uri = uri; 71 } 72} 73 74/** 75 * Configuration error 76 * Thrown when invalid configuration options are provided 77 */ 78export class ConfigurationError extends NozzleError { 79 public readonly option?: string; 80 81 constructor(message: string, option?: string) { 82 super(message); 83 this.option = option; 84 } 85} 86 87/** 88 * Document not found error 89 * Thrown when a required document is not found 90 */ 91export class DocumentNotFoundError extends NozzleError { 92 public readonly query: unknown; 93 public readonly collection: string; 94 95 constructor(collection: string, query: unknown) { 96 super(`Document not found in collection '${collection}'`); 97 this.collection = collection; 98 this.query = query; 99 } 100} 101 102/** 103 * Operation error 104 * Thrown when a database operation fails 105 */ 106export class OperationError extends NozzleError { 107 public readonly operation: string; 108 public readonly collection?: string; 109 public override readonly cause?: Error; 110 111 constructor( 112 operation: string, 113 message: string, 114 collection?: string, 115 cause?: Error, 116 ) { 117 super(`${operation} operation failed: ${message}`); 118 this.operation = operation; 119 this.collection = collection; 120 this.cause = cause; 121 } 122} 123 124/** 125 * Async validation not supported error 126 * Thrown when async validation is attempted 127 */ 128export class AsyncValidationError extends NozzleError { 129 constructor() { 130 super( 131 "Async validation is not currently supported. " + 132 "Please use synchronous validation schemas.", 133 ); 134 } 135}