@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,9 +1,4 @@
1
- import {
2
- BaseXMLExtractor,
3
- StandardXMLExtractor,
4
- AssociatedFilesExtractor,
5
- TextXMLExtractor
6
- } from './extractors/index.js';
1
+ import type { BaseXMLExtractor } from './extractors/base.extractor.js';
7
2
  import { FormatDetector } from '../utils/format.detector.js';
8
3
  import { InvoiceFormat } from '../../interfaces/common.js';
9
4
 
@@ -36,18 +31,30 @@ export interface PDFExtractResult {
36
31
  * Uses multiple specialized extractors in sequence to maximize success rate
37
32
  */
38
33
  export class PDFExtractor {
39
- private extractors: BaseXMLExtractor[] = [];
34
+ private extractors?: BaseXMLExtractor[];
40
35
 
41
36
  /**
42
37
  * Constructor initializes the chain of extractors
43
38
  */
44
- constructor() {
45
- // Add extractors in order of preference/likelihood of success
46
- this.extractors.push(
47
- new StandardXMLExtractor(), // Standard PDF/A-3 embedded files
48
- new AssociatedFilesExtractor(), // Associated files (ZUGFeRD v1, some Factur-X)
49
- new TextXMLExtractor() // Text-based extraction (fallback)
50
- );
39
+ constructor() {}
40
+
41
+ private async getExtractors(): Promise<BaseXMLExtractor[]> {
42
+ if (!this.extractors) {
43
+ const [standardModule, associatedModule, textModule] = await Promise.all([
44
+ import('./extractors/standard.extractor.js'),
45
+ import('./extractors/associated.extractor.js'),
46
+ import('./extractors/text.extractor.js')
47
+ ]);
48
+
49
+ // Add extractors in order of preference/likelihood of success
50
+ this.extractors = [
51
+ new standardModule.StandardXMLExtractor(), // Standard PDF/A-3 embedded files
52
+ new associatedModule.AssociatedFilesExtractor(), // Associated files (ZUGFeRD v1, some Factur-X)
53
+ new textModule.TextXMLExtractor() // Text-based extraction (fallback)
54
+ ];
55
+ }
56
+
57
+ return this.extractors;
51
58
  }
52
59
 
53
60
  /**
@@ -69,7 +76,8 @@ export class PDFExtractor {
69
76
  const pdfBufferArray = Buffer.isBuffer(pdfBuffer) ? new Uint8Array(pdfBuffer) : pdfBuffer;
70
77
 
71
78
  // Try each extractor in sequence
72
- for (const extractor of this.extractors) {
79
+ const extractors = await this.getExtractors();
80
+ for (const extractor of extractors) {
73
81
  const extractorName = extractor.constructor.name;
74
82
  console.log(`Trying extraction with ${extractorName}...`);
75
83
 
@@ -138,4 +146,4 @@ export class PDFExtractor {
138
146
  }
139
147
  };
140
148
  }
141
- }
149
+ }
@@ -79,7 +79,6 @@ export const SCHEMATRON_SOURCES: Record<string, SchematronSource[]> = {
79
79
  */
80
80
  export class SchematronDownloader {
81
81
  private cacheDir: string;
82
- private smartfile: any;
83
82
 
84
83
  constructor(cacheDir: string = 'assets_downloaded/schematron') {
85
84
  this.cacheDir = cacheDir;
@@ -90,7 +89,6 @@ export class SchematronDownloader {
90
89
  */
91
90
  public async initialize(): Promise<void> {
92
91
  // Ensure cache directory exists
93
- this.smartfile = await import('@push.rocks/smartfile');
94
92
  await fs.mkdir(this.cacheDir, { recursive: true });
95
93
  }
96
94
 
@@ -61,10 +61,13 @@ export class IntegratedValidator {
61
61
  try {
62
62
  await fs.access(schematronPath);
63
63
  } catch {
64
- throw new Error(`Schematron file not found: ${schematronPath}. Run 'npm run download-schematron' first.`);
64
+ throw new Error(`Schematron file not found: ${schematronPath}. Run 'pnpm run download-schematron' first.`);
65
65
  }
66
66
 
67
67
  await this.schematronValidator.loadSchematron(schematronPath, true);
68
+ if (!this.schematronValidator.canValidate()) {
69
+ throw new Error(`Schematron file is not a precompiled Saxon-JS SEF resource: ${schematronPath}`);
70
+ }
68
71
  this.schematronLoaded = true;
69
72
  }
70
73
 
@@ -1,5 +1,6 @@
1
1
  import * as plugins from '../../plugins.js';
2
2
  import type { ValidationResult } from './validation.types.js';
3
+ import { loadSaxonJS, type ISaxonJSTransformOptions, type ISaxonJSTransformResult } from '../../vendor/saxonjs.js';
3
4
 
4
5
  /**
5
6
  * Schematron validation options
@@ -11,14 +12,17 @@ export interface SchematronOptions {
11
12
  maxErrors?: number; // Maximum errors before stopping
12
13
  }
13
14
 
15
+ type TSchematronSourceKind = 'none' | 'schematron' | 'sef';
16
+
14
17
  /**
15
18
  * Schematron validation engine using Saxon-JS
16
19
  * Provides official standards validation through Schematron rules
17
20
  */
18
21
  export class SchematronValidator {
19
- private compiledStylesheet: any;
20
22
  private schematronRules: string;
21
- private isCompiled: boolean = false;
23
+ private sourceKind: TSchematronSourceKind = 'none';
24
+ private stylesheetFileName?: string;
25
+ private stylesheetInternal?: unknown;
22
26
 
23
27
  constructor(schematronRules?: string) {
24
28
  this.schematronRules = schematronRules || '';
@@ -28,42 +32,25 @@ export class SchematronValidator {
28
32
  * Load Schematron rules from file or string
29
33
  */
30
34
  public async loadSchematron(source: string, isFilePath: boolean = true): Promise<void> {
35
+ let sourceContent: string;
36
+
31
37
  if (isFilePath) {
32
- this.schematronRules = await plugins.fs.readFile(source, 'utf-8');
38
+ sourceContent = await plugins.fs.readFile(source, 'utf-8');
33
39
  } else {
34
- // Use provided string
35
- this.schematronRules = source;
40
+ sourceContent = source;
36
41
  }
37
-
38
- // Reset compilation state
39
- this.isCompiled = false;
40
- }
41
-
42
- /**
43
- * Compile Schematron to XSLT using ISO Schematron skeleton
44
- */
45
- private async compileSchematron(): Promise<void> {
46
- if (this.isCompiled) return;
47
-
48
- // The Schematron to XSLT transformation requires the ISO Schematron skeleton
49
- // For now, we'll use a simplified approach with direct XSLT generation
50
- // In production, we would use the official ISO Schematron skeleton XSLTs
51
-
52
- try {
53
- // Convert Schematron to XSLT
54
- // This is a simplified version - in production we'd use the full ISO skeleton
55
- const xslt = this.generateXSLTFromSchematron(this.schematronRules);
56
-
57
- // Compile the XSLT with Saxon-JS
58
- this.compiledStylesheet = await plugins.SaxonJS.compile({
59
- stylesheetText: xslt,
60
- warnings: 'silent'
61
- });
62
-
63
- this.isCompiled = true;
64
- } catch (error) {
65
- const errorMessage = error instanceof Error ? error.message : String(error);
66
- throw new Error(`Failed to compile Schematron: ${errorMessage}`);
42
+
43
+ this.schematronRules = sourceContent;
44
+ this.sourceKind = this.detectSourceKind(source, sourceContent, isFilePath);
45
+ this.stylesheetFileName = undefined;
46
+ this.stylesheetInternal = undefined;
47
+
48
+ if (this.sourceKind === 'sef') {
49
+ if (isFilePath) {
50
+ this.stylesheetFileName = source;
51
+ } else {
52
+ this.stylesheetInternal = JSON.parse(sourceContent);
53
+ }
67
54
  }
68
55
  }
69
56
 
@@ -78,19 +65,28 @@ export class SchematronValidator {
78
65
  throw new Error('No Schematron rules loaded');
79
66
  }
80
67
 
81
- // Ensure Schematron is compiled
82
- await this.compileSchematron();
83
-
84
68
  const results: ValidationResult[] = [];
69
+
70
+ if (!this.canValidate()) {
71
+ return [this.createUnavailableResult()];
72
+ }
85
73
 
86
74
  try {
87
- // Transform the XML with the compiled Schematron XSLT
88
- const transformResult = await plugins.SaxonJS.transform({
89
- stylesheetInternal: this.compiledStylesheet,
75
+ const transformOptions: ISaxonJSTransformOptions = {
90
76
  sourceText: xmlContent,
91
77
  destination: 'serialized',
92
78
  stylesheetParams: options.parameters || {}
93
- });
79
+ };
80
+
81
+ if (this.stylesheetFileName) {
82
+ transformOptions.stylesheetFileName = this.stylesheetFileName;
83
+ } else {
84
+ transformOptions.stylesheetInternal = this.stylesheetInternal;
85
+ }
86
+
87
+ // Transform the XML with a precompiled Saxon-JS SEF stylesheet.
88
+ const SaxonJS = await loadSaxonJS();
89
+ const transformResult = await SaxonJS.transform(transformOptions, 'async') as ISaxonJSTransformResult;
94
90
 
95
91
  // Parse the SVRL (Schematron Validation Report Language) output
96
92
  results.push(...this.parseSVRL(transformResult.principalResult));
@@ -189,43 +185,46 @@ export class SchematronValidator {
189
185
  };
190
186
  }
191
187
 
192
- /**
193
- * Generate simplified XSLT from Schematron
194
- * This is a placeholder - in production, use ISO Schematron skeleton
195
- */
196
- private generateXSLTFromSchematron(schematron: string): string {
197
- // This is a simplified transformation
198
- // In production, we would use the official ISO Schematron skeleton XSLTs
199
- // (iso_schematron_skeleton.xsl, iso_svrl_for_xslt2.xsl, etc.)
200
-
201
- // For now, return a basic XSLT that creates SVRL output
202
- return `<?xml version="1.0" encoding="UTF-8"?>
203
- <xsl:stylesheet version="3.0"
204
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
205
- xmlns:svrl="http://purl.oclc.org/dsdl/svrl">
206
-
207
- <xsl:output method="xml" indent="yes"/>
208
-
209
- <xsl:template match="/">
210
- <svrl:schematron-output>
211
- <!-- This is a placeholder transformation -->
212
- <!-- Real implementation would process Schematron patterns and rules -->
213
- <svrl:active-pattern>
214
- <xsl:attribute name="document">
215
- <xsl:value-of select="base-uri(/)"/>
216
- </xsl:attribute>
217
- </svrl:active-pattern>
218
- </svrl:schematron-output>
219
- </xsl:template>
220
- </xsl:stylesheet>`;
221
- }
222
-
223
188
  /**
224
189
  * Check if validator has rules loaded
225
190
  */
226
191
  public hasRules(): boolean {
227
192
  return !!this.schematronRules;
228
193
  }
194
+
195
+ /**
196
+ * Check if loaded rules can be executed by Saxon-JS.
197
+ */
198
+ public canValidate(): boolean {
199
+ return this.sourceKind === 'sef' && Boolean(this.stylesheetFileName || this.stylesheetInternal);
200
+ }
201
+
202
+ private detectSourceKind(source: string, sourceContent: string, isFilePath: boolean): TSchematronSourceKind {
203
+ const trimmed = sourceContent.trim();
204
+ if (!trimmed) {
205
+ return 'none';
206
+ }
207
+
208
+ if (isFilePath && /\.sef\.json$/i.test(source)) {
209
+ return 'sef';
210
+ }
211
+
212
+ if (trimmed.startsWith('{')) {
213
+ return 'sef';
214
+ }
215
+
216
+ return 'schematron';
217
+ }
218
+
219
+ private createUnavailableResult(): ValidationResult {
220
+ return {
221
+ ruleId: 'SCHEMATRON-UNCOMPILED',
222
+ source: 'SCHEMATRON',
223
+ severity: 'error',
224
+ message: 'Schematron validation requires a precompiled Saxon-JS SEF JSON stylesheet. Raw .sch files are loaded for inspection only and are not executed.',
225
+ remediation: 'Compile Schematron rules to .sef.json with Saxon tooling and load the compiled SEF resource.'
226
+ };
227
+ }
229
228
 
230
229
  /**
231
230
  * Get list of available phases from Schematron
@@ -1,8 +1,11 @@
1
1
  import { Worker } from 'worker_threads';
2
- import * as path from 'path';
3
2
  import type { ValidationResult } from './validation.types.js';
4
3
  import type { SchematronOptions } from './schematron.validator.js';
5
4
 
5
+ export interface ISchematronWorkerPoolInitializeOptions {
6
+ isFilePath?: boolean;
7
+ }
8
+
6
9
  /**
7
10
  * Worker pool for Schematron validation
8
11
  * Provides non-blocking validation in worker threads
@@ -17,7 +20,8 @@ export class SchematronWorkerPool {
17
20
  reject: (error: Error) => void;
18
21
  }> = [];
19
22
  private maxWorkers: number;
20
- private schematronRules: string = '';
23
+ private stylesheetFileName?: string;
24
+ private stylesheetInternal?: unknown;
21
25
 
22
26
  constructor(maxWorkers: number = 4) {
23
27
  this.maxWorkers = maxWorkers;
@@ -26,48 +30,81 @@ export class SchematronWorkerPool {
26
30
  /**
27
31
  * Initialize worker pool
28
32
  */
29
- public async initialize(schematronRules: string): Promise<void> {
30
- this.schematronRules = schematronRules;
33
+ public async initialize(
34
+ stylesheetSource: string,
35
+ options: ISchematronWorkerPoolInitializeOptions = {}
36
+ ): Promise<void> {
37
+ this.loadStylesheet(stylesheetSource, options);
31
38
 
32
39
  // Create workers
33
40
  for (let i = 0; i < this.maxWorkers; i++) {
34
41
  await this.createWorker();
35
42
  }
36
43
  }
44
+
45
+ private loadStylesheet(
46
+ stylesheetSource: string,
47
+ options: ISchematronWorkerPoolInitializeOptions
48
+ ): void {
49
+ const source = stylesheetSource.trim();
50
+ const isFilePath = options.isFilePath ?? /\.sef\.json$/i.test(stylesheetSource);
51
+
52
+ this.stylesheetFileName = undefined;
53
+ this.stylesheetInternal = undefined;
54
+
55
+ if (isFilePath) {
56
+ if (!/\.sef\.json$/i.test(stylesheetSource)) {
57
+ throw new Error('Schematron worker validation requires a precompiled Saxon-JS SEF JSON stylesheet file.');
58
+ }
59
+ this.stylesheetFileName = stylesheetSource;
60
+ return;
61
+ }
62
+
63
+ if (!source.startsWith('{')) {
64
+ throw new Error('Schematron worker validation requires a precompiled Saxon-JS SEF JSON stylesheet. Raw .sch files are not executed.');
65
+ }
66
+
67
+ this.stylesheetInternal = JSON.parse(source);
68
+ }
37
69
 
38
70
  /**
39
71
  * Create a new worker
40
72
  */
41
73
  private async createWorker(): Promise<void> {
42
- const workerPath = path.join(import.meta.url, 'schematron.worker.impl.js');
43
-
44
74
  const worker = new Worker(`
45
75
  const { parentPort } = require('worker_threads');
46
76
  const SaxonJS = require('saxon-js');
47
77
 
48
- let compiledStylesheet = null;
78
+ let stylesheetFileName = null;
79
+ let stylesheetInternal = null;
49
80
 
50
81
  parentPort.on('message', async (msg) => {
51
82
  try {
52
83
  if (msg.type === 'init') {
53
- // Compile Schematron to XSLT
54
- compiledStylesheet = await SaxonJS.compile({
55
- stylesheetText: msg.xslt,
56
- warnings: 'silent'
57
- });
84
+ stylesheetFileName = msg.stylesheetFileName || null;
85
+ stylesheetInternal = msg.stylesheetInternal || null;
86
+ if (!stylesheetFileName && !stylesheetInternal) {
87
+ throw new Error('Worker not initialized with a SEF stylesheet');
88
+ }
58
89
  parentPort.postMessage({ type: 'ready' });
59
90
  } else if (msg.type === 'validate') {
60
- if (!compiledStylesheet) {
91
+ if (!stylesheetFileName && !stylesheetInternal) {
61
92
  throw new Error('Worker not initialized');
62
93
  }
63
-
64
- // Transform XML with compiled Schematron
65
- const result = await SaxonJS.transform({
66
- stylesheetInternal: compiledStylesheet,
94
+
95
+ const transformOptions = {
67
96
  sourceText: msg.xmlContent,
68
97
  destination: 'serialized',
69
98
  stylesheetParams: msg.options.parameters || {}
70
- });
99
+ };
100
+
101
+ if (stylesheetFileName) {
102
+ transformOptions.stylesheetFileName = stylesheetFileName;
103
+ } else {
104
+ transformOptions.stylesheetInternal = stylesheetInternal;
105
+ }
106
+
107
+ const result = await SaxonJS.transform(transformOptions, 'async');
71
108
 
72
109
  parentPort.postMessage({
73
110
  type: 'result',
@@ -83,7 +120,7 @@ export class SchematronWorkerPool {
83
120
  });
84
121
  `, { eval: true });
85
122
 
86
- // Initialize worker with Schematron rules
123
+ // Initialize worker with a precompiled SEF stylesheet.
87
124
  await new Promise<void>((resolve, reject) => {
88
125
  worker.once('message', (msg) => {
89
126
  if (msg.type === 'ready') {
@@ -96,7 +133,8 @@ export class SchematronWorkerPool {
96
133
  // Send initialization message
97
134
  worker.postMessage({
98
135
  type: 'init',
99
- xslt: this.generateXSLTFromSchematron(this.schematronRules)
136
+ stylesheetFileName: this.stylesheetFileName,
137
+ stylesheetInternal: this.stylesheetInternal
100
138
  });
101
139
  });
102
140
 
@@ -174,26 +212,6 @@ export class SchematronWorkerPool {
174
212
  return results;
175
213
  }
176
214
 
177
- /**
178
- * Generate XSLT from Schematron (simplified)
179
- */
180
- private generateXSLTFromSchematron(schematron: string): string {
181
- // Simplified - would use ISO Schematron skeleton in production
182
- return `<?xml version="1.0" encoding="UTF-8"?>
183
- <xsl:stylesheet version="3.0"
184
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
185
- xmlns:svrl="http://purl.oclc.org/dsdl/svrl">
186
-
187
- <xsl:output method="xml" indent="yes"/>
188
-
189
- <xsl:template match="/">
190
- <svrl:schematron-output>
191
- <svrl:active-pattern document="{base-uri(/)}"/>
192
- </svrl:schematron-output>
193
- </xsl:template>
194
- </xsl:stylesheet>`;
195
- }
196
-
197
215
  /**
198
216
  * Terminate all workers
199
217
  */
@@ -218,4 +236,4 @@ export class SchematronWorkerPool {
218
236
  queuedTasks: this.taskQueue.length
219
237
  };
220
238
  }
221
- }
239
+ }
package/ts/plugins.ts CHANGED
@@ -9,24 +9,10 @@ import * as fs from 'fs/promises';
9
9
  import * as path from 'path';
10
10
  import * as crypto from 'crypto';
11
11
 
12
- // PDF-related imports
13
- import {
14
- PDFDocument,
15
- PDFDict,
16
- PDFName,
17
- PDFRawStream,
18
- PDFArray,
19
- PDFString,
20
- AFRelationship
21
- } from 'pdf-lib';
22
-
23
12
  // XML-related imports
24
13
  import { DOMParser, XMLSerializer, xmldom } from './vendor/xmldom.js';
25
14
  import * as xpath from 'xpath';
26
15
 
27
- // XSLT/Schematron imports
28
- import { SaxonJS } from './vendor/saxonjs.js';
29
-
30
16
  // Compression-related imports
31
17
  import { pako } from './vendor/pako.js';
32
18
 
@@ -40,24 +26,12 @@ export {
40
26
  path,
41
27
  crypto,
42
28
 
43
- // PDF-lib exports
44
- PDFDocument,
45
- PDFDict,
46
- PDFName,
47
- PDFRawStream,
48
- PDFArray,
49
- PDFString,
50
- AFRelationship,
51
-
52
29
  // XML-related exports
53
30
  DOMParser,
54
31
  XMLSerializer,
55
32
  xmldom,
56
33
  xpath,
57
34
 
58
- // XSLT/Schematron exports
59
- SaxonJS,
60
-
61
35
  // Compression-related exports
62
36
  pako,
63
37
 
package/ts/readme.md CHANGED
@@ -53,3 +53,24 @@ const xml = await invoice.exportXml('facturx');
53
53
 
54
54
  - `../readme.md`: full package README for end users
55
55
  - `../ts_install/readme.md`: install-time resource bootstrap module
56
+
57
+ ## License and Legal Information
58
+
59
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](../license) file.
60
+
61
+ **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.
62
+
63
+ ### Trademarks
64
+
65
+ This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
66
+
67
+ Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
68
+
69
+ ### Company Information
70
+
71
+ Task Venture Capital GmbH<br>
72
+ Registered at District Court Bremen HRB 35230 HB, Germany
73
+
74
+ For any legal inquiries or further information, please contact us via email at hello@task.vc.
75
+
76
+ By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
@@ -0,0 +1,12 @@
1
+ export type TPdfLibModule = typeof import('pdf-lib');
2
+
3
+ let cachedPdfLib: Promise<TPdfLibModule> | undefined;
4
+
5
+ // Use pdf-lib's bundled UMD build; the package entry requires JSON font assets,
6
+ // which some TS runners corrupt with require hooks.
7
+ const nativeImport = Function('specifier', 'return import(specifier)') as (specifier: string) => Promise<TPdfLibModule>;
8
+
9
+ export const loadPdfLib = async (): Promise<TPdfLibModule> => {
10
+ cachedPdfLib ||= nativeImport('pdf-lib/dist/pdf-lib.js');
11
+ return cachedPdfLib;
12
+ };
@@ -1,5 +1,3 @@
1
- import * as saxonJSRuntime from 'saxon-js';
2
-
3
1
  export interface ISaxonJSCompileOptions {
4
2
  stylesheetText: string;
5
3
  warnings?: string;
@@ -8,6 +6,7 @@ export interface ISaxonJSCompileOptions {
8
6
 
9
7
  export interface ISaxonJSTransformOptions {
10
8
  stylesheetInternal?: unknown;
9
+ stylesheetFileName?: string;
11
10
  sourceText: string;
12
11
  destination?: string;
13
12
  stylesheetParams?: Record<string, unknown>;
@@ -20,9 +19,18 @@ export interface ISaxonJSTransformResult {
20
19
  }
21
20
 
22
21
  export interface ISaxonJSModule {
23
- compile(options: ISaxonJSCompileOptions): Promise<unknown>;
24
- transform(options: ISaxonJSTransformOptions): Promise<ISaxonJSTransformResult>;
22
+ compile?: (options: ISaxonJSCompileOptions) => Promise<unknown>;
23
+ transform(options: ISaxonJSTransformOptions, executionMode?: 'async' | 'sync'): Promise<ISaxonJSTransformResult> | ISaxonJSTransformResult;
25
24
  [key: string]: unknown;
26
25
  }
27
26
 
28
- export const SaxonJS: ISaxonJSModule = saxonJSRuntime as unknown as ISaxonJSModule;
27
+ let cachedSaxonJS: Promise<ISaxonJSModule> | undefined;
28
+
29
+ export const loadSaxonJS = async (): Promise<ISaxonJSModule> => {
30
+ cachedSaxonJS ||= import('saxon-js').then((saxonJSRuntime) => {
31
+ const runtime = (saxonJSRuntime as any).default ?? saxonJSRuntime;
32
+ return runtime as ISaxonJSModule;
33
+ });
34
+
35
+ return cachedSaxonJS;
36
+ };