@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/patterns.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patterns.js","names":[],"sources":["../src/patterns.ts"],"sourcesContent":["/**\n * Derive candidate-matching regex patterns from\n * validators. These patterns find CANDIDATES in\n * text — use `validate()` to confirm each match.\n *\n * Designed for integration with regex-set or\n * similar multi-pattern scanning engines.\n *\n * @example\n * ```ts\n * import {\n * toRegex, byCountry, byEntityType,\n * } from \"@stll/stdnum/patterns\";\n * import { cz } from \"@stll/stdnum\";\n *\n * // Single validator\n * toRegex(cz.ico);\n * // → /(?<!\\w)\\d{8}(?!\\w)/g\n *\n * // All Czech validators\n * byCountry(\"CZ\");\n * // → [{ validator: cz.ico, regex }, ...]\n *\n * // All company identifiers\n * byEntityType(\"company\");\n * // → [{ validator, regex }, ...]\n * ```\n */\n\nimport type { CountryCode, Validator } from \"./types\";\n\n// ─── Pattern type ─────────────────────────────\n\nexport type ValidatorPattern = {\n /** The validator this pattern was derived from. */\n validator: Validator;\n /** Loose regex matching candidates in text. */\n regex: RegExp;\n};\n\n// ─── Regex derivation ─────────────────────────\n\n/** Separator chars that compact() strips. */\nconst SEP = \"[\\\\s\\\\-./]?\";\n\n/**\n * Infer compact lengths from metadata or examples.\n */\nconst inferLengths = (v: Validator): number[] => {\n if (v.lengths && v.lengths.length > 0) {\n return [...v.lengths];\n }\n if (v.examples && v.examples.length > 0) {\n const lens = new Set<number>();\n for (const ex of v.examples) {\n lens.add(v.compact(ex).length);\n }\n return [...lens];\n }\n return [];\n};\n\n/**\n * Derive the display grouping from format().\n * Returns an array of group sizes, e.g.,\n * \"25 123 891\" → [2, 3, 3].\n */\nconst inferGroups = (v: Validator): number[] | null => {\n if (!v.examples || v.examples.length === 0) {\n return null;\n }\n const compact = v.compact(v.examples[0]!);\n const formatted = v.format(compact);\n if (formatted === compact) return null;\n\n // Split on non-alphanumeric separators\n const parts = formatted.split(/[^a-zA-Z0-9]+/);\n if (parts.length <= 1) return null;\n\n // For digit-only validators, skip letter-only\n // tokens (prefix like \"CHE\"). For alphanumeric\n // validators (IBAN, ISIN), keep all groups.\n const isAlphanumeric = parts.some(\n (p) => /[a-zA-Z]/.test(p) && /\\d/.test(p),\n );\n const groups = parts\n .filter(\n (p) =>\n p.length > 0 && (isAlphanumeric || /\\d/.test(p)),\n )\n .map((p) => p.length);\n\n return groups.length > 1 ? groups : null;\n};\n\n/**\n * Detect if this validator uses a known prefix\n * (e.g., \"CZ\" for DIČ, \"CHE\" for Swiss UID).\n */\nconst inferPrefix = (v: Validator): string | null => {\n if (!v.examples || v.examples.length === 0) {\n return null;\n }\n const compact = v.compact(v.examples[0]!);\n // Prefix already present in compact form.\n // But only if ALL examples share the same prefix\n // (e.g., \"CHE\" for Swiss UID). If examples have\n // different prefixes (IBAN: GB/DE/FR), there's\n // no fixed prefix — it's part of the value.\n const compactMatch = compact.match(/^([A-Z]+)\\d/);\n if (compactMatch && v.examples!.length > 1) {\n const pfx = compactMatch[1]!;\n const allSame = v.examples!.every((ex) =>\n v.compact(ex).startsWith(pfx),\n );\n if (allSame) return pfx;\n } else if (compactMatch && v.examples!.length === 1) {\n return compactMatch[1]!;\n }\n // Prefix added only by format()\n // (e.g., \"DE\" for de.vat, \"CZ\" for cz.dic)\n const formatted = v.format(compact);\n const fmtMatch = formatted.match(/^([A-Z]+)[\\s\\-./]?\\d/);\n if (fmtMatch && !compact.startsWith(fmtMatch[1]!)) {\n return fmtMatch[1]!;\n }\n return null;\n};\n\n/**\n * Determine the character class needed for the\n * compact form: `\\d` if all digits, `[A-Z0-9]`\n * if alphanumeric, etc.\n */\nconst inferCharClass = (v: Validator): string => {\n if (!v.examples || v.examples.length === 0) {\n return \"\\\\d\";\n }\n let hasLetter = false;\n let hasDigit = false;\n for (const ex of v.examples) {\n const c = v.compact(ex);\n for (const ch of c) {\n if (/[a-zA-Z]/.test(ch)) hasLetter = true;\n if (/\\d/.test(ch)) hasDigit = true;\n }\n }\n if (hasLetter && hasDigit) return \"[A-Z0-9]\";\n if (hasLetter) return \"[A-Z]\";\n return \"\\\\d\";\n};\n\n/**\n * Build a group regex from group sizes + char class.\n * [2, 3, 3] with \\d → /\\d{2}[\\s\\-.]?\\d{3}[\\s\\-.]?\\d{3}/\n */\nconst groupsToPattern = (\n groups: number[],\n cc: string,\n): string => groups.map((g) => `${cc}{${g}}`).join(SEP);\n\n/**\n * Derive a loose candidate-matching regex from\n * a validator. The regex finds potential matches;\n * use `validate()` to confirm.\n *\n * Handles both digit-only (IČO, NIP) and\n * alphanumeric (IBAN, BIC, ISIN, LEI) validators.\n */\nexport const toRegex = (v: Validator): RegExp => {\n const prefix = inferPrefix(v);\n const groups = inferGroups(v);\n const lengths = inferLengths(v);\n const cc = inferCharClass(v);\n\n let pattern: string;\n\n if (groups && lengths.length <= 1) {\n pattern = groupsToPattern(groups, cc);\n } else if (lengths.length === 1) {\n pattern = `${cc}{${lengths[0]}}`;\n } else if (lengths.length > 1) {\n const min = Math.min(...lengths);\n const max = Math.max(...lengths);\n pattern = `${cc}{${min},${max}}`;\n } else {\n pattern = `${cc}{6,20}`;\n }\n\n if (prefix) {\n pattern = `${prefix}${SEP}${pattern}`;\n }\n\n // Word boundary to avoid matching inside\n // larger numbers\n return new RegExp(`(?<!\\\\w)${pattern}(?!\\\\w)`, \"g\");\n};\n\n// ─── Grouped collections ──────────────────────\n\n/**\n * All discovered validators, lazily populated.\n * Import * from \"../src\" would pull everything;\n * instead, callers pass validators explicitly.\n */\n\n/**\n * Build patterns for a list of validators.\n */\nexport const toPatterns = (\n validators: readonly Validator[],\n): ValidatorPattern[] =>\n validators.map((v) => ({\n validator: v,\n regex: toRegex(v),\n }));\n\n/**\n * Filter validators by country code and build\n * patterns.\n */\nexport const byCountry = (\n country: CountryCode,\n validators: readonly Validator[],\n): ValidatorPattern[] =>\n toPatterns(\n validators.filter((v) => v.country === country),\n );\n\n/**\n * Filter validators by entity type and build\n * patterns.\n */\nexport const byEntityType = (\n entityType: \"person\" | \"company\" | \"any\",\n validators: readonly Validator[],\n): ValidatorPattern[] =>\n toPatterns(\n validators.filter(\n (v) =>\n entityType === \"any\" ||\n v.entityType === entityType ||\n v.entityType === \"any\",\n ),\n );\n\n/**\n * Build patterns for ALL provided validators.\n */\nexport const allPatterns = (\n validators: readonly Validator[],\n): ValidatorPattern[] => toPatterns(validators);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"patterns.js","names":[],"sources":["../src/patterns.ts"],"sourcesContent":["/**\n * Derive candidate-matching regex patterns from\n * validators. These patterns find CANDIDATES in\n * text — use `validate()` to confirm each match.\n *\n * Designed for integration with regex-set or\n * similar multi-pattern scanning engines.\n *\n * @example\n * ```ts\n * import {\n * toRegex, byCountry, byEntityType,\n * } from \"@stll/stdnum/patterns\";\n * import { cz } from \"@stll/stdnum\";\n *\n * // Single validator\n * toRegex(cz.ico);\n * // → /(?<!\\w)\\d{8}(?!\\w)/g\n *\n * // All Czech validators\n * byCountry(\"CZ\");\n * // → [{ validator: cz.ico, regex }, ...]\n *\n * // All company identifiers\n * byEntityType(\"company\");\n * // → [{ validator, regex }, ...]\n * ```\n */\n\nimport type { CountryCode, Validator } from \"./types\";\n\n// ─── Pattern type ─────────────────────────────\n\nexport type ValidatorPattern = {\n /** The validator this pattern was derived from. */\n validator: Validator;\n /** Loose regex matching candidates in text. */\n regex: RegExp;\n};\n\n// ─── Regex derivation ─────────────────────────\n\n/** Separator chars that compact() strips. */\nconst SEP = \"[\\\\s\\\\-./]?\";\n\n/**\n * Infer compact lengths from metadata or examples.\n */\nconst inferLengths = (v: Validator): number[] => {\n if (v.lengths && v.lengths.length > 0) {\n return [...v.lengths];\n }\n if (v.examples && v.examples.length > 0) {\n const lens = new Set<number>();\n for (const ex of v.examples) {\n lens.add(v.compact(ex).length);\n }\n return [...lens];\n }\n return [];\n};\n\n/**\n * Derive the display grouping from format().\n * Returns an array of group sizes, e.g.,\n * \"25 123 891\" → [2, 3, 3].\n */\nconst inferGroups = (v: Validator): number[] | null => {\n const first = v.examples?.[0];\n if (first === undefined) return null;\n const compact = v.compact(first);\n const formatted = v.format(compact);\n if (formatted === compact) return null;\n\n // Split on non-alphanumeric separators\n const parts = formatted.split(/[^a-zA-Z0-9]+/);\n if (parts.length <= 1) return null;\n\n // For digit-only validators, skip letter-only\n // tokens (prefix like \"CHE\"). For alphanumeric\n // validators (IBAN, ISIN), keep all groups.\n const isAlphanumeric = parts.some(\n (p) => /[a-zA-Z]/.test(p) && /\\d/.test(p),\n );\n const groups = parts\n .filter(\n (p) =>\n p.length > 0 && (isAlphanumeric || /\\d/.test(p)),\n )\n .map((p) => p.length);\n\n return groups.length > 1 ? groups : null;\n};\n\n/**\n * Detect if this validator uses a known prefix\n * (e.g., \"CZ\" for DIČ, \"CHE\" for Swiss UID).\n */\nconst inferPrefix = (v: Validator): string | null => {\n const examples = v.examples;\n const first = examples?.[0];\n if (!examples || first === undefined) return null;\n const compact = v.compact(first);\n // Prefix already present in compact form.\n // But only if ALL examples share the same prefix\n // (e.g., \"CHE\" for Swiss UID). If examples have\n // different prefixes (IBAN: GB/DE/FR), there's\n // no fixed prefix — it's part of the value.\n const compactMatch = compact.match(/^([A-Z]+)\\d/);\n const compactPrefix = compactMatch?.[1];\n if (compactPrefix !== undefined && examples.length > 1) {\n const allSame = examples.every((ex) =>\n v.compact(ex).startsWith(compactPrefix),\n );\n if (allSame) return compactPrefix;\n } else if (\n compactPrefix !== undefined &&\n examples.length === 1\n ) {\n return compactPrefix;\n }\n // Prefix added only by format()\n // (e.g., \"DE\" for de.vat, \"CZ\" for cz.dic)\n const formatted = v.format(compact);\n const fmtMatch = formatted.match(/^([A-Z]+)[\\s\\-./]?\\d/);\n const fmtPrefix = fmtMatch?.[1];\n if (\n fmtPrefix !== undefined &&\n !compact.startsWith(fmtPrefix)\n ) {\n return fmtPrefix;\n }\n return null;\n};\n\n/**\n * Character class for a string fragment:\n * `\\d` if all digits, `[A-Z]` if all letters,\n * `[A-Z0-9]` if mixed.\n */\nconst charClassFor = (s: string): string => {\n let hasLetter = false;\n let hasDigit = false;\n for (const ch of s) {\n if (/[a-zA-Z]/.test(ch)) hasLetter = true;\n if (/\\d/.test(ch)) hasDigit = true;\n }\n if (hasLetter && hasDigit) return \"[A-Z0-9]\";\n if (hasLetter) return \"[A-Z]\";\n return \"\\\\d\";\n};\n\n/**\n * Determine the character class needed for the\n * compact form: `\\d` if all digits, `[A-Z0-9]`\n * if alphanumeric, etc.\n */\nconst inferCharClass = (v: Validator): string => {\n if (!v.examples || v.examples.length === 0) {\n return \"\\\\d\";\n }\n const combined = v.examples\n .map((ex) => v.compact(ex))\n .join(\"\");\n return charClassFor(combined);\n};\n\ntype PerGroup = { size: number; charClass: string };\n\n/**\n * Infer per-group sizes AND character classes from\n * format(). Returns groups with per-position char\n * classes, e.g., \"12 010188 M 01 1\" →\n * sizes: [2, 6, 1, 2, 1]\n * classes: [\"\\d\", \"\\d\", \"[A-Z]\", \"\\d\", \"\\d\"]\n *\n * Only returns non-null when per-group classes\n * differ (some groups are letters, some digits).\n * Letter-only groups before the first digit group\n * are treated as prefixes and excluded (handled\n * by inferPrefix separately).\n */\nconst inferPerGroup = (v: Validator): PerGroup[] | null => {\n const first = v.examples?.[0];\n if (first === undefined) return null;\n const compact = v.compact(first);\n const formatted = v.format(compact);\n if (formatted === compact) return null;\n\n // Only applies to mixed validators (compact has\n // both letters and digits in separate positions,\n // like German SVNR \"12010188M011\").\n const compactMixed =\n /[a-zA-Z]/.test(compact) && /\\d/.test(compact);\n if (!compactMixed) return null;\n\n // Also skip if any single part mixes letters and\n // digits (IBAN, ISIN) — inferGroups already\n // handles those correctly with the global class.\n const parts = formatted.split(/[^a-zA-Z0-9]+/);\n const isAlphanumeric = parts.some(\n (p) => /[a-zA-Z]/.test(p) && /\\d/.test(p),\n );\n if (isAlphanumeric) return null;\n\n // Keep digit groups and letter-only groups that\n // appear AFTER the first digit group (embedded\n // letters). Skip letter-only groups before the\n // first digit group (prefix like \"CHE\").\n const filtered: PerGroup[] = [];\n let seenDigitGroup = false;\n for (const p of parts) {\n if (p.length === 0) continue;\n if (/\\d/.test(p)) {\n seenDigitGroup = true;\n filtered.push({\n size: p.length,\n charClass: charClassFor(p),\n });\n } else if (seenDigitGroup) {\n filtered.push({\n size: p.length,\n charClass: charClassFor(p),\n });\n }\n }\n\n if (filtered.length <= 1) return null;\n\n const firstClass = filtered[0]?.charClass;\n const allSame = filtered.every(\n (g) => g.charClass === firstClass,\n );\n if (allSame) return null;\n\n return filtered;\n};\n\n/**\n * Build a group regex from group sizes + char class.\n * [2, 3, 3] with \\d → /\\d{2}[\\s\\-.]?\\d{3}[\\s\\-.]?\\d{3}/\n */\nconst groupsToPattern = (\n groups: number[],\n cc: string,\n): string => groups.map((g) => `${cc}{${g}}`).join(SEP);\n\n/**\n * Build a group regex with per-group char classes.\n * Produces tighter patterns when groups have different\n * character types (e.g., digits vs letters).\n */\nconst groupsToPatternPerClass = (\n groups: readonly { size: number; charClass: string }[],\n): string =>\n groups\n .map(({ size, charClass }) => `${charClass}{${size}}`)\n .join(SEP);\n\n/**\n * Derive a loose candidate-matching regex from\n * a validator. The regex finds potential matches;\n * use `validate()` to confirm.\n *\n * Handles both digit-only (IČO, NIP) and\n * alphanumeric (IBAN, BIC, ISIN, LEI) validators.\n */\nexport const toRegex = (v: Validator): RegExp => {\n const prefix = inferPrefix(v);\n const groups = inferGroups(v);\n const lengths = inferLengths(v);\n const cc = inferCharClass(v);\n\n let pattern: string;\n\n // Use per-group char classes when groups mix\n // digits and letters (e.g., German SVNR:\n // \"12 010188 M 01 1\" → [\\d, \\d, [A-Z], \\d, \\d]).\n // This prevents overly broad [A-Z0-9] from\n // matching all-caps prose as identifiers.\n const perGroup = inferPerGroup(v);\n\n if (perGroup && lengths.length <= 1) {\n pattern = groupsToPatternPerClass(perGroup);\n } else if (groups && lengths.length <= 1) {\n pattern = groupsToPattern(groups, cc);\n } else if (lengths.length === 1) {\n pattern = `${cc}{${lengths[0]}}`;\n } else if (lengths.length > 1) {\n const min = Math.min(...lengths);\n const max = Math.max(...lengths);\n pattern = `${cc}{${min},${max}}`;\n } else {\n pattern = `${cc}{6,20}`;\n }\n\n if (prefix) {\n pattern = `${prefix}${SEP}${pattern}`;\n }\n\n // Word boundary to avoid matching inside\n // larger numbers\n return new RegExp(`(?<!\\\\w)${pattern}(?!\\\\w)`, \"g\");\n};\n\n// ─── Grouped collections ──────────────────────\n\n/**\n * All discovered validators, lazily populated.\n * Import * from \"../src\" would pull everything;\n * instead, callers pass validators explicitly.\n */\n\n/**\n * Build patterns for a list of validators.\n */\nexport const toPatterns = (\n validators: readonly Validator[],\n): ValidatorPattern[] =>\n validators.map((v) => ({\n validator: v,\n regex: toRegex(v),\n }));\n\n/**\n * Filter validators by country code and build\n * patterns.\n */\nexport const byCountry = (\n country: CountryCode,\n validators: readonly Validator[],\n): ValidatorPattern[] =>\n toPatterns(\n validators.filter((v) => v.country === country),\n );\n\n/**\n * Filter validators by entity type and build\n * patterns.\n */\nexport const byEntityType = (\n entityType: \"person\" | \"company\" | \"any\",\n validators: readonly Validator[],\n): ValidatorPattern[] =>\n toPatterns(\n validators.filter(\n (v) =>\n entityType === \"any\" ||\n v.entityType === entityType ||\n v.entityType === \"any\",\n ),\n );\n\n/**\n * Build patterns for ALL provided validators.\n */\nexport const allPatterns = (\n validators: readonly Validator[],\n): ValidatorPattern[] => toPatterns(validators);\n"],"mappings":"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"}
|
package/dist/pe/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import ruc from "./ruc.js";
|
|
3
2
|
|
|
4
3
|
//#region src/pe/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { ruc };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { mod_d_exports, ruc };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/pe/ruc.d.ts
CHANGED
package/dist/pe/ruc.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { clean } from "../_util/clean.js";
|
|
2
|
-
import { randomDigits } from "../_util/generate.js";
|
|
2
|
+
import { randomDigits, randomPick } from "../_util/generate.js";
|
|
3
3
|
import { err } from "../_util/result.js";
|
|
4
4
|
import { isdigits } from "../_util/strings.js";
|
|
5
5
|
//#region src/pe/ruc.ts
|
|
@@ -42,6 +42,12 @@ const WEIGHTS = [
|
|
|
42
42
|
3,
|
|
43
43
|
2
|
|
44
44
|
];
|
|
45
|
+
const GENERATE_PREFIXES = [
|
|
46
|
+
"10",
|
|
47
|
+
"15",
|
|
48
|
+
"17",
|
|
49
|
+
"20"
|
|
50
|
+
];
|
|
45
51
|
const compact = (value) => clean(value, " -.").trim();
|
|
46
52
|
/**
|
|
47
53
|
* Compute the RUC check digit using weighted sum
|
|
@@ -51,7 +57,7 @@ const compact = (value) => clean(value, " -.").trim();
|
|
|
51
57
|
*/
|
|
52
58
|
const calcCheckDigit = (body) => {
|
|
53
59
|
let sum = 0;
|
|
54
|
-
for (
|
|
60
|
+
for (const [i, weight] of WEIGHTS.entries()) sum += Number(body[i]) * weight;
|
|
55
61
|
const remainder = 11 - sum % 11;
|
|
56
62
|
if (remainder >= 10) return remainder - 10;
|
|
57
63
|
return remainder;
|
|
@@ -72,13 +78,7 @@ const validate = (value) => {
|
|
|
72
78
|
const format = (value) => compact(value);
|
|
73
79
|
/** Generate a random valid Peruvian RUC. */
|
|
74
80
|
const generate = () => {
|
|
75
|
-
const
|
|
76
|
-
"10",
|
|
77
|
-
"15",
|
|
78
|
-
"17",
|
|
79
|
-
"20"
|
|
80
|
-
];
|
|
81
|
-
const body = prefixes[Math.floor(Math.random() * prefixes.length)] + randomDigits(8);
|
|
81
|
+
const body = randomPick(GENERATE_PREFIXES) + randomDigits(8);
|
|
82
82
|
return body + String(calcCheckDigit(body));
|
|
83
83
|
};
|
|
84
84
|
/**
|
package/dist/pe/ruc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ruc.js","names":[],"sources":["../../src/pe/ruc.ts"],"sourcesContent":["/**\n * RUC (Registro Único de Contribuyentes).\n *\n * Peruvian tax identification number assigned by SUNAT\n * (Superintendencia Nacional de Aduanas y de\n * Administración Tributaria). The number consists of\n * 11 digits: a type prefix (10 = person, 20 = company,\n * among others), 8 identification digits, and a check\n * digit computed using a weighted modulo 11 algorithm.\n *\n * Format: XXXXXXXXXXX (11 digits, no separators).\n *\n * @see https://www.sunat.gob.pe/\n * @see https://en.wikipedia.org/wiki/Tax_identification_number#Peru\n */\n\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\n/**\n * Valid type prefixes for RUC numbers.\n * 10 = natural person, 15 = non-domiciled without RUC,\n * 17 = non-domiciled, 20 = legal entity,\n * others for specific entity types.\n */\nconst VALID_PREFIXES = new Set([\"10\", \"15\", \"17\", \"20\"]);\n\nconst WEIGHTS = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];\n\nconst compact = (value: string): string =>\n clean(value, \" -.\").trim();\n\n/**\n * Compute the RUC check digit using weighted sum\n * mod 11. Weights: [5, 4, 3, 2, 7, 6, 5, 4, 3, 2].\n *\n * check = 11 - (sum % 11); if >= 10, subtract 10.\n */\nconst calcCheckDigit = (body: string): number => {\n let sum = 0;\n for (
|
|
1
|
+
{"version":3,"file":"ruc.js","names":[],"sources":["../../src/pe/ruc.ts"],"sourcesContent":["/**\n * RUC (Registro Único de Contribuyentes).\n *\n * Peruvian tax identification number assigned by SUNAT\n * (Superintendencia Nacional de Aduanas y de\n * Administración Tributaria). The number consists of\n * 11 digits: a type prefix (10 = person, 20 = company,\n * among others), 8 identification digits, and a check\n * digit computed using a weighted modulo 11 algorithm.\n *\n * Format: XXXXXXXXXXX (11 digits, no separators).\n *\n * @see https://www.sunat.gob.pe/\n * @see https://en.wikipedia.org/wiki/Tax_identification_number#Peru\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomPick } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\n/**\n * Valid type prefixes for RUC numbers.\n * 10 = natural person, 15 = non-domiciled without RUC,\n * 17 = non-domiciled, 20 = legal entity,\n * others for specific entity types.\n */\nconst VALID_PREFIXES = new Set([\"10\", \"15\", \"17\", \"20\"]);\n\nconst WEIGHTS = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2] as const;\nconst GENERATE_PREFIXES = [\"10\", \"15\", \"17\", \"20\"] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -.\").trim();\n\n/**\n * Compute the RUC check digit using weighted sum\n * mod 11. Weights: [5, 4, 3, 2, 7, 6, 5, 4, 3, 2].\n *\n * check = 11 - (sum % 11); if >= 10, subtract 10.\n */\nconst calcCheckDigit = (body: string): number => {\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n sum += Number(body[i]) * weight;\n }\n const remainder = 11 - (sum % 11);\n if (remainder >= 10) return remainder - 10;\n return remainder;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 11) {\n return err(\"INVALID_LENGTH\", \"RUC must be 11 digits\");\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"RUC must contain only digits\",\n );\n }\n\n const prefix = v.slice(0, 2);\n if (!VALID_PREFIXES.has(prefix)) {\n return err(\n \"INVALID_COMPONENT\",\n \"RUC has an invalid type prefix\",\n );\n }\n\n const expected = calcCheckDigit(v.slice(0, 10));\n if (Number(v[10]) !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"RUC check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Peruvian RUC. */\nconst generate = (): string => {\n const prefix = randomPick(GENERATE_PREFIXES);\n const body = prefix + randomDigits(8);\n return body + String(calcCheckDigit(body));\n};\n\n/**\n * Peruvian RUC (tax identification number).\n *\n * Examples sourced from python-stdnum test suite\n * (pe.ruc module).\n */\nconst ruc: Validator = {\n name: \"Peruvian Tax ID\",\n localName: \"Registro Único de Contribuyentes\",\n abbreviation: \"RUC\",\n aliases: [\"RUC\"] as const,\n candidatePattern: \"\\\\d{11}\",\n country: \"PE\",\n entityType: \"any\",\n compact,\n format,\n validate,\n sourceUrl: \"https://www.sunat.gob.pe/\",\n lengths: [11] as const,\n examples: [\"20131312955\", \"20100047218\"] as const,\n generate,\n};\n\nexport default ruc;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAM,iBAAiB,IAAI,IAAI;CAAC;CAAM;CAAM;CAAM;CAAK,CAAC;AAExD,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;AAC9C,MAAM,oBAAoB;CAAC;CAAM;CAAM;CAAM;CAAK;AAElD,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,CAAC,MAAM;;;;;;;AAQ5B,MAAM,kBAAkB,SAAyB;CAC/C,IAAI,MAAM;AACV,MAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,SAAS,CACzC,QAAO,OAAO,KAAK,GAAG,GAAG;CAE3B,MAAM,YAAY,KAAM,MAAM;AAC9B,KAAI,aAAa,GAAI,QAAO,YAAY;AACxC,QAAO;;AAGT,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,WAAW,GACf,QAAO,IAAI,kBAAkB,wBAAwB;AAGvD,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,+BACD;CAGH,MAAM,SAAS,EAAE,MAAM,GAAG,EAAE;AAC5B,KAAI,CAAC,eAAe,IAAI,OAAO,CAC7B,QAAO,IACL,qBACA,iCACD;CAGH,MAAM,WAAW,eAAe,EAAE,MAAM,GAAG,GAAG,CAAC;AAC/C,KAAI,OAAO,EAAE,IAAI,KAAK,SACpB,QAAO,IACL,oBACA,iCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,iBAAyB;CAE7B,MAAM,OADS,WAAW,kBAAkB,GACtB,aAAa,EAAE;AACrC,QAAO,OAAO,OAAO,eAAe,KAAK,CAAC;;;;;;;;AAS5C,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,MAAM;CAChB,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ;CACA;CACA;CACA,WAAW;CACX,SAAS,CAAC,GAAG;CACb,UAAU,CAAC,eAAe,cAAc;CACxC;CACD"}
|
package/dist/ph/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import philid from "./philid.js";
|
|
3
2
|
|
|
4
3
|
//#region src/ph/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { philid };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { mod_d_exports, philid };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/pk/cnic.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cnic.js","names":[],"sources":["../../src/pk/cnic.ts"],"sourcesContent":["/** Generate a random valid Pakistan CNIC. */\nconst generate = (): string => {\n const province = String(randomInt(1, 7));\n const district = randomDigits(4);\n const serial = randomDigits(7);\n const gender = String(randomInt(1, 9));\n return `${province}${district}${serial}${gender}`;\n};\n\n/**\n * CNIC (Computerized National Identity Card, Pakistan).\n *\n * 13 digits: PPPPP-DDDDDDD-G where P is a province/\n * district code (5 digits), D is a sequential number\n * (7 digits), and G is a gender digit (odd = male,\n * even = female, including 0). No checksum; structural\n * validation.\n *\n * @see https://www.geo.tv/latest/157233-secret-behind-every-digit-of-the-cnic-number\n * @see https://en.wikipedia.org/wiki/CNIC_(Pakistan)\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } 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\n/** Valid province IDs (first digit). */\nconst VALID_PROVINCES = new Set([\n \"1\",\n \"2\",\n \"3\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n]);\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\"INVALID_LENGTH\", \"CNIC must be 13 digits\");\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CNIC must contain only digits\",\n );\n }\n // First digit must be a valid province code\n if (!VALID_PROVINCES.has(v[0]!)) {\n return err(\n \"INVALID_COMPONENT\",\n \"CNIC province code is invalid\",\n );\n }\n // Last digit indicates gender: odd = male,\n // even = female. Digit 0 is rejected per\n // python-stdnum convention; NADRA does not\n // publish whether 0 is a valid gender code.\n // @see https://www.geo.tv/latest/157233\n if (v[12] === \"0\") {\n return err(\n \"INVALID_COMPONENT\",\n \"CNIC gender digit must not be 0\",\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, 5)}-${v.slice(5, 12)}-${v.slice(12)}`;\n};\n\n/** Pakistan Computerized National Identity Card. */\nconst cnic: Validator = {\n name: \"Computerized National Identity Card\",\n localName: \"Computerized National Identity Card\",\n abbreviation: \"CNIC\",\n aliases: [\"CNIC\", \"شناختی کارڈ\"] as const,\n candidatePattern: \"\\\\d{5}-?\\\\d{7}-?\\\\d\",\n country: \"PK\",\n entityType: \"person\",\n lengths: [13],\n examples: [\"3520112345671\", \"4210112345672\"],\n description:\n \"13-digit identity card number issued by NADRA\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/CNIC_(Pakistan)\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cnic;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;AACA,MAAM,iBAAyB;AAK7B,QAAO,GAJU,OAAO,UAAU,GAAG,EAAE,CAAC,GACvB,aAAa,EAAE,GACjB,aAAa,EAAE,GACf,OAAO,UAAU,GAAG,EAAE,CAAC;;AAwBxC,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;;AAGpB,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IAAI,kBAAkB,yBAAyB;AAExD,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,gCACD;
|
|
1
|
+
{"version":3,"file":"cnic.js","names":[],"sources":["../../src/pk/cnic.ts"],"sourcesContent":["/** Generate a random valid Pakistan CNIC. */\nconst generate = (): string => {\n const province = String(randomInt(1, 7));\n const district = randomDigits(4);\n const serial = randomDigits(7);\n const gender = String(randomInt(1, 9));\n return `${province}${district}${serial}${gender}`;\n};\n\n/**\n * CNIC (Computerized National Identity Card, Pakistan).\n *\n * 13 digits: PPPPP-DDDDDDD-G where P is a province/\n * district code (5 digits), D is a sequential number\n * (7 digits), and G is a gender digit (odd = male,\n * even = female, including 0). No checksum; structural\n * validation.\n *\n * @see https://www.geo.tv/latest/157233-secret-behind-every-digit-of-the-cnic-number\n * @see https://en.wikipedia.org/wiki/CNIC_(Pakistan)\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } 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\n/** Valid province IDs (first digit). */\nconst VALID_PROVINCES = new Set([\n \"1\",\n \"2\",\n \"3\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n]);\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\"INVALID_LENGTH\", \"CNIC must be 13 digits\");\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CNIC must contain only digits\",\n );\n }\n // First digit must be a valid province code\n // SAFETY: v.length === 13 above guarantees v[0] exists.\n // eslint-disable-next-line no-non-null-assertion\n if (!VALID_PROVINCES.has(v[0]!)) {\n return err(\n \"INVALID_COMPONENT\",\n \"CNIC province code is invalid\",\n );\n }\n // Last digit indicates gender: odd = male,\n // even = female. Digit 0 is rejected per\n // python-stdnum convention; NADRA does not\n // publish whether 0 is a valid gender code.\n // @see https://www.geo.tv/latest/157233\n if (v[12] === \"0\") {\n return err(\n \"INVALID_COMPONENT\",\n \"CNIC gender digit must not be 0\",\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, 5)}-${v.slice(5, 12)}-${v.slice(12)}`;\n};\n\n/** Pakistan Computerized National Identity Card. */\nconst cnic: Validator = {\n name: \"Computerized National Identity Card\",\n localName: \"Computerized National Identity Card\",\n abbreviation: \"CNIC\",\n aliases: [\"CNIC\", \"شناختی کارڈ\"] as const,\n candidatePattern: \"\\\\d{5}-?\\\\d{7}-?\\\\d\",\n country: \"PK\",\n entityType: \"person\",\n lengths: [13],\n examples: [\"3520112345671\", \"4210112345672\"],\n description:\n \"13-digit identity card number issued by NADRA\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/CNIC_(Pakistan)\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cnic;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;AACA,MAAM,iBAAyB;AAK7B,QAAO,GAJU,OAAO,UAAU,GAAG,EAAE,CAAC,GACvB,aAAa,EAAE,GACjB,aAAa,EAAE,GACf,OAAO,UAAU,GAAG,EAAE,CAAC;;AAwBxC,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;;AAGpB,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IAAI,kBAAkB,yBAAyB;AAExD,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,gCACD;AAKH,KAAI,CAAC,gBAAgB,IAAI,EAAE,GAAI,CAC7B,QAAO,IACL,qBACA,gCACD;AAOH,KAAI,EAAE,QAAQ,IACZ,QAAO,IACL,qBACA,kCACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,QAAO,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG;;;AAI1D,MAAM,OAAkB;CACtB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,QAAQ,cAAc;CAChC,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,GAAG;CACb,UAAU,CAAC,iBAAiB,gBAAgB;CAC5C,aACE;CACF,WACE;CACF;CACA;CACA;CACA;CACD"}
|
package/dist/pk/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import cnic from "./cnic.js";
|
|
3
2
|
|
|
4
3
|
//#region src/pk/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { cnic };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { cnic, mod_d_exports };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/pl/mod.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import nip from "./nip.js";
|
|
3
2
|
import pesel from "./pesel.js";
|
|
4
3
|
import regon from "./regon.js";
|
|
5
4
|
|
|
6
5
|
//#region src/pl/mod.d.ts
|
|
7
|
-
|
|
6
|
+
declare namespace mod_d_exports {
|
|
7
|
+
export { nip, pesel, regon };
|
|
8
|
+
}
|
|
8
9
|
//#endregion
|
|
9
10
|
export { mod_d_exports, nip, pesel, regon };
|
|
10
11
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/pl/nip.d.ts
CHANGED
package/dist/pl/pesel.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/pl/pesel.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;
|
|
@@ -13,7 +12,7 @@ declare const parse: (value: string) => ParsedPersonId | null;
|
|
|
13
12
|
/** Generate a random valid Polish PESEL. */
|
|
14
13
|
declare const generate: () => string;
|
|
15
14
|
/** Polish National Identification Number. */
|
|
16
|
-
declare const pesel: Validator
|
|
15
|
+
declare const pesel: Validator<ParsedPersonId>;
|
|
17
16
|
//#endregion
|
|
18
17
|
export { compact, pesel as default, format, generate, parse, validate };
|
|
19
18
|
//# sourceMappingURL=pesel.d.ts.map
|
package/dist/pl/pesel.js
CHANGED
package/dist/pl/pesel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pesel.js","names":[],"sources":["../../src/pl/pesel.ts"],"sourcesContent":["/**\n * PESEL (Powszechny Elektroniczny System\n * Ewidencji Ludności).\n *\n * Polish national identification number.\n * 11 digits encoding date of birth, serial\n * number, gender, and a check digit.\n *\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/poland-tin.pdf\n * @see https://www.gov.pl/web/cyfryzacja/numer-pesel\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, 3, 7, 9, 1, 3, 7, 9, 1, 3] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"PESEL must be exactly 11 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"PESEL must contain only digits\",\n );\n }\n\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\n // Century encoding via month offset\n let century: number;\n if (mm >= 81 && mm <= 92) {\n century = 1800;\n } else if (mm >= 1 && mm <= 12) {\n century = 1900;\n } else if (mm >= 21 && mm <= 32) {\n century = 2000;\n } else if (mm >= 41 && mm <= 52) {\n century = 2100;\n } else if (mm >= 61 && mm <= 72) {\n century = 2200;\n } else {\n return err(\n \"INVALID_COMPONENT\",\n \"PESEL contains an invalid month\",\n );\n }\n\n const year = century + yy;\n const month = mm % 20;\n if (!isValidDate(year, month, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"PESEL contains an invalid date\",\n );\n }\n\n const sum = weightedSum(v.slice(0, 10), WEIGHTS, 10);\n const check = (10 - sum) % 10;\n if (check !== Number(v[10])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"PESEL check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a PESEL number.\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 yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n const serial = Number(v[9]);\n\n let century: number;\n if (mm >= 81) century = 1800;\n else if (mm <= 12) century = 1900;\n else if (mm <= 32) century = 2000;\n else if (mm <= 52) century = 2100;\n else century = 2200;\n\n return {\n birthDate: new Date(century + yy, (mm % 20) - 1, dd),\n gender: serial % 2 === 0 ? \"female\" : \"male\",\n };\n};\n\n/** Generate a random valid Polish PESEL. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(0, 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 serial = randomDigits(4);\n const payload = yy + mm + dd + serial;\n const sum = weightedSum(payload, WEIGHTS, 10);\n const c = payload + String((10 - sum) % 10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Polish National Identification Number. */\nconst pesel: Validator = {\n name: \"Polish National ID\",\n localName:\n \"Powszechny Elektroniczny System Ewidencji Ludności\",\n abbreviation: \"PESEL\",\n aliases: [\"PESEL\"] as const,\n candidatePattern: \"\\\\d{11}\",\n country: \"PL\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.gov.pl/web/cyfryzacja/numer-pesel\",\n examples: [\"02070803628\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default pesel;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;AAyBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;AAE9C,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,kCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,iCACD;CAGH,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAGhC,IAAI;AACJ,KAAI,MAAM,MAAM,MAAM,GACpB,WAAU;UACD,MAAM,KAAK,MAAM,GAC1B,WAAU;UACD,MAAM,MAAM,MAAM,GAC3B,WAAU;UACD,MAAM,MAAM,MAAM,GAC3B,WAAU;UACD,MAAM,MAAM,MAAM,GAC3B,WAAU;KAEV,QAAO,IACL,qBACA,kCACD;AAKH,KAAI,CAAC,YAFQ,UAAU,IACT,KAAK,IACW,GAAG,CAC/B,QAAO,IACL,qBACA,iCACD;AAKH,MADe,KADH,YAAY,EAAE,MAAM,GAAG,GAAG,EAAE,SAAS,GAAG,IACzB,OACb,OAAO,EAAE,IAAI,CACzB,QAAO,IACL,oBACA,mCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;;;;AAMxD,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,MAAM;AAC9B,KAAI,CAAC,OAAO,MAAO,QAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,SAAS,OAAO,EAAE,GAAG;CAE3B,IAAI;AACJ,KAAI,MAAM,GAAI,WAAU;UACf,MAAM,GAAI,WAAU;UACpB,MAAM,GAAI,WAAU;UACpB,MAAM,GAAI,WAAU;KACxB,WAAU;AAEf,QAAO;EACL,WAAW,IAAI,KAAK,UAAU,IAAK,KAAK,KAAM,GAAG,GAAG;EACpD,QAAQ,SAAS,MAAM,IAAI,WAAW;EACvC;;;AAIH,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,KAAK,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,KAAK,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,SAAS,aAAa,EAAE;EAC9B,MAAM,UAAU,KAAK,KAAK,KAAK;EAC/B,MAAM,MAAM,YAAY,SAAS,SAAS,GAAG;EAC7C,MAAM,IAAI,UAAU,QAAQ,KAAK,OAAO,GAAG;AAC3C,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,
|
|
1
|
+
{"version":3,"file":"pesel.js","names":[],"sources":["../../src/pl/pesel.ts"],"sourcesContent":["/**\n * PESEL (Powszechny Elektroniczny System\n * Ewidencji Ludności).\n *\n * Polish national identification number.\n * 11 digits encoding date of birth, serial\n * number, gender, and a check digit.\n *\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/poland-tin.pdf\n * @see https://www.gov.pl/web/cyfryzacja/numer-pesel\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, 3, 7, 9, 1, 3, 7, 9, 1, 3] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"PESEL must be exactly 11 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"PESEL must contain only digits\",\n );\n }\n\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\n // Century encoding via month offset\n let century: number;\n if (mm >= 81 && mm <= 92) {\n century = 1800;\n } else if (mm >= 1 && mm <= 12) {\n century = 1900;\n } else if (mm >= 21 && mm <= 32) {\n century = 2000;\n } else if (mm >= 41 && mm <= 52) {\n century = 2100;\n } else if (mm >= 61 && mm <= 72) {\n century = 2200;\n } else {\n return err(\n \"INVALID_COMPONENT\",\n \"PESEL contains an invalid month\",\n );\n }\n\n const year = century + yy;\n const month = mm % 20;\n if (!isValidDate(year, month, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"PESEL contains an invalid date\",\n );\n }\n\n const sum = weightedSum(v.slice(0, 10), WEIGHTS, 10);\n const check = (10 - sum) % 10;\n if (check !== Number(v[10])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"PESEL check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a PESEL number.\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 yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n const serial = Number(v[9]);\n\n let century: number;\n if (mm >= 81) century = 1800;\n else if (mm <= 12) century = 1900;\n else if (mm <= 32) century = 2000;\n else if (mm <= 52) century = 2100;\n else century = 2200;\n\n return {\n birthDate: new Date(century + yy, (mm % 20) - 1, dd),\n gender: serial % 2 === 0 ? \"female\" : \"male\",\n };\n};\n\n/** Generate a random valid Polish PESEL. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(0, 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 serial = randomDigits(4);\n const payload = yy + mm + dd + serial;\n const sum = weightedSum(payload, WEIGHTS, 10);\n const c = payload + String((10 - sum) % 10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Polish National Identification Number. */\nconst pesel: Validator<ParsedPersonId> = {\n name: \"Polish National ID\",\n localName:\n \"Powszechny Elektroniczny System Ewidencji Ludności\",\n abbreviation: \"PESEL\",\n aliases: [\"PESEL\"] as const,\n candidatePattern: \"\\\\d{11}\",\n country: \"PL\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.gov.pl/web/cyfryzacja/numer-pesel\",\n examples: [\"02070803628\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default pesel;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;AAyBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;AAE9C,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,kCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,iCACD;CAGH,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAGhC,IAAI;AACJ,KAAI,MAAM,MAAM,MAAM,GACpB,WAAU;UACD,MAAM,KAAK,MAAM,GAC1B,WAAU;UACD,MAAM,MAAM,MAAM,GAC3B,WAAU;UACD,MAAM,MAAM,MAAM,GAC3B,WAAU;UACD,MAAM,MAAM,MAAM,GAC3B,WAAU;KAEV,QAAO,IACL,qBACA,kCACD;AAKH,KAAI,CAAC,YAFQ,UAAU,IACT,KAAK,IACW,GAAG,CAC/B,QAAO,IACL,qBACA,iCACD;AAKH,MADe,KADH,YAAY,EAAE,MAAM,GAAG,GAAG,EAAE,SAAS,GAAG,IACzB,OACb,OAAO,EAAE,IAAI,CACzB,QAAO,IACL,oBACA,mCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;;;;AAMxD,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,MAAM;AAC9B,KAAI,CAAC,OAAO,MAAO,QAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,SAAS,OAAO,EAAE,GAAG;CAE3B,IAAI;AACJ,KAAI,MAAM,GAAI,WAAU;UACf,MAAM,GAAI,WAAU;UACpB,MAAM,GAAI,WAAU;UACpB,MAAM,GAAI,WAAU;KACxB,WAAU;AAEf,QAAO;EACL,WAAW,IAAI,KAAK,UAAU,IAAK,KAAK,KAAM,GAAG,GAAG;EACpD,QAAQ,SAAS,MAAM,IAAI,WAAW;EACvC;;;AAIH,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,KAAK,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,KAAK,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,SAAS,aAAa,EAAE;EAC9B,MAAM,UAAU,KAAK,KAAK,KAAK;EAC/B,MAAM,MAAM,YAAY,SAAS,SAAS,GAAG;EAC7C,MAAM,IAAI,UAAU,QAAQ,KAAK,OAAO,GAAG;AAC3C,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,QAAmC;CACvC,MAAM;CACN,WACE;CACF,cAAc;CACd,SAAS,CAAC,QAAQ;CAClB,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,cAAc;CACzB;CACA;CACA;CACA;CACA;CACD"}
|
package/dist/pl/regon.d.ts
CHANGED
package/dist/pt/cc.d.ts
CHANGED
package/dist/pt/cc.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { clean } from "../_util/clean.js";
|
|
2
|
-
import {
|
|
2
|
+
import { randomChar, randomDigits } from "../_util/generate.js";
|
|
3
3
|
import { err } from "../_util/result.js";
|
|
4
4
|
//#region src/pt/cc.ts
|
|
5
5
|
/**
|
|
@@ -17,8 +17,10 @@ const compact = (value) => clean(value, " ").toUpperCase();
|
|
|
17
17
|
const calcCheckDigit = (value) => {
|
|
18
18
|
let sum = 0;
|
|
19
19
|
for (let i = value.length - 1; i >= 0; i--) {
|
|
20
|
+
const ch = value[i];
|
|
21
|
+
if (ch === void 0) continue;
|
|
20
22
|
const pos = value.length - 1 - i;
|
|
21
|
-
let n = ALPHABET.indexOf(
|
|
23
|
+
let n = ALPHABET.indexOf(ch);
|
|
22
24
|
if (pos % 2 === 0) {
|
|
23
25
|
n *= 2;
|
|
24
26
|
if (n > 9) n = Math.floor(n / 10) + n % 10;
|
|
@@ -44,8 +46,8 @@ const format = (value) => {
|
|
|
44
46
|
/** Generate a random valid Portuguese CC number. */
|
|
45
47
|
const generate = () => {
|
|
46
48
|
const digits = randomDigits(9);
|
|
47
|
-
const v0 = ALPHABET
|
|
48
|
-
const v1 = ALPHABET
|
|
49
|
+
const v0 = randomChar(ALPHABET);
|
|
50
|
+
const v1 = randomChar(ALPHABET);
|
|
49
51
|
const body = digits + v0 + v1;
|
|
50
52
|
return body + calcCheckDigit(body);
|
|
51
53
|
};
|
package/dist/pt/cc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cc.js","names":[],"sources":["../../src/pt/cc.ts"],"sourcesContent":["/**\n * CC (Cartão de Cidadão, Portuguese Identity number).\n *\n * Alphanumeric: numeric civil ID + 2-letter version +\n * 1 check digit. Validated with a Luhn-like algorithm\n * over an alphanumeric alphabet (0-9, A-Z = 0-35).\n *\n * @see https://pt.wikipedia.org/wiki/Cartão_de_cidadão\n */\n\nimport { clean } from \"#util/clean\";\nimport {
|
|
1
|
+
{"version":3,"file":"cc.js","names":[],"sources":["../../src/pt/cc.ts"],"sourcesContent":["/**\n * CC (Cartão de Cidadão, Portuguese Identity number).\n *\n * Alphanumeric: numeric civil ID + 2-letter version +\n * 1 check digit. Validated with a Luhn-like algorithm\n * over an alphanumeric alphabet (0-9, A-Z = 0-35).\n *\n * @see https://pt.wikipedia.org/wiki/Cartão_de_cidadão\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomChar, randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst CC_RE = /^\\d{9}[A-Z0-9]{2}\\d$/;\n\nconst ALPHABET = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\nconst compact = (value: string): string =>\n clean(value, \" \").toUpperCase();\n\nconst calcCheckDigit = (value: string): string => {\n let sum = 0;\n for (let i = value.length - 1; i >= 0; i--) {\n const ch = value[i];\n if (ch === undefined) continue;\n const pos = value.length - 1 - i;\n let n = ALPHABET.indexOf(ch);\n if (pos % 2 === 0) {\n n *= 2;\n if (n > 9) n = Math.floor(n / 10) + (n % 10);\n }\n sum += n;\n }\n return String((10 - (sum % 10)) % 10);\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 \"CC must be 12 characters\",\n );\n }\n\n if (!CC_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CC must be 9 digits, 2 alphanumeric version characters, and a check digit\",\n );\n }\n\n if (calcCheckDigit(v.slice(0, -1)) !== v.at(-1)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CC 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, -3)} ${v.slice(-3, -1)} ${v.at(-1)}`;\n};\n\n/** Generate a random valid Portuguese CC number. */\nconst generate = (): string => {\n const digits = randomDigits(9);\n const v0 = randomChar(ALPHABET);\n const v1 = randomChar(ALPHABET);\n const body = digits + v0 + v1;\n const check = calcCheckDigit(body);\n return body + check;\n};\n\n/** Portuguese Identity Card number. */\nconst cc: Validator = {\n name: \"Portuguese Identity Card\",\n localName: \"Cartão de Cidadão\",\n abbreviation: \"CC\",\n aliases: [\n \"cartão de cidadão\",\n \"CC\",\n \"número de identificação civil\",\n ] as const,\n candidatePattern: \"\\\\d{8}\\\\s?\\\\d\\\\s?[A-Z]{2}\\\\d\",\n country: \"PT\",\n entityType: \"person\",\n description:\n \"Alphanumeric national identity card number with Luhn-like check digit\",\n sourceUrl:\n \"https://pt.wikipedia.org/wiki/Cartão_de_cidadão\",\n lengths: [12] as const,\n examples: [\"000000000ZZ8\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cc;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAM,QAAQ;AAEd,MAAM,WAAW;AAEjB,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,CAAC,aAAa;AAEjC,MAAM,kBAAkB,UAA0B;CAChD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;EAC1C,MAAM,KAAK,MAAM;AACjB,MAAI,OAAO,KAAA,EAAW;EACtB,MAAM,MAAM,MAAM,SAAS,IAAI;EAC/B,IAAI,IAAI,SAAS,QAAQ,GAAG;AAC5B,MAAI,MAAM,MAAM,GAAG;AACjB,QAAK;AACL,OAAI,IAAI,EAAG,KAAI,KAAK,MAAM,IAAI,GAAG,GAAI,IAAI;;AAE3C,SAAO;;AAET,QAAO,QAAQ,KAAM,MAAM,MAAO,GAAG;;AAGvC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,2BACD;AAGH,KAAI,CAAC,MAAM,KAAK,EAAE,CAChB,QAAO,IACL,kBACA,4EACD;AAGH,KAAI,eAAe,EAAE,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,CAC7C,QAAO,IACL,oBACA,gCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,QAAO,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG;;;AAIzD,MAAM,iBAAyB;CAC7B,MAAM,SAAS,aAAa,EAAE;CAC9B,MAAM,KAAK,WAAW,SAAS;CAC/B,MAAM,KAAK,WAAW,SAAS;CAC/B,MAAM,OAAO,SAAS,KAAK;AAE3B,QAAO,OADO,eAAe,KAAK;;;AAKpC,MAAM,KAAgB;CACpB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,aACE;CACF,WACE;CACF,SAAS,CAAC,GAAG;CACb,UAAU,CAAC,eAAe;CAC1B;CACA;CACA;CACA;CACD"}
|
package/dist/pt/mod.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import cc from "./cc.js";
|
|
3
2
|
import vat from "./vat.js";
|
|
4
3
|
|
|
5
4
|
//#region src/pt/mod.d.ts
|
|
6
|
-
|
|
5
|
+
declare namespace mod_d_exports {
|
|
6
|
+
export { cc, vat };
|
|
7
|
+
}
|
|
7
8
|
//#endregion
|
|
8
9
|
export { cc, mod_d_exports, vat };
|
|
9
10
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/pt/vat.d.ts
CHANGED
package/dist/ro/cnp.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/ro/cnp.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;
|
|
@@ -13,7 +12,7 @@ declare const parse: (value: string) => ParsedPersonId | null;
|
|
|
13
12
|
/** Generate a random valid Romanian CNP. */
|
|
14
13
|
declare const generate: () => string;
|
|
15
14
|
/** Romanian Personal Identification Number. */
|
|
16
|
-
declare const cnp: Validator
|
|
15
|
+
declare const cnp: Validator<ParsedPersonId>;
|
|
17
16
|
//#endregion
|
|
18
17
|
export { compact, cnp as default, format, generate, parse, validate };
|
|
19
18
|
//# sourceMappingURL=cnp.d.ts.map
|
package/dist/ro/cnp.js
CHANGED
package/dist/ro/cnp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cnp.js","names":[],"sources":["../../src/ro/cnp.ts"],"sourcesContent":["/**\n * CNP (Cod Numeric Personal).\n *\n * Romanian personal identification number. 13 digits\n * encoding gender/century, date of birth, county code,\n * serial number, and a check digit.\n *\n * @see https://ro.wikipedia.org/wiki/Cod_numeric_personal\n * @see https://www.cnp.ro/\n */\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { 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 = [\n 2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, 9,\n] as const;\n\nconst VALID_COUNTIES = new Set([\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,\n 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,\n 46, 47, 48, 49, 50, 51, 52, 70, 80, 81, 82, 83,\n]);\n\nconst centuryMap: Record<number, number> = {\n 1: 1900,\n 2: 1900,\n 3: 1800,\n 4: 1800,\n 5: 2000,\n 6: 2000,\n 7: 1900, // foreign residents\n 8: 1900, // foreign residents\n};\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"CNP must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CNP must contain only digits\",\n );\n }\n\n const g = Number(v[0]);\n if (g < 1 || g > 9) {\n return err(\n \"INVALID_COMPONENT\",\n \"CNP gender/century digit is invalid\",\n );\n }\n\n const century = centuryMap[g] ?? 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 = century + yy;\n\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"CNP contains an invalid date\",\n );\n }\n\n const county = Number(v.slice(7, 9));\n if (!VALID_COUNTIES.has(county)) {\n return err(\n \"INVALID_COMPONENT\",\n \"CNP county code is invalid\",\n );\n }\n\n const sum = weightedSum(v.slice(0, 12), WEIGHTS, 11);\n const check = sum === 10 ? 1 : sum;\n if (check !== Number(v[12])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CNP check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a CNP.\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 g = Number(v[0]);\n const century = centuryMap[g] ?? 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 = century + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender: g % 2 === 1 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid Romanian CNP. */\nconst generate = (): string => {\n for (;;) {\n const g = String(randomInt(1, 6));\n const yy = String(randomInt(0, 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 county = String(randomInt(1, 52)).padStart(\n 2,\n \"0\",\n );\n const serial = String(randomInt(1, 999)).padStart(\n 3,\n \"0\",\n );\n const payload = g + yy + mm + dd + county + serial;\n const sum = weightedSum(payload, WEIGHTS, 11);\n const c = payload + String(sum === 10 ? 1 : sum);\n if (validate(c).valid) return c;\n }\n};\n\n/** Romanian Personal Identification Number. */\nconst cnp: Validator = {\n name: \"Romanian Personal ID\",\n localName: \"Cod Numeric Personal\",\n abbreviation: \"CNP\",\n aliases: [\"CNP\", \"cod numeric personal\"] as const,\n candidatePattern:\n \"[1-8]\\\\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\\\d|3[01])\\\\d{6}\",\n country: \"RO\",\n entityType: \"person\",\n sourceUrl: \"https://www.cnp.ro/\",\n examples: [\"1630615123457\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cnp;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"cnp.js","names":[],"sources":["../../src/ro/cnp.ts"],"sourcesContent":["/**\n * CNP (Cod Numeric Personal).\n *\n * Romanian personal identification number. 13 digits\n * encoding gender/century, date of birth, county code,\n * serial number, and a check digit.\n *\n * @see https://ro.wikipedia.org/wiki/Cod_numeric_personal\n * @see https://www.cnp.ro/\n */\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { 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 = [\n 2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, 9,\n] as const;\n\nconst VALID_COUNTIES = new Set([\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,\n 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,\n 46, 47, 48, 49, 50, 51, 52, 70, 80, 81, 82, 83,\n]);\n\nconst centuryMap: Record<number, number> = {\n 1: 1900,\n 2: 1900,\n 3: 1800,\n 4: 1800,\n 5: 2000,\n 6: 2000,\n 7: 1900, // foreign residents\n 8: 1900, // foreign residents\n};\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"CNP must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CNP must contain only digits\",\n );\n }\n\n const g = Number(v[0]);\n if (g < 1 || g > 9) {\n return err(\n \"INVALID_COMPONENT\",\n \"CNP gender/century digit is invalid\",\n );\n }\n\n const century = centuryMap[g] ?? 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 = century + yy;\n\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"CNP contains an invalid date\",\n );\n }\n\n const county = Number(v.slice(7, 9));\n if (!VALID_COUNTIES.has(county)) {\n return err(\n \"INVALID_COMPONENT\",\n \"CNP county code is invalid\",\n );\n }\n\n const sum = weightedSum(v.slice(0, 12), WEIGHTS, 11);\n const check = sum === 10 ? 1 : sum;\n if (check !== Number(v[12])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CNP check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a CNP.\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 g = Number(v[0]);\n const century = centuryMap[g] ?? 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 = century + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender: g % 2 === 1 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid Romanian CNP. */\nconst generate = (): string => {\n for (;;) {\n const g = String(randomInt(1, 6));\n const yy = String(randomInt(0, 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 county = String(randomInt(1, 52)).padStart(\n 2,\n \"0\",\n );\n const serial = String(randomInt(1, 999)).padStart(\n 3,\n \"0\",\n );\n const payload = g + yy + mm + dd + county + serial;\n const sum = weightedSum(payload, WEIGHTS, 11);\n const c = payload + String(sum === 10 ? 1 : sum);\n if (validate(c).valid) return c;\n }\n};\n\n/** Romanian Personal Identification Number. */\nconst cnp: Validator<ParsedPersonId> = {\n name: \"Romanian Personal ID\",\n localName: \"Cod Numeric Personal\",\n abbreviation: \"CNP\",\n aliases: [\"CNP\", \"cod numeric personal\"] as const,\n candidatePattern:\n \"[1-8]\\\\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\\\\d|3[01])\\\\d{6}\",\n country: \"RO\",\n entityType: \"person\",\n sourceUrl: \"https://www.cnp.ro/\",\n examples: [\"1630615123457\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default cnp;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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"}
|
package/dist/ro/mod.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import cnp from "./cnp.js";
|
|
3
2
|
import vat from "./vat.js";
|
|
4
3
|
|
|
5
4
|
//#region src/ro/mod.d.ts
|
|
6
|
-
|
|
5
|
+
declare namespace mod_d_exports {
|
|
6
|
+
export { cnp, vat };
|
|
7
|
+
}
|
|
7
8
|
//#endregion
|
|
8
9
|
export { cnp, mod_d_exports, vat };
|
|
9
10
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/ro/vat.d.ts
CHANGED
package/dist/rs/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import pib from "./pib.js";
|
|
3
2
|
|
|
4
3
|
//#region src/rs/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { pib };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { mod_d_exports, pib };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/rs/pib.d.ts
CHANGED
package/dist/ru/inn.d.ts
CHANGED
package/dist/ru/inn.js
CHANGED
|
@@ -52,7 +52,7 @@ const WEIGHTS_12 = [
|
|
|
52
52
|
];
|
|
53
53
|
const checkDigit = (value, weights) => {
|
|
54
54
|
let sum = 0;
|
|
55
|
-
for (
|
|
55
|
+
for (const [i, weight] of weights.entries()) sum += Number(value[i]) * weight;
|
|
56
56
|
return sum % 11 % 10;
|
|
57
57
|
};
|
|
58
58
|
const compact = (value) => clean(value, " -");
|
package/dist/ru/inn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inn.js","names":[],"sources":["../../src/ru/inn.ts"],"sourcesContent":["/**\n * INN (Идентификационный номер налогоплательщика).\n *\n * Russian taxpayer identification number. 10 digits\n * for companies (1 check digit), 12 digits for\n * individuals (2 check digits). Check digits are\n * computed as weighted sum mod 11 mod 10.\n *\n * @see https://en.wikipedia.org/wiki/Taxpayer_Identification_Number_(Russia)\n * @see https://www.nalog.gov.ru/\n */\n\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 WEIGHTS_10 = [2, 4, 10, 3, 5, 9, 4, 6, 8] as const;\nconst WEIGHTS_11 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8] as const;\nconst WEIGHTS_12 = [\n 3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8,\n] as const;\n\nconst checkDigit = (\n value: string,\n weights: readonly number[],\n): number => {\n let sum = 0;\n for (
|
|
1
|
+
{"version":3,"file":"inn.js","names":[],"sources":["../../src/ru/inn.ts"],"sourcesContent":["/**\n * INN (Идентификационный номер налогоплательщика).\n *\n * Russian taxpayer identification number. 10 digits\n * for companies (1 check digit), 12 digits for\n * individuals (2 check digits). Check digits are\n * computed as weighted sum mod 11 mod 10.\n *\n * @see https://en.wikipedia.org/wiki/Taxpayer_Identification_Number_(Russia)\n * @see https://www.nalog.gov.ru/\n */\n\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 WEIGHTS_10 = [2, 4, 10, 3, 5, 9, 4, 6, 8] as const;\nconst WEIGHTS_11 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8] as const;\nconst WEIGHTS_12 = [\n 3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8,\n] as const;\n\nconst checkDigit = (\n value: string,\n weights: readonly number[],\n): number => {\n let sum = 0;\n for (const [i, weight] of weights.entries()) {\n sum += Number(value[i]) * weight;\n }\n return (sum % 11) % 10;\n};\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10 && v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"INN must be 10 or 12 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"INN must contain only digits\",\n );\n }\n\n if (v.length === 10) {\n const check = checkDigit(v, WEIGHTS_10);\n if (check !== Number(v[9])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"INN check digit mismatch\",\n );\n }\n } else {\n const check11 = checkDigit(v, WEIGHTS_11);\n const check12 = checkDigit(v, WEIGHTS_12);\n if (\n check11 !== Number(v[10]) ||\n check12 !== Number(v[11])\n ) {\n return err(\n \"INVALID_CHECKSUM\",\n \"INN check digit mismatch\",\n );\n }\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid 10-digit Russian INN. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Russian Taxpayer Identification Number. */\nconst inn: Validator = {\n name: \"Russian Tax ID\",\n localName: \"Идентификационный номер налогоплательщика\",\n abbreviation: \"ИНН\",\n aliases: [\"ИНН\", \"INN\"] as const,\n candidatePattern: \"\\\\d{10,12}\",\n country: \"RU\",\n entityType: \"any\",\n lengths: [10, 12] as const,\n sourceUrl: \"https://www.nalog.gov.ru/\",\n examples: [\"7707083893\", \"526317984689\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default inn;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,MAAM,aAAa;CAAC;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;AAC/C,MAAM,aAAa;CAAC;CAAG;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;AAClD,MAAM,aAAa;CACjB;CAAG;CAAG;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;CAAG;CAAG;CAChC;AAED,MAAM,cACJ,OACA,YACW;CACX,IAAI,MAAM;AACV,MAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,SAAS,CACzC,QAAO,OAAO,MAAM,GAAG,GAAG;AAE5B,QAAQ,MAAM,KAAM;;AAGtB,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,MAAM,EAAE,WAAW,GAClC,QAAO,IACL,kBACA,8BACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,+BACD;AAGH,KAAI,EAAE,WAAW;MACD,WAAW,GAAG,WAAW,KACzB,OAAO,EAAE,GAAG,CACxB,QAAO,IACL,oBACA,2BACD;QAEE;EACL,MAAM,UAAU,WAAW,GAAG,WAAW;EACzC,MAAM,UAAU,WAAW,GAAG,WAAW;AACzC,MACE,YAAY,OAAO,EAAE,IAAI,IACzB,YAAY,OAAO,EAAE,IAAI,CAEzB,QAAO,IACL,oBACA,2BACD;;AAIL,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,IAAI,aAAa,GAAG;AAC1B,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,MAAM;CACvB,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,IAAI,GAAG;CACjB,WAAW;CACX,UAAU,CAAC,cAAc,eAAe;CACxC;CACA;CACA;CACA;CACD"}
|
package/dist/ru/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import inn from "./inn.js";
|
|
3
2
|
|
|
4
3
|
//#region src/ru/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { inn };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { inn, mod_d_exports };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/se/mod.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import orgnr from "./orgnr.js";
|
|
3
2
|
import personnummer from "./personnummer.js";
|
|
4
3
|
import vat from "./vat.js";
|
|
5
4
|
|
|
6
5
|
//#region src/se/mod.d.ts
|
|
7
|
-
|
|
6
|
+
declare namespace mod_d_exports {
|
|
7
|
+
export { orgnr, personnummer, vat };
|
|
8
|
+
}
|
|
8
9
|
//#endregion
|
|
9
10
|
export { mod_d_exports, orgnr, personnummer, vat };
|
|
10
11
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/se/orgnr.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/se/personnummer.d.ts
|
|
4
|
-
|
|
5
4
|
/**
|
|
6
5
|
* Match python-stdnum's compact: preserve the '-' or '+'
|
|
7
6
|
* separator at position -5, and strip any others.
|
|
@@ -17,7 +16,7 @@ declare const parse: (value: string) => ParsedPersonId | null;
|
|
|
17
16
|
/** Generate a random valid Swedish personnummer. */
|
|
18
17
|
declare const generate: () => string;
|
|
19
18
|
/** Swedish Personal Identity Number. */
|
|
20
|
-
declare const personnummer: Validator
|
|
19
|
+
declare const personnummer: Validator<ParsedPersonId>;
|
|
21
20
|
//#endregion
|
|
22
21
|
export { compact, personnummer as default, format, generate, parse, validate };
|
|
23
22
|
//# sourceMappingURL=personnummer.d.ts.map
|