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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 205x 205x 205x 205x 205x 2x 2x 2x 9x 2x 2x 2x 6x 6x 3x 5x 5x 5x 2x 3x 2x 1x 2x 2x 2x 2x 178x 2x 2x 2x 3x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 3x 2x 2x | // src/services/processingErrors.ts /** * Base class for all flyer processing errors. * This allows for catching all processing-related errors with a single `catch` block. * Each custom error should define its own `errorCode` and a user-friendly `message`. */ export class FlyerProcessingError extends Error { public errorCode: string; public userMessage: string; constructor(message: string, errorCode: string = 'UNKNOWN_ERROR', userMessage?: string) { super(message); // The 'message' property of Error is for internal/developer use. this.name = this.constructor.name; this.errorCode = errorCode; this.userMessage = userMessage || message; // User-friendly message for UI Object.setPrototypeOf(this, new.target.prototype); } toErrorPayload(): { errorCode: string; message: string; [key: string]: unknown } { return { errorCode: this.errorCode, message: this.userMessage }; } } /** * Error thrown when PDF to image conversion fails (e.g., pdftocairo produces no output). */ export class PdfConversionError extends FlyerProcessingError { public stderr?: string; constructor(message: string, stderr?: string) { super( message, 'PDF_CONVERSION_FAILED', 'The uploaded PDF could not be processed. It might be blank, corrupt, or password-protected.', ); this.stderr = stderr; } toErrorPayload(): { errorCode: string; message: string; [key: string]: unknown } { return { ...super.toErrorPayload(), stderr: this.stderr }; } } /** * Error thrown when the data returned from the AI service fails Zod validation. */ export class AiDataValidationError extends FlyerProcessingError { constructor( message: string, public validationErrors: object, public rawData: unknown, ) { super( message, 'AI_VALIDATION_FAILED', "The AI couldn't read the flyer's format. Please try a clearer image or a different flyer.", ); } toErrorPayload(): { errorCode: string; message: string; [key: string]: unknown } { return { ...super.toErrorPayload(), validationErrors: this.validationErrors, rawData: this.rawData, }; } } /** * Error thrown when a transformation step fails. */ export class TransformationError extends FlyerProcessingError { constructor(message: string) { super( message, 'TRANSFORMATION_FAILED', 'There was a problem transforming the flyer data. Please check the input.', ); } } /** * Error thrown when a database operation fails during processing. */ export class DatabaseError extends FlyerProcessingError { constructor(message: string) { super(message, 'DATABASE_ERROR', 'A database operation failed. Please try again later.'); } } /** * Error thrown when an image conversion fails (e.g., using sharp). */ export class ImageConversionError extends FlyerProcessingError { constructor(message: string) { super( message, 'IMAGE_CONVERSION_FAILED', 'The uploaded image could not be processed. It might be corrupt or in an unsupported format.', ); } } /** * Error thrown when all geocoding providers fail to find coordinates for an address. */ export class GeocodingFailedError extends FlyerProcessingError { constructor(message: string) { super(message, 'GEOCODING_FAILED', 'Failed to geocode the address.'); } } /** * Error thrown when an uploaded file is of an unsupported type (e.g., .gif, .tiff). */ export class UnsupportedFileTypeError extends FlyerProcessingError { constructor(message: string) { super(message, 'UNSUPPORTED_FILE_TYPE', message); // The message is already user-friendly. } } |