@stll/stdnum 0.0.1 → 1.0.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/LICENSE +1 -5
- package/README.md +28 -4
- package/dist/_checksums/mod112.js +5 -5
- package/dist/_checksums/mod112.js.map +1 -1
- package/dist/_util/generate.d.ts +13 -1
- package/dist/_util/generate.js +23 -1
- package/dist/_util/generate.js.map +1 -1
- package/dist/ad/mod.d.ts +3 -2
- package/dist/ad/nrt.js +3 -2
- package/dist/ad/nrt.js.map +1 -1
- package/dist/ae/eid.d.ts +0 -1
- package/dist/ae/mod.d.ts +3 -2
- package/dist/ai/mod.d.ts +3 -2
- package/dist/al/mod.d.ts +3 -2
- package/dist/am/mod.d.ts +3 -2
- package/dist/ar/cbu.d.ts +0 -1
- package/dist/ar/cbu.js +1 -1
- package/dist/ar/cbu.js.map +1 -1
- package/dist/ar/cuit.d.ts +0 -1
- package/dist/ar/cuit.js +12 -12
- package/dist/ar/cuit.js.map +1 -1
- package/dist/ar/mod.d.ts +3 -2
- package/dist/at/mod.d.ts +3 -2
- package/dist/at/tin.d.ts +0 -1
- package/dist/at/uid.d.ts +0 -1
- package/dist/at/vnr.d.ts +3 -2
- package/dist/at/vnr.js +20 -3
- package/dist/at/vnr.js.map +1 -1
- package/dist/au/abn.d.ts +0 -1
- package/dist/au/acn.d.ts +0 -1
- package/dist/au/mod.d.ts +3 -2
- package/dist/au/tfn.d.ts +0 -1
- package/dist/az/mod.d.ts +3 -2
- package/dist/az/voen.d.ts +0 -1
- package/dist/az/voen.js.map +1 -1
- package/dist/ba/jmbg.d.ts +1 -2
- package/dist/ba/jmbg.js +1 -0
- package/dist/ba/jmbg.js.map +1 -1
- package/dist/ba/mod.d.ts +3 -2
- package/dist/bd/mod.d.ts +3 -2
- package/dist/bd/nid.js +10 -11
- package/dist/bd/nid.js.map +1 -1
- package/dist/be/bis.d.ts +0 -1
- package/dist/be/mod.d.ts +3 -2
- package/dist/be/nn.d.ts +0 -1
- package/dist/be/vat.d.ts +0 -1
- package/dist/bg/egn.d.ts +1 -2
- package/dist/bg/egn.js +10 -3
- package/dist/bg/egn.js.map +1 -1
- package/dist/bg/mod.d.ts +3 -2
- package/dist/bg/pnf.d.ts +0 -1
- package/dist/bg/vat.d.ts +0 -1
- package/dist/bh/cpr.d.ts +3 -2
- package/dist/bh/cpr.js +8 -2
- package/dist/bh/cpr.js.map +1 -1
- package/dist/bh/mod.d.ts +3 -2
- package/dist/bic.js +13 -15
- package/dist/bic.js.map +1 -1
- package/dist/br/cnpj.d.ts +0 -1
- package/dist/br/cpf.d.ts +0 -1
- package/dist/br/mod.d.ts +3 -2
- package/dist/by/mod.d.ts +3 -2
- package/dist/by/unp.d.ts +0 -1
- package/dist/by/unp.js +6 -3
- package/dist/by/unp.js.map +1 -1
- package/dist/bz/mod.d.ts +3 -2
- package/dist/bz/tin.d.ts +3 -2
- package/dist/bz/tin.js +9 -1
- package/dist/bz/tin.js.map +1 -1
- package/dist/ca/bn.d.ts +0 -1
- package/dist/ca/mod.d.ts +3 -2
- package/dist/ca/sin.d.ts +0 -1
- package/dist/ch/mod.d.ts +3 -2
- package/dist/ch/ssn.d.ts +0 -1
- package/dist/ch/uid.d.ts +0 -1
- package/dist/ch/vat.d.ts +0 -1
- package/dist/cl/mod.d.ts +3 -2
- package/dist/cl/rut.d.ts +0 -1
- package/dist/cl/rut.js +1 -1
- package/dist/cl/rut.js.map +1 -1
- package/dist/cn/mod.d.ts +3 -2
- package/dist/cn/ric.d.ts +1 -2
- package/dist/cn/ric.js +1 -0
- package/dist/cn/ric.js.map +1 -1
- package/dist/cn/uscc.d.ts +0 -1
- package/dist/cn/uscc.js +7 -6
- package/dist/cn/uscc.js.map +1 -1
- package/dist/co/mod.d.ts +3 -2
- package/dist/co/nit.d.ts +0 -1
- package/dist/co/nit.js +4 -1
- package/dist/co/nit.js.map +1 -1
- package/dist/cr/cpf.js +4 -3
- package/dist/cr/cpf.js.map +1 -1
- package/dist/cr/mod.d.ts +3 -2
- package/dist/creditcard.d.ts +0 -1
- package/dist/cu/mod.d.ts +3 -2
- package/dist/cu/ni.d.ts +4 -3
- package/dist/cu/ni.js +11 -1
- package/dist/cu/ni.js.map +1 -1
- package/dist/cy/mod.d.ts +3 -2
- package/dist/cy/vat.d.ts +0 -1
- package/dist/cz/dic.d.ts +0 -1
- package/dist/cz/ico.d.ts +0 -1
- package/dist/cz/mod.d.ts +3 -2
- package/dist/cz/rc.d.ts +1 -2
- package/dist/cz/rc.js +33 -8
- package/dist/cz/rc.js.map +1 -1
- package/dist/de/handelsreg.js +9 -9
- package/dist/de/handelsreg.js.map +1 -1
- package/dist/de/idnr.d.ts +0 -1
- package/dist/de/idnr.js.map +1 -1
- package/dist/de/mod.d.ts +3 -2
- package/dist/de/stnr.d.ts +0 -1
- package/dist/de/stnr.js.map +1 -1
- package/dist/de/svnr.d.ts +0 -1
- package/dist/de/svnr.js +2 -2
- package/dist/de/svnr.js.map +1 -1
- package/dist/de/vat.d.ts +0 -1
- package/dist/dk/cpr.d.ts +4 -3
- package/dist/dk/cpr.js +12 -2
- package/dist/dk/cpr.js.map +1 -1
- package/dist/dk/cvr.d.ts +0 -1
- package/dist/dk/mod.d.ts +3 -2
- package/dist/dk/vat.d.ts +0 -1
- package/dist/do/mod.d.ts +3 -2
- package/dist/do/rnc.d.ts +0 -1
- package/dist/do/rnc.js +1 -1
- package/dist/do/rnc.js.map +1 -1
- package/dist/ec/mod.d.ts +3 -2
- package/dist/ec/ruc.d.ts +0 -1
- package/dist/ec/ruc.js +1 -1
- package/dist/ec/ruc.js.map +1 -1
- package/dist/ee/ik.d.ts +1 -2
- package/dist/ee/ik.js +12 -4
- package/dist/ee/ik.js.map +1 -1
- package/dist/ee/mod.d.ts +3 -2
- package/dist/ee/registrikood.d.ts +0 -1
- package/dist/ee/registrikood.js +8 -7
- package/dist/ee/registrikood.js.map +1 -1
- package/dist/ee/vat.d.ts +0 -1
- package/dist/eg/mod.d.ts +3 -2
- package/dist/es/cif.d.ts +0 -1
- package/dist/es/cif.js +2 -2
- package/dist/es/cif.js.map +1 -1
- package/dist/es/dni.d.ts +0 -1
- package/dist/es/mod.d.ts +3 -2
- package/dist/es/nie.d.ts +0 -1
- package/dist/es/nie.js +13 -13
- package/dist/es/nie.js.map +1 -1
- package/dist/es/nss.d.ts +0 -1
- package/dist/es/vat.d.ts +0 -1
- package/dist/eu/mod.d.ts +3 -2
- package/dist/eu/vat.d.ts +3 -2
- package/dist/eu/vat.js +43 -2
- package/dist/eu/vat.js.map +1 -1
- package/dist/fi/hetu.d.ts +4 -3
- package/dist/fi/hetu.js +17 -2
- package/dist/fi/hetu.js.map +1 -1
- package/dist/fi/mod.d.ts +3 -2
- package/dist/fi/vat.d.ts +0 -1
- package/dist/fi/ytunnus.d.ts +0 -1
- package/dist/fr/mod.d.ts +3 -2
- package/dist/fr/nif.d.ts +0 -1
- package/dist/fr/nir.d.ts +1 -2
- package/dist/fr/nir.js +1 -0
- package/dist/fr/nir.js.map +1 -1
- package/dist/fr/siren.d.ts +0 -1
- package/dist/fr/siret.d.ts +0 -1
- package/dist/fr/tva.d.ts +0 -1
- package/dist/gb/mod.d.ts +3 -2
- package/dist/gb/nino.js +7 -7
- package/dist/gb/nino.js.map +1 -1
- package/dist/gb/sedol.d.ts +0 -1
- package/dist/gb/sedol.js +8 -7
- package/dist/gb/sedol.js.map +1 -1
- package/dist/gb/utr.d.ts +0 -1
- package/dist/gb/vat.d.ts +0 -1
- package/dist/ge/mod.d.ts +3 -2
- package/dist/gh/mod.d.ts +3 -2
- package/dist/gh/tin.d.ts +0 -1
- package/dist/gh/tin.js +9 -9
- package/dist/gh/tin.js.map +1 -1
- package/dist/gr/amka.d.ts +0 -1
- package/dist/gr/mod.d.ts +3 -2
- package/dist/gr/vat.d.ts +0 -1
- package/dist/gt/mod.d.ts +3 -2
- package/dist/gt/nit.d.ts +0 -1
- package/dist/gt/nit.js +5 -2
- package/dist/gt/nit.js.map +1 -1
- package/dist/hk/hkid.d.ts +0 -1
- package/dist/hk/hkid.js +1 -0
- package/dist/hk/hkid.js.map +1 -1
- package/dist/hk/mod.d.ts +3 -2
- package/dist/hr/mod.d.ts +3 -2
- package/dist/hr/vat.d.ts +0 -1
- package/dist/hu/mod.d.ts +3 -2
- package/dist/hu/vat.d.ts +0 -1
- package/dist/iban.d.ts +0 -1
- package/dist/id/mod.d.ts +3 -2
- package/dist/id/npwp.d.ts +0 -1
- package/dist/ie/mod.d.ts +3 -2
- package/dist/ie/pps.d.ts +0 -1
- package/dist/ie/vat.d.ts +0 -1
- package/dist/il/idnr.d.ts +0 -1
- package/dist/il/mod.d.ts +3 -2
- package/dist/in/aadhaar.d.ts +0 -1
- package/dist/in/gstin.d.ts +0 -1
- package/dist/in/gstin.js +3 -1
- package/dist/in/gstin.js.map +1 -1
- package/dist/in/mod.d.ts +3 -2
- package/dist/in/pan.js +2 -2
- package/dist/in/pan.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/iq/mod.d.ts +3 -2
- package/dist/ir/mod.d.ts +3 -2
- package/dist/ir/nid.d.ts +0 -1
- package/dist/is/kennitala.d.ts +0 -1
- package/dist/is/mod.d.ts +3 -2
- package/dist/isin.d.ts +0 -1
- package/dist/isin.js +9 -9
- package/dist/isin.js.map +1 -1
- package/dist/it/codicefiscale.d.ts +4 -3
- package/dist/it/codicefiscale.js +26 -2
- package/dist/it/codicefiscale.js.map +1 -1
- package/dist/it/iva.d.ts +0 -1
- package/dist/it/mod.d.ts +3 -2
- package/dist/jp/cn.d.ts +0 -1
- package/dist/jp/mod.d.ts +3 -2
- package/dist/jp/mynumber.d.ts +0 -1
- package/dist/kr/mod.d.ts +3 -2
- package/dist/kr/rrn.d.ts +4 -3
- package/dist/kr/rrn.js +13 -2
- package/dist/kr/rrn.js.map +1 -1
- package/dist/kw/civil.d.ts +6 -5
- package/dist/kw/civil.js +18 -3
- package/dist/kw/civil.js.map +1 -1
- package/dist/kw/mod.d.ts +3 -2
- package/dist/kz/iin.d.ts +1 -2
- package/dist/kz/iin.js +1 -0
- package/dist/kz/iin.js.map +1 -1
- package/dist/kz/mod.d.ts +3 -2
- package/dist/lei.d.ts +0 -1
- package/dist/li/mod.d.ts +3 -2
- package/dist/lk/mod.d.ts +3 -2
- package/dist/lk/nic.d.ts +4 -3
- package/dist/lk/nic.js +14 -2
- package/dist/lk/nic.js.map +1 -1
- package/dist/lt/asmens.d.ts +0 -1
- package/dist/lt/mod.d.ts +3 -2
- package/dist/lt/vat.d.ts +0 -1
- package/dist/lu/mod.d.ts +3 -2
- package/dist/lu/vat.d.ts +0 -1
- package/dist/luhn.d.ts +0 -1
- package/dist/luhn.js +7 -0
- package/dist/luhn.js.map +1 -1
- package/dist/lv/mod.d.ts +3 -2
- package/dist/lv/vat.d.ts +0 -1
- package/dist/lv/vat.js +39 -12
- package/dist/lv/vat.js.map +1 -1
- package/dist/ma/ice.d.ts +0 -1
- package/dist/ma/mod.d.ts +3 -2
- package/dist/mc/mod.d.ts +3 -2
- package/dist/mc/tva.d.ts +0 -1
- package/dist/md/idno.d.ts +0 -1
- package/dist/md/mod.d.ts +3 -2
- package/dist/me/mod.d.ts +3 -2
- package/dist/me/pib.d.ts +0 -1
- package/dist/mk/edb.d.ts +0 -1
- package/dist/mk/mod.d.ts +3 -2
- package/dist/mt/mod.d.ts +3 -2
- package/dist/mt/vat.d.ts +0 -1
- package/dist/mu/mod.d.ts +3 -2
- package/dist/mx/clabe.d.ts +0 -1
- package/dist/mx/curp.d.ts +4 -3
- package/dist/mx/curp.js +25 -3
- package/dist/mx/curp.js.map +1 -1
- package/dist/mx/mod.d.ts +3 -2
- package/dist/mx/rfc.d.ts +3 -2
- package/dist/mx/rfc.js +21 -2
- package/dist/mx/rfc.js.map +1 -1
- package/dist/my/mod.d.ts +3 -2
- package/dist/my/nric.d.ts +4 -3
- package/dist/my/nric.js +16 -2
- package/dist/my/nric.js.map +1 -1
- package/dist/ng/mod.d.ts +3 -2
- package/dist/ni/mod.d.ts +3 -2
- package/dist/ni/ruc.d.ts +0 -1
- package/dist/nl/bsn.d.ts +0 -1
- package/dist/nl/mod.d.ts +3 -2
- package/dist/nl/vat.d.ts +0 -1
- package/dist/nl/vat.js +9 -43
- package/dist/nl/vat.js.map +1 -1
- package/dist/no/fodselsnummer.d.ts +1 -2
- package/dist/no/fodselsnummer.js +1 -0
- package/dist/no/fodselsnummer.js.map +1 -1
- package/dist/no/mod.d.ts +3 -2
- package/dist/no/mva.d.ts +0 -1
- package/dist/no/orgnr.d.ts +0 -1
- package/dist/nz/ird.d.ts +0 -1
- package/dist/nz/ird.js +2 -2
- package/dist/nz/ird.js.map +1 -1
- package/dist/nz/mod.d.ts +3 -2
- package/dist/pa/mod.d.ts +3 -2
- package/dist/pa/ruc.d.ts +0 -1
- package/dist/pa/ruc.js +3 -1
- package/dist/pa/ruc.js.map +1 -1
- package/dist/patterns.d.ts +1 -4
- package/dist/patterns.js +80 -23
- package/dist/patterns.js.map +1 -1
- package/dist/pe/mod.d.ts +3 -2
- package/dist/pe/ruc.d.ts +0 -1
- package/dist/pe/ruc.js +9 -9
- package/dist/pe/ruc.js.map +1 -1
- package/dist/ph/mod.d.ts +3 -2
- package/dist/pk/cnic.js.map +1 -1
- package/dist/pk/mod.d.ts +3 -2
- package/dist/pl/mod.d.ts +3 -2
- package/dist/pl/nip.d.ts +0 -1
- package/dist/pl/pesel.d.ts +1 -2
- package/dist/pl/pesel.js +1 -0
- package/dist/pl/pesel.js.map +1 -1
- package/dist/pl/regon.d.ts +0 -1
- package/dist/pt/cc.d.ts +0 -1
- package/dist/pt/cc.js +6 -4
- package/dist/pt/cc.js.map +1 -1
- package/dist/pt/mod.d.ts +3 -2
- package/dist/pt/vat.d.ts +0 -1
- package/dist/ro/cnp.d.ts +1 -2
- package/dist/ro/cnp.js +1 -0
- package/dist/ro/cnp.js.map +1 -1
- package/dist/ro/mod.d.ts +3 -2
- package/dist/ro/vat.d.ts +0 -1
- package/dist/rs/mod.d.ts +3 -2
- package/dist/rs/pib.d.ts +0 -1
- package/dist/ru/inn.d.ts +0 -1
- package/dist/ru/inn.js +1 -1
- package/dist/ru/inn.js.map +1 -1
- package/dist/ru/mod.d.ts +3 -2
- package/dist/se/mod.d.ts +3 -2
- package/dist/se/orgnr.d.ts +0 -1
- package/dist/se/personnummer.d.ts +1 -2
- package/dist/se/personnummer.js +1 -0
- package/dist/se/personnummer.js.map +1 -1
- package/dist/se/vat.d.ts +0 -1
- package/dist/sg/mod.d.ts +3 -2
- package/dist/sg/uen.d.ts +0 -1
- package/dist/sg/uen.js +46 -55
- package/dist/sg/uen.js.map +1 -1
- package/dist/si/emso.d.ts +1 -2
- package/dist/si/emso.js +17 -4
- package/dist/si/emso.js.map +1 -1
- package/dist/si/mod.d.ts +3 -2
- package/dist/si/vat.d.ts +0 -1
- package/dist/sk/dic.d.ts +0 -1
- package/dist/sk/ico.d.ts +0 -1
- package/dist/sk/mod.d.ts +3 -2
- package/dist/sk/rc.d.ts +4 -5
- package/dist/sk/rc.js +5 -2
- package/dist/sk/rc.js.map +1 -1
- package/dist/th/mod.d.ts +3 -2
- package/dist/th/tin.d.ts +0 -1
- package/dist/tr/mod.d.ts +3 -2
- package/dist/tr/tckimlik.d.ts +0 -1
- package/dist/tr/vkn.d.ts +0 -1
- package/dist/tw/mod.d.ts +3 -2
- package/dist/tw/ubn.d.ts +0 -1
- package/dist/tw/ubn.js +1 -1
- package/dist/tw/ubn.js.map +1 -1
- package/dist/types.d.ts +35 -22
- package/dist/ua/edrpou.d.ts +0 -1
- package/dist/ua/edrpou.js +4 -1
- package/dist/ua/edrpou.js.map +1 -1
- package/dist/ua/mod.d.ts +3 -2
- package/dist/us/ein.js +87 -87
- package/dist/us/ein.js.map +1 -1
- package/dist/us/itin.js +3 -4
- package/dist/us/itin.js.map +1 -1
- package/dist/us/mod.d.ts +3 -2
- package/dist/us/rtn.d.ts +0 -1
- package/dist/us/rtn.js +8 -5
- package/dist/us/rtn.js.map +1 -1
- package/dist/uy/mod.d.ts +3 -2
- package/dist/uy/rut.d.ts +0 -1
- package/dist/uy/rut.js +1 -1
- package/dist/uy/rut.js.map +1 -1
- package/dist/ve/mod.d.ts +3 -2
- package/dist/ve/rif.d.ts +0 -1
- package/dist/ve/rif.js +11 -11
- package/dist/ve/rif.js.map +1 -1
- package/dist/vn/mod.d.ts +3 -2
- package/dist/vn/mst.d.ts +0 -1
- package/dist/za/idnr.d.ts +1 -2
- package/dist/za/idnr.js +1 -0
- package/dist/za/idnr.js.map +1 -1
- package/dist/za/mod.d.ts +3 -2
- package/package.json +18 -15
- package/src/_checksums/mod112.ts +7 -6
- package/src/_util/generate.ts +38 -0
- package/src/ad/nrt.ts +12 -4
- package/src/ar/cbu.ts +2 -2
- package/src/ar/cuit.ts +15 -7
- package/src/at/vnr.ts +26 -4
- package/src/az/voen.ts +2 -0
- package/src/ba/jmbg.ts +2 -1
- package/src/bd/nid.ts +4 -4
- package/src/bg/egn.ts +12 -4
- package/src/bh/cpr.ts +10 -1
- package/src/bic.ts +19 -17
- package/src/by/unp.ts +9 -4
- package/src/bz/tin.ts +12 -1
- package/src/cl/rut.ts +4 -2
- package/src/cn/ric.ts +4 -1
- package/src/cn/uscc.ts +20 -8
- package/src/co/nit.ts +6 -2
- package/src/cr/cpf.ts +4 -3
- package/src/cu/ni.ts +22 -2
- package/src/cz/rc.ts +54 -23
- package/src/de/handelsreg.ts +14 -3
- package/src/de/idnr.ts +3 -0
- package/src/de/stnr.ts +4 -0
- package/src/de/svnr.ts +7 -2
- package/src/dk/cpr.ts +16 -2
- package/src/do/rnc.ts +2 -2
- package/src/ec/ruc.ts +2 -2
- package/src/ee/ik.ts +14 -4
- package/src/ee/registrikood.ts +4 -3
- package/src/es/cif.ts +2 -3
- package/src/es/nie.ts +10 -5
- package/src/eu/vat.ts +46 -1
- package/src/fi/hetu.ts +19 -2
- package/src/fr/nir.ts +2 -1
- package/src/gb/nino.ts +11 -10
- package/src/gb/sedol.ts +14 -12
- package/src/gh/tin.ts +4 -3
- package/src/gt/nit.ts +6 -3
- package/src/hk/hkid.ts +2 -1
- package/src/in/gstin.ts +3 -1
- package/src/in/pan.ts +8 -3
- package/src/index.ts +3 -0
- package/src/isin.ts +10 -4
- package/src/it/codicefiscale.ts +40 -2
- package/src/kr/rrn.ts +20 -2
- package/src/kw/civil.ts +25 -9
- package/src/kz/iin.ts +2 -1
- package/src/lk/nic.ts +24 -2
- package/src/luhn.ts +3 -0
- package/src/lv/vat.ts +46 -20
- package/src/mx/curp.ts +41 -5
- package/src/mx/rfc.ts +35 -4
- package/src/my/nric.ts +26 -2
- package/src/nl/vat.ts +11 -66
- package/src/no/fodselsnummer.ts +2 -1
- package/src/nz/ird.ts +4 -4
- package/src/pa/ruc.ts +32 -8
- package/src/patterns.ts +135 -28
- package/src/pe/ruc.ts +6 -7
- package/src/pk/cnic.ts +2 -0
- package/src/pl/pesel.ts +2 -1
- package/src/pt/cc.ts +6 -4
- package/src/ro/cnp.ts +2 -1
- package/src/ru/inn.ts +2 -2
- package/src/se/personnummer.ts +2 -1
- package/src/sg/uen.ts +37 -20
- package/src/si/emso.ts +30 -5
- package/src/sk/rc.ts +13 -4
- package/src/tw/ubn.ts +2 -2
- package/src/types.ts +37 -6
- package/src/ua/edrpou.ts +3 -2
- package/src/us/ein.ts +88 -88
- package/src/us/itin.ts +7 -8
- package/src/us/rtn.ts +16 -11
- package/src/uy/rut.ts +2 -2
- package/src/ve/rif.ts +11 -6
- package/src/za/idnr.ts +2 -1
package/src/lv/vat.ts
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PVN (Latvian VAT number).
|
|
3
3
|
*
|
|
4
|
-
* 11 digits.
|
|
5
|
-
* weights [9,1,4,8,3,10,2,5,7,6,1], sum % 11 === 3.
|
|
6
|
-
* Personal (first digit <= 3): 11-digit format only.
|
|
4
|
+
* 11 digits.
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* Individuals:
|
|
7
|
+
* - legacy personal codes: DDMMYY + century digit 0/1/2 + 4 digits
|
|
8
|
+
* - since 1 July 2017: codes start with 3, the second digit is 2-9,
|
|
9
|
+
* and the remaining digits are random
|
|
10
|
+
*
|
|
11
|
+
* Entities:
|
|
12
|
+
* - tax administration issued: 9XXXXXXXXXX
|
|
13
|
+
* - enterprise register issued: 4XXXXXXXXXX / 5XXXXXXXXXX
|
|
14
|
+
*
|
|
15
|
+
* Canonical sources:
|
|
16
|
+
* - OECD Latvia TIN sheet for the tax-facing formats
|
|
17
|
+
* - PMLP page documenting the post-2017 personal code
|
|
18
|
+
*
|
|
19
|
+
* These are the reasons we accept the new personal
|
|
20
|
+
* code shape (`3` + second digit `2-9`) without the
|
|
21
|
+
* legacy birth-date checksum, and why we reject
|
|
22
|
+
* legacy personal codes with century digits outside
|
|
23
|
+
* 0/1/2.
|
|
24
|
+
*
|
|
25
|
+
* @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Latvia-TIN.pdf
|
|
26
|
+
* @see https://www.pmlp.gov.lv/en/change-personal-identity-number
|
|
10
27
|
*/
|
|
11
28
|
|
|
12
29
|
import { weightedSum } from "#checksums/weighted-sum";
|
|
@@ -46,6 +63,9 @@ const validateBirthDate = (v: string): boolean => {
|
|
|
46
63
|
const month = Number(v.slice(2, 4));
|
|
47
64
|
const year2 = Number(v.slice(4, 6));
|
|
48
65
|
const century = Number(v[6]);
|
|
66
|
+
if (century < 0 || century > 2) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
49
69
|
const fullYear = 1800 + century * 100 + year2;
|
|
50
70
|
const date = new Date(fullYear, month - 1, day);
|
|
51
71
|
return (
|
|
@@ -69,9 +89,19 @@ const validate = (value: string): ValidateResult => {
|
|
|
69
89
|
"Latvian VAT number must contain only digits",
|
|
70
90
|
);
|
|
71
91
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
92
|
+
if (
|
|
93
|
+
v[0] === "3" &&
|
|
94
|
+
v[1] !== undefined &&
|
|
95
|
+
v[1] >= "2" &&
|
|
96
|
+
v[1] <= "9"
|
|
97
|
+
) {
|
|
98
|
+
// Since 1 July 2017, new personal codes start with 3
|
|
99
|
+
// and are syntactic identifiers only.
|
|
100
|
+
return { valid: true, compact: v };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const first = v[0];
|
|
104
|
+
if (first === "4" || first === "5" || first === "9") {
|
|
75
105
|
const sum = weightedSum(v, WEIGHTS, 11);
|
|
76
106
|
if (sum !== 3) {
|
|
77
107
|
return err(
|
|
@@ -79,15 +109,6 @@ const validate = (value: string): ValidateResult => {
|
|
|
79
109
|
"Latvian VAT number check digit mismatch",
|
|
80
110
|
);
|
|
81
111
|
}
|
|
82
|
-
} else if (v.startsWith("32")) {
|
|
83
|
-
// New-format personal code (from July 2017),
|
|
84
|
-
// no birth date; checksum only
|
|
85
|
-
if (!checkPersonal(v)) {
|
|
86
|
-
return err(
|
|
87
|
-
"INVALID_CHECKSUM",
|
|
88
|
-
"Latvian personal code check digit mismatch",
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
112
|
} else {
|
|
92
113
|
// Old-format personal code: first 6 digits encode
|
|
93
114
|
// birth date as DDMMYY, digit 7 encodes century
|
|
@@ -112,8 +133,12 @@ const format = (value: string): string =>
|
|
|
112
133
|
|
|
113
134
|
/** Generate a random valid Latvian VAT number. */
|
|
114
135
|
const generate = (): string => {
|
|
136
|
+
const entityPrefixes = ["4", "5", "9"] as const;
|
|
115
137
|
for (;;) {
|
|
116
|
-
const c =
|
|
138
|
+
const c =
|
|
139
|
+
randomInt(0, 1) === 0
|
|
140
|
+
? `3${randomInt(2, 9)}${randomDigits(9)}`
|
|
141
|
+
: `${entityPrefixes[randomInt(0, entityPrefixes.length - 1)] ?? "4"}${randomDigits(10)}`;
|
|
117
142
|
if (validate(c).valid) return c;
|
|
118
143
|
}
|
|
119
144
|
};
|
|
@@ -127,8 +152,9 @@ const vat: Validator = {
|
|
|
127
152
|
candidatePattern: "LV\\d{11}",
|
|
128
153
|
country: "LV",
|
|
129
154
|
entityType: "any",
|
|
130
|
-
sourceUrl:
|
|
131
|
-
|
|
155
|
+
sourceUrl:
|
|
156
|
+
"https://www.pmlp.gov.lv/en/change-personal-identity-number",
|
|
157
|
+
examples: ["40003521600", "32999999999"] as const,
|
|
132
158
|
compact,
|
|
133
159
|
format,
|
|
134
160
|
validate,
|
package/src/mx/curp.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { clean } from "#util/clean";
|
|
18
18
|
import { isValidDate } from "#util/date";
|
|
19
|
+
import { randomInt } from "#util/generate";
|
|
19
20
|
import { err } from "#util/result";
|
|
20
21
|
|
|
21
22
|
import type {
|
|
@@ -60,6 +61,8 @@ const STATE_CODES = new Set([
|
|
|
60
61
|
"ZS",
|
|
61
62
|
"NE", // Born abroad
|
|
62
63
|
]);
|
|
64
|
+
const STATE_CODE_LIST = [...STATE_CODES];
|
|
65
|
+
const LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
63
66
|
|
|
64
67
|
/**
|
|
65
68
|
* Alphabet for CURP check digit computation.
|
|
@@ -69,8 +72,8 @@ const STATE_CODES = new Set([
|
|
|
69
72
|
const ALPHABET = "0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ";
|
|
70
73
|
|
|
71
74
|
const CHAR_MAP = new Map<string, number>();
|
|
72
|
-
for (
|
|
73
|
-
CHAR_MAP.set(
|
|
75
|
+
for (const [i, ch] of [...ALPHABET].entries()) {
|
|
76
|
+
CHAR_MAP.set(ch, i);
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
const compact = (value: string): string =>
|
|
@@ -84,7 +87,9 @@ const compact = (value: string): string =>
|
|
|
84
87
|
const calcCheckDigit = (value: string): string => {
|
|
85
88
|
let sum = 0;
|
|
86
89
|
for (let i = 0; i < 17; i++) {
|
|
87
|
-
|
|
90
|
+
const ch = value[i];
|
|
91
|
+
if (ch === undefined) continue;
|
|
92
|
+
sum += (CHAR_MAP.get(ch) ?? 0) * (18 - i);
|
|
88
93
|
}
|
|
89
94
|
return String((10 - (sum % 10)) % 10);
|
|
90
95
|
};
|
|
@@ -126,6 +131,8 @@ const validate = (value: string): ValidateResult => {
|
|
|
126
131
|
const mm = Number(v.slice(6, 8));
|
|
127
132
|
const dd = Number(v.slice(8, 10));
|
|
128
133
|
|
|
134
|
+
// SAFETY: regex validation ensures v.length === 18.
|
|
135
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
129
136
|
const year = resolveCurpYear(yy, v[16]!);
|
|
130
137
|
if (!isValidDate(year, mm, dd)) {
|
|
131
138
|
return err(
|
|
@@ -170,6 +177,8 @@ const parse = (value: string): ParsedPersonId | null => {
|
|
|
170
177
|
const mm = Number(v.slice(6, 8));
|
|
171
178
|
const dd = Number(v.slice(8, 10));
|
|
172
179
|
|
|
180
|
+
// SAFETY: regex validation ensures v.length === 18.
|
|
181
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
173
182
|
const year = resolveCurpYear(yy, v[16]!);
|
|
174
183
|
|
|
175
184
|
const genderChar = v[10];
|
|
@@ -182,12 +191,37 @@ const parse = (value: string): ParsedPersonId | null => {
|
|
|
182
191
|
};
|
|
183
192
|
};
|
|
184
193
|
|
|
194
|
+
const randomLetter = (): string =>
|
|
195
|
+
LETTERS.charAt(randomInt(0, LETTERS.length - 1));
|
|
196
|
+
|
|
197
|
+
/** Generate a random valid CURP. */
|
|
198
|
+
const generate = (): string => {
|
|
199
|
+
const year = randomInt(1980, 2024);
|
|
200
|
+
const month = String(randomInt(1, 12)).padStart(2, "0");
|
|
201
|
+
const day = String(randomInt(1, 28)).padStart(2, "0");
|
|
202
|
+
const yy = String(year % 100).padStart(2, "0");
|
|
203
|
+
const gender = Math.random() < 0.5 ? "H" : "M";
|
|
204
|
+
const state =
|
|
205
|
+
STATE_CODE_LIST[
|
|
206
|
+
randomInt(0, STATE_CODE_LIST.length - 1)
|
|
207
|
+
] ?? "NE";
|
|
208
|
+
const centuryChar =
|
|
209
|
+
year >= 2000 ? randomLetter() : String(randomInt(0, 9));
|
|
210
|
+
const body =
|
|
211
|
+
`${randomLetter()}${randomLetter()}` +
|
|
212
|
+
`${randomLetter()}${randomLetter()}` +
|
|
213
|
+
`${yy}${month}${day}${gender}${state}` +
|
|
214
|
+
`${randomLetter()}${randomLetter()}${randomLetter()}` +
|
|
215
|
+
`${centuryChar}`;
|
|
216
|
+
return `${body}${calcCheckDigit(body)}`;
|
|
217
|
+
};
|
|
218
|
+
|
|
185
219
|
/**
|
|
186
220
|
* Mexican CURP (personal identification number).
|
|
187
221
|
*
|
|
188
222
|
* Example sourced from python-stdnum test suite.
|
|
189
223
|
*/
|
|
190
|
-
const curp: Validator = {
|
|
224
|
+
const curp: Validator<ParsedPersonId> = {
|
|
191
225
|
name: "Mexican Personal ID",
|
|
192
226
|
localName: "Clave Única de Registro de Población",
|
|
193
227
|
abbreviation: "CURP",
|
|
@@ -202,9 +236,11 @@ const curp: Validator = {
|
|
|
202
236
|
examples: ["BOXW310820HNERXN09"] as const,
|
|
203
237
|
compact,
|
|
204
238
|
format,
|
|
239
|
+
parse,
|
|
205
240
|
validate,
|
|
241
|
+
generate,
|
|
206
242
|
sourceUrl: "https://en.wikipedia.org/wiki/CURP",
|
|
207
243
|
};
|
|
208
244
|
|
|
209
245
|
export default curp;
|
|
210
|
-
export { compact, format, parse, validate };
|
|
246
|
+
export { compact, format, generate, parse, validate };
|
package/src/mx/rfc.ts
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import { clean } from "#util/clean";
|
|
20
20
|
import { isValidDate } from "#util/date";
|
|
21
|
+
import { randomInt } from "#util/generate";
|
|
21
22
|
import { err } from "#util/result";
|
|
22
23
|
|
|
23
24
|
import type { ValidateResult, Validator } from "../types";
|
|
@@ -26,8 +27,8 @@ import type { ValidateResult, Validator } from "../types";
|
|
|
26
27
|
const ALPHABET = "0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ Ñ";
|
|
27
28
|
|
|
28
29
|
const CHAR_MAP = new Map<string, number>();
|
|
29
|
-
for (
|
|
30
|
-
CHAR_MAP.set(
|
|
30
|
+
for (const [i, ch] of [...ALPHABET].entries()) {
|
|
31
|
+
CHAR_MAP.set(ch, i);
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
const compact = (value: string): string =>
|
|
@@ -48,7 +49,8 @@ const calcCheckDigit = (value: string): string => {
|
|
|
48
49
|
const padded = value.length === 11 ? ` ${value}` : value;
|
|
49
50
|
let sum = 0;
|
|
50
51
|
for (let i = 0; i < 12; i++) {
|
|
51
|
-
const ch = padded[i]
|
|
52
|
+
const ch = padded[i];
|
|
53
|
+
if (ch === undefined) continue;
|
|
52
54
|
const v = CHAR_MAP.get(ch) ?? 0;
|
|
53
55
|
sum += v * (13 - i);
|
|
54
56
|
}
|
|
@@ -60,6 +62,8 @@ const calcCheckDigit = (value: string): string => {
|
|
|
60
62
|
|
|
61
63
|
const PERSON_RE = /^[A-ZÑ&]{4}\d{6}[A-Z\d]{3}$/;
|
|
62
64
|
const COMPANY_RE = /^[A-ZÑ&]{3}\d{6}[A-Z\d]{3}$/;
|
|
65
|
+
const PREFIX_ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZÑ&";
|
|
66
|
+
const RFC_ALNUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
63
67
|
|
|
64
68
|
const validate = (value: string): ValidateResult => {
|
|
65
69
|
const v = compact(value);
|
|
@@ -115,6 +119,32 @@ const validate = (value: string): ValidateResult => {
|
|
|
115
119
|
|
|
116
120
|
const format = (value: string): string => compact(value);
|
|
117
121
|
|
|
122
|
+
const randomCharFrom = (chars: string): string =>
|
|
123
|
+
chars.charAt(randomInt(0, chars.length - 1));
|
|
124
|
+
|
|
125
|
+
/** Generate a random valid RFC. */
|
|
126
|
+
const generate = (): string => {
|
|
127
|
+
const isPerson = Math.random() < 0.5;
|
|
128
|
+
const prefixLength = isPerson ? 4 : 3;
|
|
129
|
+
let prefix = "";
|
|
130
|
+
for (let i = 0; i < prefixLength; i++) {
|
|
131
|
+
prefix += randomCharFrom(PREFIX_ALPHA);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const year = randomInt(2000, 2099);
|
|
135
|
+
const month = String(randomInt(1, 12)).padStart(2, "0");
|
|
136
|
+
const day = String(randomInt(1, 28)).padStart(2, "0");
|
|
137
|
+
let homoclave = "";
|
|
138
|
+
for (let i = 0; i < 2; i++) {
|
|
139
|
+
homoclave += randomCharFrom(RFC_ALNUM);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const body =
|
|
143
|
+
`${prefix}${String(year % 100).padStart(2, "0")}` +
|
|
144
|
+
`${month}${day}${homoclave}`;
|
|
145
|
+
return `${body}${calcCheckDigit(body)}`;
|
|
146
|
+
};
|
|
147
|
+
|
|
118
148
|
/**
|
|
119
149
|
* Mexican RFC (tax identification number).
|
|
120
150
|
*
|
|
@@ -136,9 +166,10 @@ const rfc: Validator = {
|
|
|
136
166
|
compact,
|
|
137
167
|
format,
|
|
138
168
|
validate,
|
|
169
|
+
generate,
|
|
139
170
|
sourceUrl:
|
|
140
171
|
"https://en.wikipedia.org/wiki/Tax_Identification_Number_(Mexico)",
|
|
141
172
|
};
|
|
142
173
|
|
|
143
174
|
export default rfc;
|
|
144
|
-
export { compact, format, validate };
|
|
175
|
+
export { compact, format, generate, validate };
|
package/src/my/nric.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import { clean } from "#util/clean";
|
|
16
16
|
import { isValidDate } from "#util/date";
|
|
17
|
+
import { randomInt } from "#util/generate";
|
|
17
18
|
import { err } from "#util/result";
|
|
18
19
|
import { isdigits } from "#util/strings";
|
|
19
20
|
|
|
@@ -211,8 +212,29 @@ const parse = (value: string): ParsedPersonId | null => {
|
|
|
211
212
|
};
|
|
212
213
|
};
|
|
213
214
|
|
|
215
|
+
const PB_CODES = [...VALID_PB_CODES];
|
|
216
|
+
|
|
217
|
+
/** Generate a random valid Malaysian NRIC. */
|
|
218
|
+
const generate = (): string => {
|
|
219
|
+
const year = randomInt(1950, 2024);
|
|
220
|
+
const month = String(randomInt(1, 12)).padStart(2, "0");
|
|
221
|
+
const day = String(randomInt(1, 28)).padStart(2, "0");
|
|
222
|
+
const pb =
|
|
223
|
+
PB_CODES[randomInt(0, PB_CODES.length - 1)] ?? "01";
|
|
224
|
+
const serial = String(randomInt(0, 999)).padStart(3, "0");
|
|
225
|
+
const isMale = Math.random() < 0.5;
|
|
226
|
+
const lastDigit = isMale
|
|
227
|
+
? String(randomInt(0, 4) * 2 + 1)
|
|
228
|
+
: String(randomInt(0, 4) * 2);
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
`${String(year % 100).padStart(2, "0")}` +
|
|
232
|
+
`${month}${day}${pb}${serial}${lastDigit}`
|
|
233
|
+
);
|
|
234
|
+
};
|
|
235
|
+
|
|
214
236
|
/** Malaysian National Registration Identity Card. */
|
|
215
|
-
const nric: Validator = {
|
|
237
|
+
const nric: Validator<ParsedPersonId> = {
|
|
216
238
|
name: "Malaysian National Registration Identity Card Number",
|
|
217
239
|
localName: "Nombor Kad Pengenalan",
|
|
218
240
|
abbreviation: "NRIC",
|
|
@@ -228,8 +250,10 @@ const nric: Validator = {
|
|
|
228
250
|
examples: ["770305021234", "880715141234"] as const,
|
|
229
251
|
compact,
|
|
230
252
|
format,
|
|
253
|
+
parse,
|
|
231
254
|
validate,
|
|
255
|
+
generate,
|
|
232
256
|
};
|
|
233
257
|
|
|
234
258
|
export default nric;
|
|
235
|
-
export { compact, format, parse, validate };
|
|
259
|
+
export { compact, format, generate, parse, validate };
|
package/src/nl/vat.ts
CHANGED
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
* BTW (Dutch VAT number).
|
|
3
3
|
*
|
|
4
4
|
* 12 characters: 9 digits + "B" + 2 digits.
|
|
5
|
-
* Mod 97 check: convert "NL" + number to numeric
|
|
6
|
-
* (N=23, L=21, B=11), mod 97 === 1.
|
|
7
5
|
*
|
|
8
|
-
*
|
|
6
|
+
* The current Dutch VAT identification number
|
|
7
|
+
* (btw-id) format is structural: `NL` + 9 digits
|
|
8
|
+
* + `B` + 2 digits. The official guidance explicitly
|
|
9
|
+
* states that the 9 digits are not derived from BSN
|
|
10
|
+
* and the final 2 digits are random.
|
|
11
|
+
*
|
|
9
12
|
* @see https://business.gov.nl/regulations/using-checking-vat-numbers/
|
|
10
13
|
*/
|
|
11
14
|
|
|
@@ -30,42 +33,6 @@ const compact = (value: string): string => {
|
|
|
30
33
|
return v;
|
|
31
34
|
};
|
|
32
35
|
|
|
33
|
-
/**
|
|
34
|
-
* Compute mod 97 of a string containing digits and
|
|
35
|
-
* uppercase letters (A=10, B=11, ..., Z=35).
|
|
36
|
-
*/
|
|
37
|
-
const mod97 = (value: string): number => {
|
|
38
|
-
let remainder = 0;
|
|
39
|
-
for (const ch of value) {
|
|
40
|
-
const code = ch.charCodeAt(0);
|
|
41
|
-
if (code >= 48 && code <= 57) {
|
|
42
|
-
// Digit
|
|
43
|
-
remainder = (remainder * 10 + (code - 48)) % 97;
|
|
44
|
-
} else if (code >= 65 && code <= 90) {
|
|
45
|
-
// Letter: two decimal digits (A=10, ..., Z=35)
|
|
46
|
-
const num = code - 55;
|
|
47
|
-
remainder = (remainder * 100 + num) % 97;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return remainder;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Check if a 9-digit string is a valid BSN (Dutch citizen
|
|
55
|
-
* identification number). Weights [9,8,7,6,5,4,3,2,-1],
|
|
56
|
-
* sum % 11 === 0.
|
|
57
|
-
*/
|
|
58
|
-
const bsnValid = (num: string): boolean => {
|
|
59
|
-
if (!isdigits(num) || num.length !== 9) return false;
|
|
60
|
-
if (Number.parseInt(num, 10) <= 0) return false;
|
|
61
|
-
let sum = 0;
|
|
62
|
-
for (let i = 0; i < 8; i++) {
|
|
63
|
-
sum += (9 - i) * Number(num[i]);
|
|
64
|
-
}
|
|
65
|
-
sum -= Number(num[8]);
|
|
66
|
-
return sum % 11 === 0;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
36
|
const validate = (value: string): ValidateResult => {
|
|
70
37
|
const v = compact(value);
|
|
71
38
|
if (v.length !== 12) {
|
|
@@ -92,25 +59,6 @@ const validate = (value: string): ValidateResult => {
|
|
|
92
59
|
"Dutch VAT number must end with 2 digits",
|
|
93
60
|
);
|
|
94
61
|
}
|
|
95
|
-
if (Number.parseInt(v.slice(0, 9), 10) <= 0) {
|
|
96
|
-
return err(
|
|
97
|
-
"INVALID_FORMAT",
|
|
98
|
-
"Dutch VAT number first 9 digits must be > 0",
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
if (Number.parseInt(v.slice(10, 12), 10) <= 0) {
|
|
102
|
-
return err(
|
|
103
|
-
"INVALID_FORMAT",
|
|
104
|
-
"Dutch VAT number last 2 digits must be > 0",
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
// Valid if BSN check passes OR mod 97 check passes
|
|
108
|
-
if (!bsnValid(v.slice(0, 9)) && mod97(`NL${v}`) !== 1) {
|
|
109
|
-
return err(
|
|
110
|
-
"INVALID_CHECKSUM",
|
|
111
|
-
"Dutch VAT number checksum failed",
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
62
|
return { valid: true, compact: v };
|
|
115
63
|
};
|
|
116
64
|
|
|
@@ -118,12 +66,8 @@ const format = (value: string): string =>
|
|
|
118
66
|
`NL${compact(value)}`;
|
|
119
67
|
|
|
120
68
|
/** Generate a random valid Dutch VAT number. */
|
|
121
|
-
const generate = (): string =>
|
|
122
|
-
|
|
123
|
-
const c = randomDigits(9) + "B" + randomDigits(2);
|
|
124
|
-
if (validate(c).valid) return c;
|
|
125
|
-
}
|
|
126
|
-
};
|
|
69
|
+
const generate = (): string =>
|
|
70
|
+
`${randomDigits(9)}B${randomDigits(2)}`;
|
|
127
71
|
|
|
128
72
|
/** Dutch VAT Number. */
|
|
129
73
|
const vat: Validator = {
|
|
@@ -134,8 +78,9 @@ const vat: Validator = {
|
|
|
134
78
|
candidatePattern: "NL\\d{9}B\\d{2}",
|
|
135
79
|
country: "NL",
|
|
136
80
|
entityType: "company",
|
|
137
|
-
sourceUrl:
|
|
138
|
-
|
|
81
|
+
sourceUrl:
|
|
82
|
+
"https://business.gov.nl/regulations/using-checking-vat-numbers/",
|
|
83
|
+
examples: ["000099998B57"] as const,
|
|
139
84
|
compact,
|
|
140
85
|
format,
|
|
141
86
|
validate,
|
package/src/no/fodselsnummer.ts
CHANGED
|
@@ -172,7 +172,7 @@ const generate = (): string => {
|
|
|
172
172
|
};
|
|
173
173
|
|
|
174
174
|
/** Norwegian Birth Number. */
|
|
175
|
-
const fodselsnummer: Validator = {
|
|
175
|
+
const fodselsnummer: Validator<ParsedPersonId> = {
|
|
176
176
|
name: "Norwegian Birth Number",
|
|
177
177
|
localName: "Fødselsnummer",
|
|
178
178
|
abbreviation: "Fødselsnr",
|
|
@@ -184,6 +184,7 @@ const fodselsnummer: Validator = {
|
|
|
184
184
|
examples: ["15108695088"] as const,
|
|
185
185
|
compact,
|
|
186
186
|
format,
|
|
187
|
+
parse,
|
|
187
188
|
validate,
|
|
188
189
|
generate,
|
|
189
190
|
};
|
package/src/nz/ird.ts
CHANGED
|
@@ -28,15 +28,15 @@ const SECONDARY_WEIGHTS = [7, 4, 3, 2, 5, 2, 7, 6] as const;
|
|
|
28
28
|
const calcCheckDigit = (payload: string): number | null => {
|
|
29
29
|
const padded = payload.padStart(8, "0");
|
|
30
30
|
let sum = 0;
|
|
31
|
-
for (
|
|
32
|
-
sum +=
|
|
31
|
+
for (const [i, weight] of PRIMARY_WEIGHTS.entries()) {
|
|
32
|
+
sum += weight * Number(padded[i]);
|
|
33
33
|
}
|
|
34
34
|
let remainder = ((-sum % 11) + 11) % 11;
|
|
35
35
|
if (remainder !== 10) return remainder;
|
|
36
36
|
|
|
37
37
|
sum = 0;
|
|
38
|
-
for (
|
|
39
|
-
sum +=
|
|
38
|
+
for (const [i, weight] of SECONDARY_WEIGHTS.entries()) {
|
|
39
|
+
sum += weight * Number(padded[i]);
|
|
40
40
|
}
|
|
41
41
|
remainder = ((-sum % 11) + 11) % 11;
|
|
42
42
|
if (remainder === 10) return null;
|
package/src/pa/ruc.ts
CHANGED
|
@@ -111,19 +111,26 @@ const computeDV = (
|
|
|
111
111
|
): string | null => {
|
|
112
112
|
const len = segments.length;
|
|
113
113
|
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
114
|
+
if (len < 3 || len > 4) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
// The NT designation requires exactly 4 segments
|
|
118
|
+
// (xxNT-NT-xxx-xxx); any other 4-segment shape is
|
|
119
|
+
// unrecognized, and a 3-segment "NT" in position 1
|
|
120
|
+
// is malformed.
|
|
121
|
+
if ((len === 4) !== (segments[1] === "NT")) {
|
|
119
122
|
return null;
|
|
120
123
|
}
|
|
121
124
|
|
|
122
125
|
let buf: string;
|
|
123
126
|
let isOld = false;
|
|
124
127
|
|
|
128
|
+
// SAFETY: length check above ensures 3..4 segments.
|
|
129
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
125
130
|
const s0 = segments[0]!;
|
|
131
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
126
132
|
const s1 = segments[1]!;
|
|
133
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
127
134
|
const s2 = segments[2]!;
|
|
128
135
|
|
|
129
136
|
if (raw[0] === "E") {
|
|
@@ -138,7 +145,9 @@ const computeDV = (
|
|
|
138
145
|
z(5 - s2.length) +
|
|
139
146
|
s2;
|
|
140
147
|
} else if (s1 === "NT") {
|
|
141
|
-
// NT designation (xxNT-xxx-xxx)
|
|
148
|
+
// NT designation (xxNT-NT-xxx-xxx)
|
|
149
|
+
// SAFETY: NT branch implies len === 4 (checked above).
|
|
150
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
142
151
|
const s3 = segments[3]!;
|
|
143
152
|
const prefix = s0.slice(0, -2);
|
|
144
153
|
buf =
|
|
@@ -220,8 +229,14 @@ const computeDV = (
|
|
|
220
229
|
s1 +
|
|
221
230
|
z(6 - s2.length) +
|
|
222
231
|
s2;
|
|
232
|
+
// SAFETY: juridical branch zero-pads s0 to at least
|
|
233
|
+
// 10 chars (z(10 - s0.length)), so buf[3..6] are
|
|
234
|
+
// always defined.
|
|
223
235
|
isOld =
|
|
224
|
-
buf[3] === "0" &&
|
|
236
|
+
buf[3] === "0" &&
|
|
237
|
+
buf[4] === "0" &&
|
|
238
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
239
|
+
buf[5]! < "5";
|
|
225
240
|
}
|
|
226
241
|
|
|
227
242
|
// Apply legacy cross-reference for old format
|
|
@@ -270,7 +285,10 @@ const validate = (value: string): ValidateResult => {
|
|
|
270
285
|
);
|
|
271
286
|
}
|
|
272
287
|
|
|
288
|
+
// SAFETY: both DV regex capture groups are required.
|
|
289
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
273
290
|
const rucPart = dvMatch[1]!;
|
|
291
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
274
292
|
const dvPart = dvMatch[2]!;
|
|
275
293
|
|
|
276
294
|
// The RUC part should be hyphen-separated segments
|
|
@@ -318,7 +336,10 @@ const format = (value: string): string => {
|
|
|
318
336
|
const dvMatch = v.match(/^(.+?)-?\s*DV[:\s]*(\d{2})$/);
|
|
319
337
|
if (!dvMatch) return v;
|
|
320
338
|
|
|
339
|
+
// SAFETY: both DV regex capture groups are required.
|
|
340
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
321
341
|
const rucPart = dvMatch[1]!.replace(/-+$/, "");
|
|
342
|
+
// eslint-disable-next-line no-non-null-assertion
|
|
322
343
|
const dvPart = dvMatch[2]!;
|
|
323
344
|
const segments = rucPart.split("-");
|
|
324
345
|
return `${segments.join("-")} DV ${dvPart}`;
|
|
@@ -330,7 +351,10 @@ const generate = (): string => {
|
|
|
330
351
|
const volume = String(randomInt(1, 9999));
|
|
331
352
|
const folio = String(randomInt(1, 99999));
|
|
332
353
|
const segments = [province, volume, folio];
|
|
333
|
-
const dv = computeDV(segments, segments.join("-"))
|
|
354
|
+
const dv = computeDV(segments, segments.join("-"));
|
|
355
|
+
if (dv === null) {
|
|
356
|
+
throw new Error("Failed to compute Panama RUC DV");
|
|
357
|
+
}
|
|
334
358
|
return `${segments.join("-")} DV${dv}`;
|
|
335
359
|
};
|
|
336
360
|
|