{"_id":"@canopynexus/factur-x","name":"@canopynexus/factur-x","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@canopynexus/factur-x","version":"0.1.0","description":"Create, verify and extract Factur-X / ZUGFeRD (EN 16931) electronic invoices — hybrid PDF+XML or plain CII XML.","keywords":["factur-x","zugferd","en16931","e-invoice","einvoicing","invoice","cii","pdf"],"homepage":"https://github.com/canopynexus/factur-x#readme","bugs":{"url":"https://github.com/canopynexus/factur-x/issues"},"repository":{"type":"git","url":"git+https://github.com/canopynexus/factur-x.git"},"license":"MIT","author":{"name":"Canopy Nexus Ltd"},"type":"module","engines":{"node":">=20"},"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"bin":{"facturx":"bin/facturx.mjs"},"scripts":{"build":"vite build && npm run build:types","build:types":"node node_modules/typescript7/lib/tsc.js -p tsconfig.build.json","check-types":"node node_modules/typescript7/lib/tsc.js --noEmit","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","lint":"eslint .","format":"prettier --write .","format:check":"prettier --check .","examples":"node ./bin/facturx.mjs batch examples --out-dir out"},"dependencies":{"fast-xml-parser":"^5.10.1","pdf-lib":"^1.17.1"},"devDependencies":{"@eslint/js":"^10.0.0","@types/node":"^24.0.0","@vitest/coverage-v8":"^4.1.10","eslint":"^10.7.0","eslint-config-prettier":"^10.1.8","prettier":"^3.9.6","typescript":"~6.0.2","typescript-eslint":"^8.65.0","typescript7":"npm:typescript@~7.0.2","vite":"^8.1.5","vitest":"^4.1.10"},"gitHead":"5217a1a04d9e9279c308cc80826a004ce489c1ce","_id":"@canopynexus/factur-x@0.1.0","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-gliYUmCCahnWWnfzLqtkZQkxI538ZscQIE8Fa9qBR3tf/eGyoFZpOVIiGV7XjZWUgsymOnX3nR33TqmI/ww0xw==","shasum":"883f22438f6af9dafa995ca3dc809d6f35804627","tarball":"https://registry.npmjs.org/@canopynexus/factur-x/-/factur-x-0.1.0.tgz","fileCount":42,"unpackedSize":274049,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDplbGR2OL/4HiGQCNzDaHrwJx4+3AkQ1jg7AOkHJe9twIhAMVVfSAIPJayfhwuxD25dLrto0yXWMoPKGesQPo4n+zC"}]},"_npmUser":{"name":"tsamaya","email":"arferrand@gmail.com"},"directories":{},"maintainers":[{"name":"tsamaya","email":"arferrand@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/factur-x_0.1.0_1784826203701_0.543819563770741"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-23T17:03:23.577Z","0.1.0":"2026-07-23T17:03:23.875Z","modified":"2026-07-23T17:03:24.460Z"},"maintainers":[{"name":"tsamaya","email":"arferrand@gmail.com"}],"description":"Create, verify and extract Factur-X / ZUGFeRD (EN 16931) electronic invoices — hybrid PDF+XML or plain CII XML.","homepage":"https://github.com/canopynexus/factur-x#readme","keywords":["factur-x","zugferd","en16931","e-invoice","einvoicing","invoice","cii","pdf"],"repository":{"type":"git","url":"git+https://github.com/canopynexus/factur-x.git"},"author":{"name":"Canopy Nexus Ltd"},"bugs":{"url":"https://github.com/canopynexus/factur-x/issues"},"license":"MIT","readme":"# Factur-x\n\nCreate, verify and extract **Factur-X / ZUGFeRD** electronic invoices in TypeScript — the Franco-German hybrid e-invoicing standard built on **EN 16931**, where a human-readable PDF carries the machine-readable UN/CEFACT Cross Industry Invoice (CII) XML inside it.\n\nMaintained by [Canopy Nexus Ltd](https://canopynexus.com) as an open-source implementation of the standard now rolling out across Europe.\n\n- **Factur-X** — official specification: <https://fnfe-mpe.org/factur-x/>\n- **ZUGFeRD** — the German twin standard: <https://www.ferd-net.de/standards/zugferd/>\n- **EN 16931** — the European semantic model: <https://ec.europa.eu/digital-building-blocks/sites/spaces/DIGITAL/pages/467108926/Compliance+with+eInvoicing+standard>\n\n## Install\n\n```sh\nnpm install @canopynexus/factur-x\n```\n\nShips ESM and CJS bundles with TypeScript declarations. Node ≥ 20.\n\n## API\n\nThree functions: `create`, `verify`, `extract`.\n\n### create\n\n```ts\nimport { create } from '@canopynexus/factur-x';\n\nconst invoice = {\n  number: 'FA-2026-0001',\n  issueDate: '2026-07-01',\n  currency: 'EUR',\n  seller: {\n    name: 'Reblochon SARL',\n    vatId: 'FR32532198476',\n    legalId: { value: '532198476', scheme: '0002' }, // SIREN\n    address: {\n      line1: '12 route des Alpages',\n      postCode: '74230',\n      city: 'Thônes',\n      countryCode: 'FR',\n    },\n  },\n  buyer: {\n    name: 'Acme France SAS',\n    vatId: 'FR90410108494',\n    address: { line1: '1 rue de la Paix', postCode: '75002', city: 'Paris', countryCode: 'FR' },\n  },\n  lines: [\n    {\n      name: 'Reblochon fermier AOP',\n      quantity: 40,\n      unit: 'H87', // piece\n      unitPrice: 6.9,\n      vat: { categoryCode: 'S', rate: 5.5 },\n    },\n  ],\n  payment: { iban: 'FR7630006000011234567890189', dueDate: '2026-08-01' },\n};\n\n// Hybrid PDF with embedded factur-x.xml (the default)\nconst { pdf, xml } = await create(invoice, { level: 'en16931', locale: 'fr-FR' });\n\n// XML only\nconst { xml: xmlOnly } = await create(invoice, { level: 'basic', format: 'xml' });\n```\n\nThe invoice object is validated against the requested level before anything is generated; a `FacturXValidationError` lists every problem at once. Totals and the VAT breakdown (BG-23) are computed from the lines — if you also pass `totals`, they are cross-checked.\n\n### verify\n\nAccepts CII XML (string or bytes) **or** a hybrid PDF. Finds the XML, checks it is a Factur-X invoice, and reports the profile level.\n\n```ts\nimport { verify } from '@canopynexus/factur-x';\n\nconst result = await verify(await readFile('invoice.pdf'));\nif (result.valid) {\n  console.log(result.level); // 'minimum' | 'basicwl' | 'basic' | 'en16931' | 'extended'\n  console.log(result.guidelineId); // e.g. 'urn:cen.eu:en16931:2017'\n  console.log(result.source); // 'pdf' or 'xml'\n} else {\n  console.error(result.errors); // what is missing or inconsistent\n}\n```\n\nVerification checks the guideline URN (BT-24), the mandatory terms of the detected profile, and arithmetic consistency of the monetary summation, line totals and VAT breakdown (BR-CO-10/14/15/16).\n\n### extract\n\n```ts\nimport { extract } from '@canopynexus/factur-x';\n\nconst { xml, filename } = await extract(await readFile('invoice.pdf'));\n```\n\nUnderstands `factur-x.xml` and the ZUGFeRD attachment names.\n\n## Factur-X levels\n\n| Level      | Guideline URN (BT-24)                                             | Contents                                 |\n| ---------- | ----------------------------------------------------------------- | ---------------------------------------- |\n| `minimum`  | `urn:factur-x.eu:1p0:minimum`                                     | Identification + totals only             |\n| `basicwl`  | `urn:factur-x.eu:1p0:basicwl`                                     | Full header, VAT breakdown, **no** lines |\n| `basic`    | `urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic`     | BASIC WL + invoice lines                 |\n| `en16931`  | `urn:cen.eu:en16931:2017`                                         | The full EN 16931 semantic model         |\n| `extended` | `urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended` | EN 16931 + Factur-X extensions           |\n\nThe same invoice object can be emitted at any level — `basicwl` uses the lines to compute the VAT breakdown but leaves them out of the XML.\n\n## Command line\n\n```sh\nnpm run build   # once — the CLI runs from dist/\n\nnpx facturx create examples/en16931-domestic-vat.json          # → .pdf next to the JSON\nnpx facturx create invoice.json --level basic --format xml -o invoice.xml\nnpx facturx verify invoice.pdf\nnpx facturx extract invoice.pdf -o factur-x.xml\nnpx facturx batch examples --out-dir out                       # generate every example\n```\n\nInvoice JSON files may embed defaults under `\"$options\"` (`level`, `format`, `locale`); command-line flags override them.\n\n## Examples\n\nThe [examples/](examples/) directory covers the VAT situations European sellers actually meet - starring **Reblochon SARL**, a Haute-Savoie cheese maker, invoicing various **Acme** entities:\n\n| Example                                                         | Scenario                                             | Level      | Currency |\n| --------------------------------------------------------------- | ---------------------------------------------------- | ---------- | -------- |\n| [minimum.json](examples/minimum.json)                           | Totals-only skeleton invoice                         | `minimum`  | EUR      |\n| [basicwl-services.json](examples/basicwl-services.json)         | Monthly service, no lines in XML                     | `basicwl`  | EUR      |\n| [basic-domestic-vat.json](examples/basic-domestic-vat.json)     | Domestic sale, reduced food VAT 5.5 %                | `basic`    | EUR      |\n| [en16931-domestic-vat.json](examples/en16931-domestic-vat.json) | Mixed 5.5 % / 20 % rates, discount terms             | `en16931`  | EUR      |\n| [extended-full.json](examples/extended-full.json)               | Deposit received, prepaid amount deducted            | `extended` | EUR      |\n| [intra-eu-supply.json](examples/intra-eu-supply.json)           | Intra-EU supply to Germany, category K, VATEX-EU-IC  | `en16931`  | EUR      |\n| [export-outside-eu.json](examples/export-outside-eu.json)       | Export to the USA, category G, billed in dollars     | `en16931`  | USD      |\n| [export-uk-gbp.json](examples/export-uk-gbp.json)               | Post-Brexit export to the UK, billed in sterling     | `en16931`  | GBP      |\n| [non-vat-franchise.json](examples/non-vat-franchise.json)       | Seller under the French _franchise en base_ (no VAT) | `en16931`  | EUR      |\n\n## Currency display\n\nAmounts on the PDF are formatted with `Intl.NumberFormat`, so the symbol lands where the locale puts it — leading or trailing, whatever the currency:\n\n```ts\nimport { formatAmount } from '@canopynexus/factur-x';\n\nformatAmount(1234.5, 'GBP', 'en-GB'); // £1,234.50\nformatAmount(1234.5, 'EUR', 'fr-FR'); // 1 234,50 €\nformatAmount(1234.5, 'USD', 'en-US'); // $1,234.50\n```\n\nPass `locale` in `CreateOptions` (default `en-GB`) to control how the PDF renders amounts.\n\n## Compliance notes & roadmap\n\nThe generated PDF embeds the XML the way the Factur-X specification requires: an `AFRelationship`-tagged embedded file referenced from the catalog's `/AF` array, plus XMP metadata declaring PDF/A-3 identification and the Factur-X extension schema (`fx:DocumentFileName`, `fx:ConformanceLevel`, …).\n\nHonest limitations of this first version, and where it goes next:\n\n- **PDF/A-3 completeness** — the standard-14 fonts are not embedded and there is no ICC\n  output intent yet, so strict PDF/A-3 validators (veraPDF) will flag the file even though every consuming platform can read the invoice. Full PDF/A-3b output is the top roadmap item.\n- **Schematron validation** — `verify` enforces structure, profile membership and the\n  arithmetic business rules, not the complete EN 16931 Schematron rule set. Wiring in the official rules is planned.\n- **Invoice styling** — the PDF layout is deliberately simple; a CSS-like theming layer so users can customise their invoices is planned.\n- **XRechnung / UBL** — detection hooks exist for guideline URNs; full support later.\n\n## Development\n\n```sh\nnpm install\nnpm test              # vitest\nnpm run check-types   # TypeScript 7 (native) — see note below\nnpm run lint          # ESLint 10 + typescript-eslint\nnpm run build         # vite (ESM + CJS) + d.ts via TypeScript 7\nnpm run examples      # regenerate out/ from examples/\n```\n\n**TypeScript toolchain note:** compiling, type-checking and declaration emit run on **TypeScript 7** (the native compiler), installed under the `typescript7` alias. The root `typescript` dependency is pinned to 6.x only because `typescript-eslint` (and editor tooling) still needs the JS compiler API, which the native package no longer ships. When\ntypescript-eslint supports TS 7, the 6.x shim goes away.\n\n## License\n\nMIT © Canopy Nexus Ltd\n\nA copy of the license is available in the repository's [LICENSE](LICENSE.md) file.\n","readmeFilename":"README.md","_rev":"1-ca3bedc723a56f1be022c702c43d1868"}