@fin.cx/einvoice 5.1.4 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{npmextra.json → .smartconfig.json} +12 -6
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/einvoice.d.ts +14 -5
- package/dist_ts/einvoice.js +165 -60
- package/dist_ts/errors.js +14 -4
- package/dist_ts/formats/base/base.decoder.d.ts +4 -0
- package/dist_ts/formats/base/base.decoder.js +9 -1
- package/dist_ts/formats/base/base.validator.js +3 -2
- package/dist_ts/formats/cii/cii.decoder.d.ts +1 -0
- package/dist_ts/formats/cii/cii.decoder.js +20 -10
- package/dist_ts/formats/cii/cii.encoder.js +2 -5
- package/dist_ts/formats/cii/cii.validator.d.ts +1 -1
- package/dist_ts/formats/cii/cii.validator.js +19 -12
- package/dist_ts/formats/converters/xml-to-einvoice.converter.js +3 -3
- package/dist_ts/formats/factories/decoder.factory.d.ts +3 -1
- package/dist_ts/formats/factories/decoder.factory.js +4 -3
- package/dist_ts/formats/factories/validator.factory.d.ts +4 -1
- package/dist_ts/formats/factories/validator.factory.js +11 -8
- package/dist_ts/formats/pdf/extractors/base.extractor.js +49 -51
- package/dist_ts/formats/pdf/extractors/text.extractor.js +19 -22
- package/dist_ts/formats/pdf/pdf.extractor.js +2 -2
- package/dist_ts/formats/semantic/semantic.adapter.js +42 -12
- package/dist_ts/formats/semantic/semantic.validator.js +3 -1
- package/dist_ts/formats/ubl/en16931.ubl.validator.js +5 -3
- package/dist_ts/formats/ubl/generic/ubl.encoder.js +11 -7
- package/dist_ts/formats/ubl/ubl.decoder.d.ts +1 -0
- package/dist_ts/formats/ubl/ubl.decoder.js +18 -8
- package/dist_ts/formats/ubl/ubl.validator.d.ts +1 -1
- package/dist_ts/formats/ubl/ubl.validator.js +17 -10
- package/dist_ts/formats/ubl/xrechnung/xrechnung.decoder.js +37 -29
- package/dist_ts/formats/utils/currency.calculator.decimal.js +4 -1
- package/dist_ts/formats/utils/currency.utils.js +4 -1
- package/dist_ts/formats/utils/decimal.js +9 -2
- package/dist_ts/formats/utils/format.detector.js +47 -17
- package/dist_ts/formats/validation/codelist.validator.js +2 -4
- package/dist_ts/formats/validation/conformance.harness.js +13 -6
- package/dist_ts/formats/validation/en16931.business-rules.validator.js +4 -4
- package/dist_ts/formats/validation/en16931.validator.d.ts +6 -0
- package/dist_ts/formats/validation/en16931.validator.js +18 -12
- package/dist_ts/formats/validation/facturx.validator.js +147 -148
- package/dist_ts/formats/validation/integrated.validator.js +12 -4
- package/dist_ts/formats/validation/peppol.validator.js +2 -1
- package/dist_ts/formats/validation/schematron.downloader.js +13 -6
- package/dist_ts/formats/validation/schematron.integration.js +12 -5
- package/dist_ts/formats/validation/schematron.validator.js +17 -13
- package/dist_ts/formats/validation/schematron.worker.js +6 -5
- package/dist_ts/formats/validation/vat-categories.validator.js +3 -4
- package/dist_ts/formats/validation/xrechnung.validator.js +7 -7
- package/dist_ts/index.js +3 -2
- package/dist_ts/interfaces/common.js +1 -2
- package/dist_ts/plugins.d.ts +3 -4
- package/dist_ts/plugins.js +4 -5
- package/dist_ts/vendor/pako.d.ts +5 -0
- package/dist_ts/vendor/pako.js +3 -0
- package/dist_ts/vendor/saxonjs.d.ts +22 -0
- package/dist_ts/vendor/saxonjs.js +3 -0
- package/dist_ts/vendor/xmldom.d.ts +20 -0
- package/dist_ts/vendor/xmldom.js +5 -0
- package/dist_ts_install/download-schematron.d.ts +0 -3
- package/dist_ts_install/download-schematron.js +20 -11
- package/dist_ts_install/download-test-samples.d.ts +0 -3
- package/dist_ts_install/download-test-samples.js +4 -2
- package/dist_ts_install/download-xrechnung-rules.js +2 -1
- package/dist_ts_install/index.d.ts +0 -5
- package/dist_ts_install/index.js +26 -12
- package/license +21 -0
- package/package.json +24 -22
- package/readme.hints.md +24 -8
- package/readme.md +195 -328
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/einvoice.ts +148 -26
- package/ts/formats/base/base.decoder.ts +7 -0
- package/ts/formats/cii/cii.decoder.ts +17 -8
- package/ts/formats/cii/cii.validator.ts +18 -13
- package/ts/formats/converters/xml-to-einvoice.converter.ts +4 -5
- package/ts/formats/factories/decoder.factory.ts +7 -2
- package/ts/formats/factories/validator.factory.ts +14 -8
- package/ts/formats/semantic/semantic.adapter.ts +49 -15
- package/ts/formats/ubl/en16931.ubl.validator.ts +5 -3
- package/ts/formats/ubl/generic/ubl.encoder.ts +12 -7
- package/ts/formats/ubl/ubl.decoder.ts +18 -9
- package/ts/formats/ubl/ubl.validator.ts +17 -12
- package/ts/formats/ubl/xrechnung/xrechnung.decoder.ts +41 -28
- package/ts/formats/utils/format.detector.ts +57 -19
- package/ts/formats/validation/conformance.harness.ts +6 -4
- package/ts/formats/validation/en16931.validator.ts +20 -10
- package/ts/formats/validation/integrated.validator.ts +5 -3
- package/ts/formats/validation/schematron.downloader.ts +11 -6
- package/ts/formats/validation/schematron.integration.ts +7 -4
- package/ts/formats/validation/schematron.validator.ts +12 -11
- package/ts/index.ts +2 -1
- package/ts/interfaces/common.ts +1 -3
- package/ts/plugins.ts +3 -4
- package/ts/readme.md +55 -0
- package/ts/vendor/modules.d.ts +32 -0
- package/ts/vendor/pako.ts +8 -0
- package/ts/vendor/saxonjs.ts +28 -0
- package/ts/vendor/xmldom.ts +27 -0
package/readme.md
CHANGED
|
@@ -1,443 +1,310 @@
|
|
|
1
|
-
# @fin.cx/einvoice
|
|
1
|
+
# @fin.cx/einvoice ⚡
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript e-invoicing for the real world: load invoice XML or hybrid PDFs, detect the format, map it into a typed invoice model, validate it, convert it, and embed XML back into PDFs.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
[](https://www.cen.eu/work/areas/ict/ebusiness/pages/einvoicing.aspx)
|
|
7
|
-
[](https://github.com/fin-cx/einvoice)
|
|
8
|
-
[](./license)
|
|
5
|
+
`@fin.cx/einvoice` is built for programmers who need a practical toolkit around European e-invoice formats without writing a parser zoo from scratch.
|
|
9
6
|
|
|
10
|
-
|
|
7
|
+
## Issue Reporting and Security
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
- **⚡ Blazing Fast**: Validate invoices in ~2.2ms, convert formats in ~0.6ms
|
|
16
|
-
- **🔐 Enterprise Security**: XXE prevention, resource limits, path traversal protection
|
|
17
|
-
- **🌍 Multi-Standard Support**: ZUGFeRD, Factur-X, XRechnung, PEPPOL BIS 3.0, UBL, and more
|
|
18
|
-
- **💎 Decimal Precision**: Arbitrary precision arithmetic for perfect financial calculations
|
|
19
|
-
- **🔄 Lossless Conversion**: 100% data preservation in round-trip conversions
|
|
20
|
-
- **📦 PDF Magic**: Extract and embed XML in PDF/A-3 documents seamlessly
|
|
21
|
-
- **🛠️ TypeScript First**: Fully typed with IntelliSense support throughout
|
|
11
|
+
## Why this library?
|
|
22
12
|
|
|
23
|
-
|
|
13
|
+
- 🚀 Load invoices from XML strings, files, or PDFs with embedded XML.
|
|
14
|
+
- 🧭 Detect `ubl`, `xrechnung`, `cii`, `facturx`, `zugferd`, and `fatturapa` documents.
|
|
15
|
+
- 🧾 Work on a typed in-memory invoice model based on `@tsclass/tsclass`.
|
|
16
|
+
- ✅ Validate invoices on syntax, semantic, and business-rule levels.
|
|
17
|
+
- 🔄 Export invoices as `facturx`, `zugferd`, `xrechnung`, `ubl`, or `cii`.
|
|
18
|
+
- 📎 Extract XML from invoice PDFs and attach XML back into existing PDFs.
|
|
19
|
+
- 🧱 Use the high-level `EInvoice` class or lower-level decoders, encoders, validators, and PDF extractors directly.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
24
22
|
|
|
25
23
|
```bash
|
|
26
|
-
# Using pnpm (recommended)
|
|
27
24
|
pnpm add @fin.cx/einvoice
|
|
25
|
+
```
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
npm install @fin.cx/einvoice
|
|
27
|
+
`postinstall` will try to download Schematron validation resources on a best-effort basis when the package is installed in a normal online environment. Install will not fail if the resources cannot be downloaded.
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
Useful commands:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pnpm download-schematron
|
|
33
|
+
pnpm download-test-samples
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Useful environment flag:
|
|
37
37
|
|
|
38
|
-
```
|
|
39
|
-
|
|
38
|
+
```bash
|
|
39
|
+
EINVOICE_SKIP_RESOURCES=1
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const invoice2 = await EInvoice.fromXml(xmlString); // From XML string
|
|
44
|
-
const invoice3 = await EInvoice.fromPdf(pdfBuffer); // From PDF with embedded XML
|
|
44
|
+
```ts
|
|
45
|
+
import { EInvoice, ValidationLevel } from '@fin.cx/einvoice';
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
const validation = await invoice.validate();
|
|
48
|
-
console.log(`Valid: ${validation.valid}`);
|
|
47
|
+
const invoice = await EInvoice.fromFile('./invoice.xml');
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const facturx = await invoice.exportXml('facturx'); // For France/Germany
|
|
54
|
-
const zugferd = await invoice.exportXml('zugferd'); // For German standard
|
|
49
|
+
console.log(invoice.getFormat());
|
|
50
|
+
console.log(invoice.id);
|
|
51
|
+
console.log(invoice.from.name, '->', invoice.to.name);
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
const validation = await invoice.validate(ValidationLevel.BUSINESS);
|
|
54
|
+
if (!validation.valid) {
|
|
55
|
+
console.log(validation.errors);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const xrechnungXml = await invoice.exportXml('xrechnung');
|
|
58
59
|
```
|
|
59
60
|
|
|
60
|
-
##
|
|
61
|
+
## What it can do
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
### Load and inspect invoices
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { EInvoice } from '@fin.cx/einvoice';
|
|
67
|
+
|
|
68
|
+
const fromXml = await EInvoice.fromXml(xmlString);
|
|
69
|
+
const fromFile = await EInvoice.fromFile('./invoice.xml');
|
|
70
|
+
const fromPdf = await EInvoice.fromPdf(pdfBuffer);
|
|
71
|
+
|
|
72
|
+
console.log(fromXml.subject);
|
|
73
|
+
console.log(fromXml.items.length);
|
|
74
|
+
console.log(fromXml.currency);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Create invoices in code
|
|
78
|
+
|
|
79
|
+
```ts
|
|
63
80
|
import { EInvoice } from '@fin.cx/einvoice';
|
|
64
81
|
|
|
65
|
-
// Create a fully compliant invoice from scratch
|
|
66
82
|
const invoice = new EInvoice();
|
|
67
83
|
|
|
68
|
-
|
|
69
|
-
invoice.
|
|
70
|
-
invoice.issueDate = new Date('2025-01-15');
|
|
71
|
-
invoice.accountingDocType = 'invoice';
|
|
84
|
+
invoice.accountingDocId = 'INV-2026-001';
|
|
85
|
+
invoice.issueDate = new Date('2026-04-16');
|
|
72
86
|
invoice.currency = 'EUR';
|
|
73
|
-
invoice.dueInDays =
|
|
87
|
+
invoice.dueInDays = 14;
|
|
74
88
|
|
|
75
|
-
// Seller information
|
|
76
89
|
invoice.from = {
|
|
77
90
|
type: 'company',
|
|
78
|
-
name: '
|
|
91
|
+
name: 'Sender GmbH',
|
|
92
|
+
description: '',
|
|
93
|
+
status: 'active',
|
|
94
|
+
foundedDate: { year: 2020, month: 1, day: 1 },
|
|
79
95
|
address: {
|
|
80
|
-
streetName: '
|
|
81
|
-
houseNumber: '
|
|
96
|
+
streetName: 'Example Street',
|
|
97
|
+
houseNumber: '1',
|
|
82
98
|
city: 'Berlin',
|
|
83
99
|
postalCode: '10115',
|
|
84
|
-
country: 'DE'
|
|
100
|
+
country: 'DE',
|
|
85
101
|
},
|
|
86
102
|
registrationDetails: {
|
|
87
103
|
vatId: 'DE123456789',
|
|
88
104
|
registrationId: 'HRB 123456',
|
|
89
|
-
registrationName: '
|
|
105
|
+
registrationName: 'Sender GmbH',
|
|
90
106
|
},
|
|
91
|
-
status: 'active'
|
|
92
107
|
};
|
|
93
108
|
|
|
94
|
-
// Buyer information
|
|
95
109
|
invoice.to = {
|
|
96
110
|
type: 'company',
|
|
97
|
-
name: '
|
|
111
|
+
name: 'Receiver SAS',
|
|
112
|
+
description: '',
|
|
113
|
+
status: 'active',
|
|
114
|
+
foundedDate: { year: 2020, month: 1, day: 1 },
|
|
98
115
|
address: {
|
|
99
|
-
streetName: 'Rue
|
|
116
|
+
streetName: 'Rue Example',
|
|
100
117
|
houseNumber: '10',
|
|
101
118
|
city: 'Paris',
|
|
102
119
|
postalCode: '75001',
|
|
103
|
-
country: 'FR'
|
|
120
|
+
country: 'FR',
|
|
104
121
|
},
|
|
105
122
|
registrationDetails: {
|
|
106
|
-
vatId: '
|
|
107
|
-
registrationId: 'RCS
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Payment details - SEPA ready
|
|
112
|
-
invoice.paymentAccount = {
|
|
113
|
-
iban: 'DE89370400440532013000',
|
|
114
|
-
bic: 'COBADEFFXXX',
|
|
115
|
-
accountName: 'Tech Solutions GmbH',
|
|
116
|
-
institutionName: 'Commerzbank'
|
|
123
|
+
vatId: 'FR12345678901',
|
|
124
|
+
registrationId: 'RCS 123456789',
|
|
125
|
+
registrationName: 'Receiver SAS',
|
|
126
|
+
},
|
|
117
127
|
};
|
|
118
128
|
|
|
119
|
-
// Line items with automatic calculations
|
|
120
129
|
invoice.items = [
|
|
121
130
|
{
|
|
122
131
|
position: 1,
|
|
123
|
-
name: '
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
unitQuantity:
|
|
127
|
-
unitNetPrice:
|
|
132
|
+
name: 'Implementation work',
|
|
133
|
+
articleNumber: 'IMPL-001',
|
|
134
|
+
unitType: 'HUR',
|
|
135
|
+
unitQuantity: 8,
|
|
136
|
+
unitNetPrice: 120,
|
|
128
137
|
vatPercentage: 19,
|
|
129
|
-
unitType: 'MON' // Month
|
|
130
138
|
},
|
|
131
|
-
{
|
|
132
|
-
position: 2,
|
|
133
|
-
name: 'Professional Consulting',
|
|
134
|
-
description: 'Architecture review and optimization',
|
|
135
|
-
articleNumber: 'CONSULT-001',
|
|
136
|
-
unitQuantity: 16,
|
|
137
|
-
unitNetPrice: 150.00,
|
|
138
|
-
vatPercentage: 19,
|
|
139
|
-
unitType: 'HUR' // Hour
|
|
140
|
-
}
|
|
141
139
|
];
|
|
142
140
|
|
|
143
|
-
|
|
144
|
-
const zugferdXml = await invoice.exportXml('zugferd');
|
|
145
|
-
const pdfWithXml = await invoice.exportPdf('facturx');
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
## 🎨 Supported Standards & Formats
|
|
149
|
-
|
|
150
|
-
| Standard | Version | Status | Use Case |
|
|
151
|
-
|----------|---------|--------|----------|
|
|
152
|
-
| **EN16931** | 2017 | ✅ 100% Complete | Core European standard |
|
|
153
|
-
| **ZUGFeRD** | 1.0, 2.0, 2.1 | ✅ Full Support | German B2B/B2C |
|
|
154
|
-
| **Factur-X** | 1.0 (all profiles) | ✅ Full Support | France/Germany |
|
|
155
|
-
| **XRechnung** | 2.0, 3.0 | ✅ Full Support | German public sector |
|
|
156
|
-
| **PEPPOL BIS 3.0** | 3.0 | ✅ Full Support | Cross-border B2G |
|
|
157
|
-
| **UBL** | 2.1 | ✅ Full Support | International |
|
|
158
|
-
| **CII** | D16B | ✅ Full Support | Cross Industry |
|
|
159
|
-
|
|
160
|
-
### 📋 Factur-X Profile Support
|
|
161
|
-
|
|
162
|
-
```typescript
|
|
163
|
-
// Automatic profile detection and validation
|
|
164
|
-
const profiles = {
|
|
165
|
-
MINIMUM: 'Essential fields only (BT-1, BT-2, BT-3)',
|
|
166
|
-
BASIC: 'Core invoice with line items',
|
|
167
|
-
BASIC_WL: 'Basic without lines (summary invoices)',
|
|
168
|
-
EN16931: 'Full EN16931 compliance',
|
|
169
|
-
EXTENDED: 'Additional structured data'
|
|
170
|
-
};
|
|
141
|
+
const xml = await invoice.exportXml('facturx');
|
|
171
142
|
```
|
|
172
143
|
|
|
173
|
-
|
|
144
|
+
### Validate at different levels
|
|
174
145
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
No more floating-point errors! Built-in arbitrary precision arithmetic:
|
|
178
|
-
|
|
179
|
-
```typescript
|
|
180
|
-
// Perfect financial calculations every time
|
|
181
|
-
const calculator = new DecimalCurrencyCalculator('EUR');
|
|
182
|
-
const result = calculator.calculateLineNet(
|
|
183
|
-
'3.14159', // Quantity
|
|
184
|
-
'999.99', // Unit price
|
|
185
|
-
'0' // Discount (optional)
|
|
186
|
-
);
|
|
187
|
-
// Result: 3141.56 (correctly rounded for EUR)
|
|
188
|
-
```
|
|
146
|
+
```ts
|
|
147
|
+
import { EInvoice, ValidationLevel } from '@fin.cx/einvoice';
|
|
189
148
|
|
|
190
|
-
|
|
149
|
+
const invoice = await EInvoice.fromXml(xmlString);
|
|
191
150
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
// Get specific rule violations
|
|
199
|
-
businessResult.errors.forEach(error => {
|
|
200
|
-
console.log(`Rule ${error.ruleId}: ${error.message}`);
|
|
201
|
-
console.log(`Business Term: ${error.btReference}`);
|
|
202
|
-
console.log(`Field: ${error.field}`);
|
|
151
|
+
const syntax = await invoice.validate(ValidationLevel.SYNTAX);
|
|
152
|
+
const semantic = await invoice.validate(ValidationLevel.SEMANTIC);
|
|
153
|
+
const business = await invoice.validate(ValidationLevel.BUSINESS, {
|
|
154
|
+
featureFlags: ['EN16931_BUSINESS_RULES', 'CODE_LIST_VALIDATION'],
|
|
155
|
+
reportOnly: true,
|
|
203
156
|
});
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### 🔄 Format Detection & Conversion
|
|
207
|
-
|
|
208
|
-
```typescript
|
|
209
|
-
// Automatic format detection
|
|
210
|
-
const format = FormatDetector.detectFormat(xmlString);
|
|
211
|
-
console.log(`Detected: ${format}`); // 'zugferd', 'facturx', 'xrechnung', etc.
|
|
212
157
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
const backToZugferd = await EInvoice.fromXml(xrechnung);
|
|
217
|
-
// All data preserved through round-trip!
|
|
158
|
+
console.log(business.valid);
|
|
159
|
+
console.log(business.errors);
|
|
160
|
+
console.log(business.warnings ?? []);
|
|
218
161
|
```
|
|
219
162
|
|
|
220
|
-
###
|
|
163
|
+
### Convert between supported XML targets
|
|
221
164
|
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
const extractor = new PDFExtractor();
|
|
225
|
-
const result = await extractor.extractXml(pdfBuffer);
|
|
226
|
-
if (result.success) {
|
|
227
|
-
console.log(`Found ${result.format} invoice`);
|
|
228
|
-
const invoice = await EInvoice.fromXml(result.xml);
|
|
229
|
-
}
|
|
165
|
+
```ts
|
|
166
|
+
import { EInvoice } from '@fin.cx/einvoice';
|
|
230
167
|
|
|
231
|
-
|
|
232
|
-
const embedder = new PDFEmbedder();
|
|
233
|
-
const pdfWithXml = await embedder.createPdfWithXml(
|
|
234
|
-
existingPdf,
|
|
235
|
-
xmlContent,
|
|
236
|
-
'factur-x.xml',
|
|
237
|
-
'Factur-X Invoice'
|
|
238
|
-
);
|
|
239
|
-
```
|
|
168
|
+
const invoice = await EInvoice.fromFile('./source.xml');
|
|
240
169
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
invoice.metadata = {
|
|
247
|
-
customizationId: 'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0',
|
|
248
|
-
extensions: {
|
|
249
|
-
leitwegId: '991-12345-67', // Required routing ID
|
|
250
|
-
buyerReference: 'DE-BUYER-REF', // Mandatory
|
|
251
|
-
sellerContact: {
|
|
252
|
-
name: 'Max Mustermann',
|
|
253
|
-
phone: '+49 30 12345678',
|
|
254
|
-
email: 'invoice@company.de'
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
};
|
|
170
|
+
const facturxXml = await invoice.exportXml('facturx');
|
|
171
|
+
const zugferdXml = await invoice.exportXml('zugferd');
|
|
172
|
+
const xrechnungXml = await invoice.exportXml('xrechnung');
|
|
173
|
+
const ublXml = await invoice.exportXml('ubl');
|
|
174
|
+
const ciiXml = await invoice.exportXml('cii');
|
|
258
175
|
```
|
|
259
176
|
|
|
260
|
-
###
|
|
177
|
+
### Work with PDFs
|
|
261
178
|
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
profileId: 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0',
|
|
265
|
-
extensions: {
|
|
266
|
-
endpointId: '0088:1234567890128', // GLN with checksum
|
|
267
|
-
documentTypeId: 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017',
|
|
268
|
-
processId: 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0'
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
```
|
|
179
|
+
```ts
|
|
180
|
+
import { EInvoice, PDFExtractor } from '@fin.cx/einvoice';
|
|
272
181
|
|
|
273
|
-
|
|
182
|
+
const extracted = await new PDFExtractor().extractXml(pdfBuffer);
|
|
183
|
+
if (extracted.success && extracted.xml) {
|
|
184
|
+
const invoice = await EInvoice.fromXml(extracted.xml);
|
|
185
|
+
console.log(extracted.format, invoice.id);
|
|
186
|
+
}
|
|
274
187
|
|
|
275
|
-
|
|
276
|
-
invoice.
|
|
277
|
-
extensions: {
|
|
278
|
-
siret: '12345678901234',
|
|
279
|
-
serviceCode: 'SERVICE-2025',
|
|
280
|
-
engagementNumber: 'ENG-123456',
|
|
281
|
-
marketReference: 'MARKET-REF-001'
|
|
282
|
-
}
|
|
283
|
-
};
|
|
188
|
+
const invoice = await EInvoice.fromXml(xmlString);
|
|
189
|
+
const pdfWithXml = await invoice.embedInPdf(existingPdfBuffer, 'facturx');
|
|
284
190
|
```
|
|
285
191
|
|
|
286
|
-
##
|
|
287
|
-
|
|
288
|
-
Lightning-fast operations with minimal memory footprint:
|
|
192
|
+
## Supported formats
|
|
289
193
|
|
|
290
|
-
|
|
|
291
|
-
|
|
292
|
-
|
|
|
293
|
-
|
|
|
294
|
-
|
|
|
295
|
-
|
|
|
296
|
-
|
|
|
297
|
-
|
|
|
194
|
+
| Format | Detect | Import | Export | Validation | Notes |
|
|
195
|
+
| --- | --- | --- | --- | --- | --- |
|
|
196
|
+
| `ubl` | Yes | Yes | Yes | Yes | Generic UBL flow |
|
|
197
|
+
| `xrechnung` | Yes | Yes | Yes | Yes | UBL-based profile |
|
|
198
|
+
| `cii` | Yes | Yes | Yes | Partial | Generic CII export currently uses the Factur-X encoder path |
|
|
199
|
+
| `facturx` | Yes | Yes | Yes | Yes | Main CII-based generation path |
|
|
200
|
+
| `zugferd` | Yes | Yes | Yes | Partial | Input supports v1 and v2+, export focuses on the current encoder |
|
|
201
|
+
| `fatturapa` | Yes | No | No | Basic placeholder | Detection exists, decoder/encoder do not |
|
|
298
202
|
|
|
299
|
-
|
|
203
|
+
### Important format notes
|
|
300
204
|
|
|
301
|
-
|
|
205
|
+
- There is no dedicated root-level `peppol` export format. PEPPOL-specific checks exist, but the XML export targets are still `ubl` / `xrechnung`.
|
|
206
|
+
- `FatturaPA` should be documented as detection-only right now.
|
|
207
|
+
- `creditnote` / `debitnote` handling exists in parts of the lower-level code, but the high-level `invoiceType` setter on `EInvoice` only accepts `'invoice'`.
|
|
302
208
|
|
|
303
|
-
|
|
304
|
-
// Factory pattern for extensibility
|
|
305
|
-
DecoderFactory.getDecoder(format) → BaseDecoder
|
|
306
|
-
EncoderFactory.getEncoder(format) → BaseEncoder
|
|
307
|
-
ValidatorFactory.getValidator(format) → BaseValidator
|
|
308
|
-
```
|
|
209
|
+
## Public API overview
|
|
309
210
|
|
|
310
|
-
|
|
211
|
+
Top-level exports from `@fin.cx/einvoice` include:
|
|
311
212
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
213
|
+
- `EInvoice`
|
|
214
|
+
- `createEInvoice()`
|
|
215
|
+
- `validateXml(xml, level?)`
|
|
216
|
+
- `FormatDetector`
|
|
217
|
+
- `PDFExtractor`, `PDFEmbedder`
|
|
218
|
+
- `DecoderFactory`, `EncoderFactory`, `ValidatorFactory`
|
|
219
|
+
- `BaseDecoder`, `BaseEncoder`, `BaseValidator`
|
|
220
|
+
- `UBLBase*` and `CIIBase*` extension classes
|
|
221
|
+
- `FacturX*` and `ZUGFeRD*` format-specific classes
|
|
222
|
+
- `ValidationLevel`, `InvoiceFormat`
|
|
223
|
+
- exported types like `TInvoice`, `ValidationResult`, `ValidationError`, `ExportFormat`, `IPdf`, `EInvoiceOptions`
|
|
319
224
|
|
|
320
|
-
##
|
|
225
|
+
## Validation resources and install-time behavior
|
|
321
226
|
|
|
322
|
-
|
|
323
|
-
- **Resource Limits**: Max 100MB XML, max 100 nesting levels
|
|
324
|
-
- **Path Traversal Protection**: Sanitized filenames in PDFs
|
|
325
|
-
- **SSRF Mitigation**: Entity blocking in XML processing
|
|
326
|
-
- **Input Validation**: Comprehensive input sanitization
|
|
227
|
+
The package includes an install bootstrap in `ts_install/` that tries to download validation resources into `assets_downloaded/schematron`.
|
|
327
228
|
|
|
328
|
-
|
|
229
|
+
Behavior to know:
|
|
329
230
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
231
|
+
- It only runs in a real `postinstall` lifecycle.
|
|
232
|
+
- It skips cleanly when offline.
|
|
233
|
+
- It skips when `dist_ts/` is not present yet.
|
|
234
|
+
- It can be disabled in CI with `EINVOICE_SKIP_RESOURCES=1`.
|
|
235
|
+
- Missing resources do not break install, but they can reduce advanced validation coverage.
|
|
333
236
|
|
|
334
|
-
|
|
335
|
-
pnpm test test/test.peppol-validator.ts
|
|
336
|
-
pnpm test test/test.facturx-validator.ts
|
|
337
|
-
pnpm test test/test.semantic-model.ts
|
|
237
|
+
If you need the resources manually:
|
|
338
238
|
|
|
339
|
-
|
|
340
|
-
pnpm
|
|
239
|
+
```bash
|
|
240
|
+
pnpm download-schematron
|
|
241
|
+
pnpm download-test-samples
|
|
341
242
|
```
|
|
342
243
|
|
|
343
|
-
##
|
|
344
|
-
|
|
345
|
-
### Batch Processing with Concurrency Control
|
|
244
|
+
## Architecture in one screen
|
|
346
245
|
|
|
347
|
-
```
|
|
348
|
-
|
|
246
|
+
```text
|
|
247
|
+
XML / PDF
|
|
248
|
+
-> format detection
|
|
249
|
+
-> decoder
|
|
250
|
+
-> EInvoice model
|
|
251
|
+
-> validation / editing
|
|
252
|
+
-> encoder
|
|
253
|
+
-> XML / PDF with embedded XML
|
|
254
|
+
```
|
|
349
255
|
|
|
350
|
-
|
|
351
|
-
const files = ['invoice1.xml', 'invoice2.xml', /* ... */];
|
|
256
|
+
This repo also exposes the lower-level pieces separately so you can plug into the pipeline at the stage you actually need.
|
|
352
257
|
|
|
353
|
-
|
|
354
|
-
files.map(file =>
|
|
355
|
-
limit(async () => {
|
|
356
|
-
const invoice = await EInvoice.fromFile(file);
|
|
357
|
-
const validation = await invoice.validate();
|
|
358
|
-
return { file, valid: validation.valid };
|
|
359
|
-
})
|
|
360
|
-
)
|
|
361
|
-
);
|
|
362
|
-
```
|
|
258
|
+
## Good things to know before using it
|
|
363
259
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
try {
|
|
369
|
-
const { xml, targetFormat } = req.body;
|
|
370
|
-
const invoice = await EInvoice.fromXml(xml);
|
|
371
|
-
|
|
372
|
-
// Validate before conversion
|
|
373
|
-
const validation = await invoice.validate();
|
|
374
|
-
if (!validation.valid) {
|
|
375
|
-
return res.status(400).json({
|
|
376
|
-
error: 'Invalid invoice',
|
|
377
|
-
violations: validation.errors
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
const converted = await invoice.exportXml(targetFormat);
|
|
382
|
-
res.json({ success: true, xml: converted });
|
|
383
|
-
} catch (error) {
|
|
384
|
-
res.status(500).json({ error: error.message });
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
```
|
|
260
|
+
- `embedInPdf()` attaches XML to an existing PDF buffer. It does not render invoice PDFs from scratch.
|
|
261
|
+
- `saveToFile('something.pdf', ...)` only works when `invoice.pdf` already exists, for example after loading from a PDF first.
|
|
262
|
+
- Validation coverage is useful and broad, but this README deliberately does not claim blanket certification or “100% compliance”.
|
|
263
|
+
- Schematron integration and richer business-rule layers exist, but they depend on downloaded resources and are not the same as guaranteed certification against every profile.
|
|
388
264
|
|
|
389
|
-
##
|
|
265
|
+
## Example workflow
|
|
390
266
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
- All 32 Business Groups structured
|
|
394
|
-
- Complete semantic model with BT/BG validation
|
|
395
|
-
- Official Schematron rules integrated
|
|
267
|
+
```ts
|
|
268
|
+
import { EInvoice, ValidationLevel } from '@fin.cx/einvoice';
|
|
396
269
|
|
|
397
|
-
|
|
398
|
-
- **500+ test cases** ensuring reliability
|
|
399
|
-
- **Battle-tested** with real-world invoice corpus
|
|
400
|
-
- **Memory efficient** - handles 1000+ line items
|
|
401
|
-
- **Thread-safe** for concurrent processing
|
|
270
|
+
const invoice = await EInvoice.fromFile('./incoming.pdf');
|
|
402
271
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
- **Comprehensive documentation** with real examples
|
|
272
|
+
const validation = await invoice.validate(ValidationLevel.BUSINESS, {
|
|
273
|
+
featureFlags: ['EN16931_BUSINESS_RULES', 'CODE_LIST_VALIDATION'],
|
|
274
|
+
reportOnly: false,
|
|
275
|
+
});
|
|
408
276
|
|
|
409
|
-
|
|
277
|
+
if (!validation.valid) {
|
|
278
|
+
throw new Error(validation.errors.map((error) => error.message).join('\n'));
|
|
279
|
+
}
|
|
410
280
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
- ~15MB installed size
|
|
414
|
-
- Zero native dependencies
|
|
281
|
+
const xmlForGermanB2G = await invoice.exportXml('xrechnung');
|
|
282
|
+
```
|
|
415
283
|
|
|
416
|
-
##
|
|
284
|
+
## Module layout
|
|
417
285
|
|
|
418
|
-
|
|
419
|
-
-
|
|
420
|
-
-
|
|
421
|
-
-
|
|
422
|
-
- **ISO 3166** - Country codes
|
|
423
|
-
- **UN/ECE Rec 20** - Units of measure
|
|
424
|
-
- **ISO 6523** - Organization identifiers
|
|
286
|
+
- `ts/`: main published API and implementation
|
|
287
|
+
- `ts_install/`: install-time resource bootstrap and download helpers
|
|
288
|
+
- `assets_downloaded/`: downloaded validation resources
|
|
289
|
+
- `test/`: corpus-heavy validation, format, PDF, performance, and security coverage
|
|
425
290
|
|
|
426
291
|
## License and Legal Information
|
|
427
292
|
|
|
428
|
-
This repository contains open-source code
|
|
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.
|
|
429
294
|
|
|
430
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.
|
|
431
296
|
|
|
432
297
|
### Trademarks
|
|
433
298
|
|
|
434
|
-
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 and are not included within the scope of the MIT license granted herein.
|
|
299
|
+
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.
|
|
300
|
+
|
|
301
|
+
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.
|
|
435
302
|
|
|
436
303
|
### Company Information
|
|
437
304
|
|
|
438
305
|
Task Venture Capital GmbH
|
|
439
|
-
Registered at District
|
|
306
|
+
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
440
307
|
|
|
441
|
-
For any legal inquiries or
|
|
308
|
+
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
|
442
309
|
|
|
443
|
-
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.
|
|
310
|
+
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.
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@fin.cx/einvoice',
|
|
6
|
-
version: '5.
|
|
6
|
+
version: '5.2.0',
|
|
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
|
}
|