1+ /**
2+ * Custom error classes for storage operations
3+ * Provides structured error handling for IndexedDB and storage provider operations
4+ */
5+
6+ /**
7+ * Base error class for storage operations
8+ */
9+ export abstract class StorageError extends Error {
10+ abstract readonly code : string ;
11+ abstract readonly userMessage : string ;
12+
13+ constructor (
14+ message : string ,
15+ public readonly cause ?: Error ,
16+ public readonly context ?: Record < string , unknown >
17+ ) {
18+ super ( message ) ;
19+ this . name = this . constructor . name ;
20+ }
21+ }
22+
23+ /**
24+ * Error when IndexedDB operations fail
25+ */
26+ export class IndexedDBError extends StorageError {
27+ readonly code = 'INDEXED_DB_ERROR' ;
28+ readonly userMessage = 'Storage operation failed. Please try again.' ;
29+
30+ constructor (
31+ operation : string ,
32+ cause ?: Error ,
33+ context ?: Record < string , unknown >
34+ ) {
35+ super ( `IndexedDB operation failed: ${ operation } ` , cause , context ) ;
36+ }
37+ }
38+
39+ /**
40+ * Error when quota is exceeded
41+ */
42+ export class QuotaExceededError extends StorageError {
43+ readonly code = 'QUOTA_EXCEEDED' ;
44+ readonly userMessage = 'Storage space full. Please clear some data and try again.' ;
45+
46+ constructor ( cause ?: Error ) {
47+ super ( 'Storage quota exceeded' , cause ) ;
48+ }
49+ }
50+
51+ /**
52+ * Error when data is not found
53+ */
54+ export class NotFoundError extends StorageError {
55+ readonly code = 'NOT_FOUND' ;
56+ readonly userMessage = 'The requested data was not found.' ;
57+
58+ constructor ( resourceType : string , identifier : string , cause ?: Error ) {
59+ super ( `${ resourceType } not found: ${ identifier } ` , cause ) ;
60+ }
61+ }
62+
63+ /**
64+ * Error when data validation fails
65+ */
66+ export class ValidationError extends StorageError {
67+ readonly code = 'VALIDATION_ERROR' ;
68+ readonly userMessage = 'Invalid data format. Please check your input and try again.' ;
69+
70+ constructor (
71+ field : string ,
72+ value : unknown ,
73+ reason : string ,
74+ cause ?: Error
75+ ) {
76+ super ( `Validation failed for ${ field } : ${ reason } ` , cause , { field, value } ) ;
77+ }
78+ }
79+
80+ /**
81+ * Error when network/connexion issues prevent storage operations
82+ */
83+ export class ConnectionError extends StorageError {
84+ readonly code = 'CONNECTION_ERROR' ;
85+ readonly userMessage = 'Connection to storage failed. Please check your browser settings.' ;
86+
87+ constructor ( cause ?: Error ) {
88+ super ( 'Storage connection failed' , cause ) ;
89+ }
90+ }
91+
92+ /**
93+ * Error when operations are aborted or interrupted
94+ */
95+ export class OperationAbortedError extends StorageError {
96+ readonly code = 'OPERATION_ABORTED' ;
97+ readonly userMessage = 'Operation was cancelled. Please try again.' ;
98+
99+ constructor ( operation : string , cause ?: Error ) {
100+ super ( `Operation aborted: ${ operation } ` , cause ) ;
101+ }
102+ }
103+
104+ /**
105+ * Utility function to determine if an error is a storage error
106+ */
107+ export function isStorageError ( error : unknown ) : error is StorageError {
108+ return error instanceof StorageError ;
109+ }
110+
111+ /**
112+ * Utility function to convert IndexedDB errors to structured storage errors
113+ */
114+ export function convertIndexedDBError (
115+ operation : string ,
116+ error : unknown
117+ ) : StorageError {
118+ if ( isStorageError ( error ) ) {
119+ return error ;
120+ }
121+
122+ if ( error instanceof DOMException ) {
123+ switch ( error . name ) {
124+ case 'QuotaExceededError' :
125+ return new QuotaExceededError ( error ) ;
126+ case 'NotFoundError' :
127+ return new NotFoundError ( 'Resource' , 'unknown' , error ) ;
128+ case 'InvalidStateError' :
129+ case 'DataError' :
130+ return new ValidationError ( 'operation' , operation , error . message , error ) ;
131+ case 'AbortError' :
132+ return new OperationAbortedError ( operation , error ) ;
133+ case 'VersionError' :
134+ return new ConnectionError ( error ) ;
135+ default :
136+ return new IndexedDBError ( operation , error ) ;
137+ }
138+ }
139+
140+ if ( error instanceof Error ) {
141+ if ( error . message . includes ( 'quota' ) || error . message . includes ( 'storage' ) ) {
142+ return new QuotaExceededError ( error ) ;
143+ }
144+ if ( error . message . includes ( 'abort' ) || error . message . includes ( 'cancel' ) ) {
145+ return new OperationAbortedError ( operation , error ) ;
146+ }
147+ return new IndexedDBError ( operation , error ) ;
148+ }
149+
150+ return new IndexedDBError ( operation , new Error ( String ( error ) ) ) ;
151+ }
0 commit comments