@stll/stdnum 1.0.0 → 2.0.1

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 (705) hide show
  1. package/README.md +1 -4
  2. package/dist/_checksums/luhn.js.map +1 -1
  3. package/dist/_checksums/mod1110.js +1 -1
  4. package/dist/_checksums/mod1110.js.map +1 -1
  5. package/dist/_checksums/mod112.js.map +1 -1
  6. package/dist/_checksums/mod97.js.map +1 -1
  7. package/dist/_checksums/verhoeff.js.map +1 -1
  8. package/dist/_checksums/weighted-sum.js.map +1 -1
  9. package/dist/_util/arabic.js.map +1 -1
  10. package/dist/_util/clean.js.map +1 -1
  11. package/dist/_util/date.js.map +1 -1
  12. package/dist/_util/generate.js.map +1 -1
  13. package/dist/_util/result.js.map +1 -1
  14. package/dist/_util/strings.js.map +1 -1
  15. package/dist/ad/nrt.d.ts +16 -2
  16. package/dist/ad/nrt.js +1 -14
  17. package/dist/ad/nrt.js.map +1 -1
  18. package/dist/ae/eid.d.ts +2 -2
  19. package/dist/ae/eid.js +2 -12
  20. package/dist/ae/eid.js.map +1 -1
  21. package/dist/ai/tin.d.ts +20 -2
  22. package/dist/ai/tin.js +1 -18
  23. package/dist/ai/tin.js.map +1 -1
  24. package/dist/al/nipt.d.ts +13 -2
  25. package/dist/al/nipt.js +1 -11
  26. package/dist/al/nipt.js.map +1 -1
  27. package/dist/am/tin.d.ts +16 -2
  28. package/dist/am/tin.js +1 -14
  29. package/dist/am/tin.js.map +1 -1
  30. package/dist/ar/cbu.d.ts +2 -2
  31. package/dist/ar/cbu.js +1 -9
  32. package/dist/ar/cbu.js.map +1 -1
  33. package/dist/ar/cuit.d.ts +2 -2
  34. package/dist/ar/cuit.js +1 -17
  35. package/dist/ar/cuit.js.map +1 -1
  36. package/dist/ar/dni.d.ts +11 -2
  37. package/dist/ar/dni.js +1 -9
  38. package/dist/ar/dni.js.map +1 -1
  39. package/dist/at/businessid.d.ts +10 -2
  40. package/dist/at/businessid.js +1 -8
  41. package/dist/at/businessid.js.map +1 -1
  42. package/dist/at/tin.d.ts +2 -2
  43. package/dist/at/tin.js +1 -11
  44. package/dist/at/tin.js.map +1 -1
  45. package/dist/at/uid.d.ts +2 -2
  46. package/dist/at/uid.js +2 -10
  47. package/dist/at/uid.js.map +1 -1
  48. package/dist/at/vnr.d.ts +2 -2
  49. package/dist/at/vnr.js +4 -14
  50. package/dist/at/vnr.js.map +1 -1
  51. package/dist/au/abn.d.ts +2 -2
  52. package/dist/au/abn.js +1 -10
  53. package/dist/au/abn.js.map +1 -1
  54. package/dist/au/acn.d.ts +2 -2
  55. package/dist/au/acn.js +1 -10
  56. package/dist/au/acn.js.map +1 -1
  57. package/dist/au/tfn.d.ts +2 -2
  58. package/dist/au/tfn.js +1 -10
  59. package/dist/au/tfn.js.map +1 -1
  60. package/dist/az/voen.d.ts +2 -2
  61. package/dist/az/voen.js +1 -14
  62. package/dist/az/voen.js.map +1 -1
  63. package/dist/ba/jmbg.d.ts +2 -2
  64. package/dist/ba/jmbg.js +3 -11
  65. package/dist/ba/jmbg.js.map +1 -1
  66. package/dist/bd/nid.d.ts +23 -2
  67. package/dist/bd/nid.js +1 -21
  68. package/dist/bd/nid.js.map +1 -1
  69. package/dist/be/bis.d.ts +2 -2
  70. package/dist/be/bis.js +1 -11
  71. package/dist/be/bis.js.map +1 -1
  72. package/dist/be/nn.d.ts +2 -2
  73. package/dist/be/nn.js +1 -11
  74. package/dist/be/nn.js.map +1 -1
  75. package/dist/be/vat.d.ts +2 -2
  76. package/dist/be/vat.js +1 -9
  77. package/dist/be/vat.js.map +1 -1
  78. package/dist/bg/egn.d.ts +2 -2
  79. package/dist/bg/egn.js +3 -18
  80. package/dist/bg/egn.js.map +1 -1
  81. package/dist/bg/pnf.d.ts +2 -2
  82. package/dist/bg/pnf.js +1 -8
  83. package/dist/bg/pnf.js.map +1 -1
  84. package/dist/bg/vat.d.ts +2 -2
  85. package/dist/bg/vat.js +3 -9
  86. package/dist/bg/vat.js.map +1 -1
  87. package/dist/bh/cpr.d.ts +2 -2
  88. package/dist/bh/cpr.js +1 -17
  89. package/dist/bh/cpr.js.map +1 -1
  90. package/dist/bic.d.ts +13 -2
  91. package/dist/bic.js +1 -11
  92. package/dist/bic.js.map +1 -1
  93. package/dist/br/cnpj.d.ts +2 -2
  94. package/dist/br/cnpj.js +1 -20
  95. package/dist/br/cnpj.js.map +1 -1
  96. package/dist/br/cpf.d.ts +2 -2
  97. package/dist/br/cpf.js +1 -14
  98. package/dist/br/cpf.js.map +1 -1
  99. package/dist/by/unp.d.ts +2 -2
  100. package/dist/by/unp.js +3 -14
  101. package/dist/by/unp.js.map +1 -1
  102. package/dist/bz/tin.d.ts +2 -2
  103. package/dist/bz/tin.js +1 -26
  104. package/dist/bz/tin.js.map +1 -1
  105. package/dist/ca/bn.d.ts +2 -2
  106. package/dist/ca/bn.js +2 -10
  107. package/dist/ca/bn.js.map +1 -1
  108. package/dist/ca/sin.d.ts +2 -2
  109. package/dist/ca/sin.js +2 -10
  110. package/dist/ca/sin.js.map +1 -1
  111. package/dist/ch/ssn.d.ts +2 -2
  112. package/dist/ch/ssn.js +1 -9
  113. package/dist/ch/ssn.js.map +1 -1
  114. package/dist/ch/uid.d.ts +2 -2
  115. package/dist/ch/uid.js +1 -9
  116. package/dist/ch/uid.js.map +1 -1
  117. package/dist/ch/vat.d.ts +2 -2
  118. package/dist/ch/vat.js +1 -9
  119. package/dist/ch/vat.js.map +1 -1
  120. package/dist/cl/rut.d.ts +2 -2
  121. package/dist/cl/rut.js +1 -14
  122. package/dist/cl/rut.js.map +1 -1
  123. package/dist/cn/ric.d.ts +2 -2
  124. package/dist/cn/ric.js +3 -14
  125. package/dist/cn/ric.js.map +1 -1
  126. package/dist/cn/uscc.d.ts +2 -2
  127. package/dist/cn/uscc.js +1 -10
  128. package/dist/cn/uscc.js.map +1 -1
  129. package/dist/co/nit.d.ts +2 -2
  130. package/dist/co/nit.js +2 -12
  131. package/dist/co/nit.js.map +1 -1
  132. package/dist/cr/cpf.d.ts +18 -2
  133. package/dist/cr/cpf.js +1 -16
  134. package/dist/cr/cpf.js.map +1 -1
  135. package/dist/creditcard.d.ts +2 -2
  136. package/dist/creditcard.js +5 -14
  137. package/dist/creditcard.js.map +1 -1
  138. package/dist/cu/ni.d.ts +2 -2
  139. package/dist/cu/ni.js +2 -17
  140. package/dist/cu/ni.js.map +1 -1
  141. package/dist/cy/vat.d.ts +2 -2
  142. package/dist/cy/vat.js +1 -8
  143. package/dist/cy/vat.js.map +1 -1
  144. package/dist/cz/dic.d.ts +2 -2
  145. package/dist/cz/dic.js +7 -13
  146. package/dist/cz/dic.js.map +1 -1
  147. package/dist/cz/ico.d.ts +2 -2
  148. package/dist/cz/ico.js +2 -10
  149. package/dist/cz/ico.js.map +1 -1
  150. package/dist/cz/rc.d.ts +2 -2
  151. package/dist/cz/rc.js +2 -26
  152. package/dist/cz/rc.js.map +1 -1
  153. package/dist/de/handelsreg.d.ts +19 -2
  154. package/dist/de/handelsreg.js +1 -17
  155. package/dist/de/handelsreg.js.map +1 -1
  156. package/dist/de/idnr.d.ts +2 -2
  157. package/dist/de/idnr.js +2 -12
  158. package/dist/de/idnr.js.map +1 -1
  159. package/dist/de/stnr.d.ts +17 -2
  160. package/dist/de/stnr.js +1 -15
  161. package/dist/de/stnr.js.map +1 -1
  162. package/dist/de/svnr.d.ts +2 -2
  163. package/dist/de/svnr.js +2 -11
  164. package/dist/de/svnr.js.map +1 -1
  165. package/dist/de/vat.d.ts +2 -2
  166. package/dist/de/vat.js +2 -11
  167. package/dist/de/vat.js.map +1 -1
  168. package/dist/dk/cpr.d.ts +2 -2
  169. package/dist/dk/cpr.js +2 -10
  170. package/dist/dk/cpr.js.map +1 -1
  171. package/dist/dk/cvr.d.ts +2 -2
  172. package/dist/dk/cvr.js +2 -15
  173. package/dist/dk/cvr.js.map +1 -1
  174. package/dist/dk/vat.d.ts +2 -2
  175. package/dist/dk/vat.js +3 -13
  176. package/dist/dk/vat.js.map +1 -1
  177. package/dist/do/rnc.d.ts +2 -2
  178. package/dist/do/rnc.js +2 -16
  179. package/dist/do/rnc.js.map +1 -1
  180. package/dist/ec/ruc.d.ts +2 -2
  181. package/dist/ec/ruc.js +1 -18
  182. package/dist/ec/ruc.js.map +1 -1
  183. package/dist/ee/ik.d.ts +2 -2
  184. package/dist/ee/ik.js +3 -20
  185. package/dist/ee/ik.js.map +1 -1
  186. package/dist/ee/registrikood.d.ts +2 -2
  187. package/dist/ee/registrikood.js +1 -8
  188. package/dist/ee/registrikood.js.map +1 -1
  189. package/dist/ee/vat.d.ts +2 -2
  190. package/dist/ee/vat.js +2 -10
  191. package/dist/ee/vat.js.map +1 -1
  192. package/dist/eg/tn.d.ts +11 -2
  193. package/dist/eg/tn.js +1 -9
  194. package/dist/eg/tn.js.map +1 -1
  195. package/dist/es/cif.d.ts +2 -2
  196. package/dist/es/cif.js +1 -10
  197. package/dist/es/cif.js.map +1 -1
  198. package/dist/es/dni.d.ts +2 -2
  199. package/dist/es/dni.js +1 -9
  200. package/dist/es/dni.js.map +1 -1
  201. package/dist/es/nie.d.ts +2 -2
  202. package/dist/es/nie.js +1 -9
  203. package/dist/es/nie.js.map +1 -1
  204. package/dist/es/nss.d.ts +2 -2
  205. package/dist/es/nss.js +1 -16
  206. package/dist/es/nss.js.map +1 -1
  207. package/dist/es/vat.d.ts +2 -2
  208. package/dist/es/vat.js +5 -10
  209. package/dist/es/vat.js.map +1 -1
  210. package/dist/eu/vat.d.ts +2 -2
  211. package/dist/eu/vat.js +1 -0
  212. package/dist/eu/vat.js.map +1 -1
  213. package/dist/fi/hetu.d.ts +2 -2
  214. package/dist/fi/hetu.js +2 -10
  215. package/dist/fi/hetu.js.map +1 -1
  216. package/dist/fi/vat.d.ts +2 -2
  217. package/dist/fi/vat.js +3 -10
  218. package/dist/fi/vat.js.map +1 -1
  219. package/dist/fi/ytunnus.d.ts +2 -2
  220. package/dist/fi/ytunnus.js +2 -10
  221. package/dist/fi/ytunnus.js.map +1 -1
  222. package/dist/fr/nif.d.ts +2 -2
  223. package/dist/fr/nif.js +1 -9
  224. package/dist/fr/nif.js.map +1 -1
  225. package/dist/fr/nir.d.ts +2 -2
  226. package/dist/fr/nir.js +2 -14
  227. package/dist/fr/nir.js.map +1 -1
  228. package/dist/fr/siren.d.ts +2 -2
  229. package/dist/fr/siren.js +2 -10
  230. package/dist/fr/siren.js.map +1 -1
  231. package/dist/fr/siret.d.ts +2 -2
  232. package/dist/fr/siret.js +2 -11
  233. package/dist/fr/siret.js.map +1 -1
  234. package/dist/fr/tva.d.ts +2 -2
  235. package/dist/fr/tva.js +2 -12
  236. package/dist/fr/tva.js.map +1 -1
  237. package/dist/gb/nino.d.ts +12 -2
  238. package/dist/gb/nino.js +1 -10
  239. package/dist/gb/nino.js.map +1 -1
  240. package/dist/gb/sedol.d.ts +2 -2
  241. package/dist/gb/sedol.js +1 -11
  242. package/dist/gb/sedol.js.map +1 -1
  243. package/dist/gb/utr.d.ts +2 -2
  244. package/dist/gb/utr.js +2 -10
  245. package/dist/gb/utr.js.map +1 -1
  246. package/dist/gb/vat.d.ts +2 -2
  247. package/dist/gb/vat.js +2 -11
  248. package/dist/gb/vat.js.map +1 -1
  249. package/dist/ge/pin.d.ts +14 -2
  250. package/dist/ge/pin.js +1 -12
  251. package/dist/ge/pin.js.map +1 -1
  252. package/dist/gh/tin.d.ts +2 -2
  253. package/dist/gh/tin.js +1 -15
  254. package/dist/gh/tin.js.map +1 -1
  255. package/dist/gr/amka.d.ts +2 -2
  256. package/dist/gr/amka.js +3 -11
  257. package/dist/gr/amka.js.map +1 -1
  258. package/dist/gr/vat.d.ts +2 -2
  259. package/dist/gr/vat.js +1 -10
  260. package/dist/gr/vat.js.map +1 -1
  261. package/dist/gt/nit.d.ts +2 -2
  262. package/dist/gt/nit.js +1 -12
  263. package/dist/gt/nit.js.map +1 -1
  264. package/dist/hk/hkid.d.ts +2 -2
  265. package/dist/hk/hkid.js +1 -10
  266. package/dist/hk/hkid.js.map +1 -1
  267. package/dist/hr/vat.d.ts +2 -2
  268. package/dist/hr/vat.js +2 -9
  269. package/dist/hr/vat.js.map +1 -1
  270. package/dist/hu/vat.d.ts +2 -2
  271. package/dist/hu/vat.js +3 -10
  272. package/dist/hu/vat.js.map +1 -1
  273. package/dist/iban.d.ts +2 -2
  274. package/dist/iban.js +2 -8
  275. package/dist/iban.js.map +1 -1
  276. package/dist/id/npwp.d.ts +2 -2
  277. package/dist/id/npwp.js +3 -13
  278. package/dist/id/npwp.js.map +1 -1
  279. package/dist/ie/pps.d.ts +2 -2
  280. package/dist/ie/pps.js +1 -10
  281. package/dist/ie/pps.js.map +1 -1
  282. package/dist/ie/vat.d.ts +2 -2
  283. package/dist/ie/vat.js +1 -9
  284. package/dist/ie/vat.js.map +1 -1
  285. package/dist/il/idnr.d.ts +2 -2
  286. package/dist/il/idnr.js +2 -9
  287. package/dist/il/idnr.js.map +1 -1
  288. package/dist/in/aadhaar.d.ts +2 -2
  289. package/dist/in/aadhaar.js +2 -12
  290. package/dist/in/aadhaar.js.map +1 -1
  291. package/dist/in/gstin.d.ts +2 -2
  292. package/dist/in/gstin.js +1 -10
  293. package/dist/in/gstin.js.map +1 -1
  294. package/dist/in/pan.d.ts +15 -2
  295. package/dist/in/pan.js +1 -13
  296. package/dist/in/pan.js.map +1 -1
  297. package/dist/index.d.ts +2 -2
  298. package/dist/index.js +6 -6
  299. package/dist/iq/nid.d.ts +16 -2
  300. package/dist/iq/nid.js +2 -15
  301. package/dist/iq/nid.js.map +1 -1
  302. package/dist/ir/nid.d.ts +2 -2
  303. package/dist/ir/nid.js +2 -24
  304. package/dist/ir/nid.js.map +1 -1
  305. package/dist/is/kennitala.d.ts +2 -2
  306. package/dist/is/kennitala.js +2 -13
  307. package/dist/is/kennitala.js.map +1 -1
  308. package/dist/is/vsk.d.ts +9 -2
  309. package/dist/is/vsk.js +1 -7
  310. package/dist/is/vsk.js.map +1 -1
  311. package/dist/isin.d.ts +2 -2
  312. package/dist/isin.js +2 -12
  313. package/dist/isin.js.map +1 -1
  314. package/dist/it/codicefiscale.d.ts +2 -2
  315. package/dist/it/codicefiscale.js +1 -21
  316. package/dist/it/codicefiscale.js.map +1 -1
  317. package/dist/it/iva.d.ts +2 -2
  318. package/dist/it/iva.js +2 -9
  319. package/dist/it/iva.js.map +1 -1
  320. package/dist/jp/cn.d.ts +2 -2
  321. package/dist/jp/cn.js +1 -9
  322. package/dist/jp/cn.js.map +1 -1
  323. package/dist/jp/mynumber.d.ts +2 -2
  324. package/dist/jp/mynumber.js +1 -10
  325. package/dist/jp/mynumber.js.map +1 -1
  326. package/dist/kr/brn.d.ts +11 -2
  327. package/dist/kr/brn.js +1 -9
  328. package/dist/kr/brn.js.map +1 -1
  329. package/dist/kr/rrn.d.ts +2 -2
  330. package/dist/kr/rrn.js +2 -11
  331. package/dist/kr/rrn.js.map +1 -1
  332. package/dist/kw/civil.d.ts +2 -2
  333. package/dist/kw/civil.js +2 -14
  334. package/dist/kw/civil.js.map +1 -1
  335. package/dist/kz/iin.d.ts +2 -2
  336. package/dist/kz/iin.js +3 -18
  337. package/dist/kz/iin.js.map +1 -1
  338. package/dist/lei.d.ts +2 -2
  339. package/dist/lei.js +2 -11
  340. package/dist/lei.js.map +1 -1
  341. package/dist/li/peid.d.ts +11 -2
  342. package/dist/li/peid.js +1 -9
  343. package/dist/li/peid.js.map +1 -1
  344. package/dist/lk/nic.d.ts +2 -2
  345. package/dist/lk/nic.js +2 -14
  346. package/dist/lk/nic.js.map +1 -1
  347. package/dist/lt/asmens.d.ts +2 -2
  348. package/dist/lt/asmens.js +2 -1
  349. package/dist/lt/asmens.js.map +1 -1
  350. package/dist/lt/vat.d.ts +2 -2
  351. package/dist/lt/vat.js +2 -10
  352. package/dist/lt/vat.js.map +1 -1
  353. package/dist/lu/vat.d.ts +2 -2
  354. package/dist/lu/vat.js +2 -8
  355. package/dist/lu/vat.js.map +1 -1
  356. package/dist/luhn.d.ts +2 -2
  357. package/dist/luhn.js +2 -9
  358. package/dist/luhn.js.map +1 -1
  359. package/dist/lv/vat.d.ts +2 -2
  360. package/dist/lv/vat.js +2 -28
  361. package/dist/lv/vat.js.map +1 -1
  362. package/dist/ma/ice.d.ts +2 -2
  363. package/dist/ma/ice.js +2 -11
  364. package/dist/ma/ice.js.map +1 -1
  365. package/dist/mc/tva.d.ts +2 -2
  366. package/dist/mc/tva.js +1 -0
  367. package/dist/mc/tva.js.map +1 -1
  368. package/dist/md/idno.d.ts +2 -2
  369. package/dist/md/idno.js +1 -10
  370. package/dist/md/idno.js.map +1 -1
  371. package/dist/me/pib.d.ts +2 -2
  372. package/dist/me/pib.js +2 -10
  373. package/dist/me/pib.js.map +1 -1
  374. package/dist/mk/edb.d.ts +2 -2
  375. package/dist/mk/edb.js +2 -11
  376. package/dist/mk/edb.js.map +1 -1
  377. package/dist/mt/vat.d.ts +2 -2
  378. package/dist/mt/vat.js +3 -10
  379. package/dist/mt/vat.js.map +1 -1
  380. package/dist/mu/brn.d.ts +23 -2
  381. package/dist/mu/brn.js +1 -21
  382. package/dist/mu/brn.js.map +1 -1
  383. package/dist/mx/clabe.d.ts +2 -2
  384. package/dist/mx/clabe.js +1 -14
  385. package/dist/mx/clabe.js.map +1 -1
  386. package/dist/mx/curp.d.ts +2 -2
  387. package/dist/mx/curp.js +3 -17
  388. package/dist/mx/curp.js.map +1 -1
  389. package/dist/mx/rfc.d.ts +2 -2
  390. package/dist/mx/rfc.js +3 -19
  391. package/dist/mx/rfc.js.map +1 -1
  392. package/dist/my/nric.d.ts +2 -2
  393. package/dist/my/nric.js +2 -14
  394. package/dist/my/nric.js.map +1 -1
  395. package/dist/ng/nin.d.ts +13 -2
  396. package/dist/ng/nin.js +1 -11
  397. package/dist/ng/nin.js.map +1 -1
  398. package/dist/ni/ruc.d.ts +2 -2
  399. package/dist/ni/ruc.js +1 -23
  400. package/dist/ni/ruc.js.map +1 -1
  401. package/dist/nl/bsn.d.ts +2 -2
  402. package/dist/nl/bsn.js +2 -10
  403. package/dist/nl/bsn.js.map +1 -1
  404. package/dist/nl/kvk.d.ts +9 -2
  405. package/dist/nl/kvk.js +1 -7
  406. package/dist/nl/kvk.js.map +1 -1
  407. package/dist/nl/vat.d.ts +2 -2
  408. package/dist/nl/vat.js +1 -13
  409. package/dist/nl/vat.js.map +1 -1
  410. package/dist/no/fodselsnummer.d.ts +2 -2
  411. package/dist/no/fodselsnummer.js +2 -10
  412. package/dist/no/fodselsnummer.js.map +1 -1
  413. package/dist/no/mva.d.ts +2 -2
  414. package/dist/no/mva.js +1 -8
  415. package/dist/no/mva.js.map +1 -1
  416. package/dist/no/orgnr.d.ts +2 -2
  417. package/dist/no/orgnr.js +2 -8
  418. package/dist/no/orgnr.js.map +1 -1
  419. package/dist/nz/ird.d.ts +2 -2
  420. package/dist/nz/ird.js +2 -11
  421. package/dist/nz/ird.js.map +1 -1
  422. package/dist/pa/ruc.d.ts +2 -2
  423. package/dist/pa/ruc.js +1 -18
  424. package/dist/pa/ruc.js.map +1 -1
  425. package/dist/patterns.d.ts +8 -7
  426. package/dist/patterns.js +3 -5
  427. package/dist/patterns.js.map +1 -1
  428. package/dist/pe/ruc.d.ts +2 -2
  429. package/dist/pe/ruc.js +1 -15
  430. package/dist/pe/ruc.js.map +1 -1
  431. package/dist/ph/philid.d.ts +14 -2
  432. package/dist/ph/philid.js +1 -12
  433. package/dist/ph/philid.js.map +1 -1
  434. package/dist/pk/cnic.d.ts +14 -2
  435. package/dist/pk/cnic.js +1 -12
  436. package/dist/pk/cnic.js.map +1 -1
  437. package/dist/pl/nip.d.ts +2 -2
  438. package/dist/pl/nip.js +2 -10
  439. package/dist/pl/nip.js.map +1 -1
  440. package/dist/pl/pesel.d.ts +2 -2
  441. package/dist/pl/pesel.js +3 -13
  442. package/dist/pl/pesel.js.map +1 -1
  443. package/dist/pl/regon.d.ts +2 -2
  444. package/dist/pl/regon.js +2 -11
  445. package/dist/pl/regon.js.map +1 -1
  446. package/dist/pt/cc.d.ts +2 -2
  447. package/dist/pt/cc.js +1 -9
  448. package/dist/pt/cc.js.map +1 -1
  449. package/dist/pt/vat.d.ts +2 -2
  450. package/dist/pt/vat.js +3 -11
  451. package/dist/pt/vat.js.map +1 -1
  452. package/dist/ro/cnp.d.ts +2 -2
  453. package/dist/ro/cnp.js +4 -14
  454. package/dist/ro/cnp.js.map +1 -1
  455. package/dist/ro/vat.d.ts +2 -2
  456. package/dist/ro/vat.js +13 -11
  457. package/dist/ro/vat.js.map +1 -1
  458. package/dist/rs/pib.d.ts +2 -2
  459. package/dist/rs/pib.js +1 -9
  460. package/dist/rs/pib.js.map +1 -1
  461. package/dist/ru/inn.d.ts +2 -2
  462. package/dist/ru/inn.js +1 -11
  463. package/dist/ru/inn.js.map +1 -1
  464. package/dist/se/orgnr.d.ts +2 -2
  465. package/dist/se/orgnr.js +2 -9
  466. package/dist/se/orgnr.js.map +1 -1
  467. package/dist/se/personnummer.d.ts +2 -2
  468. package/dist/se/personnummer.js +7 -15
  469. package/dist/se/personnummer.js.map +1 -1
  470. package/dist/se/vat.d.ts +2 -2
  471. package/dist/se/vat.js +3 -10
  472. package/dist/se/vat.js.map +1 -1
  473. package/dist/sg/uen.d.ts +2 -2
  474. package/dist/sg/uen.js +1 -15
  475. package/dist/sg/uen.js.map +1 -1
  476. package/dist/si/emso.d.ts +2 -2
  477. package/dist/si/emso.js +3 -18
  478. package/dist/si/emso.js.map +1 -1
  479. package/dist/si/vat.d.ts +2 -2
  480. package/dist/si/vat.js +3 -12
  481. package/dist/si/vat.js.map +1 -1
  482. package/dist/sk/dic.d.ts +2 -2
  483. package/dist/sk/dic.js +1 -0
  484. package/dist/sk/dic.js.map +1 -1
  485. package/dist/sk/ico.d.ts +2 -2
  486. package/dist/sk/ico.js +1 -0
  487. package/dist/sk/ico.js.map +1 -1
  488. package/dist/sk/rc.d.ts +2 -2
  489. package/dist/sk/rc.js +1 -0
  490. package/dist/sk/rc.js.map +1 -1
  491. package/dist/th/tin.d.ts +2 -2
  492. package/dist/th/tin.js +1 -11
  493. package/dist/th/tin.js.map +1 -1
  494. package/dist/tr/tckimlik.d.ts +2 -2
  495. package/dist/tr/tckimlik.js +1 -20
  496. package/dist/tr/tckimlik.js.map +1 -1
  497. package/dist/tr/vkn.d.ts +2 -2
  498. package/dist/tr/vkn.js +1 -20
  499. package/dist/tr/vkn.js.map +1 -1
  500. package/dist/tw/ubn.d.ts +2 -2
  501. package/dist/tw/ubn.js +1 -11
  502. package/dist/tw/ubn.js.map +1 -1
  503. package/dist/types.d.ts +26 -4
  504. package/dist/ua/edrpou.d.ts +2 -2
  505. package/dist/ua/edrpou.js +1 -11
  506. package/dist/ua/edrpou.js.map +1 -1
  507. package/dist/us/ein.d.ts +12 -2
  508. package/dist/us/ein.js +1 -10
  509. package/dist/us/ein.js.map +1 -1
  510. package/dist/us/itin.d.ts +13 -2
  511. package/dist/us/itin.js +1 -11
  512. package/dist/us/itin.js.map +1 -1
  513. package/dist/us/rtn.d.ts +2 -2
  514. package/dist/us/rtn.js +3 -18
  515. package/dist/us/rtn.js.map +1 -1
  516. package/dist/us/ssn.d.ts +13 -2
  517. package/dist/us/ssn.js +1 -11
  518. package/dist/us/ssn.js.map +1 -1
  519. package/dist/uy/rut.d.ts +2 -2
  520. package/dist/uy/rut.js +1 -14
  521. package/dist/uy/rut.js.map +1 -1
  522. package/dist/ve/rif.d.ts +2 -2
  523. package/dist/ve/rif.js +2 -15
  524. package/dist/ve/rif.js.map +1 -1
  525. package/dist/vn/mst.d.ts +2 -2
  526. package/dist/vn/mst.js +1 -12
  527. package/dist/vn/mst.js.map +1 -1
  528. package/dist/za/idnr.d.ts +2 -2
  529. package/dist/za/idnr.js +3 -16
  530. package/dist/za/idnr.js.map +1 -1
  531. package/package.json +22 -12
  532. package/src/_checksums/mod1110.ts +1 -1
  533. package/src/ad/nrt.ts +7 -3
  534. package/src/ae/eid.ts +7 -3
  535. package/src/ai/tin.ts +7 -3
  536. package/src/al/nipt.ts +7 -3
  537. package/src/am/tin.ts +7 -3
  538. package/src/ar/cbu.ts +7 -3
  539. package/src/ar/cuit.ts +7 -3
  540. package/src/ar/dni.ts +7 -3
  541. package/src/at/businessid.ts +7 -3
  542. package/src/at/tin.ts +7 -3
  543. package/src/at/uid.ts +7 -3
  544. package/src/at/vnr.ts +37 -9
  545. package/src/au/abn.ts +7 -3
  546. package/src/au/acn.ts +7 -3
  547. package/src/au/tfn.ts +7 -3
  548. package/src/az/voen.ts +7 -3
  549. package/src/ba/jmbg.ts +8 -7
  550. package/src/bd/nid.ts +7 -3
  551. package/src/be/bis.ts +8 -4
  552. package/src/be/nn.ts +7 -3
  553. package/src/be/vat.ts +7 -3
  554. package/src/bg/egn.ts +8 -7
  555. package/src/bg/pnf.ts +7 -3
  556. package/src/bg/vat.ts +8 -3
  557. package/src/bh/cpr.ts +7 -3
  558. package/src/bic.ts +7 -3
  559. package/src/br/cnpj.ts +7 -3
  560. package/src/br/cpf.ts +7 -3
  561. package/src/by/unp.ts +10 -5
  562. package/src/bz/tin.ts +7 -3
  563. package/src/ca/bn.ts +7 -3
  564. package/src/ca/sin.ts +7 -3
  565. package/src/ch/ssn.ts +7 -3
  566. package/src/ch/uid.ts +7 -3
  567. package/src/ch/vat.ts +9 -5
  568. package/src/cl/rut.ts +7 -3
  569. package/src/cn/ric.ts +8 -7
  570. package/src/cn/uscc.ts +7 -3
  571. package/src/co/nit.ts +8 -4
  572. package/src/cr/cpf.ts +7 -3
  573. package/src/creditcard.ts +10 -6
  574. package/src/cu/ni.ts +8 -7
  575. package/src/cy/vat.ts +7 -3
  576. package/src/cz/dic.ts +9 -4
  577. package/src/cz/ico.ts +7 -3
  578. package/src/cz/rc.ts +8 -7
  579. package/src/de/handelsreg.ts +7 -3
  580. package/src/de/idnr.ts +7 -3
  581. package/src/de/stnr.ts +7 -3
  582. package/src/de/svnr.ts +7 -3
  583. package/src/de/vat.ts +7 -3
  584. package/src/dk/cpr.ts +8 -7
  585. package/src/dk/cvr.ts +7 -3
  586. package/src/dk/vat.ts +8 -3
  587. package/src/do/rnc.ts +7 -3
  588. package/src/ec/ruc.ts +7 -3
  589. package/src/ee/ik.ts +8 -7
  590. package/src/ee/registrikood.ts +8 -4
  591. package/src/ee/vat.ts +7 -3
  592. package/src/eg/tn.ts +7 -3
  593. package/src/es/cif.ts +8 -4
  594. package/src/es/dni.ts +7 -3
  595. package/src/es/nie.ts +8 -4
  596. package/src/es/nss.ts +7 -3
  597. package/src/es/vat.ts +13 -5
  598. package/src/eu/vat.ts +10 -6
  599. package/src/fi/hetu.ts +8 -7
  600. package/src/fi/vat.ts +8 -3
  601. package/src/fi/ytunnus.ts +7 -3
  602. package/src/fr/nif.ts +7 -3
  603. package/src/fr/nir.ts +8 -7
  604. package/src/fr/siren.ts +7 -3
  605. package/src/fr/siret.ts +7 -3
  606. package/src/fr/tva.ts +7 -3
  607. package/src/gb/nino.ts +7 -3
  608. package/src/gb/sedol.ts +7 -3
  609. package/src/gb/utr.ts +7 -3
  610. package/src/gb/vat.ts +7 -3
  611. package/src/ge/pin.ts +7 -3
  612. package/src/gh/tin.ts +7 -3
  613. package/src/gr/amka.ts +7 -3
  614. package/src/gr/vat.ts +7 -3
  615. package/src/gt/nit.ts +7 -3
  616. package/src/hk/hkid.ts +7 -3
  617. package/src/hr/vat.ts +7 -3
  618. package/src/hu/vat.ts +8 -3
  619. package/src/iban.ts +7 -3
  620. package/src/id/npwp.ts +7 -3
  621. package/src/ie/pps.ts +7 -3
  622. package/src/ie/vat.ts +7 -3
  623. package/src/il/idnr.ts +7 -3
  624. package/src/in/aadhaar.ts +7 -3
  625. package/src/in/gstin.ts +7 -3
  626. package/src/in/pan.ts +7 -3
  627. package/src/index.ts +3 -0
  628. package/src/iq/nid.ts +7 -3
  629. package/src/ir/nid.ts +7 -3
  630. package/src/is/kennitala.ts +7 -3
  631. package/src/is/vsk.ts +7 -3
  632. package/src/isin.ts +7 -3
  633. package/src/it/codicefiscale.ts +11 -7
  634. package/src/it/iva.ts +7 -3
  635. package/src/jp/cn.ts +7 -3
  636. package/src/jp/mynumber.ts +7 -3
  637. package/src/kr/brn.ts +7 -3
  638. package/src/kr/rrn.ts +8 -7
  639. package/src/kw/civil.ts +8 -7
  640. package/src/kz/iin.ts +8 -8
  641. package/src/lei.ts +7 -3
  642. package/src/li/peid.ts +7 -3
  643. package/src/lk/nic.ts +8 -7
  644. package/src/lt/asmens.ts +8 -4
  645. package/src/lt/vat.ts +8 -3
  646. package/src/lu/vat.ts +8 -3
  647. package/src/luhn.ts +7 -3
  648. package/src/lv/vat.ts +7 -3
  649. package/src/ma/ice.ts +7 -3
  650. package/src/mc/tva.ts +9 -5
  651. package/src/md/idno.ts +7 -3
  652. package/src/me/pib.ts +7 -3
  653. package/src/mk/edb.ts +7 -3
  654. package/src/mt/vat.ts +8 -3
  655. package/src/mu/brn.ts +7 -3
  656. package/src/mx/clabe.ts +7 -3
  657. package/src/mx/curp.ts +9 -8
  658. package/src/mx/rfc.ts +8 -4
  659. package/src/my/nric.ts +8 -7
  660. package/src/ng/nin.ts +7 -3
  661. package/src/ni/ruc.ts +7 -3
  662. package/src/nl/bsn.ts +7 -3
  663. package/src/nl/kvk.ts +7 -3
  664. package/src/nl/vat.ts +7 -3
  665. package/src/no/fodselsnummer.ts +11 -7
  666. package/src/no/mva.ts +9 -5
  667. package/src/no/orgnr.ts +7 -3
  668. package/src/nz/ird.ts +8 -4
  669. package/src/pa/ruc.ts +7 -3
  670. package/src/patterns.ts +49 -18
  671. package/src/pe/ruc.ts +7 -3
  672. package/src/ph/philid.ts +7 -3
  673. package/src/pk/cnic.ts +7 -3
  674. package/src/pl/nip.ts +7 -3
  675. package/src/pl/pesel.ts +8 -7
  676. package/src/pl/regon.ts +7 -3
  677. package/src/pt/cc.ts +7 -3
  678. package/src/pt/vat.ts +8 -3
  679. package/src/ro/cnp.ts +15 -8
  680. package/src/ro/vat.ts +8 -3
  681. package/src/rs/pib.ts +7 -3
  682. package/src/ru/inn.ts +7 -3
  683. package/src/se/orgnr.ts +7 -3
  684. package/src/se/personnummer.ts +35 -33
  685. package/src/se/vat.ts +8 -3
  686. package/src/sg/uen.ts +7 -3
  687. package/src/si/emso.ts +8 -7
  688. package/src/si/vat.ts +8 -3
  689. package/src/sk/dic.ts +8 -4
  690. package/src/sk/ico.ts +3 -2
  691. package/src/sk/rc.ts +6 -2
  692. package/src/th/tin.ts +7 -3
  693. package/src/tr/tckimlik.ts +7 -3
  694. package/src/tr/vkn.ts +7 -3
  695. package/src/tw/ubn.ts +7 -3
  696. package/src/types.ts +34 -3
  697. package/src/ua/edrpou.ts +7 -3
  698. package/src/us/ein.ts +7 -3
  699. package/src/us/itin.ts +7 -3
  700. package/src/us/rtn.ts +16 -8
  701. package/src/us/ssn.ts +7 -3
  702. package/src/uy/rut.ts +7 -3
  703. package/src/ve/rif.ts +8 -6
  704. package/src/vn/mst.ts +7 -3
  705. package/src/za/idnr.ts +8 -7
package/dist/bg/egn.js CHANGED
@@ -1,26 +1,10 @@
1
+ import { weightedSum } from "../_checksums/weighted-sum.js";
1
2
  import { clean } from "../_util/clean.js";
3
+ import { isValidDate } from "../_util/date.js";
2
4
  import { randomInt } from "../_util/generate.js";
3
5
  import { err } from "../_util/result.js";
4
6
  import { isdigits } from "../_util/strings.js";
5
- import { weightedSum } from "../_checksums/weighted-sum.js";
6
- import { isValidDate } from "../_util/date.js";
7
7
  //#region src/bg/egn.ts
8
- /**
9
- * EGN (Единен граждански номер).
10
- *
11
- * Bulgarian personal identification number.
12
- * 10 digits encoding date of birth, serial number,
13
- * and a check digit.
14
- *
15
- * Canonical source:
16
- * - GRAO regulation PDF describing the EGN structure.
17
- *
18
- * We treat this as authoritative over third-party
19
- * oracle libraries when the checksum or date rules
20
- * disagree.
21
- *
22
- * @see https://www.grao.bg/normact/NaredbaFunkcESGR.pdf
23
- */
24
8
  const WEIGHTS = [
25
9
  2,
26
10
  4,
@@ -113,6 +97,7 @@ const egn = {
113
97
  "EGN"
114
98
  ],
115
99
  candidatePattern: "\\d{10}",
100
+ scope: "country",
116
101
  country: "BG",
117
102
  entityType: "person",
118
103
  sourceUrl: "https://www.grao.bg/normact/NaredbaFunkcESGR.pdf",
@@ -1 +1 @@
1
- {"version":3,"file":"egn.js","names":[],"sources":["../../src/bg/egn.ts"],"sourcesContent":["/**\n * EGN (Единен граждански номер).\n *\n * Bulgarian personal identification number.\n * 10 digits encoding date of birth, serial number,\n * and a check digit.\n *\n * Canonical source:\n * - GRAO regulation PDF describing the EGN structure.\n *\n * We treat this as authoritative over third-party\n * oracle libraries when the checksum or date rules\n * disagree.\n *\n * @see https://www.grao.bg/normact/NaredbaFunkcESGR.pdf\n */\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\nconst WEIGHTS = [2, 4, 8, 5, 10, 9, 7, 3, 6] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"EGN must be exactly 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"EGN must contain only digits\",\n );\n }\n\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 let year: number;\n let month: number;\n if (mm > 40) {\n year = 2000 + yy;\n month = mm - 40;\n } else if (mm > 20) {\n year = 1800 + yy;\n month = mm - 20;\n } else {\n year = 1900 + yy;\n month = mm;\n }\n\n if (!isValidDate(year, month, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"EGN contains an invalid date\",\n );\n }\n\n const sum = weightedSum(v.slice(0, 9), WEIGHTS, 11);\n const check = sum % 10;\n if (check !== Number(v[9])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"EGN check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from an EGN.\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 serial = Number(v.slice(6, 9));\n\n let year: number;\n let month: number;\n if (mm > 40) {\n year = 2000 + yy;\n month = mm - 40;\n } else if (mm > 20) {\n year = 1800 + yy;\n month = mm - 20;\n } else {\n year = 1900 + yy;\n month = mm;\n }\n\n return {\n birthDate: new Date(year, month - 1, dd),\n gender: serial % 2 === 0 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid EGN. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const serial = String(randomInt(0, 999)).padStart(\n 3,\n \"0\",\n );\n const payload = yy + mm + dd + serial;\n const sum = weightedSum(payload, WEIGHTS, 11);\n const c = payload + String(sum % 10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Bulgarian Personal Identification Number. */\nconst egn: Validator<ParsedPersonId> = {\n name: \"Bulgarian Personal ID\",\n localName: \"Единен граждански номер\",\n abbreviation: \"ЕГН\",\n aliases: [\n \"ЕГН\",\n \"единен граждански номер\",\n \"EGN\",\n ] as const,\n candidatePattern: \"\\\\d{10}\",\n country: \"BG\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.grao.bg/normact/NaredbaFunkcESGR.pdf\",\n examples: [\"7523169263\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default egn;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;CAAE;AAE5C,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,gCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,+BACD;CAGH,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,IAAI;CACJ,IAAI;AACJ,KAAI,KAAK,IAAI;AACX,SAAO,MAAO;AACd,UAAQ,KAAK;YACJ,KAAK,IAAI;AAClB,SAAO,OAAO;AACd,UAAQ,KAAK;QACR;AACL,SAAO,OAAO;AACd,UAAQ;;AAGV,KAAI,CAAC,YAAY,MAAM,OAAO,GAAG,CAC/B,QAAO,IACL,qBACA,+BACD;AAKH,KAFY,YAAY,EAAE,MAAM,GAAG,EAAE,EAAE,SAAS,GAAG,GAC/B,OACN,OAAO,EAAE,GAAG,CACxB,QAAO,IACL,oBACA,iCACD;AAGH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;;;;AAMxD,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,MAAM;AAC9B,KAAI,CAAC,OAAO,MAAO,QAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAEpC,IAAI;CACJ,IAAI;AACJ,KAAI,KAAK,IAAI;AACX,SAAO,MAAO;AACd,UAAQ,KAAK;YACJ,KAAK,IAAI;AAClB,SAAO,OAAO;AACd,UAAQ,KAAK;QACR;AACL,SAAO,OAAO;AACd,UAAQ;;AAGV,QAAO;EACL,WAAW,IAAI,KAAK,MAAM,QAAQ,GAAG,GAAG;EACxC,QAAQ,SAAS,MAAM,IAAI,SAAS;EACrC;;;AAIH,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,KAAK,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,KAAK,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI;EACpD,MAAM,SAAS,OAAO,UAAU,GAAG,IAAI,CAAC,CAAC,SACvC,GACA,IACD;EACD,MAAM,UAAU,KAAK,KAAK,KAAK;EAC/B,MAAM,MAAM,YAAY,SAAS,SAAS,GAAG;EAC7C,MAAM,IAAI,UAAU,OAAO,MAAM,GAAG;AACpC,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,MAAiC;CACrC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"egn.js","names":[],"sources":["../../src/bg/egn.ts"],"sourcesContent":["/**\n * EGN (Единен граждански номер).\n *\n * Bulgarian personal identification number.\n * 10 digits encoding date of birth, serial number,\n * and a check digit.\n *\n * Canonical source:\n * - GRAO regulation PDF describing the EGN structure.\n *\n * We treat this as authoritative over third-party\n * oracle libraries when the checksum or date rules\n * disagree.\n *\n * @see https://www.grao.bg/normact/NaredbaFunkcESGR.pdf\n */\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [2, 4, 8, 5, 10, 9, 7, 3, 6] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"EGN must be exactly 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"EGN must contain only digits\",\n );\n }\n\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 let year: number;\n let month: number;\n if (mm > 40) {\n year = 2000 + yy;\n month = mm - 40;\n } else if (mm > 20) {\n year = 1800 + yy;\n month = mm - 20;\n } else {\n year = 1900 + yy;\n month = mm;\n }\n\n if (!isValidDate(year, month, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"EGN contains an invalid date\",\n );\n }\n\n const sum = weightedSum(v.slice(0, 9), WEIGHTS, 11);\n const check = sum % 10;\n if (check !== Number(v[9])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"EGN check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from an EGN.\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 serial = Number(v.slice(6, 9));\n\n let year: number;\n let month: number;\n if (mm > 40) {\n year = 2000 + yy;\n month = mm - 40;\n } else if (mm > 20) {\n year = 1800 + yy;\n month = mm - 20;\n } else {\n year = 1900 + yy;\n month = mm;\n }\n\n return {\n birthDate: new Date(year, month - 1, dd),\n gender: serial % 2 === 0 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid EGN. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const serial = String(randomInt(0, 999)).padStart(\n 3,\n \"0\",\n );\n const payload = yy + mm + dd + serial;\n const sum = weightedSum(payload, WEIGHTS, 11);\n const c = payload + String(sum % 10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Bulgarian Personal Identification Number. */\nconst egn: CountryValidator<\"BG\", ParsedPersonId> = {\n name: \"Bulgarian Personal ID\",\n localName: \"Единен граждански номер\",\n abbreviation: \"ЕГН\",\n aliases: [\n \"ЕГН\",\n \"единен граждански номер\",\n \"EGN\",\n ] as const,\n candidatePattern: \"\\\\d{10}\",\n scope: \"country\",\n country: \"BG\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.grao.bg/normact/NaredbaFunkcESGR.pdf\",\n examples: [\"7523169263\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default egn;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;AA8BA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;AAAC;AAE3C,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,+BACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAGF,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,IAAI;CACJ,IAAI;CACJ,IAAI,KAAK,IAAI;EACX,OAAO,MAAO;EACd,QAAQ,KAAK;CACf,OAAO,IAAI,KAAK,IAAI;EAClB,OAAO,OAAO;EACd,QAAQ,KAAK;CACf,OAAO;EACL,OAAO,OAAO;EACd,QAAQ;CACV;CAEA,IAAI,CAAC,YAAY,MAAM,OAAO,EAAE,GAC9B,OAAO,IACL,qBACA,8BACF;CAKF,IAFY,YAAY,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,EAChC,IAAI,OACN,OAAO,EAAE,EAAE,GACvB,OAAO,IACL,oBACA,gCACF;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,CAAC,CAAC;CAC/B,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAEnC,IAAI;CACJ,IAAI;CACJ,IAAI,KAAK,IAAI;EACX,OAAO,MAAO;EACd,QAAQ,KAAK;CACf,OAAO,IAAI,KAAK,IAAI;EAClB,OAAO,OAAO;EACd,QAAQ,KAAK;CACf,OAAO;EACL,OAAO,OAAO;EACd,QAAQ;CACV;CAEA,OAAO;EACL,WAAW,IAAI,KAAK,MAAM,QAAQ,GAAG,EAAE;EACvC,QAAQ,SAAS,MAAM,IAAI,SAAS;CACtC;AACF;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,SAAS,OAAO,UAAU,GAAG,GAAG,CAAC,EAAE,SACvC,GACA,GACF;EACA,MAAM,UAAU,KAAK,KAAK,KAAK;EAC/B,MAAM,MAAM,YAAY,SAAS,SAAS,EAAE;EAC5C,MAAM,IAAI,UAAU,OAAO,MAAM,EAAE;EACnC,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8C;CAClD,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACA;AACF"}
package/dist/bg/pnf.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/bg/pnf.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -7,7 +7,7 @@ declare const format: (value: string) => string;
7
7
  /** Generate a random valid PNF. */
8
8
  declare const generate: () => string;
9
9
  /** Bulgarian Personal Number of a Foreigner. */
10
- declare const pnf: Validator;
10
+ declare const pnf: CountryValidator<"BG">;
11
11
  //#endregion
12
12
  export { compact, pnf as default, format, generate, validate };
13
13
  //# sourceMappingURL=pnf.d.ts.map
package/dist/bg/pnf.js CHANGED
@@ -3,14 +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/bg/pnf.ts
6
- /**
7
- * PNF (ЛНЧ, Личен номер на чужденец).
8
- *
9
- * Bulgarian personal number of a foreigner.
10
- * 10 digits; the last digit is a weighted checksum.
11
- *
12
- * @see https://en.wikipedia.org/wiki/Unique_citizenship_number
13
- */
14
6
  const WEIGHTS = [
15
7
  21,
16
8
  19,
@@ -55,6 +47,7 @@ const pnf = {
55
47
  "PNF"
56
48
  ],
57
49
  candidatePattern: "\\d{10}",
50
+ scope: "country",
58
51
  country: "BG",
59
52
  entityType: "person",
60
53
  sourceUrl: "https://en.wikipedia.org/wiki/Unique_citizenship_number",
@@ -1 +1 @@
1
- {"version":3,"file":"pnf.js","names":[],"sources":["../../src/bg/pnf.ts"],"sourcesContent":["/**\n * PNF (ЛНЧ, Личен номер на чужденец).\n *\n * Bulgarian personal number of a foreigner.\n * 10 digits; the last digit is a weighted checksum.\n *\n * @see https://en.wikipedia.org/wiki/Unique_citizenship_number\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 = [21, 19, 17, 13, 11, 9, 7, 3, 1] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -.\");\n\nconst calcCheckDigit = (number: string): string => {\n let sum = 0;\n for (let i = 0; i < 9; i++) {\n // SAFETY: WEIGHTS has exactly 9 entries\n // eslint-disable-next-line no-non-null-assertion\n sum += WEIGHTS[i]! * Number(number[i]);\n }\n return String(sum % 10);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"PNF must be exactly 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"PNF must contain only digits\",\n );\n }\n if (calcCheckDigit(v.slice(0, 9)) !== v[9]) {\n return err(\n \"INVALID_CHECKSUM\",\n \"PNF check digit does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid PNF. */\nconst generate = (): string => {\n const payload = randomDigits(9);\n return payload + calcCheckDigit(payload);\n};\n\n/** Bulgarian Personal Number of a Foreigner. */\nconst pnf: Validator = {\n name: \"Bulgarian Foreigner Number\",\n localName: \"Личен номер на чужденец\",\n abbreviation: \"ЛНЧ\",\n aliases: [\n \"ЛНЧ\",\n \"личен номер на чужденец\",\n \"PNF\",\n ] as const,\n candidatePattern: \"\\\\d{10}\",\n country: \"BG\",\n entityType: \"person\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/Unique_citizenship_number\",\n examples: [\"7111042925\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default pnf;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;AAgBA,MAAM,UAAU;CAAC;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAG;CAAE;AAEhD,MAAM,WAAW,UACf,MAAM,OAAO,MAAM;AAErB,MAAM,kBAAkB,WAA2B;CACjD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IAGrB,QAAO,QAAQ,KAAM,OAAO,OAAO,GAAG;AAExC,QAAO,OAAO,MAAM,GAAG;;AAGzB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,gCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,+BACD;AAEH,KAAI,eAAe,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,EAAE,GACtC,QAAO,IACL,oBACA,iCACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B,QAAQ,MAAM;;AAGxD,MAAM,iBAAyB;CAC7B,MAAM,UAAU,aAAa,EAAE;AAC/B,QAAO,UAAU,eAAe,QAAQ;;;AAI1C,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"pnf.js","names":[],"sources":["../../src/bg/pnf.ts"],"sourcesContent":["/**\n * PNF (ЛНЧ, Личен номер на чужденец).\n *\n * Bulgarian personal number of a foreigner.\n * 10 digits; the last digit is a weighted checksum.\n *\n * @see https://en.wikipedia.org/wiki/Unique_citizenship_number\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 = [21, 19, 17, 13, 11, 9, 7, 3, 1] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -.\");\n\nconst calcCheckDigit = (number: string): string => {\n let sum = 0;\n for (let i = 0; i < 9; i++) {\n // SAFETY: WEIGHTS has exactly 9 entries\n // eslint-disable-next-line no-non-null-assertion\n sum += WEIGHTS[i]! * Number(number[i]);\n }\n return String(sum % 10);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"PNF must be exactly 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"PNF must contain only digits\",\n );\n }\n if (calcCheckDigit(v.slice(0, 9)) !== v[9]) {\n return err(\n \"INVALID_CHECKSUM\",\n \"PNF check digit does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid PNF. */\nconst generate = (): string => {\n const payload = randomDigits(9);\n return payload + calcCheckDigit(payload);\n};\n\n/** Bulgarian Personal Number of a Foreigner. */\nconst pnf: CountryValidator<\"BG\"> = {\n name: \"Bulgarian Foreigner Number\",\n localName: \"Личен номер на чужденец\",\n abbreviation: \"ЛНЧ\",\n aliases: [\n \"ЛНЧ\",\n \"личен номер на чужденец\",\n \"PNF\",\n ] as const,\n candidatePattern: \"\\\\d{10}\",\n scope: \"country\",\n country: \"BG\",\n entityType: \"person\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/Unique_citizenship_number\",\n examples: [\"7111042925\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default pnf;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAmBA,MAAM,UAAU;CAAC;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAG;AAAC;AAE/C,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,kBAAkB,WAA2B;CACjD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAGrB,OAAO,QAAQ,KAAM,OAAO,OAAO,EAAE;CAEvC,OAAO,OAAO,MAAM,EAAE;AACxB;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,+BACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAEF,IAAI,eAAe,EAAE,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,IACtC,OAAO,IACL,oBACA,gCACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;;AAGvD,MAAM,iBAAyB;CAC7B,MAAM,UAAU,aAAa,CAAC;CAC9B,OAAO,UAAU,eAAe,OAAO;AACzC;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;AACF"}
package/dist/bg/vat.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/bg/vat.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -7,7 +7,7 @@ declare const format: (value: string) => string;
7
7
  /** Generate a random valid 9-digit Bulgarian VAT. */
8
8
  declare const generate: () => string;
9
9
  /** Bulgarian VAT Number. */
10
- declare const vat: Validator;
10
+ declare const vat: CountryValidator<"BG">;
11
11
  //#endregion
12
12
  export { compact, vat as default, format, generate, validate };
13
13
  //# sourceMappingURL=vat.d.ts.map
package/dist/bg/vat.js CHANGED
@@ -1,17 +1,9 @@
1
+ import { weightedSum } from "../_checksums/weighted-sum.js";
1
2
  import { clean } from "../_util/clean.js";
2
3
  import { randomDigits } from "../_util/generate.js";
3
4
  import { err } from "../_util/result.js";
4
5
  import { isdigits } from "../_util/strings.js";
5
- import { weightedSum } from "../_checksums/weighted-sum.js";
6
6
  //#region src/bg/vat.ts
7
- /**
8
- * ИН по ДДС (Bulgarian VAT number).
9
- *
10
- * 9 or 10 digits with weighted checksum.
11
- *
12
- * @see https://www.vatify.eu/bulgaria-vat-number.html
13
- * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/bulgaria-tin.pdf
14
- */
15
7
  const compact = (value) => {
16
8
  let v = clean(value, " -/.");
17
9
  if (v.startsWith("BG") || v.startsWith("bg")) v = v.slice(2);
@@ -138,9 +130,11 @@ const vat = {
138
130
  abbreviation: "ИН по ДДС",
139
131
  aliases: ["ДДС", "идентификационен номер по ДДС"],
140
132
  candidatePattern: "BG\\d{9,10}",
133
+ scope: "country",
141
134
  country: "BG",
142
135
  entityType: "any",
143
136
  sourceUrl: "https://www.nra.bg/",
137
+ lengths: [9, 10],
144
138
  examples: ["175074752"],
145
139
  compact,
146
140
  format,
@@ -1 +1 @@
1
- {"version":3,"file":"vat.js","names":[],"sources":["../../src/bg/vat.ts"],"sourcesContent":["/**\n * ИН по ДДС (Bulgarian VAT number).\n *\n * 9 or 10 digits with weighted checksum.\n *\n * @see https://www.vatify.eu/bulgaria-vat-number.html\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/bulgaria-tin.pdf\n */\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\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 let v = clean(value, \" -/.\");\n if (v.startsWith(\"BG\") || v.startsWith(\"bg\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst d = (v: string, i: number): number => Number(v[i]);\n\nconst WEIGHTS_9_PASS1 = [1, 2, 3, 4, 5, 6, 7, 8];\nconst WEIGHTS_9_PASS2 = [3, 4, 5, 6, 7, 8, 9, 10];\nconst WEIGHTS_EGN = [2, 4, 8, 5, 10, 9, 7, 3, 6];\nconst WEIGHTS_PNF = [21, 19, 17, 13, 11, 9, 7, 3, 1];\nconst WEIGHTS_OTHER = [4, 3, 2, 7, 6, 5, 4, 3, 2];\n\nconst validate9 = (v: string): boolean => {\n let check = weightedSum(\n v.slice(0, 8),\n WEIGHTS_9_PASS1,\n 11,\n );\n if (check === 10) {\n check = weightedSum(v.slice(0, 8), WEIGHTS_9_PASS2, 11);\n }\n return check % 10 === d(v, 8);\n};\n\n/**\n * Validate a 10-digit EGN (personal code).\n * First 6 digits encode birth date (YYMMDD with month\n * offsets: +20 for 1800s, +40 for 2000s). Check digit\n * uses weights [2,4,8,5,10,9,7,3,6], sum % 11 % 10.\n */\nconst validateEgn = (v: string): boolean => {\n const year = d(v, 0) * 10 + d(v, 1);\n let month = d(v, 2) * 10 + d(v, 3);\n const day = d(v, 4) * 10 + d(v, 5);\n let fullYear = year + 1900;\n if (month > 40) {\n fullYear += 100;\n month -= 40;\n } else if (month > 20) {\n fullYear -= 100;\n month -= 20;\n }\n // Validate the birth date\n const date = new Date(fullYear, month - 1, day);\n if (\n date.getFullYear() !== fullYear ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day\n ) {\n return false;\n }\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_EGN, 11);\n return sum % 10 === d(v, 9);\n};\n\n/**\n * Validate a 10-digit PNF (foreigner personal number).\n * Weights [21,19,17,13,11,9,7,3,1], sum % 10.\n */\nconst validatePnf = (v: string): boolean => {\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_PNF, 10);\n return sum === d(v, 9);\n};\n\n/**\n * Validate a 10-digit \"other\" VAT number.\n * Weights [4,3,2,7,6,5,4,3,2], (11 - sum%11) % 11.\n */\nconst validateOther = (v: string): boolean => {\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_OTHER, 11);\n return (11 - sum) % 11 === d(v, 9);\n};\n\nconst validate10 = (v: string): boolean =>\n validateEgn(v) || validatePnf(v) || validateOther(v);\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 9 && v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Bulgarian VAT number must be 9 or 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Bulgarian VAT number must contain only digits\",\n );\n }\n const valid =\n v.length === 9 ? validate9(v) : validate10(v);\n if (!valid) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Bulgarian VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `BG${compact(value)}`;\n\n/** Generate a random valid 9-digit Bulgarian VAT. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(9);\n if (validate(c).valid) return c;\n }\n};\n\n/** Bulgarian VAT Number. */\nconst vat: Validator = {\n name: \"Bulgarian VAT Number\",\n localName: \"ИН по ДДС\",\n abbreviation: \"ИН по ДДС\",\n aliases: [\n \"ДДС\",\n \"идентификационен номер по ДДС\",\n ] as const,\n candidatePattern: \"BG\\\\d{9,10}\",\n country: \"BG\",\n entityType: \"any\",\n sourceUrl: \"https://www.nra.bg/\",\n examples: [\"175074752\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;AAiBA,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,OAAO;AAC5B,KAAI,EAAE,WAAW,KAAK,IAAI,EAAE,WAAW,KAAK,CAC1C,KAAI,EAAE,MAAM,EAAE;AAEhB,QAAO;;AAGT,MAAM,KAAK,GAAW,MAAsB,OAAO,EAAE,GAAG;AAExD,MAAM,kBAAkB;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;AAChD,MAAM,kBAAkB;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AACjD,MAAM,cAAc;CAAC;CAAG;CAAG;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;CAAE;AAChD,MAAM,cAAc;CAAC;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAG;CAAE;AACpD,MAAM,gBAAgB;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;AAEjD,MAAM,aAAa,MAAuB;CACxC,IAAI,QAAQ,YACV,EAAE,MAAM,GAAG,EAAE,EACb,iBACA,GACD;AACD,KAAI,UAAU,GACZ,SAAQ,YAAY,EAAE,MAAM,GAAG,EAAE,EAAE,iBAAiB,GAAG;AAEzD,QAAO,QAAQ,OAAO,EAAE,GAAG,EAAE;;;;;;;;AAS/B,MAAM,eAAe,MAAuB;CAC1C,MAAM,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE;CACnC,IAAI,QAAQ,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE;CAClC,MAAM,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE;CAClC,IAAI,WAAW,OAAO;AACtB,KAAI,QAAQ,IAAI;AACd,cAAY;AACZ,WAAS;YACA,QAAQ,IAAI;AACrB,cAAY;AACZ,WAAS;;CAGX,MAAM,OAAO,IAAI,KAAK,UAAU,QAAQ,GAAG,IAAI;AAC/C,KACE,KAAK,aAAa,KAAK,YACvB,KAAK,UAAU,KAAK,QAAQ,KAC5B,KAAK,SAAS,KAAK,IAEnB,QAAO;AAGT,QADY,YAAY,EAAE,MAAM,GAAG,EAAE,EAAE,aAAa,GAAG,GAC1C,OAAO,EAAE,GAAG,EAAE;;;;;;AAO7B,MAAM,eAAe,MAAuB;AAE1C,QADY,YAAY,EAAE,MAAM,GAAG,EAAE,EAAE,aAAa,GAAG,KACxC,EAAE,GAAG,EAAE;;;;;;AAOxB,MAAM,iBAAiB,MAAuB;AAE5C,SAAQ,KADI,YAAY,EAAE,MAAM,GAAG,EAAE,EAAE,eAAe,GAAG,IACrC,OAAO,EAAE,GAAG,EAAE;;AAGpC,MAAM,cAAc,MAClB,YAAY,EAAE,IAAI,YAAY,EAAE,IAAI,cAAc,EAAE;AAEtD,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,QAAO,IACL,kBACA,8CACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,gDACD;AAIH,KAAI,EADF,EAAE,WAAW,IAAI,UAAU,EAAE,GAAG,WAAW,EAAE,EAE7C,QAAO,IACL,oBACA,4CACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UACd,KAAK,QAAQ,MAAM;;AAGrB,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,IAAI,aAAa,EAAE;AACzB,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,gCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"vat.js","names":[],"sources":["../../src/bg/vat.ts"],"sourcesContent":["/**\n * ИН по ДДС (Bulgarian VAT number).\n *\n * 9 or 10 digits with weighted checksum.\n *\n * @see https://www.vatify.eu/bulgaria-vat-number.html\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/bulgaria-tin.pdf\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\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 let v = clean(value, \" -/.\");\n if (v.startsWith(\"BG\") || v.startsWith(\"bg\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst d = (v: string, i: number): number => Number(v[i]);\n\nconst WEIGHTS_9_PASS1 = [1, 2, 3, 4, 5, 6, 7, 8];\nconst WEIGHTS_9_PASS2 = [3, 4, 5, 6, 7, 8, 9, 10];\nconst WEIGHTS_EGN = [2, 4, 8, 5, 10, 9, 7, 3, 6];\nconst WEIGHTS_PNF = [21, 19, 17, 13, 11, 9, 7, 3, 1];\nconst WEIGHTS_OTHER = [4, 3, 2, 7, 6, 5, 4, 3, 2];\n\nconst validate9 = (v: string): boolean => {\n let check = weightedSum(\n v.slice(0, 8),\n WEIGHTS_9_PASS1,\n 11,\n );\n if (check === 10) {\n check = weightedSum(v.slice(0, 8), WEIGHTS_9_PASS2, 11);\n }\n return check % 10 === d(v, 8);\n};\n\n/**\n * Validate a 10-digit EGN (personal code).\n * First 6 digits encode birth date (YYMMDD with month\n * offsets: +20 for 1800s, +40 for 2000s). Check digit\n * uses weights [2,4,8,5,10,9,7,3,6], sum % 11 % 10.\n */\nconst validateEgn = (v: string): boolean => {\n const year = d(v, 0) * 10 + d(v, 1);\n let month = d(v, 2) * 10 + d(v, 3);\n const day = d(v, 4) * 10 + d(v, 5);\n let fullYear = year + 1900;\n if (month > 40) {\n fullYear += 100;\n month -= 40;\n } else if (month > 20) {\n fullYear -= 100;\n month -= 20;\n }\n // Validate the birth date\n const date = new Date(fullYear, month - 1, day);\n if (\n date.getFullYear() !== fullYear ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day\n ) {\n return false;\n }\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_EGN, 11);\n return sum % 10 === d(v, 9);\n};\n\n/**\n * Validate a 10-digit PNF (foreigner personal number).\n * Weights [21,19,17,13,11,9,7,3,1], sum % 10.\n */\nconst validatePnf = (v: string): boolean => {\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_PNF, 10);\n return sum === d(v, 9);\n};\n\n/**\n * Validate a 10-digit \"other\" VAT number.\n * Weights [4,3,2,7,6,5,4,3,2], (11 - sum%11) % 11.\n */\nconst validateOther = (v: string): boolean => {\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_OTHER, 11);\n return (11 - sum) % 11 === d(v, 9);\n};\n\nconst validate10 = (v: string): boolean =>\n validateEgn(v) || validatePnf(v) || validateOther(v);\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 9 && v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Bulgarian VAT number must be 9 or 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Bulgarian VAT number must contain only digits\",\n );\n }\n const valid =\n v.length === 9 ? validate9(v) : validate10(v);\n if (!valid) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Bulgarian VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `BG${compact(value)}`;\n\n/** Generate a random valid 9-digit Bulgarian VAT. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(9);\n if (validate(c).valid) return c;\n }\n};\n\n/** Bulgarian VAT Number. */\nconst vat: CountryValidator<\"BG\"> = {\n name: \"Bulgarian VAT Number\",\n localName: \"ИН по ДДС\",\n abbreviation: \"ИН по ДДС\",\n aliases: [\n \"ДДС\",\n \"идентификационен номер по ДДС\",\n ] as const,\n candidatePattern: \"BG\\\\d{9,10}\",\n scope: \"country\",\n country: \"BG\",\n entityType: \"any\",\n sourceUrl: \"https://www.nra.bg/\",\n lengths: [9, 10] as const,\n examples: [\"175074752\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAoBA,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,MAAM;CAC3B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO;AACT;AAEA,MAAM,KAAK,GAAW,MAAsB,OAAO,EAAE,EAAE;AAEvD,MAAM,kBAAkB;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAC/C,MAAM,kBAAkB;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAE;AAChD,MAAM,cAAc;CAAC;CAAG;CAAG;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;AAAC;AAC/C,MAAM,cAAc;CAAC;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;CAAG;AAAC;AACnD,MAAM,gBAAgB;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAEhD,MAAM,aAAa,MAAuB;CACxC,IAAI,QAAQ,YACV,EAAE,MAAM,GAAG,CAAC,GACZ,iBACA,EACF;CACA,IAAI,UAAU,IACZ,QAAQ,YAAY,EAAE,MAAM,GAAG,CAAC,GAAG,iBAAiB,EAAE;CAExD,OAAO,QAAQ,OAAO,EAAE,GAAG,CAAC;AAC9B;;;;;;;AAQA,MAAM,eAAe,MAAuB;CAC1C,MAAM,OAAO,EAAE,GAAG,CAAC,IAAI,KAAK,EAAE,GAAG,CAAC;CAClC,IAAI,QAAQ,EAAE,GAAG,CAAC,IAAI,KAAK,EAAE,GAAG,CAAC;CACjC,MAAM,MAAM,EAAE,GAAG,CAAC,IAAI,KAAK,EAAE,GAAG,CAAC;CACjC,IAAI,WAAW,OAAO;CACtB,IAAI,QAAQ,IAAI;EACd,YAAY;EACZ,SAAS;CACX,OAAO,IAAI,QAAQ,IAAI;EACrB,YAAY;EACZ,SAAS;CACX;CAEA,MAAM,OAAO,IAAI,KAAK,UAAU,QAAQ,GAAG,GAAG;CAC9C,IACE,KAAK,YAAY,MAAM,YACvB,KAAK,SAAS,MAAM,QAAQ,KAC5B,KAAK,QAAQ,MAAM,KAEnB,OAAO;CAGT,OADY,YAAY,EAAE,MAAM,GAAG,CAAC,GAAG,aAAa,EAC3C,IAAI,OAAO,EAAE,GAAG,CAAC;AAC5B;;;;;AAMA,MAAM,eAAe,MAAuB;CAE1C,OADY,YAAY,EAAE,MAAM,GAAG,CAAC,GAAG,aAAa,EAC3C,MAAM,EAAE,GAAG,CAAC;AACvB;;;;;AAMA,MAAM,iBAAiB,MAAuB;CAE5C,QAAQ,KADI,YAAY,EAAE,MAAM,GAAG,CAAC,GAAG,eAAe,EACvC,KAAK,OAAO,EAAE,GAAG,CAAC;AACnC;AAEA,MAAM,cAAc,MAClB,YAAY,CAAC,KAAK,YAAY,CAAC,KAAK,cAAc,CAAC;AAErD,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,IACjC,OAAO,IACL,kBACA,6CACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,+CACF;CAIF,IAAI,EADF,EAAE,WAAW,IAAI,UAAU,CAAC,IAAI,WAAW,CAAC,IAE5C,OAAO,IACL,oBACA,2CACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,KAAK,QAAQ,KAAK;;AAGpB,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,CAAC;EACxB,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,+BACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,GAAG,EAAE;CACf,UAAU,CAAC,WAAW;CACtB;CACA;CACA;CACA;AACF"}
package/dist/bh/cpr.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/bh/cpr.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -7,7 +7,7 @@ declare const format: (value: string) => string;
7
7
  /** Generate a random structurally valid Bahrain CPR. */
8
8
  declare const generate: () => string;
9
9
  /** Bahrain Central Population Registration number. */
10
- declare const cpr: Validator;
10
+ declare const cpr: CountryValidator<"BH">;
11
11
  //#endregion
12
12
  export { compact, cpr as default, format, generate, validate };
13
13
  //# sourceMappingURL=cpr.d.ts.map
package/dist/bh/cpr.js CHANGED
@@ -3,23 +3,6 @@ import { randomDigits, randomInt } from "../_util/generate.js";
3
3
  import { err } from "../_util/result.js";
4
4
  import { isdigits } from "../_util/strings.js";
5
5
  //#region src/bh/cpr.ts
6
- /**
7
- * CPR (Central Population Registration number, Bahrain).
8
- *
9
- * 9-digit personal identification number:
10
- * YYMM = year and month of birth
11
- * NNNN = serial number
12
- * C = check digit
13
- *
14
- * The check digit algorithm is not publicly
15
- * documented; validation is structural only
16
- * (length, digits, and valid birth month).
17
- *
18
- * Note: a minority of older CPR numbers do not
19
- * follow the YYMMNNNNC format.
20
- *
21
- * @see https://www.bahrain.bh/wps/portal/IDInfo_en
22
- */
23
6
  const compact = (value) => clean(value, " -");
24
7
  const validate = (value) => {
25
8
  const v = compact(value);
@@ -47,6 +30,7 @@ const cpr = {
47
30
  abbreviation: "CPR",
48
31
  aliases: ["CPR", "الرقم السكاني"],
49
32
  candidatePattern: "\\d{9}",
33
+ scope: "country",
50
34
  country: "BH",
51
35
  entityType: "person",
52
36
  lengths: [9],
@@ -1 +1 @@
1
- {"version":3,"file":"cpr.js","names":[],"sources":["../../src/bh/cpr.ts"],"sourcesContent":["/**\n * CPR (Central Population Registration number, Bahrain).\n *\n * 9-digit personal identification number:\n * YYMM = year and month of birth\n * NNNN = serial number\n * C = check digit\n *\n * The check digit algorithm is not publicly\n * documented; validation is structural only\n * (length, digits, and valid birth month).\n *\n * Note: a minority of older CPR numbers do not\n * follow the YYMMNNNNC format.\n *\n * @see https://www.bahrain.bh/wps/portal/IDInfo_en\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"Bahrain CPR must be 9 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Bahrain CPR must contain only digits\",\n );\n }\n\n // Validate birth month (digits 3-4) is 01-12\n const mm = Number(v.slice(2, 4));\n if (mm < 1 || mm > 12) {\n return err(\n \"INVALID_COMPONENT\",\n \"CPR birth month must be 01-12\",\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, 2)}-${v.slice(2, 4)}-${v.slice(4)}`;\n};\n\n/** Generate a random structurally valid Bahrain CPR. */\nconst generate = (): string => {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n return `${yy}${mm}${randomDigits(5)}`;\n};\n\n/** Bahrain Central Population Registration number. */\nconst cpr: Validator = {\n name: \"Central Population Registration Number\",\n localName: \"الرقم السكاني\",\n abbreviation: \"CPR\",\n aliases: [\"CPR\", \"الرقم السكاني\"] as const,\n candidatePattern: \"\\\\d{9}\",\n country: \"BH\",\n entityType: \"person\",\n lengths: [9] as const,\n examples: [\"890112345\", \"000612345\"] as const,\n description: \"9-digit personal identification number\",\n sourceUrl: \"https://www.bahrain.bh/wps/portal/IDInfo_en\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cpr;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAyBA,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AAExB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,+BACD;AAGH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,uCACD;CAIH,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AAChC,KAAI,KAAK,KAAK,KAAK,GACjB,QAAO,IACL,qBACA,gCACD;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,EAAE;;;AAIxD,MAAM,iBAAyB;AAG7B,QAAO,GAFI,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI,GACzC,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,IAAI,GAChC,aAAa,EAAE;;;AAIrC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,gBAAgB;CACjC,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,aAAa,YAAY;CACpC,aAAa;CACb,WAAW;CACX;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"cpr.js","names":[],"sources":["../../src/bh/cpr.ts"],"sourcesContent":["/**\n * CPR (Central Population Registration number, Bahrain).\n *\n * 9-digit personal identification number:\n * YYMM = year and month of birth\n * NNNN = serial number\n * C = check digit\n *\n * The check digit algorithm is not publicly\n * documented; validation is structural only\n * (length, digits, and valid birth month).\n *\n * Note: a minority of older CPR numbers do not\n * follow the YYMMNNNNC format.\n *\n * @see https://www.bahrain.bh/wps/portal/IDInfo_en\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\";\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\n if (v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"Bahrain CPR must be 9 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Bahrain CPR must contain only digits\",\n );\n }\n\n // Validate birth month (digits 3-4) is 01-12\n const mm = Number(v.slice(2, 4));\n if (mm < 1 || mm > 12) {\n return err(\n \"INVALID_COMPONENT\",\n \"CPR birth month must be 01-12\",\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, 2)}-${v.slice(2, 4)}-${v.slice(4)}`;\n};\n\n/** Generate a random structurally valid Bahrain CPR. */\nconst generate = (): string => {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n return `${yy}${mm}${randomDigits(5)}`;\n};\n\n/** Bahrain Central Population Registration number. */\nconst cpr: CountryValidator<\"BH\"> = {\n name: \"Central Population Registration Number\",\n localName: \"الرقم السكاني\",\n abbreviation: \"CPR\",\n aliases: [\"CPR\", \"الرقم السكاني\"] as const,\n candidatePattern: \"\\\\d{9}\",\n scope: \"country\",\n country: \"BH\",\n entityType: \"person\",\n lengths: [9] as const,\n examples: [\"890112345\", \"000612345\"] as const,\n description: \"9-digit personal identification number\",\n sourceUrl: \"https://www.bahrain.bh/wps/portal/IDInfo_en\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cpr;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;AA4BA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,8BACF;CAGF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,sCACF;CAIF,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,IAAI,KAAK,KAAK,KAAK,IACjB,OAAO,IACL,qBACA,+BACF;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,CAAC;AACvD;;AAGA,MAAM,iBAAyB;CAG7B,OAAO,GAFI,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAErC,IADA,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAChC,IAAI,aAAa,CAAC;AACpC;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,eAAe;CAChC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,CAAC;CACX,UAAU,CAAC,aAAa,WAAW;CACnC,aAAa;CACb,WAAW;CACX;CACA;CACA;CACA;AACF"}
package/dist/bic.d.ts CHANGED
@@ -1,13 +1,24 @@
1
- import { ValidateResult, Validator } from "./types.js";
1
+ import { GlobalValidator, ValidateResult } from "./types.js";
2
2
 
3
3
  //#region src/bic.d.ts
4
4
  /** Generate a random valid BIC (8-character). */
5
5
  declare const generate: () => string;
6
+ /**
7
+ * BIC (Business Identifier Code).
8
+ *
9
+ * ISO 9362. 8 or 11 character code identifying
10
+ * financial institutions. Format:
11
+ * [A-Z]{4} (institution) + [A-Z]{2} (country) +
12
+ * [0-9A-Z]{2} (location) + [0-9A-Z]{3} (branch,
13
+ * optional).
14
+ *
15
+ * @see https://www.swift.com/
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
  /** Business Identifier Code (SWIFT/BIC). */
10
- declare const bic: Validator;
21
+ declare const bic: GlobalValidator;
11
22
  //#endregion
12
23
  export { compact, bic as default, format, generate, validate };
13
24
  //# sourceMappingURL=bic.d.ts.map
package/dist/bic.js CHANGED
@@ -2,17 +2,6 @@ import { clean } from "./_util/clean.js";
2
2
  import { randomChar, randomInt, randomPick } from "./_util/generate.js";
3
3
  import { err } from "./_util/result.js";
4
4
  //#region src/bic.ts
5
- /**
6
- * BIC (Business Identifier Code).
7
- *
8
- * ISO 9362. 8 or 11 character code identifying
9
- * financial institutions. Format:
10
- * [A-Z]{4} (institution) + [A-Z]{2} (country) +
11
- * [0-9A-Z]{2} (location) + [0-9A-Z]{3} (branch,
12
- * optional).
13
- *
14
- * @see https://www.swift.com/
15
- */
16
5
  const BIC_ALPHANUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
17
6
  const BIC_COUNTRIES = [
18
7
  "DE",
@@ -47,6 +36,7 @@ const format = (value) => {
47
36
  };
48
37
  /** Business Identifier Code (SWIFT/BIC). */
49
38
  const bic = {
39
+ scope: "global",
50
40
  name: "Business Identifier Code",
51
41
  localName: "Business Identifier Code",
52
42
  abbreviation: "BIC",
package/dist/bic.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bic.js","names":[],"sources":["../src/bic.ts"],"sourcesContent":["const BIC_ALPHANUM = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\";\nconst BIC_COUNTRIES = [\n \"DE\",\n \"GB\",\n \"US\",\n \"FR\",\n \"CH\",\n \"NL\",\n \"AT\",\n] as const;\n\n/** Generate a random valid BIC (8-character). */\nconst generate = (): string => {\n const randomLetter = (): string =>\n String.fromCodePoint(65 + randomInt(0, 25));\n const country = randomPick(BIC_COUNTRIES);\n const bank =\n randomLetter() +\n randomLetter() +\n randomLetter() +\n randomLetter();\n const location =\n randomChar(BIC_ALPHANUM) + randomChar(BIC_ALPHANUM);\n return `${bank}${country}${location}`;\n};\n\n/**\n * BIC (Business Identifier Code).\n *\n * ISO 9362. 8 or 11 character code identifying\n * financial institutions. Format:\n * [A-Z]{4} (institution) + [A-Z]{2} (country) +\n * [0-9A-Z]{2} (location) + [0-9A-Z]{3} (branch,\n * optional).\n *\n * @see https://www.swift.com/\n */\n\nimport { clean } from \"#util/clean\";\nimport {\n randomChar,\n randomInt,\n randomPick,\n} from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type { ValidateResult, Validator } from \"./types\";\n\nconst BIC_RE =\n /^[A-Z]{4}[A-Z]{2}[0-9A-Z]{2}([0-9A-Z]{3})?$/;\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8 && v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"BIC must be 8 or 11 characters\",\n );\n }\n if (!BIC_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"BIC must be 8 or 11 alphanumeric characters\",\n );\n }\n // Country code at positions 4-5 is already\n // validated as [A-Z]{2} by the regex above.\n // SWIFT accepts all ISO 3166-1 alpha-2 codes\n // plus XK (Kosovo); we don't restrict further.\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 11) {\n return `${v.slice(0, 4)} ${v.slice(4, 6)} ${v.slice(6, 8)} ${v.slice(8)}`;\n }\n return `${v.slice(0, 4)} ${v.slice(4, 6)} ${v.slice(6)}`;\n};\n\n/** Business Identifier Code (SWIFT/BIC). */\nconst bic: Validator = {\n name: \"Business Identifier Code\",\n localName: \"Business Identifier Code\",\n abbreviation: \"BIC\",\n aliases: [\"BIC\", \"SWIFT\", \"BIC/SWIFT\"] as const,\n candidatePattern: \"[A-Z]{6}[A-Z0-9]{2}(?:[A-Z0-9]{3})?\",\n entityType: \"company\",\n sourceUrl: \"https://www.swift.com/\",\n examples: [\"DEUTDEFF\", \"DEUTDEFF500\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default bic;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;AAAA,MAAM,eAAe;AACrB,MAAM,gBAAgB;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;AAGD,MAAM,iBAAyB;CAC7B,MAAM,qBACJ,OAAO,cAAc,KAAK,UAAU,GAAG,GAAG,CAAC;CAC7C,MAAM,UAAU,WAAW,cAAc;AAQzC,QAAO,GANL,cAAc,GACd,cAAc,GACd,cAAc,GACd,cAAc,GAGC,UADf,WAAW,aAAa,GAAG,WAAW,aAAa;;AA0BvD,MAAM,SACJ;AAEF,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,CAAC,aAAa;AAElC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,QAAO,IACL,kBACA,iCACD;AAEH,KAAI,CAAC,OAAO,KAAK,EAAE,CACjB,QAAO,IACL,kBACA,8CACD;AAMH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE;AAEzE,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;EAAC;EAAO;EAAS;EAAY;CACtC,kBAAkB;CAClB,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,YAAY,cAAc;CACrC;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"bic.js","names":[],"sources":["../src/bic.ts"],"sourcesContent":["const BIC_ALPHANUM = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\";\nconst BIC_COUNTRIES = [\n \"DE\",\n \"GB\",\n \"US\",\n \"FR\",\n \"CH\",\n \"NL\",\n \"AT\",\n] as const;\n\n/** Generate a random valid BIC (8-character). */\nconst generate = (): string => {\n const randomLetter = (): string =>\n String.fromCodePoint(65 + randomInt(0, 25));\n const country = randomPick(BIC_COUNTRIES);\n const bank =\n randomLetter() +\n randomLetter() +\n randomLetter() +\n randomLetter();\n const location =\n randomChar(BIC_ALPHANUM) + randomChar(BIC_ALPHANUM);\n return `${bank}${country}${location}`;\n};\n\n/**\n * BIC (Business Identifier Code).\n *\n * ISO 9362. 8 or 11 character code identifying\n * financial institutions. Format:\n * [A-Z]{4} (institution) + [A-Z]{2} (country) +\n * [0-9A-Z]{2} (location) + [0-9A-Z]{3} (branch,\n * optional).\n *\n * @see https://www.swift.com/\n */\n\nimport type {\n ValidateResult,\n GlobalValidator,\n} from \"./types\";\n\nimport { clean } from \"#util/clean\";\nimport {\n randomChar,\n randomInt,\n randomPick,\n} from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst BIC_RE =\n /^[A-Z]{4}[A-Z]{2}[0-9A-Z]{2}([0-9A-Z]{3})?$/;\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8 && v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"BIC must be 8 or 11 characters\",\n );\n }\n if (!BIC_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"BIC must be 8 or 11 alphanumeric characters\",\n );\n }\n // Country code at positions 4-5 is already\n // validated as [A-Z]{2} by the regex above.\n // SWIFT accepts all ISO 3166-1 alpha-2 codes\n // plus XK (Kosovo); we don't restrict further.\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 11) {\n return `${v.slice(0, 4)} ${v.slice(4, 6)} ${v.slice(6, 8)} ${v.slice(8)}`;\n }\n return `${v.slice(0, 4)} ${v.slice(4, 6)} ${v.slice(6)}`;\n};\n\n/** Business Identifier Code (SWIFT/BIC). */\nconst bic: GlobalValidator = {\n scope: \"global\",\n name: \"Business Identifier Code\",\n localName: \"Business Identifier Code\",\n abbreviation: \"BIC\",\n aliases: [\"BIC\", \"SWIFT\", \"BIC/SWIFT\"] as const,\n candidatePattern: \"[A-Z]{6}[A-Z0-9]{2}(?:[A-Z0-9]{3})?\",\n entityType: \"company\",\n sourceUrl: \"https://www.swift.com/\",\n examples: [\"DEUTDEFF\", \"DEUTDEFF500\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default bic;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAAA,MAAM,eAAe;AACrB,MAAM,gBAAgB;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAM,iBAAyB;CAC7B,MAAM,qBACJ,OAAO,cAAc,KAAK,UAAU,GAAG,EAAE,CAAC;CAC5C,MAAM,UAAU,WAAW,aAAa;CAQxC,OAAO,GANL,aAAa,IACb,aAAa,IACb,aAAa,IACb,aAAa,IAGE,UADf,WAAW,YAAY,IAAI,WAAW,YAAY;AAEtD;AA2BA,MAAM,SACJ;AAEF,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,EAAE,YAAY;AAEjC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,IACjC,OAAO,IACL,kBACA,gCACF;CAEF,IAAI,CAAC,OAAO,KAAK,CAAC,GAChB,OAAO,IACL,kBACA,6CACF;CAMF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAExE,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACvD;;AAGA,MAAM,MAAuB;CAC3B,OAAO;CACP,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EAAC;EAAO;EAAS;CAAW;CACrC,kBAAkB;CAClB,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,YAAY,aAAa;CACpC;CACA;CACA;CACA;AACF"}
package/dist/br/cnpj.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/br/cnpj.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -14,7 +14,7 @@ declare const generate: () => string;
14
14
  * - Petrobras: 33.000.167/0001-01
15
15
  * - Banco do Brasil: 00.000.000/0001-91
16
16
  */
17
- declare const cnpj: Validator;
17
+ declare const cnpj: CountryValidator<"BR">;
18
18
  //#endregion
19
19
  export { compact, cnpj as default, format, generate, validate };
20
20
  //# sourceMappingURL=cnpj.d.ts.map
package/dist/br/cnpj.js CHANGED
@@ -2,26 +2,6 @@ import { clean } from "../_util/clean.js";
2
2
  import { randomDigits } from "../_util/generate.js";
3
3
  import { err } from "../_util/result.js";
4
4
  //#region src/br/cnpj.ts
5
- /**
6
- * CNPJ (Cadastro Nacional da Pessoa Jurídica).
7
- *
8
- * Brazilian company tax identification number assigned by
9
- * the Receita Federal (Federal Revenue Service). The
10
- * number consists of 14 characters: 8 identifying the
11
- * company, 4 identifying the establishment (0001 for
12
- * headquarters), and 2 check digits computed using a
13
- * weighted modulo 11 algorithm.
14
- *
15
- * As of July 2026 the Receita Federal will begin issuing
16
- * alphanumeric CNPJs (letters A-Z in place of some
17
- * digits). The check digit algorithm uses ordinal values
18
- * (0-9 = 0-9, A-Z = 17-42) to support this.
19
- *
20
- * Format: NN.NNN.NNN/NNNN-DD (14 characters).
21
- *
22
- * @see https://www.gov.br/en/categories/finance-taxes-and-public-management/cpf-cnpj-and-other-records
23
- * @see https://en.wikipedia.org/wiki/CNPJ
24
- */
25
5
  const CNPJ_RE = /^[\dA-Z]+$/;
26
6
  const compact = (value) => clean(value, " -./").trim().toUpperCase();
27
7
  /**
@@ -117,6 +97,7 @@ const cnpj = {
117
97
  abbreviation: "CNPJ",
118
98
  aliases: ["CNPJ", "Cadastro Nacional da Pessoa Jurídica"],
119
99
  candidatePattern: "\\d{2}\\.?\\d{3}\\.?\\d{3}/?\\d{4}-?\\d{2}",
100
+ scope: "country",
120
101
  country: "BR",
121
102
  entityType: "company",
122
103
  sourceUrl: "https://www.gov.br/receitafederal/",
@@ -1 +1 @@
1
- {"version":3,"file":"cnpj.js","names":[],"sources":["../../src/br/cnpj.ts"],"sourcesContent":["/**\n * CNPJ (Cadastro Nacional da Pessoa Jurídica).\n *\n * Brazilian company tax identification number assigned by\n * the Receita Federal (Federal Revenue Service). The\n * number consists of 14 characters: 8 identifying the\n * company, 4 identifying the establishment (0001 for\n * headquarters), and 2 check digits computed using a\n * weighted modulo 11 algorithm.\n *\n * As of July 2026 the Receita Federal will begin issuing\n * alphanumeric CNPJs (letters A-Z in place of some\n * digits). The check digit algorithm uses ordinal values\n * (0-9 = 0-9, A-Z = 17-42) to support this.\n *\n * Format: NN.NNN.NNN/NNNN-DD (14 characters).\n *\n * @see https://www.gov.br/en/categories/finance-taxes-and-public-management/cpf-cnpj-and-other-records\n * @see https://en.wikipedia.org/wiki/CNPJ\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst CNPJ_RE = /^[\\dA-Z]+$/;\n\nconst compact = (value: string): string =>\n clean(value, \" -./\").trim().toUpperCase();\n\n/**\n * Convert a CNPJ character to its numeric value.\n * Digits 0-9 map to 0-9; letters A-Z map to their\n * char code minus 48 (matching python-stdnum's\n * `ord(n) - 48` convention: A=17, B=18, ..., Z=42).\n */\nconst charToValue = (ch: string): number =>\n ch.charCodeAt(0) - 48;\n\n/**\n * Calculate the two CNPJ check digits using the\n * Receita Federal modulo 11 algorithm.\n *\n * First check digit: weights [5,4,3,2,9,8,7,6,5,4,3,2]\n * applied to the first 12 characters.\n *\n * Second check digit: weights [6,5,4,3,2,9,8,7,6,5,4,3,2]\n * applied to the first 12 characters plus the first\n * check digit.\n */\nconst calcCheckDigits = (number: string): string => {\n const w1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];\n let sum = 0;\n for (let i = 0; i < 12; i++) {\n sum += (w1[i] ?? 0) * charToValue(number.charAt(i));\n }\n const d1 = ((11 - (sum % 11)) % 11) % 10;\n\n const w2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];\n sum = 0;\n for (let i = 0; i < 12; i++) {\n sum += (w2[i] ?? 0) * charToValue(number.charAt(i));\n }\n // Use the computed d1 (not the stored digit at\n // number[12]) so both check digits are derived\n // from the base alone.\n sum += (w2[12] ?? 0) * d1;\n const d2 = ((11 - (sum % 11)) % 11) % 10;\n\n return `${d1}${d2}`;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 14) {\n return err(\n \"INVALID_LENGTH\",\n \"CNPJ must be 14 characters\",\n );\n }\n if (!CNPJ_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CNPJ must contain only digits and uppercase letters\",\n );\n }\n // Reject all-zero base (first 12 chars).\n // Unlike CPF, we do not reject all-same-digit CNPJs;\n // python-stdnum only blocks the all-zero base, and\n // there is no official Receita Federal list of\n // blocked same-digit CNPJ sequences.\n if (v.startsWith(\"000000000000\")) {\n return err(\n \"INVALID_FORMAT\",\n \"CNPJ base must not be all zeros\",\n );\n }\n if (calcCheckDigits(v) !== v.slice(12)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CNPJ check digit mismatch\",\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, 2)}.${v.slice(2, 5)}.${v.slice(5, 8)}/${v.slice(8, 12)}-${v.slice(12)}`;\n};\n\n/** Generate a random valid CNPJ. */\nconst generate = (): string => {\n for (;;) {\n const base = randomDigits(12);\n if (base === \"000000000000\") continue;\n return base + calcCheckDigits(base);\n }\n};\n\n/**\n * Brazilian CNPJ (company tax ID).\n *\n * Examples sourced from publicly available Brazilian\n * corporate registries:\n * - Petrobras: 33.000.167/0001-01\n * - Banco do Brasil: 00.000.000/0001-91\n */\nconst cnpj: Validator = {\n name: \"Brazilian CNPJ\",\n localName: \"Cadastro Nacional da Pessoa Jurídica\",\n abbreviation: \"CNPJ\",\n aliases: [\n \"CNPJ\",\n \"Cadastro Nacional da Pessoa Jurídica\",\n ] as const,\n candidatePattern:\n \"\\\\d{2}\\\\.?\\\\d{3}\\\\.?\\\\d{3}/?\\\\d{4}-?\\\\d{2}\",\n country: \"BR\",\n entityType: \"company\",\n sourceUrl: \"https://www.gov.br/receitafederal/\",\n examples: [\"33000167000101\", \"00000000000191\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cnpj;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA2BA,MAAM,UAAU;AAEhB,MAAM,WAAW,UACf,MAAM,OAAO,OAAO,CAAC,MAAM,CAAC,aAAa;;;;;;;AAQ3C,MAAM,eAAe,OACnB,GAAG,WAAW,EAAE,GAAG;;;;;;;;;;;;AAarB,MAAM,mBAAmB,WAA2B;CAClD,MAAM,KAAK;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAE;CAC/C,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,IACtB,SAAQ,GAAG,MAAM,KAAK,YAAY,OAAO,OAAO,EAAE,CAAC;CAErD,MAAM,MAAO,KAAM,MAAM,MAAO,KAAM;CAEtC,MAAM,KAAK;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAE;AAClD,OAAM;AACN,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,IACtB,SAAQ,GAAG,MAAM,KAAK,YAAY,OAAO,OAAO,EAAE,CAAC;AAKrD,SAAQ,GAAG,OAAO,KAAK;AAGvB,QAAO,GAAG,MAFG,KAAM,MAAM,MAAO,KAAM;;AAKxC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,6BACD;AAEH,KAAI,CAAC,QAAQ,KAAK,EAAE,CAClB,QAAO,IACL,kBACA,sDACD;AAOH,KAAI,EAAE,WAAW,eAAe,CAC9B,QAAO,IACL,kBACA,kCACD;AAEH,KAAI,gBAAgB,EAAE,KAAK,EAAE,MAAM,GAAG,CACpC,QAAO,IACL,oBACA,4BACD;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,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG;;;AAI5F,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,OAAO,aAAa,GAAG;AAC7B,MAAI,SAAS,eAAgB;AAC7B,SAAO,OAAO,gBAAgB,KAAK;;;;;;;;;;;AAYvC,MAAM,OAAkB;CACtB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,QACA,uCACD;CACD,kBACE;CACF,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,kBAAkB,iBAAiB;CAC9C;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"cnpj.js","names":[],"sources":["../../src/br/cnpj.ts"],"sourcesContent":["/**\n * CNPJ (Cadastro Nacional da Pessoa Jurídica).\n *\n * Brazilian company tax identification number assigned by\n * the Receita Federal (Federal Revenue Service). The\n * number consists of 14 characters: 8 identifying the\n * company, 4 identifying the establishment (0001 for\n * headquarters), and 2 check digits computed using a\n * weighted modulo 11 algorithm.\n *\n * As of July 2026 the Receita Federal will begin issuing\n * alphanumeric CNPJs (letters A-Z in place of some\n * digits). The check digit algorithm uses ordinal values\n * (0-9 = 0-9, A-Z = 17-42) to support this.\n *\n * Format: NN.NNN.NNN/NNNN-DD (14 characters).\n *\n * @see https://www.gov.br/en/categories/finance-taxes-and-public-management/cpf-cnpj-and-other-records\n * @see https://en.wikipedia.org/wiki/CNPJ\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\";\n\nconst CNPJ_RE = /^[\\dA-Z]+$/;\n\nconst compact = (value: string): string =>\n clean(value, \" -./\").trim().toUpperCase();\n\n/**\n * Convert a CNPJ character to its numeric value.\n * Digits 0-9 map to 0-9; letters A-Z map to their\n * char code minus 48 (matching python-stdnum's\n * `ord(n) - 48` convention: A=17, B=18, ..., Z=42).\n */\nconst charToValue = (ch: string): number =>\n ch.charCodeAt(0) - 48;\n\n/**\n * Calculate the two CNPJ check digits using the\n * Receita Federal modulo 11 algorithm.\n *\n * First check digit: weights [5,4,3,2,9,8,7,6,5,4,3,2]\n * applied to the first 12 characters.\n *\n * Second check digit: weights [6,5,4,3,2,9,8,7,6,5,4,3,2]\n * applied to the first 12 characters plus the first\n * check digit.\n */\nconst calcCheckDigits = (number: string): string => {\n const w1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];\n let sum = 0;\n for (let i = 0; i < 12; i++) {\n sum += (w1[i] ?? 0) * charToValue(number.charAt(i));\n }\n const d1 = ((11 - (sum % 11)) % 11) % 10;\n\n const w2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];\n sum = 0;\n for (let i = 0; i < 12; i++) {\n sum += (w2[i] ?? 0) * charToValue(number.charAt(i));\n }\n // Use the computed d1 (not the stored digit at\n // number[12]) so both check digits are derived\n // from the base alone.\n sum += (w2[12] ?? 0) * d1;\n const d2 = ((11 - (sum % 11)) % 11) % 10;\n\n return `${d1}${d2}`;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 14) {\n return err(\n \"INVALID_LENGTH\",\n \"CNPJ must be 14 characters\",\n );\n }\n if (!CNPJ_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CNPJ must contain only digits and uppercase letters\",\n );\n }\n // Reject all-zero base (first 12 chars).\n // Unlike CPF, we do not reject all-same-digit CNPJs;\n // python-stdnum only blocks the all-zero base, and\n // there is no official Receita Federal list of\n // blocked same-digit CNPJ sequences.\n if (v.startsWith(\"000000000000\")) {\n return err(\n \"INVALID_FORMAT\",\n \"CNPJ base must not be all zeros\",\n );\n }\n if (calcCheckDigits(v) !== v.slice(12)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CNPJ check digit mismatch\",\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, 2)}.${v.slice(2, 5)}.${v.slice(5, 8)}/${v.slice(8, 12)}-${v.slice(12)}`;\n};\n\n/** Generate a random valid CNPJ. */\nconst generate = (): string => {\n for (;;) {\n const base = randomDigits(12);\n if (base === \"000000000000\") continue;\n return base + calcCheckDigits(base);\n }\n};\n\n/**\n * Brazilian CNPJ (company tax ID).\n *\n * Examples sourced from publicly available Brazilian\n * corporate registries:\n * - Petrobras: 33.000.167/0001-01\n * - Banco do Brasil: 00.000.000/0001-91\n */\nconst cnpj: CountryValidator<\"BR\"> = {\n name: \"Brazilian CNPJ\",\n localName: \"Cadastro Nacional da Pessoa Jurídica\",\n abbreviation: \"CNPJ\",\n aliases: [\n \"CNPJ\",\n \"Cadastro Nacional da Pessoa Jurídica\",\n ] as const,\n candidatePattern:\n \"\\\\d{2}\\\\.?\\\\d{3}\\\\.?\\\\d{3}/?\\\\d{4}-?\\\\d{2}\",\n scope: \"country\",\n country: \"BR\",\n entityType: \"company\",\n sourceUrl: \"https://www.gov.br/receitafederal/\",\n examples: [\"33000167000101\", \"00000000000191\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cnpj;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AA8BA,MAAM,UAAU;AAEhB,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,EAAE,KAAK,EAAE,YAAY;;;;;;;AAQ1C,MAAM,eAAe,OACnB,GAAG,WAAW,CAAC,IAAI;;;;;;;;;;;;AAarB,MAAM,mBAAmB,WAA2B;CAClD,MAAM,KAAK;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;CAAC;CAC9C,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KACtB,QAAQ,GAAG,MAAM,KAAK,YAAY,OAAO,OAAO,CAAC,CAAC;CAEpD,MAAM,MAAO,KAAM,MAAM,MAAO,KAAM;CAEtC,MAAM,KAAK;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;CAAC;CACjD,MAAM;CACN,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KACtB,QAAQ,GAAG,MAAM,KAAK,YAAY,OAAO,OAAO,CAAC,CAAC;CAKpD,QAAQ,GAAG,OAAO,KAAK;CAGvB,OAAO,GAAG,MAFG,KAAM,MAAM,MAAO,KAAM;AAGxC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,4BACF;CAEF,IAAI,CAAC,QAAQ,KAAK,CAAC,GACjB,OAAO,IACL,kBACA,qDACF;CAOF,IAAI,EAAE,WAAW,cAAc,GAC7B,OAAO,IACL,kBACA,iCACF;CAEF,IAAI,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GACnC,OAAO,IACL,oBACA,2BACF;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,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;AAC3F;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,OAAO,aAAa,EAAE;EAC5B,IAAI,SAAS,gBAAgB;EAC7B,OAAO,OAAO,gBAAgB,IAAI;CACpC;AACF;;;;;;;;;AAUA,MAAM,OAA+B;CACnC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,QACA,sCACF;CACA,kBACE;CACF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,kBAAkB,gBAAgB;CAC7C;CACA;CACA;CACA;AACF"}
package/dist/br/cpf.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/br/cpf.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -7,7 +7,7 @@ declare const format: (value: string) => string;
7
7
  /** Generate a random valid CPF. */
8
8
  declare const generate: () => string;
9
9
  /** Brazilian CPF (personal tax ID). */
10
- declare const cpf: Validator;
10
+ declare const cpf: CountryValidator<"BR">;
11
11
  //#endregion
12
12
  export { compact, cpf as default, format, generate, validate };
13
13
  //# sourceMappingURL=cpf.d.ts.map
package/dist/br/cpf.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/br/cpf.ts
6
- /**
7
- * CPF (Cadastro de Pessoas Físicas).
8
- *
9
- * Brazilian personal tax identification number assigned
10
- * by the Receita Federal (Federal Revenue Service) to
11
- * individuals. The number consists of 11 digits: 9 base
12
- * digits followed by 2 check digits computed using a
13
- * weighted modulo 11 algorithm.
14
- *
15
- * Format: NNN.NNN.NNN-DD (11 digits, purely numeric).
16
- *
17
- * @see https://www.gov.br/en/categories/finance-taxes-and-public-management/cpf-cnpj-and-other-records
18
- * @see https://en.wikipedia.org/wiki/CPF_number
19
- */
20
6
  const compact = (value) => clean(value, " -.").trim();
21
7
  /**
22
8
  * Calculate the two CPF check digits using the
@@ -68,6 +54,7 @@ const cpf = {
68
54
  abbreviation: "CPF",
69
55
  aliases: ["CPF", "Cadastro de Pessoas Físicas"],
70
56
  candidatePattern: "\\d{3}\\.?\\d{3}\\.?\\d{3}-?\\d{2}",
57
+ scope: "country",
71
58
  country: "BR",
72
59
  entityType: "person",
73
60
  sourceUrl: "https://www.gov.br/receitafederal/",
@@ -1 +1 @@
1
- {"version":3,"file":"cpf.js","names":[],"sources":["../../src/br/cpf.ts"],"sourcesContent":["/**\n * CPF (Cadastro de Pessoas Físicas).\n *\n * Brazilian personal tax identification number assigned\n * by the Receita Federal (Federal Revenue Service) to\n * individuals. The number consists of 11 digits: 9 base\n * digits followed by 2 check digits computed using a\n * weighted modulo 11 algorithm.\n *\n * Format: NNN.NNN.NNN-DD (11 digits, purely numeric).\n *\n * @see https://www.gov.br/en/categories/finance-taxes-and-public-management/cpf-cnpj-and-other-records\n * @see https://en.wikipedia.org/wiki/CPF_number\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, \" -.\").trim();\n\n/**\n * Calculate the two CPF check digits using the\n * Receita Federal modulo 11 algorithm.\n *\n * First check digit: multiply digits 0..8 by weights\n * 10..2, sum, then (11 - sum % 11) % 11 % 10.\n *\n * Second check digit: multiply digits 0..8 by weights\n * 11..3, add 2 * first check digit, then\n * (11 - sum % 11) % 11 % 10.\n */\nconst calcCheckDigits = (number: string): string => {\n let sum = 0;\n for (let i = 0; i < 9; i++) {\n sum += (10 - i) * Number(number[i]);\n }\n const d1 = ((11 - (sum % 11)) % 11) % 10;\n\n sum = 0;\n for (let i = 0; i < 9; i++) {\n sum += (11 - i) * Number(number[i]);\n }\n sum += 2 * d1;\n const d2 = ((11 - (sum % 11)) % 11) % 10;\n\n return `${d1}${d2}`;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\"INVALID_LENGTH\", \"CPF must be 11 digits\");\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CPF must contain only digits\",\n );\n }\n // All-same-digit CPFs (e.g. 000.000.000-00) pass the\n // checksum but are not valid registrations.\n if (/^(\\d)\\1{10}$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CPF must not be a repeated digit sequence\",\n );\n }\n if (calcCheckDigits(v) !== v.slice(9)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CPF check digit mismatch\",\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, 9)}-${v.slice(9)}`;\n};\n\n/** Generate a random valid CPF. */\nconst generate = (): string => {\n for (;;) {\n const base = randomDigits(9);\n if (/^(\\d)\\1{8}$/.test(base)) continue;\n return base + calcCheckDigits(base);\n }\n};\n\n/** Brazilian CPF (personal tax ID). */\nconst cpf: Validator = {\n name: \"Brazilian CPF\",\n localName: \"Cadastro de Pessoas Físicas\",\n abbreviation: \"CPF\",\n aliases: [\"CPF\", \"Cadastro de Pessoas Físicas\"] as const,\n candidatePattern: \"\\\\d{3}\\\\.?\\\\d{3}\\\\.?\\\\d{3}-?\\\\d{2}\",\n country: \"BR\",\n entityType: \"person\",\n sourceUrl: \"https://www.gov.br/receitafederal/\",\n examples: [\"39053344705\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cpf;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAsBA,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,CAAC,MAAM;;;;;;;;;;;;AAa5B,MAAM,mBAAmB,WAA2B;CAClD,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IACrB,SAAQ,KAAK,KAAK,OAAO,OAAO,GAAG;CAErC,MAAM,MAAO,KAAM,MAAM,MAAO,KAAM;AAEtC,OAAM;AACN,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IACrB,SAAQ,KAAK,KAAK,OAAO,OAAO,GAAG;AAErC,QAAO,IAAI;AAGX,QAAO,GAAG,MAFG,KAAM,MAAM,MAAO,KAAM;;AAKxC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IAAI,kBAAkB,wBAAwB;AAEvD,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,+BACD;AAIH,KAAI,eAAe,KAAK,EAAE,CACxB,QAAO,IACL,kBACA,4CACD;AAEH,KAAI,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,CACnC,QAAO,IACL,oBACA,2BACD;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,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE;;;AAIzE,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,OAAO,aAAa,EAAE;AAC5B,MAAI,cAAc,KAAK,KAAK,CAAE;AAC9B,SAAO,OAAO,gBAAgB,KAAK;;;;AAKvC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,8BAA8B;CAC/C,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,cAAc;CACzB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"cpf.js","names":[],"sources":["../../src/br/cpf.ts"],"sourcesContent":["/**\n * CPF (Cadastro de Pessoas Físicas).\n *\n * Brazilian personal tax identification number assigned\n * by the Receita Federal (Federal Revenue Service) to\n * individuals. The number consists of 11 digits: 9 base\n * digits followed by 2 check digits computed using a\n * weighted modulo 11 algorithm.\n *\n * Format: NNN.NNN.NNN-DD (11 digits, purely numeric).\n *\n * @see https://www.gov.br/en/categories/finance-taxes-and-public-management/cpf-cnpj-and-other-records\n * @see https://en.wikipedia.org/wiki/CPF_number\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, \" -.\").trim();\n\n/**\n * Calculate the two CPF check digits using the\n * Receita Federal modulo 11 algorithm.\n *\n * First check digit: multiply digits 0..8 by weights\n * 10..2, sum, then (11 - sum % 11) % 11 % 10.\n *\n * Second check digit: multiply digits 0..8 by weights\n * 11..3, add 2 * first check digit, then\n * (11 - sum % 11) % 11 % 10.\n */\nconst calcCheckDigits = (number: string): string => {\n let sum = 0;\n for (let i = 0; i < 9; i++) {\n sum += (10 - i) * Number(number[i]);\n }\n const d1 = ((11 - (sum % 11)) % 11) % 10;\n\n sum = 0;\n for (let i = 0; i < 9; i++) {\n sum += (11 - i) * Number(number[i]);\n }\n sum += 2 * d1;\n const d2 = ((11 - (sum % 11)) % 11) % 10;\n\n return `${d1}${d2}`;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\"INVALID_LENGTH\", \"CPF must be 11 digits\");\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CPF must contain only digits\",\n );\n }\n // All-same-digit CPFs (e.g. 000.000.000-00) pass the\n // checksum but are not valid registrations.\n if (/^(\\d)\\1{10}$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CPF must not be a repeated digit sequence\",\n );\n }\n if (calcCheckDigits(v) !== v.slice(9)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CPF check digit mismatch\",\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, 9)}-${v.slice(9)}`;\n};\n\n/** Generate a random valid CPF. */\nconst generate = (): string => {\n for (;;) {\n const base = randomDigits(9);\n if (/^(\\d)\\1{8}$/.test(base)) continue;\n return base + calcCheckDigits(base);\n }\n};\n\n/** Brazilian CPF (personal tax ID). */\nconst cpf: CountryValidator<\"BR\"> = {\n name: \"Brazilian CPF\",\n localName: \"Cadastro de Pessoas Físicas\",\n abbreviation: \"CPF\",\n aliases: [\"CPF\", \"Cadastro de Pessoas Físicas\"] as const,\n candidatePattern: \"\\\\d{3}\\\\.?\\\\d{3}\\\\.?\\\\d{3}-?\\\\d{2}\",\n scope: \"country\",\n country: \"BR\",\n entityType: \"person\",\n sourceUrl: \"https://www.gov.br/receitafederal/\",\n examples: [\"39053344705\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cpf;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAyBA,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,EAAE,KAAK;;;;;;;;;;;;AAa3B,MAAM,mBAAmB,WAA2B;CAClD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,QAAQ,KAAK,KAAK,OAAO,OAAO,EAAE;CAEpC,MAAM,MAAO,KAAM,MAAM,MAAO,KAAM;CAEtC,MAAM;CACN,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,QAAQ,KAAK,KAAK,OAAO,OAAO,EAAE;CAEpC,OAAO,IAAI;CAGX,OAAO,GAAG,MAFG,KAAM,MAAM,MAAO,KAAM;AAGxC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IAAI,kBAAkB,uBAAuB;CAEtD,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAIF,IAAI,eAAe,KAAK,CAAC,GACvB,OAAO,IACL,kBACA,2CACF;CAEF,IAAI,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,OAAO,IACL,oBACA,0BACF;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,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACxE;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,OAAO,aAAa,CAAC;EAC3B,IAAI,cAAc,KAAK,IAAI,GAAG;EAC9B,OAAO,OAAO,gBAAgB,IAAI;CACpC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,6BAA6B;CAC9C,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;AACF"}
package/dist/by/unp.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/by/unp.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -7,7 +7,7 @@ declare const format: (value: string) => string;
7
7
  /** Generate a random valid Belarus UNP. */
8
8
  declare const generate: () => string;
9
9
  /** Belarus UNP (Учётный номер плательщика). */
10
- declare const unp: Validator;
10
+ declare const unp: CountryValidator<"BY">;
11
11
  //#endregion
12
12
  export { compact, unp as default, format, generate, validate };
13
13
  //# sourceMappingURL=unp.d.ts.map
package/dist/by/unp.js CHANGED
@@ -3,18 +3,6 @@ import { randomDigits, randomInt } from "../_util/generate.js";
3
3
  import { err } from "../_util/result.js";
4
4
  import { isdigits } from "../_util/strings.js";
5
5
  //#region src/by/unp.ts
6
- /**
7
- * UNP (Учётный номер плательщика, Belarus tax number).
8
- *
9
- * 9 characters: the first two identify the region (numeric
10
- * for organisations, letters from ABCEHKMOPT for
11
- * individuals), followed by 7 digits. The last digit is a
12
- * weighted check digit (mod 11; if remainder > 9 the
13
- * number is invalid).
14
- *
15
- * @see https://be.wikipedia.org/wiki/Уліковы_нумар_плацельшчыка
16
- * @see https://www.nalog.gov.by/
17
- */
18
6
  /** Cyrillic to Latin mapping for the letter positions. */
19
7
  const CYRILLIC_TO_LATIN = {
20
8
  А: "A",
@@ -45,7 +33,7 @@ const compact = (value) => {
45
33
  let v = clean(value, " ").toUpperCase().trim();
46
34
  if (v.startsWith("УНП")) v = v.slice(3);
47
35
  else if (v.startsWith("UNP")) v = v.slice(3);
48
- return [...v].map((ch) => CYRILLIC_TO_LATIN[ch] ?? ch).join("");
36
+ return v.split("").map((ch) => CYRILLIC_TO_LATIN[ch] ?? ch).join("");
49
37
  };
50
38
  const calcCheckDigit = (number) => {
51
39
  let work = number;
@@ -73,7 +61,7 @@ const validate = (value) => {
73
61
  if (v.length !== 9) return err("INVALID_LENGTH", "Belarus UNP must be 9 characters");
74
62
  if (!isdigits(v.slice(2))) return err("INVALID_FORMAT", "Belarus UNP positions 3-9 must be digits");
75
63
  const first2 = v.slice(0, 2);
76
- if (!isdigits(first2) && ![...first2].every((ch) => ALPHA_SET.includes(ch))) return err("INVALID_FORMAT", "Belarus UNP first two characters must be digits or letters from ABCEHKMOPT");
64
+ if (!isdigits(first2) && !first2.split("").every((ch) => ALPHA_SET.includes(ch))) return err("INVALID_FORMAT", "Belarus UNP first two characters must be digits or letters from ABCEHKMOPT");
77
65
  if (!VALID_FIRST.includes(v[0])) return err("INVALID_COMPONENT", "Belarus UNP has an invalid region prefix");
78
66
  const expected = calcCheckDigit(v);
79
67
  if (expected === null) return err("INVALID_CHECKSUM", "Belarus UNP check digit is invalid (mod 11 remainder > 9)");
@@ -102,6 +90,7 @@ const unp = {
102
90
  abbreviation: "УНП",
103
91
  aliases: ["УНП", "UNP"],
104
92
  candidatePattern: "\\d{9}",
93
+ scope: "country",
105
94
  country: "BY",
106
95
  entityType: "any",
107
96
  sourceUrl: "https://www.nalog.gov.by/",