pdf-oxide 0.3.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +218 -0
- package/binding.gyp +35 -0
- package/package.json +78 -0
- package/src/builders/annotation-builder.ts +367 -0
- package/src/builders/conversion-options-builder.ts +257 -0
- package/src/builders/index.ts +12 -0
- package/src/builders/metadata-builder.ts +317 -0
- package/src/builders/pdf-builder.ts +386 -0
- package/src/builders/search-options-builder.ts +151 -0
- package/src/document-editor-manager.ts +318 -0
- package/src/errors.ts +1629 -0
- package/src/form-field-manager.ts +666 -0
- package/src/hybrid-ml-manager.ts +283 -0
- package/src/index.ts +453 -0
- package/src/managers/accessibility-manager.ts +338 -0
- package/src/managers/annotation-manager.ts +439 -0
- package/src/managers/barcode-manager.ts +235 -0
- package/src/managers/batch-manager.ts +533 -0
- package/src/managers/cache-manager.ts +486 -0
- package/src/managers/compliance-manager.ts +375 -0
- package/src/managers/content-manager.ts +339 -0
- package/src/managers/document-utility-manager.ts +922 -0
- package/src/managers/dom-pdf-creator.ts +365 -0
- package/src/managers/editing-manager.ts +514 -0
- package/src/managers/enterprise-manager.ts +478 -0
- package/src/managers/extended-managers.ts +437 -0
- package/src/managers/extraction-manager.ts +583 -0
- package/src/managers/final-utilities.ts +429 -0
- package/src/managers/hybrid-ml-advanced.ts +479 -0
- package/src/managers/index.ts +239 -0
- package/src/managers/layer-manager.ts +500 -0
- package/src/managers/metadata-manager.ts +303 -0
- package/src/managers/ocr-manager.ts +756 -0
- package/src/managers/optimization-manager.ts +262 -0
- package/src/managers/outline-manager.ts +196 -0
- package/src/managers/page-manager.ts +289 -0
- package/src/managers/pattern-detection.ts +440 -0
- package/src/managers/rendering-manager.ts +863 -0
- package/src/managers/search-manager.ts +385 -0
- package/src/managers/security-manager.ts +345 -0
- package/src/managers/signature-manager.ts +1664 -0
- package/src/managers/streams.ts +618 -0
- package/src/managers/xfa-manager.ts +500 -0
- package/src/pdf-creator-manager.ts +494 -0
- package/src/properties.ts +522 -0
- package/src/result-accessors-manager.ts +867 -0
- package/src/tests/advanced-features.test.ts +414 -0
- package/src/tests/advanced.test.ts +266 -0
- package/src/tests/extended-managers.test.ts +316 -0
- package/src/tests/final-utilities.test.ts +455 -0
- package/src/tests/foundation.test.ts +315 -0
- package/src/tests/high-demand.test.ts +257 -0
- package/src/tests/specialized.test.ts +97 -0
- package/src/thumbnail-manager.ts +272 -0
- package/src/types/common.ts +142 -0
- package/src/types/document-types.ts +457 -0
- package/src/types/index.ts +6 -0
- package/src/types/manager-types.ts +284 -0
- package/src/types/native-bindings.ts +517 -0
- package/src/workers/index.ts +7 -0
- package/src/workers/pool.ts +274 -0
- package/src/workers/worker.ts +131 -0
package/src/errors.ts
ADDED
|
@@ -0,0 +1,1629 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Error Handling for PDF Oxide
|
|
3
|
+
*
|
|
4
|
+
* Provides comprehensive exception hierarchy consistent across all language bindings.
|
|
5
|
+
* Uses 4-digit error codes organized by category (1000-9999).
|
|
6
|
+
*
|
|
7
|
+
* Error Code System:
|
|
8
|
+
* - 1000-1999: Parse errors
|
|
9
|
+
* - 2000-2999: I/O errors
|
|
10
|
+
* - 3000-3999: Encryption errors
|
|
11
|
+
* - 4000-4999: State errors
|
|
12
|
+
* - 5000-5999: Unsupported feature errors
|
|
13
|
+
* - 6000-6999: Validation errors
|
|
14
|
+
* - 7000-7999: Rendering errors
|
|
15
|
+
* - 8000-8999: Search errors
|
|
16
|
+
* - 9000-9999: Other errors (compliance, OCR, etc.)
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { PdfErrorDetails } from './types/common';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Error categories for classification and handling
|
|
23
|
+
*/
|
|
24
|
+
export enum ErrorCategory {
|
|
25
|
+
VALIDATION = 'validation',
|
|
26
|
+
IO = 'io',
|
|
27
|
+
ENCRYPTION = 'encryption',
|
|
28
|
+
PARSING = 'parsing',
|
|
29
|
+
RENDERING = 'rendering',
|
|
30
|
+
SEARCH = 'search',
|
|
31
|
+
PERMISSION = 'permission',
|
|
32
|
+
RESOURCE = 'resource',
|
|
33
|
+
STATE = 'state',
|
|
34
|
+
UNSUPPORTED = 'unsupported',
|
|
35
|
+
COMPLIANCE = 'compliance',
|
|
36
|
+
OCR = 'ocr',
|
|
37
|
+
SIGNATURE = 'signature',
|
|
38
|
+
REDACTION = 'redaction',
|
|
39
|
+
UNKNOWN = 'unknown',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Error severity levels for prioritization and monitoring
|
|
44
|
+
*/
|
|
45
|
+
export enum ErrorSeverity {
|
|
46
|
+
LOW = 'low',
|
|
47
|
+
MEDIUM = 'medium',
|
|
48
|
+
HIGH = 'high',
|
|
49
|
+
CRITICAL = 'critical',
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Recovery information for error handling
|
|
54
|
+
*/
|
|
55
|
+
export interface ErrorRecovery {
|
|
56
|
+
canRetry: boolean;
|
|
57
|
+
retryAfterMs?: number;
|
|
58
|
+
suggestions: string[];
|
|
59
|
+
alternativeApproach?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Base class for all PDF Oxide errors.
|
|
64
|
+
*
|
|
65
|
+
* @class PdfException
|
|
66
|
+
* @extends {Error}
|
|
67
|
+
* @property {string} code - 4-digit error code (XXXX format)
|
|
68
|
+
* @property {string} message - Human-readable error message
|
|
69
|
+
* @property {PdfErrorDetails} details - Additional context information
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* try {
|
|
73
|
+
* // PDF operation
|
|
74
|
+
* } catch (err) {
|
|
75
|
+
* if (err instanceof PdfException) {
|
|
76
|
+
* console.log(`[${err.code}] ${err.message}`);
|
|
77
|
+
* console.log('Context:', err.details);
|
|
78
|
+
* }
|
|
79
|
+
* }
|
|
80
|
+
*/
|
|
81
|
+
export class PdfException extends Error {
|
|
82
|
+
public readonly code: string;
|
|
83
|
+
public readonly message: string;
|
|
84
|
+
public readonly details: PdfErrorDetails;
|
|
85
|
+
public readonly category: ErrorCategory;
|
|
86
|
+
public readonly severity: ErrorSeverity;
|
|
87
|
+
public readonly recovery: ErrorRecovery;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Creates a new PdfException.
|
|
91
|
+
*
|
|
92
|
+
* @param code - 4-digit error code
|
|
93
|
+
* @param message - Human-readable error message
|
|
94
|
+
* @param category - Error category for classification
|
|
95
|
+
* @param severity - Error severity level
|
|
96
|
+
* @param details - Additional context information
|
|
97
|
+
* @param recovery - Recovery information
|
|
98
|
+
*/
|
|
99
|
+
constructor(
|
|
100
|
+
code: string,
|
|
101
|
+
message: string,
|
|
102
|
+
category: ErrorCategory = ErrorCategory.UNKNOWN,
|
|
103
|
+
severity: ErrorSeverity = ErrorSeverity.HIGH,
|
|
104
|
+
details: PdfErrorDetails = {},
|
|
105
|
+
recovery: Partial<ErrorRecovery> = {}
|
|
106
|
+
) {
|
|
107
|
+
if (!code || code.length !== 4 || !/^\d{4}$/.test(code)) {
|
|
108
|
+
throw new Error('Code must be 4 digits');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
super(`[${code}] ${message}`);
|
|
112
|
+
this.name = this.constructor.name;
|
|
113
|
+
this.code = code;
|
|
114
|
+
this.message = message;
|
|
115
|
+
this.category = category;
|
|
116
|
+
this.severity = severity;
|
|
117
|
+
this.details = {
|
|
118
|
+
timestamp: new Date().toISOString(),
|
|
119
|
+
...details,
|
|
120
|
+
};
|
|
121
|
+
this.recovery = {
|
|
122
|
+
canRetry: false,
|
|
123
|
+
suggestions: [],
|
|
124
|
+
...recovery,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Maintain proper stack trace for where our error was thrown
|
|
128
|
+
if (Error.captureStackTrace) {
|
|
129
|
+
Error.captureStackTrace(this, this.constructor);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Adds operational context to this exception for better diagnostics.
|
|
135
|
+
*
|
|
136
|
+
* @param operation - Name of the operation that failed
|
|
137
|
+
* @param context - Additional context key-value pairs
|
|
138
|
+
* @returns This exception for method chaining
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* throw new FileNotFound('Not found')
|
|
142
|
+
* .withContext('openFile', { path: '/tmp/doc.pdf' });
|
|
143
|
+
*/
|
|
144
|
+
withContext(operation: string, context: Record<string, any> = {}): this {
|
|
145
|
+
this.details.operation = operation;
|
|
146
|
+
this.details.context = { ...this.details.context, ...context };
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get a comprehensive error message with all details
|
|
152
|
+
* @returns Formatted error message with context and suggestions
|
|
153
|
+
*/
|
|
154
|
+
getFullMessage(): string {
|
|
155
|
+
const parts: string[] = [
|
|
156
|
+
`[${this.code}] ${this.message}`,
|
|
157
|
+
`Category: ${this.category} | Severity: ${this.severity}`,
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
if (this.details.operation) {
|
|
161
|
+
parts.push(`Operation: ${this.details.operation}`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (this.details.context && Object.keys(this.details.context).length > 0) {
|
|
165
|
+
const contextStr = Object.entries(this.details.context)
|
|
166
|
+
.map(([key, value]) => ` ${key}: ${JSON.stringify(value)}`)
|
|
167
|
+
.join('\n');
|
|
168
|
+
parts.push(`Context:\n${contextStr}`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (this.recovery.suggestions.length > 0) {
|
|
172
|
+
const suggestionsStr = this.recovery.suggestions
|
|
173
|
+
.map((s) => ` • ${s}`)
|
|
174
|
+
.join('\n');
|
|
175
|
+
parts.push(`Recovery Suggestions:\n${suggestionsStr}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (this.recovery.alternativeApproach) {
|
|
179
|
+
parts.push(`Alternative Approach: ${this.recovery.alternativeApproach}`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (this.recovery.canRetry) {
|
|
183
|
+
const retryMsg = this.recovery.retryAfterMs
|
|
184
|
+
? `retry after ${this.recovery.retryAfterMs}ms`
|
|
185
|
+
: 'retry';
|
|
186
|
+
parts.push(`Status: Retryable (${retryMsg})`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return parts.join('\n');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Convert error to JSON for logging/monitoring
|
|
194
|
+
* @returns JSON representation of the error
|
|
195
|
+
*/
|
|
196
|
+
toJSON() {
|
|
197
|
+
return {
|
|
198
|
+
name: this.name,
|
|
199
|
+
code: this.code,
|
|
200
|
+
message: this.message,
|
|
201
|
+
category: this.category,
|
|
202
|
+
severity: this.severity,
|
|
203
|
+
details: this.details,
|
|
204
|
+
recovery: this.recovery,
|
|
205
|
+
stack: this.stack,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// ===== Parse Errors (1000-1999) =====
|
|
211
|
+
|
|
212
|
+
export class ParseException extends PdfException {
|
|
213
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
214
|
+
super(
|
|
215
|
+
'1000',
|
|
216
|
+
message,
|
|
217
|
+
ErrorCategory.PARSING,
|
|
218
|
+
ErrorSeverity.HIGH,
|
|
219
|
+
details,
|
|
220
|
+
{
|
|
221
|
+
canRetry: false,
|
|
222
|
+
suggestions: [
|
|
223
|
+
'Verify the PDF file is not corrupted',
|
|
224
|
+
'Try opening the file with Adobe Reader',
|
|
225
|
+
'Check that the file is a valid PDF',
|
|
226
|
+
],
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export class InvalidStructure extends PdfException {
|
|
233
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
234
|
+
super(
|
|
235
|
+
'1101',
|
|
236
|
+
message,
|
|
237
|
+
ErrorCategory.PARSING,
|
|
238
|
+
ErrorSeverity.HIGH,
|
|
239
|
+
details,
|
|
240
|
+
{
|
|
241
|
+
canRetry: false,
|
|
242
|
+
suggestions: [
|
|
243
|
+
'The PDF structure is invalid or incomplete',
|
|
244
|
+
'Try re-saving the PDF with a PDF tool',
|
|
245
|
+
'Contact the PDF creator for a corrected version',
|
|
246
|
+
],
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export class CorruptedData extends PdfException {
|
|
253
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
254
|
+
super(
|
|
255
|
+
'1200',
|
|
256
|
+
message,
|
|
257
|
+
ErrorCategory.PARSING,
|
|
258
|
+
ErrorSeverity.HIGH,
|
|
259
|
+
details,
|
|
260
|
+
{
|
|
261
|
+
canRetry: false,
|
|
262
|
+
suggestions: [
|
|
263
|
+
'PDF file may be corrupted or damaged',
|
|
264
|
+
'Try opening the file with Adobe Reader',
|
|
265
|
+
'Attempt to recover the file using a PDF recovery tool',
|
|
266
|
+
],
|
|
267
|
+
}
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export class UnsupportedVersion extends PdfException {
|
|
273
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
274
|
+
super(
|
|
275
|
+
'1300',
|
|
276
|
+
message,
|
|
277
|
+
ErrorCategory.UNSUPPORTED,
|
|
278
|
+
ErrorSeverity.MEDIUM,
|
|
279
|
+
details,
|
|
280
|
+
{
|
|
281
|
+
canRetry: false,
|
|
282
|
+
suggestions: [
|
|
283
|
+
'This PDF version is not supported',
|
|
284
|
+
'Try converting the PDF to a standard format',
|
|
285
|
+
'Update your PDF library to a newer version',
|
|
286
|
+
],
|
|
287
|
+
alternativeApproach:
|
|
288
|
+
'Use a PDF converter tool to convert to standard PDF format',
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ===== I/O Errors (2000-2999) =====
|
|
295
|
+
|
|
296
|
+
export class IoException extends PdfException {
|
|
297
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
298
|
+
super(
|
|
299
|
+
'2000',
|
|
300
|
+
message,
|
|
301
|
+
ErrorCategory.IO,
|
|
302
|
+
ErrorSeverity.HIGH,
|
|
303
|
+
details,
|
|
304
|
+
{
|
|
305
|
+
canRetry: true,
|
|
306
|
+
retryAfterMs: 1000,
|
|
307
|
+
suggestions: [
|
|
308
|
+
'Check file permissions (readable)',
|
|
309
|
+
'Verify file path exists',
|
|
310
|
+
'Ensure disk space available',
|
|
311
|
+
'Check file is not locked by another process',
|
|
312
|
+
],
|
|
313
|
+
}
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export class FileNotFound extends PdfException {
|
|
319
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
320
|
+
super(
|
|
321
|
+
'2100',
|
|
322
|
+
message,
|
|
323
|
+
ErrorCategory.IO,
|
|
324
|
+
ErrorSeverity.MEDIUM,
|
|
325
|
+
details,
|
|
326
|
+
{
|
|
327
|
+
canRetry: false,
|
|
328
|
+
suggestions: [
|
|
329
|
+
'Verify the file path is correct',
|
|
330
|
+
'Check that the file exists',
|
|
331
|
+
'Ensure the path is absolute or properly resolved',
|
|
332
|
+
],
|
|
333
|
+
}
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export class PermissionDenied extends PdfException {
|
|
339
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
340
|
+
super(
|
|
341
|
+
'2200',
|
|
342
|
+
message,
|
|
343
|
+
ErrorCategory.PERMISSION,
|
|
344
|
+
ErrorSeverity.HIGH,
|
|
345
|
+
details,
|
|
346
|
+
{
|
|
347
|
+
canRetry: false,
|
|
348
|
+
suggestions: [
|
|
349
|
+
'Check file permissions using chmod/ls -l',
|
|
350
|
+
'Ensure the process has read permissions',
|
|
351
|
+
'Try running with appropriate permissions',
|
|
352
|
+
],
|
|
353
|
+
alternativeApproach:
|
|
354
|
+
'Copy the file to a location with proper permissions',
|
|
355
|
+
}
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export class DiskFull extends PdfException {
|
|
361
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
362
|
+
super(
|
|
363
|
+
'2300',
|
|
364
|
+
message,
|
|
365
|
+
ErrorCategory.RESOURCE,
|
|
366
|
+
ErrorSeverity.CRITICAL,
|
|
367
|
+
details,
|
|
368
|
+
{
|
|
369
|
+
canRetry: true,
|
|
370
|
+
retryAfterMs: 2000,
|
|
371
|
+
suggestions: [
|
|
372
|
+
'Free up disk space',
|
|
373
|
+
'Delete unnecessary files',
|
|
374
|
+
'Archive old files to external storage',
|
|
375
|
+
],
|
|
376
|
+
alternativeApproach:
|
|
377
|
+
'Process the PDF on a device with more available storage',
|
|
378
|
+
}
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export class NetworkError extends PdfException {
|
|
384
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
385
|
+
super(
|
|
386
|
+
'2400',
|
|
387
|
+
message,
|
|
388
|
+
ErrorCategory.IO,
|
|
389
|
+
ErrorSeverity.MEDIUM,
|
|
390
|
+
details,
|
|
391
|
+
{
|
|
392
|
+
canRetry: true,
|
|
393
|
+
retryAfterMs: 2000,
|
|
394
|
+
suggestions: [
|
|
395
|
+
'Check network connectivity',
|
|
396
|
+
'Verify the remote server is reachable',
|
|
397
|
+
'Check firewall and proxy settings',
|
|
398
|
+
],
|
|
399
|
+
}
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// ===== Encryption Errors (3000-3999) =====
|
|
405
|
+
|
|
406
|
+
export class EncryptionException extends PdfException {
|
|
407
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
408
|
+
super(
|
|
409
|
+
'3000',
|
|
410
|
+
message,
|
|
411
|
+
ErrorCategory.ENCRYPTION,
|
|
412
|
+
ErrorSeverity.HIGH,
|
|
413
|
+
details,
|
|
414
|
+
{
|
|
415
|
+
canRetry: false,
|
|
416
|
+
suggestions: [
|
|
417
|
+
'Check if PDF requires password',
|
|
418
|
+
'Verify encryption credentials',
|
|
419
|
+
'Try opening PDF in Adobe Reader to verify',
|
|
420
|
+
],
|
|
421
|
+
}
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export class InvalidPassword extends PdfException {
|
|
427
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
428
|
+
super(
|
|
429
|
+
'3100',
|
|
430
|
+
message,
|
|
431
|
+
ErrorCategory.ENCRYPTION,
|
|
432
|
+
ErrorSeverity.MEDIUM,
|
|
433
|
+
details,
|
|
434
|
+
{
|
|
435
|
+
canRetry: true,
|
|
436
|
+
retryAfterMs: 1000,
|
|
437
|
+
suggestions: [
|
|
438
|
+
'Verify the password is correct',
|
|
439
|
+
'Check for leading/trailing spaces',
|
|
440
|
+
'Ensure correct keyboard layout is selected',
|
|
441
|
+
'Try password with different case',
|
|
442
|
+
],
|
|
443
|
+
}
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export class DecryptionFailed extends PdfException {
|
|
449
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
450
|
+
super(
|
|
451
|
+
'3200',
|
|
452
|
+
message,
|
|
453
|
+
ErrorCategory.ENCRYPTION,
|
|
454
|
+
ErrorSeverity.HIGH,
|
|
455
|
+
details,
|
|
456
|
+
{
|
|
457
|
+
canRetry: false,
|
|
458
|
+
suggestions: [
|
|
459
|
+
'File may be corrupted',
|
|
460
|
+
'Encryption method may be unsupported',
|
|
461
|
+
'Try opening with different PDF reader',
|
|
462
|
+
],
|
|
463
|
+
}
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export class UnsupportedAlgorithm extends PdfException {
|
|
469
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
470
|
+
super(
|
|
471
|
+
'3300',
|
|
472
|
+
message,
|
|
473
|
+
ErrorCategory.ENCRYPTION,
|
|
474
|
+
ErrorSeverity.MEDIUM,
|
|
475
|
+
details,
|
|
476
|
+
{
|
|
477
|
+
canRetry: false,
|
|
478
|
+
suggestions: [
|
|
479
|
+
'This encryption algorithm is not supported',
|
|
480
|
+
'Convert PDF with different encryption algorithm',
|
|
481
|
+
'Contact PDF creator for unencrypted version',
|
|
482
|
+
],
|
|
483
|
+
alternativeApproach:
|
|
484
|
+
'Use Adobe Acrobat to re-save with supported encryption',
|
|
485
|
+
}
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// ===== State Errors (4000-4999) =====
|
|
491
|
+
|
|
492
|
+
export class InvalidStateException extends PdfException {
|
|
493
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
494
|
+
super(
|
|
495
|
+
'4000',
|
|
496
|
+
message,
|
|
497
|
+
ErrorCategory.STATE,
|
|
498
|
+
ErrorSeverity.HIGH,
|
|
499
|
+
details,
|
|
500
|
+
{
|
|
501
|
+
canRetry: false,
|
|
502
|
+
suggestions: [
|
|
503
|
+
'Ensure the document is in the correct state for this operation',
|
|
504
|
+
'Check that required initialization steps were completed',
|
|
505
|
+
'Verify operation order and dependencies',
|
|
506
|
+
],
|
|
507
|
+
}
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
export class DocumentClosed extends PdfException {
|
|
513
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
514
|
+
super(
|
|
515
|
+
'4100',
|
|
516
|
+
message,
|
|
517
|
+
ErrorCategory.STATE,
|
|
518
|
+
ErrorSeverity.HIGH,
|
|
519
|
+
details,
|
|
520
|
+
{
|
|
521
|
+
canRetry: false,
|
|
522
|
+
suggestions: [
|
|
523
|
+
'The document has been closed and cannot be used',
|
|
524
|
+
'Create a new document instance or reopen the file',
|
|
525
|
+
'Check that the document is not being used after closure',
|
|
526
|
+
],
|
|
527
|
+
}
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
export class OperationNotAllowed extends PdfException {
|
|
533
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
534
|
+
super(
|
|
535
|
+
'4200',
|
|
536
|
+
message,
|
|
537
|
+
ErrorCategory.STATE,
|
|
538
|
+
ErrorSeverity.MEDIUM,
|
|
539
|
+
details,
|
|
540
|
+
{
|
|
541
|
+
canRetry: false,
|
|
542
|
+
suggestions: [
|
|
543
|
+
'This operation is not allowed in the current document state',
|
|
544
|
+
'Check document permissions and security settings',
|
|
545
|
+
'Ensure document is writable (not read-only)',
|
|
546
|
+
],
|
|
547
|
+
}
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
export class InvalidOperation extends PdfException {
|
|
553
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
554
|
+
super(
|
|
555
|
+
'4300',
|
|
556
|
+
message,
|
|
557
|
+
ErrorCategory.STATE,
|
|
558
|
+
ErrorSeverity.MEDIUM,
|
|
559
|
+
details,
|
|
560
|
+
{
|
|
561
|
+
canRetry: false,
|
|
562
|
+
suggestions: [
|
|
563
|
+
'This operation cannot be performed on this document',
|
|
564
|
+
'Verify the document format and content type',
|
|
565
|
+
'Check operation prerequisites are met',
|
|
566
|
+
],
|
|
567
|
+
}
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// ===== Unsupported Feature Errors (5000-5999) =====
|
|
573
|
+
|
|
574
|
+
export class UnsupportedFeatureException extends PdfException {
|
|
575
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
576
|
+
super(
|
|
577
|
+
'5000',
|
|
578
|
+
message,
|
|
579
|
+
ErrorCategory.UNSUPPORTED,
|
|
580
|
+
ErrorSeverity.MEDIUM,
|
|
581
|
+
details,
|
|
582
|
+
{
|
|
583
|
+
canRetry: false,
|
|
584
|
+
suggestions: [
|
|
585
|
+
'This PDF feature is not supported',
|
|
586
|
+
'Check the documentation for supported features',
|
|
587
|
+
'Consider using a different PDF tool for this operation',
|
|
588
|
+
],
|
|
589
|
+
}
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
export class FeatureNotImplemented extends PdfException {
|
|
595
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
596
|
+
super(
|
|
597
|
+
'5100',
|
|
598
|
+
message,
|
|
599
|
+
ErrorCategory.UNSUPPORTED,
|
|
600
|
+
ErrorSeverity.LOW,
|
|
601
|
+
details,
|
|
602
|
+
{
|
|
603
|
+
canRetry: false,
|
|
604
|
+
suggestions: [
|
|
605
|
+
'This feature is not yet implemented',
|
|
606
|
+
'Check the library changelog for planned features',
|
|
607
|
+
'File a feature request if this is important for your use case',
|
|
608
|
+
],
|
|
609
|
+
}
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
export class FormatNotSupported extends PdfException {
|
|
615
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
616
|
+
super(
|
|
617
|
+
'5200',
|
|
618
|
+
message,
|
|
619
|
+
ErrorCategory.UNSUPPORTED,
|
|
620
|
+
ErrorSeverity.MEDIUM,
|
|
621
|
+
details,
|
|
622
|
+
{
|
|
623
|
+
canRetry: false,
|
|
624
|
+
suggestions: [
|
|
625
|
+
'The document format is not supported',
|
|
626
|
+
'Try converting to a standard format first',
|
|
627
|
+
'Check documentation for supported formats',
|
|
628
|
+
],
|
|
629
|
+
alternativeApproach: 'Convert the document using a format converter',
|
|
630
|
+
}
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
export class EncodingNotSupported extends PdfException {
|
|
636
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
637
|
+
super(
|
|
638
|
+
'5300',
|
|
639
|
+
message,
|
|
640
|
+
ErrorCategory.UNSUPPORTED,
|
|
641
|
+
ErrorSeverity.MEDIUM,
|
|
642
|
+
details,
|
|
643
|
+
{
|
|
644
|
+
canRetry: false,
|
|
645
|
+
suggestions: [
|
|
646
|
+
'The character encoding is not supported',
|
|
647
|
+
'Try using a different character encoding',
|
|
648
|
+
'Check that the PDF text is properly encoded',
|
|
649
|
+
],
|
|
650
|
+
}
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// ===== Validation Errors (6000-6999) =====
|
|
656
|
+
|
|
657
|
+
export class ValidationException extends PdfException {
|
|
658
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
659
|
+
super(
|
|
660
|
+
'6000',
|
|
661
|
+
message,
|
|
662
|
+
ErrorCategory.VALIDATION,
|
|
663
|
+
ErrorSeverity.MEDIUM,
|
|
664
|
+
details,
|
|
665
|
+
{
|
|
666
|
+
canRetry: false,
|
|
667
|
+
suggestions: [
|
|
668
|
+
'Verify all parameters are valid and properly formatted',
|
|
669
|
+
'Check the API documentation for parameter requirements',
|
|
670
|
+
'Ensure all required fields are provided',
|
|
671
|
+
],
|
|
672
|
+
}
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
export class InvalidParameter extends PdfException {
|
|
678
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
679
|
+
super(
|
|
680
|
+
'6100',
|
|
681
|
+
message,
|
|
682
|
+
ErrorCategory.VALIDATION,
|
|
683
|
+
ErrorSeverity.MEDIUM,
|
|
684
|
+
details,
|
|
685
|
+
{
|
|
686
|
+
canRetry: false,
|
|
687
|
+
suggestions: [
|
|
688
|
+
'Check that all parameters are valid',
|
|
689
|
+
'Review the function signature and parameter types',
|
|
690
|
+
'Ensure parameter values are within valid ranges',
|
|
691
|
+
],
|
|
692
|
+
}
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
export class InvalidValue extends PdfException {
|
|
698
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
699
|
+
super(
|
|
700
|
+
'6200',
|
|
701
|
+
message,
|
|
702
|
+
ErrorCategory.VALIDATION,
|
|
703
|
+
ErrorSeverity.MEDIUM,
|
|
704
|
+
details,
|
|
705
|
+
{
|
|
706
|
+
canRetry: false,
|
|
707
|
+
suggestions: [
|
|
708
|
+
'Verify the value is correct and properly formatted',
|
|
709
|
+
'Check acceptable value ranges in the documentation',
|
|
710
|
+
'Ensure the value type matches the expected type',
|
|
711
|
+
],
|
|
712
|
+
}
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
export class MissingRequired extends PdfException {
|
|
718
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
719
|
+
super(
|
|
720
|
+
'6300',
|
|
721
|
+
message,
|
|
722
|
+
ErrorCategory.VALIDATION,
|
|
723
|
+
ErrorSeverity.MEDIUM,
|
|
724
|
+
details,
|
|
725
|
+
{
|
|
726
|
+
canRetry: false,
|
|
727
|
+
suggestions: [
|
|
728
|
+
'Provide the required parameter or field',
|
|
729
|
+
'Check the API documentation for required fields',
|
|
730
|
+
'Ensure no required parameters are omitted',
|
|
731
|
+
],
|
|
732
|
+
}
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
export class TypeMismatch extends PdfException {
|
|
738
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
739
|
+
super(
|
|
740
|
+
'6400',
|
|
741
|
+
message,
|
|
742
|
+
ErrorCategory.VALIDATION,
|
|
743
|
+
ErrorSeverity.MEDIUM,
|
|
744
|
+
details,
|
|
745
|
+
{
|
|
746
|
+
canRetry: false,
|
|
747
|
+
suggestions: [
|
|
748
|
+
'Verify the parameter type matches the expected type',
|
|
749
|
+
'Convert the value to the correct type',
|
|
750
|
+
'Check the function signature in the documentation',
|
|
751
|
+
],
|
|
752
|
+
}
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// ===== Rendering Errors (7000-7999) =====
|
|
758
|
+
|
|
759
|
+
export class RenderingException extends PdfException {
|
|
760
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
761
|
+
super(
|
|
762
|
+
'7000',
|
|
763
|
+
message,
|
|
764
|
+
ErrorCategory.RENDERING,
|
|
765
|
+
ErrorSeverity.HIGH,
|
|
766
|
+
details,
|
|
767
|
+
{
|
|
768
|
+
canRetry: true,
|
|
769
|
+
retryAfterMs: 1000,
|
|
770
|
+
suggestions: [
|
|
771
|
+
'Check that the PDF content is valid',
|
|
772
|
+
'Verify rendering parameters are correct',
|
|
773
|
+
'Try rendering a different page to isolate the issue',
|
|
774
|
+
],
|
|
775
|
+
}
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
export class RenderFailed extends PdfException {
|
|
781
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
782
|
+
super(
|
|
783
|
+
'7100',
|
|
784
|
+
message,
|
|
785
|
+
ErrorCategory.RENDERING,
|
|
786
|
+
ErrorSeverity.HIGH,
|
|
787
|
+
details,
|
|
788
|
+
{
|
|
789
|
+
canRetry: true,
|
|
790
|
+
retryAfterMs: 1000,
|
|
791
|
+
suggestions: [
|
|
792
|
+
'The rendering operation failed',
|
|
793
|
+
'Check available system resources',
|
|
794
|
+
'Try rendering with lower quality settings',
|
|
795
|
+
],
|
|
796
|
+
}
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
export class UnsupportedRenderFormat extends PdfException {
|
|
802
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
803
|
+
super(
|
|
804
|
+
'7200',
|
|
805
|
+
message,
|
|
806
|
+
ErrorCategory.RENDERING,
|
|
807
|
+
ErrorSeverity.MEDIUM,
|
|
808
|
+
details,
|
|
809
|
+
{
|
|
810
|
+
canRetry: false,
|
|
811
|
+
suggestions: [
|
|
812
|
+
'The render format is not supported',
|
|
813
|
+
'Use a supported format (PNG, JPG, PDF, SVG)',
|
|
814
|
+
'Check documentation for supported rendering formats',
|
|
815
|
+
],
|
|
816
|
+
}
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
export class InsufficientMemory extends PdfException {
|
|
822
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
823
|
+
super(
|
|
824
|
+
'7300',
|
|
825
|
+
message,
|
|
826
|
+
ErrorCategory.RESOURCE,
|
|
827
|
+
ErrorSeverity.CRITICAL,
|
|
828
|
+
details,
|
|
829
|
+
{
|
|
830
|
+
canRetry: true,
|
|
831
|
+
retryAfterMs: 2000,
|
|
832
|
+
suggestions: [
|
|
833
|
+
'Free up system memory',
|
|
834
|
+
'Close other applications to reduce memory usage',
|
|
835
|
+
'Reduce render resolution or quality',
|
|
836
|
+
],
|
|
837
|
+
alternativeApproach:
|
|
838
|
+
'Process the document on a system with more available memory',
|
|
839
|
+
}
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// ===== Search Errors (8000-8999) =====
|
|
845
|
+
|
|
846
|
+
export class SearchException extends PdfException {
|
|
847
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
848
|
+
super(
|
|
849
|
+
'8000',
|
|
850
|
+
message,
|
|
851
|
+
ErrorCategory.SEARCH,
|
|
852
|
+
ErrorSeverity.MEDIUM,
|
|
853
|
+
details,
|
|
854
|
+
{
|
|
855
|
+
canRetry: true,
|
|
856
|
+
retryAfterMs: 500,
|
|
857
|
+
suggestions: [
|
|
858
|
+
'Verify the search term is valid',
|
|
859
|
+
'Check that the document contains searchable text',
|
|
860
|
+
'Try a simpler search pattern',
|
|
861
|
+
],
|
|
862
|
+
}
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
export class SearchFailed extends PdfException {
|
|
868
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
869
|
+
super(
|
|
870
|
+
'8100',
|
|
871
|
+
message,
|
|
872
|
+
ErrorCategory.SEARCH,
|
|
873
|
+
ErrorSeverity.MEDIUM,
|
|
874
|
+
details,
|
|
875
|
+
{
|
|
876
|
+
canRetry: true,
|
|
877
|
+
retryAfterMs: 500,
|
|
878
|
+
suggestions: [
|
|
879
|
+
'The search operation failed',
|
|
880
|
+
'Verify the document is not corrupted',
|
|
881
|
+
'Check that the search parameters are valid',
|
|
882
|
+
],
|
|
883
|
+
}
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
export class InvalidPattern extends PdfException {
|
|
889
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
890
|
+
super(
|
|
891
|
+
'8200',
|
|
892
|
+
message,
|
|
893
|
+
ErrorCategory.VALIDATION,
|
|
894
|
+
ErrorSeverity.MEDIUM,
|
|
895
|
+
details,
|
|
896
|
+
{
|
|
897
|
+
canRetry: false,
|
|
898
|
+
suggestions: [
|
|
899
|
+
'The search pattern is invalid',
|
|
900
|
+
'Check the regular expression syntax',
|
|
901
|
+
'Escape special characters if needed',
|
|
902
|
+
],
|
|
903
|
+
}
|
|
904
|
+
);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
export class IndexCorrupted extends PdfException {
|
|
909
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
910
|
+
super(
|
|
911
|
+
'8300',
|
|
912
|
+
message,
|
|
913
|
+
ErrorCategory.SEARCH,
|
|
914
|
+
ErrorSeverity.HIGH,
|
|
915
|
+
details,
|
|
916
|
+
{
|
|
917
|
+
canRetry: true,
|
|
918
|
+
retryAfterMs: 1000,
|
|
919
|
+
suggestions: [
|
|
920
|
+
'The search index may be corrupted',
|
|
921
|
+
'Try rebuilding the search index',
|
|
922
|
+
'Verify the PDF document is valid',
|
|
923
|
+
],
|
|
924
|
+
}
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// ===== Signature Errors (8500-8599) =====
|
|
930
|
+
|
|
931
|
+
export class SignatureException extends PdfException {
|
|
932
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
933
|
+
super(
|
|
934
|
+
'8500',
|
|
935
|
+
message,
|
|
936
|
+
ErrorCategory.SIGNATURE,
|
|
937
|
+
ErrorSeverity.HIGH,
|
|
938
|
+
details,
|
|
939
|
+
{
|
|
940
|
+
canRetry: false,
|
|
941
|
+
suggestions: [
|
|
942
|
+
'Verify the certificate file path and password are correct',
|
|
943
|
+
'Ensure the certificate contains a valid private key for signing',
|
|
944
|
+
'Check that the PDF data is valid and not corrupted',
|
|
945
|
+
'Confirm the signing algorithm is supported',
|
|
946
|
+
],
|
|
947
|
+
}
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
export class CertificateLoadFailed extends PdfException {
|
|
953
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
954
|
+
super(
|
|
955
|
+
'8501',
|
|
956
|
+
message,
|
|
957
|
+
ErrorCategory.SIGNATURE,
|
|
958
|
+
ErrorSeverity.HIGH,
|
|
959
|
+
details,
|
|
960
|
+
{
|
|
961
|
+
canRetry: false,
|
|
962
|
+
suggestions: [
|
|
963
|
+
'Verify the certificate file exists and is readable',
|
|
964
|
+
'Check the password for PKCS#12 files',
|
|
965
|
+
'Ensure the PEM files are properly formatted',
|
|
966
|
+
'Confirm the certificate and key match',
|
|
967
|
+
],
|
|
968
|
+
}
|
|
969
|
+
);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
export class SigningFailed extends PdfException {
|
|
974
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
975
|
+
super(
|
|
976
|
+
'8502',
|
|
977
|
+
message,
|
|
978
|
+
ErrorCategory.SIGNATURE,
|
|
979
|
+
ErrorSeverity.HIGH,
|
|
980
|
+
details,
|
|
981
|
+
{
|
|
982
|
+
canRetry: true,
|
|
983
|
+
retryAfterMs: 1000,
|
|
984
|
+
suggestions: [
|
|
985
|
+
'Verify the credentials have a valid private key',
|
|
986
|
+
'Check that the PDF data is not corrupted',
|
|
987
|
+
'Ensure the signing algorithm is compatible with the certificate',
|
|
988
|
+
'Try a different signature subfilter',
|
|
989
|
+
],
|
|
990
|
+
}
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
// ===== Redaction Errors (8600-8699) =====
|
|
996
|
+
|
|
997
|
+
export class RedactionException extends PdfException {
|
|
998
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
999
|
+
super(
|
|
1000
|
+
'8600',
|
|
1001
|
+
message,
|
|
1002
|
+
ErrorCategory.REDACTION,
|
|
1003
|
+
ErrorSeverity.HIGH,
|
|
1004
|
+
details,
|
|
1005
|
+
{
|
|
1006
|
+
canRetry: false,
|
|
1007
|
+
suggestions: [
|
|
1008
|
+
'Verify the redaction area coordinates are valid',
|
|
1009
|
+
'Ensure the document is opened for editing',
|
|
1010
|
+
'Check that the page index is within range',
|
|
1011
|
+
'Confirm the document is not read-only or encrypted',
|
|
1012
|
+
],
|
|
1013
|
+
}
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// ===== Accessibility Errors (9500-9599) =====
|
|
1019
|
+
|
|
1020
|
+
export class AccessibilityException extends PdfException {
|
|
1021
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1022
|
+
super(
|
|
1023
|
+
'9500',
|
|
1024
|
+
message,
|
|
1025
|
+
ErrorCategory.VALIDATION,
|
|
1026
|
+
ErrorSeverity.HIGH,
|
|
1027
|
+
details,
|
|
1028
|
+
{
|
|
1029
|
+
canRetry: false,
|
|
1030
|
+
suggestions: [
|
|
1031
|
+
'Check the document structure and tagging',
|
|
1032
|
+
'Verify alt text is set for images and figures',
|
|
1033
|
+
'Ensure document language and title are specified',
|
|
1034
|
+
'Run accessibility validation to identify issues',
|
|
1035
|
+
],
|
|
1036
|
+
}
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
// ===== Optimization Errors (9600-9699) =====
|
|
1042
|
+
|
|
1043
|
+
export class OptimizationException extends PdfException {
|
|
1044
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1045
|
+
super(
|
|
1046
|
+
'9600',
|
|
1047
|
+
message,
|
|
1048
|
+
ErrorCategory.RESOURCE,
|
|
1049
|
+
ErrorSeverity.MEDIUM,
|
|
1050
|
+
details,
|
|
1051
|
+
{
|
|
1052
|
+
canRetry: true,
|
|
1053
|
+
retryAfterMs: 1000,
|
|
1054
|
+
suggestions: [
|
|
1055
|
+
'Check that the document is not corrupted',
|
|
1056
|
+
'Verify sufficient disk space for optimization',
|
|
1057
|
+
'Try optimizing with different settings (DPI, quality)',
|
|
1058
|
+
'Ensure document is not encrypted or read-only',
|
|
1059
|
+
],
|
|
1060
|
+
}
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// ===== Compliance Errors (9000-9100) =====
|
|
1066
|
+
|
|
1067
|
+
export class ComplianceException extends PdfException {
|
|
1068
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1069
|
+
super(
|
|
1070
|
+
'9000',
|
|
1071
|
+
message,
|
|
1072
|
+
ErrorCategory.COMPLIANCE,
|
|
1073
|
+
ErrorSeverity.HIGH,
|
|
1074
|
+
details,
|
|
1075
|
+
{
|
|
1076
|
+
canRetry: false,
|
|
1077
|
+
suggestions: [
|
|
1078
|
+
'Check PDF compliance level requirements',
|
|
1079
|
+
'Verify document meets compliance standards',
|
|
1080
|
+
'Review compliance validation report',
|
|
1081
|
+
],
|
|
1082
|
+
}
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
export class InvalidCompliance extends PdfException {
|
|
1088
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1089
|
+
super(
|
|
1090
|
+
'9100',
|
|
1091
|
+
message,
|
|
1092
|
+
ErrorCategory.COMPLIANCE,
|
|
1093
|
+
ErrorSeverity.HIGH,
|
|
1094
|
+
details,
|
|
1095
|
+
{
|
|
1096
|
+
canRetry: false,
|
|
1097
|
+
suggestions: [
|
|
1098
|
+
'The document does not meet compliance requirements',
|
|
1099
|
+
'Fix the compliance issues identified',
|
|
1100
|
+
'Convert the document to a compliant format',
|
|
1101
|
+
],
|
|
1102
|
+
}
|
|
1103
|
+
);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
export class ValidationFailed extends PdfException {
|
|
1108
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1109
|
+
super(
|
|
1110
|
+
'9150',
|
|
1111
|
+
message,
|
|
1112
|
+
ErrorCategory.COMPLIANCE,
|
|
1113
|
+
ErrorSeverity.MEDIUM,
|
|
1114
|
+
details,
|
|
1115
|
+
{
|
|
1116
|
+
canRetry: true,
|
|
1117
|
+
retryAfterMs: 1000,
|
|
1118
|
+
suggestions: [
|
|
1119
|
+
'Validation failed for this document',
|
|
1120
|
+
'Check the validation error details',
|
|
1121
|
+
'Fix the identified issues and retry',
|
|
1122
|
+
],
|
|
1123
|
+
}
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
// ===== OCR Errors (9200-9300) =====
|
|
1129
|
+
|
|
1130
|
+
export class OcrException extends PdfException {
|
|
1131
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1132
|
+
super(
|
|
1133
|
+
'9200',
|
|
1134
|
+
message,
|
|
1135
|
+
ErrorCategory.OCR,
|
|
1136
|
+
ErrorSeverity.MEDIUM,
|
|
1137
|
+
details,
|
|
1138
|
+
{
|
|
1139
|
+
canRetry: true,
|
|
1140
|
+
retryAfterMs: 2000,
|
|
1141
|
+
suggestions: [
|
|
1142
|
+
'OCR processing failed',
|
|
1143
|
+
'Verify the image quality is sufficient',
|
|
1144
|
+
'Check that the document language is supported',
|
|
1145
|
+
],
|
|
1146
|
+
}
|
|
1147
|
+
);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
export class RecognitionFailed extends PdfException {
|
|
1152
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1153
|
+
super(
|
|
1154
|
+
'9201',
|
|
1155
|
+
message,
|
|
1156
|
+
ErrorCategory.OCR,
|
|
1157
|
+
ErrorSeverity.MEDIUM,
|
|
1158
|
+
details,
|
|
1159
|
+
{
|
|
1160
|
+
canRetry: true,
|
|
1161
|
+
retryAfterMs: 2000,
|
|
1162
|
+
suggestions: [
|
|
1163
|
+
'Text recognition failed',
|
|
1164
|
+
'Try improving the image quality',
|
|
1165
|
+
'Ensure the document language is set correctly',
|
|
1166
|
+
],
|
|
1167
|
+
}
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
export class LanguageNotSupported extends PdfException {
|
|
1173
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1174
|
+
super(
|
|
1175
|
+
'9202',
|
|
1176
|
+
message,
|
|
1177
|
+
ErrorCategory.OCR,
|
|
1178
|
+
ErrorSeverity.MEDIUM,
|
|
1179
|
+
details,
|
|
1180
|
+
{
|
|
1181
|
+
canRetry: false,
|
|
1182
|
+
suggestions: [
|
|
1183
|
+
'The document language is not supported for OCR',
|
|
1184
|
+
'Check available language packs',
|
|
1185
|
+
'Install language support if available',
|
|
1186
|
+
],
|
|
1187
|
+
}
|
|
1188
|
+
);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
export class ImageProcessingFailed extends PdfException {
|
|
1193
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1194
|
+
super(
|
|
1195
|
+
'9203',
|
|
1196
|
+
message,
|
|
1197
|
+
ErrorCategory.OCR,
|
|
1198
|
+
ErrorSeverity.MEDIUM,
|
|
1199
|
+
details,
|
|
1200
|
+
{
|
|
1201
|
+
canRetry: true,
|
|
1202
|
+
retryAfterMs: 2000,
|
|
1203
|
+
suggestions: [
|
|
1204
|
+
'Image processing failed',
|
|
1205
|
+
'Verify image format and encoding',
|
|
1206
|
+
'Try with a higher quality image',
|
|
1207
|
+
],
|
|
1208
|
+
}
|
|
1209
|
+
);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
// ===== Other Errors (9900-9999) =====
|
|
1214
|
+
|
|
1215
|
+
export class UnknownError extends PdfException {
|
|
1216
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1217
|
+
super(
|
|
1218
|
+
'9900',
|
|
1219
|
+
message,
|
|
1220
|
+
ErrorCategory.UNKNOWN,
|
|
1221
|
+
ErrorSeverity.HIGH,
|
|
1222
|
+
details,
|
|
1223
|
+
{
|
|
1224
|
+
canRetry: true,
|
|
1225
|
+
retryAfterMs: 1000,
|
|
1226
|
+
suggestions: [
|
|
1227
|
+
'An unknown error occurred',
|
|
1228
|
+
'Check the error message for details',
|
|
1229
|
+
'Try the operation again',
|
|
1230
|
+
'File a bug report if the problem persists',
|
|
1231
|
+
],
|
|
1232
|
+
}
|
|
1233
|
+
);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
export class InternalError extends PdfException {
|
|
1238
|
+
constructor(message: string, details: PdfErrorDetails = {}) {
|
|
1239
|
+
super(
|
|
1240
|
+
'9901',
|
|
1241
|
+
message,
|
|
1242
|
+
ErrorCategory.UNKNOWN,
|
|
1243
|
+
ErrorSeverity.CRITICAL,
|
|
1244
|
+
details,
|
|
1245
|
+
{
|
|
1246
|
+
canRetry: true,
|
|
1247
|
+
retryAfterMs: 2000,
|
|
1248
|
+
suggestions: [
|
|
1249
|
+
'An internal error occurred',
|
|
1250
|
+
'Please restart the application',
|
|
1251
|
+
'Check system resources',
|
|
1252
|
+
'File a bug report with error details',
|
|
1253
|
+
],
|
|
1254
|
+
}
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
// ===== Error Mapping from Rust FFI =====
|
|
1260
|
+
|
|
1261
|
+
/**
|
|
1262
|
+
* Maps Rust error type names to JavaScript exception types.
|
|
1263
|
+
*/
|
|
1264
|
+
export const ERROR_MAP: Record<string, new (message: string, details?: PdfErrorDetails) => PdfException> = {
|
|
1265
|
+
// Parse errors
|
|
1266
|
+
InvalidStructure,
|
|
1267
|
+
CorruptedData,
|
|
1268
|
+
UnsupportedVersion,
|
|
1269
|
+
|
|
1270
|
+
// I/O errors
|
|
1271
|
+
FileNotFound,
|
|
1272
|
+
PermissionDenied,
|
|
1273
|
+
DiskFull,
|
|
1274
|
+
NetworkError,
|
|
1275
|
+
|
|
1276
|
+
// Encryption errors
|
|
1277
|
+
InvalidPassword,
|
|
1278
|
+
DecryptionFailed,
|
|
1279
|
+
UnsupportedAlgorithm,
|
|
1280
|
+
|
|
1281
|
+
// State errors
|
|
1282
|
+
DocumentClosed,
|
|
1283
|
+
OperationNotAllowed,
|
|
1284
|
+
InvalidOperation,
|
|
1285
|
+
|
|
1286
|
+
// Unsupported features
|
|
1287
|
+
FeatureNotImplemented,
|
|
1288
|
+
FormatNotSupported,
|
|
1289
|
+
EncodingNotSupported,
|
|
1290
|
+
|
|
1291
|
+
// Validation errors
|
|
1292
|
+
InvalidParameter,
|
|
1293
|
+
InvalidValue,
|
|
1294
|
+
MissingRequired,
|
|
1295
|
+
TypeMismatch,
|
|
1296
|
+
|
|
1297
|
+
// Rendering errors
|
|
1298
|
+
RenderFailed,
|
|
1299
|
+
UnsupportedRenderFormat,
|
|
1300
|
+
InsufficientMemory,
|
|
1301
|
+
|
|
1302
|
+
// Search errors
|
|
1303
|
+
SearchFailed,
|
|
1304
|
+
InvalidPattern,
|
|
1305
|
+
IndexCorrupted,
|
|
1306
|
+
|
|
1307
|
+
// Signature errors
|
|
1308
|
+
SignatureException,
|
|
1309
|
+
CertificateLoadFailed,
|
|
1310
|
+
SigningFailed,
|
|
1311
|
+
|
|
1312
|
+
// Redaction errors
|
|
1313
|
+
RedactionException,
|
|
1314
|
+
|
|
1315
|
+
// Accessibility errors
|
|
1316
|
+
AccessibilityException,
|
|
1317
|
+
|
|
1318
|
+
// Optimization errors
|
|
1319
|
+
OptimizationException,
|
|
1320
|
+
|
|
1321
|
+
// Other errors
|
|
1322
|
+
ComplianceException,
|
|
1323
|
+
OcrException,
|
|
1324
|
+
UnknownError,
|
|
1325
|
+
};
|
|
1326
|
+
|
|
1327
|
+
/**
|
|
1328
|
+
* Maps a Rust error type to a JavaScript exception.
|
|
1329
|
+
*
|
|
1330
|
+
* @param rustErrorType - Rust error type name
|
|
1331
|
+
* @param message - Error message
|
|
1332
|
+
* @param details - Additional context
|
|
1333
|
+
* @returns Appropriate error instance
|
|
1334
|
+
*
|
|
1335
|
+
* @example
|
|
1336
|
+
* try {
|
|
1337
|
+
* // Native call
|
|
1338
|
+
* } catch (err) {
|
|
1339
|
+
* const jsErr = mapError('FileNotFound', 'File does not exist', { path: '/tmp/doc.pdf' });
|
|
1340
|
+
* throw jsErr;
|
|
1341
|
+
* }
|
|
1342
|
+
*/
|
|
1343
|
+
export function mapError(
|
|
1344
|
+
rustErrorType: string,
|
|
1345
|
+
message: string,
|
|
1346
|
+
details: PdfErrorDetails = {}
|
|
1347
|
+
): PdfException {
|
|
1348
|
+
const ErrorClass = ERROR_MAP[rustErrorType] || UnknownError;
|
|
1349
|
+
return new ErrorClass(message, details);
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
/**
|
|
1353
|
+
* Maps a numeric FFI error code from the Rust layer to a JavaScript exception.
|
|
1354
|
+
*
|
|
1355
|
+
* FFI Error Codes:
|
|
1356
|
+
* - 0: Success (no error)
|
|
1357
|
+
* - 1: I/O error
|
|
1358
|
+
* - 2: Parse error
|
|
1359
|
+
* - 3: Encryption error
|
|
1360
|
+
* - 4: Invalid state error
|
|
1361
|
+
* - 5: Rendering unsupported
|
|
1362
|
+
* - 6: OCR unsupported
|
|
1363
|
+
* - 7: Invalid argument
|
|
1364
|
+
* - 8: Signature error
|
|
1365
|
+
* - 100: Internal/generic error
|
|
1366
|
+
*
|
|
1367
|
+
* @param errorCode - Numeric FFI error code from native layer
|
|
1368
|
+
* @param message - Optional error message override
|
|
1369
|
+
* @returns Appropriate error instance
|
|
1370
|
+
*
|
|
1371
|
+
* @example
|
|
1372
|
+
* const errorCode = nativeCall();
|
|
1373
|
+
* if (errorCode !== 0) {
|
|
1374
|
+
* throw mapFfiErrorCode(errorCode, 'Operation failed');
|
|
1375
|
+
* }
|
|
1376
|
+
*/
|
|
1377
|
+
export function mapFfiErrorCode(
|
|
1378
|
+
errorCode: number,
|
|
1379
|
+
message?: string
|
|
1380
|
+
): PdfException {
|
|
1381
|
+
switch (errorCode) {
|
|
1382
|
+
case 0:
|
|
1383
|
+
return new UnknownError(message ?? 'Success (no error)');
|
|
1384
|
+
case 1:
|
|
1385
|
+
return new IoException(message ?? 'I/O error: File not found, permission denied, or read/write failed');
|
|
1386
|
+
case 2:
|
|
1387
|
+
return new ParseException(message ?? 'Parse error: Invalid PDF structure or content stream');
|
|
1388
|
+
case 3:
|
|
1389
|
+
return new EncryptionException(message ?? 'Encryption error: Incorrect password or unsupported encryption');
|
|
1390
|
+
case 4:
|
|
1391
|
+
return new InvalidStateException(message ?? 'Invalid state: Operation not allowed in current document state');
|
|
1392
|
+
case 5:
|
|
1393
|
+
return new UnsupportedFeatureException(message ?? 'Feature not enabled: Rendering support not compiled in');
|
|
1394
|
+
case 6:
|
|
1395
|
+
return new UnsupportedFeatureException(message ?? 'Feature not enabled: OCR support not compiled in');
|
|
1396
|
+
case 7:
|
|
1397
|
+
return new InvalidParameter(message ?? 'Invalid argument: Null pointer or invalid parameter passed');
|
|
1398
|
+
case 8:
|
|
1399
|
+
return new SignatureException(message ?? 'Signature error: Certificate loading, signing, or verification failed');
|
|
1400
|
+
case 9:
|
|
1401
|
+
return new RedactionException(message ?? 'Redaction error: Content redaction or metadata scrubbing failed');
|
|
1402
|
+
case 10:
|
|
1403
|
+
return new ComplianceException(message ?? 'Compliance error: PDF/A, PDF/X, or PDF/UA conversion or validation failed');
|
|
1404
|
+
case 11:
|
|
1405
|
+
return new AccessibilityException(message ?? 'Accessibility error: Tagging, structure tree, or alt text operation failed');
|
|
1406
|
+
case 12:
|
|
1407
|
+
return new OptimizationException(message ?? 'Optimization error: Font subsetting, image downsampling, or deduplication failed');
|
|
1408
|
+
default:
|
|
1409
|
+
return new UnknownError(message ?? `Unknown error (code: ${errorCode})`);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
/**
|
|
1414
|
+
* Creates an error with optional context.
|
|
1415
|
+
*
|
|
1416
|
+
* @param code - 4-digit error code
|
|
1417
|
+
* @param message - Error message
|
|
1418
|
+
* @param options - Configuration options
|
|
1419
|
+
* @returns Created exception
|
|
1420
|
+
*
|
|
1421
|
+
* @example
|
|
1422
|
+
* const err = createError('7100', 'Rendering failed', {
|
|
1423
|
+
* operation: 'renderPage',
|
|
1424
|
+
* context: { page: 0, format: 'png' }
|
|
1425
|
+
* });
|
|
1426
|
+
*/
|
|
1427
|
+
export function createError(
|
|
1428
|
+
code: string,
|
|
1429
|
+
message: string,
|
|
1430
|
+
options: {
|
|
1431
|
+
operation?: string;
|
|
1432
|
+
context?: Record<string, any>;
|
|
1433
|
+
} = {}
|
|
1434
|
+
): PdfException {
|
|
1435
|
+
// Map code to appropriate error class
|
|
1436
|
+
const codeMap: Record<string, new (message: string, details?: PdfErrorDetails) => PdfException> = {
|
|
1437
|
+
'1101': InvalidStructure,
|
|
1438
|
+
'1200': CorruptedData,
|
|
1439
|
+
'1300': UnsupportedVersion,
|
|
1440
|
+
'2100': FileNotFound,
|
|
1441
|
+
'2200': PermissionDenied,
|
|
1442
|
+
'2300': DiskFull,
|
|
1443
|
+
'2400': NetworkError,
|
|
1444
|
+
'3100': InvalidPassword,
|
|
1445
|
+
'3200': DecryptionFailed,
|
|
1446
|
+
'3300': UnsupportedAlgorithm,
|
|
1447
|
+
'4100': DocumentClosed,
|
|
1448
|
+
'4200': OperationNotAllowed,
|
|
1449
|
+
'4300': InvalidOperation,
|
|
1450
|
+
'5100': FeatureNotImplemented,
|
|
1451
|
+
'5200': FormatNotSupported,
|
|
1452
|
+
'5300': EncodingNotSupported,
|
|
1453
|
+
'6100': InvalidParameter,
|
|
1454
|
+
'6200': InvalidValue,
|
|
1455
|
+
'6300': MissingRequired,
|
|
1456
|
+
'6400': TypeMismatch,
|
|
1457
|
+
'7100': RenderFailed,
|
|
1458
|
+
'7200': UnsupportedRenderFormat,
|
|
1459
|
+
'7300': InsufficientMemory,
|
|
1460
|
+
'8100': SearchFailed,
|
|
1461
|
+
'8200': InvalidPattern,
|
|
1462
|
+
'8300': IndexCorrupted,
|
|
1463
|
+
'8500': SignatureException,
|
|
1464
|
+
'8501': CertificateLoadFailed,
|
|
1465
|
+
'8502': SigningFailed,
|
|
1466
|
+
'8600': RedactionException,
|
|
1467
|
+
'9500': AccessibilityException,
|
|
1468
|
+
'9600': OptimizationException,
|
|
1469
|
+
'9100': InvalidCompliance,
|
|
1470
|
+
'9150': ValidationFailed,
|
|
1471
|
+
'9200': OcrException,
|
|
1472
|
+
'9201': RecognitionFailed,
|
|
1473
|
+
'9202': LanguageNotSupported,
|
|
1474
|
+
'9203': ImageProcessingFailed,
|
|
1475
|
+
};
|
|
1476
|
+
|
|
1477
|
+
const ErrorClass = codeMap[code];
|
|
1478
|
+
const context = options.context || {};
|
|
1479
|
+
|
|
1480
|
+
let err: PdfException;
|
|
1481
|
+
if (ErrorClass) {
|
|
1482
|
+
err = new ErrorClass(message, context);
|
|
1483
|
+
} else {
|
|
1484
|
+
err = new PdfException(
|
|
1485
|
+
code,
|
|
1486
|
+
message,
|
|
1487
|
+
ErrorCategory.UNKNOWN,
|
|
1488
|
+
ErrorSeverity.HIGH,
|
|
1489
|
+
context
|
|
1490
|
+
);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
if (options.operation) {
|
|
1494
|
+
err.withContext(options.operation, context);
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
return err;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
/**
|
|
1501
|
+
* Maps native error to appropriate PDF exception.
|
|
1502
|
+
*
|
|
1503
|
+
* @param error - The error to wrap
|
|
1504
|
+
* @returns Wrapped exception
|
|
1505
|
+
*
|
|
1506
|
+
* @example
|
|
1507
|
+
* try {
|
|
1508
|
+
* // Native call
|
|
1509
|
+
* } catch (err) {
|
|
1510
|
+
* const wrapped = wrapError(err);
|
|
1511
|
+
* console.log(wrapped.code); // e.g., "2100"
|
|
1512
|
+
* }
|
|
1513
|
+
*/
|
|
1514
|
+
export function wrapError(error: unknown): PdfException {
|
|
1515
|
+
// If already a PdfException, return as-is
|
|
1516
|
+
if (error instanceof PdfException) {
|
|
1517
|
+
return error;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
let code = '9900';
|
|
1521
|
+
let message = 'Unknown error occurred';
|
|
1522
|
+
let details: PdfErrorDetails = {};
|
|
1523
|
+
|
|
1524
|
+
// Handle Error objects
|
|
1525
|
+
if (error instanceof Error) {
|
|
1526
|
+
message = error.message;
|
|
1527
|
+
|
|
1528
|
+
// Try to extract code from message format: [XXXX] message
|
|
1529
|
+
const codeMatch = message.match(/^\[(\d{4})\]/);
|
|
1530
|
+
if (codeMatch && codeMatch[1]) {
|
|
1531
|
+
code = codeMatch[1];
|
|
1532
|
+
message = message.replace(/^\[\d{4}\]\s*/, '');
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
// Copy additional properties
|
|
1536
|
+
const props = Object.getOwnPropertyNames(error);
|
|
1537
|
+
for (const prop of props) {
|
|
1538
|
+
if (prop !== 'message' && prop !== 'name' && prop !== 'stack') {
|
|
1539
|
+
details[prop as keyof PdfErrorDetails] = (error as any)[prop];
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
// Handle plain objects
|
|
1544
|
+
else if (error && typeof error === 'object') {
|
|
1545
|
+
const obj = error as Record<string, any>;
|
|
1546
|
+
if (obj.code) {
|
|
1547
|
+
code = String(obj.code);
|
|
1548
|
+
// Convert string codes to 4-digit if needed
|
|
1549
|
+
if (!/^\d{4}$/.test(code)) {
|
|
1550
|
+
code = '9900';
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
if (obj.message && typeof obj.message === 'string') {
|
|
1554
|
+
message = obj.message;
|
|
1555
|
+
}
|
|
1556
|
+
details = obj as PdfErrorDetails;
|
|
1557
|
+
}
|
|
1558
|
+
// Handle strings
|
|
1559
|
+
else if (typeof error === 'string') {
|
|
1560
|
+
message = error;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
try {
|
|
1564
|
+
return new PdfException(
|
|
1565
|
+
code,
|
|
1566
|
+
message,
|
|
1567
|
+
ErrorCategory.UNKNOWN,
|
|
1568
|
+
ErrorSeverity.HIGH,
|
|
1569
|
+
details
|
|
1570
|
+
);
|
|
1571
|
+
} catch {
|
|
1572
|
+
// If code validation fails, use generic error
|
|
1573
|
+
return new UnknownError(message, details);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
/**
|
|
1578
|
+
* Function signature for methods to be wrapped
|
|
1579
|
+
*/
|
|
1580
|
+
type MethodFunction = (...args: any[]) => any;
|
|
1581
|
+
type AsyncMethodFunction = (...args: any[]) => Promise<any>;
|
|
1582
|
+
|
|
1583
|
+
/**
|
|
1584
|
+
* Creates a method wrapper that catches native errors and converts them.
|
|
1585
|
+
*
|
|
1586
|
+
* @param fn - The method to wrap
|
|
1587
|
+
* @param thisArg - The context (this) to bind
|
|
1588
|
+
* @returns Wrapped function with error conversion
|
|
1589
|
+
*
|
|
1590
|
+
* @example
|
|
1591
|
+
* const wrapped = wrapMethod(nativeMethod, this);
|
|
1592
|
+
* const result = wrapped(arg1, arg2); // Throws PdfException on error
|
|
1593
|
+
*/
|
|
1594
|
+
export function wrapMethod<T extends MethodFunction>(
|
|
1595
|
+
fn: T,
|
|
1596
|
+
thisArg: any = null
|
|
1597
|
+
): T {
|
|
1598
|
+
return function (this: any, ...args: any[]) {
|
|
1599
|
+
try {
|
|
1600
|
+
return fn.apply(thisArg || this, args);
|
|
1601
|
+
} catch (nativeErr) {
|
|
1602
|
+
throw wrapError(nativeErr);
|
|
1603
|
+
}
|
|
1604
|
+
} as T;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
/**
|
|
1608
|
+
* Creates an async method wrapper that catches native errors.
|
|
1609
|
+
*
|
|
1610
|
+
* @param fn - The async method to wrap
|
|
1611
|
+
* @param thisArg - The context (this) to bind
|
|
1612
|
+
* @returns Wrapped async function with error conversion
|
|
1613
|
+
*
|
|
1614
|
+
* @example
|
|
1615
|
+
* const wrapped = wrapAsyncMethod(nativeAsyncMethod, this);
|
|
1616
|
+
* const result = await wrapped(arg1, arg2); // Throws PdfException on error
|
|
1617
|
+
*/
|
|
1618
|
+
export function wrapAsyncMethod<T extends AsyncMethodFunction>(
|
|
1619
|
+
fn: T,
|
|
1620
|
+
thisArg: any = null
|
|
1621
|
+
): T {
|
|
1622
|
+
return async function (this: any, ...args: any[]) {
|
|
1623
|
+
try {
|
|
1624
|
+
return await fn.apply(thisArg || this, args);
|
|
1625
|
+
} catch (nativeErr) {
|
|
1626
|
+
throw wrapError(nativeErr);
|
|
1627
|
+
}
|
|
1628
|
+
} as T;
|
|
1629
|
+
}
|