One npm package per file format, organised by format and never by country. Factur-X is French and German, UBL is universal, camt.053 is European: a format is not a country. Which formats a country uses is said by its pack — its e-invoicing profile, its bank statement formats, its declaration — never by the shape of this directory.
Each package here:
- is MIT, with its own
LICENSEfile, so it can be used anywhere, including inside other software; - imports nothing from the core — not
@ekwo-ai/core, not the schema, not another library; - declares the flat row shapes it reads or returns in its own types, so any book-keeping system that can produce those columns can use it;
- returns what does not add up in
violations[], and never corrects it.
What is here
Written from the ledger. They read the rows the core's reports return —
financial_statement(), vat_return(), ec_sales_list(), fec_lines(), the
document_* views — and produce the bytes and the file name an administration
expects:
| Package | Format |
|---|---|
fec |
The French fichier des écritures comptables |
xbrl-cbso |
XBRL annual accounts, NBB / CBSO taxonomy |
vat-consignment |
A periodic VAT return, written from the figures it was filed with |
intra-consignment, des, ecdf, vd |
Four recapitulative statements of European Union supplies, from the same rows of ec_sales_list() |
Electronic invoices, written and read. Each writes the file of a posted
invoice and lists every published rule it breaks by its identifier; each also
reads a received invoice into the same ReceivedInvoice shape — parties,
dates, lines, VAT breakdown, totals as exact decimal text, attachments — so a
received invoice becomes a purchase draft the same way whichever syntax carried
it.
| Package | Format |
|---|---|
peppol-ubl |
Peppol BIS Billing 3.0 (UBL 2.1), with participant identifiers checked offline |
factur-x |
Factur-X and ZUGFeRD: EN 16931 CII XML, embedded in and extracted from a PDF/A-3 |
Electronic invoices cleared before they are issued. An administration that validates every invoice before it is the taxpayer's gets the document from the same rows; signing it, submitting it and keeping the identifier the administration returns belong to the host:
| Package | Format |
|---|---|
myinvois |
The Malaysian MyInvois e-Invoice of LHDNM (UBL 2.1, JSON or XML): invoices, credit, debit and refund notes, the supplier's or self-billed |
Invoicing records, written. An administration that wants every invoice recorded as it is issued, chained to the one before, gets the record from the same rows; keeping the chain and sending the record belong to the host:
| Package | Format |
|---|---|
verifactu |
The Spanish VERI*FACTU registro de facturación, with its chained SHA-256 fingerprint and the URL of its QR code |
Bank statements, read. They return statements and lines under the same
field names, which is what import_bank_statement() takes:
Books kept elsewhere, read. They return accounts, parties, entries and an
opening balance under the same names, which is what import_books() takes once
the codes are translated into a company's chart. They are named after the file,
never after the software that writes it:
| Package | Format |
|---|---|
trial-balance |
A trial balance as CSV, and the open items beside it |
journal-items |
The lines of every entry, exported as CSV from a ledger kept as a table of lines |
journal-report |
A journal report or general ledger detail saved as CSV |
transaction-journal |
A transaction journal saved as CSV |
xaf |
XML Audit File Financial, versions 3.2 and 4.0 |
fec |
The FEC, read back with readFec() |
A file that comes from outside is treated as untrusted until read: the XML readers refuse DTDs and external entities and bound size and depth, and the fixed-width and CSV readers take the encoding they are told and never guess it.
Why no shared abstraction
There is no Filing interface, no plugin registry and no common xml
package. Two formats that look alike are two formats: the four recapitulative
statements read the same rows and still disagree on lines, columns, number
formats and how a VAT number is written. Each package says, in its README,
which official pages the format was read from.
Invoices, drawn. It renders the visual PDF of a sale invoice or credit note
from the rows of the document_* views, PDF/A-3b, with no country in its
layout. A Factur-X PDF is made by handing it embedFacturX:
| Package | Format |
|---|---|
invoice-pdf |
The PDF of an invoice or credit note, PDF/A-3b, fonts embedded |
tests/formats.test.ts enforces the licence, the isolation and the
dependencies of every package in this directory, and tests/ carries an
end-to-end test per package, from a country pack's year of books through the
real engine into the file.