@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":"hetu.js","names":[],"sources":["../../src/fi/hetu.ts"],"sourcesContent":["/**\n * HETU (Henkilötunnus).\n *\n * Finnish personal identity code. 11 characters in\n * format DDMMYY+CCC+X where the separator indicates\n * the century and X is a check character.\n *\n * @see https://dvv.fi/en/personal-identity-code\n */\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\nconst CHECK_CHARS = \"0123456789ABCDEFHJKLMNPRSTUVWXY\";\n\nconst SEPARATORS_1800 = new Set([\"+\"]);\nconst SEPARATORS_1900 = new Set([\n \"-\",\n \"Y\",\n \"X\",\n \"W\",\n \"V\",\n \"U\",\n]);\nconst SEPARATORS_2000 = new Set([\n \"A\",\n \"B\",\n \"C\",\n \"D\",\n \"E\",\n \"F\",\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 !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"HETU must be exactly 11 characters\",\n );\n }\n\n const dd = v.slice(0, 2);\n const mm = v.slice(2, 4);\n const yy = v.slice(4, 6);\n const separator = v.charAt(6);\n const serial = v.slice(7, 10);\n const checkChar = v.charAt(10);\n\n if (!isdigits(dd) || !isdigits(mm) || !isdigits(yy)) {\n return err(\n \"INVALID_FORMAT\",\n \"HETU date part must be digits\",\n );\n }\n if (!isdigits(serial)) {\n return err(\n \"INVALID_FORMAT\",\n \"HETU serial must be digits\",\n );\n }\n\n let century: number;\n if (SEPARATORS_1800.has(separator)) {\n century = 1800;\n } else if (SEPARATORS_1900.has(separator)) {\n century = 1900;\n } else if (SEPARATORS_2000.has(separator)) {\n century = 2000;\n } else {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU separator is invalid\",\n );\n }\n\n const year = century + Number(yy);\n const month = Number(mm);\n const day = Number(dd);\n\n if (!isValidDate(year, month, day)) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU contains an invalid date\",\n );\n }\n\n // Individual number must be >= 002\n const serialNum = Number(serial);\n if (serialNum < 2) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU individual number must be >= 002\",\n );\n }\n // Temporary range 900-999 is not valid\n if (serialNum >= 900) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU temporary individual range 900-999\",\n );\n }\n\n const checkNum = Number(`${dd}${mm}${yy}${serial}`);\n const expected = CHECK_CHARS.charAt(checkNum % 31);\n if (checkChar !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"HETU check character does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a HETU.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const yy = Number(v.slice(4, 6));\n const separator = v.charAt(6);\n const serial = Number(v.slice(7, 10));\n\n let century: number;\n if (SEPARATORS_1800.has(separator)) {\n century = 1800;\n } else if (SEPARATORS_1900.has(separator)) {\n century = 1900;\n } else {\n century = 2000;\n }\n\n const year = century + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender: serial % 2 === 0 ? \"female\" : \"male\",\n };\n};\n\n/** Finnish Personal Identity Code. */\nconst hetu: Validator = {\n name: \"Finnish Personal ID\",\n localName: \"Henkilötunnus\",\n abbreviation: \"HETU\",\n aliases: [\n \"henkilötunnus\",\n \"HETU\",\n \"sosiaaliturvatunnus\",\n ] as const,\n candidatePattern: \"\\\\d{6}[-+A]\\\\d{3}[\\\\dA-Z]\",\n country: \"FI\",\n entityType: \"person\",\n sourceUrl: \"https://dvv.fi/en/personal-identity-code\",\n examples: [\"131052-308T\"] as const,\n compact,\n format,\n validate,\n};\n\nexport default hetu;\nexport { compact, format, parse, validate };\n"],"mappings":";;;;;;;;;;;;;;AAqBA,MAAM,cAAc;AAEpB,MAAM,kBAAkB,IAAI,IAAI,CAAC,IAAI,CAAC;AACtC,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AACF,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,CAAC,aAAa;AAEjC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,qCACD;CAGH,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE;CACxB,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE;CACxB,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE;CACxB,MAAM,YAAY,EAAE,OAAO,EAAE;CAC7B,MAAM,SAAS,EAAE,MAAM,GAAG,GAAG;CAC7B,MAAM,YAAY,EAAE,OAAO,GAAG;AAE9B,KAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,GAAG,CACjD,QAAO,IACL,kBACA,gCACD;AAEH,KAAI,CAAC,SAAS,OAAO,CACnB,QAAO,IACL,kBACA,6BACD;CAGH,IAAI;AACJ,KAAI,gBAAgB,IAAI,UAAU,CAChC,WAAU;UACD,gBAAgB,IAAI,UAAU,CACvC,WAAU;UACD,gBAAgB,IAAI,UAAU,CACvC,WAAU;KAEV,QAAO,IACL,qBACA,4BACD;AAOH,KAAI,CAAC,YAJQ,UAAU,OAAO,GAAG,EACnB,OAAO,GAAG,EACZ,OAAO,GAAG,CAEY,CAChC,QAAO,IACL,qBACA,gCACD;CAIH,MAAM,YAAY,OAAO,OAAO;AAChC,KAAI,YAAY,EACd,QAAO,IACL,qBACA,wCACD;AAGH,KAAI,aAAa,IACf,QAAO,IACL,qBACA,0CACD;CAGH,MAAM,WAAW,OAAO,GAAG,KAAK,KAAK,KAAK,SAAS;AAEnD,KAAI,cADa,YAAY,OAAO,WAAW,GAAG,CAEhD,QAAO,IACL,oBACA,sCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;;;;AAMxD,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,MAAM;AAC9B,KAAI,CAAC,OAAO,MAAO,QAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,YAAY,EAAE,OAAO,EAAE;CAC7B,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;CAErC,IAAI;AACJ,KAAI,gBAAgB,IAAI,UAAU,CAChC,WAAU;UACD,gBAAgB,IAAI,UAAU,CACvC,WAAU;KAEV,WAAU;CAGZ,MAAM,OAAO,UAAU;AAEvB,QAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,GAAG;EACrC,QAAQ,SAAS,MAAM,IAAI,WAAW;EACvC;;;AAIH,MAAM,OAAkB;CACtB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,cAAc;CACzB;CACA;CACA;CACD"}
1
+ {"version":3,"file":"hetu.js","names":[],"sources":["../../src/fi/hetu.ts"],"sourcesContent":["/**\n * HETU (Henkilötunnus).\n *\n * Finnish personal identity code. 11 characters in\n * format DDMMYY+CCC+X where the separator indicates\n * the century and X is a check character.\n *\n * @see https://dvv.fi/en/personal-identity-code\n */\n\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 CHECK_CHARS = \"0123456789ABCDEFHJKLMNPRSTUVWXY\";\n\nconst SEPARATORS_1800 = new Set([\"+\"]);\nconst SEPARATORS_1900 = new Set([\n \"-\",\n \"Y\",\n \"X\",\n \"W\",\n \"V\",\n \"U\",\n]);\nconst SEPARATORS_2000 = new Set([\n \"A\",\n \"B\",\n \"C\",\n \"D\",\n \"E\",\n \"F\",\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 !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"HETU must be exactly 11 characters\",\n );\n }\n\n const dd = v.slice(0, 2);\n const mm = v.slice(2, 4);\n const yy = v.slice(4, 6);\n const separator = v.charAt(6);\n const serial = v.slice(7, 10);\n const checkChar = v.charAt(10);\n\n if (!isdigits(dd) || !isdigits(mm) || !isdigits(yy)) {\n return err(\n \"INVALID_FORMAT\",\n \"HETU date part must be digits\",\n );\n }\n if (!isdigits(serial)) {\n return err(\n \"INVALID_FORMAT\",\n \"HETU serial must be digits\",\n );\n }\n\n let century: number;\n if (SEPARATORS_1800.has(separator)) {\n century = 1800;\n } else if (SEPARATORS_1900.has(separator)) {\n century = 1900;\n } else if (SEPARATORS_2000.has(separator)) {\n century = 2000;\n } else {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU separator is invalid\",\n );\n }\n\n const year = century + Number(yy);\n const month = Number(mm);\n const day = Number(dd);\n\n if (!isValidDate(year, month, day)) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU contains an invalid date\",\n );\n }\n\n // Individual number must be >= 002\n const serialNum = Number(serial);\n if (serialNum < 2) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU individual number must be >= 002\",\n );\n }\n // Temporary range 900-999 is not valid\n if (serialNum >= 900) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU temporary individual range 900-999\",\n );\n }\n\n const checkNum = Number(`${dd}${mm}${yy}${serial}`);\n const expected = CHECK_CHARS.charAt(checkNum % 31);\n if (checkChar !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"HETU check character does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a HETU.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const yy = Number(v.slice(4, 6));\n const separator = v.charAt(6);\n const serial = Number(v.slice(7, 10));\n\n let century: number;\n if (SEPARATORS_1800.has(separator)) {\n century = 1800;\n } else if (SEPARATORS_1900.has(separator)) {\n century = 1900;\n } else {\n century = 2000;\n }\n\n const year = century + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender: serial % 2 === 0 ? \"female\" : \"male\",\n };\n};\n\n/** Generate a random valid HETU. */\nconst generate = (): string => {\n const year = randomInt(1900, 2024);\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n const yy = String(year % 100).padStart(2, \"0\");\n const separator = year >= 2000 ? \"A\" : \"-\";\n const serial = String(randomInt(2, 899)).padStart(3, \"0\");\n const checkNum = Number(`${day}${month}${yy}${serial}`);\n const checkChar = CHECK_CHARS.charAt(checkNum % 31);\n return `${day}${month}${yy}${separator}${serial}${checkChar}`;\n};\n\n/** Finnish Personal Identity Code. */\nconst hetu: Validator<ParsedPersonId> = {\n name: \"Finnish Personal ID\",\n localName: \"Henkilötunnus\",\n abbreviation: \"HETU\",\n aliases: [\n \"henkilötunnus\",\n \"HETU\",\n \"sosiaaliturvatunnus\",\n ] as const,\n candidatePattern: \"\\\\d{6}[-+A]\\\\d{3}[\\\\dA-Z]\",\n country: \"FI\",\n entityType: \"person\",\n sourceUrl: \"https://dvv.fi/en/personal-identity-code\",\n lengths: [11] as const,\n examples: [\"131052-308T\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default hetu;\nexport { compact, format, generate, parse, validate };\n"],"mappings":"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"}
package/dist/fi/mod.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import hetu from "./hetu.js";
3
2
  import vat from "./vat.js";
4
3
  import ytunnus from "./ytunnus.js";
5
4
 
6
5
  //#region src/fi/mod.d.ts
7
-
6
+ declare namespace mod_d_exports {
7
+ export { hetu, vat, ytunnus };
8
+ }
8
9
  //#endregion
9
10
  export { hetu, mod_d_exports, vat, ytunnus };
10
11
  //# sourceMappingURL=mod.d.ts.map
package/dist/fi/vat.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/fi/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;
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/fi/ytunnus.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/fr/mod.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import nif from "./nif.js";
3
2
  import nir from "./nir.js";
4
3
  import siren from "./siren.js";
@@ -6,7 +5,9 @@ import siret from "./siret.js";
6
5
  import tva from "./tva.js";
7
6
 
8
7
  //#region src/fr/mod.d.ts
9
-
8
+ declare namespace mod_d_exports {
9
+ export { nif, nir, siren, siret, tva };
10
+ }
10
11
  //#endregion
11
12
  export { mod_d_exports, nif, nir, siren, siret, tva };
12
13
  //# sourceMappingURL=mod.d.ts.map
package/dist/fr/nif.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/fr/nif.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/fr/nir.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/fr/nir.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;
@@ -9,7 +8,7 @@ declare const parse: (value: string) => ParsedPersonId | null;
9
8
  /** Generate a random valid French NIR. */
10
9
  declare const generate: () => string;
11
10
  /** French Social Security Number. */
12
- declare const nir: Validator;
11
+ declare const nir: Validator<ParsedPersonId>;
13
12
  //#endregion
14
13
  export { compact, nir as default, format, generate, parse, validate };
15
14
  //# sourceMappingURL=nir.d.ts.map
package/dist/fr/nir.js CHANGED
@@ -97,6 +97,7 @@ const nir = {
97
97
  examples: ["295117823456784"],
98
98
  compact,
99
99
  format,
100
+ parse,
100
101
  validate,
101
102
  generate
102
103
  };
@@ -1 +1 @@
1
- {"version":3,"file":"nir.js","names":[],"sources":["../../src/fr/nir.ts"],"sourcesContent":["/**\n * NIR (Numero d'Inscription au Repertoire).\n *\n * French social security number (numero de securite\n * sociale). 15 digits: 13 identity digits + 2 check\n * digits. Encodes gender, year/month of birth, and\n * department of birth.\n *\n * Corsican departments 2A/2B are encoded as 19/18\n * for the mod-97 checksum computation.\n *\n * @see https://en.wikipedia.org/wiki/INSEE_code\n */\n\nimport { clean } from \"#util/clean\";\nimport { resolveTwoDigitYear } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\nconst compact = (value: string): string =>\n clean(value, \" -.\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value).toUpperCase();\n if (v.length !== 15) {\n return err(\n \"INVALID_LENGTH\",\n \"French NIR must be 15 characters\",\n );\n }\n\n const gender = v[0];\n if (gender !== \"1\" && gender !== \"2\") {\n return err(\n \"INVALID_COMPONENT\",\n \"French NIR first digit must be 1 or 2\",\n );\n }\n\n const yearPart = v.slice(1, 3);\n if (!/^\\d{2}$/.test(yearPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR year must be 2 digits\",\n );\n }\n\n const monthPart = v.slice(3, 5);\n if (!/^\\d{2}$/.test(monthPart) || monthPart === \"00\") {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR month must be 01-99\",\n );\n }\n\n const deptPart = v.slice(5, 7);\n const isCorsica = deptPart === \"2A\" || deptPart === \"2B\";\n if (!isCorsica && !/^\\d{2}$/.test(deptPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR department must be 2 digits or 2A/2B\",\n );\n }\n\n const communePart = v.slice(7, 10);\n if (!/^\\d{3}$/.test(communePart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR commune must be 3 digits\",\n );\n }\n\n const serialPart = v.slice(10, 13);\n if (!/^\\d{3}$/.test(serialPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR serial must be 3 digits\",\n );\n }\n\n const checkPart = v.slice(13, 15);\n if (!/^\\d{2}$/.test(checkPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR check must be 2 digits\",\n );\n }\n\n let numericBase: string;\n if (deptPart === \"2A\") {\n numericBase = v.slice(0, 5) + \"19\" + v.slice(7, 13);\n } else if (deptPart === \"2B\") {\n numericBase = v.slice(0, 5) + \"18\" + v.slice(7, 13);\n } else {\n numericBase = v.slice(0, 13);\n }\n\n const base = BigInt(numericBase);\n const expected = 97n - (base % 97n);\n const actual = BigInt(checkPart);\n\n if (expected !== actual) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French NIR check digits mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value).toUpperCase();\n return (\n `${v.slice(0, 1)} ${v.slice(1, 3)}` +\n ` ${v.slice(3, 5)} ${v.slice(5, 7)}` +\n ` ${v.slice(7, 10)} ${v.slice(10, 13)}` +\n ` ${v.slice(13)}`\n );\n};\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 genderDigit = v[0];\n const yy = Number(v.slice(1, 3));\n const mm = Number(v.slice(3, 5));\n\n if (mm < 1 || mm > 12) return null;\n\n const year = resolveTwoDigitYear(yy);\n const gender = genderDigit === \"1\" ? \"male\" : \"female\";\n\n return {\n birthDate: new Date(year, mm - 1, 1),\n gender,\n };\n};\n\n/** Generate a random valid French NIR. */\nconst generate = (): string => {\n for (;;) {\n const g = String(randomInt(1, 2));\n const yy = String(randomInt(50, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dept = String(randomInt(1, 95)).padStart(2, \"0\");\n const com = String(randomInt(1, 999)).padStart(3, \"0\");\n const s = String(randomInt(1, 999)).padStart(3, \"0\");\n const base = g + yy + mm + dept + com + s;\n const check = String(97 - (Number(base) % 97)).padStart(\n 2,\n \"0\",\n );\n const c = base + check;\n if (validate(c).valid) return c;\n }\n};\n\n/** French Social Security Number. */\nconst nir: Validator = {\n name: \"French Social Security Number\",\n localName: \"Numero d'Inscription au Repertoire\",\n abbreviation: \"NIR\",\n aliases: [\n \"NIR\",\n \"numéro de sécurité sociale\",\n \"numéro SS\",\n \"sécu\",\n ] as const,\n candidatePattern:\n \"[12]\\\\s?\\\\d{2}\\\\s?\\\\d{2}\\\\s?\\\\d{2}\\\\s?\\\\d{3}\\\\s?\\\\d{3}\\\\s?\\\\d{2}\",\n country: \"FR\",\n entityType: \"person\",\n description:\n \"French social security number encoding \" +\n \"gender, birth date, and department\",\n sourceUrl: \"https://en.wikipedia.org/wiki/INSEE_code\",\n lengths: [15] as const,\n examples: [\"295117823456784\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nir;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;AAyBA,MAAM,WAAW,UACf,MAAM,OAAO,MAAM;AAErB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM,CAAC,aAAa;AACtC,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,mCACD;CAGH,MAAM,SAAS,EAAE;AACjB,KAAI,WAAW,OAAO,WAAW,IAC/B,QAAO,IACL,qBACA,wCACD;CAGH,MAAM,WAAW,EAAE,MAAM,GAAG,EAAE;AAC9B,KAAI,CAAC,UAAU,KAAK,SAAS,CAC3B,QAAO,IACL,kBACA,mCACD;CAGH,MAAM,YAAY,EAAE,MAAM,GAAG,EAAE;AAC/B,KAAI,CAAC,UAAU,KAAK,UAAU,IAAI,cAAc,KAC9C,QAAO,IACL,kBACA,iCACD;CAGH,MAAM,WAAW,EAAE,MAAM,GAAG,EAAE;AAE9B,KAAI,EADc,aAAa,QAAQ,aAAa,SAClC,CAAC,UAAU,KAAK,SAAS,CACzC,QAAO,IACL,kBACA,kDACD;CAGH,MAAM,cAAc,EAAE,MAAM,GAAG,GAAG;AAClC,KAAI,CAAC,UAAU,KAAK,YAAY,CAC9B,QAAO,IACL,kBACA,sCACD;CAGH,MAAM,aAAa,EAAE,MAAM,IAAI,GAAG;AAClC,KAAI,CAAC,UAAU,KAAK,WAAW,CAC7B,QAAO,IACL,kBACA,qCACD;CAGH,MAAM,YAAY,EAAE,MAAM,IAAI,GAAG;AACjC,KAAI,CAAC,UAAU,KAAK,UAAU,CAC5B,QAAO,IACL,kBACA,oCACD;CAGH,IAAI;AACJ,KAAI,aAAa,KACf,eAAc,EAAE,MAAM,GAAG,EAAE,GAAG,OAAO,EAAE,MAAM,GAAG,GAAG;UAC1C,aAAa,KACtB,eAAc,EAAE,MAAM,GAAG,EAAE,GAAG,OAAO,EAAE,MAAM,GAAG,GAAG;KAEnD,eAAc,EAAE,MAAM,GAAG,GAAG;AAO9B,KAHiB,MADJ,OAAO,YAAY,GACD,QAChB,OAAO,UAAU,CAG9B,QAAO,IACL,oBACA,mCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM,CAAC,aAAa;AACtC,QACE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAA,GAC7B,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAA,GAC9B,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,IAAI,GAAG,CAAA,GACjC,EAAE,MAAM,GAAG;;AAInB,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,MAAM;AAC9B,KAAI,CAAC,OAAO,MAAO,QAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,cAAc,EAAE;CACtB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AAEhC,KAAI,KAAK,KAAK,KAAK,GAAI,QAAO;CAE9B,MAAM,OAAO,oBAAoB,GAAG;CACpC,MAAM,SAAS,gBAAgB,MAAM,SAAS;AAE9C,QAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,EAAE;EACpC;EACD;;;AAIH,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,IAAI,OAAO,UAAU,GAAG,EAAE,CAAC;EACjC,MAAM,KAAK,OAAO,UAAU,IAAI,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACrD,MAAM,KAAK,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,OAAO,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACtD,MAAM,MAAM,OAAO,UAAU,GAAG,IAAI,CAAC,CAAC,SAAS,GAAG,IAAI;EACtD,MAAM,IAAI,OAAO,UAAU,GAAG,IAAI,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,OAAO,IAAI,KAAK,KAAK,OAAO,MAAM;EAKxC,MAAM,IAAI,OAJI,OAAO,KAAM,OAAO,KAAK,GAAG,GAAI,CAAC,SAC7C,GACA,IACD;AAED,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACA;EACD;CACD,kBACE;CACF,SAAS;CACT,YAAY;CACZ,aACE;CAEF,WAAW;CACX,SAAS,CAAC,GAAG;CACb,UAAU,CAAC,kBAAkB;CAC7B;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"nir.js","names":[],"sources":["../../src/fr/nir.ts"],"sourcesContent":["/**\n * NIR (Numero d'Inscription au Repertoire).\n *\n * French social security number (numero de securite\n * sociale). 15 digits: 13 identity digits + 2 check\n * digits. Encodes gender, year/month of birth, and\n * department of birth.\n *\n * Corsican departments 2A/2B are encoded as 19/18\n * for the mod-97 checksum computation.\n *\n * @see https://en.wikipedia.org/wiki/INSEE_code\n */\n\nimport { clean } from \"#util/clean\";\nimport { resolveTwoDigitYear } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\nconst compact = (value: string): string =>\n clean(value, \" -.\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value).toUpperCase();\n if (v.length !== 15) {\n return err(\n \"INVALID_LENGTH\",\n \"French NIR must be 15 characters\",\n );\n }\n\n const gender = v[0];\n if (gender !== \"1\" && gender !== \"2\") {\n return err(\n \"INVALID_COMPONENT\",\n \"French NIR first digit must be 1 or 2\",\n );\n }\n\n const yearPart = v.slice(1, 3);\n if (!/^\\d{2}$/.test(yearPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR year must be 2 digits\",\n );\n }\n\n const monthPart = v.slice(3, 5);\n if (!/^\\d{2}$/.test(monthPart) || monthPart === \"00\") {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR month must be 01-99\",\n );\n }\n\n const deptPart = v.slice(5, 7);\n const isCorsica = deptPart === \"2A\" || deptPart === \"2B\";\n if (!isCorsica && !/^\\d{2}$/.test(deptPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR department must be 2 digits or 2A/2B\",\n );\n }\n\n const communePart = v.slice(7, 10);\n if (!/^\\d{3}$/.test(communePart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR commune must be 3 digits\",\n );\n }\n\n const serialPart = v.slice(10, 13);\n if (!/^\\d{3}$/.test(serialPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR serial must be 3 digits\",\n );\n }\n\n const checkPart = v.slice(13, 15);\n if (!/^\\d{2}$/.test(checkPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR check must be 2 digits\",\n );\n }\n\n let numericBase: string;\n if (deptPart === \"2A\") {\n numericBase = v.slice(0, 5) + \"19\" + v.slice(7, 13);\n } else if (deptPart === \"2B\") {\n numericBase = v.slice(0, 5) + \"18\" + v.slice(7, 13);\n } else {\n numericBase = v.slice(0, 13);\n }\n\n const base = BigInt(numericBase);\n const expected = 97n - (base % 97n);\n const actual = BigInt(checkPart);\n\n if (expected !== actual) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French NIR check digits mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value).toUpperCase();\n return (\n `${v.slice(0, 1)} ${v.slice(1, 3)}` +\n ` ${v.slice(3, 5)} ${v.slice(5, 7)}` +\n ` ${v.slice(7, 10)} ${v.slice(10, 13)}` +\n ` ${v.slice(13)}`\n );\n};\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 genderDigit = v[0];\n const yy = Number(v.slice(1, 3));\n const mm = Number(v.slice(3, 5));\n\n if (mm < 1 || mm > 12) return null;\n\n const year = resolveTwoDigitYear(yy);\n const gender = genderDigit === \"1\" ? \"male\" : \"female\";\n\n return {\n birthDate: new Date(year, mm - 1, 1),\n gender,\n };\n};\n\n/** Generate a random valid French NIR. */\nconst generate = (): string => {\n for (;;) {\n const g = String(randomInt(1, 2));\n const yy = String(randomInt(50, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dept = String(randomInt(1, 95)).padStart(2, \"0\");\n const com = String(randomInt(1, 999)).padStart(3, \"0\");\n const s = String(randomInt(1, 999)).padStart(3, \"0\");\n const base = g + yy + mm + dept + com + s;\n const check = String(97 - (Number(base) % 97)).padStart(\n 2,\n \"0\",\n );\n const c = base + check;\n if (validate(c).valid) return c;\n }\n};\n\n/** French Social Security Number. */\nconst nir: Validator<ParsedPersonId> = {\n name: \"French Social Security Number\",\n localName: \"Numero d'Inscription au Repertoire\",\n abbreviation: \"NIR\",\n aliases: [\n \"NIR\",\n \"numéro de sécurité sociale\",\n \"numéro SS\",\n \"sécu\",\n ] as const,\n candidatePattern:\n \"[12]\\\\s?\\\\d{2}\\\\s?\\\\d{2}\\\\s?\\\\d{2}\\\\s?\\\\d{3}\\\\s?\\\\d{3}\\\\s?\\\\d{2}\",\n country: \"FR\",\n entityType: \"person\",\n description:\n \"French social security number encoding \" +\n \"gender, birth date, and department\",\n sourceUrl: \"https://en.wikipedia.org/wiki/INSEE_code\",\n lengths: [15] as const,\n examples: [\"295117823456784\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default nir;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/fr/siren.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,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/fr/siret.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/fr/tva.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/fr/tva.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/gb/mod.d.ts CHANGED
@@ -1,11 +1,12 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import nino from "./nino.js";
3
2
  import sedol from "./sedol.js";
4
3
  import utr from "./utr.js";
5
4
  import vat from "./vat.js";
6
5
 
7
6
  //#region src/gb/mod.d.ts
8
-
7
+ declare namespace mod_d_exports {
8
+ export { nino, sedol, utr, vat };
9
+ }
9
10
  //#endregion
10
11
  export { mod_d_exports, nino, sedol, utr, vat };
11
12
  //# sourceMappingURL=mod.d.ts.map
package/dist/gb/nino.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
  //#region src/gb/nino.ts
5
5
  /**
@@ -12,21 +12,21 @@ import { err } from "../_util/result.js";
12
12
  *
13
13
  * @see https://www.gov.uk/hmrc-internal-manuals/national-insurance-manual/nim39110
14
14
  */
15
+ const NINO_VALID_FIRST = "ABCEGHJKLMNOPRSTWXYZ";
16
+ const NINO_VALID_SECOND = "ABCEGHJKLMNPRSTWXYZ";
17
+ const NINO_SUFFIXES = "ABCD";
15
18
  /** Generate a random valid UK NINO. */
16
19
  const generate = () => {
17
- const validFirst = "ABCEGHJKLMNOPRSTWXYZ";
18
- const validSecond = "ABCEGHJKLMNPRSTWXYZ";
19
- const suffixes = "ABCD";
20
20
  let first;
21
21
  let second;
22
22
  let prefix;
23
23
  do {
24
- first = validFirst[randomInt(0, 19)];
25
- second = validSecond[randomInt(0, 18)];
24
+ first = randomChar(NINO_VALID_FIRST);
25
+ second = randomChar(NINO_VALID_SECOND);
26
26
  prefix = first + second;
27
27
  } while (INVALID_PREFIX.has(prefix));
28
28
  const digits = randomDigits(6);
29
- const suffix = suffixes[randomInt(0, 3)];
29
+ const suffix = randomChar(NINO_SUFFIXES);
30
30
  return `${prefix}${digits}${suffix}`;
31
31
  };
32
32
  const INVALID_FIRST = new Set([
@@ -1 +1 @@
1
- {"version":3,"file":"nino.js","names":[],"sources":["../../src/gb/nino.ts"],"sourcesContent":["/** Generate a random valid UK NINO. */\nconst generate = (): string => {\n const validFirst = \"ABCEGHJKLMNOPRSTWXYZ\";\n const validSecond = \"ABCEGHJKLMNPRSTWXYZ\";\n const suffixes = \"ABCD\";\n let first: string;\n let second: string;\n let prefix: string;\n do {\n first =\n validFirst[randomInt(0, validFirst.length - 1)]!;\n second =\n validSecond[randomInt(0, validSecond.length - 1)]!;\n prefix = first + second;\n } while (INVALID_PREFIX.has(prefix));\n const digits = randomDigits(6);\n const suffix =\n suffixes[randomInt(0, suffixes.length - 1)]!;\n return `${prefix}${digits}${suffix}`;\n};\n\n/**\n * NINO (National Insurance Number).\n *\n * UK National Insurance Number. Format: 2 letters\n * + 6 digits + 1 suffix letter (A, B, C, or D).\n * Validated by format and prefix rules only; there\n * is no checksum.\n *\n * @see https://www.gov.uk/hmrc-internal-manuals/national-insurance-manual/nim39110\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst INVALID_FIRST = new Set([\n \"D\",\n \"F\",\n \"I\",\n \"Q\",\n \"U\",\n \"V\",\n]);\n\nconst INVALID_SECOND = new Set([\n \"D\",\n \"F\",\n \"I\",\n \"O\",\n \"Q\",\n \"U\",\n \"V\",\n]);\n\nconst INVALID_PREFIX = new Set([\n \"BG\",\n \"GB\",\n \"NK\",\n \"KN\",\n \"TN\",\n \"NT\",\n \"ZZ\",\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 \"UK NINO must be 9 characters\",\n );\n }\n\n if (!/^[A-Z]{2}\\d{6}[A-D]$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK NINO must be 2 letters, 6 digits, \" +\n \"then A/B/C/D\",\n );\n }\n\n const first = v[0]!;\n const second = v[1]!;\n const prefix = v.slice(0, 2);\n\n if (INVALID_FIRST.has(first)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO first letter cannot be ${first}`,\n );\n }\n\n if (INVALID_SECOND.has(second)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO second letter cannot be ${second}`,\n );\n }\n\n if (INVALID_PREFIX.has(prefix)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO prefix ${prefix} is not allowed`,\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return (\n `${v.slice(0, 2)} ${v.slice(2, 4)}` +\n ` ${v.slice(4, 6)} ${v.slice(6, 8)}` +\n ` ${v.slice(8)}`\n );\n};\n\n/** UK National Insurance Number. */\nconst nino: Validator = {\n name: \"UK National Insurance Number\",\n localName: \"National Insurance Number\",\n abbreviation: \"NINO\",\n aliases: [\n \"National Insurance number\",\n \"NINO\",\n \"NI number\",\n ] as const,\n candidatePattern: \"[A-Z]{2}\\\\d{6}[A-Z]\",\n country: \"GB\",\n entityType: \"person\",\n description:\n \"UK National Insurance Number for tax \" +\n \"and benefits\",\n sourceUrl:\n \"https://www.gov.uk/hmrc-internal-manuals/\" +\n \"national-insurance-manual/nim39110\",\n lengths: [9] as const,\n examples: [\"AB123456C\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nino;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;AACA,MAAM,iBAAyB;CAC7B,MAAM,aAAa;CACnB,MAAM,cAAc;CACpB,MAAM,WAAW;CACjB,IAAI;CACJ,IAAI;CACJ,IAAI;AACJ,IAAG;AACD,UACE,WAAW,UAAU,GAAG,GAAsB;AAChD,WACE,YAAY,UAAU,GAAG,GAAuB;AAClD,WAAS,QAAQ;UACV,eAAe,IAAI,OAAO;CACnC,MAAM,SAAS,aAAa,EAAE;CAC9B,MAAM,SACJ,SAAS,UAAU,GAAG,EAAoB;AAC5C,QAAO,GAAG,SAAS,SAAS;;AAoB9B,MAAM,gBAAgB,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,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,+BACD;AAGH,KAAI,CAAC,uBAAuB,KAAK,EAAE,CACjC,QAAO,IACL,kBACA,oDAED;CAGH,MAAM,QAAQ,EAAE;CAChB,MAAM,SAAS,EAAE;CACjB,MAAM,SAAS,EAAE,MAAM,GAAG,EAAE;AAE5B,KAAI,cAAc,IAAI,MAAM,CAC1B,QAAO,IACL,qBACA,kCAAkC,QACnC;AAGH,KAAI,eAAe,IAAI,OAAO,CAC5B,QAAO,IACL,qBACA,mCAAmC,SACpC;AAGH,KAAI,eAAe,IAAI,OAAO,CAC5B,QAAO,IACL,qBACA,kBAAkB,OAAO,iBAC1B;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,QACE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAA,GAC7B,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAA,GAC9B,EAAE,MAAM,EAAE;;;AAKlB,MAAM,OAAkB;CACtB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,aACE;CAEF,WACE;CAEF,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"nino.js","names":[],"sources":["../../src/gb/nino.ts"],"sourcesContent":["const NINO_VALID_FIRST = \"ABCEGHJKLMNOPRSTWXYZ\";\nconst NINO_VALID_SECOND = \"ABCEGHJKLMNPRSTWXYZ\";\nconst NINO_SUFFIXES = \"ABCD\";\n\n/** Generate a random valid UK NINO. */\nconst generate = (): string => {\n let first: string;\n let second: string;\n let prefix: string;\n do {\n first = randomChar(NINO_VALID_FIRST);\n second = randomChar(NINO_VALID_SECOND);\n prefix = first + second;\n } while (INVALID_PREFIX.has(prefix));\n const digits = randomDigits(6);\n const suffix = randomChar(NINO_SUFFIXES);\n return `${prefix}${digits}${suffix}`;\n};\n\n/**\n * NINO (National Insurance Number).\n *\n * UK National Insurance Number. Format: 2 letters\n * + 6 digits + 1 suffix letter (A, B, C, or D).\n * Validated by format and prefix rules only; there\n * is no checksum.\n *\n * @see https://www.gov.uk/hmrc-internal-manuals/national-insurance-manual/nim39110\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomChar, randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst INVALID_FIRST = new Set([\n \"D\",\n \"F\",\n \"I\",\n \"Q\",\n \"U\",\n \"V\",\n]);\n\nconst INVALID_SECOND = new Set([\n \"D\",\n \"F\",\n \"I\",\n \"O\",\n \"Q\",\n \"U\",\n \"V\",\n]);\n\nconst INVALID_PREFIX = new Set([\n \"BG\",\n \"GB\",\n \"NK\",\n \"KN\",\n \"TN\",\n \"NT\",\n \"ZZ\",\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 \"UK NINO must be 9 characters\",\n );\n }\n\n if (!/^[A-Z]{2}\\d{6}[A-D]$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK NINO must be 2 letters, 6 digits, \" +\n \"then A/B/C/D\",\n );\n }\n\n // SAFETY: regex above guarantees v.length === 9.\n // eslint-disable-next-line no-non-null-assertion\n const first = v[0]!;\n // eslint-disable-next-line no-non-null-assertion\n const second = v[1]!;\n const prefix = v.slice(0, 2);\n\n if (INVALID_FIRST.has(first)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO first letter cannot be ${first}`,\n );\n }\n\n if (INVALID_SECOND.has(second)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO second letter cannot be ${second}`,\n );\n }\n\n if (INVALID_PREFIX.has(prefix)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO prefix ${prefix} is not allowed`,\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return (\n `${v.slice(0, 2)} ${v.slice(2, 4)}` +\n ` ${v.slice(4, 6)} ${v.slice(6, 8)}` +\n ` ${v.slice(8)}`\n );\n};\n\n/** UK National Insurance Number. */\nconst nino: Validator = {\n name: \"UK National Insurance Number\",\n localName: \"National Insurance Number\",\n abbreviation: \"NINO\",\n aliases: [\n \"National Insurance number\",\n \"NINO\",\n \"NI number\",\n ] as const,\n candidatePattern: \"[A-Z]{2}\\\\d{6}[A-Z]\",\n country: \"GB\",\n entityType: \"person\",\n description:\n \"UK National Insurance Number for tax \" +\n \"and benefits\",\n sourceUrl:\n \"https://www.gov.uk/hmrc-internal-manuals/\" +\n \"national-insurance-manual/nim39110\",\n lengths: [9] as const,\n examples: [\"AB123456C\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nino;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;AAAA,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAC1B,MAAM,gBAAgB;;AAGtB,MAAM,iBAAyB;CAC7B,IAAI;CACJ,IAAI;CACJ,IAAI;AACJ,IAAG;AACD,UAAQ,WAAW,iBAAiB;AACpC,WAAS,WAAW,kBAAkB;AACtC,WAAS,QAAQ;UACV,eAAe,IAAI,OAAO;CACnC,MAAM,SAAS,aAAa,EAAE;CAC9B,MAAM,SAAS,WAAW,cAAc;AACxC,QAAO,GAAG,SAAS,SAAS;;AAoB9B,MAAM,gBAAgB,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,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,+BACD;AAGH,KAAI,CAAC,uBAAuB,KAAK,EAAE,CACjC,QAAO,IACL,kBACA,oDAED;CAKH,MAAM,QAAQ,EAAE;CAEhB,MAAM,SAAS,EAAE;CACjB,MAAM,SAAS,EAAE,MAAM,GAAG,EAAE;AAE5B,KAAI,cAAc,IAAI,MAAM,CAC1B,QAAO,IACL,qBACA,kCAAkC,QACnC;AAGH,KAAI,eAAe,IAAI,OAAO,CAC5B,QAAO,IACL,qBACA,mCAAmC,SACpC;AAGH,KAAI,eAAe,IAAI,OAAO,CAC5B,QAAO,IACL,qBACA,kBAAkB,OAAO,iBAC1B;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,QACE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAA,GAC7B,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAA,GAC9B,EAAE,MAAM,EAAE;;;AAKlB,MAAM,OAAkB;CACtB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,aACE;CAEF,WACE;CAEF,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACD"}
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/gb/sedol.d.ts
4
-
5
4
  declare const calcCheckDigit: (number: string) => string;
6
5
  declare const compact: (value: string) => string;
7
6
  declare const validate: (value: string) => ValidateResult;
package/dist/gb/sedol.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { clean } from "../_util/clean.js";
2
- import { randomInt } from "../_util/generate.js";
2
+ import { randomChar } from "../_util/generate.js";
3
3
  import { err } from "../_util/result.js";
4
4
  import { isdigits } from "../_util/strings.js";
5
5
  //#region src/gb/sedol.ts
@@ -33,11 +33,12 @@ const WEIGHTS = [
33
33
  const calcCheckDigit = (number) => {
34
34
  if (number.length !== 6) throw new Error("calcCheckDigit requires a 6-character SEDOL prefix");
35
35
  let sum = 0;
36
- for (let i = 0; i < 6; i++) {
36
+ for (const [i, weight] of WEIGHTS.entries()) {
37
37
  const ch = number[i];
38
+ if (ch === void 0) continue;
38
39
  const val = ALPHABET.indexOf(ch);
39
40
  if (val < 0) throw new Error(`Invalid SEDOL character: ${ch}`);
40
- sum += WEIGHTS[i] * val;
41
+ sum += weight * val;
41
42
  }
42
43
  return String((10 - sum % 10) % 10);
43
44
  };
@@ -54,12 +55,12 @@ const validate = (value) => {
54
55
  };
55
56
  };
56
57
  const format = (value) => compact(value);
58
+ const SEDOL_CONSONANTS = "BCDFGHJKLMNPQRSTVWXYZ";
59
+ const SEDOL_CHARS = "0123456789BCDFGHJKLMNPQRSTVWXYZ";
57
60
  /** Generate a random valid SEDOL. */
58
61
  const generate = () => {
59
- const consonants = "BCDFGHJKLMNPQRSTVWXYZ";
60
- const chars = "0123456789BCDFGHJKLMNPQRSTVWXYZ";
61
- let payload = consonants[randomInt(0, 20)];
62
- for (let i = 1; i < 6; i++) payload += chars[randomInt(0, 30)];
62
+ let payload = randomChar(SEDOL_CONSONANTS);
63
+ for (let i = 1; i < 6; i++) payload += randomChar(SEDOL_CHARS);
63
64
  return payload + calcCheckDigit(payload);
64
65
  };
65
66
  /** Stock Exchange Daily Official List number. */
@@ -1 +1 @@
1
- {"version":3,"file":"sedol.js","names":[],"sources":["../../src/gb/sedol.ts"],"sourcesContent":["/**\n * SEDOL (Stock Exchange Daily Official List number).\n *\n * 7-character security identifier used in the UK and\n * Ireland, assigned by the London Stock Exchange.\n * Consists of 6 alphanumeric characters (vowels\n * excluded) followed by a weighted mod-10 check\n * digit.\n *\n * @see https://en.wikipedia.org/wiki/SEDOL\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\n/**\n * Allowed characters in a SEDOL: digits and\n * consonants only (vowels are never used).\n * Spaces occupy vowel positions (A=10, E=14,\n * I=18, O=24, U=30) so that indexOf returns\n * the correct SEDOL weight for each consonant.\n */\nconst ALPHABET = \"0123456789 BCD FGH JKLMN PQRST VWXYZ\";\n\nconst WEIGHTS = [1, 3, 1, 7, 3, 9] as const;\n\nconst calcCheckDigit = (number: string): string => {\n if (number.length !== 6) {\n throw new Error(\n \"calcCheckDigit requires a 6-character \" +\n \"SEDOL prefix\",\n );\n }\n let sum = 0;\n for (let i = 0; i < 6; i++) {\n const ch = number[i]!;\n const val = ALPHABET.indexOf(ch);\n if (val < 0) {\n throw new Error(`Invalid SEDOL character: ${ch}`);\n }\n // SAFETY: weights length matches loop bound\n sum += WEIGHTS[i]! * val;\n }\n return String((10 - (sum % 10)) % 10);\n};\n\nconst compact = (value: string): string =>\n clean(value, \" \").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 7) {\n return err(\n \"INVALID_LENGTH\",\n \"SEDOL must be exactly 7 characters\",\n );\n }\n\n for (const ch of v) {\n if (!ALPHABET.includes(ch)) {\n return err(\n \"INVALID_FORMAT\",\n \"SEDOL contains invalid character: \" +\n \"vowels are not allowed\",\n );\n }\n }\n\n // Old-style SEDOLs are fully numeric; new-style\n // SEDOLs start with a letter. A number that starts\n // with a digit but contains letters is invalid.\n if (isdigits(v[0]!) && !isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Numeric-prefix SEDOL must be fully \" +\n \"numeric (old-style)\",\n );\n }\n\n if (calcCheckDigit(v.slice(0, 6)) !== v[6]) {\n return err(\n \"INVALID_CHECKSUM\",\n \"SEDOL check digit 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 SEDOL. */\nconst generate = (): string => {\n const consonants = \"BCDFGHJKLMNPQRSTVWXYZ\";\n const chars = \"0123456789BCDFGHJKLMNPQRSTVWXYZ\";\n const first =\n consonants[randomInt(0, consonants.length - 1)]!;\n let payload = first;\n for (let i = 1; i < 6; i++)\n payload += chars[randomInt(0, chars.length - 1)]!;\n return payload + calcCheckDigit(payload);\n};\n\n/** Stock Exchange Daily Official List number. */\nconst sedol: Validator = {\n name: \"Stock Exchange Daily Official List number\",\n localName: \"Stock Exchange Daily Official List number\",\n abbreviation: \"SEDOL\",\n aliases: [\n \"SEDOL\",\n \"Stock Exchange Daily Official List\",\n ] as const,\n candidatePattern: \"[B-DF-HJ-NP-TV-Z0-9]{6}\\\\d\",\n country: \"GB\",\n entityType: \"any\",\n sourceUrl: \"https://en.wikipedia.org/wiki/SEDOL\",\n lengths: [7] as const,\n examples: [\"B15KXQ8\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default sedol;\nexport {\n calcCheckDigit,\n compact,\n format,\n validate,\n generate,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,WAAW;AAEjB,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;AAElC,MAAM,kBAAkB,WAA2B;AACjD,KAAI,OAAO,WAAW,EACpB,OAAM,IAAI,MACR,qDAED;CAEH,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,MAAM,KAAK,OAAO;EAClB,MAAM,MAAM,SAAS,QAAQ,GAAG;AAChC,MAAI,MAAM,EACR,OAAM,IAAI,MAAM,4BAA4B,KAAK;AAGnD,SAAO,QAAQ,KAAM;;AAEvB,QAAO,QAAQ,KAAM,MAAM,MAAO,GAAG;;AAGvC,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,CAAC,aAAa;AAEjC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,qCACD;AAGH,MAAK,MAAM,MAAM,EACf,KAAI,CAAC,SAAS,SAAS,GAAG,CACxB,QAAO,IACL,kBACA,2DAED;AAOL,KAAI,SAAS,EAAE,GAAI,IAAI,CAAC,SAAS,EAAE,CACjC,QAAO,IACL,kBACA,yDAED;AAGH,KAAI,eAAe,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,EAAE,GACtC,QAAO,IACL,oBACA,6BACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,iBAAyB;CAC7B,MAAM,aAAa;CACnB,MAAM,QAAQ;CAGd,IAAI,UADF,WAAW,UAAU,GAAG,GAAsB;AAEhD,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IACrB,YAAW,MAAM,UAAU,GAAG,GAAiB;AACjD,QAAO,UAAU,eAAe,QAAQ;;;AAI1C,MAAM,QAAmB;CACvB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,SACA,qCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,UAAU;CACrB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"sedol.js","names":[],"sources":["../../src/gb/sedol.ts"],"sourcesContent":["/**\n * SEDOL (Stock Exchange Daily Official List number).\n *\n * 7-character security identifier used in the UK and\n * Ireland, assigned by the London Stock Exchange.\n * Consists of 6 alphanumeric characters (vowels\n * excluded) followed by a weighted mod-10 check\n * digit.\n *\n * @see https://en.wikipedia.org/wiki/SEDOL\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomChar } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\n/**\n * Allowed characters in a SEDOL: digits and\n * consonants only (vowels are never used).\n * Spaces occupy vowel positions (A=10, E=14,\n * I=18, O=24, U=30) so that indexOf returns\n * the correct SEDOL weight for each consonant.\n */\nconst ALPHABET = \"0123456789 BCD FGH JKLMN PQRST VWXYZ\";\n\nconst WEIGHTS = [1, 3, 1, 7, 3, 9] as const;\n\nconst calcCheckDigit = (number: string): string => {\n if (number.length !== 6) {\n throw new Error(\n \"calcCheckDigit requires a 6-character \" +\n \"SEDOL prefix\",\n );\n }\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n const ch = number[i];\n if (ch === undefined) continue;\n const val = ALPHABET.indexOf(ch);\n if (val < 0) {\n throw new Error(`Invalid SEDOL character: ${ch}`);\n }\n sum += weight * val;\n }\n return String((10 - (sum % 10)) % 10);\n};\n\nconst compact = (value: string): string =>\n clean(value, \" \").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 7) {\n return err(\n \"INVALID_LENGTH\",\n \"SEDOL must be exactly 7 characters\",\n );\n }\n\n for (const ch of v) {\n if (!ALPHABET.includes(ch)) {\n return err(\n \"INVALID_FORMAT\",\n \"SEDOL contains invalid character: \" +\n \"vowels are not allowed\",\n );\n }\n }\n\n // Old-style SEDOLs are fully numeric; new-style\n // SEDOLs start with a letter. A number that starts\n // with a digit but contains letters is invalid.\n // SAFETY: v.length === 7 here.\n // eslint-disable-next-line no-non-null-assertion\n if (isdigits(v[0]!) && !isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Numeric-prefix SEDOL must be fully \" +\n \"numeric (old-style)\",\n );\n }\n\n if (calcCheckDigit(v.slice(0, 6)) !== v[6]) {\n return err(\n \"INVALID_CHECKSUM\",\n \"SEDOL check digit mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst SEDOL_CONSONANTS = \"BCDFGHJKLMNPQRSTVWXYZ\";\nconst SEDOL_CHARS = \"0123456789BCDFGHJKLMNPQRSTVWXYZ\";\n\n/** Generate a random valid SEDOL. */\nconst generate = (): string => {\n let payload = randomChar(SEDOL_CONSONANTS);\n for (let i = 1; i < 6; i++) {\n payload += randomChar(SEDOL_CHARS);\n }\n return payload + calcCheckDigit(payload);\n};\n\n/** Stock Exchange Daily Official List number. */\nconst sedol: Validator = {\n name: \"Stock Exchange Daily Official List number\",\n localName: \"Stock Exchange Daily Official List number\",\n abbreviation: \"SEDOL\",\n aliases: [\n \"SEDOL\",\n \"Stock Exchange Daily Official List\",\n ] as const,\n candidatePattern: \"[B-DF-HJ-NP-TV-Z0-9]{6}\\\\d\",\n country: \"GB\",\n entityType: \"any\",\n sourceUrl: \"https://en.wikipedia.org/wiki/SEDOL\",\n lengths: [7] as const,\n examples: [\"B15KXQ8\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default sedol;\nexport {\n calcCheckDigit,\n compact,\n format,\n validate,\n generate,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,WAAW;AAEjB,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;AAElC,MAAM,kBAAkB,WAA2B;AACjD,KAAI,OAAO,WAAW,EACpB,OAAM,IAAI,MACR,qDAED;CAEH,IAAI,MAAM;AACV,MAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,SAAS,EAAE;EAC3C,MAAM,KAAK,OAAO;AAClB,MAAI,OAAO,KAAA,EAAW;EACtB,MAAM,MAAM,SAAS,QAAQ,GAAG;AAChC,MAAI,MAAM,EACR,OAAM,IAAI,MAAM,4BAA4B,KAAK;AAEnD,SAAO,SAAS;;AAElB,QAAO,QAAQ,KAAM,MAAM,MAAO,GAAG;;AAGvC,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,CAAC,aAAa;AAEjC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,qCACD;AAGH,MAAK,MAAM,MAAM,EACf,KAAI,CAAC,SAAS,SAAS,GAAG,CACxB,QAAO,IACL,kBACA,2DAED;AASL,KAAI,SAAS,EAAE,GAAI,IAAI,CAAC,SAAS,EAAE,CACjC,QAAO,IACL,kBACA,yDAED;AAGH,KAAI,eAAe,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,EAAE,GACtC,QAAO,IACL,oBACA,6BACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;AAExD,MAAM,mBAAmB;AACzB,MAAM,cAAc;;AAGpB,MAAM,iBAAyB;CAC7B,IAAI,UAAU,WAAW,iBAAiB;AAC1C,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IACrB,YAAW,WAAW,YAAY;AAEpC,QAAO,UAAU,eAAe,QAAQ;;;AAI1C,MAAM,QAAmB;CACvB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,SACA,qCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,UAAU;CACrB;CACA;CACA;CACA;CACD"}
package/dist/gb/utr.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/gb/utr.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/gb/vat.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/gb/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/ge/mod.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import pin from "./pin.js";
3
2
 
4
3
  //#region src/ge/mod.d.ts
5
-
4
+ declare namespace mod_d_exports {
5
+ export { pin };
6
+ }
6
7
  //#endregion
7
8
  export { mod_d_exports, pin };
8
9
  //# sourceMappingURL=mod.d.ts.map
package/dist/gh/mod.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import tin from "./tin.js";
3
2
 
4
3
  //#region src/gh/mod.d.ts
5
-
4
+ declare namespace mod_d_exports {
5
+ export { tin };
6
+ }
6
7
  //#endregion
7
8
  export { mod_d_exports, tin };
8
9
  //# sourceMappingURL=mod.d.ts.map
package/dist/gh/tin.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/gh/tin.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/gh/tin.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
  //#region src/gh/tin.ts
5
5
  /**
@@ -41,17 +41,17 @@ const validate = (value) => {
41
41
  };
42
42
  };
43
43
  const format = (value) => compact(value);
44
+ const TIN_PREFIXES = [
45
+ "P",
46
+ "C",
47
+ "G",
48
+ "Q",
49
+ "V"
50
+ ];
44
51
  /** Generate a random valid Ghana TIN. */
45
52
  const generate = () => {
46
- const prefixes = [
47
- "P",
48
- "C",
49
- "G",
50
- "Q",
51
- "V"
52
- ];
53
53
  for (;;) {
54
- const partial = prefixes[randomInt(0, 4)] + randomDigits(9);
54
+ const partial = randomPick(TIN_PREFIXES) + randomDigits(9);
55
55
  const c = partial + calcCheckDigit(partial);
56
56
  if (validate(c).valid) return c;
57
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tin.js","names":[],"sources":["../../src/gh/tin.ts"],"sourcesContent":["/**\n * TIN (Tax Identification Number, Ghana).\n *\n * 11-character alphanumeric identifier. Structure:\n * - Position 1: type prefix (P/C/G/Q/V)\n * - Positions 2-3: always \"00\"\n * - Positions 4-10: digits\n * - Position 11: check digit (0-9 or X)\n *\n * Prefixes: P = individual, C = company,\n * G = government, Q = foreign mission,\n * V = public institution / trust.\n *\n * @see https://gra.gov.gh/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst FORMAT_RE = /^[PCGQV]00[0-9]{7}[0-9X]$/;\n\nconst compact = (value: string): string =>\n clean(value, \" \").toUpperCase();\n\n/**\n * Calculate the expected check digit.\n * Uses positions 1-9 (0-indexed) with weights 1-9,\n * mod 11. Returns \"X\" when the remainder is 10.\n */\nconst calcCheckDigit = (value: string): string => {\n let sum = 0;\n for (let i = 1; i <= 9; i++) {\n sum += i * Number(value[i]);\n }\n const check = sum % 11;\n return check === 10 ? \"X\" : String(check);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"Ghanaian TIN must be exactly 11 characters\",\n );\n }\n if (!FORMAT_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Ghanaian TIN must match [PCGQV]00 + \" +\n \"7 digits + check digit\",\n );\n }\n if (v[10] !== calcCheckDigit(v)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Ghanaian TIN 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 Ghana TIN. */\nconst generate = (): string => {\n const prefixes = [\"P\", \"C\", \"G\", \"Q\", \"V\"] as const;\n for (;;) {\n const p = prefixes[randomInt(0, 4)]!;\n const d = randomDigits(9);\n const partial = p + d;\n const c = partial + calcCheckDigit(partial);\n if (validate(c).valid) return c;\n }\n};\n\n/** Ghanaian Tax Identification Number. */\nconst tin: Validator = {\n name: \"Ghanaian Tax Identification Number\",\n localName: \"Tax Identification Number\",\n abbreviation: \"TIN\",\n aliases: [\"TIN\", \"Tax Identification Number\"] as const,\n candidatePattern: \"[A-Z]\\\\d{9,10}\",\n country: \"GH\",\n entityType: \"any\",\n compact,\n format,\n validate,\n description: \"Ghanaian tax identification number\",\n sourceUrl: \"https://gra.gov.gh/\",\n lengths: [11] as const,\n examples: [\"C0000803561\"] as const,\n generate,\n};\n\nexport default tin;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAsBA,MAAM,YAAY;AAElB,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,CAAC,aAAa;;;;;;AAOjC,MAAM,kBAAkB,UAA0B;CAChD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,KAAK,GAAG,IACtB,QAAO,IAAI,OAAO,MAAM,GAAG;CAE7B,MAAM,QAAQ,MAAM;AACpB,QAAO,UAAU,KAAK,MAAM,OAAO,MAAM;;AAG3C,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,6CACD;AAEH,KAAI,CAAC,UAAU,KAAK,EAAE,CACpB,QAAO,IACL,kBACA,6DAED;AAEH,KAAI,EAAE,QAAQ,eAAe,EAAE,CAC7B,QAAO,IACL,oBACA,oCACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,iBAAyB;CAC7B,MAAM,WAAW;EAAC;EAAK;EAAK;EAAK;EAAK;EAAI;AAC1C,UAAS;EAGP,MAAM,UAFI,SAAS,UAAU,GAAG,EAAE,IACxB,aAAa,EAAE;EAEzB,MAAM,IAAI,UAAU,eAAe,QAAQ;AAC3C,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,4BAA4B;CAC7C,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ;CACA;CACA;CACA,aAAa;CACb,WAAW;CACX,SAAS,CAAC,GAAG;CACb,UAAU,CAAC,cAAc;CACzB;CACD"}
1
+ {"version":3,"file":"tin.js","names":[],"sources":["../../src/gh/tin.ts"],"sourcesContent":["/**\n * TIN (Tax Identification Number, Ghana).\n *\n * 11-character alphanumeric identifier. Structure:\n * - Position 1: type prefix (P/C/G/Q/V)\n * - Positions 2-3: always \"00\"\n * - Positions 4-10: digits\n * - Position 11: check digit (0-9 or X)\n *\n * Prefixes: P = individual, C = company,\n * G = government, Q = foreign mission,\n * V = public institution / trust.\n *\n * @see https://gra.gov.gh/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomPick } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst FORMAT_RE = /^[PCGQV]00[0-9]{7}[0-9X]$/;\n\nconst compact = (value: string): string =>\n clean(value, \" \").toUpperCase();\n\n/**\n * Calculate the expected check digit.\n * Uses positions 1-9 (0-indexed) with weights 1-9,\n * mod 11. Returns \"X\" when the remainder is 10.\n */\nconst calcCheckDigit = (value: string): string => {\n let sum = 0;\n for (let i = 1; i <= 9; i++) {\n sum += i * Number(value[i]);\n }\n const check = sum % 11;\n return check === 10 ? \"X\" : String(check);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"Ghanaian TIN must be exactly 11 characters\",\n );\n }\n if (!FORMAT_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Ghanaian TIN must match [PCGQV]00 + \" +\n \"7 digits + check digit\",\n );\n }\n if (v[10] !== calcCheckDigit(v)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Ghanaian TIN check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst TIN_PREFIXES = [\"P\", \"C\", \"G\", \"Q\", \"V\"] as const;\n\n/** Generate a random valid Ghana TIN. */\nconst generate = (): string => {\n for (;;) {\n const p = randomPick(TIN_PREFIXES);\n const d = randomDigits(9);\n const partial = p + d;\n const c = partial + calcCheckDigit(partial);\n if (validate(c).valid) return c;\n }\n};\n\n/** Ghanaian Tax Identification Number. */\nconst tin: Validator = {\n name: \"Ghanaian Tax Identification Number\",\n localName: \"Tax Identification Number\",\n abbreviation: \"TIN\",\n aliases: [\"TIN\", \"Tax Identification Number\"] as const,\n candidatePattern: \"[A-Z]\\\\d{9,10}\",\n country: \"GH\",\n entityType: \"any\",\n compact,\n format,\n validate,\n description: \"Ghanaian tax identification number\",\n sourceUrl: \"https://gra.gov.gh/\",\n lengths: [11] as const,\n examples: [\"C0000803561\"] as const,\n generate,\n};\n\nexport default tin;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAsBA,MAAM,YAAY;AAElB,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,CAAC,aAAa;;;;;;AAOjC,MAAM,kBAAkB,UAA0B;CAChD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,KAAK,GAAG,IACtB,QAAO,IAAI,OAAO,MAAM,GAAG;CAE7B,MAAM,QAAQ,MAAM;AACpB,QAAO,UAAU,KAAK,MAAM,OAAO,MAAM;;AAG3C,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,6CACD;AAEH,KAAI,CAAC,UAAU,KAAK,EAAE,CACpB,QAAO,IACL,kBACA,6DAED;AAEH,KAAI,EAAE,QAAQ,eAAe,EAAE,CAC7B,QAAO,IACL,oBACA,oCACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;AAExD,MAAM,eAAe;CAAC;CAAK;CAAK;CAAK;CAAK;CAAI;;AAG9C,MAAM,iBAAyB;AAC7B,UAAS;EAGP,MAAM,UAFI,WAAW,aAAa,GACxB,aAAa,EAAE;EAEzB,MAAM,IAAI,UAAU,eAAe,QAAQ;AAC3C,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,4BAA4B;CAC7C,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ;CACA;CACA;CACA,aAAa;CACb,WAAW;CACX,SAAS,CAAC,GAAG;CACb,UAAU,CAAC,cAAc;CACzB;CACD"}
package/dist/gr/amka.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/gr/amka.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/gr/mod.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import amka from "./amka.js";
3
2
  import vat from "./vat.js";
4
3
 
5
4
  //#region src/gr/mod.d.ts
6
-
5
+ declare namespace mod_d_exports {
6
+ export { amka, vat };
7
+ }
7
8
  //#endregion
8
9
  export { amka, mod_d_exports, vat };
9
10
  //# sourceMappingURL=mod.d.ts.map
package/dist/gr/vat.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/gr/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/gt/mod.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import nit from "./nit.js";
3
2
 
4
3
  //#region src/gt/mod.d.ts
5
-
4
+ declare namespace mod_d_exports {
5
+ export { nit };
6
+ }
6
7
  //#endregion
7
8
  export { mod_d_exports, nit };
8
9
  //# sourceMappingURL=mod.d.ts.map
package/dist/gt/nit.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/gt/nit.d.ts
4
-
5
4
  /**
6
5
  * Compact: strip spaces, hyphens, leading zeros,
7
6
  * and uppercase.
package/dist/gt/nit.js CHANGED
@@ -55,8 +55,11 @@ const format = (value) => {
55
55
  };
56
56
  /** Generate a random valid NIT (7 body digits). */
57
57
  const generate = () => {
58
- const body = randomDigits(7);
59
- return `${body}${calcCheckChar(body)}`;
58
+ for (;;) {
59
+ const body = randomDigits(7);
60
+ if (body.startsWith("0")) continue;
61
+ return `${body}${calcCheckChar(body)}`;
62
+ }
60
63
  };
61
64
  /** Guatemala tax identification number. */
62
65
  const nit = {
@@ -1 +1 @@
1
- {"version":3,"file":"nit.js","names":[],"sources":["../../src/gt/nit.ts"],"sourcesContent":["/**\n * NIT (Número de Identificación Tributaria,\n * Guatemala tax number).\n *\n * 2–12 characters: body digits followed by a check\n * character. The check character is computed via a\n * weighted sum mod 11; remainder 10 maps to 'K'.\n *\n * Ported from python-stdnum gt.nit module.\n *\n * @see https://portal.sat.gob.gt/portal/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\n/**\n * Compact: strip spaces, hyphens, leading zeros,\n * and uppercase.\n */\nconst compact = (value: string): string => {\n const v = clean(value, \" -\").trim().toUpperCase();\n return v.replace(/^0+/, \"\");\n};\n\n/**\n * Calculate the check character for a body string.\n * Weighted sum mod 11; remainder 10 yields 'K'.\n */\nconst calcCheckChar = (body: string): string => {\n let sum = 0;\n const len = body.length;\n for (let i = 0; i < len; i++) {\n sum += (len - i + 1) * Number(body[i]);\n }\n const remainder = ((-sum % 11) + 11) % 11;\n return remainder === 10 ? \"K\" : String(remainder);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length < 2 || v.length > 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Guatemala NIT must be 2–12 characters\",\n );\n }\n\n const body = v.slice(0, -1);\n const check = v.slice(-1);\n\n if (!isdigits(body)) {\n return err(\n \"INVALID_FORMAT\",\n \"Guatemala NIT body must contain only digits\",\n );\n }\n\n if (check !== \"K\" && !/^\\d$/.test(check)) {\n return err(\n \"INVALID_FORMAT\",\n \"Guatemala NIT check character must be a digit or K\",\n );\n }\n\n if (check !== calcCheckChar(body)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Guatemala NIT check character does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\n/**\n * Format: insert a hyphen before the check character.\n */\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, -1)}-${v.slice(-1)}`;\n};\n\n/** Generate a random valid NIT (7 body digits). */\nconst generate = (): string => {\n const body = randomDigits(7);\n const check = calcCheckChar(body);\n return `${body}${check}`;\n};\n\n/** Guatemala tax identification number. */\nconst nit: Validator = {\n name: \"Tax Identification Number\",\n localName: \"Número de Identificación Tributaria\",\n abbreviation: \"NIT\",\n aliases: [\"NIT\"] as const,\n candidatePattern: \"\\\\d{7,8}-?\\\\d\",\n country: \"GT\",\n entityType: \"any\",\n description: \"Tax identifier issued by Guatemala's SAT\",\n sourceUrl: \"https://portal.sat.gob.gt/portal/\",\n lengths: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] as const,\n examples: [\"576937K\", \"39525503\", \"71080\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nit;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,WAAW,UAA0B;AAEzC,QADU,MAAM,OAAO,KAAK,CAAC,MAAM,CAAC,aAAa,CACxC,QAAQ,OAAO,GAAG;;;;;;AAO7B,MAAM,iBAAiB,SAAyB;CAC9C,IAAI,MAAM;CACV,MAAM,MAAM,KAAK;AACjB,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IACvB,SAAQ,MAAM,IAAI,KAAK,OAAO,KAAK,GAAG;CAExC,MAAM,aAAc,CAAC,MAAM,KAAM,MAAM;AACvC,QAAO,cAAc,KAAK,MAAM,OAAO,UAAU;;AAGnD,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,SAAS,KAAK,EAAE,SAAS,GAC7B,QAAO,IACL,kBACA,wCACD;CAGH,MAAM,OAAO,EAAE,MAAM,GAAG,GAAG;CAC3B,MAAM,QAAQ,EAAE,MAAM,GAAG;AAEzB,KAAI,CAAC,SAAS,KAAK,CACjB,QAAO,IACL,kBACA,8CACD;AAGH,KAAI,UAAU,OAAO,CAAC,OAAO,KAAK,MAAM,CACtC,QAAO,IACL,kBACA,qDACD;AAGH,KAAI,UAAU,cAAc,KAAK,CAC/B,QAAO,IACL,oBACA,+CACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;;;;AAMpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,QAAO,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG;;;AAIzC,MAAM,iBAAyB;CAC7B,MAAM,OAAO,aAAa,EAAE;AAE5B,QAAO,GAAG,OADI,cAAc,KAAK;;;AAKnC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,MAAM;CAChB,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,aAAa;CACb,WAAW;CACX,SAAS;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;CAC7C,UAAU;EAAC;EAAW;EAAY;EAAQ;CAC1C;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"nit.js","names":[],"sources":["../../src/gt/nit.ts"],"sourcesContent":["/**\n * NIT (Número de Identificación Tributaria,\n * Guatemala tax number).\n *\n * 2–12 characters: body digits followed by a check\n * character. The check character is computed via a\n * weighted sum mod 11; remainder 10 maps to 'K'.\n *\n * Ported from python-stdnum gt.nit module.\n *\n * @see https://portal.sat.gob.gt/portal/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\n/**\n * Compact: strip spaces, hyphens, leading zeros,\n * and uppercase.\n */\nconst compact = (value: string): string => {\n const v = clean(value, \" -\").trim().toUpperCase();\n return v.replace(/^0+/, \"\");\n};\n\n/**\n * Calculate the check character for a body string.\n * Weighted sum mod 11; remainder 10 yields 'K'.\n */\nconst calcCheckChar = (body: string): string => {\n let sum = 0;\n const len = body.length;\n for (let i = 0; i < len; i++) {\n sum += (len - i + 1) * Number(body[i]);\n }\n const remainder = ((-sum % 11) + 11) % 11;\n return remainder === 10 ? \"K\" : String(remainder);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length < 2 || v.length > 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Guatemala NIT must be 2–12 characters\",\n );\n }\n\n const body = v.slice(0, -1);\n const check = v.slice(-1);\n\n if (!isdigits(body)) {\n return err(\n \"INVALID_FORMAT\",\n \"Guatemala NIT body must contain only digits\",\n );\n }\n\n if (check !== \"K\" && !/^\\d$/.test(check)) {\n return err(\n \"INVALID_FORMAT\",\n \"Guatemala NIT check character must be a digit or K\",\n );\n }\n\n if (check !== calcCheckChar(body)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Guatemala NIT check character does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\n/**\n * Format: insert a hyphen before the check character.\n */\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, -1)}-${v.slice(-1)}`;\n};\n\n/** Generate a random valid NIT (7 body digits). */\nconst generate = (): string => {\n for (;;) {\n const body = randomDigits(7);\n if (body.startsWith(\"0\")) continue;\n const check = calcCheckChar(body);\n return `${body}${check}`;\n }\n};\n\n/** Guatemala tax identification number. */\nconst nit: Validator = {\n name: \"Tax Identification Number\",\n localName: \"Número de Identificación Tributaria\",\n abbreviation: \"NIT\",\n aliases: [\"NIT\"] as const,\n candidatePattern: \"\\\\d{7,8}-?\\\\d\",\n country: \"GT\",\n entityType: \"any\",\n description: \"Tax identifier issued by Guatemala's SAT\",\n sourceUrl: \"https://portal.sat.gob.gt/portal/\",\n lengths: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] as const,\n examples: [\"576937K\", \"39525503\", \"71080\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nit;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,WAAW,UAA0B;AAEzC,QADU,MAAM,OAAO,KAAK,CAAC,MAAM,CAAC,aAAa,CACxC,QAAQ,OAAO,GAAG;;;;;;AAO7B,MAAM,iBAAiB,SAAyB;CAC9C,IAAI,MAAM;CACV,MAAM,MAAM,KAAK;AACjB,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,IACvB,SAAQ,MAAM,IAAI,KAAK,OAAO,KAAK,GAAG;CAExC,MAAM,aAAc,CAAC,MAAM,KAAM,MAAM;AACvC,QAAO,cAAc,KAAK,MAAM,OAAO,UAAU;;AAGnD,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,SAAS,KAAK,EAAE,SAAS,GAC7B,QAAO,IACL,kBACA,wCACD;CAGH,MAAM,OAAO,EAAE,MAAM,GAAG,GAAG;CAC3B,MAAM,QAAQ,EAAE,MAAM,GAAG;AAEzB,KAAI,CAAC,SAAS,KAAK,CACjB,QAAO,IACL,kBACA,8CACD;AAGH,KAAI,UAAU,OAAO,CAAC,OAAO,KAAK,MAAM,CACtC,QAAO,IACL,kBACA,qDACD;AAGH,KAAI,UAAU,cAAc,KAAK,CAC/B,QAAO,IACL,oBACA,+CACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;;;;AAMpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,QAAO,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG;;;AAIzC,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,OAAO,aAAa,EAAE;AAC5B,MAAI,KAAK,WAAW,IAAI,CAAE;AAE1B,SAAO,GAAG,OADI,cAAc,KAAK;;;;AAMrC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,MAAM;CAChB,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,aAAa;CACb,WAAW;CACX,SAAS;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;CAC7C,UAAU;EAAC;EAAW;EAAY;EAAQ;CAC1C;CACA;CACA;CACA;CACD"}
package/dist/hk/hkid.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ValidateResult, Validator } from "../types.js";
2
2
 
3
3
  //#region src/hk/hkid.d.ts
4
-
5
4
  /** Strip spaces, parentheses, and dashes. */
6
5
  declare const compact: (value: string) => string;
7
6
  declare const validate: (value: string) => ValidateResult;
package/dist/hk/hkid.js CHANGED
@@ -27,6 +27,7 @@ const computeCheck = (body) => {
27
27
  let sum = 0;
28
28
  for (let i = 0; i < 8; i++) {
29
29
  const ch = padded[i];
30
+ if (ch === void 0) continue;
30
31
  let val;
31
32
  if (ch === " ") val = 36;
32
33
  else if (ch >= "A" && ch <= "Z") val = ch.charCodeAt(0) - 55;
@@ -1 +1 @@
1
- {"version":3,"file":"hkid.js","names":[],"sources":["../../src/hk/hkid.ts"],"sourcesContent":["/**\n * HKID (Hong Kong Identity Card number).\n *\n * 1-2 letters + 6 digits + check digit in parentheses.\n * The check digit is computed via a weighted sum mod 11,\n * where letters have values A=10, B=11, ..., Z=35.\n * A remainder of 10 yields check digit 'A'.\n *\n * @see https://en.wikipedia.org/wiki/Hong_Kong_identity_card\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\n/** Strip spaces, parentheses, and dashes. */\nconst compact = (value: string): string =>\n clean(value, \" -()\").toUpperCase();\n\n/**\n * Compute the weighted check character.\n *\n * For a two-letter prefix the weights are 9,8,7,6,5,4,3,2\n * over the 8 characters (2 letters + 6 digits). For a\n * single-letter prefix, a space (value 36) is prepended\n * so the weights stay the same.\n */\nconst computeCheck = (body: string): string => {\n const padded = body.length === 7 ? ` ${body}` : body;\n\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n const ch = padded[i]!;\n let val: number;\n if (ch === \" \") {\n val = 36;\n } else if (ch >= \"A\" && ch <= \"Z\") {\n val = ch.charCodeAt(0) - 55; // A=10\n } else {\n val = Number(ch);\n }\n sum += val * (9 - i);\n }\n\n const remainder = sum % 11;\n if (remainder === 0) return \"0\";\n if (remainder === 1) return \"A\";\n return String(11 - remainder);\n};\n\nconst HKID_RE = /^[A-Z]{1,2}\\d{6}[0-9A]$/;\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8 && v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"HKID must be 8 or 9 characters\",\n );\n }\n if (!HKID_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"HKID must be 1-2 letters, 6 digits, \" +\n \"and a check character\",\n );\n }\n\n const body = v.slice(0, -1);\n const check = v.slice(-1);\n if (computeCheck(body) !== check) {\n return err(\n \"INVALID_CHECKSUM\",\n \"HKID check digit mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n const prefix = v.slice(0, -7);\n const digits = v.slice(-7, -1);\n const check = v.slice(-1);\n return `${prefix}${digits}(${check})`;\n};\n\n/** Generate a random valid HKID. */\nconst generate = (): string => {\n for (;;) {\n const letter = String.fromCharCode(\n 65 + randomInt(0, 25),\n );\n const digits = randomDigits(6);\n for (let d = 0; d <= 9; d++) {\n const c = letter + digits + String(d);\n if (validate(c).valid) return compact(c);\n }\n const cA = letter + digits + \"A\";\n if (validate(cA).valid) return compact(cA);\n }\n};\n\n/** Hong Kong Identity Card number. */\nconst hkid: Validator = {\n name: \"Hong Kong Identity Card Number\",\n localName: \"Hong Kong Identity Card Number\",\n abbreviation: \"HKID\",\n aliases: [\"HKID\", \"香港身份證\"] as const,\n candidatePattern: \"[A-Z]{1,2}\\\\d{6}[\\\\dA]\",\n country: \"HK\",\n entityType: \"person\",\n lengths: [8, 9],\n examples: [\"G123456A\", \"AB9876543\"],\n description:\n \"Identity card number issued by the Hong Kong \" +\n \"Immigration Department\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/\" +\n \"Hong_Kong_identity_card\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default hkid;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,MAAM,WAAW,UACf,MAAM,OAAO,OAAO,CAAC,aAAa;;;;;;;;;AAUpC,MAAM,gBAAgB,SAAyB;CAC7C,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,SAAS;CAEhD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,MAAM,KAAK,OAAO;EAClB,IAAI;AACJ,MAAI,OAAO,IACT,OAAM;WACG,MAAM,OAAO,MAAM,IAC5B,OAAM,GAAG,WAAW,EAAE,GAAG;MAEzB,OAAM,OAAO,GAAG;AAElB,SAAO,OAAO,IAAI;;CAGpB,MAAM,YAAY,MAAM;AACxB,KAAI,cAAc,EAAG,QAAO;AAC5B,KAAI,cAAc,EAAG,QAAO;AAC5B,QAAO,OAAO,KAAK,UAAU;;AAG/B,MAAM,UAAU;AAEhB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,KAAK,EAAE,WAAW,EACjC,QAAO,IACL,kBACA,iCACD;AAEH,KAAI,CAAC,QAAQ,KAAK,EAAE,CAClB,QAAO,IACL,kBACA,4DAED;CAGH,MAAM,OAAO,EAAE,MAAM,GAAG,GAAG;CAC3B,MAAM,QAAQ,EAAE,MAAM,GAAG;AACzB,KAAI,aAAa,KAAK,KAAK,MACzB,QAAO,IACL,oBACA,4BACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AAIxB,QAAO,GAHQ,EAAE,MAAM,GAAG,GAAG,GACd,EAAE,MAAM,IAAI,GAAG,CAEJ,GADZ,EAAE,MAAM,GAAG,CACU;;;AAIrC,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,SAAS,OAAO,aACpB,KAAK,UAAU,GAAG,GAAG,CACtB;EACD,MAAM,SAAS,aAAa,EAAE;AAC9B,OAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;GAC3B,MAAM,IAAI,SAAS,SAAS,OAAO,EAAE;AACrC,OAAI,SAAS,EAAE,CAAC,MAAO,QAAO,QAAQ,EAAE;;EAE1C,MAAM,KAAK,SAAS,SAAS;AAC7B,MAAI,SAAS,GAAG,CAAC,MAAO,QAAO,QAAQ,GAAG;;;;AAK9C,MAAM,OAAkB;CACtB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,QAAQ,QAAQ;CAC1B,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,GAAG,EAAE;CACf,UAAU,CAAC,YAAY,YAAY;CACnC,aACE;CAEF,WACE;CAEF;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"hkid.js","names":[],"sources":["../../src/hk/hkid.ts"],"sourcesContent":["/**\n * HKID (Hong Kong Identity Card number).\n *\n * 1-2 letters + 6 digits + check digit in parentheses.\n * The check digit is computed via a weighted sum mod 11,\n * where letters have values A=10, B=11, ..., Z=35.\n * A remainder of 10 yields check digit 'A'.\n *\n * @see https://en.wikipedia.org/wiki/Hong_Kong_identity_card\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\n/** Strip spaces, parentheses, and dashes. */\nconst compact = (value: string): string =>\n clean(value, \" -()\").toUpperCase();\n\n/**\n * Compute the weighted check character.\n *\n * For a two-letter prefix the weights are 9,8,7,6,5,4,3,2\n * over the 8 characters (2 letters + 6 digits). For a\n * single-letter prefix, a space (value 36) is prepended\n * so the weights stay the same.\n */\nconst computeCheck = (body: string): string => {\n const padded = body.length === 7 ? ` ${body}` : body;\n\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n const ch = padded[i];\n if (ch === undefined) continue;\n let val: number;\n if (ch === \" \") {\n val = 36;\n } else if (ch >= \"A\" && ch <= \"Z\") {\n val = ch.charCodeAt(0) - 55; // A=10\n } else {\n val = Number(ch);\n }\n sum += val * (9 - i);\n }\n\n const remainder = sum % 11;\n if (remainder === 0) return \"0\";\n if (remainder === 1) return \"A\";\n return String(11 - remainder);\n};\n\nconst HKID_RE = /^[A-Z]{1,2}\\d{6}[0-9A]$/;\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8 && v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"HKID must be 8 or 9 characters\",\n );\n }\n if (!HKID_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"HKID must be 1-2 letters, 6 digits, \" +\n \"and a check character\",\n );\n }\n\n const body = v.slice(0, -1);\n const check = v.slice(-1);\n if (computeCheck(body) !== check) {\n return err(\n \"INVALID_CHECKSUM\",\n \"HKID check digit mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n const prefix = v.slice(0, -7);\n const digits = v.slice(-7, -1);\n const check = v.slice(-1);\n return `${prefix}${digits}(${check})`;\n};\n\n/** Generate a random valid HKID. */\nconst generate = (): string => {\n for (;;) {\n const letter = String.fromCharCode(\n 65 + randomInt(0, 25),\n );\n const digits = randomDigits(6);\n for (let d = 0; d <= 9; d++) {\n const c = letter + digits + String(d);\n if (validate(c).valid) return compact(c);\n }\n const cA = letter + digits + \"A\";\n if (validate(cA).valid) return compact(cA);\n }\n};\n\n/** Hong Kong Identity Card number. */\nconst hkid: Validator = {\n name: \"Hong Kong Identity Card Number\",\n localName: \"Hong Kong Identity Card Number\",\n abbreviation: \"HKID\",\n aliases: [\"HKID\", \"香港身份證\"] as const,\n candidatePattern: \"[A-Z]{1,2}\\\\d{6}[\\\\dA]\",\n country: \"HK\",\n entityType: \"person\",\n lengths: [8, 9],\n examples: [\"G123456A\", \"AB9876543\"],\n description:\n \"Identity card number issued by the Hong Kong \" +\n \"Immigration Department\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/\" +\n \"Hong_Kong_identity_card\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default hkid;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,MAAM,WAAW,UACf,MAAM,OAAO,OAAO,CAAC,aAAa;;;;;;;;;AAUpC,MAAM,gBAAgB,SAAyB;CAC7C,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,SAAS;CAEhD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,MAAM,KAAK,OAAO;AAClB,MAAI,OAAO,KAAA,EAAW;EACtB,IAAI;AACJ,MAAI,OAAO,IACT,OAAM;WACG,MAAM,OAAO,MAAM,IAC5B,OAAM,GAAG,WAAW,EAAE,GAAG;MAEzB,OAAM,OAAO,GAAG;AAElB,SAAO,OAAO,IAAI;;CAGpB,MAAM,YAAY,MAAM;AACxB,KAAI,cAAc,EAAG,QAAO;AAC5B,KAAI,cAAc,EAAG,QAAO;AAC5B,QAAO,OAAO,KAAK,UAAU;;AAG/B,MAAM,UAAU;AAEhB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,KAAK,EAAE,WAAW,EACjC,QAAO,IACL,kBACA,iCACD;AAEH,KAAI,CAAC,QAAQ,KAAK,EAAE,CAClB,QAAO,IACL,kBACA,4DAED;CAGH,MAAM,OAAO,EAAE,MAAM,GAAG,GAAG;CAC3B,MAAM,QAAQ,EAAE,MAAM,GAAG;AACzB,KAAI,aAAa,KAAK,KAAK,MACzB,QAAO,IACL,oBACA,4BACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AAIxB,QAAO,GAHQ,EAAE,MAAM,GAAG,GAAG,GACd,EAAE,MAAM,IAAI,GAAG,CAEJ,GADZ,EAAE,MAAM,GAAG,CACU;;;AAIrC,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,SAAS,OAAO,aACpB,KAAK,UAAU,GAAG,GAAG,CACtB;EACD,MAAM,SAAS,aAAa,EAAE;AAC9B,OAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;GAC3B,MAAM,IAAI,SAAS,SAAS,OAAO,EAAE;AACrC,OAAI,SAAS,EAAE,CAAC,MAAO,QAAO,QAAQ,EAAE;;EAE1C,MAAM,KAAK,SAAS,SAAS;AAC7B,MAAI,SAAS,GAAG,CAAC,MAAO,QAAO,QAAQ,GAAG;;;;AAK9C,MAAM,OAAkB;CACtB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,QAAQ,QAAQ;CAC1B,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,GAAG,EAAE;CACf,UAAU,CAAC,YAAY,YAAY;CACnC,aACE;CAEF,WACE;CAEF;CACA;CACA;CACA;CACD"}