@fin.cx/einvoice 5.0.2

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.
Files changed (171) hide show
  1. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  2. package/dist_ts/00_commitinfo_data.js +9 -0
  3. package/dist_ts/classes.decoder.d.ts +40 -0
  4. package/dist_ts/classes.decoder.js +320 -0
  5. package/dist_ts/classes.encoder.d.ts +51 -0
  6. package/dist_ts/classes.encoder.js +293 -0
  7. package/dist_ts/classes.xinvoice.d.ts +136 -0
  8. package/dist_ts/classes.xinvoice.js +352 -0
  9. package/dist_ts/einvoice.d.ts +217 -0
  10. package/dist_ts/einvoice.js +505 -0
  11. package/dist_ts/errors.d.ts +121 -0
  12. package/dist_ts/errors.js +241 -0
  13. package/dist_ts/formats/base/base.decoder.d.ts +32 -0
  14. package/dist_ts/formats/base/base.decoder.js +52 -0
  15. package/dist_ts/formats/base/base.encoder.d.ts +13 -0
  16. package/dist_ts/formats/base/base.encoder.js +7 -0
  17. package/dist_ts/formats/base/base.validator.d.ts +44 -0
  18. package/dist_ts/formats/base/base.validator.js +39 -0
  19. package/dist_ts/formats/base.decoder.d.ts +19 -0
  20. package/dist_ts/formats/base.decoder.js +130 -0
  21. package/dist_ts/formats/base.validator.d.ts +44 -0
  22. package/dist_ts/formats/base.validator.js +39 -0
  23. package/dist_ts/formats/cii/cii.decoder.d.ts +61 -0
  24. package/dist_ts/formats/cii/cii.decoder.js +111 -0
  25. package/dist_ts/formats/cii/cii.encoder.d.ts +43 -0
  26. package/dist_ts/formats/cii/cii.encoder.js +48 -0
  27. package/dist_ts/formats/cii/cii.types.d.ts +31 -0
  28. package/dist_ts/formats/cii/cii.types.js +40 -0
  29. package/dist_ts/formats/cii/cii.validator.d.ts +56 -0
  30. package/dist_ts/formats/cii/cii.validator.js +146 -0
  31. package/dist_ts/formats/cii/facturx/facturx.decoder.d.ts +43 -0
  32. package/dist_ts/formats/cii/facturx/facturx.decoder.js +207 -0
  33. package/dist_ts/formats/cii/facturx/facturx.encoder.d.ts +82 -0
  34. package/dist_ts/formats/cii/facturx/facturx.encoder.js +400 -0
  35. package/dist_ts/formats/cii/facturx/facturx.types.d.ts +10 -0
  36. package/dist_ts/formats/cii/facturx/facturx.types.js +15 -0
  37. package/dist_ts/formats/cii/facturx/facturx.validator.d.ts +32 -0
  38. package/dist_ts/formats/cii/facturx/facturx.validator.js +138 -0
  39. package/dist_ts/formats/cii/zugferd/zugferd.decoder.d.ts +43 -0
  40. package/dist_ts/formats/cii/zugferd/zugferd.decoder.js +218 -0
  41. package/dist_ts/formats/cii/zugferd/zugferd.encoder.d.ts +97 -0
  42. package/dist_ts/formats/cii/zugferd/zugferd.encoder.js +550 -0
  43. package/dist_ts/formats/cii/zugferd/zugferd.types.d.ts +10 -0
  44. package/dist_ts/formats/cii/zugferd/zugferd.types.js +15 -0
  45. package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.d.ts +49 -0
  46. package/dist_ts/formats/cii/zugferd/zugferd.v1.decoder.js +229 -0
  47. package/dist_ts/formats/cii/zugferd/zugferd.validator.d.ts +16 -0
  48. package/dist_ts/formats/cii/zugferd/zugferd.validator.js +29 -0
  49. package/dist_ts/formats/decoder.factory.d.ts +15 -0
  50. package/dist_ts/formats/decoder.factory.js +46 -0
  51. package/dist_ts/formats/factories/decoder.factory.d.ts +13 -0
  52. package/dist_ts/formats/factories/decoder.factory.js +56 -0
  53. package/dist_ts/formats/factories/encoder.factory.d.ts +14 -0
  54. package/dist_ts/formats/factories/encoder.factory.js +40 -0
  55. package/dist_ts/formats/factories/validator.factory.d.ts +12 -0
  56. package/dist_ts/formats/factories/validator.factory.js +110 -0
  57. package/dist_ts/formats/factorx.decoder.d.ts +18 -0
  58. package/dist_ts/formats/factorx.decoder.js +178 -0
  59. package/dist_ts/formats/factorx.encoder.d.ts +51 -0
  60. package/dist_ts/formats/factorx.encoder.js +293 -0
  61. package/dist_ts/formats/facturx.decoder.d.ts +18 -0
  62. package/dist_ts/formats/facturx.decoder.js +210 -0
  63. package/dist_ts/formats/facturx.encoder.d.ts +51 -0
  64. package/dist_ts/formats/facturx.encoder.js +293 -0
  65. package/dist_ts/formats/facturx.validator.d.ts +67 -0
  66. package/dist_ts/formats/facturx.validator.js +266 -0
  67. package/dist_ts/formats/pdf/extractors/associated.extractor.d.ts +14 -0
  68. package/dist_ts/formats/pdf/extractors/associated.extractor.js +68 -0
  69. package/dist_ts/formats/pdf/extractors/base.extractor.d.ts +92 -0
  70. package/dist_ts/formats/pdf/extractors/base.extractor.js +319 -0
  71. package/dist_ts/formats/pdf/extractors/index.d.ts +4 -0
  72. package/dist_ts/formats/pdf/extractors/index.js +5 -0
  73. package/dist_ts/formats/pdf/extractors/standard.extractor.d.ts +13 -0
  74. package/dist_ts/formats/pdf/extractors/standard.extractor.js +74 -0
  75. package/dist_ts/formats/pdf/extractors/text.extractor.d.ts +45 -0
  76. package/dist_ts/formats/pdf/extractors/text.extractor.js +151 -0
  77. package/dist_ts/formats/pdf/pdf.embedder.d.ts +69 -0
  78. package/dist_ts/formats/pdf/pdf.embedder.js +183 -0
  79. package/dist_ts/formats/pdf/pdf.extractor.d.ts +49 -0
  80. package/dist_ts/formats/pdf/pdf.extractor.js +98 -0
  81. package/dist_ts/formats/pdf/robust-pdf.extractor.d.ts +40 -0
  82. package/dist_ts/formats/pdf/robust-pdf.extractor.js +324 -0
  83. package/dist_ts/formats/ubl/en16931.ubl.validator.d.ts +18 -0
  84. package/dist_ts/formats/ubl/en16931.ubl.validator.js +169 -0
  85. package/dist_ts/formats/ubl/generic/ubl.encoder.d.ts +151 -0
  86. package/dist_ts/formats/ubl/generic/ubl.encoder.js +892 -0
  87. package/dist_ts/formats/ubl/ubl.decoder.d.ts +61 -0
  88. package/dist_ts/formats/ubl/ubl.decoder.js +95 -0
  89. package/dist_ts/formats/ubl/ubl.encoder.d.ts +38 -0
  90. package/dist_ts/formats/ubl/ubl.encoder.js +46 -0
  91. package/dist_ts/formats/ubl/ubl.types.d.ts +16 -0
  92. package/dist_ts/formats/ubl/ubl.types.js +21 -0
  93. package/dist_ts/formats/ubl/ubl.validator.d.ts +50 -0
  94. package/dist_ts/formats/ubl/ubl.validator.js +112 -0
  95. package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.d.ts +34 -0
  96. package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.js +424 -0
  97. package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.d.ts +75 -0
  98. package/dist_ts/formats/ubl/xrechnung/xrechnung.encoder.js +555 -0
  99. package/dist_ts/formats/ubl/xrechnung.validator.d.ts +15 -0
  100. package/dist_ts/formats/ubl/xrechnung.validator.js +107 -0
  101. package/dist_ts/formats/ubl.validator.d.ts +82 -0
  102. package/dist_ts/formats/ubl.validator.js +306 -0
  103. package/dist_ts/formats/utils/format.detector.d.ts +62 -0
  104. package/dist_ts/formats/utils/format.detector.js +249 -0
  105. package/dist_ts/formats/validation/en16931.validator.d.ts +23 -0
  106. package/dist_ts/formats/validation/en16931.validator.js +119 -0
  107. package/dist_ts/formats/validator.factory.d.ts +18 -0
  108. package/dist_ts/formats/validator.factory.js +78 -0
  109. package/dist_ts/formats/xinvoice.decoder.d.ts +28 -0
  110. package/dist_ts/formats/xinvoice.decoder.js +332 -0
  111. package/dist_ts/formats/xinvoice.encoder.d.ts +19 -0
  112. package/dist_ts/formats/xinvoice.encoder.js +282 -0
  113. package/dist_ts/index.d.ts +51 -0
  114. package/dist_ts/index.js +90 -0
  115. package/dist_ts/interfaces/common.d.ts +79 -0
  116. package/dist_ts/interfaces/common.js +24 -0
  117. package/dist_ts/interfaces.d.ts +87 -0
  118. package/dist_ts/interfaces.js +23 -0
  119. package/dist_ts/plugins.d.ts +14 -0
  120. package/dist_ts/plugins.js +31 -0
  121. package/npmextra.json +35 -0
  122. package/package.json +71 -0
  123. package/readme.hints.md +1107 -0
  124. package/readme.howtofixtests.md +38 -0
  125. package/readme.literature.md +1 -0
  126. package/readme.md +998 -0
  127. package/readme.plan.md +481 -0
  128. package/ts/00_commitinfo_data.ts +8 -0
  129. package/ts/einvoice.ts +603 -0
  130. package/ts/errors.ts +341 -0
  131. package/ts/formats/base/base.decoder.ts +68 -0
  132. package/ts/formats/base/base.encoder.ts +14 -0
  133. package/ts/formats/base/base.validator.ts +64 -0
  134. package/ts/formats/cii/cii.decoder.ts +139 -0
  135. package/ts/formats/cii/cii.encoder.ts +64 -0
  136. package/ts/formats/cii/cii.types.ts +44 -0
  137. package/ts/formats/cii/cii.validator.ts +171 -0
  138. package/ts/formats/cii/facturx/facturx.decoder.ts +243 -0
  139. package/ts/formats/cii/facturx/facturx.encoder.ts +483 -0
  140. package/ts/formats/cii/facturx/facturx.types.ts +18 -0
  141. package/ts/formats/cii/facturx/facturx.validator.ts +180 -0
  142. package/ts/formats/cii/zugferd/zugferd.decoder.ts +256 -0
  143. package/ts/formats/cii/zugferd/zugferd.encoder.ts +661 -0
  144. package/ts/formats/cii/zugferd/zugferd.types.ts +18 -0
  145. package/ts/formats/cii/zugferd/zugferd.v1.decoder.ts +267 -0
  146. package/ts/formats/cii/zugferd/zugferd.validator.ts +31 -0
  147. package/ts/formats/factories/decoder.factory.ts +62 -0
  148. package/ts/formats/factories/encoder.factory.ts +47 -0
  149. package/ts/formats/factories/validator.factory.ts +134 -0
  150. package/ts/formats/pdf/extractors/associated.extractor.ts +78 -0
  151. package/ts/formats/pdf/extractors/base.extractor.ts +355 -0
  152. package/ts/formats/pdf/extractors/index.ts +4 -0
  153. package/ts/formats/pdf/extractors/standard.extractor.ts +86 -0
  154. package/ts/formats/pdf/extractors/text.extractor.ts +162 -0
  155. package/ts/formats/pdf/pdf.embedder.ts +242 -0
  156. package/ts/formats/pdf/pdf.extractor.ts +141 -0
  157. package/ts/formats/ubl/en16931.ubl.validator.ts +216 -0
  158. package/ts/formats/ubl/generic/ubl.encoder.ts +1041 -0
  159. package/ts/formats/ubl/ubl.decoder.ts +121 -0
  160. package/ts/formats/ubl/ubl.encoder.ts +63 -0
  161. package/ts/formats/ubl/ubl.types.ts +22 -0
  162. package/ts/formats/ubl/ubl.validator.ts +133 -0
  163. package/ts/formats/ubl/xrechnung/xrechnung.decoder.ts +471 -0
  164. package/ts/formats/ubl/xrechnung/xrechnung.encoder.ts +619 -0
  165. package/ts/formats/ubl/xrechnung.validator.ts +185 -0
  166. package/ts/formats/utils/format.detector.ts +306 -0
  167. package/ts/formats/validation/en16931.validator.ts +135 -0
  168. package/ts/index.ts +164 -0
  169. package/ts/interfaces/common.ts +90 -0
  170. package/ts/interfaces.ts +98 -0
  171. package/ts/plugins.ts +61 -0
@@ -0,0 +1,151 @@
1
+ import { BaseXMLExtractor } from './base.extractor.js';
2
+ /**
3
+ * Text-based XML extractor for PDF documents
4
+ * Extracts XML by searching for XML patterns in the PDF text
5
+ * Used as a fallback when other extraction methods fail
6
+ */
7
+ export class TextXMLExtractor extends BaseXMLExtractor {
8
+ constructor() {
9
+ super(...arguments);
10
+ // Maximum chunk size to process at once (4MB)
11
+ this.CHUNK_SIZE = 4 * 1024 * 1024;
12
+ // Maximum number of chunks to check (effective 20MB search limit)
13
+ this.MAX_CHUNKS = 5;
14
+ // Common XML patterns to look for
15
+ this.XML_PATTERNS = [
16
+ '<?xml',
17
+ '<CrossIndustryInvoice',
18
+ '<CrossIndustryDocument',
19
+ '<Invoice',
20
+ '<CreditNote',
21
+ '<rsm:CrossIndustryInvoice',
22
+ '<rsm:CrossIndustryDocument',
23
+ '<ram:CrossIndustryDocument',
24
+ '<ubl:Invoice',
25
+ '<ubl:CreditNote',
26
+ '<FatturaElettronica'
27
+ ];
28
+ }
29
+ /**
30
+ * Extract XML from a PDF buffer by searching for XML patterns in the text
31
+ * Uses a chunked approach to handle large files efficiently
32
+ * @param pdfBuffer PDF buffer
33
+ * @returns XML content or null if not found
34
+ */
35
+ async extractXml(pdfBuffer) {
36
+ try {
37
+ console.log('Attempting text-based XML extraction from PDF...');
38
+ // Convert Buffer to Uint8Array if needed
39
+ const buffer = Buffer.isBuffer(pdfBuffer) ? new Uint8Array(pdfBuffer) : pdfBuffer;
40
+ // Try extracting XML using the chunked approach
41
+ return this.extractXmlFromBufferChunked(buffer);
42
+ }
43
+ catch (error) {
44
+ console.error('Error in text-based extraction:', error);
45
+ return null;
46
+ }
47
+ }
48
+ /**
49
+ * Extract XML from buffer using a chunked approach
50
+ * This helps avoid memory issues with large PDFs
51
+ * @param buffer Buffer to search in
52
+ * @returns XML content or null if not found
53
+ */
54
+ extractXmlFromBufferChunked(buffer) {
55
+ // Process the PDF in chunks
56
+ for (let chunkIndex = 0; chunkIndex < this.MAX_CHUNKS; chunkIndex++) {
57
+ const startPos = chunkIndex * this.CHUNK_SIZE;
58
+ if (startPos >= buffer.length)
59
+ break;
60
+ const endPos = Math.min(startPos + this.CHUNK_SIZE, buffer.length);
61
+ const chunk = buffer.slice(startPos, endPos);
62
+ // Try to extract XML from this chunk
63
+ const chunkResult = this.processChunk(chunk, startPos);
64
+ if (chunkResult) {
65
+ return chunkResult;
66
+ }
67
+ }
68
+ console.warn('No valid XML found in any chunk of the PDF');
69
+ return null;
70
+ }
71
+ /**
72
+ * Process a single chunk of the PDF buffer
73
+ * @param chunk Chunk buffer to process
74
+ * @param chunkOffset Offset position of the chunk in the original buffer
75
+ * @returns XML content or null if not found
76
+ */
77
+ processChunk(chunk, chunkOffset) {
78
+ try {
79
+ // First try UTF-8 encoding for this chunk
80
+ const utf8String = this.decodeBufferToString(chunk, 'utf-8');
81
+ let xmlContent = this.searchForXmlInString(utf8String);
82
+ if (xmlContent) {
83
+ console.log(`Found XML content in chunk at offset ${chunkOffset} using UTF-8 encoding`);
84
+ return xmlContent;
85
+ }
86
+ // If UTF-8 fails, try Latin-1 (ISO-8859-1) which can handle binary better
87
+ const latin1String = this.decodeBufferToString(chunk, 'latin1');
88
+ xmlContent = this.searchForXmlInString(latin1String);
89
+ if (xmlContent) {
90
+ console.log(`Found XML content in chunk at offset ${chunkOffset} using Latin-1 encoding`);
91
+ return xmlContent;
92
+ }
93
+ // No XML found in this chunk
94
+ return null;
95
+ }
96
+ catch (error) {
97
+ console.warn(`Error processing chunk at offset ${chunkOffset}:`, error);
98
+ return null;
99
+ }
100
+ }
101
+ /**
102
+ * Safely decode a buffer to string using the specified encoding
103
+ * @param buffer Buffer to decode
104
+ * @param encoding Encoding to use ('utf-8' or 'latin1')
105
+ * @returns Decoded string
106
+ */
107
+ decodeBufferToString(buffer, encoding) {
108
+ try {
109
+ if (encoding === 'utf-8') {
110
+ return new TextDecoder('utf-8', { fatal: false }).decode(buffer);
111
+ }
112
+ else {
113
+ // For Latin-1 we can use a direct mapping (bytes 0-255 map directly to code points 0-255)
114
+ // This is more reliable for binary data than TextDecoder for legacy encodings
115
+ return Array.from(buffer)
116
+ .map(byte => String.fromCharCode(byte))
117
+ .join('');
118
+ }
119
+ }
120
+ catch (error) {
121
+ console.warn(`Error decoding buffer using ${encoding}:`, error);
122
+ // Return empty string on error to allow processing to continue
123
+ return '';
124
+ }
125
+ }
126
+ /**
127
+ * Search for XML patterns in a string
128
+ * @param content String to search in
129
+ * @returns XML content or null if not found
130
+ */
131
+ searchForXmlInString(content) {
132
+ if (!content)
133
+ return null;
134
+ // Search for each XML pattern
135
+ for (const pattern of this.XML_PATTERNS) {
136
+ const patternIndex = content.indexOf(pattern);
137
+ if (patternIndex !== -1) {
138
+ console.log(`Found XML pattern "${pattern}" at position ${patternIndex}`);
139
+ // Try to extract the XML content starting from the pattern position
140
+ const xmlContent = this.extractXmlFromString(content, patternIndex);
141
+ // Validate the extracted content
142
+ if (xmlContent && this.isValidXml(xmlContent)) {
143
+ console.log('Successfully extracted and validated XML from text');
144
+ return xmlContent;
145
+ }
146
+ }
147
+ }
148
+ return null;
149
+ }
150
+ }
151
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC5leHRyYWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9mb3JtYXRzL3BkZi9leHRyYWN0b3JzL3RleHQuZXh0cmFjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRXZEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWlCLFNBQVEsZ0JBQWdCO0lBQXREOztRQUNFLDhDQUE4QztRQUM3QixlQUFVLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7UUFFOUMsa0VBQWtFO1FBQ2pELGVBQVUsR0FBRyxDQUFDLENBQUM7UUFFaEMsa0NBQWtDO1FBQ2pCLGlCQUFZLEdBQUc7WUFDOUIsT0FBTztZQUNQLHVCQUF1QjtZQUN2Qix3QkFBd0I7WUFDeEIsVUFBVTtZQUNWLGFBQWE7WUFDYiwyQkFBMkI7WUFDM0IsNEJBQTRCO1lBQzVCLDRCQUE0QjtZQUM1QixjQUFjO1lBQ2QsaUJBQWlCO1lBQ2pCLHFCQUFxQjtTQUN0QixDQUFDO0lBc0lKLENBQUM7SUFwSUM7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsVUFBVSxDQUFDLFNBQThCO1FBQ3BELElBQUksQ0FBQztZQUNILE9BQU8sQ0FBQyxHQUFHLENBQUMsa0RBQWtELENBQUMsQ0FBQztZQUVoRSx5Q0FBeUM7WUFDekMsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUVsRixnREFBZ0Q7WUFDaEQsT0FBTyxJQUFJLENBQUMsMkJBQTJCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbEQsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixPQUFPLENBQUMsS0FBSyxDQUFDLGlDQUFpQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3hELE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLDJCQUEyQixDQUFDLE1BQWtCO1FBQ3BELDRCQUE0QjtRQUM1QixLQUFLLElBQUksVUFBVSxHQUFHLENBQUMsRUFBRSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsRUFBRSxDQUFDO1lBQ3BFLE1BQU0sUUFBUSxHQUFHLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO1lBQzlDLElBQUksUUFBUSxJQUFJLE1BQU0sQ0FBQyxNQUFNO2dCQUFFLE1BQU07WUFFckMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbkUsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFFN0MscUNBQXFDO1lBQ3JDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3ZELElBQUksV0FBVyxFQUFFLENBQUM7Z0JBQ2hCLE9BQU8sV0FBVyxDQUFDO1lBQ3JCLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxDQUFDLElBQUksQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO1FBQzNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssWUFBWSxDQUFDLEtBQWlCLEVBQUUsV0FBbUI7UUFDekQsSUFBSSxDQUFDO1lBQ0gsMENBQTBDO1lBQzFDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDN0QsSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBRXZELElBQUksVUFBVSxFQUFFLENBQUM7Z0JBQ2YsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3Q0FBd0MsV0FBVyx1QkFBdUIsQ0FBQyxDQUFDO2dCQUN4RixPQUFPLFVBQVUsQ0FBQztZQUNwQixDQUFDO1lBRUQsMEVBQTBFO1lBQzFFLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDaEUsVUFBVSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUVyRCxJQUFJLFVBQVUsRUFBRSxDQUFDO2dCQUNmLE9BQU8sQ0FBQyxHQUFHLENBQUMsd0NBQXdDLFdBQVcseUJBQXlCLENBQUMsQ0FBQztnQkFDMUYsT0FBTyxVQUFVLENBQUM7WUFDcEIsQ0FBQztZQUVELDZCQUE2QjtZQUM3QixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxDQUFDLElBQUksQ0FBQyxvQ0FBb0MsV0FBVyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDeEUsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssb0JBQW9CLENBQUMsTUFBa0IsRUFBRSxRQUE0QjtRQUMzRSxJQUFJLENBQUM7WUFDSCxJQUFJLFFBQVEsS0FBSyxPQUFPLEVBQUUsQ0FBQztnQkFDekIsT0FBTyxJQUFJLFdBQVcsQ0FBQyxPQUFPLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbkUsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLDBGQUEwRjtnQkFDMUYsOEVBQThFO2dCQUM5RSxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO3FCQUN0QixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO3FCQUN0QyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixPQUFPLENBQUMsSUFBSSxDQUFDLCtCQUErQixRQUFRLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNoRSwrREFBK0Q7WUFDL0QsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxvQkFBb0IsQ0FBQyxPQUFlO1FBQzFDLElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFFMUIsOEJBQThCO1FBQzlCLEtBQUssTUFBTSxPQUFPLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3hDLE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDOUMsSUFBSSxZQUFZLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDeEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsT0FBTyxpQkFBaUIsWUFBWSxFQUFFLENBQUMsQ0FBQztnQkFFMUUsb0VBQW9FO2dCQUNwRSxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUVwRSxpQ0FBaUM7Z0JBQ2pDLElBQUksVUFBVSxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztvQkFDOUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO29CQUNsRSxPQUFPLFVBQVUsQ0FBQztnQkFDcEIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0NBQ0YifQ==
@@ -0,0 +1,69 @@
1
+ import type { IPdf } from '../../interfaces/common.js';
2
+ /**
3
+ * Error types for PDF embedding operations
4
+ */
5
+ export declare enum PDFEmbedError {
6
+ LOAD_ERROR = "PDF loading failed",
7
+ EMBED_ERROR = "XML embedding failed",
8
+ SAVE_ERROR = "PDF saving failed",
9
+ INVALID_INPUT = "Invalid input parameters"
10
+ }
11
+ /**
12
+ * Result of a PDF embedding operation
13
+ */
14
+ export interface PDFEmbedResult {
15
+ success: boolean;
16
+ data?: Uint8Array;
17
+ pdf?: IPdf;
18
+ error?: {
19
+ type: PDFEmbedError;
20
+ message: string;
21
+ originalError?: Error;
22
+ };
23
+ }
24
+ /**
25
+ * Class for embedding XML into PDF files
26
+ * Provides robust error handling and support for different PDF formats
27
+ */
28
+ export declare class PDFEmbedder {
29
+ /**
30
+ * Embeds XML into a PDF
31
+ * @param pdfBuffer PDF buffer
32
+ * @param xmlContent XML content to embed
33
+ * @param filename Filename for the embedded XML
34
+ * @param description Description for the embedded XML
35
+ * @returns Result with either modified PDF buffer or error information
36
+ */
37
+ embedXml(pdfBuffer: Uint8Array | Buffer, xmlContent: string, filename?: string, description?: string): Promise<PDFEmbedResult>;
38
+ /**
39
+ * Creates an IPdf object with embedded XML
40
+ * @param pdfBuffer PDF buffer
41
+ * @param xmlContent XML content to embed
42
+ * @param filename Filename for the embedded XML
43
+ * @param description Description for the embedded XML
44
+ * @param pdfName Name for the PDF
45
+ * @param pdfId ID for the PDF
46
+ * @returns Result with either IPdf object or error information
47
+ */
48
+ createPdfWithXml(pdfBuffer: Uint8Array | Buffer, xmlContent: string, filename?: string, description?: string, pdfName?: string, pdfId?: string): Promise<PDFEmbedResult>;
49
+ /**
50
+ * Ensures the filename is normalized according to PDF/A requirements
51
+ * @param filename Filename to normalize
52
+ * @returns Normalized filename
53
+ */
54
+ private normalizeFilename;
55
+ /**
56
+ * Tries to detect the format of the XML content
57
+ * @param xmlContent XML content
58
+ * @returns Format string or undefined
59
+ */
60
+ private detectPdfFormat;
61
+ /**
62
+ * Creates an error result object
63
+ * @param type Error type
64
+ * @param message Error message
65
+ * @param originalError Original error object
66
+ * @returns Error result
67
+ */
68
+ private createErrorResult;
69
+ }
@@ -0,0 +1,183 @@
1
+ import { PDFDocument, AFRelationship } from '../../plugins.js';
2
+ /**
3
+ * Error types for PDF embedding operations
4
+ */
5
+ export var PDFEmbedError;
6
+ (function (PDFEmbedError) {
7
+ PDFEmbedError["LOAD_ERROR"] = "PDF loading failed";
8
+ PDFEmbedError["EMBED_ERROR"] = "XML embedding failed";
9
+ PDFEmbedError["SAVE_ERROR"] = "PDF saving failed";
10
+ PDFEmbedError["INVALID_INPUT"] = "Invalid input parameters";
11
+ })(PDFEmbedError || (PDFEmbedError = {}));
12
+ /**
13
+ * Class for embedding XML into PDF files
14
+ * Provides robust error handling and support for different PDF formats
15
+ */
16
+ export class PDFEmbedder {
17
+ /**
18
+ * Embeds XML into a PDF
19
+ * @param pdfBuffer PDF buffer
20
+ * @param xmlContent XML content to embed
21
+ * @param filename Filename for the embedded XML
22
+ * @param description Description for the embedded XML
23
+ * @returns Result with either modified PDF buffer or error information
24
+ */
25
+ async embedXml(pdfBuffer, xmlContent, filename = 'invoice.xml', description = 'XML Invoice') {
26
+ try {
27
+ // Validate inputs
28
+ if (!pdfBuffer || pdfBuffer.length === 0) {
29
+ return this.createErrorResult(PDFEmbedError.INVALID_INPUT, 'PDF buffer is empty or undefined');
30
+ }
31
+ if (!xmlContent) {
32
+ return this.createErrorResult(PDFEmbedError.INVALID_INPUT, 'XML content is empty or undefined');
33
+ }
34
+ // Ensure buffer is Uint8Array
35
+ const pdfBufferArray = Buffer.isBuffer(pdfBuffer) ? new Uint8Array(pdfBuffer) : pdfBuffer;
36
+ // Load the PDF
37
+ let pdfDoc;
38
+ try {
39
+ pdfDoc = await PDFDocument.load(pdfBufferArray, {
40
+ ignoreEncryption: true, // Try to load encrypted PDFs
41
+ updateMetadata: false // Don't automatically update metadata
42
+ });
43
+ }
44
+ catch (error) {
45
+ return this.createErrorResult(PDFEmbedError.LOAD_ERROR, `Failed to load PDF: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : undefined);
46
+ }
47
+ // Normalize filename (lowercase with XML extension)
48
+ filename = this.normalizeFilename(filename);
49
+ // Convert the XML string to a Uint8Array
50
+ const xmlBuffer = new TextEncoder().encode(xmlContent);
51
+ try {
52
+ // Use pdf-lib's .attach() to embed the XML
53
+ pdfDoc.attach(xmlBuffer, filename, {
54
+ mimeType: 'text/xml',
55
+ description: description,
56
+ creationDate: new Date(),
57
+ modificationDate: new Date(),
58
+ afRelationship: AFRelationship.Alternative,
59
+ });
60
+ }
61
+ catch (error) {
62
+ return this.createErrorResult(PDFEmbedError.EMBED_ERROR, `Failed to embed XML: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : undefined);
63
+ }
64
+ // Save the modified PDF
65
+ let modifiedPdfBytes;
66
+ try {
67
+ modifiedPdfBytes = await pdfDoc.save({
68
+ addDefaultPage: false, // Don't add a page if the document is empty
69
+ useObjectStreams: false, // Better compatibility with older PDF readers
70
+ updateFieldAppearances: false // Don't update form fields
71
+ });
72
+ }
73
+ catch (error) {
74
+ return this.createErrorResult(PDFEmbedError.SAVE_ERROR, `Failed to save modified PDF: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : undefined);
75
+ }
76
+ return {
77
+ success: true,
78
+ data: modifiedPdfBytes
79
+ };
80
+ }
81
+ catch (error) {
82
+ // Catch any uncaught errors
83
+ return this.createErrorResult(PDFEmbedError.EMBED_ERROR, `Unexpected error during XML embedding: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : undefined);
84
+ }
85
+ }
86
+ /**
87
+ * Creates an IPdf object with embedded XML
88
+ * @param pdfBuffer PDF buffer
89
+ * @param xmlContent XML content to embed
90
+ * @param filename Filename for the embedded XML
91
+ * @param description Description for the embedded XML
92
+ * @param pdfName Name for the PDF
93
+ * @param pdfId ID for the PDF
94
+ * @returns Result with either IPdf object or error information
95
+ */
96
+ async createPdfWithXml(pdfBuffer, xmlContent, filename = 'invoice.xml', description = 'XML Invoice', pdfName = 'invoice.pdf', pdfId = `invoice-${Date.now()}`) {
97
+ // Embed XML into PDF
98
+ const embedResult = await this.embedXml(pdfBuffer, xmlContent, filename, description);
99
+ // If embedding failed, return the error
100
+ if (!embedResult.success || !embedResult.data) {
101
+ return embedResult;
102
+ }
103
+ // Create IPdf object
104
+ const pdfObject = {
105
+ name: pdfName,
106
+ id: pdfId,
107
+ metadata: {
108
+ textExtraction: '',
109
+ format: this.detectPdfFormat(xmlContent),
110
+ embeddedXml: {
111
+ filename: filename,
112
+ description: description
113
+ }
114
+ },
115
+ buffer: embedResult.data
116
+ };
117
+ return {
118
+ success: true,
119
+ pdf: pdfObject
120
+ };
121
+ }
122
+ /**
123
+ * Ensures the filename is normalized according to PDF/A requirements
124
+ * @param filename Filename to normalize
125
+ * @returns Normalized filename
126
+ */
127
+ normalizeFilename(filename) {
128
+ // Convert to lowercase
129
+ let normalized = filename.toLowerCase();
130
+ // Ensure it has .xml extension
131
+ if (!normalized.endsWith('.xml')) {
132
+ normalized = normalized.replace(/\.[^/.]+$/, '') + '.xml';
133
+ }
134
+ // Replace invalid characters
135
+ normalized = normalized.replace(/[^a-z0-9_.-]/g, '_');
136
+ return normalized;
137
+ }
138
+ /**
139
+ * Tries to detect the format of the XML content
140
+ * @param xmlContent XML content
141
+ * @returns Format string or undefined
142
+ */
143
+ detectPdfFormat(xmlContent) {
144
+ if (xmlContent.includes('factur-x.eu') || xmlContent.includes('factur-x.xml')) {
145
+ return 'factur-x';
146
+ }
147
+ else if (xmlContent.includes('zugferd') || xmlContent.includes('ZUGFeRD')) {
148
+ return 'zugferd';
149
+ }
150
+ else if (xmlContent.includes('xrechnung')) {
151
+ return 'xrechnung';
152
+ }
153
+ else if (xmlContent.includes('<Invoice') || xmlContent.includes('<CreditNote')) {
154
+ return 'ubl';
155
+ }
156
+ else if (xmlContent.includes('FatturaElettronica')) {
157
+ return 'fatturapa';
158
+ }
159
+ return undefined;
160
+ }
161
+ /**
162
+ * Creates an error result object
163
+ * @param type Error type
164
+ * @param message Error message
165
+ * @param originalError Original error object
166
+ * @returns Error result
167
+ */
168
+ createErrorResult(type, message, originalError) {
169
+ console.error(`PDF Embedder Error (${type}): ${message}`);
170
+ if (originalError) {
171
+ console.error(originalError);
172
+ }
173
+ return {
174
+ success: false,
175
+ error: {
176
+ type,
177
+ message,
178
+ originalError
179
+ }
180
+ };
181
+ }
182
+ }
183
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGRmLmVtYmVkZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvZm9ybWF0cy9wZGYvcGRmLmVtYmVkZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFHL0Q7O0dBRUc7QUFDSCxNQUFNLENBQU4sSUFBWSxhQUtYO0FBTEQsV0FBWSxhQUFhO0lBQ3ZCLGtEQUFpQyxDQUFBO0lBQ2pDLHFEQUFvQyxDQUFBO0lBQ3BDLGlEQUFnQyxDQUFBO0lBQ2hDLDJEQUEwQyxDQUFBO0FBQzVDLENBQUMsRUFMVyxhQUFhLEtBQWIsYUFBYSxRQUt4QjtBQWdCRDs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sV0FBVztJQUN0Qjs7Ozs7OztPQU9HO0lBQ0ksS0FBSyxDQUFDLFFBQVEsQ0FDbkIsU0FBOEIsRUFDOUIsVUFBa0IsRUFDbEIsV0FBbUIsYUFBYSxFQUNoQyxjQUFzQixhQUFhO1FBRW5DLElBQUksQ0FBQztZQUNILGtCQUFrQjtZQUNsQixJQUFJLENBQUMsU0FBUyxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ3pDLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsQ0FBQyxhQUFhLEVBQUUsa0NBQWtDLENBQUMsQ0FBQztZQUNqRyxDQUFDO1lBRUQsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUNoQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLENBQUMsYUFBYSxFQUFFLG1DQUFtQyxDQUFDLENBQUM7WUFDbEcsQ0FBQztZQUVELDhCQUE4QjtZQUM5QixNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1lBRTFGLGVBQWU7WUFDZixJ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
@@ -0,0 +1,49 @@
1
+ import { InvoiceFormat } from '../../interfaces/common.js';
2
+ /**
3
+ * Error types for PDF extraction operations
4
+ */
5
+ export declare enum PDFExtractError {
6
+ EXTRACT_ERROR = "XML extraction failed",
7
+ INVALID_INPUT = "Invalid input parameters",
8
+ NO_XML_FOUND = "No XML found in PDF"
9
+ }
10
+ /**
11
+ * Result of a PDF extraction operation
12
+ */
13
+ export interface PDFExtractResult {
14
+ success: boolean;
15
+ xml?: string;
16
+ format?: InvoiceFormat;
17
+ extractorUsed?: string;
18
+ error?: {
19
+ type: PDFExtractError;
20
+ message: string;
21
+ originalError?: Error;
22
+ };
23
+ }
24
+ /**
25
+ * Main PDF extractor class that orchestrates the extraction process
26
+ * Uses multiple specialized extractors in sequence to maximize success rate
27
+ */
28
+ export declare class PDFExtractor {
29
+ private extractors;
30
+ /**
31
+ * Constructor initializes the chain of extractors
32
+ */
33
+ constructor();
34
+ /**
35
+ * Extract XML from a PDF buffer
36
+ * Tries multiple extraction methods in sequence
37
+ * @param pdfBuffer PDF buffer
38
+ * @returns Result with either the extracted XML or error information
39
+ */
40
+ extractXml(pdfBuffer: Uint8Array | Buffer): Promise<PDFExtractResult>;
41
+ /**
42
+ * Create a PDF extract result with error information
43
+ * @param type Error type
44
+ * @param message Error message
45
+ * @param originalError Original error object
46
+ * @returns Error result
47
+ */
48
+ private createErrorResult;
49
+ }
@@ -0,0 +1,98 @@
1
+ import { BaseXMLExtractor, StandardXMLExtractor, AssociatedFilesExtractor, TextXMLExtractor } from './extractors/index.js';
2
+ import { FormatDetector } from '../utils/format.detector.js';
3
+ import { InvoiceFormat } from '../../interfaces/common.js';
4
+ /**
5
+ * Error types for PDF extraction operations
6
+ */
7
+ export var PDFExtractError;
8
+ (function (PDFExtractError) {
9
+ PDFExtractError["EXTRACT_ERROR"] = "XML extraction failed";
10
+ PDFExtractError["INVALID_INPUT"] = "Invalid input parameters";
11
+ PDFExtractError["NO_XML_FOUND"] = "No XML found in PDF";
12
+ })(PDFExtractError || (PDFExtractError = {}));
13
+ /**
14
+ * Main PDF extractor class that orchestrates the extraction process
15
+ * Uses multiple specialized extractors in sequence to maximize success rate
16
+ */
17
+ export class PDFExtractor {
18
+ /**
19
+ * Constructor initializes the chain of extractors
20
+ */
21
+ constructor() {
22
+ this.extractors = [];
23
+ // Add extractors in order of preference/likelihood of success
24
+ this.extractors.push(new StandardXMLExtractor(), // Standard PDF/A-3 embedded files
25
+ new AssociatedFilesExtractor(), // Associated files (ZUGFeRD v1, some Factur-X)
26
+ new TextXMLExtractor() // Text-based extraction (fallback)
27
+ );
28
+ }
29
+ /**
30
+ * Extract XML from a PDF buffer
31
+ * Tries multiple extraction methods in sequence
32
+ * @param pdfBuffer PDF buffer
33
+ * @returns Result with either the extracted XML or error information
34
+ */
35
+ async extractXml(pdfBuffer) {
36
+ try {
37
+ console.log('Starting XML extraction from PDF...');
38
+ // Validate input
39
+ if (!pdfBuffer || pdfBuffer.length === 0) {
40
+ return this.createErrorResult(PDFExtractError.INVALID_INPUT, 'PDF buffer is empty or undefined');
41
+ }
42
+ // Ensure buffer is Uint8Array
43
+ const pdfBufferArray = Buffer.isBuffer(pdfBuffer) ? new Uint8Array(pdfBuffer) : pdfBuffer;
44
+ // Try each extractor in sequence
45
+ for (const extractor of this.extractors) {
46
+ const extractorName = extractor.constructor.name;
47
+ console.log(`Trying extraction with ${extractorName}...`);
48
+ try {
49
+ const xml = await extractor.extractXml(pdfBufferArray);
50
+ if (xml) {
51
+ console.log(`Successfully extracted XML using ${extractorName}`);
52
+ // Detect format of the extracted XML
53
+ const format = FormatDetector.detectFormat(xml);
54
+ return {
55
+ success: true,
56
+ xml,
57
+ format,
58
+ extractorUsed: extractorName
59
+ };
60
+ }
61
+ console.log(`Extraction with ${extractorName} failed, trying next method...`);
62
+ }
63
+ catch (error) {
64
+ // Log error but continue with next extractor
65
+ console.warn(`Error using ${extractorName}: ${error instanceof Error ? error.message : String(error)}`);
66
+ }
67
+ }
68
+ // If all extractors fail, return a no XML found error
69
+ return this.createErrorResult(PDFExtractError.NO_XML_FOUND, 'All extraction methods failed, no valid XML found in PDF');
70
+ }
71
+ catch (error) {
72
+ // Handle any unexpected errors
73
+ return this.createErrorResult(PDFExtractError.EXTRACT_ERROR, `Unexpected error during XML extraction: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : undefined);
74
+ }
75
+ }
76
+ /**
77
+ * Create a PDF extract result with error information
78
+ * @param type Error type
79
+ * @param message Error message
80
+ * @param originalError Original error object
81
+ * @returns Error result
82
+ */
83
+ createErrorResult(type, message, originalError) {
84
+ console.error(`PDF Extractor Error (${type}): ${message}`);
85
+ if (originalError) {
86
+ console.error(originalError);
87
+ }
88
+ return {
89
+ success: false,
90
+ error: {
91
+ type,
92
+ message,
93
+ originalError
94
+ }
95
+ };
96
+ }
97
+ }
98
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGRmLmV4dHJhY3Rvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL2Zvcm1hdHMvcGRmL3BkZi5leHRyYWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLGdCQUFnQixFQUNoQixvQkFBb0IsRUFDcEIsd0JBQXdCLEVBQ3hCLGdCQUFnQixFQUNqQixNQUFNLHVCQUF1QixDQUFDO0FBQy9CLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFM0Q7O0dBRUc7QUFDSCxNQUFNLENBQU4sSUFBWSxlQUlYO0FBSkQsV0FBWSxlQUFlO0lBQ3pCLDBEQUF1QyxDQUFBO0lBQ3ZDLDZEQUEwQyxDQUFBO0lBQzFDLHVEQUFvQyxDQUFBO0FBQ3RDLENBQUMsRUFKVyxlQUFlLEtBQWYsZUFBZSxRQUkxQjtBQWlCRDs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sWUFBWTtJQUd2Qjs7T0FFRztJQUNIO1FBTFEsZUFBVSxHQUF1QixFQUFFLENBQUM7UUFNMUMsOERBQThEO1FBQzlELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUNsQixJQUFJLG9CQUFvQixFQUFFLEVBQU8sa0NBQWtDO1FBQ25FLElBQUksd0JBQXdCLEVBQUUsRUFBRywrQ0FBK0M7UUFDaEYsSUFBSSxnQkFBZ0IsRUFBRSxDQUFXLG1DQUFtQztTQUNyRSxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksS0FBSyxDQUFDLFVBQVUsQ0FBQyxTQUE4QjtRQUNwRCxJQUFJLENBQUM7WUFDSCxPQUFPLENBQUMsR0FBRyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7WUFFbkQsaUJBQWlCO1lBQ2pCLElBQUksQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDekMsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENB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
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Class for extracting XML from PDF files with robust error handling
3
+ */
4
+ export declare class RobustPDFExtractor {
5
+ /**
6
+ * Extracts XML from a PDF buffer
7
+ * @param pdfBuffer PDF buffer
8
+ * @returns XML content or null if not found
9
+ */
10
+ extractXml(pdfBuffer: Uint8Array | Buffer): Promise<string | null>;
11
+ /**
12
+ * Standard extraction method using PDF-lib
13
+ * @param pdfBuffer PDF buffer
14
+ * @returns XML content or null if not found
15
+ */
16
+ private standardExtraction;
17
+ /**
18
+ * Alternative extraction method using a more robust approach
19
+ * @param pdfBuffer PDF buffer
20
+ * @returns XML content or null if not found
21
+ */
22
+ private alternativeExtraction;
23
+ /**
24
+ * Extracts XML from a string
25
+ * @param pdfString PDF string
26
+ * @returns XML content or null if not found
27
+ */
28
+ private extractXmlFromString;
29
+ /**
30
+ * Checks if an XML string is valid
31
+ * @param xmlString XML string to check
32
+ * @returns True if the XML is valid
33
+ */
34
+ private isValidXml;
35
+ /**
36
+ * Extracts a sample XML file for testing
37
+ * @returns Sample XML content
38
+ */
39
+ private extractSampleXml;
40
+ }