Thin MongoDB ODM built for Standard Schema
mongodb zod deno
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(issues: ValidationIssue[], operation: "insert" | "update" | "replace") { 29 const message = ValidationError.formatIssues(issues); 30 super(`Validation failed on ${operation}: ${message}`); 31 this.issues = issues; 32 this.operation = operation; 33 } 34 35 private static formatIssues(issues: ValidationIssue[]): string { 36 return issues.map(issue => { 37 const path = issue.path.join('.'); 38 return `${path || 'root'}: ${issue.message}`; 39 }).join('; '); 40 } 41 42 /** 43 * Get validation errors grouped by field 44 */ 45 public getFieldErrors(): Record<string, string[]> { 46 const fieldErrors: Record<string, string[]> = {}; 47 for (const issue of this.issues) { 48 const field = issue.path.join('.') || 'root'; 49 if (!fieldErrors[field]) { 50 fieldErrors[field] = []; 51 } 52 fieldErrors[field].push(issue.message); 53 } 54 return fieldErrors; 55 } 56} 57 58/** 59 * Connection error 60 * Thrown when database connection fails or is not established 61 */ 62export class ConnectionError extends NozzleError { 63 public readonly uri?: string; 64 65 constructor(message: string, uri?: string) { 66 super(message); 67 this.uri = uri; 68 } 69} 70 71/** 72 * Configuration error 73 * Thrown when invalid configuration options are provided 74 */ 75export class ConfigurationError extends NozzleError { 76 public readonly option?: string; 77 78 constructor(message: string, option?: string) { 79 super(message); 80 this.option = option; 81 } 82} 83 84/** 85 * Document not found error 86 * Thrown when a required document is not found 87 */ 88export class DocumentNotFoundError extends NozzleError { 89 public readonly query: unknown; 90 public readonly collection: string; 91 92 constructor(collection: string, query: unknown) { 93 super(`Document not found in collection '${collection}'`); 94 this.collection = collection; 95 this.query = query; 96 } 97} 98 99/** 100 * Operation error 101 * Thrown when a database operation fails 102 */ 103export class OperationError extends NozzleError { 104 public readonly operation: string; 105 public readonly collection?: string; 106 public override readonly cause?: Error; 107 108 constructor(operation: string, message: string, collection?: string, cause?: Error) { 109 super(`${operation} operation failed: ${message}`); 110 this.operation = operation; 111 this.collection = collection; 112 this.cause = cause; 113 } 114} 115 116/** 117 * Async validation not supported error 118 * Thrown when async validation is attempted 119 */ 120export class AsyncValidationError extends NozzleError { 121 constructor() { 122 super( 123 "Async validation is not currently supported. " + 124 "Please use synchronous validation schemas." 125 ); 126 } 127}