@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.
Files changed (474) hide show
  1. package/LICENSE +1 -5
  2. package/README.md +28 -4
  3. package/dist/_checksums/mod112.js +5 -5
  4. package/dist/_checksums/mod112.js.map +1 -1
  5. package/dist/_util/generate.d.ts +13 -1
  6. package/dist/_util/generate.js +23 -1
  7. package/dist/_util/generate.js.map +1 -1
  8. package/dist/ad/mod.d.ts +3 -2
  9. package/dist/ad/nrt.js +3 -2
  10. package/dist/ad/nrt.js.map +1 -1
  11. package/dist/ae/eid.d.ts +0 -1
  12. package/dist/ae/mod.d.ts +3 -2
  13. package/dist/ai/mod.d.ts +3 -2
  14. package/dist/al/mod.d.ts +3 -2
  15. package/dist/am/mod.d.ts +3 -2
  16. package/dist/ar/cbu.d.ts +0 -1
  17. package/dist/ar/cbu.js +1 -1
  18. package/dist/ar/cbu.js.map +1 -1
  19. package/dist/ar/cuit.d.ts +0 -1
  20. package/dist/ar/cuit.js +12 -12
  21. package/dist/ar/cuit.js.map +1 -1
  22. package/dist/ar/mod.d.ts +3 -2
  23. package/dist/at/mod.d.ts +3 -2
  24. package/dist/at/tin.d.ts +0 -1
  25. package/dist/at/uid.d.ts +0 -1
  26. package/dist/at/vnr.d.ts +3 -2
  27. package/dist/at/vnr.js +20 -3
  28. package/dist/at/vnr.js.map +1 -1
  29. package/dist/au/abn.d.ts +0 -1
  30. package/dist/au/acn.d.ts +0 -1
  31. package/dist/au/mod.d.ts +3 -2
  32. package/dist/au/tfn.d.ts +0 -1
  33. package/dist/az/mod.d.ts +3 -2
  34. package/dist/az/voen.d.ts +0 -1
  35. package/dist/az/voen.js.map +1 -1
  36. package/dist/ba/jmbg.d.ts +1 -2
  37. package/dist/ba/jmbg.js +1 -0
  38. package/dist/ba/jmbg.js.map +1 -1
  39. package/dist/ba/mod.d.ts +3 -2
  40. package/dist/bd/mod.d.ts +3 -2
  41. package/dist/bd/nid.js +10 -11
  42. package/dist/bd/nid.js.map +1 -1
  43. package/dist/be/bis.d.ts +0 -1
  44. package/dist/be/mod.d.ts +3 -2
  45. package/dist/be/nn.d.ts +0 -1
  46. package/dist/be/vat.d.ts +0 -1
  47. package/dist/bg/egn.d.ts +1 -2
  48. package/dist/bg/egn.js +10 -3
  49. package/dist/bg/egn.js.map +1 -1
  50. package/dist/bg/mod.d.ts +3 -2
  51. package/dist/bg/pnf.d.ts +0 -1
  52. package/dist/bg/vat.d.ts +0 -1
  53. package/dist/bh/cpr.d.ts +3 -2
  54. package/dist/bh/cpr.js +8 -2
  55. package/dist/bh/cpr.js.map +1 -1
  56. package/dist/bh/mod.d.ts +3 -2
  57. package/dist/bic.js +13 -15
  58. package/dist/bic.js.map +1 -1
  59. package/dist/br/cnpj.d.ts +0 -1
  60. package/dist/br/cpf.d.ts +0 -1
  61. package/dist/br/mod.d.ts +3 -2
  62. package/dist/by/mod.d.ts +3 -2
  63. package/dist/by/unp.d.ts +0 -1
  64. package/dist/by/unp.js +6 -3
  65. package/dist/by/unp.js.map +1 -1
  66. package/dist/bz/mod.d.ts +3 -2
  67. package/dist/bz/tin.d.ts +3 -2
  68. package/dist/bz/tin.js +9 -1
  69. package/dist/bz/tin.js.map +1 -1
  70. package/dist/ca/bn.d.ts +0 -1
  71. package/dist/ca/mod.d.ts +3 -2
  72. package/dist/ca/sin.d.ts +0 -1
  73. package/dist/ch/mod.d.ts +3 -2
  74. package/dist/ch/ssn.d.ts +0 -1
  75. package/dist/ch/uid.d.ts +0 -1
  76. package/dist/ch/vat.d.ts +0 -1
  77. package/dist/cl/mod.d.ts +3 -2
  78. package/dist/cl/rut.d.ts +0 -1
  79. package/dist/cl/rut.js +1 -1
  80. package/dist/cl/rut.js.map +1 -1
  81. package/dist/cn/mod.d.ts +3 -2
  82. package/dist/cn/ric.d.ts +1 -2
  83. package/dist/cn/ric.js +1 -0
  84. package/dist/cn/ric.js.map +1 -1
  85. package/dist/cn/uscc.d.ts +0 -1
  86. package/dist/cn/uscc.js +7 -6
  87. package/dist/cn/uscc.js.map +1 -1
  88. package/dist/co/mod.d.ts +3 -2
  89. package/dist/co/nit.d.ts +0 -1
  90. package/dist/co/nit.js +4 -1
  91. package/dist/co/nit.js.map +1 -1
  92. package/dist/cr/cpf.js +4 -3
  93. package/dist/cr/cpf.js.map +1 -1
  94. package/dist/cr/mod.d.ts +3 -2
  95. package/dist/creditcard.d.ts +0 -1
  96. package/dist/cu/mod.d.ts +3 -2
  97. package/dist/cu/ni.d.ts +4 -3
  98. package/dist/cu/ni.js +11 -1
  99. package/dist/cu/ni.js.map +1 -1
  100. package/dist/cy/mod.d.ts +3 -2
  101. package/dist/cy/vat.d.ts +0 -1
  102. package/dist/cz/dic.d.ts +0 -1
  103. package/dist/cz/ico.d.ts +0 -1
  104. package/dist/cz/mod.d.ts +3 -2
  105. package/dist/cz/rc.d.ts +1 -2
  106. package/dist/cz/rc.js +33 -8
  107. package/dist/cz/rc.js.map +1 -1
  108. package/dist/de/handelsreg.js +9 -9
  109. package/dist/de/handelsreg.js.map +1 -1
  110. package/dist/de/idnr.d.ts +0 -1
  111. package/dist/de/idnr.js.map +1 -1
  112. package/dist/de/mod.d.ts +3 -2
  113. package/dist/de/stnr.d.ts +0 -1
  114. package/dist/de/stnr.js.map +1 -1
  115. package/dist/de/svnr.d.ts +0 -1
  116. package/dist/de/svnr.js +2 -2
  117. package/dist/de/svnr.js.map +1 -1
  118. package/dist/de/vat.d.ts +0 -1
  119. package/dist/dk/cpr.d.ts +4 -3
  120. package/dist/dk/cpr.js +12 -2
  121. package/dist/dk/cpr.js.map +1 -1
  122. package/dist/dk/cvr.d.ts +0 -1
  123. package/dist/dk/mod.d.ts +3 -2
  124. package/dist/dk/vat.d.ts +0 -1
  125. package/dist/do/mod.d.ts +3 -2
  126. package/dist/do/rnc.d.ts +0 -1
  127. package/dist/do/rnc.js +1 -1
  128. package/dist/do/rnc.js.map +1 -1
  129. package/dist/ec/mod.d.ts +3 -2
  130. package/dist/ec/ruc.d.ts +0 -1
  131. package/dist/ec/ruc.js +1 -1
  132. package/dist/ec/ruc.js.map +1 -1
  133. package/dist/ee/ik.d.ts +1 -2
  134. package/dist/ee/ik.js +12 -4
  135. package/dist/ee/ik.js.map +1 -1
  136. package/dist/ee/mod.d.ts +3 -2
  137. package/dist/ee/registrikood.d.ts +0 -1
  138. package/dist/ee/registrikood.js +8 -7
  139. package/dist/ee/registrikood.js.map +1 -1
  140. package/dist/ee/vat.d.ts +0 -1
  141. package/dist/eg/mod.d.ts +3 -2
  142. package/dist/es/cif.d.ts +0 -1
  143. package/dist/es/cif.js +2 -2
  144. package/dist/es/cif.js.map +1 -1
  145. package/dist/es/dni.d.ts +0 -1
  146. package/dist/es/mod.d.ts +3 -2
  147. package/dist/es/nie.d.ts +0 -1
  148. package/dist/es/nie.js +13 -13
  149. package/dist/es/nie.js.map +1 -1
  150. package/dist/es/nss.d.ts +0 -1
  151. package/dist/es/vat.d.ts +0 -1
  152. package/dist/eu/mod.d.ts +3 -2
  153. package/dist/eu/vat.d.ts +3 -2
  154. package/dist/eu/vat.js +43 -2
  155. package/dist/eu/vat.js.map +1 -1
  156. package/dist/fi/hetu.d.ts +4 -3
  157. package/dist/fi/hetu.js +17 -2
  158. package/dist/fi/hetu.js.map +1 -1
  159. package/dist/fi/mod.d.ts +3 -2
  160. package/dist/fi/vat.d.ts +0 -1
  161. package/dist/fi/ytunnus.d.ts +0 -1
  162. package/dist/fr/mod.d.ts +3 -2
  163. package/dist/fr/nif.d.ts +0 -1
  164. package/dist/fr/nir.d.ts +1 -2
  165. package/dist/fr/nir.js +1 -0
  166. package/dist/fr/nir.js.map +1 -1
  167. package/dist/fr/siren.d.ts +0 -1
  168. package/dist/fr/siret.d.ts +0 -1
  169. package/dist/fr/tva.d.ts +0 -1
  170. package/dist/gb/mod.d.ts +3 -2
  171. package/dist/gb/nino.js +7 -7
  172. package/dist/gb/nino.js.map +1 -1
  173. package/dist/gb/sedol.d.ts +0 -1
  174. package/dist/gb/sedol.js +8 -7
  175. package/dist/gb/sedol.js.map +1 -1
  176. package/dist/gb/utr.d.ts +0 -1
  177. package/dist/gb/vat.d.ts +0 -1
  178. package/dist/ge/mod.d.ts +3 -2
  179. package/dist/gh/mod.d.ts +3 -2
  180. package/dist/gh/tin.d.ts +0 -1
  181. package/dist/gh/tin.js +9 -9
  182. package/dist/gh/tin.js.map +1 -1
  183. package/dist/gr/amka.d.ts +0 -1
  184. package/dist/gr/mod.d.ts +3 -2
  185. package/dist/gr/vat.d.ts +0 -1
  186. package/dist/gt/mod.d.ts +3 -2
  187. package/dist/gt/nit.d.ts +0 -1
  188. package/dist/gt/nit.js +5 -2
  189. package/dist/gt/nit.js.map +1 -1
  190. package/dist/hk/hkid.d.ts +0 -1
  191. package/dist/hk/hkid.js +1 -0
  192. package/dist/hk/hkid.js.map +1 -1
  193. package/dist/hk/mod.d.ts +3 -2
  194. package/dist/hr/mod.d.ts +3 -2
  195. package/dist/hr/vat.d.ts +0 -1
  196. package/dist/hu/mod.d.ts +3 -2
  197. package/dist/hu/vat.d.ts +0 -1
  198. package/dist/iban.d.ts +0 -1
  199. package/dist/id/mod.d.ts +3 -2
  200. package/dist/id/npwp.d.ts +0 -1
  201. package/dist/ie/mod.d.ts +3 -2
  202. package/dist/ie/pps.d.ts +0 -1
  203. package/dist/ie/vat.d.ts +0 -1
  204. package/dist/il/idnr.d.ts +0 -1
  205. package/dist/il/mod.d.ts +3 -2
  206. package/dist/in/aadhaar.d.ts +0 -1
  207. package/dist/in/gstin.d.ts +0 -1
  208. package/dist/in/gstin.js +3 -1
  209. package/dist/in/gstin.js.map +1 -1
  210. package/dist/in/mod.d.ts +3 -2
  211. package/dist/in/pan.js +2 -2
  212. package/dist/in/pan.js.map +1 -1
  213. package/dist/index.d.ts +2 -2
  214. package/dist/iq/mod.d.ts +3 -2
  215. package/dist/ir/mod.d.ts +3 -2
  216. package/dist/ir/nid.d.ts +0 -1
  217. package/dist/is/kennitala.d.ts +0 -1
  218. package/dist/is/mod.d.ts +3 -2
  219. package/dist/isin.d.ts +0 -1
  220. package/dist/isin.js +9 -9
  221. package/dist/isin.js.map +1 -1
  222. package/dist/it/codicefiscale.d.ts +4 -3
  223. package/dist/it/codicefiscale.js +26 -2
  224. package/dist/it/codicefiscale.js.map +1 -1
  225. package/dist/it/iva.d.ts +0 -1
  226. package/dist/it/mod.d.ts +3 -2
  227. package/dist/jp/cn.d.ts +0 -1
  228. package/dist/jp/mod.d.ts +3 -2
  229. package/dist/jp/mynumber.d.ts +0 -1
  230. package/dist/kr/mod.d.ts +3 -2
  231. package/dist/kr/rrn.d.ts +4 -3
  232. package/dist/kr/rrn.js +13 -2
  233. package/dist/kr/rrn.js.map +1 -1
  234. package/dist/kw/civil.d.ts +6 -5
  235. package/dist/kw/civil.js +18 -3
  236. package/dist/kw/civil.js.map +1 -1
  237. package/dist/kw/mod.d.ts +3 -2
  238. package/dist/kz/iin.d.ts +1 -2
  239. package/dist/kz/iin.js +1 -0
  240. package/dist/kz/iin.js.map +1 -1
  241. package/dist/kz/mod.d.ts +3 -2
  242. package/dist/lei.d.ts +0 -1
  243. package/dist/li/mod.d.ts +3 -2
  244. package/dist/lk/mod.d.ts +3 -2
  245. package/dist/lk/nic.d.ts +4 -3
  246. package/dist/lk/nic.js +14 -2
  247. package/dist/lk/nic.js.map +1 -1
  248. package/dist/lt/asmens.d.ts +0 -1
  249. package/dist/lt/mod.d.ts +3 -2
  250. package/dist/lt/vat.d.ts +0 -1
  251. package/dist/lu/mod.d.ts +3 -2
  252. package/dist/lu/vat.d.ts +0 -1
  253. package/dist/luhn.d.ts +0 -1
  254. package/dist/luhn.js +7 -0
  255. package/dist/luhn.js.map +1 -1
  256. package/dist/lv/mod.d.ts +3 -2
  257. package/dist/lv/vat.d.ts +0 -1
  258. package/dist/lv/vat.js +39 -12
  259. package/dist/lv/vat.js.map +1 -1
  260. package/dist/ma/ice.d.ts +0 -1
  261. package/dist/ma/mod.d.ts +3 -2
  262. package/dist/mc/mod.d.ts +3 -2
  263. package/dist/mc/tva.d.ts +0 -1
  264. package/dist/md/idno.d.ts +0 -1
  265. package/dist/md/mod.d.ts +3 -2
  266. package/dist/me/mod.d.ts +3 -2
  267. package/dist/me/pib.d.ts +0 -1
  268. package/dist/mk/edb.d.ts +0 -1
  269. package/dist/mk/mod.d.ts +3 -2
  270. package/dist/mt/mod.d.ts +3 -2
  271. package/dist/mt/vat.d.ts +0 -1
  272. package/dist/mu/mod.d.ts +3 -2
  273. package/dist/mx/clabe.d.ts +0 -1
  274. package/dist/mx/curp.d.ts +4 -3
  275. package/dist/mx/curp.js +25 -3
  276. package/dist/mx/curp.js.map +1 -1
  277. package/dist/mx/mod.d.ts +3 -2
  278. package/dist/mx/rfc.d.ts +3 -2
  279. package/dist/mx/rfc.js +21 -2
  280. package/dist/mx/rfc.js.map +1 -1
  281. package/dist/my/mod.d.ts +3 -2
  282. package/dist/my/nric.d.ts +4 -3
  283. package/dist/my/nric.js +16 -2
  284. package/dist/my/nric.js.map +1 -1
  285. package/dist/ng/mod.d.ts +3 -2
  286. package/dist/ni/mod.d.ts +3 -2
  287. package/dist/ni/ruc.d.ts +0 -1
  288. package/dist/nl/bsn.d.ts +0 -1
  289. package/dist/nl/mod.d.ts +3 -2
  290. package/dist/nl/vat.d.ts +0 -1
  291. package/dist/nl/vat.js +9 -43
  292. package/dist/nl/vat.js.map +1 -1
  293. package/dist/no/fodselsnummer.d.ts +1 -2
  294. package/dist/no/fodselsnummer.js +1 -0
  295. package/dist/no/fodselsnummer.js.map +1 -1
  296. package/dist/no/mod.d.ts +3 -2
  297. package/dist/no/mva.d.ts +0 -1
  298. package/dist/no/orgnr.d.ts +0 -1
  299. package/dist/nz/ird.d.ts +0 -1
  300. package/dist/nz/ird.js +2 -2
  301. package/dist/nz/ird.js.map +1 -1
  302. package/dist/nz/mod.d.ts +3 -2
  303. package/dist/pa/mod.d.ts +3 -2
  304. package/dist/pa/ruc.d.ts +0 -1
  305. package/dist/pa/ruc.js +3 -1
  306. package/dist/pa/ruc.js.map +1 -1
  307. package/dist/patterns.d.ts +1 -4
  308. package/dist/patterns.js +80 -23
  309. package/dist/patterns.js.map +1 -1
  310. package/dist/pe/mod.d.ts +3 -2
  311. package/dist/pe/ruc.d.ts +0 -1
  312. package/dist/pe/ruc.js +9 -9
  313. package/dist/pe/ruc.js.map +1 -1
  314. package/dist/ph/mod.d.ts +3 -2
  315. package/dist/pk/cnic.js.map +1 -1
  316. package/dist/pk/mod.d.ts +3 -2
  317. package/dist/pl/mod.d.ts +3 -2
  318. package/dist/pl/nip.d.ts +0 -1
  319. package/dist/pl/pesel.d.ts +1 -2
  320. package/dist/pl/pesel.js +1 -0
  321. package/dist/pl/pesel.js.map +1 -1
  322. package/dist/pl/regon.d.ts +0 -1
  323. package/dist/pt/cc.d.ts +0 -1
  324. package/dist/pt/cc.js +6 -4
  325. package/dist/pt/cc.js.map +1 -1
  326. package/dist/pt/mod.d.ts +3 -2
  327. package/dist/pt/vat.d.ts +0 -1
  328. package/dist/ro/cnp.d.ts +1 -2
  329. package/dist/ro/cnp.js +1 -0
  330. package/dist/ro/cnp.js.map +1 -1
  331. package/dist/ro/mod.d.ts +3 -2
  332. package/dist/ro/vat.d.ts +0 -1
  333. package/dist/rs/mod.d.ts +3 -2
  334. package/dist/rs/pib.d.ts +0 -1
  335. package/dist/ru/inn.d.ts +0 -1
  336. package/dist/ru/inn.js +1 -1
  337. package/dist/ru/inn.js.map +1 -1
  338. package/dist/ru/mod.d.ts +3 -2
  339. package/dist/se/mod.d.ts +3 -2
  340. package/dist/se/orgnr.d.ts +0 -1
  341. package/dist/se/personnummer.d.ts +1 -2
  342. package/dist/se/personnummer.js +1 -0
  343. package/dist/se/personnummer.js.map +1 -1
  344. package/dist/se/vat.d.ts +0 -1
  345. package/dist/sg/mod.d.ts +3 -2
  346. package/dist/sg/uen.d.ts +0 -1
  347. package/dist/sg/uen.js +46 -55
  348. package/dist/sg/uen.js.map +1 -1
  349. package/dist/si/emso.d.ts +1 -2
  350. package/dist/si/emso.js +17 -4
  351. package/dist/si/emso.js.map +1 -1
  352. package/dist/si/mod.d.ts +3 -2
  353. package/dist/si/vat.d.ts +0 -1
  354. package/dist/sk/dic.d.ts +0 -1
  355. package/dist/sk/ico.d.ts +0 -1
  356. package/dist/sk/mod.d.ts +3 -2
  357. package/dist/sk/rc.d.ts +4 -5
  358. package/dist/sk/rc.js +5 -2
  359. package/dist/sk/rc.js.map +1 -1
  360. package/dist/th/mod.d.ts +3 -2
  361. package/dist/th/tin.d.ts +0 -1
  362. package/dist/tr/mod.d.ts +3 -2
  363. package/dist/tr/tckimlik.d.ts +0 -1
  364. package/dist/tr/vkn.d.ts +0 -1
  365. package/dist/tw/mod.d.ts +3 -2
  366. package/dist/tw/ubn.d.ts +0 -1
  367. package/dist/tw/ubn.js +1 -1
  368. package/dist/tw/ubn.js.map +1 -1
  369. package/dist/types.d.ts +35 -22
  370. package/dist/ua/edrpou.d.ts +0 -1
  371. package/dist/ua/edrpou.js +4 -1
  372. package/dist/ua/edrpou.js.map +1 -1
  373. package/dist/ua/mod.d.ts +3 -2
  374. package/dist/us/ein.js +87 -87
  375. package/dist/us/ein.js.map +1 -1
  376. package/dist/us/itin.js +3 -4
  377. package/dist/us/itin.js.map +1 -1
  378. package/dist/us/mod.d.ts +3 -2
  379. package/dist/us/rtn.d.ts +0 -1
  380. package/dist/us/rtn.js +8 -5
  381. package/dist/us/rtn.js.map +1 -1
  382. package/dist/uy/mod.d.ts +3 -2
  383. package/dist/uy/rut.d.ts +0 -1
  384. package/dist/uy/rut.js +1 -1
  385. package/dist/uy/rut.js.map +1 -1
  386. package/dist/ve/mod.d.ts +3 -2
  387. package/dist/ve/rif.d.ts +0 -1
  388. package/dist/ve/rif.js +11 -11
  389. package/dist/ve/rif.js.map +1 -1
  390. package/dist/vn/mod.d.ts +3 -2
  391. package/dist/vn/mst.d.ts +0 -1
  392. package/dist/za/idnr.d.ts +1 -2
  393. package/dist/za/idnr.js +1 -0
  394. package/dist/za/idnr.js.map +1 -1
  395. package/dist/za/mod.d.ts +3 -2
  396. package/package.json +18 -15
  397. package/src/_checksums/mod112.ts +7 -6
  398. package/src/_util/generate.ts +38 -0
  399. package/src/ad/nrt.ts +12 -4
  400. package/src/ar/cbu.ts +2 -2
  401. package/src/ar/cuit.ts +15 -7
  402. package/src/at/vnr.ts +26 -4
  403. package/src/az/voen.ts +2 -0
  404. package/src/ba/jmbg.ts +2 -1
  405. package/src/bd/nid.ts +4 -4
  406. package/src/bg/egn.ts +12 -4
  407. package/src/bh/cpr.ts +10 -1
  408. package/src/bic.ts +19 -17
  409. package/src/by/unp.ts +9 -4
  410. package/src/bz/tin.ts +12 -1
  411. package/src/cl/rut.ts +4 -2
  412. package/src/cn/ric.ts +4 -1
  413. package/src/cn/uscc.ts +20 -8
  414. package/src/co/nit.ts +6 -2
  415. package/src/cr/cpf.ts +4 -3
  416. package/src/cu/ni.ts +22 -2
  417. package/src/cz/rc.ts +54 -23
  418. package/src/de/handelsreg.ts +14 -3
  419. package/src/de/idnr.ts +3 -0
  420. package/src/de/stnr.ts +4 -0
  421. package/src/de/svnr.ts +7 -2
  422. package/src/dk/cpr.ts +16 -2
  423. package/src/do/rnc.ts +2 -2
  424. package/src/ec/ruc.ts +2 -2
  425. package/src/ee/ik.ts +14 -4
  426. package/src/ee/registrikood.ts +4 -3
  427. package/src/es/cif.ts +2 -3
  428. package/src/es/nie.ts +10 -5
  429. package/src/eu/vat.ts +46 -1
  430. package/src/fi/hetu.ts +19 -2
  431. package/src/fr/nir.ts +2 -1
  432. package/src/gb/nino.ts +11 -10
  433. package/src/gb/sedol.ts +14 -12
  434. package/src/gh/tin.ts +4 -3
  435. package/src/gt/nit.ts +6 -3
  436. package/src/hk/hkid.ts +2 -1
  437. package/src/in/gstin.ts +3 -1
  438. package/src/in/pan.ts +8 -3
  439. package/src/index.ts +3 -0
  440. package/src/isin.ts +10 -4
  441. package/src/it/codicefiscale.ts +40 -2
  442. package/src/kr/rrn.ts +20 -2
  443. package/src/kw/civil.ts +25 -9
  444. package/src/kz/iin.ts +2 -1
  445. package/src/lk/nic.ts +24 -2
  446. package/src/luhn.ts +3 -0
  447. package/src/lv/vat.ts +46 -20
  448. package/src/mx/curp.ts +41 -5
  449. package/src/mx/rfc.ts +35 -4
  450. package/src/my/nric.ts +26 -2
  451. package/src/nl/vat.ts +11 -66
  452. package/src/no/fodselsnummer.ts +2 -1
  453. package/src/nz/ird.ts +4 -4
  454. package/src/pa/ruc.ts +32 -8
  455. package/src/patterns.ts +135 -28
  456. package/src/pe/ruc.ts +6 -7
  457. package/src/pk/cnic.ts +2 -0
  458. package/src/pl/pesel.ts +2 -1
  459. package/src/pt/cc.ts +6 -4
  460. package/src/ro/cnp.ts +2 -1
  461. package/src/ru/inn.ts +2 -2
  462. package/src/se/personnummer.ts +2 -1
  463. package/src/sg/uen.ts +37 -20
  464. package/src/si/emso.ts +30 -5
  465. package/src/sk/rc.ts +13 -4
  466. package/src/tw/ubn.ts +2 -2
  467. package/src/types.ts +37 -6
  468. package/src/ua/edrpou.ts +3 -2
  469. package/src/us/ein.ts +88 -88
  470. package/src/us/itin.ts +7 -8
  471. package/src/us/rtn.ts +16 -11
  472. package/src/uy/rut.ts +2 -2
  473. package/src/ve/rif.ts +11 -6
  474. package/src/za/idnr.ts +2 -1
package/src/bz/tin.ts CHANGED
@@ -26,6 +26,7 @@
26
26
  */
27
27
 
28
28
  import { clean } from "#util/clean";
29
+ import { randomDigits, randomInt } from "#util/generate";
29
30
  import { err } from "#util/result";
30
31
 
31
32
  import type { ValidateResult, Validator } from "../types";
@@ -79,6 +80,15 @@ const format = (value: string): string => {
79
80
  return `${v.slice(0, 6)}-${v.slice(6)}`;
80
81
  };
81
82
 
83
+ /** Generate a random valid Belize TIN. */
84
+ const generate = (): string => {
85
+ const base = randomDigits(6);
86
+ const suffixes = ["", ...SUFFIX_CODES] as const;
87
+ const suffix =
88
+ suffixes[randomInt(0, suffixes.length - 1)] ?? "";
89
+ return `${base}${suffix}`;
90
+ };
91
+
82
92
  /**
83
93
  * Belize Tax Identification Number.
84
94
  *
@@ -97,6 +107,7 @@ const tin: Validator = {
97
107
  compact,
98
108
  format,
99
109
  validate,
110
+ generate,
100
111
  description:
101
112
  "Belize tax number issued by the Belize Tax Service Department",
102
113
  sourceUrl:
@@ -104,4 +115,4 @@ const tin: Validator = {
104
115
  };
105
116
 
106
117
  export default tin;
107
- export { compact, format, validate };
118
+ export { compact, format, generate, validate };
package/src/cl/rut.ts CHANGED
@@ -35,10 +35,12 @@ const compact = (value: string): string => {
35
35
  * 11 -> "0", 10 -> "K", else the digit as string.
36
36
  */
37
37
  const calcCheckDigit = (body: string): string => {
38
- const weights = [2, 3, 4, 5, 6, 7];
38
+ const weights = [2, 3, 4, 5, 6, 7] as const;
39
39
  let sum = 0;
40
40
  for (let i = body.length - 1, w = 0; i >= 0; i--, w++) {
41
- sum += Number(body[i]) * weights[w % 6]!;
41
+ // SAFETY: w % weights.length is a valid index.
42
+ // eslint-disable-next-line no-non-null-assertion
43
+ sum += Number(body[i]) * weights[w % weights.length]!;
42
44
  }
43
45
  const remainder = 11 - (sum % 11);
44
46
  if (remainder === 11) return "0";
package/src/cn/ric.ts CHANGED
@@ -67,6 +67,8 @@ const validate = (value: string): ValidateResult => {
67
67
  "RIC must contain only digits (plus check char)",
68
68
  );
69
69
  }
70
+ // SAFETY: 18-character branch guarantees v[17] exists.
71
+ // eslint-disable-next-line no-non-null-assertion
70
72
  const lastChar = v[17]!;
71
73
  if (!isdigits(lastChar) && lastChar !== "X") {
72
74
  return err(
@@ -153,7 +155,7 @@ const generate = (): string => {
153
155
  };
154
156
 
155
157
  /** Chinese Resident Identity Card number. */
156
- const ric: Validator = {
158
+ const ric: Validator<ParsedPersonId> = {
157
159
  name: "Chinese Resident Identity Card",
158
160
  localName: "居民身份证号码",
159
161
  abbreviation: "RIC",
@@ -172,6 +174,7 @@ const ric: Validator = {
172
174
  ] as const,
173
175
  compact,
174
176
  format,
177
+ parse,
175
178
  validate,
176
179
  generate,
177
180
  };
package/src/cn/uscc.ts CHANGED
@@ -10,7 +10,11 @@
10
10
  */
11
11
 
12
12
  import { clean } from "#util/clean";
13
- import { randomDigits, randomInt } from "#util/generate";
13
+ import {
14
+ randomChar,
15
+ randomDigits,
16
+ randomInt,
17
+ } from "#util/generate";
14
18
  import { err } from "#util/result";
15
19
  import { isdigits } from "#util/strings";
16
20
 
@@ -28,10 +32,14 @@ const compact = (value: string): string =>
28
32
 
29
33
  const calcCheckChar = (value: string): string => {
30
34
  let total = 0;
31
- for (let i = 0; i < 17; i++) {
32
- const idx = ALPHABET.indexOf(value[i]!);
33
- total += idx * WEIGHTS[i]!;
35
+ for (const [i, weight] of WEIGHTS.entries()) {
36
+ const ch = value[i];
37
+ if (ch === undefined) continue;
38
+ total += ALPHABET.indexOf(ch) * weight;
34
39
  }
40
+ // SAFETY: (31 - total % 31) % 31 is in 0..30 and
41
+ // ALPHABET has 31 characters.
42
+ // eslint-disable-next-line no-non-null-assertion
35
43
  return ALPHABET[(31 - (total % 31)) % 31]!;
36
44
  };
37
45
 
@@ -45,8 +53,8 @@ const validate = (value: string): ValidateResult => {
45
53
  );
46
54
  }
47
55
 
48
- for (let i = 0; i < 18; i++) {
49
- if (!ALPHABET.includes(v[i]!)) {
56
+ for (const ch of v) {
57
+ if (!ALPHABET.includes(ch)) {
50
58
  return err(
51
59
  "INVALID_FORMAT",
52
60
  "USCC contains invalid character",
@@ -75,12 +83,16 @@ const format = (value: string): string => compact(value);
75
83
 
76
84
  /** Generate a random valid USCC. */
77
85
  const generate = (): string => {
86
+ // SAFETY: indices 1..9 are within ALPHABET (31 chars).
87
+ // eslint-disable-next-line no-non-null-assertion
78
88
  const reg = ALPHABET[randomInt(1, 9)]!;
89
+ // eslint-disable-next-line no-non-null-assertion
79
90
  const etype = ALPHABET[randomInt(1, 9)]!;
80
91
  const region = randomDigits(6);
81
92
  let org = "";
82
- for (let i = 0; i < 9; i++)
83
- org += ALPHABET[randomInt(0, ALPHABET.length - 1)]!;
93
+ for (let i = 0; i < 9; i++) {
94
+ org += randomChar(ALPHABET);
95
+ }
84
96
  const payload = reg + etype + region + org;
85
97
  return payload + calcCheckChar(payload);
86
98
  };
package/src/co/nit.ts CHANGED
@@ -30,9 +30,13 @@ const compact = (value: string): string =>
30
30
  const calcCheckDigit = (body: string): number => {
31
31
  let sum = 0;
32
32
  const len = body.length;
33
- for (let i = 0; i < len; i++) {
34
- sum += Number(body[len - 1 - i]) * WEIGHTS[i]!;
33
+ for (const [i, weight] of WEIGHTS.entries()) {
34
+ if (i >= len) break;
35
+ sum += Number(body[len - 1 - i]) * weight;
35
36
  }
37
+ // SAFETY: sum % 11 is in 0..10 and CHECK_DIGITS has
38
+ // 11 entries.
39
+ // eslint-disable-next-line no-non-null-assertion
36
40
  return CHECK_DIGITS[sum % 11]!;
37
41
  };
38
42
 
package/src/cr/cpf.ts CHANGED
@@ -38,9 +38,10 @@ const compact = (value: string): string => {
38
38
 
39
39
  const parts = number.split("-");
40
40
  if (parts.length === 3) {
41
- const p0 = parts[0]!.padStart(2, "0");
42
- const p1 = parts[1]!.padStart(4, "0");
43
- const p2 = parts[2]!.padStart(4, "0");
41
+ const [raw0, raw1, raw2] = parts;
42
+ const p0 = (raw0 ?? "").padStart(2, "0");
43
+ const p1 = (raw1 ?? "").padStart(4, "0");
44
+ const p2 = (raw2 ?? "").padStart(4, "0");
44
45
  number = p0 + p1 + p2;
45
46
  } else {
46
47
  number = number.replaceAll("-", "");
package/src/cu/ni.ts CHANGED
@@ -17,6 +17,7 @@
17
17
 
18
18
  import { clean } from "#util/clean";
19
19
  import { isValidDate } from "#util/date";
20
+ import { randomDigits, randomInt } from "#util/generate";
20
21
  import { err } from "#util/result";
21
22
 
22
23
  import type {
@@ -58,6 +59,8 @@ const validate = (value: string): ValidateResult => {
58
59
  const yy = Number(v.slice(0, 2));
59
60
  const mm = Number(v.slice(2, 4));
60
61
  const dd = Number(v.slice(4, 6));
62
+ // SAFETY: regex check above guarantees v.length === 11.
63
+ // eslint-disable-next-line no-non-null-assertion
61
64
  const year = centuryOffset(v[6]!) + yy;
62
65
 
63
66
  if (!isValidDate(year, mm, dd)) {
@@ -84,6 +87,8 @@ const parse = (value: string): ParsedPersonId | null => {
84
87
  const yy = Number(v.slice(0, 2));
85
88
  const mm = Number(v.slice(2, 4));
86
89
  const dd = Number(v.slice(4, 6));
90
+ // SAFETY: regex check above guarantees v.length === 11.
91
+ // eslint-disable-next-line no-non-null-assertion
87
92
  const year = centuryOffset(v[6]!) + yy;
88
93
 
89
94
  const genderDigit = Number(v[9]);
@@ -96,12 +101,25 @@ const parse = (value: string): ParsedPersonId | null => {
96
101
  };
97
102
  };
98
103
 
104
+ /** Generate a random valid Cuban NI. */
105
+ const generate = (): string => {
106
+ const year = randomInt(1950, 2024);
107
+ const month = String(randomInt(1, 12)).padStart(2, "0");
108
+ const day = String(randomInt(1, 28)).padStart(2, "0");
109
+ const yy = String(year % 100).padStart(2, "0");
110
+ const century =
111
+ year >= 2000
112
+ ? String(randomInt(6, 8))
113
+ : String(randomInt(0, 5));
114
+ return `${yy}${month}${day}${century}${randomDigits(4)}`;
115
+ };
116
+
99
117
  /**
100
118
  * Cuban identity card number (NI).
101
119
  *
102
120
  * Examples sourced from python-stdnum test suite.
103
121
  */
104
- const ni: Validator = {
122
+ const ni: Validator<ParsedPersonId> = {
105
123
  name: "Cuban Identity Card Number",
106
124
  localName: "Número de Identidad",
107
125
  abbreviation: "NI",
@@ -117,9 +135,11 @@ const ni: Validator = {
117
135
  examples: ["91021027775", "72062506561"] as const,
118
136
  compact,
119
137
  format,
138
+ parse,
120
139
  validate,
140
+ generate,
121
141
  sourceUrl: "https://www.ecured.cu/Carnet_de_Identidad",
122
142
  };
123
143
 
124
144
  export default ni;
125
- export { compact, format, parse, validate };
145
+ export { compact, format, generate, parse, validate };
package/src/cz/rc.ts CHANGED
@@ -6,9 +6,19 @@
6
6
  * and gender. 10-digit numbers (post-1954) must
7
7
  * be divisible by 11.
8
8
  *
9
- * Women have 50 added to the month. Since 2004,
10
- * an extra +20 offset is used when the serial
11
- * range is exhausted.
9
+ * Women have 50 added to the month. For modern
10
+ * 10-digit numbers, an additional +20 offset may
11
+ * be used when the daily serial range is exhausted
12
+ * (+70 for women).
13
+ *
14
+ * Canonical source:
15
+ * - Czech Ministry of the Interior guidance on rodne
16
+ * cislo, with the modern overflow-month rules
17
+ *
18
+ * We use this to keep the 9-digit historical form
19
+ * valid while rejecting modern +20/+70 month offsets
20
+ * on 9-digit numbers. Those overflow offsets are a
21
+ * modern rule for 10-digit values.
12
22
  *
13
23
  * @see https://www.mvcr.cz/mvcren/docDetail.aspx?docid=21975362&doctype=ART
14
24
  * @see Law 133/2000 Sb.
@@ -29,6 +39,24 @@ import type {
29
39
  const compact = (value: string): string =>
30
40
  clean(value, " /");
31
41
 
42
+ const decodeMonth = (
43
+ rawMonth: number,
44
+ year: number,
45
+ length: number,
46
+ ): number | null => {
47
+ const candidates =
48
+ length === 10 && year >= 2004
49
+ ? [0, 50, 20, 70]
50
+ : [0, 50];
51
+ for (const offset of candidates) {
52
+ const month = rawMonth - offset;
53
+ if (month >= 1 && month <= 12) {
54
+ return month;
55
+ }
56
+ }
57
+ return null;
58
+ };
59
+
32
60
  const validate = (value: string): ValidateResult => {
33
61
  const v = compact(value);
34
62
  if (v.length !== 9 && v.length !== 10) {
@@ -48,22 +76,6 @@ const validate = (value: string): ValidateResult => {
48
76
  const mm = Number(v.slice(2, 4));
49
77
  const dd = Number(v.slice(4, 6));
50
78
 
51
- // Strip gender (+50) and overflow (+20) offsets
52
- const month = (mm % 50) % 20 || mm % 50;
53
- if (month < 1 || month > 12) {
54
- return err(
55
- "INVALID_COMPONENT",
56
- "Birth number contains an invalid month",
57
- );
58
- }
59
-
60
- if (dd < 1 || dd > 31) {
61
- return err(
62
- "INVALID_COMPONENT",
63
- "Birth number contains an invalid day",
64
- );
65
- }
66
-
67
79
  // Resolve full year
68
80
  let year = yy + 1900;
69
81
  if (v.length === 9) {
@@ -80,6 +92,21 @@ const validate = (value: string): ValidateResult => {
80
92
  if (year < 1954) year += 100;
81
93
  }
82
94
 
95
+ const month = decodeMonth(mm, year, v.length);
96
+ if (month === null) {
97
+ return err(
98
+ "INVALID_COMPONENT",
99
+ "Birth number contains an invalid month",
100
+ );
101
+ }
102
+
103
+ if (dd < 1 || dd > 31) {
104
+ return err(
105
+ "INVALID_COMPONENT",
106
+ "Birth number contains an invalid day",
107
+ );
108
+ }
109
+
83
110
  // Validate the actual date
84
111
  if (!isValidDate(year, month, dd)) {
85
112
  return err(
@@ -122,13 +149,16 @@ const parse = (value: string): ParsedPersonId | null => {
122
149
  const mm = Number(v.slice(2, 4));
123
150
  const dd = Number(v.slice(4, 6));
124
151
 
125
- const gender = mm > 50 ? "female" : "male";
126
- const month = (mm % 50) % 20 || mm % 50;
127
-
152
+ const gender = mm >= 50 ? "female" : "male";
128
153
  let year = yy + 1900;
129
154
  if (v.length === 10 && year < 1954) year += 100;
130
155
  if (v.length === 9 && year >= 1980) year -= 100;
131
156
 
157
+ const month = decodeMonth(mm, year, v.length);
158
+ if (month === null) {
159
+ return null;
160
+ }
161
+
132
162
  return {
133
163
  birthDate: new Date(year, month - 1, dd),
134
164
  gender,
@@ -166,7 +196,7 @@ const generate = (): string => {
166
196
  };
167
197
 
168
198
  /** Czech/Slovak Birth Number. */
169
- const rc: Validator = {
199
+ const rc: Validator<ParsedPersonId> = {
170
200
  name: "Czech Birth Number",
171
201
  localName: "Rodné číslo",
172
202
  abbreviation: "RČ",
@@ -182,6 +212,7 @@ const rc: Validator = {
182
212
  examples: ["7103192745"] as const,
183
213
  compact,
184
214
  format,
215
+ parse,
185
216
  validate,
186
217
  generate,
187
218
  };
@@ -1,7 +1,14 @@
1
+ const GENERATE_TYPES = [
2
+ "HRA",
3
+ "HRB",
4
+ "GNR",
5
+ "PR",
6
+ "VR",
7
+ ] as const;
8
+
1
9
  /** Generate a random valid Handelsregisternummer. */
2
10
  const generate = (): string => {
3
- const types = ["HRA", "HRB", "GNR", "PR", "VR"];
4
- const type = types[randomInt(0, types.length - 1)]!;
11
+ const type = randomPick(GENERATE_TYPES);
5
12
  const number = randomDigits(5);
6
13
  return `${type} ${number}`;
7
14
  };
@@ -25,7 +32,7 @@ const generate = (): string => {
25
32
  */
26
33
 
27
34
  import { clean } from "#util/clean";
28
- import { randomDigits, randomInt } from "#util/generate";
35
+ import { randomDigits, randomPick } from "#util/generate";
29
36
  import { err } from "#util/result";
30
37
 
31
38
  import type { ValidateResult, Validator } from "../types";
@@ -62,7 +69,11 @@ const validate = (value: string): ValidateResult => {
62
69
  );
63
70
  }
64
71
 
72
+ // SAFETY: both capture groups are required, so a
73
+ // successful match always populates [1] and [2].
74
+ // eslint-disable-next-line no-non-null-assertion
65
75
  const type = match[1]!;
76
+ // eslint-disable-next-line no-non-null-assertion
66
77
  const number = match[2]!;
67
78
 
68
79
  if (!REGISTER_TYPES.has(type)) {
package/src/de/idnr.ts CHANGED
@@ -103,6 +103,9 @@ const generate = (): string => {
103
103
  while (pool.length < 10) pool.push(randomInt(0, 9));
104
104
  for (let i = pool.length - 1; i > 0; i--) {
105
105
  const j = randomInt(0, i);
106
+ // SAFETY: i and j are valid indices of `pool`
107
+ // (i > 0, j ∈ [0, i]).
108
+ // eslint-disable-next-line no-non-null-assertion
106
109
  [pool[i], pool[j]] = [pool[j]!, pool[i]!];
107
110
  }
108
111
  if (pool[0] === 0) continue;
package/src/de/stnr.ts CHANGED
@@ -166,9 +166,13 @@ const format = (value: string): string => {
166
166
  // category: literal digits, F, B, U, P
167
167
  const segments: string[] = [];
168
168
  let segStart = 0;
169
+ // SAFETY: fmt is a non-empty literal from COMPILED.
170
+ // eslint-disable-next-line no-non-null-assertion
169
171
  let prevCat = charCat(fmt[0]!);
170
172
 
171
173
  for (let i = 1; i < fmt.length; i++) {
174
+ // SAFETY: i < fmt.length.
175
+ // eslint-disable-next-line no-non-null-assertion
172
176
  const cat = charCat(fmt[i]!);
173
177
  if (cat !== prevCat) {
174
178
  segments.push(v.slice(segStart, i));
package/src/de/svnr.ts CHANGED
@@ -39,6 +39,8 @@ const computeCheck = (v: string): number => {
39
39
  digits.push(Number(v[i]));
40
40
  }
41
41
 
42
+ // SAFETY: caller guarantees v.length === 12.
43
+ // eslint-disable-next-line no-non-null-assertion
42
44
  const lv = letterValue(v[8]!);
43
45
  digits.push(Math.floor(lv / 10));
44
46
  digits.push(lv % 10);
@@ -47,8 +49,11 @@ const computeCheck = (v: string): number => {
47
49
  digits.push(Number(v[10]));
48
50
 
49
51
  let sum = 0;
50
- for (let i = 0; i < 12; i++) {
51
- const product = digits[i]! * WEIGHTS[i]!;
52
+ for (const [i, weight] of WEIGHTS.entries()) {
53
+ // SAFETY: WEIGHTS.length === 12 and we just pushed
54
+ // 12 entries onto `digits`.
55
+ // eslint-disable-next-line no-non-null-assertion
56
+ const product = digits[i]! * weight;
52
57
  if (product >= 10) {
53
58
  sum += Math.floor(product / 10) + (product % 10);
54
59
  } else {
package/src/dk/cpr.ts CHANGED
@@ -10,6 +10,7 @@
10
10
 
11
11
  import { clean } from "#util/clean";
12
12
  import { isValidDate } from "#util/date";
13
+ import { randomDigits, randomInt } from "#util/generate";
13
14
  import { err } from "#util/result";
14
15
  import { isdigits } from "#util/strings";
15
16
 
@@ -102,8 +103,18 @@ const parse = (value: string): ParsedPersonId | null => {
102
103
  };
103
104
  };
104
105
 
106
+ /** Generate a random valid Danish CPR. */
107
+ const generate = (): string => {
108
+ const year = randomInt(1900, 2024);
109
+ const month = String(randomInt(1, 12)).padStart(2, "0");
110
+ const day = String(randomInt(1, 28)).padStart(2, "0");
111
+ const yy = String(year % 100).padStart(2, "0");
112
+ const serialPrefix = String(randomInt(0, 3));
113
+ return `${day}${month}${yy}${serialPrefix}${randomDigits(3)}`;
114
+ };
115
+
105
116
  /** Danish Personal Identification Number. */
106
- const cpr: Validator = {
117
+ const cpr: Validator<ParsedPersonId> = {
107
118
  name: "Danish Personal ID",
108
119
  localName: "Det Centrale Personregister",
109
120
  abbreviation: "CPR",
@@ -112,11 +123,14 @@ const cpr: Validator = {
112
123
  country: "DK",
113
124
  entityType: "person",
114
125
  sourceUrl: "https://cpr.dk/",
126
+ lengths: [10] as const,
115
127
  examples: ["2110625629"] as const,
116
128
  compact,
117
129
  format,
130
+ parse,
118
131
  validate,
132
+ generate,
119
133
  };
120
134
 
121
135
  export default cpr;
122
- export { compact, format, parse, validate };
136
+ export { compact, format, generate, parse, validate };
package/src/do/rnc.ts CHANGED
@@ -38,8 +38,8 @@ const compact = (value: string): string =>
38
38
  */
39
39
  const calcRncCheckDigit = (value: string): string => {
40
40
  let sum = 0;
41
- for (let i = 0; i < 8; i++) {
42
- sum += Number(value[i]) * RNC_WEIGHTS[i]!;
41
+ for (const [i, weight] of RNC_WEIGHTS.entries()) {
42
+ sum += Number(value[i]) * weight;
43
43
  }
44
44
  const remainder = sum % 11;
45
45
  return String(((10 - remainder) % 9) + 1);
package/src/ec/ruc.ts CHANGED
@@ -46,8 +46,8 @@ const mod11Checksum = (
46
46
  weights: readonly number[],
47
47
  ): number => {
48
48
  let sum = 0;
49
- for (let i = 0; i < weights.length; i++) {
50
- sum += Number(digits[i]) * weights[i]!;
49
+ for (const [i, weight] of weights.entries()) {
50
+ sum += Number(digits[i]) * weight;
51
51
  }
52
52
  return sum % 11;
53
53
  };
package/src/ee/ik.ts CHANGED
@@ -5,7 +5,16 @@
5
5
  * gender/century digit, YYMMDD, 3-digit serial, and
6
6
  * a check digit computed with two-pass weighted sums.
7
7
  *
8
+ * Canonical sources:
9
+ * - Estonian legislation for the personal code format
10
+ * - OECD Estonia TIN sheet summarising the same
11
+ * first-digit ranges for cross-border tax use
12
+ *
13
+ * These sources are why we restrict the first digit
14
+ * to 1-6 rather than accepting speculative 7/8 forms.
15
+ *
8
16
  * @see https://www.riigiteataja.ee/en/eli/512012015003/consolide
17
+ * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Estonia-TIN.pdf
9
18
  */
10
19
 
11
20
  import { weightedSum } from "#checksums/weighted-sum";
@@ -31,8 +40,6 @@ const centuryMap: Record<number, number> = {
31
40
  4: 1900,
32
41
  5: 2000,
33
42
  6: 2000,
34
- 7: 2100,
35
- 8: 2100,
36
43
  };
37
44
 
38
45
  const compact = (value: string): string =>
@@ -65,7 +72,9 @@ const validate = (value: string): ValidateResult => {
65
72
  }
66
73
 
67
74
  const g = Number(v[0]);
68
- if (g < 1 || g > 8) {
75
+ // Official Estonian structure uses 1-6:
76
+ // 1-2 = 1800s, 3-4 = 1900s, 5-6 = 2000s.
77
+ if (g < 1 || g > 6) {
69
78
  return err(
70
79
  "INVALID_COMPONENT",
71
80
  "Isikukood gender/century digit is invalid",
@@ -135,7 +144,7 @@ const generate = (): string => {
135
144
  };
136
145
 
137
146
  /** Estonian Personal Identification Code. */
138
- const ik: Validator = {
147
+ const ik: Validator<ParsedPersonId> = {
139
148
  name: "Estonian Personal ID",
140
149
  localName: "Isikukood",
141
150
  abbreviation: "IK",
@@ -148,6 +157,7 @@ const ik: Validator = {
148
157
  examples: ["36805280109"] as const,
149
158
  compact,
150
159
  format,
160
+ parse,
151
161
  validate,
152
162
  generate,
153
163
  };
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { clean } from "#util/clean";
11
- import { randomDigits, randomInt } from "#util/generate";
11
+ import { randomDigits, randomPick } from "#util/generate";
12
12
  import { err } from "#util/result";
13
13
  import { isdigits } from "#util/strings";
14
14
 
@@ -52,10 +52,11 @@ const validate = (value: string): ValidateResult => {
52
52
 
53
53
  const format = (value: string): string => compact(value);
54
54
 
55
+ const REGISTRIKOOD_FIRSTS = [1, 7, 8, 9] as const;
56
+
55
57
  /** Generate a random valid Estonian Registrikood. */
56
58
  const generate = (): string => {
57
- const firsts = [1, 7, 8, 9];
58
- const first = String(firsts[randomInt(0, 3)]!);
59
+ const first = String(randomPick(REGISTRIKOOD_FIRSTS));
59
60
  const payload = first + randomDigits(6);
60
61
  return payload + String(twoPassCheck(payload));
61
62
  };
package/src/es/cif.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { clean } from "#util/clean";
13
- import { randomDigits, randomInt } from "#util/generate";
13
+ import { randomChar, randomDigits } from "#util/generate";
14
14
  import { err } from "#util/result";
15
15
  import { isdigits } from "#util/strings";
16
16
 
@@ -72,8 +72,7 @@ const format = (value: string): string => compact(value);
72
72
 
73
73
  /** Generate a random valid Spanish CIF. */
74
74
  const generate = (): string => {
75
- const letter =
76
- CIF_PREFIXES[randomInt(0, CIF_PREFIXES.length - 1)]!;
75
+ const letter = randomChar(CIF_PREFIXES);
77
76
  const payload = randomDigits(7);
78
77
  const check = cifChecksum(payload);
79
78
  if ("KPQS".includes(letter))
package/src/es/nie.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import { clean } from "#util/clean";
12
- import { randomDigits, randomInt } from "#util/generate";
12
+ import { randomDigits, randomPick } from "#util/generate";
13
13
  import { err } from "#util/result";
14
14
  import { isdigits } from "#util/strings";
15
15
 
@@ -66,13 +66,18 @@ const validate = (value: string): ValidateResult => {
66
66
 
67
67
  const format = (value: string): string => compact(value);
68
68
 
69
+ const NIE_PREFIXES = ["X", "Y", "Z"] as const;
70
+ const NIE_PREFIX_VALUES: Record<
71
+ (typeof NIE_PREFIXES)[number],
72
+ number
73
+ > = { X: 0, Y: 1, Z: 2 };
74
+
69
75
  /** Generate a random valid Spanish NIE. */
70
76
  const generate = (): string => {
71
- const prefixes = ["X", "Y", "Z"] as const;
72
- const vals: Record<string, number> = { X: 0, Y: 1, Z: 2 };
73
- const prefix = prefixes[randomInt(0, 2)]!;
77
+ const prefix = randomPick(NIE_PREFIXES);
74
78
  const digits = randomDigits(7);
75
- const num = vals[prefix]! * 10000000 + Number(digits);
79
+ const num =
80
+ NIE_PREFIX_VALUES[prefix] * 10000000 + Number(digits);
76
81
  return prefix + digits + CHECK_LETTERS.charAt(num % 23);
77
82
  };
78
83