@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"personnummer.js","names":[],"sources":["../../src/se/personnummer.ts"],"sourcesContent":["/**\n * Personnummer (Personal Identity Number).\n *\n * Swedish personal identification number. 10 digits\n * in compact form (YYMMDDNNNC) with a Luhn checksum\n * on all 10 digits.\n *\n * @see https://www.skatteverket.se/privat/folkbokforing/personnummer.4.3810a01c150939e893f18c29.html\n */\n\nimport {\n luhnValidate,\n luhnChecksum,\n} from \"#checksums/luhn\";\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\n/**\n * Match python-stdnum's compact: preserve the '-' or '+'\n * separator at position -5, and strip any others.\n */\nconst compact = (value: string): string => {\n let v = clean(value, \" :\");\n if (\n (v.length === 10 || v.length === 12) &&\n v[v.length - 5] !== \"-\" &&\n v[v.length - 5] !== \"+\"\n ) {\n v = `${v.slice(0, -4)}-${v.slice(-4)}`;\n }\n const prefix = v\n .slice(0, -5)\n .replace(/-/g, \"\")\n .replace(/\\+/g, \"\");\n return `${prefix}${v.slice(-5)}`;\n};\n\n/**\n * Extract the birth date from the compacted number.\n * Matches python-stdnum's get_birth_date.\n */\nconst getBirthDate = (\n v: string,\n): { year: number; month: number; day: number } | null => {\n let year: number;\n let month: number;\n let day: number;\n\n if (v.length === 13) {\n year = Number(v.slice(0, 4));\n month = Number(v.slice(4, 6));\n day = Number(v.slice(6, 8));\n } else {\n const currentYear = new Date().getFullYear();\n let century = Math.floor(currentYear / 100);\n const yy = Number(v.slice(0, 2));\n if (yy > currentYear % 100) century -= 1;\n if (v[v.length - 5] === \"+\") century -= 1;\n year = century * 100 + yy;\n month = Number(v.slice(2, 4));\n day = Number(v.slice(4, 6));\n }\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 !== 11 && v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"Personnummer must be 10 or 12 digits\",\n );\n }\n\n const digits = v.slice(0, -5) + v.slice(-4);\n const sep = v[v.length - 5];\n if ((sep !== \"-\" && sep !== \"+\") || !isdigits(digits)) {\n return err(\n \"INVALID_FORMAT\",\n \"Personnummer has invalid format\",\n );\n }\n\n if (getBirthDate(v) === null) {\n return err(\n \"INVALID_COMPONENT\",\n \"Personnummer contains an invalid date\",\n );\n }\n\n if (!luhnValidate(digits.slice(-10))) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Personnummer Luhn check 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 Personnummer.\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 birthDate = getBirthDate(v);\n if (birthDate === null) return null;\n\n const genderDigit = Number(v[v.length - 2]);\n\n return {\n birthDate: new Date(\n birthDate.year,\n birthDate.month - 1,\n birthDate.day,\n ),\n gender: genderDigit % 2 === 0 ? \"female\" : \"male\",\n };\n};\n\n/** Generate a random valid Swedish personnummer. */\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 serial = String(randomInt(0, 999)).padStart(\n 3,\n \"0\",\n );\n const payload = yy + mm + dd + serial;\n const cs = luhnChecksum(payload + \"0\");\n const c = payload + String((10 - cs) % 10);\n const result = validate(c);\n if (result.valid) return result.compact;\n }\n};\n\n/** Swedish Personal Identity Number. */\nconst personnummer: Validator = {\n name: \"Swedish Personal ID\",\n localName: \"Personnummer\",\n abbreviation: \"PN\",\n aliases: [\n \"personnummer\",\n \"personnr\",\n \"pers.nr\",\n \"personal identity number\",\n ] as const,\n candidatePattern: \"\\\\d{6,8}-\\\\d{4}\",\n country: \"SE\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.skatteverket.se/privat/folkbokforing/personnummer.4.3810a01c150939e893f18c29.html\",\n examples: [\"880320-0016\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default personnummer;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"personnummer.js","names":[],"sources":["../../src/se/personnummer.ts"],"sourcesContent":["/**\n * Personnummer (Personal Identity Number).\n *\n * Swedish personal identification number. 10 digits\n * in compact form (YYMMDDNNNC) with a Luhn checksum\n * on all 10 digits.\n *\n * @see https://www.skatteverket.se/privat/folkbokforing/personnummer.4.3810a01c150939e893f18c29.html\n */\n\nimport {\n luhnValidate,\n luhnChecksum,\n} from \"#checksums/luhn\";\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\n/**\n * Match python-stdnum's compact: preserve the '-' or '+'\n * separator at position -5, and strip any others.\n */\nconst compact = (value: string): string => {\n let v = clean(value, \" :\");\n if (\n (v.length === 10 || v.length === 12) &&\n v[v.length - 5] !== \"-\" &&\n v[v.length - 5] !== \"+\"\n ) {\n v = `${v.slice(0, -4)}-${v.slice(-4)}`;\n }\n const prefix = v\n .slice(0, -5)\n .replace(/-/g, \"\")\n .replace(/\\+/g, \"\");\n return `${prefix}${v.slice(-5)}`;\n};\n\n/**\n * Extract the birth date from the compacted number.\n * Matches python-stdnum's get_birth_date.\n */\nconst getBirthDate = (\n v: string,\n): { year: number; month: number; day: number } | null => {\n let year: number;\n let month: number;\n let day: number;\n\n if (v.length === 13) {\n year = Number(v.slice(0, 4));\n month = Number(v.slice(4, 6));\n day = Number(v.slice(6, 8));\n } else {\n const currentYear = new Date().getFullYear();\n let century = Math.floor(currentYear / 100);\n const yy = Number(v.slice(0, 2));\n if (yy > currentYear % 100) century -= 1;\n if (v[v.length - 5] === \"+\") century -= 1;\n year = century * 100 + yy;\n month = Number(v.slice(2, 4));\n day = Number(v.slice(4, 6));\n }\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 !== 11 && v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"Personnummer must be 10 or 12 digits\",\n );\n }\n\n const digits = v.slice(0, -5) + v.slice(-4);\n const sep = v[v.length - 5];\n if ((sep !== \"-\" && sep !== \"+\") || !isdigits(digits)) {\n return err(\n \"INVALID_FORMAT\",\n \"Personnummer has invalid format\",\n );\n }\n\n if (getBirthDate(v) === null) {\n return err(\n \"INVALID_COMPONENT\",\n \"Personnummer contains an invalid date\",\n );\n }\n\n if (!luhnValidate(digits.slice(-10))) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Personnummer Luhn check 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 Personnummer.\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 birthDate = getBirthDate(v);\n if (birthDate === null) return null;\n\n const genderDigit = Number(v[v.length - 2]);\n\n return {\n birthDate: new Date(\n birthDate.year,\n birthDate.month - 1,\n birthDate.day,\n ),\n gender: genderDigit % 2 === 0 ? \"female\" : \"male\",\n };\n};\n\n/** Generate a random valid Swedish personnummer. */\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 serial = String(randomInt(0, 999)).padStart(\n 3,\n \"0\",\n );\n const payload = yy + mm + dd + serial;\n const cs = luhnChecksum(payload + \"0\");\n const c = payload + String((10 - cs) % 10);\n const result = validate(c);\n if (result.valid) return result.compact;\n }\n};\n\n/** Swedish Personal Identity Number. */\nconst personnummer: Validator<ParsedPersonId> = {\n name: \"Swedish Personal ID\",\n localName: \"Personnummer\",\n abbreviation: \"PN\",\n aliases: [\n \"personnummer\",\n \"personnr\",\n \"pers.nr\",\n \"personal identity number\",\n ] as const,\n candidatePattern: \"\\\\d{6,8}-\\\\d{4}\",\n country: \"SE\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.skatteverket.se/privat/folkbokforing/personnummer.4.3810a01c150939e893f18c29.html\",\n examples: [\"880320-0016\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default personnummer;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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"}
|
package/dist/se/vat.d.ts
CHANGED
package/dist/sg/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import uen from "./uen.js";
|
|
3
2
|
|
|
4
3
|
//#region src/sg/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { uen };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { mod_d_exports, uen };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/sg/uen.d.ts
CHANGED
package/dist/sg/uen.js
CHANGED
|
@@ -65,23 +65,23 @@ const compact = (value) => clean(value, " -").toUpperCase();
|
|
|
65
65
|
* Validate Business (ROB) UEN (9 chars):
|
|
66
66
|
* 8 digits + 1 check letter.
|
|
67
67
|
*/
|
|
68
|
+
const BUSINESS_WEIGHTS = [
|
|
69
|
+
10,
|
|
70
|
+
4,
|
|
71
|
+
9,
|
|
72
|
+
3,
|
|
73
|
+
8,
|
|
74
|
+
2,
|
|
75
|
+
7,
|
|
76
|
+
1
|
|
77
|
+
];
|
|
78
|
+
const BUSINESS_CHECK_ALPHA = "XMKECAWLJDB";
|
|
68
79
|
const validateBusiness = (v) => {
|
|
69
80
|
if (!isdigits(v.slice(0, 8))) return err("INVALID_FORMAT", "Business UEN must start with 8 digits");
|
|
70
81
|
if (!/^[A-Z]$/.test(v[8])) return err("INVALID_FORMAT", "Business UEN must end with a letter");
|
|
71
|
-
const weights = [
|
|
72
|
-
10,
|
|
73
|
-
4,
|
|
74
|
-
9,
|
|
75
|
-
3,
|
|
76
|
-
8,
|
|
77
|
-
2,
|
|
78
|
-
7,
|
|
79
|
-
1
|
|
80
|
-
];
|
|
81
|
-
const checkAlpha = "XMKECAWLJDB";
|
|
82
82
|
let sum = 0;
|
|
83
|
-
for (
|
|
84
|
-
const expected =
|
|
83
|
+
for (const [i, weight] of BUSINESS_WEIGHTS.entries()) sum += Number(v[i]) * weight;
|
|
84
|
+
const expected = BUSINESS_CHECK_ALPHA[sum % 11];
|
|
85
85
|
if (v[8] !== expected) return err("INVALID_CHECKSUM", "UEN check letter does not match");
|
|
86
86
|
return {
|
|
87
87
|
valid: true,
|
|
@@ -92,24 +92,24 @@ const validateBusiness = (v) => {
|
|
|
92
92
|
* Validate Local Company (ROC) UEN (10 chars):
|
|
93
93
|
* 9 digits (year prefix) + 1 check letter.
|
|
94
94
|
*/
|
|
95
|
+
const LOCAL_WEIGHTS = [
|
|
96
|
+
10,
|
|
97
|
+
8,
|
|
98
|
+
6,
|
|
99
|
+
4,
|
|
100
|
+
9,
|
|
101
|
+
7,
|
|
102
|
+
5,
|
|
103
|
+
3,
|
|
104
|
+
1
|
|
105
|
+
];
|
|
106
|
+
const LOCAL_CHECK_ALPHA = "ZKCMDNERGWH";
|
|
95
107
|
const validateLocalCompany = (v) => {
|
|
96
108
|
if (!isdigits(v.slice(0, 9))) return err("INVALID_FORMAT", "Company UEN must have 9 digits");
|
|
97
109
|
if (!/^[A-Z]$/.test(v[9])) return err("INVALID_FORMAT", "Company UEN must end with a letter");
|
|
98
|
-
const weights = [
|
|
99
|
-
10,
|
|
100
|
-
8,
|
|
101
|
-
6,
|
|
102
|
-
4,
|
|
103
|
-
9,
|
|
104
|
-
7,
|
|
105
|
-
5,
|
|
106
|
-
3,
|
|
107
|
-
1
|
|
108
|
-
];
|
|
109
|
-
const checkAlpha = "ZKCMDNERGWH";
|
|
110
110
|
let sum = 0;
|
|
111
|
-
for (
|
|
112
|
-
const expected =
|
|
111
|
+
for (const [i, weight] of LOCAL_WEIGHTS.entries()) sum += Number(v[i]) * weight;
|
|
112
|
+
const expected = LOCAL_CHECK_ALPHA[sum % 11];
|
|
113
113
|
if (v[9] !== expected) return err("INVALID_CHECKSUM", "UEN check letter does not match");
|
|
114
114
|
return {
|
|
115
115
|
valid: true,
|
|
@@ -121,6 +121,17 @@ const validateLocalCompany = (v) => {
|
|
|
121
121
|
* R/S/T + 2 digits + 2-letter type + 4 digits
|
|
122
122
|
* + 1 check letter.
|
|
123
123
|
*/
|
|
124
|
+
const OTHER_WEIGHTS = [
|
|
125
|
+
4,
|
|
126
|
+
3,
|
|
127
|
+
5,
|
|
128
|
+
3,
|
|
129
|
+
10,
|
|
130
|
+
2,
|
|
131
|
+
2,
|
|
132
|
+
5,
|
|
133
|
+
7
|
|
134
|
+
];
|
|
124
135
|
const validateOther = (v) => {
|
|
125
136
|
const prefix = v[0];
|
|
126
137
|
if (prefix !== "R" && prefix !== "S" && prefix !== "T") return err("INVALID_COMPONENT", "Other UEN must start with R, S, or T");
|
|
@@ -128,22 +139,13 @@ const validateOther = (v) => {
|
|
|
128
139
|
const entityType = v.slice(3, 5);
|
|
129
140
|
if (!ENTITY_TYPES.has(entityType)) return err("INVALID_COMPONENT", "Unknown entity type: " + entityType);
|
|
130
141
|
if (!isdigits(v.slice(5, 9))) return err("INVALID_FORMAT", "Other UEN positions 6-9 must be digits");
|
|
131
|
-
const weights = [
|
|
132
|
-
4,
|
|
133
|
-
3,
|
|
134
|
-
5,
|
|
135
|
-
3,
|
|
136
|
-
10,
|
|
137
|
-
2,
|
|
138
|
-
2,
|
|
139
|
-
5,
|
|
140
|
-
7
|
|
141
|
-
];
|
|
142
142
|
let sum = 0;
|
|
143
|
-
for (
|
|
144
|
-
const
|
|
145
|
-
if (
|
|
146
|
-
|
|
143
|
+
for (const [i, weight] of OTHER_WEIGHTS.entries()) {
|
|
144
|
+
const ch = v[i];
|
|
145
|
+
if (ch === void 0) continue;
|
|
146
|
+
const idx = OTHER_ALPHA.indexOf(ch);
|
|
147
|
+
if (idx === -1) return err("INVALID_FORMAT", `Unexpected character at position ${i + 1}: ${ch}`);
|
|
148
|
+
sum += idx * weight;
|
|
147
149
|
}
|
|
148
150
|
const expected = OTHER_ALPHA[((sum - 5) % 11 + 11) % 11];
|
|
149
151
|
if (v[9] !== expected) return err("INVALID_CHECKSUM", "UEN check letter does not match");
|
|
@@ -163,21 +165,10 @@ const validate = (value) => {
|
|
|
163
165
|
const format = (value) => compact(value);
|
|
164
166
|
/** Generate a random valid Singapore UEN (business format). */
|
|
165
167
|
const generate = () => {
|
|
166
|
-
const weights = [
|
|
167
|
-
10,
|
|
168
|
-
4,
|
|
169
|
-
9,
|
|
170
|
-
3,
|
|
171
|
-
8,
|
|
172
|
-
2,
|
|
173
|
-
7,
|
|
174
|
-
1
|
|
175
|
-
];
|
|
176
|
-
const checkAlpha = "XMKECAWLJDB";
|
|
177
168
|
const body = randomDigits(8);
|
|
178
169
|
let sum = 0;
|
|
179
|
-
for (
|
|
180
|
-
return body +
|
|
170
|
+
for (const [i, weight] of BUSINESS_WEIGHTS.entries()) sum += Number(body[i]) * weight;
|
|
171
|
+
return body + BUSINESS_CHECK_ALPHA[sum % 11];
|
|
181
172
|
};
|
|
182
173
|
/** Singapore Unique Entity Number. */
|
|
183
174
|
const uen = {
|
package/dist/sg/uen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uen.js","names":[],"sources":["../../src/sg/uen.ts"],"sourcesContent":["/**\n * UEN (Singapore Unique Entity Number).\n *\n * 9 or 10 characters identifying businesses and\n * entities registered in Singapore. Three formats:\n *\n * - Business (ROB): 8 digits + 1 check letter\n * - Local company (ROC): 4-digit year + 5 digits\n * + 1 check letter\n * - Other entities: R/S/T + 2-digit year + 2-letter\n * entity type + 4 digits + 1 check letter\n *\n * @see https://www.uen.gov.sg/\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Singapore-TIN.pdf\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/** Check letter alphabet for \"Other\" format. */\nconst OTHER_ALPHA = \"ABCDEFGHJKLMNPQRSTUVWX0123456789\";\n\nconst ENTITY_TYPES = new Set([\n \"CC\",\n \"CD\",\n \"CH\",\n \"CL\",\n \"CM\",\n \"CP\",\n \"CS\",\n \"CX\",\n \"DP\",\n \"FB\",\n \"FC\",\n \"FM\",\n \"FN\",\n \"GA\",\n \"GB\",\n \"GS\",\n \"HS\",\n \"LL\",\n \"LP\",\n \"MB\",\n \"MC\",\n \"MD\",\n \"MH\",\n \"MM\",\n \"MQ\",\n \"NB\",\n \"NR\",\n \"PA\",\n \"PB\",\n \"PF\",\n \"RF\",\n \"RP\",\n \"SM\",\n \"SS\",\n \"TC\",\n \"TU\",\n \"VH\",\n \"XL\",\n]);\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\n/**\n * Validate Business (ROB) UEN (9 chars):\n * 8 digits + 1 check letter.\n */\nconst validateBusiness = (v: string): ValidateResult => {\n if (!isdigits(v.slice(0, 8))) {\n return err(\n \"INVALID_FORMAT\",\n \"Business UEN must start with 8 digits\",\n );\n }\n if (!/^[A-Z]$/.test(v[8]!)) {\n return err(\n \"INVALID_FORMAT\",\n \"Business UEN must end with a letter\",\n );\n }\n\n
|
|
1
|
+
{"version":3,"file":"uen.js","names":[],"sources":["../../src/sg/uen.ts"],"sourcesContent":["/**\n * UEN (Singapore Unique Entity Number).\n *\n * 9 or 10 characters identifying businesses and\n * entities registered in Singapore. Three formats:\n *\n * - Business (ROB): 8 digits + 1 check letter\n * - Local company (ROC): 4-digit year + 5 digits\n * + 1 check letter\n * - Other entities: R/S/T + 2-digit year + 2-letter\n * entity type + 4 digits + 1 check letter\n *\n * @see https://www.uen.gov.sg/\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Singapore-TIN.pdf\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/** Check letter alphabet for \"Other\" format. */\nconst OTHER_ALPHA = \"ABCDEFGHJKLMNPQRSTUVWX0123456789\";\n\nconst ENTITY_TYPES = new Set([\n \"CC\",\n \"CD\",\n \"CH\",\n \"CL\",\n \"CM\",\n \"CP\",\n \"CS\",\n \"CX\",\n \"DP\",\n \"FB\",\n \"FC\",\n \"FM\",\n \"FN\",\n \"GA\",\n \"GB\",\n \"GS\",\n \"HS\",\n \"LL\",\n \"LP\",\n \"MB\",\n \"MC\",\n \"MD\",\n \"MH\",\n \"MM\",\n \"MQ\",\n \"NB\",\n \"NR\",\n \"PA\",\n \"PB\",\n \"PF\",\n \"RF\",\n \"RP\",\n \"SM\",\n \"SS\",\n \"TC\",\n \"TU\",\n \"VH\",\n \"XL\",\n]);\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\n/**\n * Validate Business (ROB) UEN (9 chars):\n * 8 digits + 1 check letter.\n */\nconst BUSINESS_WEIGHTS = [10, 4, 9, 3, 8, 2, 7, 1] as const;\nconst BUSINESS_CHECK_ALPHA = \"XMKECAWLJDB\";\n\nconst validateBusiness = (v: string): ValidateResult => {\n if (!isdigits(v.slice(0, 8))) {\n return err(\n \"INVALID_FORMAT\",\n \"Business UEN must start with 8 digits\",\n );\n }\n // SAFETY: caller routes to this only when\n // v.length === 9.\n // eslint-disable-next-line no-non-null-assertion\n if (!/^[A-Z]$/.test(v[8]!)) {\n return err(\n \"INVALID_FORMAT\",\n \"Business UEN must end with a letter\",\n );\n }\n\n let sum = 0;\n for (const [i, weight] of BUSINESS_WEIGHTS.entries()) {\n sum += Number(v[i]) * weight;\n }\n const expected = BUSINESS_CHECK_ALPHA[sum % 11];\n if (v[8] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UEN check letter does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\n/**\n * Validate Local Company (ROC) UEN (10 chars):\n * 9 digits (year prefix) + 1 check letter.\n */\nconst LOCAL_WEIGHTS = [10, 8, 6, 4, 9, 7, 5, 3, 1] as const;\nconst LOCAL_CHECK_ALPHA = \"ZKCMDNERGWH\";\n\nconst validateLocalCompany = (\n v: string,\n): ValidateResult => {\n if (!isdigits(v.slice(0, 9))) {\n return err(\n \"INVALID_FORMAT\",\n \"Company UEN must have 9 digits\",\n );\n }\n // SAFETY: caller routes to this only when\n // v.length === 10.\n // eslint-disable-next-line no-non-null-assertion\n if (!/^[A-Z]$/.test(v[9]!)) {\n return err(\n \"INVALID_FORMAT\",\n \"Company UEN must end with a letter\",\n );\n }\n\n let sum = 0;\n for (const [i, weight] of LOCAL_WEIGHTS.entries()) {\n sum += Number(v[i]) * weight;\n }\n const expected = LOCAL_CHECK_ALPHA[sum % 11];\n if (v[9] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UEN check letter does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\n/**\n * Validate Other entity UEN (10 chars):\n * R/S/T + 2 digits + 2-letter type + 4 digits\n * + 1 check letter.\n */\nconst OTHER_WEIGHTS = [4, 3, 5, 3, 10, 2, 2, 5, 7] as const;\n\nconst validateOther = (v: string): ValidateResult => {\n // SAFETY: caller routes to this only when\n // v.length === 10.\n // eslint-disable-next-line no-non-null-assertion\n const prefix = v[0]!;\n if (prefix !== \"R\" && prefix !== \"S\" && prefix !== \"T\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Other UEN must start with R, S, or T\",\n );\n }\n if (!isdigits(v.slice(1, 3))) {\n return err(\n \"INVALID_FORMAT\",\n \"Other UEN positions 2-3 must be digits\",\n );\n }\n const entityType = v.slice(3, 5);\n if (!ENTITY_TYPES.has(entityType)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Unknown entity type: \" + entityType,\n );\n }\n if (!isdigits(v.slice(5, 9))) {\n return err(\n \"INVALID_FORMAT\",\n \"Other UEN positions 6-9 must be digits\",\n );\n }\n\n let sum = 0;\n for (const [i, weight] of OTHER_WEIGHTS.entries()) {\n const ch = v[i];\n if (ch === undefined) continue;\n const idx = OTHER_ALPHA.indexOf(ch);\n if (idx === -1) {\n return err(\n \"INVALID_FORMAT\",\n `Unexpected character at position ${i + 1}: ${ch}`,\n );\n }\n sum += idx * weight;\n }\n const expected =\n OTHER_ALPHA[(((sum - 5) % 11) + 11) % 11];\n if (v[9] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UEN check letter does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 9 && v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"UEN must be 9 or 10 characters\",\n );\n }\n\n if (!/^[A-Z0-9]+$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UEN must contain only digits and letters\",\n );\n }\n\n // 9 chars: business (ROB)\n if (v.length === 9) {\n return validateBusiness(v);\n }\n\n // 10 chars: first char digit => local company,\n // otherwise \"other\" entity\n // SAFETY: v.length === 10 here.\n // eslint-disable-next-line no-non-null-assertion\n if (isdigits(v[0]!)) {\n return validateLocalCompany(v);\n }\n return validateOther(v);\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Singapore UEN (business format). */\nconst generate = (): string => {\n const body = randomDigits(8);\n let sum = 0;\n for (const [i, weight] of BUSINESS_WEIGHTS.entries()) {\n sum += Number(body[i]) * weight;\n }\n // SAFETY: sum % 11 is in 0..10 and BUSINESS_CHECK_ALPHA\n // has 11 characters.\n // eslint-disable-next-line no-non-null-assertion\n const check = BUSINESS_CHECK_ALPHA[sum % 11]!;\n return body + check;\n};\n\n/** Singapore Unique Entity Number. */\nconst uen: Validator = {\n name: \"Singapore Unique Entity Number\",\n localName: \"Unique Entity Number\",\n abbreviation: \"UEN\",\n aliases: [\"UEN\", \"Unique Entity Number\"] as const,\n candidatePattern: \"[\\\\dSTR]\\\\d{7}[A-Z]\",\n country: \"SG\",\n entityType: \"company\",\n description:\n \"9 or 10-character business identifier issued by ACRA\",\n sourceUrl: \"https://www.uen.gov.sg/\",\n lengths: [9, 10] as const,\n examples: [\n \"00192200M\",\n \"197401143C\",\n \"S16FC0121D\",\n ] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default uen;\nexport { compact, format, validate, generate };\n"],"mappings":"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"}
|
package/dist/si/emso.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/si/emso.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 Slovenian EMSO. */
|
|
14
13
|
declare const generate: () => string;
|
|
15
14
|
/** Slovenian Unique Master Citizen Number. */
|
|
16
|
-
declare const emso: Validator
|
|
15
|
+
declare const emso: Validator<ParsedPersonId>;
|
|
17
16
|
//#endregion
|
|
18
17
|
export { compact, emso as default, format, generate, parse, validate };
|
|
19
18
|
//# sourceMappingURL=emso.d.ts.map
|
package/dist/si/emso.js
CHANGED
|
@@ -12,8 +12,14 @@ import { isValidDate } from "../_util/date.js";
|
|
|
12
12
|
* encoding DDMMYYY (7-digit birth year), region code,
|
|
13
13
|
* serial number, and a check digit.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* Canonical source:
|
|
16
|
+
* - Slovenia government registry overview
|
|
17
|
+
*
|
|
18
|
+
* This is the source behind the stricter register
|
|
19
|
+
* code check (50-59) and the decision to reject
|
|
20
|
+
* future birth dates in the embedded date field.
|
|
21
|
+
*
|
|
22
|
+
* @see https://www.gov.si/teme/registri-in-evidence-prebivalstva/
|
|
17
23
|
*/
|
|
18
24
|
const WEIGHTS = [
|
|
19
25
|
7,
|
|
@@ -47,6 +53,12 @@ const validate = (value) => {
|
|
|
47
53
|
if (yyyy < 900) yyyy += 2e3;
|
|
48
54
|
else yyyy += 1e3;
|
|
49
55
|
if (!isValidDate(yyyy, mm, dd)) return err("INVALID_COMPONENT", "EMŠO contains an invalid date");
|
|
56
|
+
const birthDate = new Date(yyyy, mm - 1, dd);
|
|
57
|
+
const today = /* @__PURE__ */ new Date();
|
|
58
|
+
today.setHours(0, 0, 0, 0);
|
|
59
|
+
if (birthDate > today) return err("INVALID_COMPONENT", "EMŠO cannot contain a future birth date");
|
|
60
|
+
const register = Number(v.slice(7, 9));
|
|
61
|
+
if (register < 50 || register > 59) return err("INVALID_COMPONENT", "EMSO register code must be between 50 and 59");
|
|
50
62
|
if (calcCheckDigit(v) !== Number(v[12])) return err("INVALID_CHECKSUM", "EMŠO check digit does not match");
|
|
51
63
|
return {
|
|
52
64
|
valid: true,
|
|
@@ -79,7 +91,7 @@ const generate = () => {
|
|
|
79
91
|
const dd = String(randomInt(1, 28)).padStart(2, "0");
|
|
80
92
|
const mm = String(randomInt(1, 12)).padStart(2, "0");
|
|
81
93
|
const yyy = String(randomInt(900, 999));
|
|
82
|
-
const rr = String(randomInt(50,
|
|
94
|
+
const rr = String(randomInt(50, 59));
|
|
83
95
|
const sss = String(randomInt(0, 999)).padStart(3, "0");
|
|
84
96
|
const partial = dd + mm + yyy + rr + sss;
|
|
85
97
|
const c = partial + String(calcCheckDigit(partial));
|
|
@@ -95,10 +107,11 @@ const emso = {
|
|
|
95
107
|
candidatePattern: "\\d{13}",
|
|
96
108
|
country: "SI",
|
|
97
109
|
entityType: "person",
|
|
98
|
-
sourceUrl: "https://www.gov.si/",
|
|
110
|
+
sourceUrl: "https://www.gov.si/teme/registri-in-evidence-prebivalstva/",
|
|
99
111
|
examples: ["0101006500006"],
|
|
100
112
|
compact,
|
|
101
113
|
format,
|
|
114
|
+
parse,
|
|
102
115
|
validate,
|
|
103
116
|
generate
|
|
104
117
|
};
|
package/dist/si/emso.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emso.js","names":[],"sources":["../../src/si/emso.ts"],"sourcesContent":["/**\n * EMŠO (Enotna matična številka občana).\n *\n * Slovenian unique master citizen number. 13 digits\n * encoding DDMMYYY (7-digit birth year), region code,\n * serial number, and a check digit.\n *\n *
|
|
1
|
+
{"version":3,"file":"emso.js","names":[],"sources":["../../src/si/emso.ts"],"sourcesContent":["/**\n * EMŠO (Enotna matična številka občana).\n *\n * Slovenian unique master citizen number. 13 digits\n * encoding DDMMYYY (7-digit birth year), region code,\n * serial number, and a check digit.\n *\n * Canonical source:\n * - Slovenia government registry overview\n *\n * This is the source behind the stricter register\n * code check (50-59) and the decision to reject\n * future birth dates in the embedded date field.\n *\n * @see https://www.gov.si/teme/registri-in-evidence-prebivalstva/\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 7, 6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2,\n] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\n/**\n * Compute the check digit matching python-stdnum:\n * `str(-total % 11 % 10)`.\n */\nconst calcCheckDigit = (v: string): number => {\n const total = weightedSum(v.slice(0, 12), WEIGHTS, 11);\n // Python's (-total % 11 % 10) — always 0..9\n // weightedSum already returns (sum % 11 + 11) % 11,\n // so total is 0..10. Negate within mod 11:\n return ((11 - total) % 11) % 10;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"EMŠO must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"EMŠO must contain only digits\",\n );\n }\n\n // Validate embedded birth date (DDMMYYY)\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n let yyyy = Number(v.slice(4, 7));\n // JMBG standard: 900-999 → 1900s, 000-899 → 2000s\n // Note: python-stdnum uses 800 as threshold, but\n // the official JMBG spec uses 900. No practical\n // difference (800-899 range has no living citizens).\n if (yyyy < 900) {\n yyyy += 2000;\n } else {\n yyyy += 1000;\n }\n if (!isValidDate(yyyy, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"EMŠO contains an invalid date\",\n );\n }\n const birthDate = new Date(yyyy, mm - 1, dd);\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n if (birthDate > today) {\n return err(\n \"INVALID_COMPONENT\",\n \"EMŠO cannot contain a future birth date\",\n );\n }\n\n const register = Number(v.slice(7, 9));\n if (register < 50 || register > 59) {\n return err(\n \"INVALID_COMPONENT\",\n \"EMSO register code must be between 50 and 59\",\n );\n }\n\n if (calcCheckDigit(v) !== Number(v[12])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"EMŠO 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 an EMSO.\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 dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n let yyyy = Number(v.slice(4, 7));\n if (yyyy < 900) {\n yyyy += 2000;\n } else {\n yyyy += 1000;\n }\n\n const serial = Number(v.slice(9, 12));\n\n return {\n birthDate: new Date(yyyy, mm - 1, dd),\n gender: serial < 500 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid Slovenian EMSO. */\nconst generate = (): string => {\n for (;;) {\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const yyy = String(randomInt(900, 999));\n const rr = String(randomInt(50, 59));\n const sss = String(randomInt(0, 999)).padStart(3, \"0\");\n const partial = dd + mm + yyy + rr + sss;\n const c = partial + String(calcCheckDigit(partial));\n if (validate(c).valid) return c;\n }\n};\n\n/** Slovenian Unique Master Citizen Number. */\nconst emso: Validator<ParsedPersonId> = {\n name: \"Slovenian Personal ID\",\n localName: \"Enotna matična številka občana\",\n abbreviation: \"EMŠO\",\n aliases: [\n \"EMŠO\",\n \"enotna matična številka občana\",\n ] as const,\n candidatePattern: \"\\\\d{13}\",\n country: \"SI\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.gov.si/teme/registri-in-evidence-prebivalstva/\",\n examples: [\"0101006500006\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default emso;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,UAAU;CACd;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAClC;AAED,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;;;;;AAMpB,MAAM,kBAAkB,MAAsB;AAK5C,SAAS,KAJK,YAAY,EAAE,MAAM,GAAG,GAAG,EAAE,SAAS,GAAG,IAI/B,KAAM;;AAG/B,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,iCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,gCACD;CAIH,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,IAAI,OAAO,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AAKhC,KAAI,OAAO,IACT,SAAQ;KAER,SAAQ;AAEV,KAAI,CAAC,YAAY,MAAM,IAAI,GAAG,CAC5B,QAAO,IACL,qBACA,gCACD;CAEH,MAAM,YAAY,IAAI,KAAK,MAAM,KAAK,GAAG,GAAG;CAC5C,MAAM,wBAAQ,IAAI,MAAM;AACxB,OAAM,SAAS,GAAG,GAAG,GAAG,EAAE;AAC1B,KAAI,YAAY,MACd,QAAO,IACL,qBACA,0CACD;CAGH,MAAM,WAAW,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AACtC,KAAI,WAAW,MAAM,WAAW,GAC9B,QAAO,IACL,qBACA,+CACD;AAGH,KAAI,eAAe,EAAE,KAAK,OAAO,EAAE,IAAI,CACrC,QAAO,IACL,oBACA,kCACD;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,IAAI,OAAO,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AAChC,KAAI,OAAO,IACT,SAAQ;KAER,SAAQ;CAGV,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;AAErC,QAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,GAAG;EACrC,QAAQ,SAAS,MAAM,SAAS;EACjC;;;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,MAAM,OAAO,UAAU,KAAK,IAAI,CAAC;EACvC,MAAM,KAAK,OAAO,UAAU,IAAI,GAAG,CAAC;EACpC,MAAM,MAAM,OAAO,UAAU,GAAG,IAAI,CAAC,CAAC,SAAS,GAAG,IAAI;EACtD,MAAM,UAAU,KAAK,KAAK,MAAM,KAAK;EACrC,MAAM,IAAI,UAAU,OAAO,eAAe,QAAQ,CAAC;AACnD,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,OAAkC;CACtC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,QACA,iCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;CACD"}
|
package/dist/si/mod.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import emso from "./emso.js";
|
|
3
2
|
import vat from "./vat.js";
|
|
4
3
|
|
|
5
4
|
//#region src/si/mod.d.ts
|
|
6
|
-
|
|
5
|
+
declare namespace mod_d_exports {
|
|
6
|
+
export { emso, vat };
|
|
7
|
+
}
|
|
7
8
|
//#endregion
|
|
8
9
|
export { emso, mod_d_exports, vat };
|
|
9
10
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/si/vat.d.ts
CHANGED
package/dist/sk/dic.d.ts
CHANGED
package/dist/sk/ico.d.ts
CHANGED
package/dist/sk/mod.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import dic from "./dic.js";
|
|
3
2
|
import ico from "./ico.js";
|
|
4
3
|
import rc from "./rc.js";
|
|
5
4
|
|
|
6
5
|
//#region src/sk/mod.d.ts
|
|
7
|
-
|
|
6
|
+
declare namespace mod_d_exports {
|
|
7
|
+
export { dic, ico, rc };
|
|
8
|
+
}
|
|
8
9
|
//#endregion
|
|
9
10
|
export { dic, ico, mod_d_exports, rc };
|
|
10
11
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/sk/rc.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { Validator } from "../types.js";
|
|
2
|
-
import { compact, format, parse, validate } from "../cz/rc.js";
|
|
1
|
+
import { ParsedPersonId, Validator } from "../types.js";
|
|
2
|
+
import { compact, format, generate, parse, validate } from "../cz/rc.js";
|
|
3
3
|
|
|
4
4
|
//#region src/sk/rc.d.ts
|
|
5
|
-
|
|
6
5
|
/** Slovak Birth Number. */
|
|
7
|
-
declare const rc: Validator
|
|
6
|
+
declare const rc: Validator<ParsedPersonId>;
|
|
8
7
|
//#endregion
|
|
9
|
-
export { compact, rc as default, format, parse, validate };
|
|
8
|
+
export { compact, rc as default, format, generate, parse, validate };
|
|
10
9
|
//# sourceMappingURL=rc.d.ts.map
|
package/dist/sk/rc.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { compact, format, parse, validate } from "../cz/rc.js";
|
|
1
|
+
import { compact, format, generate, parse, validate } from "../cz/rc.js";
|
|
2
2
|
//#region src/sk/rc.ts
|
|
3
3
|
/**
|
|
4
4
|
* RČ (Rodné číslo).
|
|
@@ -19,12 +19,15 @@ const rc = {
|
|
|
19
19
|
country: "SK",
|
|
20
20
|
entityType: "person",
|
|
21
21
|
sourceUrl: "https://www.minv.sk/",
|
|
22
|
+
lengths: [9, 10],
|
|
22
23
|
examples: ["7103192745"],
|
|
23
24
|
compact,
|
|
24
25
|
format,
|
|
26
|
+
generate,
|
|
27
|
+
parse,
|
|
25
28
|
validate
|
|
26
29
|
};
|
|
27
30
|
//#endregion
|
|
28
|
-
export { compact, rc as default, format, parse, validate };
|
|
31
|
+
export { compact, rc as default, format, generate, parse, validate };
|
|
29
32
|
|
|
30
33
|
//# sourceMappingURL=rc.js.map
|
package/dist/sk/rc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rc.js","names":[],"sources":["../../src/sk/rc.ts"],"sourcesContent":["/**\n * RČ (Rodné číslo).\n *\n * Slovak birth number. Identical algorithm to\n * the Czech birth number.\n *\n * @see https://www.mvcr.cz/mvcren/docDetail.aspx?docid=21975362&doctype=ART\n * @see https://www.minv.sk/\n */\n\nimport {
|
|
1
|
+
{"version":3,"file":"rc.js","names":[],"sources":["../../src/sk/rc.ts"],"sourcesContent":["/**\n * RČ (Rodné číslo).\n *\n * Slovak birth number. Identical algorithm to\n * the Czech birth number.\n *\n * @see https://www.mvcr.cz/mvcren/docDetail.aspx?docid=21975362&doctype=ART\n * @see https://www.minv.sk/\n */\n\nimport {\n compact,\n format,\n generate,\n parse,\n validate,\n} from \"../cz/rc\";\nimport type { ParsedPersonId, Validator } from \"../types\";\n\n/** Slovak Birth Number. */\nconst rc: Validator<ParsedPersonId> = {\n name: \"Slovak Birth Number\",\n localName: \"Rodné číslo\",\n abbreviation: \"RČ\",\n aliases: [\"rodné číslo\", \"RČ\"] as const,\n candidatePattern: \"\\\\d{6}/\\\\d{3,4}\",\n country: \"SK\",\n entityType: \"person\",\n sourceUrl: \"https://www.minv.sk/\",\n lengths: [9, 10] as const,\n examples: [\"7103192745\"] as const,\n compact,\n format,\n generate,\n parse,\n validate,\n};\n\nexport default rc;\nexport { compact, format, generate, parse, validate };\n"],"mappings":";;;;;;;;;;;;AAoBA,MAAM,KAAgC;CACpC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,eAAe,KAAK;CAC9B,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,GAAG,GAAG;CAChB,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;CACA;CACD"}
|
package/dist/th/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import tin from "./tin.js";
|
|
3
2
|
|
|
4
3
|
//#region src/th/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { tin };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { mod_d_exports, tin };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/th/tin.d.ts
CHANGED
package/dist/tr/mod.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import tckimlik from "./tckimlik.js";
|
|
3
2
|
import vkn from "./vkn.js";
|
|
4
3
|
|
|
5
4
|
//#region src/tr/mod.d.ts
|
|
6
|
-
|
|
5
|
+
declare namespace mod_d_exports {
|
|
6
|
+
export { tckimlik, vkn };
|
|
7
|
+
}
|
|
7
8
|
//#endregion
|
|
8
9
|
export { mod_d_exports, tckimlik, vkn };
|
|
9
10
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/tr/tckimlik.d.ts
CHANGED
package/dist/tr/vkn.d.ts
CHANGED
package/dist/tw/mod.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
1
|
import ubn from "./ubn.js";
|
|
3
2
|
|
|
4
3
|
//#region src/tw/mod.d.ts
|
|
5
|
-
|
|
4
|
+
declare namespace mod_d_exports {
|
|
5
|
+
export { ubn };
|
|
6
|
+
}
|
|
6
7
|
//#endregion
|
|
7
8
|
export { mod_d_exports, ubn };
|
|
8
9
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/tw/ubn.d.ts
CHANGED
package/dist/tw/ubn.js
CHANGED
|
@@ -39,7 +39,7 @@ const validate = (value) => {
|
|
|
39
39
|
if (v.length !== 8) return err("INVALID_LENGTH", "UBN must be exactly 8 digits");
|
|
40
40
|
if (!isdigits(v)) return err("INVALID_FORMAT", "UBN must contain only digits");
|
|
41
41
|
let sum = 0;
|
|
42
|
-
for (
|
|
42
|
+
for (const [i, weight] of WEIGHTS.entries()) sum += digitSum(Number(v[i]) * weight);
|
|
43
43
|
const checksum = sum % 10;
|
|
44
44
|
if (checksum === 0) return {
|
|
45
45
|
valid: true,
|
package/dist/tw/ubn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ubn.js","names":[],"sources":["../../src/tw/ubn.ts"],"sourcesContent":["/**\n * UBN (Unified Business Number, 統一編號).\n *\n * Taiwanese company identifier. 8 digits with a\n * weighted checksum. Weights [1,2,1,2,1,2,4,1];\n * sum the individual digits of each product, total\n * mod 10 must be 0. Special case: when the 7th digit\n * is 7, checksum 9 is also accepted.\n *\n * @see https://zh.wikipedia.org/wiki/統一編號\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 = [1, 2, 1, 2, 1, 2, 4, 1] as const;\n\n/** Sum the individual digits of a number. */\nconst digitSum = (n: number): number => {\n let sum = 0;\n while (n > 0) {\n sum += n % 10;\n n = Math.floor(n / 10);\n }\n return sum;\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 !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"UBN must be exactly 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UBN must contain only digits\",\n );\n }\n\n let sum = 0;\n for (
|
|
1
|
+
{"version":3,"file":"ubn.js","names":[],"sources":["../../src/tw/ubn.ts"],"sourcesContent":["/**\n * UBN (Unified Business Number, 統一編號).\n *\n * Taiwanese company identifier. 8 digits with a\n * weighted checksum. Weights [1,2,1,2,1,2,4,1];\n * sum the individual digits of each product, total\n * mod 10 must be 0. Special case: when the 7th digit\n * is 7, checksum 9 is also accepted.\n *\n * @see https://zh.wikipedia.org/wiki/統一編號\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 = [1, 2, 1, 2, 1, 2, 4, 1] as const;\n\n/** Sum the individual digits of a number. */\nconst digitSum = (n: number): number => {\n let sum = 0;\n while (n > 0) {\n sum += n % 10;\n n = Math.floor(n / 10);\n }\n return sum;\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 !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"UBN must be exactly 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UBN must contain only digits\",\n );\n }\n\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n sum += digitSum(Number(v[i]) * weight);\n }\n\n const checksum = sum % 10;\n if (checksum === 0) {\n return { valid: true, compact: v };\n }\n\n // Special case: when the 7th digit is 7 (product\n // 4*7=28), the checksum may be 9 instead of 0.\n if (checksum === 9 && v[6] === \"7\") {\n return { valid: true, compact: v };\n }\n\n return err(\n \"INVALID_CHECKSUM\",\n \"UBN checksum does not match\",\n );\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid UBN. */\nconst generate = (): string => {\n for (;;) {\n const prefix = randomDigits(7);\n for (let d = 0; d < 10; d++) {\n const candidate = `${prefix}${d}`;\n const r = validate(candidate);\n if (r.valid) return candidate;\n }\n }\n};\n\n/** Taiwanese Unified Business Number. */\nconst ubn: Validator = {\n name: \"Unified Business Number\",\n localName: \"統一編號\",\n abbreviation: \"UBN\",\n aliases: [\"統一編號\", \"UBN\"] as const,\n candidatePattern: \"\\\\d{8}\",\n country: \"TW\",\n entityType: \"company\",\n description:\n \"8-digit company identifier issued by the Ministry of Economic Affairs\",\n sourceUrl:\n \"https://zh.wikipedia.org/wiki/%E7%B5%B1%E4%B8%80%E7%B7%A8%E8%99%9F\",\n lengths: [8] as const,\n examples: [\"00501503\", \"04595257\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default ubn;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;;AAGxC,MAAM,YAAY,MAAsB;CACtC,IAAI,MAAM;AACV,QAAO,IAAI,GAAG;AACZ,SAAO,IAAI;AACX,MAAI,KAAK,MAAM,IAAI,GAAG;;AAExB,QAAO;;AAGT,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,+BACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,+BACD;CAGH,IAAI,MAAM;AACV,MAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,SAAS,CACzC,QAAO,SAAS,OAAO,EAAE,GAAG,GAAG,OAAO;CAGxC,MAAM,WAAW,MAAM;AACvB,KAAI,aAAa,EACf,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;AAKpC,KAAI,aAAa,KAAK,EAAE,OAAO,IAC7B,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;AAGpC,QAAO,IACL,oBACA,8BACD;;AAGH,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,SAAS,aAAa,EAAE;AAC9B,OAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;GAC3B,MAAM,YAAY,GAAG,SAAS;AAE9B,OADU,SAAS,UAAU,CACvB,MAAO,QAAO;;;;;AAM1B,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,QAAQ,MAAM;CACxB,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,aACE;CACF,WACE;CACF,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,YAAY,WAAW;CAClC;CACA;CACA;CACA;CACD"}
|