@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/dist/kr/rrn.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { clean } from "../_util/clean.js";
|
|
2
|
+
import { randomDigits, randomInt } from "../_util/generate.js";
|
|
2
3
|
import { err } from "../_util/result.js";
|
|
3
4
|
import { isdigits } from "../_util/strings.js";
|
|
4
5
|
import { isValidDate } from "../_util/date.js";
|
|
@@ -106,6 +107,14 @@ const parse = (value) => {
|
|
|
106
107
|
gender: isMale ? "male" : "female"
|
|
107
108
|
};
|
|
108
109
|
};
|
|
110
|
+
/** Generate a random valid Korean RRN. */
|
|
111
|
+
const generate = () => {
|
|
112
|
+
const year = randomInt(1900, 2024);
|
|
113
|
+
const month = String(randomInt(1, 12)).padStart(2, "0");
|
|
114
|
+
const day = String(randomInt(1, 28)).padStart(2, "0");
|
|
115
|
+
const body = `${String(year % 100).padStart(2, "0")}${month}${day}${year >= 2e3 ? String(randomInt(3, 4)) : String(randomInt(1, 2))}${String(randomInt(0, 96)).padStart(2, "0")}${randomDigits(3)}`;
|
|
116
|
+
return `${body}${String(checkDigit(body))}`;
|
|
117
|
+
};
|
|
109
118
|
/** Korean Resident Registration Number. */
|
|
110
119
|
const rrn = {
|
|
111
120
|
name: "Korean Resident Registration Number",
|
|
@@ -125,9 +134,11 @@ const rrn = {
|
|
|
125
134
|
examples: ["9710139019902", "9501011000109"],
|
|
126
135
|
compact,
|
|
127
136
|
format,
|
|
128
|
-
|
|
137
|
+
parse,
|
|
138
|
+
validate,
|
|
139
|
+
generate
|
|
129
140
|
};
|
|
130
141
|
//#endregion
|
|
131
|
-
export { compact, rrn as default, format, parse, validate };
|
|
142
|
+
export { compact, rrn as default, format, generate, parse, validate };
|
|
132
143
|
|
|
133
144
|
//# sourceMappingURL=rrn.js.map
|
package/dist/kr/rrn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rrn.js","names":[],"sources":["../../src/kr/rrn.ts"],"sourcesContent":["/**\n * RRN (Resident Registration Number, 주민등록번호).\n *\n * Korean Resident Registration Number. 13 digits\n * formatted as YYMMDD-GPPCCSD. Encodes date of\n * birth, gender/century, place of birth, community\n * center, serial, and a check digit.\n *\n * @see https://en.wikipedia.org/wiki/Resident_registration_number\n */\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\nconst compact = (value: string): string =>\n clean(value, \" -/\");\n\nconst CHECK_WEIGHTS = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5];\n\n/**\n * Compute the check digit for the first 12 digits.\n * Formula: (11 - sum(w_i * d_i) % 11) % 10.\n */\nconst checkDigit = (digits: string): number => {\n let sum = 0;\n for (let i = 0; i < 12; i++) {\n sum +=\n (CHECK_WEIGHTS[i] ?? 0) * Number(digits.charAt(i));\n }\n return (11 - (sum % 11)) % 10;\n};\n\n/** Century prefix derived from the 7th digit. */\nconst CENTURY_BY_GENDER: Record<string, number> = {\n \"0\": 1800,\n \"1\": 1900,\n \"2\": 1900,\n \"3\": 2000,\n \"4\": 2000,\n \"5\": 1900,\n \"6\": 1900,\n \"7\": 2000,\n \"8\": 2000,\n \"9\": 1800,\n};\n\n/**\n * Resolve birth date components from a compacted RRN.\n * Returns null if the date is invalid.\n */\nconst resolveBirthDate = (\n v: string,\n): { year: number; month: number; day: number } | null => {\n const century = CENTURY_BY_GENDER[v.charAt(6)];\n if (century === undefined) return null;\n\n const year = century + Number(v.slice(0, 2));\n const month = Number(v.slice(2, 4));\n const day = Number(v.slice(4, 6));\n\n if (!isValidDate(year, month, day)) return null;\n return { year, month, day };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"RRN must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"RRN must contain only digits\",\n );\n }\n if (resolveBirthDate(v) === null) {\n return err(\n \"INVALID_COMPONENT\",\n \"RRN contains an invalid date of birth\",\n );\n }\n const place = Number(v.slice(7, 9));\n if (place > 96) {\n return err(\n \"INVALID_COMPONENT\",\n \"RRN place-of-birth code must be <= 96\",\n );\n }\n if (checkDigit(v.slice(0, 12)) !== Number(v[12])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"RRN check digit does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 13) {\n return `${v.slice(0, 6)}-${v.slice(6)}`;\n }\n return v;\n};\n\n/**\n * Extract birth date and gender from an RRN.\n * Returns null if the value is not valid.\n *\n * Gender digit mapping:\n * 1, 3 = male Korean; 2, 4 = female Korean\n * 5, 7 = male foreigner; 6, 8 = female foreigner\n * 0, 9 = pre-1800 (male/female by convention)\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const bd = resolveBirthDate(v);\n if (bd === null) return null;\n\n const genderDigit = v.charAt(6);\n const isMale = \"13579\".includes(genderDigit);\n\n return {\n birthDate: new Date(bd.year, bd.month - 1, bd.day),\n gender: isMale ? \"male\" : \"female\",\n };\n};\n\n/** Korean Resident Registration Number. */\nconst rrn: Validator = {\n name: \"Korean Resident Registration Number\",\n localName: \"주민등록번호\",\n abbreviation: \"RRN\",\n aliases: [\n \"RRN\",\n \"주민등록번호\",\n \"Resident Registration Number\",\n ] as const,\n candidatePattern: \"\\\\d{6}[\\\\s-]?\\\\d{7}\",\n country: \"KR\",\n entityType: \"person\",\n description:\n \"13-digit personal identifier issued to all\" +\n \" residents of South Korea\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/\" +\n \"Resident_registration_number\",\n lengths: [13] as const,\n examples: [\"9710139019902\", \"9501011000109\"] as const,\n compact,\n format,\n validate,\n};\n\nexport default rrn;\nexport { compact, format, parse, validate };\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"rrn.js","names":[],"sources":["../../src/kr/rrn.ts"],"sourcesContent":["/**\n * RRN (Resident Registration Number, 주민등록번호).\n *\n * Korean Resident Registration Number. 13 digits\n * formatted as YYMMDD-GPPCCSD. Encodes date of\n * birth, gender/century, place of birth, community\n * center, serial, and a check digit.\n *\n * @see https://en.wikipedia.org/wiki/Resident_registration_number\n */\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\nconst compact = (value: string): string =>\n clean(value, \" -/\");\n\nconst CHECK_WEIGHTS = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5];\n\n/**\n * Compute the check digit for the first 12 digits.\n * Formula: (11 - sum(w_i * d_i) % 11) % 10.\n */\nconst checkDigit = (digits: string): number => {\n let sum = 0;\n for (let i = 0; i < 12; i++) {\n sum +=\n (CHECK_WEIGHTS[i] ?? 0) * Number(digits.charAt(i));\n }\n return (11 - (sum % 11)) % 10;\n};\n\n/** Century prefix derived from the 7th digit. */\nconst CENTURY_BY_GENDER: Record<string, number> = {\n \"0\": 1800,\n \"1\": 1900,\n \"2\": 1900,\n \"3\": 2000,\n \"4\": 2000,\n \"5\": 1900,\n \"6\": 1900,\n \"7\": 2000,\n \"8\": 2000,\n \"9\": 1800,\n};\n\n/**\n * Resolve birth date components from a compacted RRN.\n * Returns null if the date is invalid.\n */\nconst resolveBirthDate = (\n v: string,\n): { year: number; month: number; day: number } | null => {\n const century = CENTURY_BY_GENDER[v.charAt(6)];\n if (century === undefined) return null;\n\n const year = century + Number(v.slice(0, 2));\n const month = Number(v.slice(2, 4));\n const day = Number(v.slice(4, 6));\n\n if (!isValidDate(year, month, day)) return null;\n return { year, month, day };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"RRN must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"RRN must contain only digits\",\n );\n }\n if (resolveBirthDate(v) === null) {\n return err(\n \"INVALID_COMPONENT\",\n \"RRN contains an invalid date of birth\",\n );\n }\n const place = Number(v.slice(7, 9));\n if (place > 96) {\n return err(\n \"INVALID_COMPONENT\",\n \"RRN place-of-birth code must be <= 96\",\n );\n }\n if (checkDigit(v.slice(0, 12)) !== Number(v[12])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"RRN check digit does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 13) {\n return `${v.slice(0, 6)}-${v.slice(6)}`;\n }\n return v;\n};\n\n/**\n * Extract birth date and gender from an RRN.\n * Returns null if the value is not valid.\n *\n * Gender digit mapping:\n * 1, 3 = male Korean; 2, 4 = female Korean\n * 5, 7 = male foreigner; 6, 8 = female foreigner\n * 0, 9 = pre-1800 (male/female by convention)\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const bd = resolveBirthDate(v);\n if (bd === null) return null;\n\n const genderDigit = v.charAt(6);\n const isMale = \"13579\".includes(genderDigit);\n\n return {\n birthDate: new Date(bd.year, bd.month - 1, bd.day),\n gender: isMale ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid Korean RRN. */\nconst generate = (): string => {\n const year = randomInt(1900, 2024);\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n const yy = String(year % 100).padStart(2, \"0\");\n const genderDigit =\n year >= 2000\n ? String(randomInt(3, 4))\n : String(randomInt(1, 2));\n const place = String(randomInt(0, 96)).padStart(2, \"0\");\n const body = `${yy}${month}${day}${genderDigit}${place}${randomDigits(3)}`;\n return `${body}${String(checkDigit(body))}`;\n};\n\n/** Korean Resident Registration Number. */\nconst rrn: Validator<ParsedPersonId> = {\n name: \"Korean Resident Registration Number\",\n localName: \"주민등록번호\",\n abbreviation: \"RRN\",\n aliases: [\n \"RRN\",\n \"주민등록번호\",\n \"Resident Registration Number\",\n ] as const,\n candidatePattern: \"\\\\d{6}[\\\\s-]?\\\\d{7}\",\n country: \"KR\",\n entityType: \"person\",\n description:\n \"13-digit personal identifier issued to all\" +\n \" residents of South Korea\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/\" +\n \"Resident_registration_number\",\n lengths: [13] as const,\n examples: [\"9710139019902\", \"9501011000109\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default rrn;\nexport { compact, format, generate, parse, validate };\n"],"mappings":"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"}
|
package/dist/kw/civil.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ParsedBirthDate, ValidateResult, Validator } from "../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/kw/civil.d.ts
|
|
4
|
-
|
|
5
4
|
declare const compact: (value: string) => string;
|
|
6
5
|
declare const validate: (value: string) => ValidateResult;
|
|
7
6
|
declare const format: (value: string) => string;
|
|
@@ -10,9 +9,11 @@ declare const format: (value: string) => string;
|
|
|
10
9
|
* Gender is not encoded in the number.
|
|
11
10
|
* Returns null if the value is not valid.
|
|
12
11
|
*/
|
|
13
|
-
declare const parse: (value: string) =>
|
|
12
|
+
declare const parse: (value: string) => ParsedBirthDate | null;
|
|
13
|
+
/** Generate a random valid Kuwait civil number. */
|
|
14
|
+
declare const generate: () => string;
|
|
14
15
|
/** Kuwait Civil Number (الرقم المدني). */
|
|
15
|
-
declare const civil: Validator
|
|
16
|
+
declare const civil: Validator<ParsedBirthDate>;
|
|
16
17
|
//#endregion
|
|
17
|
-
export { compact, civil as default, format, parse, validate };
|
|
18
|
+
export { compact, civil as default, format, generate, parse, validate };
|
|
18
19
|
//# sourceMappingURL=civil.d.ts.map
|
package/dist/kw/civil.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { clean } from "../_util/clean.js";
|
|
2
|
+
import { randomDigits, randomInt } from "../_util/generate.js";
|
|
2
3
|
import { err } from "../_util/result.js";
|
|
3
4
|
import { isdigits } from "../_util/strings.js";
|
|
4
5
|
import { isValidDate } from "../_util/date.js";
|
|
@@ -36,7 +37,7 @@ const centuryMap = {
|
|
|
36
37
|
const compact = (value) => clean(value, " -");
|
|
37
38
|
const calcCheckDigit = (digits) => {
|
|
38
39
|
let sum = 0;
|
|
39
|
-
for (
|
|
40
|
+
for (const [i, weight] of WEIGHTS.entries()) sum += Number(digits[i]) * weight;
|
|
40
41
|
return (11 - sum % 11) % 11;
|
|
41
42
|
};
|
|
42
43
|
const validate = (value) => {
|
|
@@ -76,6 +77,18 @@ const parse = (value) => {
|
|
|
76
77
|
const year = yearBase + yy;
|
|
77
78
|
return { birthDate: new Date(year, mm - 1, dd) };
|
|
78
79
|
};
|
|
80
|
+
/** Generate a random valid Kuwait civil number. */
|
|
81
|
+
const generate = () => {
|
|
82
|
+
for (;;) {
|
|
83
|
+
const year = randomInt(1950, 2024);
|
|
84
|
+
const month = String(randomInt(1, 12)).padStart(2, "0");
|
|
85
|
+
const day = String(randomInt(1, 28)).padStart(2, "0");
|
|
86
|
+
const body = `${year >= 2e3 ? "3" : "2"}${String(year % 100).padStart(2, "0")}${month}${day}${randomDigits(4)}`;
|
|
87
|
+
const check = calcCheckDigit(body);
|
|
88
|
+
if (check > 9) continue;
|
|
89
|
+
return `${body}${String(check)}`;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
79
92
|
/** Kuwait Civil Number (الرقم المدني). */
|
|
80
93
|
const civil = {
|
|
81
94
|
name: "Civil Number",
|
|
@@ -91,9 +104,11 @@ const civil = {
|
|
|
91
104
|
sourceUrl: "https://kuwaitsexpat.com/kuwait-civil-id-format/",
|
|
92
105
|
compact,
|
|
93
106
|
format,
|
|
94
|
-
|
|
107
|
+
parse,
|
|
108
|
+
validate,
|
|
109
|
+
generate
|
|
95
110
|
};
|
|
96
111
|
//#endregion
|
|
97
|
-
export { compact, civil as default, format, parse, validate };
|
|
112
|
+
export { compact, civil as default, format, generate, parse, validate };
|
|
98
113
|
|
|
99
114
|
//# sourceMappingURL=civil.js.map
|
package/dist/kw/civil.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"civil.js","names":[],"sources":["../../src/kw/civil.ts"],"sourcesContent":["/**\n * Civil Number (الرقم المدني, Kuwait).\n *\n * 12-digit number issued by PACI (Public Authority\n * for Civil Information):\n * C = century indicator (2 = 1900s, 3 = 2000s)\n * YYMMDD = birth date\n * SSSS = serial number\n * K = check digit (mod 11 weighted sum)\n *\n * @see https://prakhar.me/articles/kuwait-civil-id-checksum/\n * @see https://kuwaitsexpat.com/kuwait-civil-id-format/\n */\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n
|
|
1
|
+
{"version":3,"file":"civil.js","names":[],"sources":["../../src/kw/civil.ts"],"sourcesContent":["/**\n * Civil Number (الرقم المدني, Kuwait).\n *\n * 12-digit number issued by PACI (Public Authority\n * for Civil Information):\n * C = century indicator (2 = 1900s, 3 = 2000s)\n * YYMMDD = birth date\n * SSSS = serial number\n * K = check digit (mod 11 weighted sum)\n *\n * @see https://prakhar.me/articles/kuwait-civil-id-checksum/\n * @see https://kuwaitsexpat.com/kuwait-civil-id-format/\n */\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n ParsedBirthDate,\n ValidateResult,\n Validator,\n} from \"../types\";\n\nconst WEIGHTS = [2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] as const;\n\nconst centuryMap: Record<number, number> = {\n 2: 1900,\n 3: 2000,\n};\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst calcCheckDigit = (digits: string): number => {\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n sum += Number(digits[i]) * weight;\n }\n return (11 - (sum % 11)) % 11;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Kuwait civil number must be 12 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Kuwait civil number must contain only digits\",\n );\n }\n\n const centuryDigit = Number(v[0]);\n if (centuryDigit !== 2 && centuryDigit !== 3) {\n return err(\n \"INVALID_COMPONENT\",\n \"Century digit must be 2 or 3\",\n );\n }\n\n const yearBase = centuryMap[centuryDigit] ?? 1900;\n const yy = Number(v.slice(1, 3));\n const mm = Number(v.slice(3, 5));\n const dd = Number(v.slice(5, 7));\n const year = yearBase + yy;\n\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Civil number contains an invalid birth date\",\n );\n }\n\n const expected = calcCheckDigit(v.slice(0, 11));\n if (expected !== Number(v[11])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Civil number check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 1)} ${v.slice(1, 7)} ${v.slice(7, 11)} ${v.slice(11)}`;\n};\n\n/**\n * Extract birth date from a Kuwait civil number.\n * Gender is not encoded in the number.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedBirthDate | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const centuryDigit = Number(v[0]);\n const yearBase = centuryMap[centuryDigit] ?? 1900;\n const yy = Number(v.slice(1, 3));\n const mm = Number(v.slice(3, 5));\n const dd = Number(v.slice(5, 7));\n const year = yearBase + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n };\n};\n\n/** Generate a random valid Kuwait civil number. */\nconst generate = (): string => {\n for (;;) {\n const year = randomInt(1950, 2024);\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n const body =\n `${year >= 2000 ? \"3\" : \"2\"}` +\n `${String(year % 100).padStart(2, \"0\")}` +\n `${month}${day}${randomDigits(4)}`;\n const check = calcCheckDigit(body);\n if (check > 9) continue;\n return `${body}${String(check)}`;\n }\n};\n\n/** Kuwait Civil Number (الرقم المدني). */\nconst civil: Validator<ParsedBirthDate> = {\n name: \"Civil Number\",\n localName: \"الرقم المدني\",\n abbreviation: \"Civil ID\",\n aliases: [\"Civil ID\", \"الرقم المدني\"] as const,\n candidatePattern: \"\\\\d{12}\",\n country: \"KW\",\n entityType: \"person\",\n lengths: [12] as const,\n examples: [\"289011200032\", \"305031512348\"] as const,\n description:\n \"12-digit civil identification number issued by PACI\",\n sourceUrl:\n \"https://kuwaitsexpat.com/kuwait-civil-id-format/\",\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default civil;\nexport { compact, format, generate, parse, validate };\n"],"mappings":"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"}
|
package/dist/kw/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import civil from "./civil.js";
|
|
3
2
|
|
|
4
3
|
//#region src/kw/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { civil };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { civil, mod_d_exports };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/kz/iin.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/kz/iin.d.ts
|
|
4
|
-
|
|
5
4
|
declare const compact: (value: string) => string;
|
|
6
5
|
declare const validate: (value: string) => ValidateResult;
|
|
7
6
|
declare const format: (value: string) => string;
|
|
@@ -17,7 +16,7 @@ declare const generate: () => string;
|
|
|
17
16
|
*
|
|
18
17
|
* Examples sourced from identique/idnumbers test suite.
|
|
19
18
|
*/
|
|
20
|
-
declare const iin: Validator
|
|
19
|
+
declare const iin: Validator<ParsedPersonId>;
|
|
21
20
|
//#endregion
|
|
22
21
|
export { compact, iin as default, format, generate, parse, validate };
|
|
23
22
|
//# sourceMappingURL=iin.d.ts.map
|
package/dist/kz/iin.js
CHANGED
|
@@ -140,6 +140,7 @@ const iin = {
|
|
|
140
140
|
examples: ["880515300120", "950101400012"],
|
|
141
141
|
compact,
|
|
142
142
|
format,
|
|
143
|
+
parse,
|
|
143
144
|
validate,
|
|
144
145
|
sourceUrl: "https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Kazakhstan-TIN.pdf",
|
|
145
146
|
generate
|
package/dist/kz/iin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iin.js","names":[],"sources":["../../src/kz/iin.ts"],"sourcesContent":["/**\n * IIN (Individual Identification Number,\n * Жеке сәйкестендіру нөмірі / ИИН).\n *\n * Kazakhstan individual identification number. 12 digits:\n * YYMMDD = birth date\n * C = century/gender (1-6)\n * SSSS = serial number\n * K = check digit (two-pass weighted sum mod 11)\n *\n * Odd century digits = male, even = female.\n * 1-2 = 1800s, 3-4 = 1900s, 5-6 = 2000s.\n *\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Kazakhstan-TIN.pdf\n */\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\nconst WEIGHTS_1 = [\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n] as const;\nconst WEIGHTS_2 = [\n 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2,\n] as const;\n\nconst centuryMap: Record<number, number> = {\n 1: 1800,\n 2: 1800,\n 3: 1900,\n 4: 1900,\n 5: 2000,\n 6: 2000,\n};\n\nconst compact = (value: string): string =>\n clean(value, \" -\").trim();\n\n/**\n * Two-pass check digit: weighted sum mod 11 with\n * fallback to second weight set.\n */\nconst calcCheckDigit = (digits: string): number => {\n let remainder = weightedSum(digits, WEIGHTS_1, 11);\n if (remainder === 10) {\n remainder = weightedSum(digits, WEIGHTS_2, 11);\n }\n return remainder === 10 ? 0 : remainder;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Kazakhstan IIN must be 12 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Kazakhstan IIN must contain only digits\",\n );\n }\n\n const centuryDigit = Number(v[6]);\n if (centuryDigit < 1 || centuryDigit > 6) {\n return err(\n \"INVALID_COMPONENT\",\n \"IIN century/gender digit must be 1-6\",\n );\n }\n\n const yearBase = centuryMap[centuryDigit] ?? 1900;\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n const year = yearBase + yy;\n\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"IIN contains an invalid birth date\",\n );\n }\n\n const expected = calcCheckDigit(v.slice(0, 11));\n if (expected !== Number(v[11])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"IIN check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 6)} ${v.slice(6)}`;\n};\n\n/**\n * Extract birth date and gender from a Kazakhstan IIN.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const centuryDigit = Number(v[6]);\n const yearBase = centuryMap[centuryDigit] ?? 1900;\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n const year = yearBase + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender: centuryDigit % 2 === 1 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid Kazakhstan IIN. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(50, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const gender = String(randomInt(1, 6));\n const serial = randomDigits(4);\n const payload = yy + mm + dd + gender + serial;\n const check = calcCheckDigit(payload);\n if (check === null) continue;\n const c = payload + String(check);\n if (validate(c).valid) return c;\n }\n};\n\n/**\n * Kazakhstan Individual Identification Number (IIN).\n *\n * Examples sourced from identique/idnumbers test suite.\n */\nconst iin: Validator = {\n name: \"Kazakhstan Individual ID\",\n localName: \"Жеке сәйкестендіру нөмірі\",\n abbreviation: \"IIN\",\n aliases: [\n \"ИИН\",\n \"IIN\",\n \"индивидуальный идентификационный номер\",\n ] as const,\n candidatePattern: \"\\\\d{12}\",\n country: \"KZ\",\n entityType: \"person\",\n lengths: [12] as const,\n examples: [\"880515300120\", \"950101400012\"] as const,\n compact,\n format,\n validate,\n sourceUrl:\n \"https://www.oecd.org/tax/automatic-exchange/\" +\n \"crs-implementation-and-assistance/\" +\n \"tax-identification-numbers/Kazakhstan-TIN.pdf\",\n generate,\n};\n\nexport default iin;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"iin.js","names":[],"sources":["../../src/kz/iin.ts"],"sourcesContent":["/**\n * IIN (Individual Identification Number,\n * Жеке сәйкестендіру нөмірі / ИИН).\n *\n * Kazakhstan individual identification number. 12 digits:\n * YYMMDD = birth date\n * C = century/gender (1-6)\n * SSSS = serial number\n * K = check digit (two-pass weighted sum mod 11)\n *\n * Odd century digits = male, even = female.\n * 1-2 = 1800s, 3-4 = 1900s, 5-6 = 2000s.\n *\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Kazakhstan-TIN.pdf\n */\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\nconst WEIGHTS_1 = [\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,\n] as const;\nconst WEIGHTS_2 = [\n 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2,\n] as const;\n\nconst centuryMap: Record<number, number> = {\n 1: 1800,\n 2: 1800,\n 3: 1900,\n 4: 1900,\n 5: 2000,\n 6: 2000,\n};\n\nconst compact = (value: string): string =>\n clean(value, \" -\").trim();\n\n/**\n * Two-pass check digit: weighted sum mod 11 with\n * fallback to second weight set.\n */\nconst calcCheckDigit = (digits: string): number => {\n let remainder = weightedSum(digits, WEIGHTS_1, 11);\n if (remainder === 10) {\n remainder = weightedSum(digits, WEIGHTS_2, 11);\n }\n return remainder === 10 ? 0 : remainder;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Kazakhstan IIN must be 12 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Kazakhstan IIN must contain only digits\",\n );\n }\n\n const centuryDigit = Number(v[6]);\n if (centuryDigit < 1 || centuryDigit > 6) {\n return err(\n \"INVALID_COMPONENT\",\n \"IIN century/gender digit must be 1-6\",\n );\n }\n\n const yearBase = centuryMap[centuryDigit] ?? 1900;\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n const year = yearBase + yy;\n\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"IIN contains an invalid birth date\",\n );\n }\n\n const expected = calcCheckDigit(v.slice(0, 11));\n if (expected !== Number(v[11])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"IIN check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 6)} ${v.slice(6)}`;\n};\n\n/**\n * Extract birth date and gender from a Kazakhstan IIN.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const centuryDigit = Number(v[6]);\n const yearBase = centuryMap[centuryDigit] ?? 1900;\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n const year = yearBase + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender: centuryDigit % 2 === 1 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid Kazakhstan IIN. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(50, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const gender = String(randomInt(1, 6));\n const serial = randomDigits(4);\n const payload = yy + mm + dd + gender + serial;\n const check = calcCheckDigit(payload);\n if (check === null) continue;\n const c = payload + String(check);\n if (validate(c).valid) return c;\n }\n};\n\n/**\n * Kazakhstan Individual Identification Number (IIN).\n *\n * Examples sourced from identique/idnumbers test suite.\n */\nconst iin: Validator<ParsedPersonId> = {\n name: \"Kazakhstan Individual ID\",\n localName: \"Жеке сәйкестендіру нөмірі\",\n abbreviation: \"IIN\",\n aliases: [\n \"ИИН\",\n \"IIN\",\n \"индивидуальный идентификационный номер\",\n ] as const,\n candidatePattern: \"\\\\d{12}\",\n country: \"KZ\",\n entityType: \"person\",\n lengths: [12] as const,\n examples: [\"880515300120\", \"950101400012\"] as const,\n compact,\n format,\n parse,\n validate,\n sourceUrl:\n \"https://www.oecd.org/tax/automatic-exchange/\" +\n \"crs-implementation-and-assistance/\" +\n \"tax-identification-numbers/Kazakhstan-TIN.pdf\",\n generate,\n};\n\nexport default iin;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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"}
|
package/dist/kz/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import iin from "./iin.js";
|
|
3
2
|
|
|
4
3
|
//#region src/kz/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { iin };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { iin, mod_d_exports };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/lei.d.ts
CHANGED
package/dist/li/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import peid from "./peid.js";
|
|
3
2
|
|
|
4
3
|
//#region src/li/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { peid };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { mod_d_exports, peid };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/lk/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import nic from "./nic.js";
|
|
3
2
|
|
|
4
3
|
//#region src/lk/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { nic };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { mod_d_exports, nic };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/lk/nic.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/lk/nic.d.ts
|
|
4
|
-
|
|
5
4
|
declare const compact: (value: string) => string;
|
|
6
5
|
declare const validate: (value: string) => ValidateResult;
|
|
7
6
|
declare const format: (value: string) => string;
|
|
@@ -10,8 +9,10 @@ declare const format: (value: string) => string;
|
|
|
10
9
|
* Returns null if the value is not valid.
|
|
11
10
|
*/
|
|
12
11
|
declare const parse: (value: string) => ParsedPersonId | null;
|
|
12
|
+
/** Generate a random valid Sri Lankan NIC. */
|
|
13
|
+
declare const generate: () => string;
|
|
13
14
|
/** Sri Lankan National Identity Card. */
|
|
14
|
-
declare const nic: Validator
|
|
15
|
+
declare const nic: Validator<ParsedPersonId>;
|
|
15
16
|
//#endregion
|
|
16
|
-
export { compact, nic as default, format, parse, validate };
|
|
17
|
+
export { compact, nic as default, format, generate, parse, validate };
|
|
17
18
|
//# sourceMappingURL=nic.d.ts.map
|
package/dist/lk/nic.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { clean } from "../_util/clean.js";
|
|
2
|
+
import { randomDigits, randomInt } from "../_util/generate.js";
|
|
2
3
|
import { err } from "../_util/result.js";
|
|
3
4
|
import { isdigits } from "../_util/strings.js";
|
|
4
5
|
import { isValidDate } from "../_util/date.js";
|
|
@@ -116,6 +117,15 @@ const parse = (value) => {
|
|
|
116
117
|
gender: info.gender
|
|
117
118
|
};
|
|
118
119
|
};
|
|
120
|
+
/** Generate a random valid Sri Lankan NIC. */
|
|
121
|
+
const generate = () => {
|
|
122
|
+
const year = randomInt(1950, 2024);
|
|
123
|
+
const start = new Date(year, 0, 1);
|
|
124
|
+
const end = new Date(year, 11, 31);
|
|
125
|
+
const dayOfYear = randomInt(1, Math.round((end.getTime() - start.getTime()) / 864e5) + 1);
|
|
126
|
+
const body = `${year}${String(dayOfYear + (Math.random() < .5 ? 0 : 500)).padStart(3, "0")}0${randomDigits(3)}`;
|
|
127
|
+
return `${body}${String(checkDigit(body))}`;
|
|
128
|
+
};
|
|
119
129
|
/** Sri Lankan National Identity Card. */
|
|
120
130
|
const nic = {
|
|
121
131
|
name: "National Identity Card",
|
|
@@ -131,9 +141,11 @@ const nic = {
|
|
|
131
141
|
examples: ["197819202757", "862348753V"],
|
|
132
142
|
compact,
|
|
133
143
|
format,
|
|
134
|
-
|
|
144
|
+
parse,
|
|
145
|
+
validate,
|
|
146
|
+
generate
|
|
135
147
|
};
|
|
136
148
|
//#endregion
|
|
137
|
-
export { compact, nic as default, format, parse, validate };
|
|
149
|
+
export { compact, nic as default, format, generate, parse, validate };
|
|
138
150
|
|
|
139
151
|
//# sourceMappingURL=nic.js.map
|
package/dist/lk/nic.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nic.js","names":[],"sources":["../../src/lk/nic.ts"],"sourcesContent":["/**\n * NIC (National Identity Card, ජාතික හැඳුනුම්පත).\n *\n * Sri Lankan personal identity number. Two formats:\n * Old (pre-2016): 9 digits + V or X (10 chars)\n * New (2016+): 12 digits\n *\n * Both encode birth date (day-of-year), gender, a\n * serial number, and a check digit.\n *\n * @see https://en.wikipedia.org/wiki/National_identification_number#Sri_Lanka\n * @see https://drp.gov.lk/Templates/Artical%20-%20English%20new%20number.html\n */\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\n/** Old format: 9 digits + V or X (case-insensitive). */\nconst OLD_RE = /^\\d{9}[VvXx]$/;\n\n/** New format: exactly 12 digits. */\nconst NEW_RE = /^\\d{12}$/;\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\n/**\n * Convert an old-format NIC to the 12-digit new\n * format for uniform validation.\n *\n * Old: YY DDD SSS C V/X (10 chars)\n * New: 19YY DDD 0SSS C (12 digits)\n */\nconst toNewFormat = (v: string): string => {\n const yy = v.slice(0, 2);\n const ddd = v.slice(2, 5);\n const sss = v.slice(5, 8);\n const check = v[8];\n return `19${yy}${ddd}0${sss}${check}`;\n};\n\n/**\n * Checksum weights for the first 11 digits.\n * Algorithm: weighted sum mod 11, then mod 10\n * if >= 10.\n */\nconst CHECK_WEIGHTS = [\n 8, 4, 3, 2, 7, 6, 5, 7, 4, 3, 2,\n] as const;\n\nconst checkDigit = (digits: string): number => {\n let sum = 0;\n for (let i = 0; i < 11; i++) {\n sum +=\n (CHECK_WEIGHTS[i] ?? 0) * Number(digits.charAt(i));\n }\n const d = 11 - (sum % 11);\n return d > 9 ? d % 10 : d;\n};\n\n/**\n * Resolve birth date and gender from the 12-digit\n * normalised form (YYYY DDD ...).\n *\n * Day-of-year encoding:\n * Male: 1–366\n * Female: 501–866 (subtract 500)\n */\nconst resolveBirthInfo = (\n v: string,\n): {\n year: number;\n month: number;\n day: number;\n gender: \"male\" | \"female\";\n} | null => {\n const year = Number(v.slice(0, 4));\n let days = Number(v.slice(4, 7));\n\n const gender: \"male\" | \"female\" =\n days > 500 ? \"female\" : \"male\";\n if (days > 500) days -= 500;\n\n if (days < 1 || days > 366) return null;\n\n // Convert day-of-year to month/day via Date\n const d = new Date(year, 0, days);\n const month = d.getMonth() + 1;\n const dayOfMonth = d.getDate();\n\n if (!isValidDate(year, month, dayOfMonth)) {\n return null;\n }\n\n // Guard against day 366 in non-leap years\n if (d.getFullYear() !== year) return null;\n\n return { year, month, day: dayOfMonth, gender };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n const isOld = OLD_RE.test(v);\n const isNew = NEW_RE.test(v);\n\n if (!isOld && !isNew) {\n if (v.length !== 10 && v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"NIC must be 10 (old) or 12 (new) characters\",\n );\n }\n return err(\n \"INVALID_FORMAT\",\n \"NIC must be 9 digits + V/X (old) or\" +\n \" 12 digits (new)\",\n );\n }\n\n const normalized = isOld ? toNewFormat(v) : v;\n\n if (!isdigits(normalized)) {\n return err(\n \"INVALID_FORMAT\",\n \"NIC contains invalid characters\",\n );\n }\n\n if (resolveBirthInfo(normalized) === null) {\n return err(\n \"INVALID_COMPONENT\",\n \"NIC contains an invalid date of birth\",\n );\n }\n\n const expected = checkDigit(normalized.slice(0, 11));\n if (expected !== Number(normalized[11])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"NIC check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n // Old format: YYDDDSSSXV → no standard separator\n // New format: YYYYDDDSSSSC → no standard separator\n return v;\n};\n\n/**\n * Extract birth date and gender from an NIC.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const isOld = OLD_RE.test(v);\n const normalized = isOld ? toNewFormat(v) : v;\n\n const info = resolveBirthInfo(normalized);\n if (info === null) return null;\n\n return {\n birthDate: new Date(\n info.year,\n info.month - 1,\n info.day,\n ),\n gender: info.gender,\n };\n};\n\n/** Sri Lankan National Identity Card. */\nconst nic: Validator = {\n name: \"National Identity Card\",\n localName: \"ජාතික හැඳුනුම්පත\",\n abbreviation: \"NIC\",\n aliases: [\"NIC\", \"ජාතික හැඳුනුම්පත\"] as const,\n candidatePattern: \"\\\\d{9}[VXvx]|\\\\d{12}\",\n country: \"LK\",\n entityType: \"person\",\n description:\n \"Sri Lankan personal identity number issued to\" +\n \" all citizens\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/\" +\n \"National_identification_number#Sri_Lanka\",\n lengths: [10, 12] as const,\n examples: [\"197819202757\", \"862348753V\"] as const,\n compact,\n format,\n validate,\n};\n\nexport default nic;\nexport { compact, format, parse, validate };\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"nic.js","names":[],"sources":["../../src/lk/nic.ts"],"sourcesContent":["/**\n * NIC (National Identity Card, ජාතික හැඳුනුම්පත).\n *\n * Sri Lankan personal identity number. Two formats:\n * Old (pre-2016): 9 digits + V or X (10 chars)\n * New (2016+): 12 digits\n *\n * Both encode birth date (day-of-year), gender, a\n * serial number, and a check digit.\n *\n * @see https://en.wikipedia.org/wiki/National_identification_number#Sri_Lanka\n * @see https://drp.gov.lk/Templates/Artical%20-%20English%20new%20number.html\n */\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\n/** Old format: 9 digits + V or X (case-insensitive). */\nconst OLD_RE = /^\\d{9}[VvXx]$/;\n\n/** New format: exactly 12 digits. */\nconst NEW_RE = /^\\d{12}$/;\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\n/**\n * Convert an old-format NIC to the 12-digit new\n * format for uniform validation.\n *\n * Old: YY DDD SSS C V/X (10 chars)\n * New: 19YY DDD 0SSS C (12 digits)\n */\nconst toNewFormat = (v: string): string => {\n const yy = v.slice(0, 2);\n const ddd = v.slice(2, 5);\n const sss = v.slice(5, 8);\n const check = v[8];\n return `19${yy}${ddd}0${sss}${check}`;\n};\n\n/**\n * Checksum weights for the first 11 digits.\n * Algorithm: weighted sum mod 11, then mod 10\n * if >= 10.\n */\nconst CHECK_WEIGHTS = [\n 8, 4, 3, 2, 7, 6, 5, 7, 4, 3, 2,\n] as const;\n\nconst checkDigit = (digits: string): number => {\n let sum = 0;\n for (let i = 0; i < 11; i++) {\n sum +=\n (CHECK_WEIGHTS[i] ?? 0) * Number(digits.charAt(i));\n }\n const d = 11 - (sum % 11);\n return d > 9 ? d % 10 : d;\n};\n\n/**\n * Resolve birth date and gender from the 12-digit\n * normalised form (YYYY DDD ...).\n *\n * Day-of-year encoding:\n * Male: 1–366\n * Female: 501–866 (subtract 500)\n */\nconst resolveBirthInfo = (\n v: string,\n): {\n year: number;\n month: number;\n day: number;\n gender: \"male\" | \"female\";\n} | null => {\n const year = Number(v.slice(0, 4));\n let days = Number(v.slice(4, 7));\n\n const gender: \"male\" | \"female\" =\n days > 500 ? \"female\" : \"male\";\n if (days > 500) days -= 500;\n\n if (days < 1 || days > 366) return null;\n\n // Convert day-of-year to month/day via Date\n const d = new Date(year, 0, days);\n const month = d.getMonth() + 1;\n const dayOfMonth = d.getDate();\n\n if (!isValidDate(year, month, dayOfMonth)) {\n return null;\n }\n\n // Guard against day 366 in non-leap years\n if (d.getFullYear() !== year) return null;\n\n return { year, month, day: dayOfMonth, gender };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n const isOld = OLD_RE.test(v);\n const isNew = NEW_RE.test(v);\n\n if (!isOld && !isNew) {\n if (v.length !== 10 && v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"NIC must be 10 (old) or 12 (new) characters\",\n );\n }\n return err(\n \"INVALID_FORMAT\",\n \"NIC must be 9 digits + V/X (old) or\" +\n \" 12 digits (new)\",\n );\n }\n\n const normalized = isOld ? toNewFormat(v) : v;\n\n if (!isdigits(normalized)) {\n return err(\n \"INVALID_FORMAT\",\n \"NIC contains invalid characters\",\n );\n }\n\n if (resolveBirthInfo(normalized) === null) {\n return err(\n \"INVALID_COMPONENT\",\n \"NIC contains an invalid date of birth\",\n );\n }\n\n const expected = checkDigit(normalized.slice(0, 11));\n if (expected !== Number(normalized[11])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"NIC check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n // Old format: YYDDDSSSXV → no standard separator\n // New format: YYYYDDDSSSSC → no standard separator\n return v;\n};\n\n/**\n * Extract birth date and gender from an NIC.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const isOld = OLD_RE.test(v);\n const normalized = isOld ? toNewFormat(v) : v;\n\n const info = resolveBirthInfo(normalized);\n if (info === null) return null;\n\n return {\n birthDate: new Date(\n info.year,\n info.month - 1,\n info.day,\n ),\n gender: info.gender,\n };\n};\n\n/** Generate a random valid Sri Lankan NIC. */\nconst generate = (): string => {\n const year = randomInt(1950, 2024);\n const start = new Date(year, 0, 1);\n const end = new Date(year, 11, 31);\n const maxDay =\n Math.round(\n (end.getTime() - start.getTime()) / 86_400_000,\n ) + 1;\n const dayOfYear = randomInt(1, maxDay);\n const genderOffset = Math.random() < 0.5 ? 0 : 500;\n const ddd = String(dayOfYear + genderOffset).padStart(\n 3,\n \"0\",\n );\n const body = `${year}${ddd}0${randomDigits(3)}`;\n return `${body}${String(checkDigit(body))}`;\n};\n\n/** Sri Lankan National Identity Card. */\nconst nic: Validator<ParsedPersonId> = {\n name: \"National Identity Card\",\n localName: \"ජාතික හැඳුනුම්පත\",\n abbreviation: \"NIC\",\n aliases: [\"NIC\", \"ජාතික හැඳුනුම්පත\"] as const,\n candidatePattern: \"\\\\d{9}[VXvx]|\\\\d{12}\",\n country: \"LK\",\n entityType: \"person\",\n description:\n \"Sri Lankan personal identity number issued to\" +\n \" all citizens\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/\" +\n \"National_identification_number#Sri_Lanka\",\n lengths: [10, 12] as const,\n examples: [\"197819202757\", \"862348753V\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default nic;\nexport { compact, format, generate, parse, validate };\n"],"mappings":"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"}
|
package/dist/lt/asmens.d.ts
CHANGED
package/dist/lt/mod.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import asmens from "./asmens.js";
|
|
3
2
|
import vat from "./vat.js";
|
|
4
3
|
|
|
5
4
|
//#region src/lt/mod.d.ts
|
|
6
|
-
|
|
5
|
+
declare namespace mod_d_exports {
|
|
6
|
+
export { asmens, vat };
|
|
7
|
+
}
|
|
7
8
|
//#endregion
|
|
8
9
|
export { asmens, mod_d_exports, vat };
|
|
9
10
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/lt/vat.d.ts
CHANGED
package/dist/lu/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import vat from "./vat.js";
|
|
3
2
|
|
|
4
3
|
//#region src/lu/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { vat };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { mod_d_exports, vat };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/lu/vat.d.ts
CHANGED
package/dist/luhn.d.ts
CHANGED
package/dist/luhn.js
CHANGED
|
@@ -38,7 +38,14 @@ const luhn = {
|
|
|
38
38
|
name: "Luhn",
|
|
39
39
|
localName: "Luhn",
|
|
40
40
|
abbreviation: "Luhn",
|
|
41
|
+
aliases: [
|
|
42
|
+
"Luhn",
|
|
43
|
+
"Luhn algorithm",
|
|
44
|
+
"mod 10"
|
|
45
|
+
],
|
|
46
|
+
candidatePattern: "\\d{2,}",
|
|
41
47
|
entityType: "any",
|
|
48
|
+
sourceUrl: "https://en.wikipedia.org/wiki/Luhn_algorithm",
|
|
42
49
|
examples: ["4111111111111111", "18"],
|
|
43
50
|
compact,
|
|
44
51
|
format,
|
package/dist/luhn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"luhn.js","names":[],"sources":["../src/luhn.ts"],"sourcesContent":["/**\n * Generic Luhn checksum validation.\n *\n * Validates any digit string using the Luhn\n * algorithm (ISO/IEC 7812-1). No length\n * restriction. For credit card validation\n * (13-19 digits), use `creditcard` instead.\n */\n\nimport {\n luhnChecksum,\n luhnValidate,\n} from \"#checksums/luhn\";\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"./types\";\n\nconst compact = (value: string): string =>\n clean(value, \" -.\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length < 1) {\n return err(\"INVALID_LENGTH\", \"Value must not be empty\");\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Value must contain only digits\",\n );\n }\n if (!luhnValidate(v)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Luhn check digit does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Generate a random Luhn-valid number of the\n * given length (default 16).\n */\nconst generate = (length = 16): string => {\n const payload = randomDigits(length - 1);\n const partial = `${payload}0`;\n const remainder = luhnChecksum(partial);\n const check = (10 - remainder) % 10;\n return `${payload}${String(check)}`;\n};\n\n/** Generic Luhn Validator. */\nconst luhn: Validator = {\n name: \"Luhn\",\n localName: \"Luhn\",\n abbreviation: \"Luhn\",\n entityType: \"any\",\n examples: [\"4111111111111111\", \"18\"] as const,\n compact,\n format,\n validate,\n generate: () => generate(),\n};\n\nexport default luhn;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;;;;;;AAoBA,MAAM,WAAW,UACf,MAAM,OAAO,MAAM;AAErB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,SAAS,EACb,QAAO,IAAI,kBAAkB,0BAA0B;AAEzD,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,iCACD;AAEH,KAAI,CAAC,aAAa,EAAE,CAClB,QAAO,IACL,oBACA,kCACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;;;;AAMxD,MAAM,YAAY,SAAS,OAAe;CACxC,MAAM,UAAU,aAAa,SAAS,EAAE;CAGxC,MAAM,SAAS,KADG,aADF,GAAG,QAAQ,GACY,IACN;AACjC,QAAO,GAAG,UAAU,OAAO,MAAM;;;AAInC,MAAM,OAAkB;CACtB,MAAM;CACN,WAAW;CACX,cAAc;CACd,YAAY;CACZ,UAAU,CAAC,oBAAoB,KAAK;CACpC;CACA;CACA;CACA,gBAAgB,UAAU;CAC3B"}
|
|
1
|
+
{"version":3,"file":"luhn.js","names":[],"sources":["../src/luhn.ts"],"sourcesContent":["/**\n * Generic Luhn checksum validation.\n *\n * Validates any digit string using the Luhn\n * algorithm (ISO/IEC 7812-1). No length\n * restriction. For credit card validation\n * (13-19 digits), use `creditcard` instead.\n */\n\nimport {\n luhnChecksum,\n luhnValidate,\n} from \"#checksums/luhn\";\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"./types\";\n\nconst compact = (value: string): string =>\n clean(value, \" -.\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length < 1) {\n return err(\"INVALID_LENGTH\", \"Value must not be empty\");\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Value must contain only digits\",\n );\n }\n if (!luhnValidate(v)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Luhn check digit does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Generate a random Luhn-valid number of the\n * given length (default 16).\n */\nconst generate = (length = 16): string => {\n const payload = randomDigits(length - 1);\n const partial = `${payload}0`;\n const remainder = luhnChecksum(partial);\n const check = (10 - remainder) % 10;\n return `${payload}${String(check)}`;\n};\n\n/** Generic Luhn Validator. */\nconst luhn: Validator = {\n name: \"Luhn\",\n localName: \"Luhn\",\n abbreviation: \"Luhn\",\n aliases: [\"Luhn\", \"Luhn algorithm\", \"mod 10\"] as const,\n candidatePattern: \"\\\\d{2,}\",\n entityType: \"any\",\n sourceUrl: \"https://en.wikipedia.org/wiki/Luhn_algorithm\",\n examples: [\"4111111111111111\", \"18\"] as const,\n compact,\n format,\n validate,\n generate: () => generate(),\n};\n\nexport default luhn;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;;;;;;AAoBA,MAAM,WAAW,UACf,MAAM,OAAO,MAAM;AAErB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,SAAS,EACb,QAAO,IAAI,kBAAkB,0BAA0B;AAEzD,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,iCACD;AAEH,KAAI,CAAC,aAAa,EAAE,CAClB,QAAO,IACL,oBACA,kCACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;;;;AAMxD,MAAM,YAAY,SAAS,OAAe;CACxC,MAAM,UAAU,aAAa,SAAS,EAAE;CAGxC,MAAM,SAAS,KADG,aADF,GAAG,QAAQ,GACY,IACN;AACjC,QAAO,GAAG,UAAU,OAAO,MAAM;;;AAInC,MAAM,OAAkB;CACtB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EAAC;EAAQ;EAAkB;EAAS;CAC7C,kBAAkB;CAClB,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,oBAAoB,KAAK;CACpC;CACA;CACA;CACA,gBAAgB,UAAU;CAC3B"}
|
package/dist/lv/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import vat from "./vat.js";
|
|
3
2
|
|
|
4
3
|
//#region src/lv/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { vat };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { mod_d_exports, vat };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/lv/vat.d.ts
CHANGED
package/dist/lv/vat.js
CHANGED
|
@@ -7,12 +7,29 @@ import { weightedSum } from "../_checksums/weighted-sum.js";
|
|
|
7
7
|
/**
|
|
8
8
|
* PVN (Latvian VAT number).
|
|
9
9
|
*
|
|
10
|
-
* 11 digits.
|
|
11
|
-
* weights [9,1,4,8,3,10,2,5,7,6,1], sum % 11 === 3.
|
|
12
|
-
* Personal (first digit <= 3): 11-digit format only.
|
|
10
|
+
* 11 digits.
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* Individuals:
|
|
13
|
+
* - legacy personal codes: DDMMYY + century digit 0/1/2 + 4 digits
|
|
14
|
+
* - since 1 July 2017: codes start with 3, the second digit is 2-9,
|
|
15
|
+
* and the remaining digits are random
|
|
16
|
+
*
|
|
17
|
+
* Entities:
|
|
18
|
+
* - tax administration issued: 9XXXXXXXXXX
|
|
19
|
+
* - enterprise register issued: 4XXXXXXXXXX / 5XXXXXXXXXX
|
|
20
|
+
*
|
|
21
|
+
* Canonical sources:
|
|
22
|
+
* - OECD Latvia TIN sheet for the tax-facing formats
|
|
23
|
+
* - PMLP page documenting the post-2017 personal code
|
|
24
|
+
*
|
|
25
|
+
* These are the reasons we accept the new personal
|
|
26
|
+
* code shape (`3` + second digit `2-9`) without the
|
|
27
|
+
* legacy birth-date checksum, and why we reject
|
|
28
|
+
* legacy personal codes with century digits outside
|
|
29
|
+
* 0/1/2.
|
|
30
|
+
*
|
|
31
|
+
* @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Latvia-TIN.pdf
|
|
32
|
+
* @see https://www.pmlp.gov.lv/en/change-personal-identity-number
|
|
16
33
|
*/
|
|
17
34
|
const WEIGHTS = [
|
|
18
35
|
9,
|
|
@@ -53,7 +70,9 @@ const validateBirthDate = (v) => {
|
|
|
53
70
|
const day = Number(v.slice(0, 2));
|
|
54
71
|
const month = Number(v.slice(2, 4));
|
|
55
72
|
const year2 = Number(v.slice(4, 6));
|
|
56
|
-
const
|
|
73
|
+
const century = Number(v[6]);
|
|
74
|
+
if (century < 0 || century > 2) return false;
|
|
75
|
+
const fullYear = 1800 + century * 100 + year2;
|
|
57
76
|
const date = new Date(fullYear, month - 1, day);
|
|
58
77
|
return date.getFullYear() === fullYear && date.getMonth() === month - 1 && date.getDate() === day;
|
|
59
78
|
};
|
|
@@ -61,10 +80,13 @@ const validate = (value) => {
|
|
|
61
80
|
const v = compact(value);
|
|
62
81
|
if (v.length !== 11) return err("INVALID_LENGTH", "Latvian VAT number must be 11 digits");
|
|
63
82
|
if (!isdigits(v)) return err("INVALID_FORMAT", "Latvian VAT number must contain only digits");
|
|
64
|
-
if (
|
|
83
|
+
if (v[0] === "3" && v[1] !== void 0 && v[1] >= "2" && v[1] <= "9") return {
|
|
84
|
+
valid: true,
|
|
85
|
+
compact: v
|
|
86
|
+
};
|
|
87
|
+
const first = v[0];
|
|
88
|
+
if (first === "4" || first === "5" || first === "9") {
|
|
65
89
|
if (weightedSum(v, WEIGHTS, 11) !== 3) return err("INVALID_CHECKSUM", "Latvian VAT number check digit mismatch");
|
|
66
|
-
} else if (v.startsWith("32")) {
|
|
67
|
-
if (!checkPersonal(v)) return err("INVALID_CHECKSUM", "Latvian personal code check digit mismatch");
|
|
68
90
|
} else {
|
|
69
91
|
if (!validateBirthDate(v)) return err("INVALID_COMPONENT", "Latvian personal code has invalid birth date");
|
|
70
92
|
if (!checkPersonal(v)) return err("INVALID_CHECKSUM", "Latvian personal code check digit mismatch");
|
|
@@ -77,8 +99,13 @@ const validate = (value) => {
|
|
|
77
99
|
const format = (value) => `LV${compact(value)}`;
|
|
78
100
|
/** Generate a random valid Latvian VAT number. */
|
|
79
101
|
const generate = () => {
|
|
102
|
+
const entityPrefixes = [
|
|
103
|
+
"4",
|
|
104
|
+
"5",
|
|
105
|
+
"9"
|
|
106
|
+
];
|
|
80
107
|
for (;;) {
|
|
81
|
-
const c =
|
|
108
|
+
const c = randomInt(0, 1) === 0 ? `3${randomInt(2, 9)}${randomDigits(9)}` : `${entityPrefixes[randomInt(0, entityPrefixes.length - 1)] ?? "4"}${randomDigits(10)}`;
|
|
82
109
|
if (validate(c).valid) return c;
|
|
83
110
|
}
|
|
84
111
|
};
|
|
@@ -91,8 +118,8 @@ const vat = {
|
|
|
91
118
|
candidatePattern: "LV\\d{11}",
|
|
92
119
|
country: "LV",
|
|
93
120
|
entityType: "any",
|
|
94
|
-
sourceUrl: "https://www.
|
|
95
|
-
examples: ["40003521600"],
|
|
121
|
+
sourceUrl: "https://www.pmlp.gov.lv/en/change-personal-identity-number",
|
|
122
|
+
examples: ["40003521600", "32999999999"],
|
|
96
123
|
compact,
|
|
97
124
|
format,
|
|
98
125
|
validate,
|