@fin.cx/einvoice 5.2.0 → 5.2.1

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 (43) hide show
  1. package/.smartconfig.json +29 -11
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/einvoice.d.ts +2 -2
  4. package/dist_ts/einvoice.js +11 -9
  5. package/dist_ts/formats/cii/facturx/facturx.encoder.js +25 -16
  6. package/dist_ts/formats/pdf/extractors/associated.extractor.js +3 -2
  7. package/dist_ts/formats/pdf/extractors/base.extractor.d.ts +1 -1
  8. package/dist_ts/formats/pdf/extractors/base.extractor.js +2 -2
  9. package/dist_ts/formats/pdf/extractors/standard.extractor.js +3 -2
  10. package/dist_ts/formats/pdf/pdf.embedder.js +3 -2
  11. package/dist_ts/formats/pdf/pdf.extractor.d.ts +2 -1
  12. package/dist_ts/formats/pdf/pdf.extractor.js +20 -10
  13. package/dist_ts/formats/validation/schematron.downloader.d.ts +0 -1
  14. package/dist_ts/formats/validation/schematron.downloader.js +1 -3
  15. package/dist_ts/formats/validation/schematron.integration.js +5 -2
  16. package/dist_ts/formats/validation/schematron.validator.d.ts +9 -11
  17. package/dist_ts/formats/validation/schematron.validator.js +61 -67
  18. package/dist_ts/formats/validation/schematron.worker.d.ts +7 -6
  19. package/dist_ts/formats/validation/schematron.worker.js +44 -39
  20. package/dist_ts/plugins.d.ts +1 -3
  21. package/dist_ts/plugins.js +1 -9
  22. package/dist_ts/vendor/pdflib.d.ts +2 -0
  23. package/dist_ts/vendor/pdflib.js +9 -0
  24. package/dist_ts/vendor/saxonjs.d.ts +4 -3
  25. package/dist_ts/vendor/saxonjs.js +9 -3
  26. package/package.json +22 -18
  27. package/readme.md +1 -1
  28. package/ts/00_commitinfo_data.ts +1 -1
  29. package/ts/einvoice.ts +12 -11
  30. package/ts/formats/cii/facturx/facturx.encoder.ts +25 -15
  31. package/ts/formats/pdf/extractors/associated.extractor.ts +2 -1
  32. package/ts/formats/pdf/extractors/base.extractor.ts +3 -2
  33. package/ts/formats/pdf/extractors/standard.extractor.ts +2 -1
  34. package/ts/formats/pdf/pdf.embedder.ts +6 -3
  35. package/ts/formats/pdf/pdf.extractor.ts +24 -16
  36. package/ts/formats/validation/schematron.downloader.ts +0 -2
  37. package/ts/formats/validation/schematron.integration.ts +4 -1
  38. package/ts/formats/validation/schematron.validator.ts +72 -73
  39. package/ts/formats/validation/schematron.worker.ts +59 -41
  40. package/ts/plugins.ts +0 -26
  41. package/ts/readme.md +21 -0
  42. package/ts/vendor/pdflib.ts +12 -0
  43. package/ts/vendor/saxonjs.ts +13 -5
@@ -1,5 +1,4 @@
1
1
  import { Worker } from 'worker_threads';
2
- import * as path from 'path';
3
2
  /**
4
3
  * Worker pool for Schematron validation
5
4
  * Provides non-blocking validation in worker threads
@@ -9,52 +8,76 @@ export class SchematronWorkerPool {
9
8
  availableWorkers = [];
10
9
  taskQueue = [];
11
10
  maxWorkers;
12
- schematronRules = '';
11
+ stylesheetFileName;
12
+ stylesheetInternal;
13
13
  constructor(maxWorkers = 4) {
14
14
  this.maxWorkers = maxWorkers;
15
15
  }
16
16
  /**
17
17
  * Initialize worker pool
18
18
  */
19
- async initialize(schematronRules) {
20
- this.schematronRules = schematronRules;
19
+ async initialize(stylesheetSource, options = {}) {
20
+ this.loadStylesheet(stylesheetSource, options);
21
21
  // Create workers
22
22
  for (let i = 0; i < this.maxWorkers; i++) {
23
23
  await this.createWorker();
24
24
  }
25
25
  }
26
+ loadStylesheet(stylesheetSource, options) {
27
+ const source = stylesheetSource.trim();
28
+ const isFilePath = options.isFilePath ?? /\.sef\.json$/i.test(stylesheetSource);
29
+ this.stylesheetFileName = undefined;
30
+ this.stylesheetInternal = undefined;
31
+ if (isFilePath) {
32
+ if (!/\.sef\.json$/i.test(stylesheetSource)) {
33
+ throw new Error('Schematron worker validation requires a precompiled Saxon-JS SEF JSON stylesheet file.');
34
+ }
35
+ this.stylesheetFileName = stylesheetSource;
36
+ return;
37
+ }
38
+ if (!source.startsWith('{')) {
39
+ throw new Error('Schematron worker validation requires a precompiled Saxon-JS SEF JSON stylesheet. Raw .sch files are not executed.');
40
+ }
41
+ this.stylesheetInternal = JSON.parse(source);
42
+ }
26
43
  /**
27
44
  * Create a new worker
28
45
  */
29
46
  async createWorker() {
30
- const workerPath = path.join(import.meta.url, 'schematron.worker.impl.js');
31
47
  const worker = new Worker(`
32
48
  const { parentPort } = require('worker_threads');
33
49
  const SaxonJS = require('saxon-js');
34
50
 
35
- let compiledStylesheet = null;
51
+ let stylesheetFileName = null;
52
+ let stylesheetInternal = null;
36
53
 
37
54
  parentPort.on('message', async (msg) => {
38
55
  try {
39
56
  if (msg.type === 'init') {
40
- // Compile Schematron to XSLT
41
- compiledStylesheet = await SaxonJS.compile({
42
- stylesheetText: msg.xslt,
43
- warnings: 'silent'
44
- });
57
+ stylesheetFileName = msg.stylesheetFileName || null;
58
+ stylesheetInternal = msg.stylesheetInternal || null;
59
+ if (!stylesheetFileName && !stylesheetInternal) {
60
+ throw new Error('Worker not initialized with a SEF stylesheet');
61
+ }
45
62
  parentPort.postMessage({ type: 'ready' });
46
63
  } else if (msg.type === 'validate') {
47
- if (!compiledStylesheet) {
64
+ if (!stylesheetFileName && !stylesheetInternal) {
48
65
  throw new Error('Worker not initialized');
49
66
  }
50
-
51
- // Transform XML with compiled Schematron
52
- const result = await SaxonJS.transform({
53
- stylesheetInternal: compiledStylesheet,
67
+
68
+ const transformOptions = {
54
69
  sourceText: msg.xmlContent,
55
70
  destination: 'serialized',
56
71
  stylesheetParams: msg.options.parameters || {}
57
- });
72
+ };
73
+
74
+ if (stylesheetFileName) {
75
+ transformOptions.stylesheetFileName = stylesheetFileName;
76
+ } else {
77
+ transformOptions.stylesheetInternal = stylesheetInternal;
78
+ }
79
+
80
+ const result = await SaxonJS.transform(transformOptions, 'async');
58
81
 
59
82
  parentPort.postMessage({
60
83
  type: 'result',
@@ -69,7 +92,7 @@ export class SchematronWorkerPool {
69
92
  }
70
93
  });
71
94
  `, { eval: true });
72
- // Initialize worker with Schematron rules
95
+ // Initialize worker with a precompiled SEF stylesheet.
73
96
  await new Promise((resolve, reject) => {
74
97
  worker.once('message', (msg) => {
75
98
  if (msg.type === 'ready') {
@@ -82,7 +105,8 @@ export class SchematronWorkerPool {
82
105
  // Send initialization message
83
106
  worker.postMessage({
84
107
  type: 'init',
85
- xslt: this.generateXSLTFromSchematron(this.schematronRules)
108
+ stylesheetFileName: this.stylesheetFileName,
109
+ stylesheetInternal: this.stylesheetInternal
86
110
  });
87
111
  });
88
112
  this.workers.push(worker);
@@ -144,25 +168,6 @@ export class SchematronWorkerPool {
144
168
  // Simplified for brevity
145
169
  return results;
146
170
  }
147
- /**
148
- * Generate XSLT from Schematron (simplified)
149
- */
150
- generateXSLTFromSchematron(schematron) {
151
- // Simplified - would use ISO Schematron skeleton in production
152
- return `<?xml version="1.0" encoding="UTF-8"?>
153
- <xsl:stylesheet version="3.0"
154
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
155
- xmlns:svrl="http://purl.oclc.org/dsdl/svrl">
156
-
157
- <xsl:output method="xml" indent="yes"/>
158
-
159
- <xsl:template match="/">
160
- <svrl:schematron-output>
161
- <svrl:active-pattern document="{base-uri(/)}"/>
162
- </svrl:schematron-output>
163
- </xsl:template>
164
- </xsl:stylesheet>`;
165
- }
166
171
  /**
167
172
  * Terminate all workers
168
173
  */
@@ -183,4 +188,4 @@ export class SchematronWorkerPool {
183
188
  };
184
189
  }
185
190
  }
186
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hdHJvbi53b3JrZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9mb3JtYXRzL3ZhbGlkYXRpb24vc2NoZW1hdHJvbi53b3JrZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBSTdCOzs7R0FHRztBQUNILE1BQU0sT0FBTyxvQkFBb0I7SUFDdkIsT0FBTyxHQUFhLEVBQUUsQ0FBQztJQUN2QixnQkFBZ0IsR0FBYSxFQUFFLENBQUM7SUFDaEMsU0FBUyxHQUtaLEVBQUUsQ0FBQztJQUNBLFVBQVUsQ0FBUztJQUNuQixlQUFlLEdBQVcsRUFBRSxDQUFDO0lBRXJDLFlBQVksYUFBcUIsQ0FBQztRQUNoQyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztJQUMvQixDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsVUFBVSxDQUFDLGVBQXVCO1FBQzdDLElBQUksQ0FBQyxlQUFlLEdBQUcsZUFBZSxDQUFDO1FBRXZDLGlCQUFpQjtRQUNqQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3pDLE1BQU0sSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzVCLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxLQUFLLENBQUMsWUFBWTtRQUN4QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLDJCQUEyQixDQUFDLENBQUM7UUFFM0UsTUFBTSxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7S0F3Q3pCLEVBQUUsRUFBRSxJQUFJ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
191
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hdHJvbi53b3JrZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9mb3JtYXRzL3ZhbGlkYXRpb24vc2NoZW1hdHJvbi53b3JrZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBUXhDOzs7R0FHRztBQUNILE1BQU0sT0FBTyxvQkFBb0I7SUFDdkIsT0FBTyxHQUFhLEVBQUUsQ0FBQztJQUN2QixnQkFBZ0IsR0FBYSxFQUFFLENBQUM7SUFDaEMsU0FBUyxHQUtaLEVBQUUsQ0FBQztJQUNBLFVBQVUsQ0FBUztJQUNuQixrQkFBa0IsQ0FBVTtJQUM1QixrQkFBa0IsQ0FBVztJQUVyQyxZQUFZLGFBQXFCLENBQUM7UUFDaEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7SUFDL0IsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLFVBQVUsQ0FDckIsZ0JBQXdCLEVBQ3hCLFVBQWtELEVBQUU7UUFFcEQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUUvQyxpQkFBaUI7UUFDakIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUN6QyxNQUFNLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUM1QixDQUFDO0lBQ0gsQ0FBQztJQUVPLGNBQWMsQ0FDcEIsZ0JBQXdCLEVBQ3hCLE9BQStDO1FBRS9DLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRWhGLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxTQUFTLENBQUM7UUFDcEMs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
@@ -6,10 +6,8 @@
6
6
  import * as fs from 'fs/promises';
7
7
  import * as path from 'path';
8
8
  import * as crypto from 'crypto';
9
- import { PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString, AFRelationship } from 'pdf-lib';
10
9
  import { DOMParser, XMLSerializer, xmldom } from './vendor/xmldom.js';
11
10
  import * as xpath from 'xpath';
12
- import { SaxonJS } from './vendor/saxonjs.js';
13
11
  import { pako } from './vendor/pako.js';
14
12
  import { business, finance, general } from '@tsclass/tsclass';
15
- export { fs, path, crypto, PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString, AFRelationship, DOMParser, XMLSerializer, xmldom, xpath, SaxonJS, pako, business, finance, general };
13
+ export { fs, path, crypto, DOMParser, XMLSerializer, xmldom, xpath, pako, business, finance, general };
@@ -7,13 +7,9 @@
7
7
  import * as fs from 'fs/promises';
8
8
  import * as path from 'path';
9
9
  import * as crypto from 'crypto';
10
- // PDF-related imports
11
- import { PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString, AFRelationship } from 'pdf-lib';
12
10
  // XML-related imports
13
11
  import { DOMParser, XMLSerializer, xmldom } from './vendor/xmldom.js';
14
12
  import * as xpath from 'xpath';
15
- // XSLT/Schematron imports
16
- import { SaxonJS } from './vendor/saxonjs.js';
17
13
  // Compression-related imports
18
14
  import { pako } from './vendor/pako.js';
19
15
  // Business model imports
@@ -22,14 +18,10 @@ import { business, finance, general } from '@tsclass/tsclass';
22
18
  export {
23
19
  // Node.js built-in modules
24
20
  fs, path, crypto,
25
- // PDF-lib exports
26
- PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString, AFRelationship,
27
21
  // XML-related exports
28
22
  DOMParser, XMLSerializer, xmldom, xpath,
29
- // XSLT/Schematron exports
30
- SaxonJS,
31
23
  // Compression-related exports
32
24
  pako,
33
25
  // Business model exports
34
26
  business, finance, general };
35
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILDJCQUEyQjtBQUMzQixPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUVqQyxzQkFBc0I7QUFDdEIsT0FBTyxFQUNMLFdBQVcsRUFDWCxPQUFPLEVBQ1AsT0FBTyxFQUNQLFlBQVksRUFDWixRQUFRLEVBQ1IsU0FBUyxFQUNULGNBQWMsRUFDZixNQUFNLFNBQVMsQ0FBQztBQUVqQixzQkFBc0I7QUFDdEIsT0FBTyxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDdEUsT0FBTyxLQUFLLEtBQUssTUFBTSxPQUFPLENBQUM7QUFFL0IsMEJBQTBCO0FBQzFCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUU5Qyw4QkFBOEI7QUFDOUIsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXhDLHlCQUF5QjtBQUN6QixPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUU5RCx3QkFBd0I7QUFDeEIsT0FBTztBQUNMLDJCQUEyQjtBQUMzQixFQUFFLEVBQ0YsSUFBSSxFQUNKLE1BQU07QUFFTixrQkFBa0I7QUFDbEIsV0FBVyxFQUNYLE9BQU8sRUFDUCxPQUFPLEVBQ1AsWUFBWSxFQUNaLFFBQVEsRUFDUixTQUFTLEVBQ1QsY0FBYztBQUVkLHNCQUFzQjtBQUN0QixTQUFTLEVBQ1QsYUFBYSxFQUNiLE1BQU0sRUFDTixLQUFLO0FBRUwsMEJBQTBCO0FBQzFCLE9BQU87QUFFUCw4QkFBOEI7QUFDOUIsSUFBSTtBQUVKLHlCQUF5QjtBQUN6QixRQUFRLEVBQ1IsT0FBTyxFQUNQLE9BQU8sRUFDUixDQUFDIn0=
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILDJCQUEyQjtBQUMzQixPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUVqQyxzQkFBc0I7QUFDdEIsT0FBTyxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDdEUsT0FBTyxLQUFLLEtBQUssTUFBTSxPQUFPLENBQUM7QUFFL0IsOEJBQThCO0FBQzlCLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUV4Qyx5QkFBeUI7QUFDekIsT0FBTyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFOUQsd0JBQXdCO0FBQ3hCLE9BQU87QUFDTCwyQkFBMkI7QUFDM0IsRUFBRSxFQUNGLElBQUksRUFDSixNQUFNO0FBRU4sc0JBQXNCO0FBQ3RCLFNBQVMsRUFDVCxhQUFhLEVBQ2IsTUFBTSxFQUNOLEtBQUs7QUFFTCw4QkFBOEI7QUFDOUIsSUFBSTtBQUVKLHlCQUF5QjtBQUN6QixRQUFRLEVBQ1IsT0FBTyxFQUNQLE9BQU8sRUFDUixDQUFDIn0=
@@ -0,0 +1,2 @@
1
+ export type TPdfLibModule = typeof import('pdf-lib');
2
+ export declare const loadPdfLib: () => Promise<TPdfLibModule>;
@@ -0,0 +1,9 @@
1
+ let cachedPdfLib;
2
+ // Use pdf-lib's bundled UMD build; the package entry requires JSON font assets,
3
+ // which some TS runners corrupt with require hooks.
4
+ const nativeImport = Function('specifier', 'return import(specifier)');
5
+ export const loadPdfLib = async () => {
6
+ cachedPdfLib ||= nativeImport('pdf-lib/dist/pdf-lib.js');
7
+ return cachedPdfLib;
8
+ };
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGRmbGliLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvdmVuZG9yL3BkZmxpYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxJQUFJLFlBQWdELENBQUM7QUFFckQsZ0ZBQWdGO0FBQ2hGLG9EQUFvRDtBQUNwRCxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsV0FBVyxFQUFFLDBCQUEwQixDQUFrRCxDQUFDO0FBRXhILE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRyxLQUFLLElBQTRCLEVBQUU7SUFDM0QsWUFBWSxLQUFLLFlBQVksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQ3pELE9BQU8sWUFBWSxDQUFDO0FBQ3RCLENBQUMsQ0FBQyJ9
@@ -5,6 +5,7 @@ export interface ISaxonJSCompileOptions {
5
5
  }
6
6
  export interface ISaxonJSTransformOptions {
7
7
  stylesheetInternal?: unknown;
8
+ stylesheetFileName?: string;
8
9
  sourceText: string;
9
10
  destination?: string;
10
11
  stylesheetParams?: Record<string, unknown>;
@@ -15,8 +16,8 @@ export interface ISaxonJSTransformResult {
15
16
  [key: string]: unknown;
16
17
  }
17
18
  export interface ISaxonJSModule {
18
- compile(options: ISaxonJSCompileOptions): Promise<unknown>;
19
- transform(options: ISaxonJSTransformOptions): Promise<ISaxonJSTransformResult>;
19
+ compile?: (options: ISaxonJSCompileOptions) => Promise<unknown>;
20
+ transform(options: ISaxonJSTransformOptions, executionMode?: 'async' | 'sync'): Promise<ISaxonJSTransformResult> | ISaxonJSTransformResult;
20
21
  [key: string]: unknown;
21
22
  }
22
- export declare const SaxonJS: ISaxonJSModule;
23
+ export declare const loadSaxonJS: () => Promise<ISaxonJSModule>;
@@ -1,3 +1,9 @@
1
- import * as saxonJSRuntime from 'saxon-js';
2
- export const SaxonJS = saxonJSRuntime;
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2F4b25qcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3ZlbmRvci9zYXhvbmpzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxjQUFjLE1BQU0sVUFBVSxDQUFDO0FBMkIzQyxNQUFNLENBQUMsTUFBTSxPQUFPLEdBQW1CLGNBQTJDLENBQUMifQ==
1
+ let cachedSaxonJS;
2
+ export const loadSaxonJS = async () => {
3
+ cachedSaxonJS ||= import('saxon-js').then((saxonJSRuntime) => {
4
+ const runtime = saxonJSRuntime.default ?? saxonJSRuntime;
5
+ return runtime;
6
+ });
7
+ return cachedSaxonJS;
8
+ };
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2F4b25qcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3ZlbmRvci9zYXhvbmpzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQTBCQSxJQUFJLGFBQWtELENBQUM7QUFFdkQsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLEtBQUssSUFBNkIsRUFBRTtJQUM3RCxhQUFhLEtBQUssTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLGNBQWMsRUFBRSxFQUFFO1FBQzNELE1BQU0sT0FBTyxHQUFJLGNBQXNCLENBQUMsT0FBTyxJQUFJLGNBQWMsQ0FBQztRQUNsRSxPQUFPLE9BQXlCLENBQUM7SUFDbkMsQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPLGFBQWEsQ0FBQztBQUN2QixDQUFDLENBQUMifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fin.cx/einvoice",
3
- "version": "5.2.0",
3
+ "version": "5.2.1",
4
4
  "private": false,
5
5
  "description": "A TypeScript module for creating, manipulating, and embedding XML data within PDF files specifically tailored for electronic invoice (einvoice) packages.",
6
6
  "main": "dist_ts/index.js",
@@ -8,22 +8,12 @@
8
8
  "type": "module",
9
9
  "author": "Task Venture Capital GmbH",
10
10
  "license": "MIT",
11
- "scripts": {
12
- "test": "(tstest test/ --verbose --logfile --timeout 60)",
13
- "build": "(tsbuild tsfolders --allowimplicitany)",
14
- "typecheck:published": "pnpm exec tsc -p test/strict-consumer/tsconfig.json",
15
- "buildDocs": "(tsdoc)",
16
- "postinstall": "node dist_ts_install/index.js 2>/dev/null || true",
17
- "download-schematron": "tsx ts_install/download-schematron.ts",
18
- "download-test-samples": "tsx ts_install/download-test-samples.ts",
19
- "test:conformance": "tstest test/test.conformance-harness.ts"
20
- },
21
11
  "devDependencies": {
22
- "@git.zone/tsbuild": "^4.4.0",
23
- "@git.zone/tsbundle": "^2.10.0",
24
- "@git.zone/tsrun": "^2.0.2",
25
- "@git.zone/tstest": "^3.6.3",
26
- "@types/node": "^25.6.0"
12
+ "@git.zone/tsbuild": "^4.4.2",
13
+ "@git.zone/tsbundle": "^2.10.4",
14
+ "@git.zone/tsrun": "^2.0.4",
15
+ "@git.zone/tstest": "^3.6.6",
16
+ "@types/node": "^25.9.1"
27
17
  },
28
18
  "dependencies": {
29
19
  "@push.rocks/smartfile": "^13.1.2",
@@ -74,5 +64,19 @@
74
64
  "esm",
75
65
  "financial technology"
76
66
  ],
77
- "packageManager": "pnpm@10.7.0+sha512.6b865ad4b62a1d9842b61d674a393903b871d9244954f652b8842c2b553c72176b278f64c463e52d40fff8aba385c235c8c9ecf5cc7de4fd78b8bb6d49633ab6"
78
- }
67
+ "scripts": {
68
+ "test": "pnpm run test:unit",
69
+ "test:unit": "tstest test/test.einvoice.ts --verbose --logfile --timeout 60 && tstest test/test.decimal.ts --verbose --logfile --timeout 60 && tstest test/test.decimal-currency-calculator.ts --verbose --logfile --timeout 60 && tstest test/test.currency-utils.ts --verbose --logfile --timeout 60 && tstest test/test.en16931-validators.ts --verbose --logfile --timeout 60 && tstest test/test.schematron-validator.ts --verbose --logfile --timeout 60",
70
+ "test:format": "tstest test/test.format-detection.ts --verbose --logfile --timeout 60",
71
+ "test:corpus": "tstest test/suite/einvoice_corpus-validation/ --verbose --logfile --timeout 60",
72
+ "test:performance": "NODE_OPTIONS=--expose-gc tstest test/suite/einvoice_performance/ --verbose --logfile --timeout 60",
73
+ "test:all": "NODE_OPTIONS=--expose-gc tstest test/ --verbose --logfile --timeout 60",
74
+ "build": "(tsbuild tsfolders --allowimplicitany)",
75
+ "typecheck:published": "pnpm exec tsc -p test/strict-consumer/tsconfig.json",
76
+ "buildDocs": "(tsdoc)",
77
+ "postinstall": "node dist_ts_install/index.js 2>/dev/null || true",
78
+ "download-schematron": "tsrun ts_install/download-schematron.ts",
79
+ "download-test-samples": "tsrun ts_install/download-test-samples.ts",
80
+ "test:conformance": "tstest test/test.conformance-harness.ts"
81
+ }
82
+ }
package/readme.md CHANGED
@@ -290,7 +290,7 @@ const xmlForGermanB2G = await invoice.exportXml('xrechnung');
290
290
 
291
291
  ## License and Legal Information
292
292
 
293
- This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./license) file.
293
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.
294
294
 
295
295
  **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
296
296
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@fin.cx/einvoice',
6
- version: '5.2.0',
6
+ version: '5.2.1',
7
7
  description: 'A TypeScript module for creating, manipulating, and embedding XML data within PDF files specifically tailored for electronic invoice (einvoice) packages.'
8
8
  }
package/ts/einvoice.ts CHANGED
@@ -20,10 +20,6 @@ import { DecoderFactory } from './formats/factories/decoder.factory.js';
20
20
  import { EncoderFactory } from './formats/factories/encoder.factory.js';
21
21
  import { ValidatorFactory } from './formats/factories/validator.factory.js';
22
22
 
23
- // Import PDF utilities
24
- import { PDFEmbedder } from './formats/pdf/pdf.embedder.js';
25
- import { PDFExtractor } from './formats/pdf/pdf.extractor.js';
26
-
27
23
  // Import format detector
28
24
  import { FormatDetector } from './formats/utils/format.detector.js';
29
25
 
@@ -42,8 +38,8 @@ import type { IEInvoiceMetadata } from './interfaces/en16931-metadata.js';
42
38
  * Extends the TInvoice interface for seamless integration with existing systems
43
39
  */
44
40
  export class EInvoice implements TInvoice {
45
- private static sharedPdfEmbedder?: PDFEmbedder;
46
- private static sharedPdfExtractor?: PDFExtractor;
41
+ private static sharedPdfEmbedder?: import('./formats/pdf/pdf.embedder.js').PDFEmbedder;
42
+ private static sharedPdfExtractor?: import('./formats/pdf/pdf.extractor.js').PDFExtractor;
47
43
 
48
44
  /**
49
45
  * Creates an EInvoice instance from XML string
@@ -79,7 +75,8 @@ export class EInvoice implements TInvoice {
79
75
  await invoice.fromPdfFile(pdfBuffer);
80
76
  } else {
81
77
  // If given a buffer, extract XML and parse it
82
- const extractResult = await invoice.pdfExtractor.extractXml(pdfBuffer);
78
+ const pdfExtractor = await invoice.getPdfExtractor();
79
+ const extractResult = await pdfExtractor.extractXml(pdfBuffer);
83
80
  if (!extractResult.success || !extractResult.xml) {
84
81
  throw new EInvoicePDFError('No invoice XML found in PDF', 'extract');
85
82
  }
@@ -200,15 +197,17 @@ export class EInvoice implements TInvoice {
200
197
  };
201
198
 
202
199
  // PDF utilities are created lazily because most invoice workflows never touch PDF I/O.
203
- private get pdfEmbedder(): PDFEmbedder {
200
+ private async getPdfEmbedder(): Promise<import('./formats/pdf/pdf.embedder.js').PDFEmbedder> {
204
201
  if (!EInvoice.sharedPdfEmbedder) {
202
+ const { PDFEmbedder } = await import('./formats/pdf/pdf.embedder.js');
205
203
  EInvoice.sharedPdfEmbedder = new PDFEmbedder();
206
204
  }
207
205
  return EInvoice.sharedPdfEmbedder;
208
206
  }
209
207
 
210
- private get pdfExtractor(): PDFExtractor {
208
+ private async getPdfExtractor(): Promise<import('./formats/pdf/pdf.extractor.js').PDFExtractor> {
211
209
  if (!EInvoice.sharedPdfExtractor) {
210
+ const { PDFExtractor } = await import('./formats/pdf/pdf.extractor.js');
212
211
  EInvoice.sharedPdfExtractor = new PDFExtractor();
213
212
  }
214
213
  return EInvoice.sharedPdfExtractor;
@@ -350,7 +349,8 @@ export class EInvoice implements TInvoice {
350
349
  public async fromPdfFile(filePath: string): Promise<EInvoice> {
351
350
  try {
352
351
  const pdfBuffer = await plugins.fs.readFile(filePath);
353
- const extractResult = await this.pdfExtractor.extractXml(pdfBuffer);
352
+ const pdfExtractor = await this.getPdfExtractor();
353
+ const extractResult = await pdfExtractor.extractXml(pdfBuffer);
354
354
  const extractedXml = extractResult.success ? extractResult.xml : null;
355
355
 
356
356
  if (!extractedXml) {
@@ -612,7 +612,8 @@ export class EInvoice implements TInvoice {
612
612
  public async embedInPdf(pdfBuffer: Buffer, format: ExportFormat = 'facturx'): Promise<Buffer> {
613
613
  try {
614
614
  const xmlString = await this.toXmlString(format);
615
- const embedResult = await this.pdfEmbedder.embedXml(pdfBuffer, xmlString, 'invoice.xml', `${format} Invoice`);
615
+ const pdfEmbedder = await this.getPdfEmbedder();
616
+ const embedResult = await pdfEmbedder.embedXml(pdfBuffer, xmlString, 'invoice.xml', `${format} Invoice`);
616
617
  if (!embedResult.success) {
617
618
  throw new EInvoicePDFError('Failed to embed XML in PDF', 'embed', { format });
618
619
  }
@@ -2,6 +2,9 @@ import { CIIBaseEncoder } from '../cii.encoder.js';
2
2
  import type { TInvoice, TCreditNote, TDebitNote } from '../../../interfaces/common.js';
3
3
  import { FACTURX_PROFILE_IDS } from './facturx.types.js';
4
4
  import { DOMParser, XMLSerializer } from '../../../plugins.js';
5
+ import { Decimal } from '../../utils/decimal.js';
6
+ import { DecimalCurrencyCalculator } from '../../utils/currency.calculator.decimal.js';
7
+ import { getCurrencyMinorUnits } from '../../utils/currency.utils.js';
5
8
 
6
9
  /**
7
10
  * Encoder for Factur-X invoice format
@@ -329,42 +332,46 @@ export class FacturXEncoder extends CIIBaseEncoder {
329
332
  // Add totals
330
333
  const monetarySummationElement = doc.createElement('ram:SpecifiedTradeSettlementHeaderMonetarySummation');
331
334
 
332
- // Calculate totals
333
- let totalNetAmount = 0;
334
- let totalTaxAmount = 0;
335
+ // Calculate totals with decimal arithmetic to avoid floating point drift.
336
+ const calculator = new DecimalCurrencyCalculator(invoice.currency);
337
+ const minorUnits = getCurrencyMinorUnits(invoice.currency);
338
+ let totalNetAmount = Decimal.ZERO;
339
+ let totalTaxAmount = Decimal.ZERO;
335
340
 
336
341
  // Calculate from items
337
342
  if (invoice.items) {
338
343
  for (const item of invoice.items) {
339
- const itemNetAmount = item.unitNetPrice * item.unitQuantity;
340
- const itemTaxAmount = itemNetAmount * (item.vatPercentage / 100);
344
+ const itemNetAmount = calculator.calculateLineNet(item.unitQuantity, item.unitNetPrice);
345
+ const itemTaxAmount = calculator.calculateVAT(itemNetAmount, item.vatPercentage);
341
346
 
342
- totalNetAmount += itemNetAmount;
343
- totalTaxAmount += itemTaxAmount;
347
+ totalNetAmount = totalNetAmount.add(itemNetAmount);
348
+ totalTaxAmount = totalTaxAmount.add(itemTaxAmount);
344
349
  }
345
350
  }
346
351
 
347
- const totalGrossAmount = totalNetAmount + totalTaxAmount;
352
+ totalNetAmount = calculator.round(totalNetAmount);
353
+ totalTaxAmount = calculator.round(totalTaxAmount);
354
+ const totalGrossAmount = calculator.calculateGrossAmount(totalNetAmount, totalTaxAmount);
348
355
 
349
356
  // Add line total amount
350
357
  const lineTotalElement = doc.createElement('ram:LineTotalAmount');
351
- lineTotalElement.textContent = totalNetAmount.toFixed(2);
358
+ lineTotalElement.textContent = totalNetAmount.toFixed(minorUnits);
352
359
  monetarySummationElement.appendChild(lineTotalElement);
353
360
 
354
361
  // Add tax total amount
355
362
  const taxTotalElement = doc.createElement('ram:TaxTotalAmount');
356
- taxTotalElement.textContent = totalTaxAmount.toFixed(2);
363
+ taxTotalElement.textContent = totalTaxAmount.toFixed(minorUnits);
357
364
  taxTotalElement.setAttribute('currencyID', invoice.currency);
358
365
  monetarySummationElement.appendChild(taxTotalElement);
359
366
 
360
367
  // Add grand total amount
361
368
  const grandTotalElement = doc.createElement('ram:GrandTotalAmount');
362
- grandTotalElement.textContent = totalGrossAmount.toFixed(2);
369
+ grandTotalElement.textContent = totalGrossAmount.toFixed(minorUnits);
363
370
  monetarySummationElement.appendChild(grandTotalElement);
364
371
 
365
372
  // Add due payable amount
366
373
  const duePayableElement = doc.createElement('ram:DuePayableAmount');
367
- duePayableElement.textContent = totalGrossAmount.toFixed(2);
374
+ duePayableElement.textContent = totalGrossAmount.toFixed(minorUnits);
368
375
  monetarySummationElement.appendChild(duePayableElement);
369
376
 
370
377
  settlementElement.appendChild(monetarySummationElement);
@@ -377,6 +384,9 @@ export class FacturXEncoder extends CIIBaseEncoder {
377
384
  * @param invoice Invoice data
378
385
  */
379
386
  private addLineItems(doc: Document, transactionElement: Element, invoice: TInvoice): void {
387
+ const calculator = new DecimalCurrencyCalculator(invoice.currency);
388
+ const minorUnits = getCurrencyMinorUnits(invoice.currency);
389
+
380
390
  // Add each line item
381
391
  if (invoice.items) {
382
392
  for (const item of invoice.items) {
@@ -450,12 +460,12 @@ export class FacturXEncoder extends CIIBaseEncoder {
450
460
  // Add monetary summation
451
461
  const monetarySummationElement = doc.createElement('ram:SpecifiedLineTradeSettlementMonetarySummation');
452
462
 
453
- // Calculate item total
454
- const itemNetAmount = item.unitNetPrice * item.unitQuantity;
463
+ // Calculate item total with decimal arithmetic and currency rounding.
464
+ const itemNetAmount = calculator.calculateLineNet(item.unitQuantity, item.unitNetPrice);
455
465
 
456
466
  // Add line total amount
457
467
  const lineTotalElement = doc.createElement('ram:LineTotalAmount');
458
- lineTotalElement.textContent = itemNetAmount.toFixed(2);
468
+ lineTotalElement.textContent = itemNetAmount.toFixed(minorUnits);
459
469
  monetarySummationElement.appendChild(lineTotalElement);
460
470
 
461
471
  settlementElement.appendChild(monetarySummationElement);
@@ -1,5 +1,5 @@
1
- import { PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString } from '../../../plugins.js';
2
1
  import { BaseXMLExtractor } from './base.extractor.js';
2
+ import { loadPdfLib } from '../../../vendor/pdflib.js';
3
3
 
4
4
  /**
5
5
  * Associated files extractor for PDF/A-3 documents
@@ -14,6 +14,7 @@ export class AssociatedFilesExtractor extends BaseXMLExtractor {
14
14
  */
15
15
  public async extractXml(pdfBuffer: Uint8Array | Buffer): Promise<string | null> {
16
16
  try {
17
+ const { PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString } = await loadPdfLib();
17
18
  const pdfDoc = await PDFDocument.load(pdfBuffer);
18
19
 
19
20
  // Try to find associated files via the AF entry in the catalog
@@ -1,4 +1,5 @@
1
- import { PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString, pako } from '../../../plugins.js';
1
+ import type { PDFRawStream } from 'pdf-lib';
2
+ import { pako } from '../../../plugins.js';
2
3
 
3
4
  /**
4
5
  * Base class for PDF XML extractors with common functionality
@@ -352,4 +353,4 @@ export abstract class BaseXMLExtractor {
352
353
  (content.includes('<?xml') ||
353
354
  this.knownFormats.some(format => content.includes(format)));
354
355
  }
355
- }
356
+ }
@@ -1,5 +1,5 @@
1
- import { PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString } from '../../../plugins.js';
2
1
  import { BaseXMLExtractor } from './base.extractor.js';
2
+ import { loadPdfLib } from '../../../vendor/pdflib.js';
3
3
 
4
4
  /**
5
5
  * Standard PDF XML extractor that extracts XML from embedded files
@@ -13,6 +13,7 @@ export class StandardXMLExtractor extends BaseXMLExtractor {
13
13
  */
14
14
  public async extractXml(pdfBuffer: Uint8Array | Buffer): Promise<string | null> {
15
15
  try {
16
+ const { PDFDocument, PDFDict, PDFName, PDFRawStream, PDFArray, PDFString } = await loadPdfLib();
16
17
  const pdfDoc = await PDFDocument.load(pdfBuffer);
17
18
 
18
19
  // Get the document's metadata dictionary
@@ -1,5 +1,6 @@
1
- import { PDFDocument, AFRelationship } from '../../plugins.js';
1
+ import type { PDFDocument as TPdfDocument } from 'pdf-lib';
2
2
  import type { IPdf } from '../../interfaces/common.js';
3
+ import { loadPdfLib } from '../../vendor/pdflib.js';
3
4
 
4
5
  /**
5
6
  * Error types for PDF embedding operations
@@ -57,8 +58,10 @@ export class PDFEmbedder {
57
58
  // Ensure buffer is Uint8Array
58
59
  const pdfBufferArray = Buffer.isBuffer(pdfBuffer) ? new Uint8Array(pdfBuffer) : pdfBuffer;
59
60
 
61
+ const { PDFDocument, AFRelationship } = await loadPdfLib();
62
+
60
63
  // Load the PDF
61
- let pdfDoc: PDFDocument;
64
+ let pdfDoc: TPdfDocument;
62
65
  try {
63
66
  pdfDoc = await PDFDocument.load(pdfBufferArray, {
64
67
  ignoreEncryption: true, // Try to load encrypted PDFs
@@ -239,4 +242,4 @@ export class PDFEmbedder {
239
242
  }
240
243
  };
241
244
  }
242
- }
245
+ }