@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
@@ -1 +1 @@
1
- {"version":3,"file":"ruc.js","names":[],"sources":["../../src/ec/ruc.ts"],"sourcesContent":["/**\n * RUC (Registro Único de Contribuyentes).\n *\n * Ecuadorian tax identification number. 13 digits:\n * - Digits 1-2: province code (01-24, 30, or 50)\n * - Digit 3: type indicator\n * - 0-5: natural person (CI + establishment)\n * - 6: public entity (or natural person fallback)\n * - 9: juridical entity (public checksum first,\n * then juridical fallback)\n *\n * Natural persons use a Luhn-like mod-10 checksum on\n * the first 10 digits. Public entities use a mod-11\n * checksum on the first 9 digits. Private companies\n * use a mod-11 checksum on the first 10 digits.\n *\n * @see https://www.sri.gob.ec/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\n/** CI mod-10 checksum: weights [2,1,2,1,...], fold\n * products > 9 by subtracting 9, sum mod 10 == 0. */\nconst ciChecksum = (digits: string): number => {\n let sum = 0;\n for (let i = 0; i < digits.length; i++) {\n const weight = i % 2 === 0 ? 2 : 1;\n let product = Number(digits[i]) * weight;\n if (product > 9) product -= 9;\n sum += product;\n }\n return sum % 10;\n};\n\n/** Weighted mod-11 checksum. */\nconst mod11Checksum = (\n digits: string,\n weights: readonly number[],\n): number => {\n let sum = 0;\n for (let i = 0; i < weights.length; i++) {\n sum += Number(digits[i]) * weights[i]!;\n }\n return sum % 11;\n};\n\nconst PUBLIC_WEIGHTS = [3, 2, 7, 6, 5, 4, 3, 2, 1];\nconst JURIDICAL_WEIGHTS = [4, 3, 2, 7, 6, 5, 4, 3, 2, 1];\n\nconst isValidProvince = (v: string): boolean => {\n const province = v.slice(0, 2);\n return (\n (province >= \"01\" && province <= \"24\") ||\n province === \"30\" ||\n province === \"50\"\n );\n};\n\nconst validateNatural = (\n v: string,\n): ValidateResult | null => {\n if (v.slice(-3) === \"000\") return null;\n if (ciChecksum(v.slice(0, 10)) !== 0) return null;\n return { valid: true, compact: v };\n};\n\nconst validatePublic = (\n v: string,\n): ValidateResult | null => {\n if (v.slice(-4) === \"0000\") return null;\n if (mod11Checksum(v, PUBLIC_WEIGHTS) !== 0) return null;\n return { valid: true, compact: v };\n};\n\nconst validateJuridical = (\n v: string,\n): ValidateResult | null => {\n if (v.slice(-3) === \"000\") return null;\n if (mod11Checksum(v, JURIDICAL_WEIGHTS) !== 0) {\n return null;\n }\n return { valid: true, compact: v };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"RUC must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"RUC must contain only digits\",\n );\n }\n if (!isValidProvince(v)) {\n return err(\n \"INVALID_COMPONENT\",\n \"RUC province code is invalid\",\n );\n }\n\n const typeDigit = Number(v[2]);\n\n if (typeDigit <= 5) {\n // Natural person\n const result = validateNatural(v);\n if (result) return result;\n return err(\n \"INVALID_CHECKSUM\",\n \"RUC check digit does not match\",\n );\n }\n\n if (typeDigit === 6) {\n // Public entity; fall back to natural person\n const pub = validatePublic(v);\n if (pub) return pub;\n const nat = validateNatural(v);\n if (nat) return nat;\n return err(\n \"INVALID_CHECKSUM\",\n \"RUC check digit does not match\",\n );\n }\n\n if (typeDigit === 9) {\n // Juridical RUC; try public checksum first, fall\n // back to juridical (matches python-stdnum).\n const pub = validatePublic(v);\n if (pub) return pub;\n const jur = validateJuridical(v);\n if (jur) return jur;\n return err(\n \"INVALID_CHECKSUM\",\n \"RUC check digit does not match\",\n );\n }\n\n return err(\n \"INVALID_COMPONENT\",\n \"RUC type digit is invalid\",\n );\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Ecuadorian RUC. */\nconst generate = (): string => {\n for (;;) {\n const province = String(randomInt(1, 24)).padStart(\n 2,\n \"0\",\n );\n const c = province + randomDigits(11);\n if (validate(c).valid) return c;\n }\n};\n\n/** Ecuadorian tax identification number. */\nconst ruc: Validator = {\n name: \"Registro Único de Contribuyentes\",\n localName: \"Registro Único de Contribuyentes\",\n abbreviation: \"RUC\",\n aliases: [\n \"RUC\",\n \"Registro Único de Contribuyentes\",\n ] as const,\n candidatePattern: \"\\\\d{13}\",\n country: \"EC\",\n entityType: \"any\",\n description:\n \"13-digit tax identification number issued by the SRI\",\n sourceUrl: \"https://www.sri.gob.ec/\",\n lengths: [13] as const,\n examples: [\"1792060346001\", \"1790011674001\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default ruc;\nexport { compact, format, validate, generate };\n"],"mappings":"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"}
1
+ {"version":3,"file":"ruc.js","names":[],"sources":["../../src/ec/ruc.ts"],"sourcesContent":["/**\n * RUC (Registro Único de Contribuyentes).\n *\n * Ecuadorian tax identification number. 13 digits:\n * - Digits 1-2: province code (01-24, 30, or 50)\n * - Digit 3: type indicator\n * - 0-5: natural person (CI + establishment)\n * - 6: public entity (or natural person fallback)\n * - 9: juridical entity (public checksum first,\n * then juridical fallback)\n *\n * Natural persons use a Luhn-like mod-10 checksum on\n * the first 10 digits. Public entities use a mod-11\n * checksum on the first 9 digits. Private companies\n * use a mod-11 checksum on the first 10 digits.\n *\n * @see https://www.sri.gob.ec/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\n/** CI mod-10 checksum: weights [2,1,2,1,...], fold\n * products > 9 by subtracting 9, sum mod 10 == 0. */\nconst ciChecksum = (digits: string): number => {\n let sum = 0;\n for (let i = 0; i < digits.length; i++) {\n const weight = i % 2 === 0 ? 2 : 1;\n let product = Number(digits[i]) * weight;\n if (product > 9) product -= 9;\n sum += product;\n }\n return sum % 10;\n};\n\n/** Weighted mod-11 checksum. */\nconst mod11Checksum = (\n digits: string,\n weights: readonly number[],\n): number => {\n let sum = 0;\n for (const [i, weight] of weights.entries()) {\n sum += Number(digits[i]) * weight;\n }\n return sum % 11;\n};\n\nconst PUBLIC_WEIGHTS = [3, 2, 7, 6, 5, 4, 3, 2, 1];\nconst JURIDICAL_WEIGHTS = [4, 3, 2, 7, 6, 5, 4, 3, 2, 1];\n\nconst isValidProvince = (v: string): boolean => {\n const province = v.slice(0, 2);\n return (\n (province >= \"01\" && province <= \"24\") ||\n province === \"30\" ||\n province === \"50\"\n );\n};\n\nconst validateNatural = (\n v: string,\n): ValidateResult | null => {\n if (v.slice(-3) === \"000\") return null;\n if (ciChecksum(v.slice(0, 10)) !== 0) return null;\n return { valid: true, compact: v };\n};\n\nconst validatePublic = (\n v: string,\n): ValidateResult | null => {\n if (v.slice(-4) === \"0000\") return null;\n if (mod11Checksum(v, PUBLIC_WEIGHTS) !== 0) return null;\n return { valid: true, compact: v };\n};\n\nconst validateJuridical = (\n v: string,\n): ValidateResult | null => {\n if (v.slice(-3) === \"000\") return null;\n if (mod11Checksum(v, JURIDICAL_WEIGHTS) !== 0) {\n return null;\n }\n return { valid: true, compact: v };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"RUC must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"RUC must contain only digits\",\n );\n }\n if (!isValidProvince(v)) {\n return err(\n \"INVALID_COMPONENT\",\n \"RUC province code is invalid\",\n );\n }\n\n const typeDigit = Number(v[2]);\n\n if (typeDigit <= 5) {\n // Natural person\n const result = validateNatural(v);\n if (result) return result;\n return err(\n \"INVALID_CHECKSUM\",\n \"RUC check digit does not match\",\n );\n }\n\n if (typeDigit === 6) {\n // Public entity; fall back to natural person\n const pub = validatePublic(v);\n if (pub) return pub;\n const nat = validateNatural(v);\n if (nat) return nat;\n return err(\n \"INVALID_CHECKSUM\",\n \"RUC check digit does not match\",\n );\n }\n\n if (typeDigit === 9) {\n // Juridical RUC; try public checksum first, fall\n // back to juridical (matches python-stdnum).\n const pub = validatePublic(v);\n if (pub) return pub;\n const jur = validateJuridical(v);\n if (jur) return jur;\n return err(\n \"INVALID_CHECKSUM\",\n \"RUC check digit does not match\",\n );\n }\n\n return err(\n \"INVALID_COMPONENT\",\n \"RUC type digit is invalid\",\n );\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Ecuadorian RUC. */\nconst generate = (): string => {\n for (;;) {\n const province = String(randomInt(1, 24)).padStart(\n 2,\n \"0\",\n );\n const c = province + randomDigits(11);\n if (validate(c).valid) return c;\n }\n};\n\n/** Ecuadorian tax identification number. */\nconst ruc: Validator = {\n name: \"Registro Único de Contribuyentes\",\n localName: \"Registro Único de Contribuyentes\",\n abbreviation: \"RUC\",\n aliases: [\n \"RUC\",\n \"Registro Único de Contribuyentes\",\n ] as const,\n candidatePattern: \"\\\\d{13}\",\n country: \"EC\",\n entityType: \"any\",\n description:\n \"13-digit tax identification number issued by the SRI\",\n sourceUrl: \"https://www.sri.gob.ec/\",\n lengths: [13] as const,\n examples: [\"1792060346001\", \"1790011674001\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default ruc;\nexport { compact, format, validate, generate };\n"],"mappings":"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"}
package/dist/ee/ik.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/ee/ik.d.ts
4
-
5
4
  declare const compact: (value: string) => string;
6
5
  /**
7
6
  * Compute the two-pass check digit used by both
@@ -18,7 +17,7 @@ declare const parse: (value: string) => ParsedPersonId | null;
18
17
  /** Generate a random valid Estonian IK. */
19
18
  declare const generate: () => string;
20
19
  /** Estonian Personal Identification Code. */
21
- declare const ik: Validator;
20
+ declare const ik: Validator<ParsedPersonId>;
22
21
  //#endregion
23
22
  export { compact, ik as default, format, generate, parse, twoPassCheck, validate };
24
23
  //# sourceMappingURL=ik.d.ts.map
package/dist/ee/ik.js CHANGED
@@ -12,7 +12,16 @@ import { isValidDate } from "../_util/date.js";
12
12
  * gender/century digit, YYMMDD, 3-digit serial, and
13
13
  * a check digit computed with two-pass weighted sums.
14
14
  *
15
+ * Canonical sources:
16
+ * - Estonian legislation for the personal code format
17
+ * - OECD Estonia TIN sheet summarising the same
18
+ * first-digit ranges for cross-border tax use
19
+ *
20
+ * These sources are why we restrict the first digit
21
+ * to 1-6 rather than accepting speculative 7/8 forms.
22
+ *
15
23
  * @see https://www.riigiteataja.ee/en/eli/512012015003/consolide
24
+ * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Estonia-TIN.pdf
16
25
  */
17
26
  const WEIGHTS_1 = [
18
27
  1,
@@ -44,9 +53,7 @@ const centuryMap = {
44
53
  3: 1900,
45
54
  4: 1900,
46
55
  5: 2e3,
47
- 6: 2e3,
48
- 7: 2100,
49
- 8: 2100
56
+ 6: 2e3
50
57
  };
51
58
  const compact = (value) => clean(value, " -");
52
59
  /**
@@ -64,7 +71,7 @@ const validate = (value) => {
64
71
  if (v.length !== 11) return err("INVALID_LENGTH", "Isikukood must be exactly 11 digits");
65
72
  if (!isdigits(v)) return err("INVALID_FORMAT", "Isikukood must contain only digits");
66
73
  const g = Number(v[0]);
67
- if (g < 1 || g > 8) return err("INVALID_COMPONENT", "Isikukood gender/century digit is invalid");
74
+ if (g < 1 || g > 6) return err("INVALID_COMPONENT", "Isikukood gender/century digit is invalid");
68
75
  const century = centuryMap[g] ?? 1900;
69
76
  const yy = Number(v.slice(1, 3));
70
77
  const mm = Number(v.slice(3, 5));
@@ -122,6 +129,7 @@ const ik = {
122
129
  examples: ["36805280109"],
123
130
  compact,
124
131
  format,
132
+ parse,
125
133
  validate,
126
134
  generate
127
135
  };
package/dist/ee/ik.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ik.js","names":[],"sources":["../../src/ee/ik.ts"],"sourcesContent":["/**\n * Isikukood (IK).\n *\n * Estonian personal identification code. 11 digits:\n * gender/century digit, YYMMDD, 3-digit serial, and\n * a check digit computed with two-pass weighted sums.\n *\n * @see https://www.riigiteataja.ee/en/eli/512012015003/consolide\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_1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1] as const;\nconst WEIGHTS_2 = [3, 4, 5, 6, 7, 8, 9, 1, 2, 3] as const;\n\nconst centuryMap: Record<number, number> = {\n 1: 1800,\n 2: 1800,\n 3: 1900,\n 4: 1900,\n 5: 2000,\n 6: 2000,\n 7: 2100,\n 8: 2100,\n};\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\n/**\n * Compute the two-pass check digit used by both\n * Estonian IK and Lithuanian Asmens kodas.\n */\nexport const twoPassCheck = (digits: string): number => {\n let remainder = weightedSum(digits, WEIGHTS_1, 11);\n if (remainder !== 10) return remainder;\n remainder = weightedSum(digits, WEIGHTS_2, 11);\n return remainder === 10 ? 0 : remainder;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"Isikukood must be exactly 11 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Isikukood must contain only digits\",\n );\n }\n\n const g = Number(v[0]);\n if (g < 1 || g > 8) {\n return err(\n \"INVALID_COMPONENT\",\n \"Isikukood gender/century digit is invalid\",\n );\n }\n\n const century = centuryMap[g] ?? 1900;\n const yy = Number(v.slice(1, 3));\n const mm = Number(v.slice(3, 5));\n const dd = Number(v.slice(5, 7));\n const year = century + yy;\n\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Isikukood contains an invalid date\",\n );\n }\n\n const check = twoPassCheck(v.slice(0, 10));\n if (check !== Number(v[10])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Isikukood 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 Isikukood.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const g = Number(v[0]);\n const century = centuryMap[g] ?? 1900;\n const yy = Number(v.slice(1, 3));\n const mm = Number(v.slice(3, 5));\n const dd = Number(v.slice(5, 7));\n const year = century + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender: g % 2 === 1 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid Estonian IK. */\nconst generate = (): string => {\n for (;;) {\n const g = String(randomInt(3, 6));\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const s = String(randomInt(0, 999)).padStart(3, \"0\");\n const payload = g + yy + mm + dd + s;\n const c = payload + String(twoPassCheck(payload));\n if (validate(c).valid) return c;\n }\n};\n\n/** Estonian Personal Identification Code. */\nconst ik: Validator = {\n name: \"Estonian Personal ID\",\n localName: \"Isikukood\",\n abbreviation: \"IK\",\n aliases: [\"isikukood\", \"IK\"] as const,\n candidatePattern: \"[1-6]\\\\d{10}\",\n country: \"EE\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.riigiteataja.ee/en/eli/512012015003/consolide\",\n examples: [\"36805280109\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default ik;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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"}
1
+ {"version":3,"file":"ik.js","names":[],"sources":["../../src/ee/ik.ts"],"sourcesContent":["/**\n * Isikukood (IK).\n *\n * Estonian personal identification code. 11 digits:\n * gender/century digit, YYMMDD, 3-digit serial, and\n * a check digit computed with two-pass weighted sums.\n *\n * Canonical sources:\n * - Estonian legislation for the personal code format\n * - OECD Estonia TIN sheet summarising the same\n * first-digit ranges for cross-border tax use\n *\n * These sources are why we restrict the first digit\n * to 1-6 rather than accepting speculative 7/8 forms.\n *\n * @see https://www.riigiteataja.ee/en/eli/512012015003/consolide\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Estonia-TIN.pdf\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_1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1] as const;\nconst WEIGHTS_2 = [3, 4, 5, 6, 7, 8, 9, 1, 2, 3] as const;\n\nconst centuryMap: Record<number, number> = {\n 1: 1800,\n 2: 1800,\n 3: 1900,\n 4: 1900,\n 5: 2000,\n 6: 2000,\n};\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\n/**\n * Compute the two-pass check digit used by both\n * Estonian IK and Lithuanian Asmens kodas.\n */\nexport const twoPassCheck = (digits: string): number => {\n let remainder = weightedSum(digits, WEIGHTS_1, 11);\n if (remainder !== 10) return remainder;\n remainder = weightedSum(digits, WEIGHTS_2, 11);\n return remainder === 10 ? 0 : remainder;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"Isikukood must be exactly 11 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Isikukood must contain only digits\",\n );\n }\n\n const g = Number(v[0]);\n // Official Estonian structure uses 1-6:\n // 1-2 = 1800s, 3-4 = 1900s, 5-6 = 2000s.\n if (g < 1 || g > 6) {\n return err(\n \"INVALID_COMPONENT\",\n \"Isikukood gender/century digit is invalid\",\n );\n }\n\n const century = centuryMap[g] ?? 1900;\n const yy = Number(v.slice(1, 3));\n const mm = Number(v.slice(3, 5));\n const dd = Number(v.slice(5, 7));\n const year = century + yy;\n\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Isikukood contains an invalid date\",\n );\n }\n\n const check = twoPassCheck(v.slice(0, 10));\n if (check !== Number(v[10])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Isikukood 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 Isikukood.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const g = Number(v[0]);\n const century = centuryMap[g] ?? 1900;\n const yy = Number(v.slice(1, 3));\n const mm = Number(v.slice(3, 5));\n const dd = Number(v.slice(5, 7));\n const year = century + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender: g % 2 === 1 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid Estonian IK. */\nconst generate = (): string => {\n for (;;) {\n const g = String(randomInt(3, 6));\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const s = String(randomInt(0, 999)).padStart(3, \"0\");\n const payload = g + yy + mm + dd + s;\n const c = payload + String(twoPassCheck(payload));\n if (validate(c).valid) return c;\n }\n};\n\n/** Estonian Personal Identification Code. */\nconst ik: Validator<ParsedPersonId> = {\n name: \"Estonian Personal ID\",\n localName: \"Isikukood\",\n abbreviation: \"IK\",\n aliases: [\"isikukood\", \"IK\"] as const,\n candidatePattern: \"[1-6]\\\\d{10}\",\n country: \"EE\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.riigiteataja.ee/en/eli/512012015003/consolide\",\n examples: [\"36805280109\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default ik;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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"}
package/dist/ee/mod.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import ik from "./ik.js";
3
2
  import registrikood from "./registrikood.js";
4
3
  import vat from "./vat.js";
5
4
 
6
5
  //#region src/ee/mod.d.ts
7
-
6
+ declare namespace mod_d_exports {
7
+ export { ik, registrikood, vat };
8
+ }
8
9
  //#endregion
9
10
  export { ik, mod_d_exports, registrikood, vat };
10
11
  //# sourceMappingURL=mod.d.ts.map
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/ee/registrikood.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;
@@ -1,5 +1,5 @@
1
1
  import { clean } from "../_util/clean.js";
2
- import { randomDigits, randomInt } from "../_util/generate.js";
2
+ import { randomDigits, randomPick } from "../_util/generate.js";
3
3
  import { err } from "../_util/result.js";
4
4
  import { isdigits } from "../_util/strings.js";
5
5
  import { twoPassCheck } from "./ik.js";
@@ -31,14 +31,15 @@ const validate = (value) => {
31
31
  };
32
32
  };
33
33
  const format = (value) => compact(value);
34
+ const REGISTRIKOOD_FIRSTS = [
35
+ 1,
36
+ 7,
37
+ 8,
38
+ 9
39
+ ];
34
40
  /** Generate a random valid Estonian Registrikood. */
35
41
  const generate = () => {
36
- const payload = String([
37
- 1,
38
- 7,
39
- 8,
40
- 9
41
- ][randomInt(0, 3)]) + randomDigits(6);
42
+ const payload = String(randomPick(REGISTRIKOOD_FIRSTS)) + randomDigits(6);
42
43
  return payload + String(twoPassCheck(payload));
43
44
  };
44
45
  /** Estonian Company Registration Code. */
@@ -1 +1 @@
1
- {"version":3,"file":"registrikood.js","names":[],"sources":["../../src/ee/registrikood.ts"],"sourcesContent":["/**\n * Registrikood (Estonian company registration code).\n *\n * 8 digits. First digit must be 1, 7, 8, or 9.\n * Two-pass checksum (same algorithm as EE IK).\n *\n * @see https://www.rik.ee/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\nimport { twoPassCheck } from \"./ik\";\n\nconst VALID_FIRST = new Set([\"1\", \"7\", \"8\", \"9\"]);\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 \"Estonian Registrikood must be 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Estonian Registrikood must contain only digits\",\n );\n }\n if (!VALID_FIRST.has(v.charAt(0))) {\n return err(\n \"INVALID_COMPONENT\",\n \"Estonian Registrikood must start with 1, 7, 8, or 9\",\n );\n }\n const check = twoPassCheck(v.slice(0, 7));\n if (check !== Number(v[7])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Estonian Registrikood check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Estonian Registrikood. */\nconst generate = (): string => {\n const firsts = [1, 7, 8, 9];\n const first = String(firsts[randomInt(0, 3)]!);\n const payload = first + randomDigits(6);\n return payload + String(twoPassCheck(payload));\n};\n\n/** Estonian Company Registration Code. */\nconst registrikood: Validator = {\n name: \"Estonian Company Registration Code\",\n localName: \"Registrikood\",\n abbreviation: \"Registrikood\",\n aliases: [\"registrikood\"] as const,\n candidatePattern: \"\\\\d{8}\",\n country: \"EE\",\n entityType: \"company\",\n sourceUrl: \"https://www.rik.ee/\",\n examples: [\"12345678\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default registrikood;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;AAiBA,MAAM,cAAc,IAAI,IAAI;CAAC;CAAK;CAAK;CAAK;CAAI,CAAC;AAEjD,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,yCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,iDACD;AAEH,KAAI,CAAC,YAAY,IAAI,EAAE,OAAO,EAAE,CAAC,CAC/B,QAAO,IACL,qBACA,sDACD;AAGH,KADc,aAAa,EAAE,MAAM,GAAG,EAAE,CAAC,KAC3B,OAAO,EAAE,GAAG,CACxB,QAAO,IACL,oBACA,6CACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,iBAAyB;CAG7B,MAAM,UADQ,OADC;EAAC;EAAG;EAAG;EAAG;EAAE,CACC,UAAU,GAAG,EAAE,EAAG,GACtB,aAAa,EAAE;AACvC,QAAO,UAAU,OAAO,aAAa,QAAQ,CAAC;;;AAIhD,MAAM,eAA0B;CAC9B,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,eAAe;CACzB,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,WAAW;CACtB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"registrikood.js","names":[],"sources":["../../src/ee/registrikood.ts"],"sourcesContent":["/**\n * Registrikood (Estonian company registration code).\n *\n * 8 digits. First digit must be 1, 7, 8, or 9.\n * Two-pass checksum (same algorithm as EE IK).\n *\n * @see https://www.rik.ee/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomPick } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\nimport { twoPassCheck } from \"./ik\";\n\nconst VALID_FIRST = new Set([\"1\", \"7\", \"8\", \"9\"]);\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 \"Estonian Registrikood must be 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Estonian Registrikood must contain only digits\",\n );\n }\n if (!VALID_FIRST.has(v.charAt(0))) {\n return err(\n \"INVALID_COMPONENT\",\n \"Estonian Registrikood must start with 1, 7, 8, or 9\",\n );\n }\n const check = twoPassCheck(v.slice(0, 7));\n if (check !== Number(v[7])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Estonian Registrikood check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst REGISTRIKOOD_FIRSTS = [1, 7, 8, 9] as const;\n\n/** Generate a random valid Estonian Registrikood. */\nconst generate = (): string => {\n const first = String(randomPick(REGISTRIKOOD_FIRSTS));\n const payload = first + randomDigits(6);\n return payload + String(twoPassCheck(payload));\n};\n\n/** Estonian Company Registration Code. */\nconst registrikood: Validator = {\n name: \"Estonian Company Registration Code\",\n localName: \"Registrikood\",\n abbreviation: \"Registrikood\",\n aliases: [\"registrikood\"] as const,\n candidatePattern: \"\\\\d{8}\",\n country: \"EE\",\n entityType: \"company\",\n sourceUrl: \"https://www.rik.ee/\",\n examples: [\"12345678\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default registrikood;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;AAiBA,MAAM,cAAc,IAAI,IAAI;CAAC;CAAK;CAAK;CAAK;CAAI,CAAC;AAEjD,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,yCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,iDACD;AAEH,KAAI,CAAC,YAAY,IAAI,EAAE,OAAO,EAAE,CAAC,CAC/B,QAAO,IACL,qBACA,sDACD;AAGH,KADc,aAAa,EAAE,MAAM,GAAG,EAAE,CAAC,KAC3B,OAAO,EAAE,GAAG,CACxB,QAAO,IACL,oBACA,6CACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;AAExD,MAAM,sBAAsB;CAAC;CAAG;CAAG;CAAG;CAAE;;AAGxC,MAAM,iBAAyB;CAE7B,MAAM,UADQ,OAAO,WAAW,oBAAoB,CAAC,GAC7B,aAAa,EAAE;AACvC,QAAO,UAAU,OAAO,aAAa,QAAQ,CAAC;;;AAIhD,MAAM,eAA0B;CAC9B,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,eAAe;CACzB,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,WAAW;CACtB;CACA;CACA;CACA;CACD"}
package/dist/ee/vat.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/ee/vat.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;
package/dist/eg/mod.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import tn from "./tn.js";
3
2
 
4
3
  //#region src/eg/mod.d.ts
5
-
4
+ declare namespace mod_d_exports {
5
+ export { tn };
6
+ }
6
7
  //#endregion
7
8
  export { mod_d_exports, tn };
8
9
  //# sourceMappingURL=mod.d.ts.map
package/dist/es/cif.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/es/cif.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;
package/dist/es/cif.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { clean } from "../_util/clean.js";
2
- import { randomDigits, randomInt } from "../_util/generate.js";
2
+ import { randomChar, randomDigits } from "../_util/generate.js";
3
3
  import { err } from "../_util/result.js";
4
4
  import { isdigits } from "../_util/strings.js";
5
5
  import { cifChecksum } from "./vat.js";
@@ -38,7 +38,7 @@ const validate = (value) => {
38
38
  const format = (value) => compact(value);
39
39
  /** Generate a random valid Spanish CIF. */
40
40
  const generate = () => {
41
- const letter = CIF_PREFIXES[randomInt(0, 16)];
41
+ const letter = randomChar(CIF_PREFIXES);
42
42
  const payload = randomDigits(7);
43
43
  const check = cifChecksum(payload);
44
44
  if ("KPQS".includes(letter)) return letter + payload + CIF_LETTERS.charAt(check);
@@ -1 +1 @@
1
- {"version":3,"file":"cif.js","names":[],"sources":["../../src/es/cif.ts"],"sourcesContent":["/**\n * CIF (Código de Identificación Fiscal).\n *\n * Spanish company tax identification number.\n * Letter prefix (ABCDEFGHJNPQRSUVW) + 7 digits +\n * check digit or letter. Delegates to the CIF\n * branch of es/vat validation.\n *\n * @see https://www.agenciatributaria.es/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\nimport { cifChecksum } from \"./vat\";\n\nconst CIF_PREFIXES = \"ABCDEFGHJNPQRSUVW\";\nconst CIF_LETTERS = \"JABCDEFGHI\";\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"ES\") || v.startsWith(\"es\")) {\n v = v.slice(2);\n }\n return v.toUpperCase();\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"Spanish CIF must be 9 characters\",\n );\n }\n\n const first = v.charAt(0);\n if (!CIF_PREFIXES.includes(first)) {\n return err(\n \"INVALID_FORMAT\",\n \"Spanish CIF must start with a valid prefix letter\",\n );\n }\n\n if (!isdigits(v.slice(1, 8))) {\n return err(\n \"INVALID_FORMAT\",\n \"Spanish CIF must have 7 digits after prefix\",\n );\n }\n\n const last = v.charAt(8);\n const check = cifChecksum(v.slice(1, 8));\n\n if (\n last !== String(check) &&\n last !== CIF_LETTERS.charAt(check)\n ) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Spanish CIF check digit/letter mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Spanish CIF. */\nconst generate = (): string => {\n const letter =\n CIF_PREFIXES[randomInt(0, CIF_PREFIXES.length - 1)]!;\n const payload = randomDigits(7);\n const check = cifChecksum(payload);\n if (\"KPQS\".includes(letter))\n return letter + payload + CIF_LETTERS.charAt(check);\n return letter + payload + String(check);\n};\n\n/** Spanish Company Tax ID (CIF). */\nconst cif: Validator = {\n name: \"Spanish Company Tax ID\",\n localName: \"Código de Identificación Fiscal\",\n abbreviation: \"CIF\",\n aliases: [\n \"CIF\",\n \"código de identificación fiscal\",\n ] as const,\n candidatePattern: \"[A-HJNP-SUVW]\\\\d{7}[\\\\dA-J]\",\n country: \"ES\",\n entityType: \"company\",\n sourceUrl: \"https://www.agenciatributaria.es/\",\n examples: [\"A13585625\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cif;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,MAAM,eAAe;AACrB,MAAM,cAAc;AAEpB,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,OAAO;AAC5B,KAAI,EAAE,WAAW,KAAK,IAAI,EAAE,WAAW,KAAK,CAC1C,KAAI,EAAE,MAAM,EAAE;AAEhB,QAAO,EAAE,aAAa;;AAGxB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,mCACD;CAGH,MAAM,QAAQ,EAAE,OAAO,EAAE;AACzB,KAAI,CAAC,aAAa,SAAS,MAAM,CAC/B,QAAO,IACL,kBACA,oDACD;AAGH,KAAI,CAAC,SAAS,EAAE,MAAM,GAAG,EAAE,CAAC,CAC1B,QAAO,IACL,kBACA,8CACD;CAGH,MAAM,OAAO,EAAE,OAAO,EAAE;CACxB,MAAM,QAAQ,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAExC,KACE,SAAS,OAAO,MAAM,IACtB,SAAS,YAAY,OAAO,MAAM,CAElC,QAAO,IACL,oBACA,0CACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,iBAAyB;CAC7B,MAAM,SACJ,aAAa,UAAU,GAAG,GAAwB;CACpD,MAAM,UAAU,aAAa,EAAE;CAC/B,MAAM,QAAQ,YAAY,QAAQ;AAClC,KAAI,OAAO,SAAS,OAAO,CACzB,QAAO,SAAS,UAAU,YAAY,OAAO,MAAM;AACrD,QAAO,SAAS,UAAU,OAAO,MAAM;;;AAIzC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,kCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"cif.js","names":[],"sources":["../../src/es/cif.ts"],"sourcesContent":["/**\n * CIF (Código de Identificación Fiscal).\n *\n * Spanish company tax identification number.\n * Letter prefix (ABCDEFGHJNPQRSUVW) + 7 digits +\n * check digit or letter. Delegates to the CIF\n * branch of es/vat validation.\n *\n * @see https://www.agenciatributaria.es/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomChar, randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\nimport { cifChecksum } from \"./vat\";\n\nconst CIF_PREFIXES = \"ABCDEFGHJNPQRSUVW\";\nconst CIF_LETTERS = \"JABCDEFGHI\";\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"ES\") || v.startsWith(\"es\")) {\n v = v.slice(2);\n }\n return v.toUpperCase();\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"Spanish CIF must be 9 characters\",\n );\n }\n\n const first = v.charAt(0);\n if (!CIF_PREFIXES.includes(first)) {\n return err(\n \"INVALID_FORMAT\",\n \"Spanish CIF must start with a valid prefix letter\",\n );\n }\n\n if (!isdigits(v.slice(1, 8))) {\n return err(\n \"INVALID_FORMAT\",\n \"Spanish CIF must have 7 digits after prefix\",\n );\n }\n\n const last = v.charAt(8);\n const check = cifChecksum(v.slice(1, 8));\n\n if (\n last !== String(check) &&\n last !== CIF_LETTERS.charAt(check)\n ) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Spanish CIF check digit/letter mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Spanish CIF. */\nconst generate = (): string => {\n const letter = randomChar(CIF_PREFIXES);\n const payload = randomDigits(7);\n const check = cifChecksum(payload);\n if (\"KPQS\".includes(letter))\n return letter + payload + CIF_LETTERS.charAt(check);\n return letter + payload + String(check);\n};\n\n/** Spanish Company Tax ID (CIF). */\nconst cif: Validator = {\n name: \"Spanish Company Tax ID\",\n localName: \"Código de Identificación Fiscal\",\n abbreviation: \"CIF\",\n aliases: [\n \"CIF\",\n \"código de identificación fiscal\",\n ] as const,\n candidatePattern: \"[A-HJNP-SUVW]\\\\d{7}[\\\\dA-J]\",\n country: \"ES\",\n entityType: \"company\",\n sourceUrl: \"https://www.agenciatributaria.es/\",\n examples: [\"A13585625\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cif;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,MAAM,eAAe;AACrB,MAAM,cAAc;AAEpB,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,OAAO;AAC5B,KAAI,EAAE,WAAW,KAAK,IAAI,EAAE,WAAW,KAAK,CAC1C,KAAI,EAAE,MAAM,EAAE;AAEhB,QAAO,EAAE,aAAa;;AAGxB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,mCACD;CAGH,MAAM,QAAQ,EAAE,OAAO,EAAE;AACzB,KAAI,CAAC,aAAa,SAAS,MAAM,CAC/B,QAAO,IACL,kBACA,oDACD;AAGH,KAAI,CAAC,SAAS,EAAE,MAAM,GAAG,EAAE,CAAC,CAC1B,QAAO,IACL,kBACA,8CACD;CAGH,MAAM,OAAO,EAAE,OAAO,EAAE;CACxB,MAAM,QAAQ,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAExC,KACE,SAAS,OAAO,MAAM,IACtB,SAAS,YAAY,OAAO,MAAM,CAElC,QAAO,IACL,oBACA,0CACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,iBAAyB;CAC7B,MAAM,SAAS,WAAW,aAAa;CACvC,MAAM,UAAU,aAAa,EAAE;CAC/B,MAAM,QAAQ,YAAY,QAAQ;AAClC,KAAI,OAAO,SAAS,OAAO,CACzB,QAAO,SAAS,UAAU,YAAY,OAAO,MAAM;AACrD,QAAO,SAAS,UAAU,OAAO,MAAM;;;AAIzC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,kCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACD"}
package/dist/es/dni.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/es/dni.d.ts
4
-
5
4
  declare const CHECK_LETTERS = "TRWAGMYFPDXBNJZSQVHLCKE";
6
5
  declare const compact: (value: string) => string;
7
6
  declare const validate: (value: string) => ValidateResult;
package/dist/es/mod.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import cif from "./cif.js";
3
2
  import dni from "./dni.js";
4
3
  import nie from "./nie.js";
@@ -6,7 +5,9 @@ import nss from "./nss.js";
6
5
  import vat from "./vat.js";
7
6
 
8
7
  //#region src/es/mod.d.ts
9
-
8
+ declare namespace mod_d_exports {
9
+ export { cif, dni, nie, nss, vat };
10
+ }
10
11
  //#endregion
11
12
  export { cif, dni, mod_d_exports, nie, nss, vat };
12
13
  //# sourceMappingURL=mod.d.ts.map
package/dist/es/nie.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/es/nie.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;
package/dist/es/nie.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { clean } from "../_util/clean.js";
2
- import { randomDigits, randomInt } from "../_util/generate.js";
2
+ import { randomDigits, randomPick } from "../_util/generate.js";
3
3
  import { err } from "../_util/result.js";
4
4
  import { isdigits } from "../_util/strings.js";
5
5
  import { CHECK_LETTERS } from "./dni.js";
@@ -35,21 +35,21 @@ const validate = (value) => {
35
35
  };
36
36
  };
37
37
  const format = (value) => compact(value);
38
+ const NIE_PREFIXES = [
39
+ "X",
40
+ "Y",
41
+ "Z"
42
+ ];
43
+ const NIE_PREFIX_VALUES = {
44
+ X: 0,
45
+ Y: 1,
46
+ Z: 2
47
+ };
38
48
  /** Generate a random valid Spanish NIE. */
39
49
  const generate = () => {
40
- const prefixes = [
41
- "X",
42
- "Y",
43
- "Z"
44
- ];
45
- const vals = {
46
- X: 0,
47
- Y: 1,
48
- Z: 2
49
- };
50
- const prefix = prefixes[randomInt(0, 2)];
50
+ const prefix = randomPick(NIE_PREFIXES);
51
51
  const digits = randomDigits(7);
52
- const num = vals[prefix] * 1e7 + Number(digits);
52
+ const num = NIE_PREFIX_VALUES[prefix] * 1e7 + Number(digits);
53
53
  return prefix + digits + CHECK_LETTERS.charAt(num % 23);
54
54
  };
55
55
  /** Spanish Foreigner Identification Number. */
@@ -1 +1 @@
1
- {"version":3,"file":"nie.js","names":[],"sources":["../../src/es/nie.ts"],"sourcesContent":["/**\n * NIE (Número de Identidad de Extranjero).\n *\n * Spanish foreigner identification number. Starts\n * with X, Y, or Z, followed by 7 digits and a check\n * letter computed using the DNI algorithm.\n *\n * @see https://www.interior.gob.es/opencms/es/servicios-al-ciudadano/tramites-y-gestiones/nie/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\nimport { CHECK_LETTERS } from \"./dni\";\n\nconst PREFIX_MAP: Record<string, string> = {\n X: \"0\",\n Y: \"1\",\n Z: \"2\",\n};\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"NIE must be 9 characters\",\n );\n }\n\n const prefix = v.charAt(0);\n const replacement = PREFIX_MAP[prefix];\n if (replacement === undefined) {\n return err(\n \"INVALID_FORMAT\",\n \"NIE must start with X, Y, or Z\",\n );\n }\n\n const digits = v.slice(1, 8);\n if (!isdigits(digits)) {\n return err(\n \"INVALID_FORMAT\",\n \"NIE must have 7 digits after prefix\",\n );\n }\n\n const letter = v.charAt(8);\n const num = Number(replacement + digits);\n const expected = CHECK_LETTERS.charAt(num % 23);\n if (letter !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"NIE check letter does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Spanish NIE. */\nconst generate = (): string => {\n const prefixes = [\"X\", \"Y\", \"Z\"] as const;\n const vals: Record<string, number> = { X: 0, Y: 1, Z: 2 };\n const prefix = prefixes[randomInt(0, 2)]!;\n const digits = randomDigits(7);\n const num = vals[prefix]! * 10000000 + Number(digits);\n return prefix + digits + CHECK_LETTERS.charAt(num % 23);\n};\n\n/** Spanish Foreigner Identification Number. */\nconst nie: Validator = {\n name: \"Spanish Foreigner ID\",\n localName: \"Número de Identidad de Extranjero\",\n abbreviation: \"NIE\",\n aliases: [\n \"N.I.E.\",\n \"NIE\",\n \"número de identidad de extranjero\",\n ] as const,\n candidatePattern: \"[XYZ]-?\\\\d{7}-?[A-Z]\",\n country: \"ES\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.interior.gob.es/opencms/es/servicios-al-ciudadano/tramites-y-gestiones/nie/\",\n examples: [\"X5253868R\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nie;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,MAAM,aAAqC;CACzC,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAED,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,CAAC,aAAa;AAElC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,2BACD;CAIH,MAAM,cAAc,WADL,EAAE,OAAO,EAAE;AAE1B,KAAI,gBAAgB,KAAA,EAClB,QAAO,IACL,kBACA,iCACD;CAGH,MAAM,SAAS,EAAE,MAAM,GAAG,EAAE;AAC5B,KAAI,CAAC,SAAS,OAAO,CACnB,QAAO,IACL,kBACA,sCACD;CAGH,MAAM,SAAS,EAAE,OAAO,EAAE;CAC1B,MAAM,MAAM,OAAO,cAAc,OAAO;AAExC,KAAI,WAAA,0BAD2B,OAAO,MAAM,GAAG,CAE7C,QAAO,IACL,oBACA,kCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,iBAAyB;CAC7B,MAAM,WAAW;EAAC;EAAK;EAAK;EAAI;CAChC,MAAM,OAA+B;EAAE,GAAG;EAAG,GAAG;EAAG,GAAG;EAAG;CACzD,MAAM,SAAS,SAAS,UAAU,GAAG,EAAE;CACvC,MAAM,SAAS,aAAa,EAAE;CAC9B,MAAM,MAAM,KAAK,UAAW,MAAW,OAAO,OAAO;AACrD,QAAO,SAAS,SAAS,cAAc,OAAO,MAAM,GAAG;;;AAIzD,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"nie.js","names":[],"sources":["../../src/es/nie.ts"],"sourcesContent":["/**\n * NIE (Número de Identidad de Extranjero).\n *\n * Spanish foreigner identification number. Starts\n * with X, Y, or Z, followed by 7 digits and a check\n * letter computed using the DNI algorithm.\n *\n * @see https://www.interior.gob.es/opencms/es/servicios-al-ciudadano/tramites-y-gestiones/nie/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomPick } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\nimport { CHECK_LETTERS } from \"./dni\";\n\nconst PREFIX_MAP: Record<string, string> = {\n X: \"0\",\n Y: \"1\",\n Z: \"2\",\n};\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"NIE must be 9 characters\",\n );\n }\n\n const prefix = v.charAt(0);\n const replacement = PREFIX_MAP[prefix];\n if (replacement === undefined) {\n return err(\n \"INVALID_FORMAT\",\n \"NIE must start with X, Y, or Z\",\n );\n }\n\n const digits = v.slice(1, 8);\n if (!isdigits(digits)) {\n return err(\n \"INVALID_FORMAT\",\n \"NIE must have 7 digits after prefix\",\n );\n }\n\n const letter = v.charAt(8);\n const num = Number(replacement + digits);\n const expected = CHECK_LETTERS.charAt(num % 23);\n if (letter !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"NIE check letter does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst NIE_PREFIXES = [\"X\", \"Y\", \"Z\"] as const;\nconst NIE_PREFIX_VALUES: Record<\n (typeof NIE_PREFIXES)[number],\n number\n> = { X: 0, Y: 1, Z: 2 };\n\n/** Generate a random valid Spanish NIE. */\nconst generate = (): string => {\n const prefix = randomPick(NIE_PREFIXES);\n const digits = randomDigits(7);\n const num =\n NIE_PREFIX_VALUES[prefix] * 10000000 + Number(digits);\n return prefix + digits + CHECK_LETTERS.charAt(num % 23);\n};\n\n/** Spanish Foreigner Identification Number. */\nconst nie: Validator = {\n name: \"Spanish Foreigner ID\",\n localName: \"Número de Identidad de Extranjero\",\n abbreviation: \"NIE\",\n aliases: [\n \"N.I.E.\",\n \"NIE\",\n \"número de identidad de extranjero\",\n ] as const,\n candidatePattern: \"[XYZ]-?\\\\d{7}-?[A-Z]\",\n country: \"ES\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.interior.gob.es/opencms/es/servicios-al-ciudadano/tramites-y-gestiones/nie/\",\n examples: [\"X5253868R\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nie;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,MAAM,aAAqC;CACzC,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAED,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,CAAC,aAAa;AAElC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,2BACD;CAIH,MAAM,cAAc,WADL,EAAE,OAAO,EAAE;AAE1B,KAAI,gBAAgB,KAAA,EAClB,QAAO,IACL,kBACA,iCACD;CAGH,MAAM,SAAS,EAAE,MAAM,GAAG,EAAE;AAC5B,KAAI,CAAC,SAAS,OAAO,CACnB,QAAO,IACL,kBACA,sCACD;CAGH,MAAM,SAAS,EAAE,OAAO,EAAE;CAC1B,MAAM,MAAM,OAAO,cAAc,OAAO;AAExC,KAAI,WAAA,0BAD2B,OAAO,MAAM,GAAG,CAE7C,QAAO,IACL,oBACA,kCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;AAExD,MAAM,eAAe;CAAC;CAAK;CAAK;CAAI;AACpC,MAAM,oBAGF;CAAE,GAAG;CAAG,GAAG;CAAG,GAAG;CAAG;;AAGxB,MAAM,iBAAyB;CAC7B,MAAM,SAAS,WAAW,aAAa;CACvC,MAAM,SAAS,aAAa,EAAE;CAC9B,MAAM,MACJ,kBAAkB,UAAU,MAAW,OAAO,OAAO;AACvD,QAAO,SAAS,SAAS,cAAc,OAAO,MAAM,GAAG;;;AAIzD,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACD"}
package/dist/es/nss.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/es/nss.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;
package/dist/es/vat.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/es/vat.d.ts
4
-
5
4
  declare const compact: (value: string) => string;
6
5
  declare const cifChecksum: (digits: string) => number;
7
6
  declare const validate: (value: string) => ValidateResult;
package/dist/eu/mod.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import euVat from "./vat.js";
3
2
 
4
3
  //#region src/eu/mod.d.ts
5
-
4
+ declare namespace mod_d_exports {
5
+ export { euVat as vat };
6
+ }
6
7
  //#endregion
7
8
  export { mod_d_exports, euVat as vat };
8
9
  //# sourceMappingURL=mod.d.ts.map
package/dist/eu/vat.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/eu/vat.d.ts
4
-
5
4
  declare const compact: (value: string) => string;
6
5
  declare const validate: (value: string) => ValidateResult;
7
6
  /**
@@ -13,8 +12,10 @@ declare const validate: (value: string) => ValidateResult;
13
12
  * prefixing if used here.
14
13
  */
15
14
  declare const format: (value: string) => string;
15
+ /** Generate a random EU VAT number from a member validator. */
16
+ declare const generate: () => string;
16
17
  /** European Union VAT Number. */
17
18
  declare const euVat: Validator;
18
19
  //#endregion
19
- export { compact, euVat as default, format, validate };
20
+ export { compact, euVat as default, format, generate, validate };
20
21
  //# sourceMappingURL=vat.d.ts.map
package/dist/eu/vat.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { clean } from "../_util/clean.js";
2
+ import { randomInt } from "../_util/generate.js";
2
3
  import { err } from "../_util/result.js";
3
4
  import uid from "../at/uid.js";
4
5
  import vat from "../be/vat.js";
@@ -125,6 +126,45 @@ const format = (value) => {
125
126
  if (validator === void 0) return value;
126
127
  return `${parts.cc}${validator.compact(parts.rest)}`;
127
128
  };
129
+ const GENERATORS = [
130
+ ["AT", uid],
131
+ ["BE", vat],
132
+ ["BG", vat$1],
133
+ ["CY", vat$2],
134
+ ["CZ", dic],
135
+ ["DE", vat$3],
136
+ ["DK", vat$4],
137
+ ["EE", vat$5],
138
+ ["ES", vat$6],
139
+ ["FI", vat$7],
140
+ ["FR", tva],
141
+ ["GR", vat$9],
142
+ ["HR", vat$10],
143
+ ["HU", vat$11],
144
+ ["IE", vat$12],
145
+ ["IT", iva],
146
+ ["LT", vat$13],
147
+ ["LU", vat$14],
148
+ ["LV", vat$15],
149
+ ["MT", vat$16],
150
+ ["NL", vat$17],
151
+ ["PL", nip],
152
+ ["PT", vat$18],
153
+ ["RO", vat$19],
154
+ ["SE", vat$20],
155
+ ["SI", vat$21],
156
+ ["SK", dic$1]
157
+ ];
158
+ /** Generate a random EU VAT number from a member validator. */
159
+ const generate = () => {
160
+ for (;;) {
161
+ const candidate = GENERATORS[randomInt(0, GENERATORS.length - 1)];
162
+ if (!candidate) continue;
163
+ const [prefix, validator] = candidate;
164
+ if (validator.generate === void 0) continue;
165
+ return `${prefix}${validator.generate()}`;
166
+ }
167
+ };
128
168
  /** European Union VAT Number. */
129
169
  const euVat = {
130
170
  name: "EU VAT Number",
@@ -137,9 +177,10 @@ const euVat = {
137
177
  examples: ["ATU13585627", "DE136695976"],
138
178
  compact,
139
179
  format,
140
- validate
180
+ validate,
181
+ generate
141
182
  };
142
183
  //#endregion
143
- export { compact, euVat as default, format, validate };
184
+ export { compact, euVat as default, format, generate, validate };
144
185
 
145
186
  //# sourceMappingURL=vat.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"vat.js","names":["atUid","beVat","bgVat","cyVat","czDic","deVat","dkVat","eeVat","grVat","esVat","fiVat","frTva","hrVat","huVat","ieVat","itIva","ltVat","luVat","lvVat","mtVat","nlVat","plNip","ptVat","roVat","seVat","siVat","skDic","gbVat"],"sources":["../../src/eu/vat.ts"],"sourcesContent":["/**\n * EU VAT (European Union VAT Number).\n *\n * Dispatcher that routes to per-country VAT\n * validators. Extracts the 2-letter country prefix\n * and delegates to the matching country module.\n *\n * Special cases:\n * - EL → Greece (gr.vat)\n * - XI → Northern Ireland (gb.vat)\n *\n * @see https://ec.europa.eu/taxation_customs/vies/\n */\n\nimport { clean } from \"#util/clean\";\nimport { err } from \"#util/result\";\n\nimport atUid from \"../at/uid\";\nimport beVat from \"../be/vat\";\nimport bgVat from \"../bg/vat\";\nimport cyVat from \"../cy/vat\";\nimport czDic from \"../cz/dic\";\nimport deVat from \"../de/vat\";\nimport dkVat from \"../dk/vat\";\nimport eeVat from \"../ee/vat\";\nimport esVat from \"../es/vat\";\nimport fiVat from \"../fi/vat\";\nimport frTva from \"../fr/tva\";\nimport gbVat from \"../gb/vat\";\nimport grVat from \"../gr/vat\";\nimport hrVat from \"../hr/vat\";\nimport huVat from \"../hu/vat\";\nimport ieVat from \"../ie/vat\";\nimport itIva from \"../it/iva\";\nimport ltVat from \"../lt/vat\";\nimport luVat from \"../lu/vat\";\nimport lvVat from \"../lv/vat\";\nimport mtVat from \"../mt/vat\";\nimport nlVat from \"../nl/vat\";\nimport plNip from \"../pl/nip\";\nimport ptVat from \"../pt/vat\";\nimport roVat from \"../ro/vat\";\nimport seVat from \"../se/vat\";\nimport siVat from \"../si/vat\";\nimport skDic from \"../sk/dic\";\nimport type { Validator, ValidateResult } from \"../types\";\n\ntype CountryValidator = {\n compact: (value: string) => string;\n validate: (value: string) => ValidateResult;\n format: (value: string) => string;\n};\n\n/**\n * Map of EU VAT country prefixes to their\n * country-specific validators.\n */\nconst VALIDATORS: Record<string, CountryValidator> = {\n AT: atUid,\n BE: beVat,\n BG: bgVat,\n CY: cyVat,\n CZ: czDic,\n DE: deVat,\n DK: dkVat,\n EE: eeVat,\n EL: grVat, // Greece uses EL prefix in EU VAT\n ES: esVat,\n FI: fiVat,\n FR: frTva,\n GR: grVat,\n HR: hrVat,\n HU: huVat,\n IE: ieVat,\n IT: itIva,\n LT: ltVat,\n LU: luVat,\n LV: lvVat,\n MT: mtVat,\n NL: nlVat,\n PL: plNip,\n PT: ptVat,\n RO: roVat,\n SE: seVat,\n SI: siVat,\n SK: skDic,\n XI: gbVat, // Northern Ireland\n};\n\n/**\n * Extract the 2-letter country prefix and the\n * remaining number from an EU VAT string.\n */\nconst splitPrefix = (\n value: string,\n): { cc: string; rest: string } | undefined => {\n const v = clean(value, \" -\").toUpperCase();\n if (v.length < 3) return undefined;\n const cc = v.slice(0, 2);\n if (!/^[A-Z]{2}$/.test(cc)) return undefined;\n return { cc, rest: v.slice(2) };\n};\n\nconst compact = (value: string): string => {\n const parts = splitPrefix(value);\n if (parts === undefined) {\n return clean(value, \" -\").toUpperCase();\n }\n const validator = VALIDATORS[parts.cc];\n if (validator === undefined) {\n return clean(value, \" -\").toUpperCase();\n }\n return `${parts.cc}${validator.compact(parts.rest)}`;\n};\n\nconst validate = (value: string): ValidateResult => {\n const parts = splitPrefix(value);\n if (parts === undefined) {\n return err(\n \"INVALID_FORMAT\",\n \"EU VAT must start with a 2-letter country code\",\n );\n }\n const validator = VALIDATORS[parts.cc];\n if (validator === undefined) {\n return err(\n \"INVALID_COMPONENT\",\n `Unsupported EU VAT country: ${parts.cc}`,\n );\n }\n const result = validator.validate(parts.rest);\n if (!result.valid) return result;\n return {\n valid: true,\n compact: `${parts.cc}${result.compact}`,\n };\n};\n\n/**\n * Format returns the compact EU VAT form:\n * `CC` + country-compacted number. Equivalent to\n * compact() because country format() methods\n * prepend their own prefix (e.g., AT UID format\n * returns \"ATU...\"), which would cause double-\n * prefixing if used here.\n */\nconst format = (value: string): string => {\n const parts = splitPrefix(value);\n if (parts === undefined) return value;\n const validator = VALIDATORS[parts.cc];\n if (validator === undefined) return value;\n return `${parts.cc}${validator.compact(parts.rest)}`;\n};\n\n/** European Union VAT Number. */\nconst euVat: Validator = {\n name: \"EU VAT Number\",\n localName: \"EU VAT Number\",\n abbreviation: \"EU VAT\",\n aliases: [\"EU VAT\", \"VAT identification number\"] as const,\n candidatePattern: \"[A-Z]{2}\\\\d{8,12}\",\n entityType: \"company\",\n sourceUrl: \"https://ec.europa.eu/taxation_customs/vies/\",\n examples: [\"ATU13585627\", \"DE136695976\"] as const,\n compact,\n format,\n validate,\n};\n\nexport default euVat;\nexport { compact, format, validate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,MAAM,aAA+C;CACnD,IAAIA;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIH;CACJ,IAAII;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACL;;;;;AAMD,MAAM,eACJ,UAC6C;CAC7C,MAAM,IAAI,MAAM,OAAO,KAAK,CAAC,aAAa;AAC1C,KAAI,EAAE,SAAS,EAAG,QAAO,KAAA;CACzB,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE;AACxB,KAAI,CAAC,aAAa,KAAK,GAAG,CAAE,QAAO,KAAA;AACnC,QAAO;EAAE;EAAI,MAAM,EAAE,MAAM,EAAE;EAAE;;AAGjC,MAAM,WAAW,UAA0B;CACzC,MAAM,QAAQ,YAAY,MAAM;AAChC,KAAI,UAAU,KAAA,EACZ,QAAO,MAAM,OAAO,KAAK,CAAC,aAAa;CAEzC,MAAM,YAAY,WAAW,MAAM;AACnC,KAAI,cAAc,KAAA,EAChB,QAAO,MAAM,OAAO,KAAK,CAAC,aAAa;AAEzC,QAAO,GAAG,MAAM,KAAK,UAAU,QAAQ,MAAM,KAAK;;AAGpD,MAAM,YAAY,UAAkC;CAClD,MAAM,QAAQ,YAAY,MAAM;AAChC,KAAI,UAAU,KAAA,EACZ,QAAO,IACL,kBACA,iDACD;CAEH,MAAM,YAAY,WAAW,MAAM;AACnC,KAAI,cAAc,KAAA,EAChB,QAAO,IACL,qBACA,+BAA+B,MAAM,KACtC;CAEH,MAAM,SAAS,UAAU,SAAS,MAAM,KAAK;AAC7C,KAAI,CAAC,OAAO,MAAO,QAAO;AAC1B,QAAO;EACL,OAAO;EACP,SAAS,GAAG,MAAM,KAAK,OAAO;EAC/B;;;;;;;;;;AAWH,MAAM,UAAU,UAA0B;CACxC,MAAM,QAAQ,YAAY,MAAM;AAChC,KAAI,UAAU,KAAA,EAAW,QAAO;CAChC,MAAM,YAAY,WAAW,MAAM;AACnC,KAAI,cAAc,KAAA,EAAW,QAAO;AACpC,QAAO,GAAG,MAAM,KAAK,UAAU,QAAQ,MAAM,KAAK;;;AAIpD,MAAM,QAAmB;CACvB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,UAAU,4BAA4B;CAChD,kBAAkB;CAClB,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,eAAe,cAAc;CACxC;CACA;CACA;CACD"}
1
+ {"version":3,"file":"vat.js","names":["atUid","beVat","bgVat","cyVat","czDic","deVat","dkVat","eeVat","grVat","esVat","fiVat","frTva","hrVat","huVat","ieVat","itIva","ltVat","luVat","lvVat","mtVat","nlVat","plNip","ptVat","roVat","seVat","siVat","skDic","gbVat"],"sources":["../../src/eu/vat.ts"],"sourcesContent":["/**\n * EU VAT (European Union VAT Number).\n *\n * Dispatcher that routes to per-country VAT\n * validators. Extracts the 2-letter country prefix\n * and delegates to the matching country module.\n *\n * Special cases:\n * - EL → Greece (gr.vat)\n * - XI → Northern Ireland (gb.vat)\n *\n * @see https://ec.europa.eu/taxation_customs/vies/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport atUid from \"../at/uid\";\nimport beVat from \"../be/vat\";\nimport bgVat from \"../bg/vat\";\nimport cyVat from \"../cy/vat\";\nimport czDic from \"../cz/dic\";\nimport deVat from \"../de/vat\";\nimport dkVat from \"../dk/vat\";\nimport eeVat from \"../ee/vat\";\nimport esVat from \"../es/vat\";\nimport fiVat from \"../fi/vat\";\nimport frTva from \"../fr/tva\";\nimport gbVat from \"../gb/vat\";\nimport grVat from \"../gr/vat\";\nimport hrVat from \"../hr/vat\";\nimport huVat from \"../hu/vat\";\nimport ieVat from \"../ie/vat\";\nimport itIva from \"../it/iva\";\nimport ltVat from \"../lt/vat\";\nimport luVat from \"../lu/vat\";\nimport lvVat from \"../lv/vat\";\nimport mtVat from \"../mt/vat\";\nimport nlVat from \"../nl/vat\";\nimport plNip from \"../pl/nip\";\nimport ptVat from \"../pt/vat\";\nimport roVat from \"../ro/vat\";\nimport seVat from \"../se/vat\";\nimport siVat from \"../si/vat\";\nimport skDic from \"../sk/dic\";\nimport type { Validator, ValidateResult } from \"../types\";\n\ntype CountryValidator = {\n compact: (value: string) => string;\n validate: (value: string) => ValidateResult;\n format: (value: string) => string;\n};\n\n/**\n * Map of EU VAT country prefixes to their\n * country-specific validators.\n */\nconst VALIDATORS: Record<string, CountryValidator> = {\n AT: atUid,\n BE: beVat,\n BG: bgVat,\n CY: cyVat,\n CZ: czDic,\n DE: deVat,\n DK: dkVat,\n EE: eeVat,\n EL: grVat, // Greece uses EL prefix in EU VAT\n ES: esVat,\n FI: fiVat,\n FR: frTva,\n GR: grVat,\n HR: hrVat,\n HU: huVat,\n IE: ieVat,\n IT: itIva,\n LT: ltVat,\n LU: luVat,\n LV: lvVat,\n MT: mtVat,\n NL: nlVat,\n PL: plNip,\n PT: ptVat,\n RO: roVat,\n SE: seVat,\n SI: siVat,\n SK: skDic,\n XI: gbVat, // Northern Ireland\n};\n\n/**\n * Extract the 2-letter country prefix and the\n * remaining number from an EU VAT string.\n */\nconst splitPrefix = (\n value: string,\n): { cc: string; rest: string } | undefined => {\n const v = clean(value, \" -\").toUpperCase();\n if (v.length < 3) return undefined;\n const cc = v.slice(0, 2);\n if (!/^[A-Z]{2}$/.test(cc)) return undefined;\n return { cc, rest: v.slice(2) };\n};\n\nconst compact = (value: string): string => {\n const parts = splitPrefix(value);\n if (parts === undefined) {\n return clean(value, \" -\").toUpperCase();\n }\n const validator = VALIDATORS[parts.cc];\n if (validator === undefined) {\n return clean(value, \" -\").toUpperCase();\n }\n return `${parts.cc}${validator.compact(parts.rest)}`;\n};\n\nconst validate = (value: string): ValidateResult => {\n const parts = splitPrefix(value);\n if (parts === undefined) {\n return err(\n \"INVALID_FORMAT\",\n \"EU VAT must start with a 2-letter country code\",\n );\n }\n const validator = VALIDATORS[parts.cc];\n if (validator === undefined) {\n return err(\n \"INVALID_COMPONENT\",\n `Unsupported EU VAT country: ${parts.cc}`,\n );\n }\n const result = validator.validate(parts.rest);\n if (!result.valid) return result;\n return {\n valid: true,\n compact: `${parts.cc}${result.compact}`,\n };\n};\n\n/**\n * Format returns the compact EU VAT form:\n * `CC` + country-compacted number. Equivalent to\n * compact() because country format() methods\n * prepend their own prefix (e.g., AT UID format\n * returns \"ATU...\"), which would cause double-\n * prefixing if used here.\n */\nconst format = (value: string): string => {\n const parts = splitPrefix(value);\n if (parts === undefined) return value;\n const validator = VALIDATORS[parts.cc];\n if (validator === undefined) return value;\n return `${parts.cc}${validator.compact(parts.rest)}`;\n};\n\nconst GENERATORS = [\n [\"AT\", atUid],\n [\"BE\", beVat],\n [\"BG\", bgVat],\n [\"CY\", cyVat],\n [\"CZ\", czDic],\n [\"DE\", deVat],\n [\"DK\", dkVat],\n [\"EE\", eeVat],\n [\"ES\", esVat],\n [\"FI\", fiVat],\n [\"FR\", frTva],\n [\"GR\", grVat],\n [\"HR\", hrVat],\n [\"HU\", huVat],\n [\"IE\", ieVat],\n [\"IT\", itIva],\n [\"LT\", ltVat],\n [\"LU\", luVat],\n [\"LV\", lvVat],\n [\"MT\", mtVat],\n [\"NL\", nlVat],\n [\"PL\", plNip],\n [\"PT\", ptVat],\n [\"RO\", roVat],\n [\"SE\", seVat],\n [\"SI\", siVat],\n [\"SK\", skDic],\n] as const;\n\n/** Generate a random EU VAT number from a member validator. */\nconst generate = (): string => {\n for (;;) {\n const candidate =\n GENERATORS[randomInt(0, GENERATORS.length - 1)];\n if (!candidate) continue;\n\n const [prefix, validator] = candidate;\n if (validator.generate === undefined) continue;\n return `${prefix}${validator.generate()}`;\n }\n};\n\n/** European Union VAT Number. */\nconst euVat: Validator = {\n name: \"EU VAT Number\",\n localName: \"EU VAT Number\",\n abbreviation: \"EU VAT\",\n aliases: [\"EU VAT\", \"VAT identification number\"] as const,\n candidatePattern: \"[A-Z]{2}\\\\d{8,12}\",\n entityType: \"company\",\n sourceUrl: \"https://ec.europa.eu/taxation_customs/vies/\",\n examples: [\"ATU13585627\", \"DE136695976\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default euVat;\nexport { compact, format, generate, validate };\n"],"mappings":"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"}
package/dist/fi/hetu.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/fi/hetu.d.ts
4
-
5
4
  declare const compact: (value: string) => string;
6
5
  declare const validate: (value: string) => ValidateResult;
7
6
  declare const format: (value: string) => string;
@@ -10,8 +9,10 @@ declare const format: (value: string) => string;
10
9
  * Returns null if the value is not valid.
11
10
  */
12
11
  declare const parse: (value: string) => ParsedPersonId | null;
12
+ /** Generate a random valid HETU. */
13
+ declare const generate: () => string;
13
14
  /** Finnish Personal Identity Code. */
14
- declare const hetu: Validator;
15
+ declare const hetu: Validator<ParsedPersonId>;
15
16
  //#endregion
16
- export { compact, hetu as default, format, parse, validate };
17
+ export { compact, hetu as default, format, generate, parse, validate };
17
18
  //# sourceMappingURL=hetu.d.ts.map
package/dist/fi/hetu.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { clean } from "../_util/clean.js";
2
+ import { randomInt } from "../_util/generate.js";
2
3
  import { err } from "../_util/result.js";
3
4
  import { isdigits } from "../_util/strings.js";
4
5
  import { isValidDate } from "../_util/date.js";
@@ -82,6 +83,17 @@ const parse = (value) => {
82
83
  gender: serial % 2 === 0 ? "female" : "male"
83
84
  };
84
85
  };
86
+ /** Generate a random valid HETU. */
87
+ const generate = () => {
88
+ const year = randomInt(1900, 2024);
89
+ const month = String(randomInt(1, 12)).padStart(2, "0");
90
+ const day = String(randomInt(1, 28)).padStart(2, "0");
91
+ const yy = String(year % 100).padStart(2, "0");
92
+ const separator = year >= 2e3 ? "A" : "-";
93
+ const serial = String(randomInt(2, 899)).padStart(3, "0");
94
+ const checkNum = Number(`${day}${month}${yy}${serial}`);
95
+ return `${day}${month}${yy}${separator}${serial}${CHECK_CHARS.charAt(checkNum % 31)}`;
96
+ };
85
97
  /** Finnish Personal Identity Code. */
86
98
  const hetu = {
87
99
  name: "Finnish Personal ID",
@@ -96,12 +108,15 @@ const hetu = {
96
108
  country: "FI",
97
109
  entityType: "person",
98
110
  sourceUrl: "https://dvv.fi/en/personal-identity-code",
111
+ lengths: [11],
99
112
  examples: ["131052-308T"],
100
113
  compact,
101
114
  format,
102
- validate
115
+ parse,
116
+ validate,
117
+ generate
103
118
  };
104
119
  //#endregion
105
- export { compact, hetu as default, format, parse, validate };
120
+ export { compact, hetu as default, format, generate, parse, validate };
106
121
 
107
122
  //# sourceMappingURL=hetu.js.map