@stll/stdnum 1.0.0 → 2.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 (704) hide show
  1. package/dist/_checksums/luhn.js.map +1 -1
  2. package/dist/_checksums/mod1110.js +1 -1
  3. package/dist/_checksums/mod1110.js.map +1 -1
  4. package/dist/_checksums/mod112.js.map +1 -1
  5. package/dist/_checksums/mod97.js.map +1 -1
  6. package/dist/_checksums/verhoeff.js.map +1 -1
  7. package/dist/_checksums/weighted-sum.js.map +1 -1
  8. package/dist/_util/arabic.js.map +1 -1
  9. package/dist/_util/clean.js.map +1 -1
  10. package/dist/_util/date.js.map +1 -1
  11. package/dist/_util/generate.js.map +1 -1
  12. package/dist/_util/result.js.map +1 -1
  13. package/dist/_util/strings.js.map +1 -1
  14. package/dist/ad/nrt.d.ts +16 -2
  15. package/dist/ad/nrt.js +1 -14
  16. package/dist/ad/nrt.js.map +1 -1
  17. package/dist/ae/eid.d.ts +2 -2
  18. package/dist/ae/eid.js +2 -12
  19. package/dist/ae/eid.js.map +1 -1
  20. package/dist/ai/tin.d.ts +20 -2
  21. package/dist/ai/tin.js +1 -18
  22. package/dist/ai/tin.js.map +1 -1
  23. package/dist/al/nipt.d.ts +13 -2
  24. package/dist/al/nipt.js +1 -11
  25. package/dist/al/nipt.js.map +1 -1
  26. package/dist/am/tin.d.ts +16 -2
  27. package/dist/am/tin.js +1 -14
  28. package/dist/am/tin.js.map +1 -1
  29. package/dist/ar/cbu.d.ts +2 -2
  30. package/dist/ar/cbu.js +1 -9
  31. package/dist/ar/cbu.js.map +1 -1
  32. package/dist/ar/cuit.d.ts +2 -2
  33. package/dist/ar/cuit.js +1 -17
  34. package/dist/ar/cuit.js.map +1 -1
  35. package/dist/ar/dni.d.ts +11 -2
  36. package/dist/ar/dni.js +1 -9
  37. package/dist/ar/dni.js.map +1 -1
  38. package/dist/at/businessid.d.ts +10 -2
  39. package/dist/at/businessid.js +1 -8
  40. package/dist/at/businessid.js.map +1 -1
  41. package/dist/at/tin.d.ts +2 -2
  42. package/dist/at/tin.js +1 -11
  43. package/dist/at/tin.js.map +1 -1
  44. package/dist/at/uid.d.ts +2 -2
  45. package/dist/at/uid.js +2 -10
  46. package/dist/at/uid.js.map +1 -1
  47. package/dist/at/vnr.d.ts +2 -2
  48. package/dist/at/vnr.js +4 -14
  49. package/dist/at/vnr.js.map +1 -1
  50. package/dist/au/abn.d.ts +2 -2
  51. package/dist/au/abn.js +1 -10
  52. package/dist/au/abn.js.map +1 -1
  53. package/dist/au/acn.d.ts +2 -2
  54. package/dist/au/acn.js +1 -10
  55. package/dist/au/acn.js.map +1 -1
  56. package/dist/au/tfn.d.ts +2 -2
  57. package/dist/au/tfn.js +1 -10
  58. package/dist/au/tfn.js.map +1 -1
  59. package/dist/az/voen.d.ts +2 -2
  60. package/dist/az/voen.js +1 -14
  61. package/dist/az/voen.js.map +1 -1
  62. package/dist/ba/jmbg.d.ts +2 -2
  63. package/dist/ba/jmbg.js +3 -11
  64. package/dist/ba/jmbg.js.map +1 -1
  65. package/dist/bd/nid.d.ts +23 -2
  66. package/dist/bd/nid.js +1 -21
  67. package/dist/bd/nid.js.map +1 -1
  68. package/dist/be/bis.d.ts +2 -2
  69. package/dist/be/bis.js +1 -11
  70. package/dist/be/bis.js.map +1 -1
  71. package/dist/be/nn.d.ts +2 -2
  72. package/dist/be/nn.js +1 -11
  73. package/dist/be/nn.js.map +1 -1
  74. package/dist/be/vat.d.ts +2 -2
  75. package/dist/be/vat.js +1 -9
  76. package/dist/be/vat.js.map +1 -1
  77. package/dist/bg/egn.d.ts +2 -2
  78. package/dist/bg/egn.js +3 -18
  79. package/dist/bg/egn.js.map +1 -1
  80. package/dist/bg/pnf.d.ts +2 -2
  81. package/dist/bg/pnf.js +1 -8
  82. package/dist/bg/pnf.js.map +1 -1
  83. package/dist/bg/vat.d.ts +2 -2
  84. package/dist/bg/vat.js +3 -9
  85. package/dist/bg/vat.js.map +1 -1
  86. package/dist/bh/cpr.d.ts +2 -2
  87. package/dist/bh/cpr.js +1 -17
  88. package/dist/bh/cpr.js.map +1 -1
  89. package/dist/bic.d.ts +13 -2
  90. package/dist/bic.js +1 -11
  91. package/dist/bic.js.map +1 -1
  92. package/dist/br/cnpj.d.ts +2 -2
  93. package/dist/br/cnpj.js +1 -20
  94. package/dist/br/cnpj.js.map +1 -1
  95. package/dist/br/cpf.d.ts +2 -2
  96. package/dist/br/cpf.js +1 -14
  97. package/dist/br/cpf.js.map +1 -1
  98. package/dist/by/unp.d.ts +2 -2
  99. package/dist/by/unp.js +3 -14
  100. package/dist/by/unp.js.map +1 -1
  101. package/dist/bz/tin.d.ts +2 -2
  102. package/dist/bz/tin.js +1 -26
  103. package/dist/bz/tin.js.map +1 -1
  104. package/dist/ca/bn.d.ts +2 -2
  105. package/dist/ca/bn.js +2 -10
  106. package/dist/ca/bn.js.map +1 -1
  107. package/dist/ca/sin.d.ts +2 -2
  108. package/dist/ca/sin.js +2 -10
  109. package/dist/ca/sin.js.map +1 -1
  110. package/dist/ch/ssn.d.ts +2 -2
  111. package/dist/ch/ssn.js +1 -9
  112. package/dist/ch/ssn.js.map +1 -1
  113. package/dist/ch/uid.d.ts +2 -2
  114. package/dist/ch/uid.js +1 -9
  115. package/dist/ch/uid.js.map +1 -1
  116. package/dist/ch/vat.d.ts +2 -2
  117. package/dist/ch/vat.js +1 -9
  118. package/dist/ch/vat.js.map +1 -1
  119. package/dist/cl/rut.d.ts +2 -2
  120. package/dist/cl/rut.js +1 -14
  121. package/dist/cl/rut.js.map +1 -1
  122. package/dist/cn/ric.d.ts +2 -2
  123. package/dist/cn/ric.js +3 -14
  124. package/dist/cn/ric.js.map +1 -1
  125. package/dist/cn/uscc.d.ts +2 -2
  126. package/dist/cn/uscc.js +1 -10
  127. package/dist/cn/uscc.js.map +1 -1
  128. package/dist/co/nit.d.ts +2 -2
  129. package/dist/co/nit.js +2 -12
  130. package/dist/co/nit.js.map +1 -1
  131. package/dist/cr/cpf.d.ts +18 -2
  132. package/dist/cr/cpf.js +1 -16
  133. package/dist/cr/cpf.js.map +1 -1
  134. package/dist/creditcard.d.ts +2 -2
  135. package/dist/creditcard.js +5 -14
  136. package/dist/creditcard.js.map +1 -1
  137. package/dist/cu/ni.d.ts +2 -2
  138. package/dist/cu/ni.js +2 -17
  139. package/dist/cu/ni.js.map +1 -1
  140. package/dist/cy/vat.d.ts +2 -2
  141. package/dist/cy/vat.js +1 -8
  142. package/dist/cy/vat.js.map +1 -1
  143. package/dist/cz/dic.d.ts +2 -2
  144. package/dist/cz/dic.js +7 -13
  145. package/dist/cz/dic.js.map +1 -1
  146. package/dist/cz/ico.d.ts +2 -2
  147. package/dist/cz/ico.js +2 -10
  148. package/dist/cz/ico.js.map +1 -1
  149. package/dist/cz/rc.d.ts +2 -2
  150. package/dist/cz/rc.js +2 -26
  151. package/dist/cz/rc.js.map +1 -1
  152. package/dist/de/handelsreg.d.ts +19 -2
  153. package/dist/de/handelsreg.js +1 -17
  154. package/dist/de/handelsreg.js.map +1 -1
  155. package/dist/de/idnr.d.ts +2 -2
  156. package/dist/de/idnr.js +2 -12
  157. package/dist/de/idnr.js.map +1 -1
  158. package/dist/de/stnr.d.ts +17 -2
  159. package/dist/de/stnr.js +1 -15
  160. package/dist/de/stnr.js.map +1 -1
  161. package/dist/de/svnr.d.ts +2 -2
  162. package/dist/de/svnr.js +2 -11
  163. package/dist/de/svnr.js.map +1 -1
  164. package/dist/de/vat.d.ts +2 -2
  165. package/dist/de/vat.js +2 -11
  166. package/dist/de/vat.js.map +1 -1
  167. package/dist/dk/cpr.d.ts +2 -2
  168. package/dist/dk/cpr.js +2 -10
  169. package/dist/dk/cpr.js.map +1 -1
  170. package/dist/dk/cvr.d.ts +2 -2
  171. package/dist/dk/cvr.js +2 -15
  172. package/dist/dk/cvr.js.map +1 -1
  173. package/dist/dk/vat.d.ts +2 -2
  174. package/dist/dk/vat.js +3 -13
  175. package/dist/dk/vat.js.map +1 -1
  176. package/dist/do/rnc.d.ts +2 -2
  177. package/dist/do/rnc.js +2 -16
  178. package/dist/do/rnc.js.map +1 -1
  179. package/dist/ec/ruc.d.ts +2 -2
  180. package/dist/ec/ruc.js +1 -18
  181. package/dist/ec/ruc.js.map +1 -1
  182. package/dist/ee/ik.d.ts +2 -2
  183. package/dist/ee/ik.js +3 -20
  184. package/dist/ee/ik.js.map +1 -1
  185. package/dist/ee/registrikood.d.ts +2 -2
  186. package/dist/ee/registrikood.js +1 -8
  187. package/dist/ee/registrikood.js.map +1 -1
  188. package/dist/ee/vat.d.ts +2 -2
  189. package/dist/ee/vat.js +2 -10
  190. package/dist/ee/vat.js.map +1 -1
  191. package/dist/eg/tn.d.ts +11 -2
  192. package/dist/eg/tn.js +1 -9
  193. package/dist/eg/tn.js.map +1 -1
  194. package/dist/es/cif.d.ts +2 -2
  195. package/dist/es/cif.js +1 -10
  196. package/dist/es/cif.js.map +1 -1
  197. package/dist/es/dni.d.ts +2 -2
  198. package/dist/es/dni.js +1 -9
  199. package/dist/es/dni.js.map +1 -1
  200. package/dist/es/nie.d.ts +2 -2
  201. package/dist/es/nie.js +1 -9
  202. package/dist/es/nie.js.map +1 -1
  203. package/dist/es/nss.d.ts +2 -2
  204. package/dist/es/nss.js +1 -16
  205. package/dist/es/nss.js.map +1 -1
  206. package/dist/es/vat.d.ts +2 -2
  207. package/dist/es/vat.js +5 -10
  208. package/dist/es/vat.js.map +1 -1
  209. package/dist/eu/vat.d.ts +2 -2
  210. package/dist/eu/vat.js +1 -0
  211. package/dist/eu/vat.js.map +1 -1
  212. package/dist/fi/hetu.d.ts +2 -2
  213. package/dist/fi/hetu.js +2 -10
  214. package/dist/fi/hetu.js.map +1 -1
  215. package/dist/fi/vat.d.ts +2 -2
  216. package/dist/fi/vat.js +3 -10
  217. package/dist/fi/vat.js.map +1 -1
  218. package/dist/fi/ytunnus.d.ts +2 -2
  219. package/dist/fi/ytunnus.js +2 -10
  220. package/dist/fi/ytunnus.js.map +1 -1
  221. package/dist/fr/nif.d.ts +2 -2
  222. package/dist/fr/nif.js +1 -9
  223. package/dist/fr/nif.js.map +1 -1
  224. package/dist/fr/nir.d.ts +2 -2
  225. package/dist/fr/nir.js +2 -14
  226. package/dist/fr/nir.js.map +1 -1
  227. package/dist/fr/siren.d.ts +2 -2
  228. package/dist/fr/siren.js +2 -10
  229. package/dist/fr/siren.js.map +1 -1
  230. package/dist/fr/siret.d.ts +2 -2
  231. package/dist/fr/siret.js +2 -11
  232. package/dist/fr/siret.js.map +1 -1
  233. package/dist/fr/tva.d.ts +2 -2
  234. package/dist/fr/tva.js +2 -12
  235. package/dist/fr/tva.js.map +1 -1
  236. package/dist/gb/nino.d.ts +12 -2
  237. package/dist/gb/nino.js +1 -10
  238. package/dist/gb/nino.js.map +1 -1
  239. package/dist/gb/sedol.d.ts +2 -2
  240. package/dist/gb/sedol.js +1 -11
  241. package/dist/gb/sedol.js.map +1 -1
  242. package/dist/gb/utr.d.ts +2 -2
  243. package/dist/gb/utr.js +2 -10
  244. package/dist/gb/utr.js.map +1 -1
  245. package/dist/gb/vat.d.ts +2 -2
  246. package/dist/gb/vat.js +2 -11
  247. package/dist/gb/vat.js.map +1 -1
  248. package/dist/ge/pin.d.ts +14 -2
  249. package/dist/ge/pin.js +1 -12
  250. package/dist/ge/pin.js.map +1 -1
  251. package/dist/gh/tin.d.ts +2 -2
  252. package/dist/gh/tin.js +1 -15
  253. package/dist/gh/tin.js.map +1 -1
  254. package/dist/gr/amka.d.ts +2 -2
  255. package/dist/gr/amka.js +3 -11
  256. package/dist/gr/amka.js.map +1 -1
  257. package/dist/gr/vat.d.ts +2 -2
  258. package/dist/gr/vat.js +1 -10
  259. package/dist/gr/vat.js.map +1 -1
  260. package/dist/gt/nit.d.ts +2 -2
  261. package/dist/gt/nit.js +1 -12
  262. package/dist/gt/nit.js.map +1 -1
  263. package/dist/hk/hkid.d.ts +2 -2
  264. package/dist/hk/hkid.js +1 -10
  265. package/dist/hk/hkid.js.map +1 -1
  266. package/dist/hr/vat.d.ts +2 -2
  267. package/dist/hr/vat.js +2 -9
  268. package/dist/hr/vat.js.map +1 -1
  269. package/dist/hu/vat.d.ts +2 -2
  270. package/dist/hu/vat.js +3 -10
  271. package/dist/hu/vat.js.map +1 -1
  272. package/dist/iban.d.ts +2 -2
  273. package/dist/iban.js +2 -8
  274. package/dist/iban.js.map +1 -1
  275. package/dist/id/npwp.d.ts +2 -2
  276. package/dist/id/npwp.js +3 -13
  277. package/dist/id/npwp.js.map +1 -1
  278. package/dist/ie/pps.d.ts +2 -2
  279. package/dist/ie/pps.js +1 -10
  280. package/dist/ie/pps.js.map +1 -1
  281. package/dist/ie/vat.d.ts +2 -2
  282. package/dist/ie/vat.js +1 -9
  283. package/dist/ie/vat.js.map +1 -1
  284. package/dist/il/idnr.d.ts +2 -2
  285. package/dist/il/idnr.js +2 -9
  286. package/dist/il/idnr.js.map +1 -1
  287. package/dist/in/aadhaar.d.ts +2 -2
  288. package/dist/in/aadhaar.js +2 -12
  289. package/dist/in/aadhaar.js.map +1 -1
  290. package/dist/in/gstin.d.ts +2 -2
  291. package/dist/in/gstin.js +1 -10
  292. package/dist/in/gstin.js.map +1 -1
  293. package/dist/in/pan.d.ts +15 -2
  294. package/dist/in/pan.js +1 -13
  295. package/dist/in/pan.js.map +1 -1
  296. package/dist/index.d.ts +2 -2
  297. package/dist/index.js +6 -6
  298. package/dist/iq/nid.d.ts +16 -2
  299. package/dist/iq/nid.js +2 -15
  300. package/dist/iq/nid.js.map +1 -1
  301. package/dist/ir/nid.d.ts +2 -2
  302. package/dist/ir/nid.js +2 -24
  303. package/dist/ir/nid.js.map +1 -1
  304. package/dist/is/kennitala.d.ts +2 -2
  305. package/dist/is/kennitala.js +2 -13
  306. package/dist/is/kennitala.js.map +1 -1
  307. package/dist/is/vsk.d.ts +9 -2
  308. package/dist/is/vsk.js +1 -7
  309. package/dist/is/vsk.js.map +1 -1
  310. package/dist/isin.d.ts +2 -2
  311. package/dist/isin.js +2 -12
  312. package/dist/isin.js.map +1 -1
  313. package/dist/it/codicefiscale.d.ts +2 -2
  314. package/dist/it/codicefiscale.js +1 -21
  315. package/dist/it/codicefiscale.js.map +1 -1
  316. package/dist/it/iva.d.ts +2 -2
  317. package/dist/it/iva.js +2 -9
  318. package/dist/it/iva.js.map +1 -1
  319. package/dist/jp/cn.d.ts +2 -2
  320. package/dist/jp/cn.js +1 -9
  321. package/dist/jp/cn.js.map +1 -1
  322. package/dist/jp/mynumber.d.ts +2 -2
  323. package/dist/jp/mynumber.js +1 -10
  324. package/dist/jp/mynumber.js.map +1 -1
  325. package/dist/kr/brn.d.ts +11 -2
  326. package/dist/kr/brn.js +1 -9
  327. package/dist/kr/brn.js.map +1 -1
  328. package/dist/kr/rrn.d.ts +2 -2
  329. package/dist/kr/rrn.js +2 -11
  330. package/dist/kr/rrn.js.map +1 -1
  331. package/dist/kw/civil.d.ts +2 -2
  332. package/dist/kw/civil.js +2 -14
  333. package/dist/kw/civil.js.map +1 -1
  334. package/dist/kz/iin.d.ts +2 -2
  335. package/dist/kz/iin.js +3 -18
  336. package/dist/kz/iin.js.map +1 -1
  337. package/dist/lei.d.ts +2 -2
  338. package/dist/lei.js +2 -11
  339. package/dist/lei.js.map +1 -1
  340. package/dist/li/peid.d.ts +11 -2
  341. package/dist/li/peid.js +1 -9
  342. package/dist/li/peid.js.map +1 -1
  343. package/dist/lk/nic.d.ts +2 -2
  344. package/dist/lk/nic.js +2 -14
  345. package/dist/lk/nic.js.map +1 -1
  346. package/dist/lt/asmens.d.ts +2 -2
  347. package/dist/lt/asmens.js +2 -1
  348. package/dist/lt/asmens.js.map +1 -1
  349. package/dist/lt/vat.d.ts +2 -2
  350. package/dist/lt/vat.js +2 -10
  351. package/dist/lt/vat.js.map +1 -1
  352. package/dist/lu/vat.d.ts +2 -2
  353. package/dist/lu/vat.js +2 -8
  354. package/dist/lu/vat.js.map +1 -1
  355. package/dist/luhn.d.ts +2 -2
  356. package/dist/luhn.js +2 -9
  357. package/dist/luhn.js.map +1 -1
  358. package/dist/lv/vat.d.ts +2 -2
  359. package/dist/lv/vat.js +2 -28
  360. package/dist/lv/vat.js.map +1 -1
  361. package/dist/ma/ice.d.ts +2 -2
  362. package/dist/ma/ice.js +2 -11
  363. package/dist/ma/ice.js.map +1 -1
  364. package/dist/mc/tva.d.ts +2 -2
  365. package/dist/mc/tva.js +1 -0
  366. package/dist/mc/tva.js.map +1 -1
  367. package/dist/md/idno.d.ts +2 -2
  368. package/dist/md/idno.js +1 -10
  369. package/dist/md/idno.js.map +1 -1
  370. package/dist/me/pib.d.ts +2 -2
  371. package/dist/me/pib.js +2 -10
  372. package/dist/me/pib.js.map +1 -1
  373. package/dist/mk/edb.d.ts +2 -2
  374. package/dist/mk/edb.js +2 -11
  375. package/dist/mk/edb.js.map +1 -1
  376. package/dist/mt/vat.d.ts +2 -2
  377. package/dist/mt/vat.js +3 -10
  378. package/dist/mt/vat.js.map +1 -1
  379. package/dist/mu/brn.d.ts +23 -2
  380. package/dist/mu/brn.js +1 -21
  381. package/dist/mu/brn.js.map +1 -1
  382. package/dist/mx/clabe.d.ts +2 -2
  383. package/dist/mx/clabe.js +1 -14
  384. package/dist/mx/clabe.js.map +1 -1
  385. package/dist/mx/curp.d.ts +2 -2
  386. package/dist/mx/curp.js +3 -17
  387. package/dist/mx/curp.js.map +1 -1
  388. package/dist/mx/rfc.d.ts +2 -2
  389. package/dist/mx/rfc.js +3 -19
  390. package/dist/mx/rfc.js.map +1 -1
  391. package/dist/my/nric.d.ts +2 -2
  392. package/dist/my/nric.js +2 -14
  393. package/dist/my/nric.js.map +1 -1
  394. package/dist/ng/nin.d.ts +13 -2
  395. package/dist/ng/nin.js +1 -11
  396. package/dist/ng/nin.js.map +1 -1
  397. package/dist/ni/ruc.d.ts +2 -2
  398. package/dist/ni/ruc.js +1 -23
  399. package/dist/ni/ruc.js.map +1 -1
  400. package/dist/nl/bsn.d.ts +2 -2
  401. package/dist/nl/bsn.js +2 -10
  402. package/dist/nl/bsn.js.map +1 -1
  403. package/dist/nl/kvk.d.ts +9 -2
  404. package/dist/nl/kvk.js +1 -7
  405. package/dist/nl/kvk.js.map +1 -1
  406. package/dist/nl/vat.d.ts +2 -2
  407. package/dist/nl/vat.js +1 -13
  408. package/dist/nl/vat.js.map +1 -1
  409. package/dist/no/fodselsnummer.d.ts +2 -2
  410. package/dist/no/fodselsnummer.js +2 -10
  411. package/dist/no/fodselsnummer.js.map +1 -1
  412. package/dist/no/mva.d.ts +2 -2
  413. package/dist/no/mva.js +1 -8
  414. package/dist/no/mva.js.map +1 -1
  415. package/dist/no/orgnr.d.ts +2 -2
  416. package/dist/no/orgnr.js +2 -8
  417. package/dist/no/orgnr.js.map +1 -1
  418. package/dist/nz/ird.d.ts +2 -2
  419. package/dist/nz/ird.js +2 -11
  420. package/dist/nz/ird.js.map +1 -1
  421. package/dist/pa/ruc.d.ts +2 -2
  422. package/dist/pa/ruc.js +1 -18
  423. package/dist/pa/ruc.js.map +1 -1
  424. package/dist/patterns.d.ts +8 -7
  425. package/dist/patterns.js +3 -5
  426. package/dist/patterns.js.map +1 -1
  427. package/dist/pe/ruc.d.ts +2 -2
  428. package/dist/pe/ruc.js +1 -15
  429. package/dist/pe/ruc.js.map +1 -1
  430. package/dist/ph/philid.d.ts +14 -2
  431. package/dist/ph/philid.js +1 -12
  432. package/dist/ph/philid.js.map +1 -1
  433. package/dist/pk/cnic.d.ts +14 -2
  434. package/dist/pk/cnic.js +1 -12
  435. package/dist/pk/cnic.js.map +1 -1
  436. package/dist/pl/nip.d.ts +2 -2
  437. package/dist/pl/nip.js +2 -10
  438. package/dist/pl/nip.js.map +1 -1
  439. package/dist/pl/pesel.d.ts +2 -2
  440. package/dist/pl/pesel.js +3 -13
  441. package/dist/pl/pesel.js.map +1 -1
  442. package/dist/pl/regon.d.ts +2 -2
  443. package/dist/pl/regon.js +2 -11
  444. package/dist/pl/regon.js.map +1 -1
  445. package/dist/pt/cc.d.ts +2 -2
  446. package/dist/pt/cc.js +1 -9
  447. package/dist/pt/cc.js.map +1 -1
  448. package/dist/pt/vat.d.ts +2 -2
  449. package/dist/pt/vat.js +3 -11
  450. package/dist/pt/vat.js.map +1 -1
  451. package/dist/ro/cnp.d.ts +2 -2
  452. package/dist/ro/cnp.js +4 -14
  453. package/dist/ro/cnp.js.map +1 -1
  454. package/dist/ro/vat.d.ts +2 -2
  455. package/dist/ro/vat.js +13 -11
  456. package/dist/ro/vat.js.map +1 -1
  457. package/dist/rs/pib.d.ts +2 -2
  458. package/dist/rs/pib.js +1 -9
  459. package/dist/rs/pib.js.map +1 -1
  460. package/dist/ru/inn.d.ts +2 -2
  461. package/dist/ru/inn.js +1 -11
  462. package/dist/ru/inn.js.map +1 -1
  463. package/dist/se/orgnr.d.ts +2 -2
  464. package/dist/se/orgnr.js +2 -9
  465. package/dist/se/orgnr.js.map +1 -1
  466. package/dist/se/personnummer.d.ts +2 -2
  467. package/dist/se/personnummer.js +7 -15
  468. package/dist/se/personnummer.js.map +1 -1
  469. package/dist/se/vat.d.ts +2 -2
  470. package/dist/se/vat.js +3 -10
  471. package/dist/se/vat.js.map +1 -1
  472. package/dist/sg/uen.d.ts +2 -2
  473. package/dist/sg/uen.js +1 -15
  474. package/dist/sg/uen.js.map +1 -1
  475. package/dist/si/emso.d.ts +2 -2
  476. package/dist/si/emso.js +3 -18
  477. package/dist/si/emso.js.map +1 -1
  478. package/dist/si/vat.d.ts +2 -2
  479. package/dist/si/vat.js +3 -12
  480. package/dist/si/vat.js.map +1 -1
  481. package/dist/sk/dic.d.ts +2 -2
  482. package/dist/sk/dic.js +1 -0
  483. package/dist/sk/dic.js.map +1 -1
  484. package/dist/sk/ico.d.ts +2 -2
  485. package/dist/sk/ico.js +1 -0
  486. package/dist/sk/ico.js.map +1 -1
  487. package/dist/sk/rc.d.ts +2 -2
  488. package/dist/sk/rc.js +1 -0
  489. package/dist/sk/rc.js.map +1 -1
  490. package/dist/th/tin.d.ts +2 -2
  491. package/dist/th/tin.js +1 -11
  492. package/dist/th/tin.js.map +1 -1
  493. package/dist/tr/tckimlik.d.ts +2 -2
  494. package/dist/tr/tckimlik.js +1 -20
  495. package/dist/tr/tckimlik.js.map +1 -1
  496. package/dist/tr/vkn.d.ts +2 -2
  497. package/dist/tr/vkn.js +1 -20
  498. package/dist/tr/vkn.js.map +1 -1
  499. package/dist/tw/ubn.d.ts +2 -2
  500. package/dist/tw/ubn.js +1 -11
  501. package/dist/tw/ubn.js.map +1 -1
  502. package/dist/types.d.ts +26 -4
  503. package/dist/ua/edrpou.d.ts +2 -2
  504. package/dist/ua/edrpou.js +1 -11
  505. package/dist/ua/edrpou.js.map +1 -1
  506. package/dist/us/ein.d.ts +12 -2
  507. package/dist/us/ein.js +1 -10
  508. package/dist/us/ein.js.map +1 -1
  509. package/dist/us/itin.d.ts +13 -2
  510. package/dist/us/itin.js +1 -11
  511. package/dist/us/itin.js.map +1 -1
  512. package/dist/us/rtn.d.ts +2 -2
  513. package/dist/us/rtn.js +3 -18
  514. package/dist/us/rtn.js.map +1 -1
  515. package/dist/us/ssn.d.ts +13 -2
  516. package/dist/us/ssn.js +1 -11
  517. package/dist/us/ssn.js.map +1 -1
  518. package/dist/uy/rut.d.ts +2 -2
  519. package/dist/uy/rut.js +1 -14
  520. package/dist/uy/rut.js.map +1 -1
  521. package/dist/ve/rif.d.ts +2 -2
  522. package/dist/ve/rif.js +2 -15
  523. package/dist/ve/rif.js.map +1 -1
  524. package/dist/vn/mst.d.ts +2 -2
  525. package/dist/vn/mst.js +1 -12
  526. package/dist/vn/mst.js.map +1 -1
  527. package/dist/za/idnr.d.ts +2 -2
  528. package/dist/za/idnr.js +3 -16
  529. package/dist/za/idnr.js.map +1 -1
  530. package/package.json +22 -12
  531. package/src/_checksums/mod1110.ts +1 -1
  532. package/src/ad/nrt.ts +7 -3
  533. package/src/ae/eid.ts +7 -3
  534. package/src/ai/tin.ts +7 -3
  535. package/src/al/nipt.ts +7 -3
  536. package/src/am/tin.ts +7 -3
  537. package/src/ar/cbu.ts +7 -3
  538. package/src/ar/cuit.ts +7 -3
  539. package/src/ar/dni.ts +7 -3
  540. package/src/at/businessid.ts +7 -3
  541. package/src/at/tin.ts +7 -3
  542. package/src/at/uid.ts +7 -3
  543. package/src/at/vnr.ts +37 -9
  544. package/src/au/abn.ts +7 -3
  545. package/src/au/acn.ts +7 -3
  546. package/src/au/tfn.ts +7 -3
  547. package/src/az/voen.ts +7 -3
  548. package/src/ba/jmbg.ts +8 -7
  549. package/src/bd/nid.ts +7 -3
  550. package/src/be/bis.ts +8 -4
  551. package/src/be/nn.ts +7 -3
  552. package/src/be/vat.ts +7 -3
  553. package/src/bg/egn.ts +8 -7
  554. package/src/bg/pnf.ts +7 -3
  555. package/src/bg/vat.ts +8 -3
  556. package/src/bh/cpr.ts +7 -3
  557. package/src/bic.ts +7 -3
  558. package/src/br/cnpj.ts +7 -3
  559. package/src/br/cpf.ts +7 -3
  560. package/src/by/unp.ts +10 -5
  561. package/src/bz/tin.ts +7 -3
  562. package/src/ca/bn.ts +7 -3
  563. package/src/ca/sin.ts +7 -3
  564. package/src/ch/ssn.ts +7 -3
  565. package/src/ch/uid.ts +7 -3
  566. package/src/ch/vat.ts +9 -5
  567. package/src/cl/rut.ts +7 -3
  568. package/src/cn/ric.ts +8 -7
  569. package/src/cn/uscc.ts +7 -3
  570. package/src/co/nit.ts +8 -4
  571. package/src/cr/cpf.ts +7 -3
  572. package/src/creditcard.ts +10 -6
  573. package/src/cu/ni.ts +8 -7
  574. package/src/cy/vat.ts +7 -3
  575. package/src/cz/dic.ts +9 -4
  576. package/src/cz/ico.ts +7 -3
  577. package/src/cz/rc.ts +8 -7
  578. package/src/de/handelsreg.ts +7 -3
  579. package/src/de/idnr.ts +7 -3
  580. package/src/de/stnr.ts +7 -3
  581. package/src/de/svnr.ts +7 -3
  582. package/src/de/vat.ts +7 -3
  583. package/src/dk/cpr.ts +8 -7
  584. package/src/dk/cvr.ts +7 -3
  585. package/src/dk/vat.ts +8 -3
  586. package/src/do/rnc.ts +7 -3
  587. package/src/ec/ruc.ts +7 -3
  588. package/src/ee/ik.ts +8 -7
  589. package/src/ee/registrikood.ts +8 -4
  590. package/src/ee/vat.ts +7 -3
  591. package/src/eg/tn.ts +7 -3
  592. package/src/es/cif.ts +8 -4
  593. package/src/es/dni.ts +7 -3
  594. package/src/es/nie.ts +8 -4
  595. package/src/es/nss.ts +7 -3
  596. package/src/es/vat.ts +13 -5
  597. package/src/eu/vat.ts +10 -6
  598. package/src/fi/hetu.ts +8 -7
  599. package/src/fi/vat.ts +8 -3
  600. package/src/fi/ytunnus.ts +7 -3
  601. package/src/fr/nif.ts +7 -3
  602. package/src/fr/nir.ts +8 -7
  603. package/src/fr/siren.ts +7 -3
  604. package/src/fr/siret.ts +7 -3
  605. package/src/fr/tva.ts +7 -3
  606. package/src/gb/nino.ts +7 -3
  607. package/src/gb/sedol.ts +7 -3
  608. package/src/gb/utr.ts +7 -3
  609. package/src/gb/vat.ts +7 -3
  610. package/src/ge/pin.ts +7 -3
  611. package/src/gh/tin.ts +7 -3
  612. package/src/gr/amka.ts +7 -3
  613. package/src/gr/vat.ts +7 -3
  614. package/src/gt/nit.ts +7 -3
  615. package/src/hk/hkid.ts +7 -3
  616. package/src/hr/vat.ts +7 -3
  617. package/src/hu/vat.ts +8 -3
  618. package/src/iban.ts +7 -3
  619. package/src/id/npwp.ts +7 -3
  620. package/src/ie/pps.ts +7 -3
  621. package/src/ie/vat.ts +7 -3
  622. package/src/il/idnr.ts +7 -3
  623. package/src/in/aadhaar.ts +7 -3
  624. package/src/in/gstin.ts +7 -3
  625. package/src/in/pan.ts +7 -3
  626. package/src/index.ts +3 -0
  627. package/src/iq/nid.ts +7 -3
  628. package/src/ir/nid.ts +7 -3
  629. package/src/is/kennitala.ts +7 -3
  630. package/src/is/vsk.ts +7 -3
  631. package/src/isin.ts +7 -3
  632. package/src/it/codicefiscale.ts +11 -7
  633. package/src/it/iva.ts +7 -3
  634. package/src/jp/cn.ts +7 -3
  635. package/src/jp/mynumber.ts +7 -3
  636. package/src/kr/brn.ts +7 -3
  637. package/src/kr/rrn.ts +8 -7
  638. package/src/kw/civil.ts +8 -7
  639. package/src/kz/iin.ts +8 -8
  640. package/src/lei.ts +7 -3
  641. package/src/li/peid.ts +7 -3
  642. package/src/lk/nic.ts +8 -7
  643. package/src/lt/asmens.ts +8 -4
  644. package/src/lt/vat.ts +8 -3
  645. package/src/lu/vat.ts +8 -3
  646. package/src/luhn.ts +7 -3
  647. package/src/lv/vat.ts +7 -3
  648. package/src/ma/ice.ts +7 -3
  649. package/src/mc/tva.ts +9 -5
  650. package/src/md/idno.ts +7 -3
  651. package/src/me/pib.ts +7 -3
  652. package/src/mk/edb.ts +7 -3
  653. package/src/mt/vat.ts +8 -3
  654. package/src/mu/brn.ts +7 -3
  655. package/src/mx/clabe.ts +7 -3
  656. package/src/mx/curp.ts +9 -8
  657. package/src/mx/rfc.ts +8 -4
  658. package/src/my/nric.ts +8 -7
  659. package/src/ng/nin.ts +7 -3
  660. package/src/ni/ruc.ts +7 -3
  661. package/src/nl/bsn.ts +7 -3
  662. package/src/nl/kvk.ts +7 -3
  663. package/src/nl/vat.ts +7 -3
  664. package/src/no/fodselsnummer.ts +11 -7
  665. package/src/no/mva.ts +9 -5
  666. package/src/no/orgnr.ts +7 -3
  667. package/src/nz/ird.ts +8 -4
  668. package/src/pa/ruc.ts +7 -3
  669. package/src/patterns.ts +49 -18
  670. package/src/pe/ruc.ts +7 -3
  671. package/src/ph/philid.ts +7 -3
  672. package/src/pk/cnic.ts +7 -3
  673. package/src/pl/nip.ts +7 -3
  674. package/src/pl/pesel.ts +8 -7
  675. package/src/pl/regon.ts +7 -3
  676. package/src/pt/cc.ts +7 -3
  677. package/src/pt/vat.ts +8 -3
  678. package/src/ro/cnp.ts +15 -8
  679. package/src/ro/vat.ts +8 -3
  680. package/src/rs/pib.ts +7 -3
  681. package/src/ru/inn.ts +7 -3
  682. package/src/se/orgnr.ts +7 -3
  683. package/src/se/personnummer.ts +35 -33
  684. package/src/se/vat.ts +8 -3
  685. package/src/sg/uen.ts +7 -3
  686. package/src/si/emso.ts +8 -7
  687. package/src/si/vat.ts +8 -3
  688. package/src/sk/dic.ts +8 -4
  689. package/src/sk/ico.ts +3 -2
  690. package/src/sk/rc.ts +6 -2
  691. package/src/th/tin.ts +7 -3
  692. package/src/tr/tckimlik.ts +7 -3
  693. package/src/tr/vkn.ts +7 -3
  694. package/src/tw/ubn.ts +7 -3
  695. package/src/types.ts +34 -3
  696. package/src/ua/edrpou.ts +7 -3
  697. package/src/us/ein.ts +7 -3
  698. package/src/us/itin.ts +7 -3
  699. package/src/us/rtn.ts +16 -8
  700. package/src/us/ssn.ts +7 -3
  701. package/src/uy/rut.ts +7 -3
  702. package/src/ve/rif.ts +8 -6
  703. package/src/vn/mst.ts +7 -3
  704. package/src/za/idnr.ts +8 -7
package/dist/mu/brn.js CHANGED
@@ -2,27 +2,6 @@ import { clean } from "../_util/clean.js";
2
2
  import { randomDigits, randomInt } from "../_util/generate.js";
3
3
  import { err } from "../_util/result.js";
4
4
  //#region src/mu/brn.ts
5
- /**
6
- * BRN (Business Registration Number, Mauritius).
7
- *
8
- * Issued by the Corporate and Business Registration
9
- * Department (CBRD). Used to identify entities and
10
- * individuals carrying out business activities.
11
- *
12
- * Entity BRN: 1 letter prefix + 8 digits (9 chars).
13
- * - Letter indicates entity type (e.g. C = company,
14
- * F = foreign company).
15
- * - Digits 2-3 encode the registration year
16
- * (e.g. 07 = 2007).
17
- * - Digits 4-9 are a sequential number.
18
- *
19
- * Individual BRN: 8 digits, first digit 0-3.
20
- *
21
- * No public check digit algorithm is documented.
22
- *
23
- * @see https://companies.govmu.org/
24
- * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/mauritius-tin.pdf
25
- */
26
5
  /** Generate a random valid Mauritius BRN (entity). */
27
6
  const generate = () => {
28
7
  return `${String.fromCodePoint(65 + randomInt(0, 25))}${randomDigits(8)}`;
@@ -51,6 +30,7 @@ const brn = {
51
30
  abbreviation: "BRN",
52
31
  aliases: ["BRN", "Business Registration Number"],
53
32
  candidatePattern: "[A-Z]\\d{8}",
33
+ scope: "country",
54
34
  country: "MU",
55
35
  entityType: "any",
56
36
  compact,
@@ -1 +1 @@
1
- {"version":3,"file":"brn.js","names":[],"sources":["../../src/mu/brn.ts"],"sourcesContent":["/** Generate a random valid Mauritius BRN (entity). */\nconst generate = (): string => {\n const letter = String.fromCodePoint(\n 65 + randomInt(0, 25),\n );\n const digits = randomDigits(8);\n return `${letter}${digits}`;\n};\n\n/**\n * BRN (Business Registration Number, Mauritius).\n *\n * Issued by the Corporate and Business Registration\n * Department (CBRD). Used to identify entities and\n * individuals carrying out business activities.\n *\n * Entity BRN: 1 letter prefix + 8 digits (9 chars).\n * - Letter indicates entity type (e.g. C = company,\n * F = foreign company).\n * - Digits 2-3 encode the registration year\n * (e.g. 07 = 2007).\n * - Digits 4-9 are a sequential number.\n *\n * Individual BRN: 8 digits, first digit 0-3.\n *\n * No public check digit algorithm is documented.\n *\n * @see https://companies.govmu.org/\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/mauritius-tin.pdf\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/** Entity BRN: letter + 8 digits. */\nconst ENTITY_RE = /^[A-Z]\\d{8}$/;\n\n/** Individual BRN: 8 digits, starts with 0-3. */\nconst INDIVIDUAL_RE = /^[0-3]\\d{7}$/;\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 !== 8 && v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"Mauritius BRN must be 8 or 9 characters\",\n );\n }\n\n if (v.length === 9) {\n if (!ENTITY_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Mauritius entity BRN must be \" +\n \"1 letter followed by 8 digits\",\n );\n }\n } else {\n if (!INDIVIDUAL_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Mauritius individual BRN must be \" +\n \"8 digits starting with 0-3\",\n );\n }\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Mauritius Business Registration Number. */\nconst brn: Validator = {\n name: \"Mauritius Business Registration Number\",\n localName: \"Business Registration Number\",\n abbreviation: \"BRN\",\n aliases: [\"BRN\", \"Business Registration Number\"] as const,\n candidatePattern: \"[A-Z]\\\\d{8}\",\n country: \"MU\",\n entityType: \"any\",\n compact,\n format,\n validate,\n description:\n \"Mauritius business registration number \" +\n \"issued by the CBRD\",\n sourceUrl: \"https://companies.govmu.org/\",\n lengths: [8, 9] as const,\n examples: [\"C07015330\", \"C16135302\"] as const,\n generate,\n};\n\nexport default brn;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AACA,MAAM,iBAAyB;AAK7B,QAAO,GAJQ,OAAO,cACpB,KAAK,UAAU,GAAG,GAAG,CACtB,GACc,aAAa,EAAE;;;AAiChC,MAAM,YAAY;;AAGlB,MAAM,gBAAgB;AAEtB,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,CAAC,aAAa;AAEnC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,WAAW,KAAK,EAAE,WAAW,EACjC,QAAO,IACL,kBACA,0CACD;AAGH,KAAI,EAAE,WAAW;MACX,CAAC,UAAU,KAAK,EAAE,CACpB,QAAO,IACL,kBACA,6DAED;YAGC,CAAC,cAAc,KAAK,EAAE,CACxB,QAAO,IACL,kBACA,8DAED;AAIL,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,+BAA+B;CAChD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ;CACA;CACA;CACA,aACE;CAEF,WAAW;CACX,SAAS,CAAC,GAAG,EAAE;CACf,UAAU,CAAC,aAAa,YAAY;CACpC;CACD"}
1
+ {"version":3,"file":"brn.js","names":[],"sources":["../../src/mu/brn.ts"],"sourcesContent":["/** Generate a random valid Mauritius BRN (entity). */\nconst generate = (): string => {\n const letter = String.fromCodePoint(\n 65 + randomInt(0, 25),\n );\n const digits = randomDigits(8);\n return `${letter}${digits}`;\n};\n\n/**\n * BRN (Business Registration Number, Mauritius).\n *\n * Issued by the Corporate and Business Registration\n * Department (CBRD). Used to identify entities and\n * individuals carrying out business activities.\n *\n * Entity BRN: 1 letter prefix + 8 digits (9 chars).\n * - Letter indicates entity type (e.g. C = company,\n * F = foreign company).\n * - Digits 2-3 encode the registration year\n * (e.g. 07 = 2007).\n * - Digits 4-9 are a sequential number.\n *\n * Individual BRN: 8 digits, first digit 0-3.\n *\n * No public check digit algorithm is documented.\n *\n * @see https://companies.govmu.org/\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/mauritius-tin.pdf\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\n/** Entity BRN: letter + 8 digits. */\nconst ENTITY_RE = /^[A-Z]\\d{8}$/;\n\n/** Individual BRN: 8 digits, starts with 0-3. */\nconst INDIVIDUAL_RE = /^[0-3]\\d{7}$/;\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 !== 8 && v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"Mauritius BRN must be 8 or 9 characters\",\n );\n }\n\n if (v.length === 9) {\n if (!ENTITY_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Mauritius entity BRN must be \" +\n \"1 letter followed by 8 digits\",\n );\n }\n } else {\n if (!INDIVIDUAL_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Mauritius individual BRN must be \" +\n \"8 digits starting with 0-3\",\n );\n }\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Mauritius Business Registration Number. */\nconst brn: CountryValidator<\"MU\"> = {\n name: \"Mauritius Business Registration Number\",\n localName: \"Business Registration Number\",\n abbreviation: \"BRN\",\n aliases: [\"BRN\", \"Business Registration Number\"] as const,\n candidatePattern: \"[A-Z]\\\\d{8}\",\n scope: \"country\",\n country: \"MU\",\n entityType: \"any\",\n compact,\n format,\n validate,\n description:\n \"Mauritius business registration number \" +\n \"issued by the CBRD\",\n sourceUrl: \"https://companies.govmu.org/\",\n lengths: [8, 9] as const,\n examples: [\"C07015330\", \"C16135302\"] as const,\n generate,\n};\n\nexport default brn;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AACA,MAAM,iBAAyB;CAK7B,OAAO,GAJQ,OAAO,cACpB,KAAK,UAAU,GAAG,EAAE,CAGP,IADA,aAAa,CACJ;AAC1B;;AAkCA,MAAM,YAAY;;AAGlB,MAAM,gBAAgB;AAEtB,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,EAAE,YAAY;AAElC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,OAAO,IACL,kBACA,yCACF;CAGF,IAAI,EAAE,WAAW;MACX,CAAC,UAAU,KAAK,CAAC,GACnB,OAAO,IACL,kBACA,4DAEF;CAAA,OAGF,IAAI,CAAC,cAAc,KAAK,CAAC,GACvB,OAAO,IACL,kBACA,6DAEF;CAIJ,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;;AAGvD,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,8BAA8B;CAC/C,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ;CACA;CACA;CACA,aACE;CAEF,WAAW;CACX,SAAS,CAAC,GAAG,CAAC;CACd,UAAU,CAAC,aAAa,WAAW;CACnC;AACF"}
@@ -1,4 +1,4 @@
1
- import { ValidateResult, Validator } from "../types.js";
1
+ import { CountryValidator, ValidateResult } from "../types.js";
2
2
 
3
3
  //#region src/mx/clabe.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -11,7 +11,7 @@ declare const generate: () => string;
11
11
  *
12
12
  * Example sourced from Wikipedia CLABE article.
13
13
  */
14
- declare const clabe: Validator;
14
+ declare const clabe: CountryValidator<"MX">;
15
15
  //#endregion
16
16
  export { compact, clabe as default, format, generate, validate };
17
17
  //# sourceMappingURL=clabe.d.ts.map
package/dist/mx/clabe.js CHANGED
@@ -3,20 +3,6 @@ import { randomDigits } from "../_util/generate.js";
3
3
  import { err } from "../_util/result.js";
4
4
  import { isdigits } from "../_util/strings.js";
5
5
  //#region src/mx/clabe.ts
6
- /**
7
- * CLABE (Clave Bancaria Estandarizada).
8
- *
9
- * Mexican standardized bank account number used for
10
- * interbank electronic fund transfers. 18 digits:
11
- * 3 (bank code) + 3 (branch) + 11 (account number)
12
- * + 1 (check digit).
13
- *
14
- * The check digit is computed using a weighted sum with
15
- * repeating weights [3, 7, 1] modulo 10:
16
- * check = (10 - sum % 10) % 10.
17
- *
18
- * @see https://en.wikipedia.org/wiki/CLABE
19
- */
20
6
  const WEIGHTS = [
21
7
  3,
22
8
  7,
@@ -71,6 +57,7 @@ const clabe = {
71
57
  abbreviation: "CLABE",
72
58
  aliases: ["CLABE", "Clave Bancaria Estandarizada"],
73
59
  candidatePattern: "\\d{18}",
60
+ scope: "country",
74
61
  country: "MX",
75
62
  entityType: "any",
76
63
  lengths: [18],
@@ -1 +1 @@
1
- {"version":3,"file":"clabe.js","names":[],"sources":["../../src/mx/clabe.ts"],"sourcesContent":["/**\n * CLABE (Clave Bancaria Estandarizada).\n *\n * Mexican standardized bank account number used for\n * interbank electronic fund transfers. 18 digits:\n * 3 (bank code) + 3 (branch) + 11 (account number)\n * + 1 (check digit).\n *\n * The check digit is computed using a weighted sum with\n * repeating weights [3, 7, 1] modulo 10:\n * check = (10 - sum % 10) % 10.\n *\n * @see https://en.wikipedia.org/wiki/CLABE\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst WEIGHTS = [3, 7, 1] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\").trim();\n\n/**\n * Compute the CLABE check digit.\n *\n * For each of the first 17 digits, multiply by the\n * corresponding weight [3, 7, 1, 3, 7, 1, ...], take\n * the result mod 10, sum all remainders, then\n * check = (10 - sum % 10) % 10.\n */\nconst calcCheckDigit = (value: string): string => {\n let sum = 0;\n for (let i = 0; i < 17; i++) {\n const digit = Number(value[i]);\n // SAFETY: modulo guarantees valid index\n // eslint-disable-next-line no-non-null-assertion\n const weight = WEIGHTS[i % WEIGHTS.length]!;\n sum += (digit * weight) % 10;\n }\n return String((10 - (sum % 10)) % 10);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 18) {\n return err(\"INVALID_LENGTH\", \"CLABE must be 18 digits\");\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CLABE must contain only digits\",\n );\n }\n\n // Verify check digit (last digit).\n const expected = calcCheckDigit(v);\n if (v[17] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CLABE check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 3)} ${v.slice(3, 6)} ${v.slice(6, 17)} ${v.slice(17)}`;\n};\n\n/** Generate a random valid Mexican CLABE. */\nconst generate = (): string => {\n const payload = randomDigits(17);\n return payload + calcCheckDigit(payload);\n};\n\n/**\n * Mexican CLABE (standardized bank account number).\n *\n * Example sourced from Wikipedia CLABE article.\n */\nconst clabe: Validator = {\n name: \"Mexican Bank Account\",\n localName: \"Clave Bancaria Estandarizada\",\n abbreviation: \"CLABE\",\n aliases: [\n \"CLABE\",\n \"Clave Bancaria Estandarizada\",\n ] as const,\n candidatePattern: \"\\\\d{18}\",\n country: \"MX\",\n entityType: \"any\",\n lengths: [18] as const,\n examples: [\"032180000118359719\"] as const,\n compact,\n format,\n validate,\n sourceUrl: \"https://en.wikipedia.org/wiki/CLABE\",\n generate,\n};\n\nexport default clabe;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAsBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAE;AAEzB,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,CAAC,MAAM;;;;;;;;;AAU3B,MAAM,kBAAkB,UAA0B;CAChD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;EAC3B,MAAM,QAAQ,OAAO,MAAM,GAAG;EAG9B,MAAM,SAAS,QAAQ,IAAI,QAAQ;AACnC,SAAQ,QAAQ,SAAU;;AAE5B,QAAO,QAAQ,KAAM,MAAM,MAAO,GAAG;;AAGvC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,WAAW,GACf,QAAO,IAAI,kBAAkB,0BAA0B;AAGzD,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,iCACD;CAIH,MAAM,WAAW,eAAe,EAAE;AAClC,KAAI,EAAE,QAAQ,SACZ,QAAO,IACL,oBACA,mCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,QAAO,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG;;;AAI3E,MAAM,iBAAyB;CAC7B,MAAM,UAAU,aAAa,GAAG;AAChC,QAAO,UAAU,eAAe,QAAQ;;;;;;;AAQ1C,MAAM,QAAmB;CACvB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,SACA,+BACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,GAAG;CACb,UAAU,CAAC,qBAAqB;CAChC;CACA;CACA;CACA,WAAW;CACX;CACD"}
1
+ {"version":3,"file":"clabe.js","names":[],"sources":["../../src/mx/clabe.ts"],"sourcesContent":["/**\n * CLABE (Clave Bancaria Estandarizada).\n *\n * Mexican standardized bank account number used for\n * interbank electronic fund transfers. 18 digits:\n * 3 (bank code) + 3 (branch) + 11 (account number)\n * + 1 (check digit).\n *\n * The check digit is computed using a weighted sum with\n * repeating weights [3, 7, 1] modulo 10:\n * check = (10 - sum % 10) % 10.\n *\n * @see https://en.wikipedia.org/wiki/CLABE\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [3, 7, 1] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\").trim();\n\n/**\n * Compute the CLABE check digit.\n *\n * For each of the first 17 digits, multiply by the\n * corresponding weight [3, 7, 1, 3, 7, 1, ...], take\n * the result mod 10, sum all remainders, then\n * check = (10 - sum % 10) % 10.\n */\nconst calcCheckDigit = (value: string): string => {\n let sum = 0;\n for (let i = 0; i < 17; i++) {\n const digit = Number(value[i]);\n // SAFETY: modulo guarantees valid index\n // eslint-disable-next-line no-non-null-assertion\n const weight = WEIGHTS[i % WEIGHTS.length]!;\n sum += (digit * weight) % 10;\n }\n return String((10 - (sum % 10)) % 10);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 18) {\n return err(\"INVALID_LENGTH\", \"CLABE must be 18 digits\");\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CLABE must contain only digits\",\n );\n }\n\n // Verify check digit (last digit).\n const expected = calcCheckDigit(v);\n if (v[17] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CLABE check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 3)} ${v.slice(3, 6)} ${v.slice(6, 17)} ${v.slice(17)}`;\n};\n\n/** Generate a random valid Mexican CLABE. */\nconst generate = (): string => {\n const payload = randomDigits(17);\n return payload + calcCheckDigit(payload);\n};\n\n/**\n * Mexican CLABE (standardized bank account number).\n *\n * Example sourced from Wikipedia CLABE article.\n */\nconst clabe: CountryValidator<\"MX\"> = {\n name: \"Mexican Bank Account\",\n localName: \"Clave Bancaria Estandarizada\",\n abbreviation: \"CLABE\",\n aliases: [\n \"CLABE\",\n \"Clave Bancaria Estandarizada\",\n ] as const,\n candidatePattern: \"\\\\d{18}\",\n scope: \"country\",\n country: \"MX\",\n entityType: \"any\",\n lengths: [18] as const,\n examples: [\"032180000118359719\"] as const,\n compact,\n format,\n validate,\n sourceUrl: \"https://en.wikipedia.org/wiki/CLABE\",\n generate,\n};\n\nexport default clabe;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAyBA,MAAM,UAAU;CAAC;CAAG;CAAG;AAAC;AAExB,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,EAAE,KAAK;;;;;;;;;AAU1B,MAAM,kBAAkB,UAA0B;CAChD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;EAC3B,MAAM,QAAQ,OAAO,MAAM,EAAE;EAG7B,MAAM,SAAS,QAAQ,IAAI,QAAQ;EACnC,OAAQ,QAAQ,SAAU;CAC5B;CACA,OAAO,QAAQ,KAAM,MAAM,MAAO,EAAE;AACtC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,IACf,OAAO,IAAI,kBAAkB,yBAAyB;CAGxD,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,gCACF;CAIF,MAAM,WAAW,eAAe,CAAC;CACjC,IAAI,EAAE,QAAQ,UACZ,OAAO,IACL,oBACA,kCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;AAC1E;;AAGA,MAAM,iBAAyB;CAC7B,MAAM,UAAU,aAAa,EAAE;CAC/B,OAAO,UAAU,eAAe,OAAO;AACzC;;;;;;AAOA,MAAM,QAAgC;CACpC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,SACA,8BACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,oBAAoB;CAC/B;CACA;CACA;CACA,WAAW;CACX;AACF"}
package/dist/mx/curp.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
1
+ import { CountryValidator, ParsedPersonId, ValidateResult } from "../types.js";
2
2
 
3
3
  //#region src/mx/curp.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -16,7 +16,7 @@ declare const generate: () => string;
16
16
  *
17
17
  * Example sourced from python-stdnum test suite.
18
18
  */
19
- declare const curp: Validator<ParsedPersonId>;
19
+ declare const curp: CountryValidator<"MX", ParsedPersonId>;
20
20
  //#endregion
21
21
  export { compact, curp as default, format, generate, parse, validate };
22
22
  //# sourceMappingURL=curp.d.ts.map
package/dist/mx/curp.js CHANGED
@@ -1,23 +1,8 @@
1
1
  import { clean } from "../_util/clean.js";
2
+ import { isValidDate } from "../_util/date.js";
2
3
  import { randomInt } from "../_util/generate.js";
3
4
  import { err } from "../_util/result.js";
4
- import { isValidDate } from "../_util/date.js";
5
5
  //#region src/mx/curp.ts
6
- /**
7
- * CURP (Clave Única de Registro de Población).
8
- *
9
- * Mexican personal identification number. 18 characters:
10
- * 4 letters (name encoding) + 6 digits (YYMMDD birth
11
- * date) + 1 letter (gender: H=male, M=female) + 2
12
- * letters (state code) + 3 consonants (name
13
- * disambiguation) + 1 digit (century discriminator) +
14
- * 1 check digit.
15
- *
16
- * The check digit is computed as a weighted sum mod 10
17
- * using an alphabet mapping (0-9, A-N, &, O-Z).
18
- *
19
- * @see https://en.wikipedia.org/wiki/CURP
20
- */
21
6
  /** Valid Mexican state codes (2-letter). */
22
7
  const STATE_CODES = new Set([
23
8
  "AS",
@@ -63,7 +48,7 @@ const LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
63
48
  */
64
49
  const ALPHABET = "0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ";
65
50
  const CHAR_MAP = /* @__PURE__ */ new Map();
66
- for (const [i, ch] of [...ALPHABET].entries()) CHAR_MAP.set(ch, i);
51
+ for (const [i, ch] of ALPHABET.split("").entries()) CHAR_MAP.set(ch, i);
67
52
  const compact = (value) => clean(value, " -").trim().toUpperCase();
68
53
  /**
69
54
  * Compute the CURP check digit. Sum each of the first
@@ -145,6 +130,7 @@ const curp = {
145
130
  abbreviation: "CURP",
146
131
  aliases: ["CURP", "Clave Única de Registro de Población"],
147
132
  candidatePattern: "[A-Z]{4}\\d{6}[HM][A-Z]{5}[A-Z\\d]\\d",
133
+ scope: "country",
148
134
  country: "MX",
149
135
  entityType: "person",
150
136
  lengths: [18],
@@ -1 +1 @@
1
- {"version":3,"file":"curp.js","names":[],"sources":["../../src/mx/curp.ts"],"sourcesContent":["/**\n * CURP (Clave Única de Registro de Población).\n *\n * Mexican personal identification number. 18 characters:\n * 4 letters (name encoding) + 6 digits (YYMMDD birth\n * date) + 1 letter (gender: H=male, M=female) + 2\n * letters (state code) + 3 consonants (name\n * disambiguation) + 1 digit (century discriminator) +\n * 1 check digit.\n *\n * The check digit is computed as a weighted sum mod 10\n * using an alphabet mapping (0-9, A-N, &, O-Z).\n *\n * @see https://en.wikipedia.org/wiki/CURP\n */\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } 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\n/** Valid Mexican state codes (2-letter). */\nconst STATE_CODES = new Set([\n \"AS\",\n \"BC\",\n \"BS\",\n \"CC\",\n \"CL\",\n \"CM\",\n \"CS\",\n \"CH\",\n \"DF\",\n \"DG\",\n \"GT\",\n \"GR\",\n \"HG\",\n \"JC\",\n \"MC\",\n \"MN\",\n \"MS\",\n \"NT\",\n \"NL\",\n \"OC\",\n \"PL\",\n \"QT\",\n \"QR\",\n \"SP\",\n \"SL\",\n \"SR\",\n \"TC\",\n \"TS\",\n \"TL\",\n \"VZ\",\n \"YN\",\n \"ZS\",\n \"NE\", // Born abroad\n]);\nconst STATE_CODE_LIST = [...STATE_CODES];\nconst LETTERS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\n/**\n * Alphabet for CURP check digit computation.\n * Matches python-stdnum: digits 0-9, then A-N,\n * ampersand, O-Z.\n */\nconst ALPHABET = \"0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ\";\n\nconst CHAR_MAP = new Map<string, number>();\nfor (const [i, ch] of [...ALPHABET].entries()) {\n CHAR_MAP.set(ch, i);\n}\n\nconst compact = (value: string): string =>\n clean(value, \" -\").trim().toUpperCase();\n\n/**\n * Compute the CURP check digit. Sum each of the first\n * 17 characters multiplied by weight (18 - position),\n * then check = (10 - sum % 10) % 10.\n */\nconst calcCheckDigit = (value: string): string => {\n let sum = 0;\n for (let i = 0; i < 17; i++) {\n const ch = value[i];\n if (ch === undefined) continue;\n sum += (CHAR_MAP.get(ch) ?? 0) * (18 - i);\n }\n return String((10 - (sum % 10)) % 10);\n};\n\n/**\n * Resolve full year from 2-digit year and century\n * discriminator: 0-9 = 1900s, letter = 2000s.\n */\nconst resolveCurpYear = (\n yy: number,\n centuryChar: string,\n): number =>\n centuryChar >= \"0\" && centuryChar <= \"9\"\n ? 1900 + yy\n : 2000 + yy;\n\nconst CURP_RE =\n /^[A-Z]{4}\\d{6}[HM][A-Z]{2}[A-Z]{3}[0-9A-Z]\\d$/;\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 18) {\n return err(\n \"INVALID_LENGTH\",\n \"CURP must be 18 characters\",\n );\n }\n\n if (!CURP_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CURP has an invalid format\",\n );\n }\n\n // Validate the embedded date (YYMMDD at positions 4-9).\n const yy = Number(v.slice(4, 6));\n const mm = Number(v.slice(6, 8));\n const dd = Number(v.slice(8, 10));\n\n // SAFETY: regex validation ensures v.length === 18.\n // eslint-disable-next-line no-non-null-assertion\n const year = resolveCurpYear(yy, v[16]!);\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"CURP contains an invalid birth date\",\n );\n }\n\n // Validate state code at positions 11-12.\n const state = v.slice(11, 13);\n if (!STATE_CODES.has(state)) {\n return err(\n \"INVALID_COMPONENT\",\n \"CURP contains an invalid state code\",\n );\n }\n\n // Verify check digit (last character).\n const expected = calcCheckDigit(v);\n if (v[17] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CURP check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a CURP.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const yy = Number(v.slice(4, 6));\n const mm = Number(v.slice(6, 8));\n const dd = Number(v.slice(8, 10));\n\n // SAFETY: regex validation ensures v.length === 18.\n // eslint-disable-next-line no-non-null-assertion\n const year = resolveCurpYear(yy, v[16]!);\n\n const genderChar = v[10];\n const gender: \"male\" | \"female\" =\n genderChar === \"H\" ? \"male\" : \"female\";\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender,\n };\n};\n\nconst randomLetter = (): string =>\n LETTERS.charAt(randomInt(0, LETTERS.length - 1));\n\n/** Generate a random valid CURP. */\nconst generate = (): string => {\n const year = randomInt(1980, 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 gender = Math.random() < 0.5 ? \"H\" : \"M\";\n const state =\n STATE_CODE_LIST[\n randomInt(0, STATE_CODE_LIST.length - 1)\n ] ?? \"NE\";\n const centuryChar =\n year >= 2000 ? randomLetter() : String(randomInt(0, 9));\n const body =\n `${randomLetter()}${randomLetter()}` +\n `${randomLetter()}${randomLetter()}` +\n `${yy}${month}${day}${gender}${state}` +\n `${randomLetter()}${randomLetter()}${randomLetter()}` +\n `${centuryChar}`;\n return `${body}${calcCheckDigit(body)}`;\n};\n\n/**\n * Mexican CURP (personal identification number).\n *\n * Example sourced from python-stdnum test suite.\n */\nconst curp: Validator<ParsedPersonId> = {\n name: \"Mexican Personal ID\",\n localName: \"Clave Única de Registro de Población\",\n abbreviation: \"CURP\",\n aliases: [\n \"CURP\",\n \"Clave Única de Registro de Población\",\n ] as const,\n candidatePattern: \"[A-Z]{4}\\\\d{6}[HM][A-Z]{5}[A-Z\\\\d]\\\\d\",\n country: \"MX\",\n entityType: \"person\",\n lengths: [18] as const,\n examples: [\"BOXW310820HNERXN09\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n sourceUrl: \"https://en.wikipedia.org/wiki/CURP\",\n};\n\nexport default curp;\nexport { compact, format, generate, parse, validate };\n"],"mappings":"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"}
1
+ {"version":3,"file":"curp.js","names":[],"sources":["../../src/mx/curp.ts"],"sourcesContent":["/**\n * CURP (Clave Única de Registro de Población).\n *\n * Mexican personal identification number. 18 characters:\n * 4 letters (name encoding) + 6 digits (YYMMDD birth\n * date) + 1 letter (gender: H=male, M=female) + 2\n * letters (state code) + 3 consonants (name\n * disambiguation) + 1 digit (century discriminator) +\n * 1 check digit.\n *\n * The check digit is computed as a weighted sum mod 10\n * using an alphabet mapping (0-9, A-N, &, O-Z).\n *\n * @see https://en.wikipedia.org/wiki/CURP\n */\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\n/** Valid Mexican state codes (2-letter). */\nconst STATE_CODES = new Set([\n \"AS\",\n \"BC\",\n \"BS\",\n \"CC\",\n \"CL\",\n \"CM\",\n \"CS\",\n \"CH\",\n \"DF\",\n \"DG\",\n \"GT\",\n \"GR\",\n \"HG\",\n \"JC\",\n \"MC\",\n \"MN\",\n \"MS\",\n \"NT\",\n \"NL\",\n \"OC\",\n \"PL\",\n \"QT\",\n \"QR\",\n \"SP\",\n \"SL\",\n \"SR\",\n \"TC\",\n \"TS\",\n \"TL\",\n \"VZ\",\n \"YN\",\n \"ZS\",\n \"NE\", // Born abroad\n]);\nconst STATE_CODE_LIST = [...STATE_CODES];\nconst LETTERS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\n/**\n * Alphabet for CURP check digit computation.\n * Matches python-stdnum: digits 0-9, then A-N,\n * ampersand, O-Z.\n */\nconst ALPHABET = \"0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ\";\n\nconst CHAR_MAP = new Map<string, number>();\nfor (const [i, ch] of ALPHABET.split(\"\").entries()) {\n CHAR_MAP.set(ch, i);\n}\n\nconst compact = (value: string): string =>\n clean(value, \" -\").trim().toUpperCase();\n\n/**\n * Compute the CURP check digit. Sum each of the first\n * 17 characters multiplied by weight (18 - position),\n * then check = (10 - sum % 10) % 10.\n */\nconst calcCheckDigit = (value: string): string => {\n let sum = 0;\n for (let i = 0; i < 17; i++) {\n const ch = value[i];\n if (ch === undefined) continue;\n sum += (CHAR_MAP.get(ch) ?? 0) * (18 - i);\n }\n return String((10 - (sum % 10)) % 10);\n};\n\n/**\n * Resolve full year from 2-digit year and century\n * discriminator: 0-9 = 1900s, letter = 2000s.\n */\nconst resolveCurpYear = (\n yy: number,\n centuryChar: string,\n): number =>\n centuryChar >= \"0\" && centuryChar <= \"9\"\n ? 1900 + yy\n : 2000 + yy;\n\nconst CURP_RE =\n /^[A-Z]{4}\\d{6}[HM][A-Z]{2}[A-Z]{3}[0-9A-Z]\\d$/;\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 18) {\n return err(\n \"INVALID_LENGTH\",\n \"CURP must be 18 characters\",\n );\n }\n\n if (!CURP_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CURP has an invalid format\",\n );\n }\n\n // Validate the embedded date (YYMMDD at positions 4-9).\n const yy = Number(v.slice(4, 6));\n const mm = Number(v.slice(6, 8));\n const dd = Number(v.slice(8, 10));\n\n // SAFETY: regex validation ensures v.length === 18.\n // eslint-disable-next-line no-non-null-assertion\n const year = resolveCurpYear(yy, v[16]!);\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"CURP contains an invalid birth date\",\n );\n }\n\n // Validate state code at positions 11-12.\n const state = v.slice(11, 13);\n if (!STATE_CODES.has(state)) {\n return err(\n \"INVALID_COMPONENT\",\n \"CURP contains an invalid state code\",\n );\n }\n\n // Verify check digit (last character).\n const expected = calcCheckDigit(v);\n if (v[17] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CURP check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a CURP.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const yy = Number(v.slice(4, 6));\n const mm = Number(v.slice(6, 8));\n const dd = Number(v.slice(8, 10));\n\n // SAFETY: regex validation ensures v.length === 18.\n // eslint-disable-next-line no-non-null-assertion\n const year = resolveCurpYear(yy, v[16]!);\n\n const genderChar = v[10];\n const gender: \"male\" | \"female\" =\n genderChar === \"H\" ? \"male\" : \"female\";\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender,\n };\n};\n\nconst randomLetter = (): string =>\n LETTERS.charAt(randomInt(0, LETTERS.length - 1));\n\n/** Generate a random valid CURP. */\nconst generate = (): string => {\n const year = randomInt(1980, 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 gender = Math.random() < 0.5 ? \"H\" : \"M\";\n const state =\n STATE_CODE_LIST[\n randomInt(0, STATE_CODE_LIST.length - 1)\n ] ?? \"NE\";\n const centuryChar =\n year >= 2000 ? randomLetter() : String(randomInt(0, 9));\n const body =\n `${randomLetter()}${randomLetter()}` +\n `${randomLetter()}${randomLetter()}` +\n `${yy}${month}${day}${gender}${state}` +\n `${randomLetter()}${randomLetter()}${randomLetter()}` +\n `${centuryChar}`;\n return `${body}${calcCheckDigit(body)}`;\n};\n\n/**\n * Mexican CURP (personal identification number).\n *\n * Example sourced from python-stdnum test suite.\n */\nconst curp: CountryValidator<\"MX\", ParsedPersonId> = {\n name: \"Mexican Personal ID\",\n localName: \"Clave Única de Registro de Población\",\n abbreviation: \"CURP\",\n aliases: [\n \"CURP\",\n \"Clave Única de Registro de Población\",\n ] as const,\n candidatePattern: \"[A-Z]{4}\\\\d{6}[HM][A-Z]{5}[A-Z\\\\d]\\\\d\",\n scope: \"country\",\n country: \"MX\",\n entityType: \"person\",\n lengths: [18] as const,\n examples: [\"BOXW310820HNERXN09\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n sourceUrl: \"https://en.wikipedia.org/wiki/CURP\",\n};\n\nexport default curp;\nexport { compact, format, generate, parse, validate };\n"],"mappings":";;;;;;AA4BA,MAAM,cAAc,IAAI,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AACD,MAAM,kBAAkB,CAAC,GAAG,WAAW;AACvC,MAAM,UAAU;;;;;;AAOhB,MAAM,WAAW;AAEjB,MAAM,2BAAW,IAAI,IAAoB;AACzC,KAAK,MAAM,CAAC,GAAG,OAAO,SAAS,MAAM,EAAE,EAAE,QAAQ,GAC/C,SAAS,IAAI,IAAI,CAAC;AAGpB,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,EAAE,KAAK,EAAE,YAAY;;;;;;AAOxC,MAAM,kBAAkB,UAA0B;CAChD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;EAC3B,MAAM,KAAK,MAAM;EACjB,IAAI,OAAO,KAAA,GAAW;EACtB,QAAQ,SAAS,IAAI,EAAE,KAAK,MAAM,KAAK;CACzC;CACA,OAAO,QAAQ,KAAM,MAAM,MAAO,EAAE;AACtC;;;;;AAMA,MAAM,mBACJ,IACA,gBAEA,eAAe,OAAO,eAAe,MACjC,OAAO,KACP,MAAO;AAEb,MAAM,UACJ;AAEF,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,4BACF;CAGF,IAAI,CAAC,QAAQ,KAAK,CAAC,GACjB,OAAO,IACL,kBACA,4BACF;CAIF,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAKhC,IAAI,CAAC,YADQ,gBAAgB,IAAI,EAAE,GACf,GAAG,IAAI,EAAE,GAC3B,OAAO,IACL,qBACA,qCACF;CAIF,MAAM,QAAQ,EAAE,MAAM,IAAI,EAAE;CAC5B,IAAI,CAAC,YAAY,IAAI,KAAK,GACxB,OAAO,IACL,qBACA,qCACF;CAIF,MAAM,WAAW,eAAe,CAAC;CACjC,IAAI,EAAE,QAAQ,UACZ,OAAO,IACL,oBACA,iCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;;;;;AAMvD,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,KAAK;CAC7B,IAAI,CAAC,OAAO,OAAO,OAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAIhC,MAAM,OAAO,gBAAgB,IAAI,EAAE,GAAI;CAGvC,MAAM,SADa,EAAE,QAEJ,MAAM,SAAS;CAEhC,OAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,EAAE;EACpC;CACF;AACF;AAEA,MAAM,qBACJ,QAAQ,OAAO,UAAU,GAAG,EAAkB,CAAC;;AAGjD,MAAM,iBAAyB;CAC7B,MAAM,OAAO,UAAU,MAAM,IAAI;CACjC,MAAM,QAAQ,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;CACtD,MAAM,MAAM,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;CACpD,MAAM,KAAK,OAAO,OAAO,GAAG,EAAE,SAAS,GAAG,GAAG;CAC7C,MAAM,SAAS,KAAK,OAAO,IAAI,KAAM,MAAM;CAC3C,MAAM,QACJ,gBACE,UAAU,GAAG,gBAAgB,SAAS,CAAC,MACpC;CACP,MAAM,cACJ,QAAQ,MAAO,aAAa,IAAI,OAAO,UAAU,GAAG,CAAC,CAAC;CACxD,MAAM,OACJ,GAAG,aAAa,IAAI,aAAa,IAC9B,aAAa,IAAI,aAAa,IAC9B,KAAK,QAAQ,MAAM,SAAS,QAC5B,aAAa,IAAI,aAAa,IAAI,aAAa,IAC/C;CACL,OAAO,GAAG,OAAO,eAAe,IAAI;AACtC;;;;;;AAOA,MAAM,OAA+C;CACnD,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,QACA,sCACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,oBAAoB;CAC/B;CACA;CACA;CACA;CACA;CACA,WAAW;AACb"}
package/dist/mx/rfc.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ValidateResult, Validator } from "../types.js";
1
+ import { CountryValidator, ValidateResult } from "../types.js";
2
2
 
3
3
  //#region src/mx/rfc.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -11,7 +11,7 @@ declare const generate: () => string;
11
11
  *
12
12
  * Examples sourced from python-stdnum test suite.
13
13
  */
14
- declare const rfc: Validator;
14
+ declare const rfc: CountryValidator<"MX">;
15
15
  //#endregion
16
16
  export { compact, rfc as default, format, generate, validate };
17
17
  //# sourceMappingURL=rfc.d.ts.map
package/dist/mx/rfc.js CHANGED
@@ -1,29 +1,12 @@
1
1
  import { clean } from "../_util/clean.js";
2
+ import { isValidDate } from "../_util/date.js";
2
3
  import { randomInt } from "../_util/generate.js";
3
4
  import { err } from "../_util/result.js";
4
- import { isValidDate } from "../_util/date.js";
5
5
  //#region src/mx/rfc.ts
6
- /**
7
- * RFC (Registro Federal de Contribuyentes).
8
- *
9
- * Mexican tax identification number issued by the SAT
10
- * (Servicio de Administración Tributaria). The number is
11
- * 13 characters for individuals (4 letters + 6 digits
12
- * YYMMDD + 3 alphanumeric) or 12 characters for
13
- * companies (3 letters + 6 digits YYMMDD + 3
14
- * alphanumeric). The last character is a check digit
15
- * computed with a mod 11 algorithm over a specific
16
- * alphabet mapping.
17
- *
18
- * Format: AAAA######XXX (persons, 13 chars)
19
- * AAA######XXX (companies, 12 chars)
20
- *
21
- * @see https://en.wikipedia.org/wiki/Tax_Identification_Number_(Mexico)
22
- */
23
6
  /** Alphabet for RFC check digit computation. */
24
7
  const ALPHABET = "0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ Ñ";
25
8
  const CHAR_MAP = /* @__PURE__ */ new Map();
26
- for (const [i, ch] of [...ALPHABET].entries()) CHAR_MAP.set(ch, i);
9
+ for (const [i, ch] of ALPHABET.split("").entries()) CHAR_MAP.set(ch, i);
27
10
  const compact = (value) => clean(value, " -.").trim().toUpperCase();
28
11
  /**
29
12
  * Compute the RFC check digit using mod 11 with
@@ -95,6 +78,7 @@ const rfc = {
95
78
  abbreviation: "RFC",
96
79
  aliases: ["RFC", "Registro Federal de Contribuyentes"],
97
80
  candidatePattern: "[A-ZÑ&]{3,4}\\d{6}[A-Z\\d]{3}",
81
+ scope: "country",
98
82
  country: "MX",
99
83
  entityType: "any",
100
84
  lengths: [12, 13],
@@ -1 +1 @@
1
- {"version":3,"file":"rfc.js","names":[],"sources":["../../src/mx/rfc.ts"],"sourcesContent":["/**\n * RFC (Registro Federal de Contribuyentes).\n *\n * Mexican tax identification number issued by the SAT\n * (Servicio de Administración Tributaria). The number is\n * 13 characters for individuals (4 letters + 6 digits\n * YYMMDD + 3 alphanumeric) or 12 characters for\n * companies (3 letters + 6 digits YYMMDD + 3\n * alphanumeric). The last character is a check digit\n * computed with a mod 11 algorithm over a specific\n * alphabet mapping.\n *\n * Format: AAAA######XXX (persons, 13 chars)\n * AAA######XXX (companies, 12 chars)\n *\n * @see https://en.wikipedia.org/wiki/Tax_Identification_Number_(Mexico)\n */\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\n/** Alphabet for RFC check digit computation. */\nconst ALPHABET = \"0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ Ñ\";\n\nconst CHAR_MAP = new Map<string, number>();\nfor (const [i, ch] of [...ALPHABET].entries()) {\n CHAR_MAP.set(ch, i);\n}\n\nconst compact = (value: string): string =>\n clean(value, \" -.\").trim().toUpperCase();\n\n/**\n * Compute the RFC check digit using mod 11 with\n * the SAT alphabet mapping.\n *\n * Each character is mapped to its position in the\n * ALPHABET, then multiplied by a weight that starts\n * at (len + 1) and decreases by 1. The check digit\n * is (11 - sum % 11) % 11, mapped to 0-9 or \"A\".\n */\nconst calcCheckDigit = (value: string): string => {\n // Pad 12-char company RFCs with a leading space\n // to align weights with the 13-char algorithm.\n const padded = value.length === 11 ? ` ${value}` : value;\n let sum = 0;\n for (let i = 0; i < 12; i++) {\n const ch = padded[i];\n if (ch === undefined) continue;\n const v = CHAR_MAP.get(ch) ?? 0;\n sum += v * (13 - i);\n }\n const remainder = sum % 11;\n if (remainder === 0) return \"0\";\n const digit = 11 - remainder;\n return digit === 10 ? \"A\" : String(digit);\n};\n\nconst PERSON_RE = /^[A-ZÑ&]{4}\\d{6}[A-Z\\d]{3}$/;\nconst COMPANY_RE = /^[A-ZÑ&]{3}\\d{6}[A-Z\\d]{3}$/;\nconst PREFIX_ALPHA = \"ABCDEFGHIJKLMNOPQRSTUVWXYZÑ&\";\nconst RFC_ALNUM = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 12 && v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"RFC must be 12 or 13 characters\",\n );\n }\n\n const isPerson = v.length === 13;\n const re = isPerson ? PERSON_RE : COMPANY_RE;\n if (!re.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"RFC has an invalid format\",\n );\n }\n\n // Validate the embedded date (YYMMDD).\n const dateOffset = isPerson ? 4 : 3;\n const yy = Number(v.slice(dateOffset, dateOffset + 2));\n const mm = Number(\n v.slice(dateOffset + 2, dateOffset + 4),\n );\n const dd = Number(\n v.slice(dateOffset + 4, dateOffset + 6),\n );\n\n // RFC dates use 2-digit years; use 2000 century for\n // date validation (any valid calendar date is accepted).\n const year = 2000 + yy;\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"RFC contains an invalid date\",\n );\n }\n\n // Verify check digit (last character).\n const body = v.slice(0, -1);\n const expected = calcCheckDigit(body);\n if (v.at(-1) !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"RFC check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst randomCharFrom = (chars: string): string =>\n chars.charAt(randomInt(0, chars.length - 1));\n\n/** Generate a random valid RFC. */\nconst generate = (): string => {\n const isPerson = Math.random() < 0.5;\n const prefixLength = isPerson ? 4 : 3;\n let prefix = \"\";\n for (let i = 0; i < prefixLength; i++) {\n prefix += randomCharFrom(PREFIX_ALPHA);\n }\n\n const year = randomInt(2000, 2099);\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n let homoclave = \"\";\n for (let i = 0; i < 2; i++) {\n homoclave += randomCharFrom(RFC_ALNUM);\n }\n\n const body =\n `${prefix}${String(year % 100).padStart(2, \"0\")}` +\n `${month}${day}${homoclave}`;\n return `${body}${calcCheckDigit(body)}`;\n};\n\n/**\n * Mexican RFC (tax identification number).\n *\n * Examples sourced from python-stdnum test suite.\n */\nconst rfc: Validator = {\n name: \"Mexican Tax ID\",\n localName: \"Registro Federal de Contribuyentes\",\n abbreviation: \"RFC\",\n aliases: [\n \"RFC\",\n \"Registro Federal de Contribuyentes\",\n ] as const,\n candidatePattern: \"[A-ZÑ&]{3,4}\\\\d{6}[A-Z\\\\d]{3}\",\n country: \"MX\",\n entityType: \"any\",\n lengths: [12, 13] as const,\n examples: [\"GODE561231GR8\", \"MAB9307148T4\"] as const,\n compact,\n format,\n validate,\n generate,\n sourceUrl:\n \"https://en.wikipedia.org/wiki/Tax_Identification_Number_(Mexico)\",\n};\n\nexport default rfc;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,WAAW;AAEjB,MAAM,2BAAW,IAAI,KAAqB;AAC1C,KAAK,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,SAAS,CAAC,SAAS,CAC3C,UAAS,IAAI,IAAI,EAAE;AAGrB,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa;;;;;;;;;;AAW1C,MAAM,kBAAkB,UAA0B;CAGhD,MAAM,SAAS,MAAM,WAAW,KAAK,IAAI,UAAU;CACnD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;EAC3B,MAAM,KAAK,OAAO;AAClB,MAAI,OAAO,KAAA,EAAW;EACtB,MAAM,IAAI,SAAS,IAAI,GAAG,IAAI;AAC9B,SAAO,KAAK,KAAK;;CAEnB,MAAM,YAAY,MAAM;AACxB,KAAI,cAAc,EAAG,QAAO;CAC5B,MAAM,QAAQ,KAAK;AACnB,QAAO,UAAU,KAAK,MAAM,OAAO,MAAM;;AAG3C,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,eAAe;AACrB,MAAM,YAAY;AAElB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,WAAW,MAAM,EAAE,WAAW,GAClC,QAAO,IACL,kBACA,kCACD;CAGH,MAAM,WAAW,EAAE,WAAW;AAE9B,KAAI,EADO,WAAW,YAAY,YAC1B,KAAK,EAAE,CACb,QAAO,IACL,kBACA,4BACD;CAIH,MAAM,aAAa,WAAW,IAAI;CAClC,MAAM,KAAK,OAAO,EAAE,MAAM,YAAY,aAAa,EAAE,CAAC;CACtD,MAAM,KAAK,OACT,EAAE,MAAM,aAAa,GAAG,aAAa,EAAE,CACxC;CACD,MAAM,KAAK,OACT,EAAE,MAAM,aAAa,GAAG,aAAa,EAAE,CACxC;AAKD,KAAI,CAAC,YADQ,MAAO,IACG,IAAI,GAAG,CAC5B,QAAO,IACL,qBACA,+BACD;CAKH,MAAM,WAAW,eADJ,EAAE,MAAM,GAAG,GAAG,CACU;AACrC,KAAI,EAAE,GAAG,GAAG,KAAK,SACf,QAAO,IACL,oBACA,iCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;AAExD,MAAM,kBAAkB,UACtB,MAAM,OAAO,UAAU,GAAG,MAAM,SAAS,EAAE,CAAC;;AAG9C,MAAM,iBAAyB;CAE7B,MAAM,eADW,KAAK,QAAQ,GAAG,KACD,IAAI;CACpC,IAAI,SAAS;AACb,MAAK,IAAI,IAAI,GAAG,IAAI,cAAc,IAChC,WAAU,eAAe,aAAa;CAGxC,MAAM,OAAO,UAAU,KAAM,KAAK;CAClC,MAAM,QAAQ,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;CACvD,MAAM,MAAM,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;CACrD,IAAI,YAAY;AAChB,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IACrB,cAAa,eAAe,UAAU;CAGxC,MAAM,OACJ,GAAG,SAAS,OAAO,OAAO,IAAI,CAAC,SAAS,GAAG,IAAI,GAC5C,QAAQ,MAAM;AACnB,QAAO,GAAG,OAAO,eAAe,KAAK;;;;;;;AAQvC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,qCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,IAAI,GAAG;CACjB,UAAU,CAAC,iBAAiB,eAAe;CAC3C;CACA;CACA;CACA;CACA,WACE;CACH"}
1
+ {"version":3,"file":"rfc.js","names":[],"sources":["../../src/mx/rfc.ts"],"sourcesContent":["/**\n * RFC (Registro Federal de Contribuyentes).\n *\n * Mexican tax identification number issued by the SAT\n * (Servicio de Administración Tributaria). The number is\n * 13 characters for individuals (4 letters + 6 digits\n * YYMMDD + 3 alphanumeric) or 12 characters for\n * companies (3 letters + 6 digits YYMMDD + 3\n * alphanumeric). The last character is a check digit\n * computed with a mod 11 algorithm over a specific\n * alphabet mapping.\n *\n * Format: AAAA######XXX (persons, 13 chars)\n * AAA######XXX (companies, 12 chars)\n *\n * @see https://en.wikipedia.org/wiki/Tax_Identification_Number_(Mexico)\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\n/** Alphabet for RFC check digit computation. */\nconst ALPHABET = \"0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ Ñ\";\n\nconst CHAR_MAP = new Map<string, number>();\nfor (const [i, ch] of ALPHABET.split(\"\").entries()) {\n CHAR_MAP.set(ch, i);\n}\n\nconst compact = (value: string): string =>\n clean(value, \" -.\").trim().toUpperCase();\n\n/**\n * Compute the RFC check digit using mod 11 with\n * the SAT alphabet mapping.\n *\n * Each character is mapped to its position in the\n * ALPHABET, then multiplied by a weight that starts\n * at (len + 1) and decreases by 1. The check digit\n * is (11 - sum % 11) % 11, mapped to 0-9 or \"A\".\n */\nconst calcCheckDigit = (value: string): string => {\n // Pad 12-char company RFCs with a leading space\n // to align weights with the 13-char algorithm.\n const padded = value.length === 11 ? ` ${value}` : value;\n let sum = 0;\n for (let i = 0; i < 12; i++) {\n const ch = padded[i];\n if (ch === undefined) continue;\n const v = CHAR_MAP.get(ch) ?? 0;\n sum += v * (13 - i);\n }\n const remainder = sum % 11;\n if (remainder === 0) return \"0\";\n const digit = 11 - remainder;\n return digit === 10 ? \"A\" : String(digit);\n};\n\nconst PERSON_RE = /^[A-ZÑ&]{4}\\d{6}[A-Z\\d]{3}$/;\nconst COMPANY_RE = /^[A-ZÑ&]{3}\\d{6}[A-Z\\d]{3}$/;\nconst PREFIX_ALPHA = \"ABCDEFGHIJKLMNOPQRSTUVWXYZÑ&\";\nconst RFC_ALNUM = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 12 && v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"RFC must be 12 or 13 characters\",\n );\n }\n\n const isPerson = v.length === 13;\n const re = isPerson ? PERSON_RE : COMPANY_RE;\n if (!re.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"RFC has an invalid format\",\n );\n }\n\n // Validate the embedded date (YYMMDD).\n const dateOffset = isPerson ? 4 : 3;\n const yy = Number(v.slice(dateOffset, dateOffset + 2));\n const mm = Number(\n v.slice(dateOffset + 2, dateOffset + 4),\n );\n const dd = Number(\n v.slice(dateOffset + 4, dateOffset + 6),\n );\n\n // RFC dates use 2-digit years; use 2000 century for\n // date validation (any valid calendar date is accepted).\n const year = 2000 + yy;\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"RFC contains an invalid date\",\n );\n }\n\n // Verify check digit (last character).\n const body = v.slice(0, -1);\n const expected = calcCheckDigit(body);\n if (v.at(-1) !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"RFC check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst randomCharFrom = (chars: string): string =>\n chars.charAt(randomInt(0, chars.length - 1));\n\n/** Generate a random valid RFC. */\nconst generate = (): string => {\n const isPerson = Math.random() < 0.5;\n const prefixLength = isPerson ? 4 : 3;\n let prefix = \"\";\n for (let i = 0; i < prefixLength; i++) {\n prefix += randomCharFrom(PREFIX_ALPHA);\n }\n\n const year = randomInt(2000, 2099);\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n let homoclave = \"\";\n for (let i = 0; i < 2; i++) {\n homoclave += randomCharFrom(RFC_ALNUM);\n }\n\n const body =\n `${prefix}${String(year % 100).padStart(2, \"0\")}` +\n `${month}${day}${homoclave}`;\n return `${body}${calcCheckDigit(body)}`;\n};\n\n/**\n * Mexican RFC (tax identification number).\n *\n * Examples sourced from python-stdnum test suite.\n */\nconst rfc: CountryValidator<\"MX\"> = {\n name: \"Mexican Tax ID\",\n localName: \"Registro Federal de Contribuyentes\",\n abbreviation: \"RFC\",\n aliases: [\n \"RFC\",\n \"Registro Federal de Contribuyentes\",\n ] as const,\n candidatePattern: \"[A-ZÑ&]{3,4}\\\\d{6}[A-Z\\\\d]{3}\",\n scope: \"country\",\n country: \"MX\",\n entityType: \"any\",\n lengths: [12, 13] as const,\n examples: [\"GODE561231GR8\", \"MAB9307148T4\"] as const,\n compact,\n format,\n validate,\n generate,\n sourceUrl:\n \"https://en.wikipedia.org/wiki/Tax_Identification_Number_(Mexico)\",\n};\n\nexport default rfc;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;AA6BA,MAAM,WAAW;AAEjB,MAAM,2BAAW,IAAI,IAAoB;AACzC,KAAK,MAAM,CAAC,GAAG,OAAO,SAAS,MAAM,EAAE,EAAE,QAAQ,GAC/C,SAAS,IAAI,IAAI,CAAC;AAGpB,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY;;;;;;;;;;AAWzC,MAAM,kBAAkB,UAA0B;CAGhD,MAAM,SAAS,MAAM,WAAW,KAAK,IAAI,UAAU;CACnD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;EAC3B,MAAM,KAAK,OAAO;EAClB,IAAI,OAAO,KAAA,GAAW;EACtB,MAAM,IAAI,SAAS,IAAI,EAAE,KAAK;EAC9B,OAAO,KAAK,KAAK;CACnB;CACA,MAAM,YAAY,MAAM;CACxB,IAAI,cAAc,GAAG,OAAO;CAC5B,MAAM,QAAQ,KAAK;CACnB,OAAO,UAAU,KAAK,MAAM,OAAO,KAAK;AAC1C;AAEA,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,eAAe;AACrB,MAAM,YAAY;AAElB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,MAAM,EAAE,WAAW,IAClC,OAAO,IACL,kBACA,iCACF;CAGF,MAAM,WAAW,EAAE,WAAW;CAE9B,IAAI,EADO,WAAW,YAAY,YAC1B,KAAK,CAAC,GACZ,OAAO,IACL,kBACA,2BACF;CAIF,MAAM,aAAa,WAAW,IAAI;CAClC,MAAM,KAAK,OAAO,EAAE,MAAM,YAAY,aAAa,CAAC,CAAC;CACrD,MAAM,KAAK,OACT,EAAE,MAAM,aAAa,GAAG,aAAa,CAAC,CACxC;CACA,MAAM,KAAK,OACT,EAAE,MAAM,aAAa,GAAG,aAAa,CAAC,CACxC;CAKA,IAAI,CAAC,YADQ,MAAO,IACG,IAAI,EAAE,GAC3B,OAAO,IACL,qBACA,8BACF;CAKF,MAAM,WAAW,eADJ,EAAE,MAAM,GAAG,EACW,CAAC;CACpC,IAAI,EAAE,GAAG,EAAE,MAAM,UACf,OAAO,IACL,oBACA,gCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;AAEvD,MAAM,kBAAkB,UACtB,MAAM,OAAO,UAAU,GAAG,MAAM,SAAS,CAAC,CAAC;;AAG7C,MAAM,iBAAyB;CAE7B,MAAM,eADW,KAAK,OAAO,IAAI,KACD,IAAI;CACpC,IAAI,SAAS;CACb,KAAK,IAAI,IAAI,GAAG,IAAI,cAAc,KAChC,UAAU,eAAe,YAAY;CAGvC,MAAM,OAAO,UAAU,KAAM,IAAI;CACjC,MAAM,QAAQ,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;CACtD,MAAM,MAAM,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;CACpD,IAAI,YAAY;CAChB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,aAAa,eAAe,SAAS;CAGvC,MAAM,OACJ,GAAG,SAAS,OAAO,OAAO,GAAG,EAAE,SAAS,GAAG,GAAG,IAC3C,QAAQ,MAAM;CACnB,OAAO,GAAG,OAAO,eAAe,IAAI;AACtC;;;;;;AAOA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,oCACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,IAAI,EAAE;CAChB,UAAU,CAAC,iBAAiB,cAAc;CAC1C;CACA;CACA;CACA;CACA,WACE;AACJ"}
package/dist/my/nric.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
1
+ import { CountryValidator, ParsedPersonId, ValidateResult } from "../types.js";
2
2
 
3
3
  //#region src/my/nric.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -12,7 +12,7 @@ declare const parse: (value: string) => ParsedPersonId | null;
12
12
  /** Generate a random valid Malaysian NRIC. */
13
13
  declare const generate: () => string;
14
14
  /** Malaysian National Registration Identity Card. */
15
- declare const nric: Validator<ParsedPersonId>;
15
+ declare const nric: CountryValidator<"MY", ParsedPersonId>;
16
16
  //#endregion
17
17
  export { compact, nric as default, format, generate, parse, validate };
18
18
  //# sourceMappingURL=nric.d.ts.map
package/dist/my/nric.js CHANGED
@@ -1,23 +1,10 @@
1
1
  import { clean } from "../_util/clean.js";
2
+ import { isValidDate } from "../_util/date.js";
2
3
  import { randomInt } from "../_util/generate.js";
3
4
  import { err } from "../_util/result.js";
4
5
  import { isdigits } from "../_util/strings.js";
5
- import { isValidDate } from "../_util/date.js";
6
6
  //#region src/my/nric.ts
7
7
  /**
8
- * NRIC (Malaysian National Registration Identity
9
- * Card Number, Nombor Kad Pengenalan).
10
- *
11
- * 12 digits: YYMMDD (birth date) + PB (place of
12
- * birth, 2 digits) + SSS (serial) + G (gender:
13
- * odd = male, even = female).
14
- *
15
- * No checksum; validation is structural (valid date
16
- * and valid place-of-birth code).
17
- *
18
- * @see https://en.wikipedia.org/wiki/Malaysian_identity_card
19
- */
20
- /**
21
8
  * Valid place-of-birth codes (2-digit).
22
9
  * Codes 01-16 are states, 21-59 are pre-2000
23
10
  * state codes, 60-68 born outside (ASEAN),
@@ -182,6 +169,7 @@ const nric = {
182
169
  "kad pengenalan"
183
170
  ],
184
171
  candidatePattern: "\\d{6}-?\\d{2}-?\\d{4}",
172
+ scope: "country",
185
173
  country: "MY",
186
174
  entityType: "person",
187
175
  description: "12-digit identity card number encoding birth date, place of birth, and gender",
@@ -1 +1 @@
1
- {"version":3,"file":"nric.js","names":[],"sources":["../../src/my/nric.ts"],"sourcesContent":["/**\n * NRIC (Malaysian National Registration Identity\n * Card Number, Nombor Kad Pengenalan).\n *\n * 12 digits: YYMMDD (birth date) + PB (place of\n * birth, 2 digits) + SSS (serial) + G (gender:\n * odd = male, even = female).\n *\n * No checksum; validation is structural (valid date\n * and valid place-of-birth code).\n *\n * @see https://en.wikipedia.org/wiki/Malaysian_identity_card\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\n/**\n * Valid place-of-birth codes (2-digit).\n * Codes 01-16 are states, 21-59 are pre-2000\n * state codes, 60-68 born outside (ASEAN),\n * 71-72/74-79 foreign nationals, 82-93 regions,\n * 98-99 legacy.\n */\nconst VALID_PB_CODES = new Set([\n \"01\",\n \"02\",\n \"03\",\n \"04\",\n \"05\",\n \"06\",\n \"07\",\n \"08\",\n \"09\",\n \"10\",\n \"11\",\n \"12\",\n \"13\",\n \"14\",\n \"15\",\n \"16\",\n \"21\",\n \"22\",\n \"23\",\n \"24\",\n \"25\",\n \"26\",\n \"27\",\n \"28\",\n \"29\",\n \"30\",\n \"31\",\n \"32\",\n \"33\",\n \"34\",\n \"35\",\n \"36\",\n \"37\",\n \"38\",\n \"39\",\n \"40\",\n \"41\",\n \"42\",\n \"43\",\n \"44\",\n \"45\",\n \"46\",\n \"47\",\n \"48\",\n \"49\",\n \"50\",\n \"51\",\n \"52\",\n \"53\",\n \"54\",\n \"55\",\n \"56\",\n \"57\",\n \"58\",\n \"59\",\n \"60\",\n \"61\",\n \"62\",\n \"63\",\n \"64\",\n \"65\",\n \"66\",\n \"67\",\n \"68\",\n \"71\",\n \"72\",\n \"74\",\n \"75\",\n \"76\",\n \"77\",\n \"78\",\n \"79\",\n \"82\",\n \"83\",\n \"84\",\n \"85\",\n \"86\",\n \"87\",\n \"88\",\n \"89\",\n \"90\",\n \"91\",\n \"92\",\n \"93\",\n \"98\",\n \"99\",\n]);\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\n/**\n * Resolve the birth year from a 2-digit year.\n * Years after the reference year are assumed to be\n * in the previous century. Accepts an explicit\n * reference year to avoid multiple clock reads.\n */\nconst resolveYear = (\n yy: number,\n referenceYear: number,\n): number => {\n const century = Math.floor(referenceYear / 100);\n const year = century * 100 + yy;\n return year > referenceYear ? year - 100 : year;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"NRIC must be exactly 12 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"NRIC must contain only digits\",\n );\n }\n\n // Validate birth date (YYMMDD)\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n\n const now = new Date().getFullYear();\n const year = resolveYear(yy, now);\n\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"NRIC contains an invalid birth date\",\n );\n }\n\n // Validate place-of-birth code\n const pb = v.slice(6, 8);\n if (!VALID_PB_CODES.has(pb)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Invalid place-of-birth code: \" + pb,\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, 6) + \"-\" + v.slice(6, 8) + \"-\" + v.slice(8)\n );\n};\n\n/**\n * Extract birth date and gender from an NRIC.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n const now = new Date().getFullYear();\n const year = resolveYear(yy, now);\n\n // Last digit: odd = male, even = female\n const lastDigit = Number(v[11]);\n const gender = lastDigit % 2 === 1 ? \"male\" : \"female\";\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender,\n };\n};\n\nconst PB_CODES = [...VALID_PB_CODES];\n\n/** Generate a random valid Malaysian NRIC. */\nconst generate = (): string => {\n const year = randomInt(1950, 2024);\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n const pb =\n PB_CODES[randomInt(0, PB_CODES.length - 1)] ?? \"01\";\n const serial = String(randomInt(0, 999)).padStart(3, \"0\");\n const isMale = Math.random() < 0.5;\n const lastDigit = isMale\n ? String(randomInt(0, 4) * 2 + 1)\n : String(randomInt(0, 4) * 2);\n\n return (\n `${String(year % 100).padStart(2, \"0\")}` +\n `${month}${day}${pb}${serial}${lastDigit}`\n );\n};\n\n/** Malaysian National Registration Identity Card. */\nconst nric: Validator<ParsedPersonId> = {\n name: \"Malaysian National Registration Identity Card Number\",\n localName: \"Nombor Kad Pengenalan\",\n abbreviation: \"NRIC\",\n aliases: [\"NRIC\", \"MyKad\", \"kad pengenalan\"] as const,\n candidatePattern: \"\\\\d{6}-?\\\\d{2}-?\\\\d{4}\",\n country: \"MY\",\n entityType: \"person\",\n description:\n \"12-digit identity card number encoding birth date, place of birth, and gender\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/Malaysian_identity_card\",\n lengths: [12] as const,\n examples: [\"770305021234\", \"880715141234\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default nric;\nexport { compact, format, generate, parse, validate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;;;;;;;AAQpB,MAAM,eACJ,IACA,kBACW;CAEX,MAAM,OADU,KAAK,MAAM,gBAAgB,IAAI,GACxB,MAAM;AAC7B,QAAO,OAAO,gBAAgB,OAAO,MAAM;;AAG7C,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,iCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,gCACD;CAIH,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AAKhC,KAAI,CAAC,YAFQ,YAAY,qBADb,IAAI,MAAM,EAAC,aAAa,CACH,EAEV,IAAI,GAAG,CAC5B,QAAO,IACL,qBACA,sCACD;CAIH,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE;AACxB,KAAI,CAAC,eAAe,IAAI,GAAG,CACzB,QAAO,IACL,qBACA,kCAAkC,GACnC;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,QACE,EAAE,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE;;;;;;AAQ1D,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;CAEhC,MAAM,OAAO,YAAY,qBADb,IAAI,MAAM,EAAC,aAAa,CACH;CAIjC,MAAM,SADY,OAAO,EAAE,IAAI,GACJ,MAAM,IAAI,SAAS;AAE9C,QAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,GAAG;EACrC;EACD;;AAGH,MAAM,WAAW,CAAC,GAAG,eAAe;;AAGpC,MAAM,iBAAyB;CAC7B,MAAM,OAAO,UAAU,MAAM,KAAK;CAClC,MAAM,QAAQ,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;CACvD,MAAM,MAAM,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;CACrD,MAAM,KACJ,SAAS,UAAU,GAAG,SAAS,SAAS,EAAE,KAAK;CACjD,MAAM,SAAS,OAAO,UAAU,GAAG,IAAI,CAAC,CAAC,SAAS,GAAG,IAAI;CAEzD,MAAM,YADS,KAAK,QAAQ,GAAG,KAE3B,OAAO,UAAU,GAAG,EAAE,GAAG,IAAI,EAAE,GAC/B,OAAO,UAAU,GAAG,EAAE,GAAG,EAAE;AAE/B,QACE,GAAG,OAAO,OAAO,IAAI,CAAC,SAAS,GAAG,IAAI,GACnC,QAAQ,MAAM,KAAK,SAAS;;;AAKnC,MAAM,OAAkC;CACtC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EAAC;EAAQ;EAAS;EAAiB;CAC5C,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,aACE;CACF,WACE;CACF,SAAS,CAAC,GAAG;CACb,UAAU,CAAC,gBAAgB,eAAe;CAC1C;CACA;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"nric.js","names":[],"sources":["../../src/my/nric.ts"],"sourcesContent":["/**\n * NRIC (Malaysian National Registration Identity\n * Card Number, Nombor Kad Pengenalan).\n *\n * 12 digits: YYMMDD (birth date) + PB (place of\n * birth, 2 digits) + SSS (serial) + G (gender:\n * odd = male, even = female).\n *\n * No checksum; validation is structural (valid date\n * and valid place-of-birth code).\n *\n * @see https://en.wikipedia.org/wiki/Malaysian_identity_card\n */\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n CountryValidator,\n} from \"../types\";\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\n/**\n * Valid place-of-birth codes (2-digit).\n * Codes 01-16 are states, 21-59 are pre-2000\n * state codes, 60-68 born outside (ASEAN),\n * 71-72/74-79 foreign nationals, 82-93 regions,\n * 98-99 legacy.\n */\nconst VALID_PB_CODES = new Set([\n \"01\",\n \"02\",\n \"03\",\n \"04\",\n \"05\",\n \"06\",\n \"07\",\n \"08\",\n \"09\",\n \"10\",\n \"11\",\n \"12\",\n \"13\",\n \"14\",\n \"15\",\n \"16\",\n \"21\",\n \"22\",\n \"23\",\n \"24\",\n \"25\",\n \"26\",\n \"27\",\n \"28\",\n \"29\",\n \"30\",\n \"31\",\n \"32\",\n \"33\",\n \"34\",\n \"35\",\n \"36\",\n \"37\",\n \"38\",\n \"39\",\n \"40\",\n \"41\",\n \"42\",\n \"43\",\n \"44\",\n \"45\",\n \"46\",\n \"47\",\n \"48\",\n \"49\",\n \"50\",\n \"51\",\n \"52\",\n \"53\",\n \"54\",\n \"55\",\n \"56\",\n \"57\",\n \"58\",\n \"59\",\n \"60\",\n \"61\",\n \"62\",\n \"63\",\n \"64\",\n \"65\",\n \"66\",\n \"67\",\n \"68\",\n \"71\",\n \"72\",\n \"74\",\n \"75\",\n \"76\",\n \"77\",\n \"78\",\n \"79\",\n \"82\",\n \"83\",\n \"84\",\n \"85\",\n \"86\",\n \"87\",\n \"88\",\n \"89\",\n \"90\",\n \"91\",\n \"92\",\n \"93\",\n \"98\",\n \"99\",\n]);\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\n/**\n * Resolve the birth year from a 2-digit year.\n * Years after the reference year are assumed to be\n * in the previous century. Accepts an explicit\n * reference year to avoid multiple clock reads.\n */\nconst resolveYear = (\n yy: number,\n referenceYear: number,\n): number => {\n const century = Math.floor(referenceYear / 100);\n const year = century * 100 + yy;\n return year > referenceYear ? year - 100 : year;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"NRIC must be exactly 12 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"NRIC must contain only digits\",\n );\n }\n\n // Validate birth date (YYMMDD)\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n\n const now = new Date().getFullYear();\n const year = resolveYear(yy, now);\n\n if (!isValidDate(year, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"NRIC contains an invalid birth date\",\n );\n }\n\n // Validate place-of-birth code\n const pb = v.slice(6, 8);\n if (!VALID_PB_CODES.has(pb)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Invalid place-of-birth code: \" + pb,\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, 6) + \"-\" + v.slice(6, 8) + \"-\" + v.slice(8)\n );\n};\n\n/**\n * Extract birth date and gender from an NRIC.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n const now = new Date().getFullYear();\n const year = resolveYear(yy, now);\n\n // Last digit: odd = male, even = female\n const lastDigit = Number(v[11]);\n const gender = lastDigit % 2 === 1 ? \"male\" : \"female\";\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender,\n };\n};\n\nconst PB_CODES = [...VALID_PB_CODES];\n\n/** Generate a random valid Malaysian NRIC. */\nconst generate = (): string => {\n const year = randomInt(1950, 2024);\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n const pb =\n PB_CODES[randomInt(0, PB_CODES.length - 1)] ?? \"01\";\n const serial = String(randomInt(0, 999)).padStart(3, \"0\");\n const isMale = Math.random() < 0.5;\n const lastDigit = isMale\n ? String(randomInt(0, 4) * 2 + 1)\n : String(randomInt(0, 4) * 2);\n\n return (\n `${String(year % 100).padStart(2, \"0\")}` +\n `${month}${day}${pb}${serial}${lastDigit}`\n );\n};\n\n/** Malaysian National Registration Identity Card. */\nconst nric: CountryValidator<\"MY\", ParsedPersonId> = {\n name: \"Malaysian National Registration Identity Card Number\",\n localName: \"Nombor Kad Pengenalan\",\n abbreviation: \"NRIC\",\n aliases: [\"NRIC\", \"MyKad\", \"kad pengenalan\"] as const,\n candidatePattern: \"\\\\d{6}-?\\\\d{2}-?\\\\d{4}\",\n scope: \"country\",\n country: \"MY\",\n entityType: \"person\",\n description:\n \"12-digit identity card number encoding birth date, place of birth, and gender\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/Malaysian_identity_card\",\n lengths: [12] as const,\n examples: [\"770305021234\", \"880715141234\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default nric;\nexport { compact, format, generate, parse, validate };\n"],"mappings":";;;;;;;;;;;;;AAiCA,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;;;;;;;AAQnB,MAAM,eACJ,IACA,kBACW;CAEX,MAAM,OADU,KAAK,MAAM,gBAAgB,GACxB,IAAI,MAAM;CAC7B,OAAO,OAAO,gBAAgB,OAAO,MAAM;AAC7C;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,gCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,+BACF;CAIF,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAK/B,IAAI,CAAC,YAFQ,YAAY,qBADb,IAAI,KAAK,GAAE,YACQ,CAEX,GAAG,IAAI,EAAE,GAC3B,OAAO,IACL,qBACA,qCACF;CAIF,MAAM,KAAK,EAAE,MAAM,GAAG,CAAC;CACvB,IAAI,CAAC,eAAe,IAAI,EAAE,GACxB,OAAO,IACL,qBACA,kCAAkC,EACpC;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OACE,EAAE,MAAM,GAAG,CAAC,IAAI,MAAM,EAAE,MAAM,GAAG,CAAC,IAAI,MAAM,EAAE,MAAM,CAAC;AAEzD;;;;;AAMA,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,KAAK;CAC7B,IAAI,CAAC,OAAO,OAAO,OAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAE/B,MAAM,OAAO,YAAY,qBADb,IAAI,KAAK,GAAE,YACQ,CAAC;CAIhC,MAAM,SADY,OAAO,EAAE,GACJ,IAAI,MAAM,IAAI,SAAS;CAE9C,OAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,EAAE;EACpC;CACF;AACF;AAEA,MAAM,WAAW,CAAC,GAAG,cAAc;;AAGnC,MAAM,iBAAyB;CAC7B,MAAM,OAAO,UAAU,MAAM,IAAI;CACjC,MAAM,QAAQ,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;CACtD,MAAM,MAAM,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;CACpD,MAAM,KACJ,SAAS,UAAU,GAAG,SAAS,SAAS,CAAC,MAAM;CACjD,MAAM,SAAS,OAAO,UAAU,GAAG,GAAG,CAAC,EAAE,SAAS,GAAG,GAAG;CAExD,MAAM,YADS,KAAK,OAAO,IAAI,KAE3B,OAAO,UAAU,GAAG,CAAC,IAAI,IAAI,CAAC,IAC9B,OAAO,UAAU,GAAG,CAAC,IAAI,CAAC;CAE9B,OACE,GAAG,OAAO,OAAO,GAAG,EAAE,SAAS,GAAG,GAAG,IAClC,QAAQ,MAAM,KAAK,SAAS;AAEnC;;AAGA,MAAM,OAA+C;CACnD,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EAAC;EAAQ;EAAS;CAAgB;CAC3C,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,aACE;CACF,WACE;CACF,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,gBAAgB,cAAc;CACzC;CACA;CACA;CACA;CACA;AACF"}
package/dist/ng/nin.d.ts CHANGED
@@ -1,13 +1,24 @@
1
- import { ValidateResult, Validator } from "../types.js";
1
+ import { CountryValidator, ValidateResult } from "../types.js";
2
2
 
3
3
  //#region src/ng/nin.d.ts
4
4
  /** Generate a random valid Nigerian NIN. */
5
5
  declare const generate: () => string;
6
+ /**
7
+ * NIN (National Identification Number, Nigeria).
8
+ *
9
+ * 11-digit number randomly assigned by NIMC (National
10
+ * Identity Management Commission). No checksum; the
11
+ * digits are non-intelligible and carry no embedded
12
+ * meaning. Once assigned, a NIN is permanent and
13
+ * cannot be reassigned.
14
+ *
15
+ * @see https://nimc.gov.ng/about-nin/
16
+ */
6
17
  declare const compact: (value: string) => string;
7
18
  declare const validate: (value: string) => ValidateResult;
8
19
  declare const format: (value: string) => string;
9
20
  /** Nigerian National Identification Number. */
10
- declare const nin: Validator;
21
+ declare const nin: CountryValidator<"NG">;
11
22
  //#endregion
12
23
  export { compact, nin as default, format, generate, validate };
13
24
  //# sourceMappingURL=nin.d.ts.map
package/dist/ng/nin.js CHANGED
@@ -3,17 +3,6 @@ import { randomDigits } from "../_util/generate.js";
3
3
  import { err } from "../_util/result.js";
4
4
  import { isdigits } from "../_util/strings.js";
5
5
  //#region src/ng/nin.ts
6
- /**
7
- * NIN (National Identification Number, Nigeria).
8
- *
9
- * 11-digit number randomly assigned by NIMC (National
10
- * Identity Management Commission). No checksum; the
11
- * digits are non-intelligible and carry no embedded
12
- * meaning. Once assigned, a NIN is permanent and
13
- * cannot be reassigned.
14
- *
15
- * @see https://nimc.gov.ng/about-nin/
16
- */
17
6
  /** Generate a random valid Nigerian NIN. */
18
7
  const generate = () => randomDigits(11);
19
8
  const compact = (value) => clean(value, " -");
@@ -37,6 +26,7 @@ const nin = {
37
26
  abbreviation: "NIN",
38
27
  aliases: ["NIN", "National Identification Number"],
39
28
  candidatePattern: "\\d{11}",
29
+ scope: "country",
40
30
  country: "NG",
41
31
  entityType: "person",
42
32
  lengths: [11],
@@ -1 +1 @@
1
- {"version":3,"file":"nin.js","names":[],"sources":["../../src/ng/nin.ts"],"sourcesContent":["/** Generate a random valid Nigerian NIN. */\nconst generate = (): string => randomDigits(11);\n\n/**\n * NIN (National Identification Number, Nigeria).\n *\n * 11-digit number randomly assigned by NIMC (National\n * Identity Management Commission). No checksum; the\n * digits are non-intelligible and carry no embedded\n * meaning. Once assigned, a NIN is permanent and\n * cannot be reassigned.\n *\n * @see https://nimc.gov.ng/about-nin/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"Nigerian NIN must be 11 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Nigerian NIN must contain only digits\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 3)} ${v.slice(3, 7)} ${v.slice(7)}`;\n};\n\n/** Nigerian National Identification Number. */\nconst nin: Validator = {\n name: \"National Identification Number\",\n localName: \"National Identification Number\",\n abbreviation: \"NIN\",\n aliases: [\n \"NIN\",\n \"National Identification Number\",\n ] as const,\n candidatePattern: \"\\\\d{11}\",\n country: \"NG\",\n entityType: \"person\",\n lengths: [11] as const,\n examples: [\"13478900989\", \"70123456789\"] as const,\n description:\n \"11-digit national identity number issued by NIMC\",\n sourceUrl: \"https://nimc.gov.ng/about-nin/\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nin;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;AACA,MAAM,iBAAyB,aAAa,GAAG;AAqB/C,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,iCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,wCACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,QAAO,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE;;;AAIxD,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,iCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,GAAG;CACb,UAAU,CAAC,eAAe,cAAc;CACxC,aACE;CACF,WAAW;CACX;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"nin.js","names":[],"sources":["../../src/ng/nin.ts"],"sourcesContent":["/** Generate a random valid Nigerian NIN. */\nconst generate = (): string => randomDigits(11);\n\n/**\n * NIN (National Identification Number, Nigeria).\n *\n * 11-digit number randomly assigned by NIMC (National\n * Identity Management Commission). No checksum; the\n * digits are non-intelligible and carry no embedded\n * meaning. Once assigned, a NIN is permanent and\n * cannot be reassigned.\n *\n * @see https://nimc.gov.ng/about-nin/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"Nigerian NIN must be 11 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Nigerian NIN must contain only digits\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 3)} ${v.slice(3, 7)} ${v.slice(7)}`;\n};\n\n/** Nigerian National Identification Number. */\nconst nin: CountryValidator<\"NG\"> = {\n name: \"National Identification Number\",\n localName: \"National Identification Number\",\n abbreviation: \"NIN\",\n aliases: [\n \"NIN\",\n \"National Identification Number\",\n ] as const,\n candidatePattern: \"\\\\d{11}\",\n scope: \"country\",\n country: \"NG\",\n entityType: \"person\",\n lengths: [11] as const,\n examples: [\"13478900989\", \"70123456789\"] as const,\n description:\n \"11-digit national identity number issued by NIMC\",\n sourceUrl: \"https://nimc.gov.ng/about-nin/\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nin;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AACA,MAAM,iBAAyB,aAAa,EAAE;AAwB9C,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,gCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,uCACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACvD;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,gCACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,eAAe,aAAa;CACvC,aACE;CACF,WAAW;CACX;CACA;CACA;CACA;AACF"}
package/dist/ni/ruc.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ValidateResult, Validator } from "../types.js";
1
+ import { CountryValidator, ValidateResult } from "../types.js";
2
2
 
3
3
  //#region src/ni/ruc.d.ts
4
4
  /**
@@ -16,7 +16,7 @@ declare const format: (value: string) => string;
16
16
  /** Generate a random valid Nicaraguan RUC (legal entity). */
17
17
  declare const generate: () => string;
18
18
  /** Nicaragua tax identification number. */
19
- declare const ruc: Validator;
19
+ declare const ruc: CountryValidator<"NI">;
20
20
  //#endregion
21
21
  export { compact, ruc as default, format, generate, validate };
22
22
  //# sourceMappingURL=ruc.d.ts.map
package/dist/ni/ruc.js CHANGED
@@ -4,29 +4,6 @@ import { err } from "../_util/result.js";
4
4
  import { isdigits } from "../_util/strings.js";
5
5
  //#region src/ni/ruc.ts
6
6
  /**
7
- * RUC (Registro Único de Contribuyente, Nicaragua
8
- * tax number).
9
- *
10
- * For natural persons the RUC is the cédula de
11
- * identidad: 14 characters structured as
12
- * MMM-DDMMYY-NNNNL where:
13
- * - MMM = municipality code (001–999)
14
- * - DDMMYY = birth date
15
- * - NNNN = sequential number
16
- * - L = check letter (mod 23, ISO 7064)
17
- *
18
- * For legal entities (Personas Jurídicas) the RUC
19
- * starts with "J" followed by 13 digits. No public
20
- * check-digit algorithm is documented for the "J"
21
- * format, so validation is format-only.
22
- *
23
- * The check letter for natural persons uses modulo 23
24
- * with a 23-letter alphabet that excludes I, O, and Z
25
- * to avoid confusion with digits.
26
- *
27
- * @see https://www.dgi.gob.ni/
28
- */
29
- /**
30
7
  * Check letter alphabet (mod 23). Excludes I, O, Z
31
8
  * to prevent transcription errors.
32
9
  */
@@ -96,6 +73,7 @@ const ruc = {
96
73
  abbreviation: "RUC",
97
74
  aliases: ["RUC"],
98
75
  candidatePattern: "[JKME]\\d{13}",
76
+ scope: "country",
99
77
  country: "NI",
100
78
  entityType: "any",
101
79
  description: "Tax identifier issued by Nicaragua's DGI",
@@ -1 +1 @@
1
- {"version":3,"file":"ruc.js","names":[],"sources":["../../src/ni/ruc.ts"],"sourcesContent":["/**\n * RUC (Registro Único de Contribuyente, Nicaragua\n * tax number).\n *\n * For natural persons the RUC is the cédula de\n * identidad: 14 characters structured as\n * MMM-DDMMYY-NNNNL where:\n * - MMM = municipality code (001–999)\n * - DDMMYY = birth date\n * - NNNN = sequential number\n * - L = check letter (mod 23, ISO 7064)\n *\n * For legal entities (Personas Jurídicas) the RUC\n * starts with \"J\" followed by 13 digits. No public\n * check-digit algorithm is documented for the \"J\"\n * format, so validation is format-only.\n *\n * The check letter for natural persons uses modulo 23\n * with a 23-letter alphabet that excludes I, O, and Z\n * to avoid confusion with digits.\n *\n * @see https://www.dgi.gob.ni/\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 * Check letter alphabet (mod 23). Excludes I, O, Z\n * to prevent transcription errors.\n */\nconst CHECK_ALPHABET = \"ABCDEFGHJKLMNPQRSTUVWXY\";\n\n/**\n * Compact: strip spaces, hyphens, and uppercase.\n */\nconst compact = (value: string): string =>\n clean(value, \" -\").trim().toUpperCase();\n\n/**\n * Validate a birth date encoded as DDMMYY.\n * Returns true if the date components are plausible.\n */\nconst isValidDate = (ddmmyy: string): boolean => {\n const day = Number(ddmmyy.slice(0, 2));\n const month = Number(ddmmyy.slice(2, 4));\n\n if (month < 1 || month > 12) return false;\n if (day < 1 || day > 31) return false;\n\n return true;\n};\n\n/**\n * Calculate the check letter for a 13-digit body\n * using modulo 23.\n */\nconst calcCheckLetter = (body: string): string => {\n let n = 0n;\n for (const ch of body) {\n n = n * 10n + BigInt(ch);\n }\n const idx = Number(n % 23n);\n // SAFETY: idx is always 0–22 (mod 23), and\n // CHECK_ALPHABET has exactly 23 characters.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return CHECK_ALPHABET[idx]!;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 14) {\n return err(\n \"INVALID_LENGTH\",\n \"Nicaragua RUC must be 14 characters\",\n );\n }\n\n // Legal entity: starts with J + 13 digits\n if (v[0] === \"J\") {\n if (!isdigits(v.slice(1))) {\n return err(\n \"INVALID_FORMAT\",\n \"Nicaragua legal entity RUC must be \" +\n \"J followed by 13 digits\",\n );\n }\n return { valid: true, compact: v };\n }\n\n // Natural person: 13 digits + 1 letter\n const body = v.slice(0, 13);\n // SAFETY: length is validated as exactly 14 above.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const check = v[13]!;\n\n if (!isdigits(body)) {\n return err(\n \"INVALID_FORMAT\",\n \"Nicaragua RUC body must contain only digits\",\n );\n }\n\n if (!CHECK_ALPHABET.includes(check)) {\n return err(\n \"INVALID_FORMAT\",\n \"Nicaragua RUC check letter is invalid\",\n );\n }\n\n // Validate date portion (positions 3–8: DDMMYY)\n const datePart = body.slice(3, 9);\n if (!isValidDate(datePart)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Nicaragua RUC contains an invalid \" + \"birth date\",\n );\n }\n\n // Verify check letter\n const expected = calcCheckLetter(body);\n if (check !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Nicaragua RUC check letter does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\n/**\n * Format: insert hyphens as MMM-DDMMYY-NNNNL\n * for natural persons. Legal entities are returned\n * in compact form (JNNNNNNNNNNNNN); no documented\n * segmentation exists for the J-prefix format.\n */\nconst format = (value: string): string => {\n const v = compact(value);\n if (v[0] === \"J\") {\n return `J-${v.slice(1)}`;\n }\n return (\n `${v.slice(0, 3)}-${v.slice(3, 9)}` + `-${v.slice(9)}`\n );\n};\n\n/** Generate a random valid Nicaraguan RUC (legal entity). */\nconst generate = (): string => \"J\" + randomDigits(13);\n\n/** Nicaragua tax identification number. */\nconst ruc: Validator = {\n name: \"Tax Identification Number\",\n localName: \"Registro Único de Contribuyente\",\n abbreviation: \"RUC\",\n aliases: [\"RUC\"] as const,\n candidatePattern: \"[JKME]\\\\d{13}\",\n country: \"NI\",\n entityType: \"any\",\n description: \"Tax identifier issued by Nicaragua's DGI\",\n sourceUrl: \"https://www.dgi.gob.ni/\",\n lengths: [14] as const,\n examples: [\"6071904680001F\", \"2811505850012D\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default ruc;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAM,iBAAiB;;;;AAKvB,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,CAAC,MAAM,CAAC,aAAa;;;;;AAMzC,MAAM,eAAe,WAA4B;CAC/C,MAAM,MAAM,OAAO,OAAO,MAAM,GAAG,EAAE,CAAC;CACtC,MAAM,QAAQ,OAAO,OAAO,MAAM,GAAG,EAAE,CAAC;AAExC,KAAI,QAAQ,KAAK,QAAQ,GAAI,QAAO;AACpC,KAAI,MAAM,KAAK,MAAM,GAAI,QAAO;AAEhC,QAAO;;;;;;AAOT,MAAM,mBAAmB,SAAyB;CAChD,IAAI,IAAI;AACR,MAAK,MAAM,MAAM,KACf,KAAI,IAAI,MAAM,OAAO,GAAG;AAM1B,QAAO,eAJK,OAAO,IAAI,IAAI;;AAO7B,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,sCACD;AAIH,KAAI,EAAE,OAAO,KAAK;AAChB,MAAI,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,CACvB,QAAO,IACL,kBACA,6DAED;AAEH,SAAO;GAAE,OAAO;GAAM,SAAS;GAAG;;CAIpC,MAAM,OAAO,EAAE,MAAM,GAAG,GAAG;CAG3B,MAAM,QAAQ,EAAE;AAEhB,KAAI,CAAC,SAAS,KAAK,CACjB,QAAO,IACL,kBACA,8CACD;AAGH,KAAI,CAAC,eAAe,SAAS,MAAM,CACjC,QAAO,IACL,kBACA,wCACD;AAKH,KAAI,CAAC,YADY,KAAK,MAAM,GAAG,EAAE,CACP,CACxB,QAAO,IACL,qBACA,+CACD;AAKH,KAAI,UADa,gBAAgB,KAAK,CAEpC,QAAO,IACL,oBACA,4CACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;;;;;;;AASpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,OAAO,IACX,QAAO,KAAK,EAAE,MAAM,EAAE;AAExB,QACE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAA,GAAS,EAAE,MAAM,EAAE;;;AAKxD,MAAM,iBAAyB,MAAM,aAAa,GAAG;;AAGrD,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,MAAM;CAChB,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,aAAa;CACb,WAAW;CACX,SAAS,CAAC,GAAG;CACb,UAAU,CAAC,kBAAkB,iBAAiB;CAC9C;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"ruc.js","names":[],"sources":["../../src/ni/ruc.ts"],"sourcesContent":["/**\n * RUC (Registro Único de Contribuyente, Nicaragua\n * tax number).\n *\n * For natural persons the RUC is the cédula de\n * identidad: 14 characters structured as\n * MMM-DDMMYY-NNNNL where:\n * - MMM = municipality code (001–999)\n * - DDMMYY = birth date\n * - NNNN = sequential number\n * - L = check letter (mod 23, ISO 7064)\n *\n * For legal entities (Personas Jurídicas) the RUC\n * starts with \"J\" followed by 13 digits. No public\n * check-digit algorithm is documented for the \"J\"\n * format, so validation is format-only.\n *\n * The check letter for natural persons uses modulo 23\n * with a 23-letter alphabet that excludes I, O, and Z\n * to avoid confusion with digits.\n *\n * @see https://www.dgi.gob.ni/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/**\n * Check letter alphabet (mod 23). Excludes I, O, Z\n * to prevent transcription errors.\n */\nconst CHECK_ALPHABET = \"ABCDEFGHJKLMNPQRSTUVWXY\";\n\n/**\n * Compact: strip spaces, hyphens, and uppercase.\n */\nconst compact = (value: string): string =>\n clean(value, \" -\").trim().toUpperCase();\n\n/**\n * Validate a birth date encoded as DDMMYY.\n * Returns true if the date components are plausible.\n */\nconst isValidDate = (ddmmyy: string): boolean => {\n const day = Number(ddmmyy.slice(0, 2));\n const month = Number(ddmmyy.slice(2, 4));\n\n if (month < 1 || month > 12) return false;\n if (day < 1 || day > 31) return false;\n\n return true;\n};\n\n/**\n * Calculate the check letter for a 13-digit body\n * using modulo 23.\n */\nconst calcCheckLetter = (body: string): string => {\n let n = 0n;\n for (const ch of body) {\n n = n * 10n + BigInt(ch);\n }\n const idx = Number(n % 23n);\n // SAFETY: idx is always 0–22 (mod 23), and\n // CHECK_ALPHABET has exactly 23 characters.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return CHECK_ALPHABET[idx]!;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 14) {\n return err(\n \"INVALID_LENGTH\",\n \"Nicaragua RUC must be 14 characters\",\n );\n }\n\n // Legal entity: starts with J + 13 digits\n if (v[0] === \"J\") {\n if (!isdigits(v.slice(1))) {\n return err(\n \"INVALID_FORMAT\",\n \"Nicaragua legal entity RUC must be \" +\n \"J followed by 13 digits\",\n );\n }\n return { valid: true, compact: v };\n }\n\n // Natural person: 13 digits + 1 letter\n const body = v.slice(0, 13);\n // SAFETY: length is validated as exactly 14 above.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const check = v[13]!;\n\n if (!isdigits(body)) {\n return err(\n \"INVALID_FORMAT\",\n \"Nicaragua RUC body must contain only digits\",\n );\n }\n\n if (!CHECK_ALPHABET.includes(check)) {\n return err(\n \"INVALID_FORMAT\",\n \"Nicaragua RUC check letter is invalid\",\n );\n }\n\n // Validate date portion (positions 3–8: DDMMYY)\n const datePart = body.slice(3, 9);\n if (!isValidDate(datePart)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Nicaragua RUC contains an invalid \" + \"birth date\",\n );\n }\n\n // Verify check letter\n const expected = calcCheckLetter(body);\n if (check !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Nicaragua RUC check letter does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\n/**\n * Format: insert hyphens as MMM-DDMMYY-NNNNL\n * for natural persons. Legal entities are returned\n * in compact form (JNNNNNNNNNNNNN); no documented\n * segmentation exists for the J-prefix format.\n */\nconst format = (value: string): string => {\n const v = compact(value);\n if (v[0] === \"J\") {\n return `J-${v.slice(1)}`;\n }\n return (\n `${v.slice(0, 3)}-${v.slice(3, 9)}` + `-${v.slice(9)}`\n );\n};\n\n/** Generate a random valid Nicaraguan RUC (legal entity). */\nconst generate = (): string => \"J\" + randomDigits(13);\n\n/** Nicaragua tax identification number. */\nconst ruc: CountryValidator<\"NI\"> = {\n name: \"Tax Identification Number\",\n localName: \"Registro Único de Contribuyente\",\n abbreviation: \"RUC\",\n aliases: [\"RUC\"] as const,\n candidatePattern: \"[JKME]\\\\d{13}\",\n scope: \"country\",\n country: \"NI\",\n entityType: \"any\",\n description: \"Tax identifier issued by Nicaragua's DGI\",\n sourceUrl: \"https://www.dgi.gob.ni/\",\n lengths: [14] as const,\n examples: [\"6071904680001F\", \"2811505850012D\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default ruc;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;AAsCA,MAAM,iBAAiB;;;;AAKvB,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,EAAE,KAAK,EAAE,YAAY;;;;;AAMxC,MAAM,eAAe,WAA4B;CAC/C,MAAM,MAAM,OAAO,OAAO,MAAM,GAAG,CAAC,CAAC;CACrC,MAAM,QAAQ,OAAO,OAAO,MAAM,GAAG,CAAC,CAAC;CAEvC,IAAI,QAAQ,KAAK,QAAQ,IAAI,OAAO;CACpC,IAAI,MAAM,KAAK,MAAM,IAAI,OAAO;CAEhC,OAAO;AACT;;;;;AAMA,MAAM,mBAAmB,SAAyB;CAChD,IAAI,IAAI;CACR,KAAK,MAAM,MAAM,MACf,IAAI,IAAI,MAAM,OAAO,EAAE;CAMzB,OAAO,eAJK,OAAO,IAAI,GAIC;AAC1B;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,qCACF;CAIF,IAAI,EAAE,OAAO,KAAK;EAChB,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,GACtB,OAAO,IACL,kBACA,4DAEF;EAEF,OAAO;GAAE,OAAO;GAAM,SAAS;EAAE;CACnC;CAGA,MAAM,OAAO,EAAE,MAAM,GAAG,EAAE;CAG1B,MAAM,QAAQ,EAAE;CAEhB,IAAI,CAAC,SAAS,IAAI,GAChB,OAAO,IACL,kBACA,6CACF;CAGF,IAAI,CAAC,eAAe,SAAS,KAAK,GAChC,OAAO,IACL,kBACA,uCACF;CAKF,IAAI,CAAC,YADY,KAAK,MAAM,GAAG,CACP,CAAC,GACvB,OAAO,IACL,qBACA,8CACF;CAKF,IAAI,UADa,gBAAgB,IACZ,GACnB,OAAO,IACL,oBACA,2CACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;;;;;;;AAQA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,OAAO,KACX,OAAO,KAAK,EAAE,MAAM,CAAC;CAEvB,OACE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAA,GAAU,EAAE,MAAM,CAAC;AAEvD;;AAGA,MAAM,iBAAyB,MAAM,aAAa,EAAE;;AAGpD,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,KAAK;CACf,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,aAAa;CACb,WAAW;CACX,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,kBAAkB,gBAAgB;CAC7C;CACA;CACA;CACA;AACF"}