v1.0.0
15 Sep 2026First release.
Added
encodeInvoice()for the Saudi ZATCA QR payload, phase one tags 1–5 and phase two tags 6–9, verified against the ASCII and Arabic vectors published by the reference implementation the Saudi market uses.decodeInvoice()andisZatcaPayload()— reading a payload back into its fields, which no other package in this space does.check()with twelve reason codes: missing and empty tags, values past the 255 bytes a length field holds, VAT number shape, timestamp format and future dates, amount format and sign, VAT exceeding the total, VAT implausible for a given rate, and an incomplete phase-two stamp.describe()turns one into a sentence andMESSAGESholds the wording for translation.- Byte-correct TLV throughout: the length field is the UTF-8 byte count, never the character count, which is what makes an Arabic seller name readable.
- A
TlvErrornaming the tag when a value is too long for a one-byte length, rather than wrapping silently. formatAmount()andformatTimestamp(): two decimals in ASCII digits with no separators, and an ISO 8601 string passed through untouched so a signed timestamp is never invalidated by reformatting.checkVatNumber()on its own, which verifies the fifteen-digit shape beginning and ending with 3 — all that Saudi Arabia publishes a rule for.- Base64 implemented directly rather than through
btoaorBuffer, so the package behaves the same in a browser, in Node and in a worker with no branch and no type definitions. - Eleven shared test vectors in
tests/fixtures/vectors.json, generated byscripts/vectors.mjs, covering both payload bytes and expected validation problems — ready for a PHP twin to be held to the same answers. - 2.6 kB gzip, zero dependencies.