stdnum 1.10.0 → 1.10.2

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 (496) hide show
  1. package/README.md +1 -0
  2. package/lib/cjs/in/gstin.js +3 -3
  3. package/lib/cjs/no/fodselsnummer.js +2 -2
  4. package/lib/cjs/tw/natid.js +8 -5
  5. package/lib/cjs/tw/ui.js +8 -5
  6. package/lib/esm/in/gstin.js +3 -3
  7. package/lib/esm/no/fodselsnummer.js +2 -2
  8. package/lib/esm/tw/natid.js +8 -5
  9. package/lib/esm/tw/ui.js +8 -5
  10. package/package.json +5 -2
  11. package/src/ad/index.ts +1 -0
  12. package/src/ad/nrt.spec.ts +36 -0
  13. package/src/ad/nrt.ts +87 -0
  14. package/src/al/index.ts +1 -0
  15. package/src/al/nipt.spec.ts +43 -0
  16. package/src/al/nipt.ts +111 -0
  17. package/src/ar/cbu.spec.ts +28 -0
  18. package/src/ar/cbu.ts +96 -0
  19. package/src/ar/cuit.spec.ts +28 -0
  20. package/src/ar/cuit.ts +102 -0
  21. package/src/ar/dni.spec.ts +22 -0
  22. package/src/ar/dni.ts +72 -0
  23. package/src/ar/index.ts +3 -0
  24. package/src/at/businessid.spec.ts +34 -0
  25. package/src/at/businessid.ts +73 -0
  26. package/src/at/index.ts +4 -0
  27. package/src/at/tin.spec.ts +173 -0
  28. package/src/at/tin.ts +140 -0
  29. package/src/at/uid.spec.ts +44 -0
  30. package/src/at/uid.ts +84 -0
  31. package/src/at/vnr.spec.ts +38 -0
  32. package/src/at/vnr.ts +84 -0
  33. package/src/au/abn.spec.ts +28 -0
  34. package/src/au/abn.ts +78 -0
  35. package/src/au/acn.spec.ts +34 -0
  36. package/src/au/acn.ts +76 -0
  37. package/src/au/index.ts +3 -0
  38. package/src/au/tfn.spec.ts +28 -0
  39. package/src/au/tfn.ts +79 -0
  40. package/src/az/index.ts +2 -0
  41. package/src/az/pin.spec.ts +16 -0
  42. package/src/az/pin.ts +61 -0
  43. package/src/az/tin.spec.ts +28 -0
  44. package/src/az/tin.ts +64 -0
  45. package/src/ba/index.ts +1 -0
  46. package/src/ba/jmbg.spec.ts +28 -0
  47. package/src/ba/jmbg.ts +85 -0
  48. package/src/be/bis.spec.ts +184 -0
  49. package/src/be/bis.ts +85 -0
  50. package/src/be/index.ts +4 -0
  51. package/src/be/insz.spec.ts +51 -0
  52. package/src/be/insz.ts +55 -0
  53. package/src/be/nn.spec.ts +117 -0
  54. package/src/be/nn.ts +77 -0
  55. package/src/be/personIdentifierHelpers.spec.ts +254 -0
  56. package/src/be/personIdentifierHelpers.ts +130 -0
  57. package/src/be/vat.spec.ts +46 -0
  58. package/src/be/vat.ts +84 -0
  59. package/src/bg/egn.spec.ts +28 -0
  60. package/src/bg/egn.ts +75 -0
  61. package/src/bg/index.ts +3 -0
  62. package/src/bg/pnf.spec.ts +28 -0
  63. package/src/bg/pnf.ts +73 -0
  64. package/src/bg/vat.spec.ts +34 -0
  65. package/src/bg/vat.ts +120 -0
  66. package/src/br/cnpj.spec.ts +34 -0
  67. package/src/br/cnpj.ts +89 -0
  68. package/src/br/cpf.spec.ts +34 -0
  69. package/src/br/cpf.ts +87 -0
  70. package/src/br/index.ts +2 -0
  71. package/src/by/index.ts +1 -0
  72. package/src/by/unp.spec.ts +34 -0
  73. package/src/by/unp.ts +108 -0
  74. package/src/bz/index.ts +1 -0
  75. package/src/bz/tin.spec.ts +28 -0
  76. package/src/bz/tin.ts +67 -0
  77. package/src/ca/bn.spec.ts +40 -0
  78. package/src/ca/bn.ts +88 -0
  79. package/src/ca/gst.spec.ts +34 -0
  80. package/src/ca/gst.ts +70 -0
  81. package/src/ca/index.ts +5 -0
  82. package/src/ca/pst.spec.ts +28 -0
  83. package/src/ca/pst.ts +71 -0
  84. package/src/ca/qst.spec.ts +47 -0
  85. package/src/ca/qst.ts +88 -0
  86. package/src/ca/sin.spec.ts +34 -0
  87. package/src/ca/sin.ts +72 -0
  88. package/src/ch/index.ts +3 -0
  89. package/src/ch/ssn.spec.ts +50 -0
  90. package/src/ch/ssn.ts +74 -0
  91. package/src/ch/uid.spec.ts +34 -0
  92. package/src/ch/uid.ts +82 -0
  93. package/src/ch/vat.spec.ts +28 -0
  94. package/src/ch/vat.ts +83 -0
  95. package/src/cl/index.ts +2 -0
  96. package/src/cl/run.ts +13 -0
  97. package/src/cl/rut.spec.ts +50 -0
  98. package/src/cl/rut.ts +97 -0
  99. package/src/cn/index.ts +2 -0
  100. package/src/cn/ric.spec.ts +34 -0
  101. package/src/cn/ric.ts +86 -0
  102. package/src/cn/uscc.spec.ts +34 -0
  103. package/src/cn/uscc.ts +110 -0
  104. package/src/co/index.ts +1 -0
  105. package/src/co/nit.spec.ts +40 -0
  106. package/src/co/nit.ts +85 -0
  107. package/src/cr/cpf.spec.ts +34 -0
  108. package/src/cr/cpf.ts +93 -0
  109. package/src/cr/cpj.spec.ts +28 -0
  110. package/src/cr/cpj.ts +111 -0
  111. package/src/cr/cr.spec.ts +28 -0
  112. package/src/cr/cr.ts +75 -0
  113. package/src/cr/index.ts +3 -0
  114. package/src/cu/index.ts +1 -0
  115. package/src/cu/ni.spec.ts +34 -0
  116. package/src/cu/ni.ts +74 -0
  117. package/src/cy/index.ts +1 -0
  118. package/src/cy/vat.spec.ts +28 -0
  119. package/src/cy/vat.ts +98 -0
  120. package/src/cz/dic.spec.ts +28 -0
  121. package/src/cz/dic.ts +127 -0
  122. package/src/cz/index.ts +2 -0
  123. package/src/cz/rc.spec.ts +44 -0
  124. package/src/cz/rc.ts +95 -0
  125. package/src/de/idnr.spec.ts +34 -0
  126. package/src/de/idnr.ts +91 -0
  127. package/src/de/index.ts +6 -0
  128. package/src/de/passport.spec.ts +31 -0
  129. package/src/de/passport.ts +86 -0
  130. package/src/de/pwnr.spec.ts +62 -0
  131. package/src/de/pwnr.ts +190 -0
  132. package/src/de/stnr.spec.ts +85 -0
  133. package/src/de/stnr.ts +193 -0
  134. package/src/de/svnr.spec.ts +56 -0
  135. package/src/de/svnr.ts +158 -0
  136. package/src/de/vat.spec.ts +28 -0
  137. package/src/de/vat.ts +74 -0
  138. package/src/dk/cpr.spec.ts +34 -0
  139. package/src/dk/cpr.ts +129 -0
  140. package/src/dk/cvr.spec.ts +28 -0
  141. package/src/dk/cvr.ts +81 -0
  142. package/src/dk/index.ts +2 -0
  143. package/src/do/cedula.spec.ts +34 -0
  144. package/src/do/cedula.ts +67 -0
  145. package/src/do/index.ts +3 -0
  146. package/src/do/ncf.spec.ts +34 -0
  147. package/src/do/ncf.ts +133 -0
  148. package/src/do/rnc.spec.ts +40 -0
  149. package/src/do/rnc.ts +74 -0
  150. package/src/dz/index.ts +1 -0
  151. package/src/dz/nif.spec.ts +39 -0
  152. package/src/dz/nif.ts +80 -0
  153. package/src/ec/ci.spec.ts +28 -0
  154. package/src/ec/ci.ts +92 -0
  155. package/src/ec/index.ts +2 -0
  156. package/src/ec/ruc.spec.ts +37 -0
  157. package/src/ec/ruc.ts +117 -0
  158. package/src/ee/ik.spec.ts +28 -0
  159. package/src/ee/ik.ts +114 -0
  160. package/src/ee/index.ts +3 -0
  161. package/src/ee/kmkr.spec.ts +28 -0
  162. package/src/ee/kmkr.ts +76 -0
  163. package/src/ee/registrikood.spec.ts +28 -0
  164. package/src/ee/registrikood.ts +80 -0
  165. package/src/eg/index.ts +1 -0
  166. package/src/eg/tn.spec.ts +44 -0
  167. package/src/eg/tn.ts +96 -0
  168. package/src/es/cif.spec.ts +43 -0
  169. package/src/es/cif.ts +84 -0
  170. package/src/es/dni.spec.ts +28 -0
  171. package/src/es/dni.ts +83 -0
  172. package/src/es/index.ts +5 -0
  173. package/src/es/nie.spec.ts +28 -0
  174. package/src/es/nie.ts +79 -0
  175. package/src/es/nif.spec.ts +52 -0
  176. package/src/es/nif.ts +95 -0
  177. package/src/es/nss.spec.ts +28 -0
  178. package/src/es/nss.ts +132 -0
  179. package/src/exceptions.ts +66 -0
  180. package/src/fi/alv.spec.ts +28 -0
  181. package/src/fi/alv.ts +76 -0
  182. package/src/fi/hetu.spec.ts +37 -0
  183. package/src/fi/hetu.ts +108 -0
  184. package/src/fi/index.ts +3 -0
  185. package/src/fi/ytunnus.spec.ts +28 -0
  186. package/src/fi/ytunnus.ts +49 -0
  187. package/src/fo/index.ts +1 -0
  188. package/src/fo/vn.spec.ts +34 -0
  189. package/src/fo/vn.ts +71 -0
  190. package/src/fr/index.ts +5 -0
  191. package/src/fr/nif.spec.ts +34 -0
  192. package/src/fr/nif.ts +82 -0
  193. package/src/fr/nir.spec.ts +36 -0
  194. package/src/fr/nir.ts +98 -0
  195. package/src/fr/siren.spec.ts +28 -0
  196. package/src/fr/siren.ts +68 -0
  197. package/src/fr/siret.spec.ts +38 -0
  198. package/src/fr/siret.ts +79 -0
  199. package/src/fr/tva.spec.ts +40 -0
  200. package/src/fr/tva.ts +125 -0
  201. package/src/gb/index.ts +3 -0
  202. package/src/gb/nino-prefixes.ts +245 -0
  203. package/src/gb/nino.spec.ts +80 -0
  204. package/src/gb/nino.ts +80 -0
  205. package/src/gb/utr.spec.ts +28 -0
  206. package/src/gb/utr.ts +76 -0
  207. package/src/gb/vat.spec.ts +40 -0
  208. package/src/gb/vat.ts +112 -0
  209. package/src/gen/ean.spec.ts +34 -0
  210. package/src/gen/ean.ts +71 -0
  211. package/src/gen/index.ts +1 -0
  212. package/src/gh/index.ts +1 -0
  213. package/src/gh/tin.spec.ts +42 -0
  214. package/src/gh/tin.ts +93 -0
  215. package/src/gn/index.ts +1 -0
  216. package/src/gn/nifp.spec.ts +40 -0
  217. package/src/gn/nifp.ts +72 -0
  218. package/src/gr/amka.spec.ts +28 -0
  219. package/src/gr/amka.ts +76 -0
  220. package/src/gr/index.ts +2 -0
  221. package/src/gr/vat.spec.ts +34 -0
  222. package/src/gr/vat.ts +84 -0
  223. package/src/gt/cui.spec.ts +34 -0
  224. package/src/gt/cui.ts +110 -0
  225. package/src/gt/index.ts +2 -0
  226. package/src/gt/nit.spec.ts +34 -0
  227. package/src/gt/nit.ts +86 -0
  228. package/src/hk/hkid.spec.ts +52 -0
  229. package/src/hk/hkid.ts +90 -0
  230. package/src/hk/index.ts +1 -0
  231. package/src/hr/index.ts +1 -0
  232. package/src/hr/oib.spec.ts +28 -0
  233. package/src/hr/oib.ts +67 -0
  234. package/src/hu/anum.spec.ts +28 -0
  235. package/src/hu/anum.ts +71 -0
  236. package/src/hu/index.ts +1 -0
  237. package/src/id/index.ts +1 -0
  238. package/src/id/npwp.spec.ts +34 -0
  239. package/src/id/npwp.ts +116 -0
  240. package/src/ie/index.ts +2 -0
  241. package/src/ie/pps.spec.ts +58 -0
  242. package/src/ie/pps.ts +81 -0
  243. package/src/ie/vat.spec.ts +40 -0
  244. package/src/ie/vat.ts +99 -0
  245. package/src/il/hp.spec.ts +38 -0
  246. package/src/il/hp.ts +75 -0
  247. package/src/il/idnr.spec.ts +28 -0
  248. package/src/il/idnr.ts +70 -0
  249. package/src/il/index.ts +2 -0
  250. package/src/in/aadhaar.spec.ts +40 -0
  251. package/src/in/aadhaar.ts +85 -0
  252. package/src/in/epic.spec.ts +34 -0
  253. package/src/in/epic.ts +85 -0
  254. package/src/in/gstin.spec.ts +34 -0
  255. package/src/in/gstin.ts +156 -0
  256. package/src/in/index.ts +4 -0
  257. package/src/in/pan.spec.ts +40 -0
  258. package/src/in/pan.ts +93 -0
  259. package/src/index.ts +404 -0
  260. package/src/is/index.ts +2 -0
  261. package/src/is/kennitala.spec.ts +46 -0
  262. package/src/is/kennitala.ts +80 -0
  263. package/src/is/vsk.spec.ts +22 -0
  264. package/src/is/vsk.ts +60 -0
  265. package/src/it/aic.spec.ts +40 -0
  266. package/src/it/aic.ts +97 -0
  267. package/src/it/codicefiscale.spec.ts +28 -0
  268. package/src/it/codicefiscale.ts +167 -0
  269. package/src/it/index.ts +3 -0
  270. package/src/it/iva.spec.ts +28 -0
  271. package/src/it/iva.ts +65 -0
  272. package/src/jp/cn.spec.ts +28 -0
  273. package/src/jp/cn.ts +77 -0
  274. package/src/jp/index.ts +1 -0
  275. package/src/ke/index.ts +1 -0
  276. package/src/ke/pin.spec.ts +34 -0
  277. package/src/ke/pin.ts +77 -0
  278. package/src/kr/brn.spec.ts +28 -0
  279. package/src/kr/brn.ts +91 -0
  280. package/src/kr/index.ts +2 -0
  281. package/src/kr/rrn.spec.ts +34 -0
  282. package/src/kr/rrn.ts +104 -0
  283. package/src/li/index.ts +1 -0
  284. package/src/li/peid.spec.ts +22 -0
  285. package/src/li/peid.ts +71 -0
  286. package/src/lt/asmens.spec.ts +28 -0
  287. package/src/lt/asmens.ts +73 -0
  288. package/src/lt/index.ts +2 -0
  289. package/src/lt/pvm.spec.ts +34 -0
  290. package/src/lt/pvm.ts +75 -0
  291. package/src/lu/index.ts +1 -0
  292. package/src/lu/tva.spec.ts +28 -0
  293. package/src/lu/tva.ts +70 -0
  294. package/src/lv/index.ts +1 -0
  295. package/src/lv/pvn.spec.ts +44 -0
  296. package/src/lv/pvn.ts +102 -0
  297. package/src/ma/ice.spec.ts +39 -0
  298. package/src/ma/ice.ts +72 -0
  299. package/src/ma/ice9.spec.ts +28 -0
  300. package/src/ma/ice9.ts +62 -0
  301. package/src/ma/index.ts +2 -0
  302. package/src/mc/index.ts +1 -0
  303. package/src/mc/tva.spec.ts +28 -0
  304. package/src/mc/tva.ts +67 -0
  305. package/src/md/idno.spec.ts +28 -0
  306. package/src/md/idno.ts +78 -0
  307. package/src/md/index.ts +1 -0
  308. package/src/me/index.ts +2 -0
  309. package/src/me/jmbg.ts +17 -0
  310. package/src/me/pib.spec.ts +158 -0
  311. package/src/me/pib.ts +77 -0
  312. package/src/mk/edb.spec.ts +50 -0
  313. package/src/mk/edb.ts +88 -0
  314. package/src/mk/index.ts +2 -0
  315. package/src/mk/jmbg.ts +17 -0
  316. package/src/mt/index.ts +1 -0
  317. package/src/mt/vat.spec.ts +28 -0
  318. package/src/mt/vat.ts +69 -0
  319. package/src/mu/index.ts +1 -0
  320. package/src/mu/nid.spec.ts +34 -0
  321. package/src/mu/nid.ts +89 -0
  322. package/src/mx/banks.ts +658 -0
  323. package/src/mx/clabe.spec.ts +68 -0
  324. package/src/mx/clabe.ts +105 -0
  325. package/src/mx/curp.spec.ts +28 -0
  326. package/src/mx/curp.ts +261 -0
  327. package/src/mx/index.ts +3 -0
  328. package/src/mx/rfc.spec.ts +69 -0
  329. package/src/mx/rfc.ts +193 -0
  330. package/src/my/index.ts +1 -0
  331. package/src/my/nric.spec.ts +40 -0
  332. package/src/my/nric.ts +91 -0
  333. package/src/nl/bsn.spec.ts +68 -0
  334. package/src/nl/bsn.ts +81 -0
  335. package/src/nl/btw.spec.ts +40 -0
  336. package/src/nl/btw.ts +95 -0
  337. package/src/nl/index.ts +3 -0
  338. package/src/nl/onderwijsnummer.spec.ts +34 -0
  339. package/src/nl/onderwijsnummer.ts +77 -0
  340. package/src/no/fodselsnummer.spec.ts +56 -0
  341. package/src/no/fodselsnummer.ts +118 -0
  342. package/src/no/index.ts +4 -0
  343. package/src/no/kontonr.spec.ts +34 -0
  344. package/src/no/kontonr.ts +84 -0
  345. package/src/no/mva.spec.ts +28 -0
  346. package/src/no/mva.ts +80 -0
  347. package/src/no/orgnr.spec.ts +28 -0
  348. package/src/no/orgnr.ts +75 -0
  349. package/src/nz/bank.spec.ts +28 -0
  350. package/src/nz/bank.ts +238 -0
  351. package/src/nz/index.ts +2 -0
  352. package/src/nz/ird.spec.ts +34 -0
  353. package/src/nz/ird.ts +102 -0
  354. package/src/pe/ce.spec.ts +46 -0
  355. package/src/pe/ce.ts +61 -0
  356. package/src/pe/cui.spec.ts +28 -0
  357. package/src/pe/cui.ts +85 -0
  358. package/src/pe/index.ts +3 -0
  359. package/src/pe/ruc.spec.ts +46 -0
  360. package/src/pe/ruc.ts +84 -0
  361. package/src/pk/cnic.spec.ts +34 -0
  362. package/src/pk/cnic.ts +97 -0
  363. package/src/pk/index.ts +2 -0
  364. package/src/pk/ntn.spec.ts +22 -0
  365. package/src/pk/ntn.ts +65 -0
  366. package/src/pl/index.ts +3 -0
  367. package/src/pl/nip.spec.ts +34 -0
  368. package/src/pl/nip.ts +74 -0
  369. package/src/pl/pesel.spec.ts +34 -0
  370. package/src/pl/pesel.ts +97 -0
  371. package/src/pl/regon.spec.ts +52 -0
  372. package/src/pl/regon.ts +88 -0
  373. package/src/pt/cc.spec.ts +43 -0
  374. package/src/pt/cc.ts +74 -0
  375. package/src/pt/index.ts +3 -0
  376. package/src/pt/nif.spec.ts +28 -0
  377. package/src/pt/nif.ts +78 -0
  378. package/src/pt/nipc.ts +27 -0
  379. package/src/py/cedula.spec.ts +46 -0
  380. package/src/py/cedula.ts +73 -0
  381. package/src/py/index.ts +2 -0
  382. package/src/py/ruc.spec.ts +40 -0
  383. package/src/py/ruc.ts +93 -0
  384. package/src/ro/cif.spec.ts +40 -0
  385. package/src/ro/cif.ts +62 -0
  386. package/src/ro/cnp.spec.ts +50 -0
  387. package/src/ro/cnp.ts +158 -0
  388. package/src/ro/cui.spec.ts +28 -0
  389. package/src/ro/cui.ts +83 -0
  390. package/src/ro/index.ts +4 -0
  391. package/src/ro/onrc.spec.ts +28 -0
  392. package/src/ro/onrc.ts +109 -0
  393. package/src/rs/index.ts +2 -0
  394. package/src/rs/jmbg.ts +16 -0
  395. package/src/rs/pib.spec.ts +28 -0
  396. package/src/rs/pib.ts +69 -0
  397. package/src/ru/index.ts +1 -0
  398. package/src/ru/inn.spec.ts +32 -0
  399. package/src/ru/inn.ts +106 -0
  400. package/src/se/index.ts +3 -0
  401. package/src/se/orgnr.spec.ts +28 -0
  402. package/src/se/orgnr.ts +68 -0
  403. package/src/se/personnummer.spec.ts +45 -0
  404. package/src/se/personnummer.ts +143 -0
  405. package/src/se/vat.spec.ts +28 -0
  406. package/src/se/vat.ts +73 -0
  407. package/src/sg/index.ts +1 -0
  408. package/src/sg/uen.spec.ts +46 -0
  409. package/src/sg/uen.ts +209 -0
  410. package/src/si/ddv.spec.ts +28 -0
  411. package/src/si/ddv.ts +76 -0
  412. package/src/si/emso.spec.ts +15 -0
  413. package/src/si/emso.ts +27 -0
  414. package/src/si/index.ts +3 -0
  415. package/src/si/jmbg.ts +20 -0
  416. package/src/sk/dph.spec.ts +28 -0
  417. package/src/sk/dph.ts +71 -0
  418. package/src/sk/index.ts +2 -0
  419. package/src/sk/rc.ts +12 -0
  420. package/src/sm/coe.spec.ts +34 -0
  421. package/src/sm/coe.ts +80 -0
  422. package/src/sm/index.ts +1 -0
  423. package/src/sv/index.ts +1 -0
  424. package/src/sv/nit.spec.ts +34 -0
  425. package/src/sv/nit.ts +117 -0
  426. package/src/th/idnr.spec.ts +41 -0
  427. package/src/th/idnr.ts +80 -0
  428. package/src/th/index.ts +3 -0
  429. package/src/th/moa.spec.ts +62 -0
  430. package/src/th/moa.ts +85 -0
  431. package/src/th/tin.spec.ts +77 -0
  432. package/src/th/tin.ts +56 -0
  433. package/src/tn/index.ts +1 -0
  434. package/src/tn/mf.spec.ts +37 -0
  435. package/src/tn/mf.ts +169 -0
  436. package/src/tr/index.ts +2 -0
  437. package/src/tr/tckimlik.spec.ts +40 -0
  438. package/src/tr/tckimlik.ts +87 -0
  439. package/src/tr/vkn.spec.ts +28 -0
  440. package/src/tr/vkn.ts +87 -0
  441. package/src/tw/ban.spec.ts +28 -0
  442. package/src/tw/ban.ts +67 -0
  443. package/src/tw/index.ts +5 -0
  444. package/src/tw/natid.spec.ts +41 -0
  445. package/src/tw/natid.ts +109 -0
  446. package/src/tw/tax_code.spec.ts +34 -0
  447. package/src/tw/tax_code.ts +98 -0
  448. package/src/tw/ubn.spec.ts +28 -0
  449. package/src/tw/ubn.ts +80 -0
  450. package/src/tw/ui.spec.ts +49 -0
  451. package/src/tw/ui.ts +111 -0
  452. package/src/types.ts +82 -0
  453. package/src/ua/edrpou.spec.ts +28 -0
  454. package/src/ua/edrpou.ts +88 -0
  455. package/src/ua/index.ts +2 -0
  456. package/src/ua/rntrc.spec.ts +28 -0
  457. package/src/ua/rntrc.ts +77 -0
  458. package/src/us/ein.spec.ts +28 -0
  459. package/src/us/ein.ts +179 -0
  460. package/src/us/index.ts +2 -0
  461. package/src/us/ssn.spec.ts +28 -0
  462. package/src/us/ssn.ts +117 -0
  463. package/src/util/checksum.spec.ts +70 -0
  464. package/src/util/checksum.ts +258 -0
  465. package/src/util/index.ts +13 -0
  466. package/src/util/isValidDate.spec.ts +49 -0
  467. package/src/util/isValidDate.ts +87 -0
  468. package/src/util/iso7064.spec.ts +17 -0
  469. package/src/util/iso7064.ts +8 -0
  470. package/src/util/pymod.ts +8 -0
  471. package/src/util/strings/char.ts +18 -0
  472. package/src/util/strings/clean.spec.ts +15 -0
  473. package/src/util/strings/clean.ts +305 -0
  474. package/src/util/strings/format.ts +18 -0
  475. package/src/util/strings/index.ts +5 -0
  476. package/src/util/strings/reverseString.ts +3 -0
  477. package/src/util/strings/splitAt.spec.ts +15 -0
  478. package/src/util/strings/splitAt.ts +16 -0
  479. package/src/uy/cedula.spec.ts +28 -0
  480. package/src/uy/cedula.ts +74 -0
  481. package/src/uy/index.ts +3 -0
  482. package/src/uy/nie.spec.ts +28 -0
  483. package/src/uy/nie.ts +84 -0
  484. package/src/uy/rut.spec.ts +34 -0
  485. package/src/uy/rut.ts +99 -0
  486. package/src/ve/index.ts +1 -0
  487. package/src/ve/rif.spec.ts +38 -0
  488. package/src/ve/rif.ts +92 -0
  489. package/src/vn/index.ts +1 -0
  490. package/src/vn/mst.spec.ts +40 -0
  491. package/src/vn/mst.ts +100 -0
  492. package/src/za/idnr.spec.ts +28 -0
  493. package/src/za/idnr.ts +84 -0
  494. package/src/za/index.ts +2 -0
  495. package/src/za/tin.spec.ts +28 -0
  496. package/src/za/tin.ts +75 -0
package/src/be/insz.ts ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The Belgian Social Security Identification Number is an 11 digit number.
3
+ * It can be either a National Register Number (NN, NISS) or BIS.
4
+ *
5
+ * Sources
6
+ * https://fr.wikipedia.org/wiki/Numéro_de_registre_national
7
+ * https://www2.deloitte.com/content/dam/Deloitte/be/Documents/tax/TaxAlerts/IndividualTaxAlerts/Social%20Security%20alert%20-%20BelgianIDpro%20-%2026%20Nov%202020.pdf
8
+ *
9
+ * PERSON
10
+ */
11
+
12
+ import { strings } from '../util';
13
+ import { validate as nnValidate } from './nn';
14
+ import { validate as bisValidate } from './bis';
15
+ import { Validator, ValidateReturn } from '../types';
16
+
17
+ function clean(input: string): ReturnType<typeof strings.cleanUnicode> {
18
+ return strings.cleanUnicode(input, ' -.');
19
+ }
20
+
21
+ const impl: Validator = {
22
+ name: 'Belgian Social Security Identification Number',
23
+ localName: 'Identificatienummer van de Sociale Zekerheid',
24
+ abbreviation: 'INSZ, NISS',
25
+ compact(input: string): string {
26
+ const [value, err] = clean(input);
27
+
28
+ if (err) {
29
+ throw err;
30
+ }
31
+
32
+ return value;
33
+ },
34
+ format(input: string): string {
35
+ const [value] = clean(input);
36
+ return value;
37
+ },
38
+ validate(input: string): ValidateReturn {
39
+ const results = [nnValidate(input), bisValidate(input)];
40
+ const validResult = results.find(r => r.isValid);
41
+ if (validResult) return validResult;
42
+
43
+ // The only case with two different error types is an invalid checksum and an
44
+ // invalid format. The identifier with the checksum error had correct
45
+ // formatting, so invalid checksum seems like the more descriptive error.
46
+
47
+ const checksumErrorResult = results.find(
48
+ r => r.error && r.error.name === 'InvalidChecksum',
49
+ );
50
+ return checksumErrorResult || results[0];
51
+ },
52
+ };
53
+
54
+ export const { name, localName, abbreviation, validate, format, compact } =
55
+ impl;
@@ -0,0 +1,117 @@
1
+ import { validate, format } from './nn';
2
+ import { InvalidLength, InvalidChecksum, InvalidFormat } from '../exceptions';
3
+
4
+ describe('be/nn', () => {
5
+ it('format:88 02 29-999.90', () => {
6
+ const result = format('88 02 29-999.90');
7
+
8
+ expect(result).toEqual('88022999990');
9
+ });
10
+
11
+ it('format:88022999990', () => {
12
+ const result = format('88022999990');
13
+
14
+ expect(result).toEqual('88022999990');
15
+ });
16
+
17
+ it('validate:1', () => {
18
+ const result = validate('1');
19
+
20
+ expect(result.error).toBeInstanceOf(InvalidLength);
21
+ });
22
+
23
+ it('validate:88022999990', () => {
24
+ const result = validate('88022999990');
25
+
26
+ expect(result.isValid && result.compact).toEqual('88022999990');
27
+ });
28
+
29
+ it('validate:88022999991', () => {
30
+ const result = validate('88022999991');
31
+
32
+ expect(result.error).toBeInstanceOf(InvalidChecksum);
33
+ });
34
+
35
+ it('validate:87022999991', () => {
36
+ const result = validate('87022999991');
37
+
38
+ expect(result.error).toBeInstanceOf(InvalidFormat);
39
+ });
40
+
41
+ test.each([
42
+ '88022999297',
43
+ '85073003328',
44
+ '20070199922',
45
+ '20070199951',
46
+ '80000099902',
47
+ '00000199938',
48
+ '99000099913',
49
+ ])('validate:%s', value => {
50
+ const result = validate(value);
51
+
52
+ expect(result.isValid).toEqual(true);
53
+ });
54
+
55
+ it('validate:20070199952', () => {
56
+ const result = validate('20070199952');
57
+
58
+ expect(result.error).toBeInstanceOf(InvalidChecksum);
59
+ });
60
+
61
+ it('validate:80000099903', () => {
62
+ const result = validate('80000099903');
63
+
64
+ expect(result.error).toBeInstanceOf(InvalidChecksum);
65
+ });
66
+
67
+ it('validate:00000199939', () => {
68
+ const result = validate('00000199939');
69
+
70
+ expect(result.error).toBeInstanceOf(InvalidChecksum);
71
+ });
72
+
73
+ it('validate:99000099942', () => {
74
+ const result = validate('99000099942');
75
+
76
+ expect(result.error).toBeInstanceOf(InvalidChecksum);
77
+ });
78
+
79
+ it('validate:40000100133', () => {
80
+ const result = validate('40000100133');
81
+
82
+ expect(result.isValid && result.compact).toEqual('40000100133');
83
+ });
84
+
85
+ it('validate:00000199938', () => {
86
+ const result = validate('00000199938');
87
+
88
+ expect(result.isValid && result.compact).toEqual('00000199938');
89
+ });
90
+
91
+ it('validate:40000095579', () => {
92
+ const result = validate('40000095579');
93
+
94
+ expect(result.isValid && result.compact).toEqual('40000095579');
95
+ });
96
+
97
+ it('validate:(unspecified date in current year)', () => {
98
+ const yy = new Date().getFullYear() % 100;
99
+ const baseNum = parseInt(`${yy}0000999`, 10);
100
+ const twoPrefixedBaseNumber = parseInt(`${2}${baseNum}`, 10);
101
+ const checksum = 97 - (twoPrefixedBaseNumber % 97);
102
+ const id = `${baseNum}${checksum}`;
103
+
104
+ const result = validate(id);
105
+ expect(result.isValid && result.compact).toEqual(id);
106
+ });
107
+
108
+ it('validate:(unspecified date 100 years ago)', () => {
109
+ const yy = new Date().getFullYear() % 100;
110
+ const baseNum = parseInt(`${yy}0000999`, 10);
111
+ const checksum = 97 - (baseNum % 97);
112
+ const id = `${baseNum}${checksum}`;
113
+
114
+ const result = validate(id);
115
+ expect(result.isValid && result.compact).toEqual(id);
116
+ });
117
+ });
package/src/be/nn.ts ADDED
@@ -0,0 +1,77 @@
1
+ /**
2
+ * NN, NISS, RRN (Belgian national number).
3
+ *
4
+ * The national registration number (Rijksregisternummer, Numéro de registre
5
+ * national, Nationalregisternummer) is a unique identification number of
6
+ * natural persons who are registered in Belgium.
7
+ *
8
+ * The number consists of 11 digits and includes the person's date of birth and
9
+ * gender. It encodes the date of birth in the first 6 digits in the format
10
+ * YYMMDD. The following 3 digits represent a counter of people born on the same
11
+ * date, seperated by sex (odd for male and even for females respectively). The
12
+ * final 2 digits form a check number based on the 9 preceding digits.
13
+ *
14
+ * Source
15
+ * https://nl.wikipedia.org/wiki/Rijksregisternummer
16
+ * https://fr.wikipedia.org/wiki/Numéro_de_registre_national
17
+ * https://www.ibz.rrn.fgov.be/fileadmin/user_upload/nl/rr/instructies/IT-lijst/IT000_Rijksregisternummer.pdf
18
+ *
19
+ * PERSON
20
+ */
21
+
22
+ import * as exceptions from '../exceptions';
23
+ import { strings } from '../util';
24
+ import { validStructure, validChecksum } from './personIdentifierHelpers';
25
+ import { Validator, ValidateReturn } from '../types';
26
+
27
+ function clean(input: string): ReturnType<typeof strings.cleanUnicode> {
28
+ return strings.cleanUnicode(input, ' -.');
29
+ }
30
+
31
+ const impl: Validator = {
32
+ name: 'Belgian National Number',
33
+ localName: 'Numéro National',
34
+ abbreviation: 'NN, RN',
35
+ compact(input: string): string {
36
+ const [value, err] = clean(input);
37
+
38
+ if (err) {
39
+ throw err;
40
+ }
41
+
42
+ return value;
43
+ },
44
+ format(input: string): string {
45
+ const [value] = clean(input);
46
+ return value;
47
+ },
48
+ validate(input: string): ValidateReturn {
49
+ const value = impl.compact(input);
50
+
51
+ if (!strings.isdigits(value) || parseInt(value, 10) <= 0) {
52
+ return { isValid: false, error: new exceptions.InvalidFormat() };
53
+ }
54
+
55
+ if (value.length !== 11) {
56
+ return { isValid: false, error: new exceptions.InvalidLength() };
57
+ }
58
+
59
+ if (!validStructure(value)) {
60
+ return { isValid: false, error: new exceptions.InvalidFormat() };
61
+ }
62
+
63
+ if (!validChecksum(value)) {
64
+ return { isValid: false, error: new exceptions.InvalidChecksum() };
65
+ }
66
+
67
+ return {
68
+ isValid: true,
69
+ compact: value,
70
+ isIndividual: true,
71
+ isCompany: false,
72
+ };
73
+ },
74
+ };
75
+
76
+ export const { name, localName, abbreviation, validate, format, compact } =
77
+ impl;
@@ -0,0 +1,254 @@
1
+ import {
2
+ validStructure,
3
+ validChecksum,
4
+ toDateArray,
5
+ } from './personIdentifierHelpers';
6
+
7
+ describe('personIdentifierHelpers', () => {
8
+ const toDob = (string: string): string => {
9
+ const [y, m, d] = toDateArray(string).map(s => parseInt(s, 10));
10
+ return [y, m - 1, d].map(n => `${n}`.padStart(2, '0')).join('');
11
+ };
12
+
13
+ describe('validStructure', () => {
14
+ describe('default dob conversion', () => {
15
+ it('returns true for a valid 20th century date', () => {
16
+ expect(validStructure('99012599999')).toEqual(true);
17
+ });
18
+
19
+ it('returns true for a potential 21st century date', () => {
20
+ expect(validStructure('01012599999')).toEqual(true);
21
+ });
22
+
23
+ it('returns true for an unknown date of birth', () => {
24
+ expect(validStructure('01009999999')).toEqual(true);
25
+ });
26
+
27
+ it('returns false for a string that is neither an unknown date of birth or a valid date of birth', () => {
28
+ expect(validStructure('99999999999')).toEqual(false);
29
+ });
30
+ });
31
+
32
+ describe('specified dob conversion', () => {
33
+ it('returns true for a valid 20th century date', () => {
34
+ expect(validStructure('991331999999', toDob)).toEqual(true);
35
+ });
36
+
37
+ it('returns true for a potential 21st century date', () => {
38
+ expect(validStructure('011331999999', toDob)).toEqual(true);
39
+ });
40
+
41
+ it('returns true for an unknown date of birth', () => {
42
+ expect(validStructure('990199999999', toDob)).toEqual(true);
43
+ });
44
+
45
+ it('returns false for a string that is neither an unknown date of birth or a valid date of birth', () => {
46
+ expect(validStructure('99999999999', toDob)).toEqual(false);
47
+ });
48
+ });
49
+ });
50
+
51
+ describe('validChecksum', () => {
52
+ const range = Array.from({ length: 100 }, (_, n) => n);
53
+
54
+ describe('default dob conversion', () => {
55
+ describe('a date of birth valid in the 20th century only', () => {
56
+ const baseString = '990430999';
57
+ const checksum = 14;
58
+
59
+ it('returns true when the checksum is valid', () => {
60
+ const string = `${baseString}${checksum}`;
61
+ expect(validChecksum(string)).toEqual(true);
62
+ });
63
+
64
+ it('returns false when the checksum is invalid', () => {
65
+ const toCheck = range.filter(x => x !== checksum);
66
+ toCheck.forEach(cs => {
67
+ const string = `${baseString}${cs}`;
68
+ expect(validChecksum(string)).toEqual(false);
69
+ });
70
+ });
71
+ });
72
+
73
+ describe('a date of birth valid in the 21st century only', () => {
74
+ const baseString = '000229999'; // 1900 was not a leap year
75
+ const checksum = 17;
76
+
77
+ it('returns true when the checksum is valid', () => {
78
+ const string = `${baseString}${checksum}`;
79
+ expect(validChecksum(string)).toEqual(true);
80
+ });
81
+
82
+ it('returns false when the checksum is invalid', () => {
83
+ const toCheck = range.filter(x => x !== checksum);
84
+ toCheck.forEach(cs => {
85
+ const string = `${baseString}${cs}`;
86
+ expect(validChecksum(string)).toEqual(false);
87
+ });
88
+ });
89
+ });
90
+
91
+ describe('a date of birth valid in either the 20th or 21st century', () => {
92
+ const baseString = '100430999';
93
+ const twentiethCenturyChecksum = 85;
94
+ const twentyfirstCenturyChecksum = 17;
95
+
96
+ it('returns true when the checksum is valid for the 20th century', () => {
97
+ const string = `${baseString}${twentiethCenturyChecksum}`;
98
+ expect(validChecksum(string)).toEqual(true);
99
+ });
100
+
101
+ it('returns true when the checksum is valid for the 21th century', () => {
102
+ const string = `${baseString}${twentyfirstCenturyChecksum}`;
103
+ expect(validChecksum(string)).toEqual(true);
104
+ });
105
+
106
+ it('returns false when the checksum is invalid', () => {
107
+ const excludedChecksums = [
108
+ twentiethCenturyChecksum,
109
+ twentyfirstCenturyChecksum,
110
+ ];
111
+ const toCheck = range.filter(x => !excludedChecksums.includes(x));
112
+ toCheck.forEach(cs => {
113
+ const string = `${baseString}${cs}`;
114
+ expect(validChecksum(string)).toEqual(false);
115
+ });
116
+ });
117
+ });
118
+
119
+ describe('an unknown date of birth', () => {
120
+ const baseString = '100001999';
121
+ const twentiethCenturyChecksum = 54;
122
+ const twentyfirstCenturyChecksum = 83;
123
+
124
+ it('returns true when the checksum is valid for the 20th century', () => {
125
+ const string = `${baseString}${twentiethCenturyChecksum}`;
126
+ expect(validChecksum(string)).toEqual(true);
127
+ });
128
+
129
+ it('returns true when the checksum is valid for the 21th century', () => {
130
+ const string = `${baseString}${twentyfirstCenturyChecksum}`;
131
+ expect(validChecksum(string)).toEqual(true);
132
+ });
133
+
134
+ it('returns false when the checksum is invalid', () => {
135
+ const excludedChecksums = [
136
+ twentiethCenturyChecksum,
137
+ twentyfirstCenturyChecksum,
138
+ ];
139
+ const toCheck = range.filter(x => !excludedChecksums.includes(x));
140
+ toCheck.forEach(cs => {
141
+ const string = `${baseString}${cs}`;
142
+ expect(validChecksum(string)).toEqual(false);
143
+ });
144
+ });
145
+ });
146
+ });
147
+
148
+ describe('specified dob conversion', () => {
149
+ describe('a date of birth valid in the 20th century only', () => {
150
+ const baseString = '990631999';
151
+ const checksum = 95;
152
+
153
+ it('returns true when the checksum is valid', () => {
154
+ const string = `${baseString}${checksum}`;
155
+ expect(validChecksum(string, toDob)).toEqual(true);
156
+ });
157
+
158
+ it('returns false when the checksum is invalid', () => {
159
+ const toCheck = range.filter(x => x !== checksum);
160
+ toCheck.forEach(cs => {
161
+ const string = `${baseString}${cs}`;
162
+ expect(validChecksum(string, toDob)).toEqual(false);
163
+ });
164
+ });
165
+ });
166
+
167
+ describe('a date of birth valid in the 21st century only', () => {
168
+ const baseString = '000329999'; // 1900 was not a leap year
169
+ const checksum = 24;
170
+
171
+ it('returns true when the checksum is valid', () => {
172
+ const string = `${baseString}${checksum}`;
173
+ expect(validChecksum(string, toDob)).toEqual(true);
174
+ });
175
+
176
+ it('returns false when the checksum is invalid', () => {
177
+ const toCheck = range.filter(x => x !== checksum);
178
+ toCheck.forEach(cs => {
179
+ const string = `${baseString}${cs}`;
180
+ expect(validChecksum(string, toDob)).toEqual(false);
181
+ });
182
+ });
183
+ });
184
+
185
+ describe('a date of birth valid in either the 20th or 21st century', () => {
186
+ const baseString = '100430999';
187
+ const twentiethCenturyChecksum = 85;
188
+ const twentyfirstCenturyChecksum = 17;
189
+
190
+ it('returns true when the checksum is valid for the 20th century', () => {
191
+ const string = `${baseString}${twentiethCenturyChecksum}`;
192
+ expect(validChecksum(string, toDob)).toEqual(true);
193
+ });
194
+
195
+ it('returns true when the checksum is valid for the 21th century', () => {
196
+ const string = `${baseString}${twentyfirstCenturyChecksum}`;
197
+ expect(validChecksum(string, toDob)).toEqual(true);
198
+ });
199
+
200
+ it('returns false when the checksum is invalid', () => {
201
+ const excludedChecksums = [
202
+ twentiethCenturyChecksum,
203
+ twentyfirstCenturyChecksum,
204
+ ];
205
+ const toCheck = range.filter(x => !excludedChecksums.includes(x));
206
+ toCheck.forEach(cs => {
207
+ const string = `${baseString}${cs}`;
208
+ expect(validChecksum(string, toDob)).toEqual(false);
209
+ });
210
+ });
211
+ });
212
+
213
+ describe('an unknown date of birth', () => {
214
+ const baseString = '100101999';
215
+ const twentiethCenturyChecksum = 61;
216
+ const twentyfirstCenturyChecksum = 90;
217
+
218
+ it('returns true when the checksum is valid for the 20th century', () => {
219
+ const string = `${baseString}${twentiethCenturyChecksum}`;
220
+ expect(validChecksum(string, toDob)).toEqual(true);
221
+ });
222
+
223
+ it('returns true when the checksum is valid for the 21th century', () => {
224
+ const string = `${baseString}${twentyfirstCenturyChecksum}`;
225
+ expect(validChecksum(string, toDob)).toEqual(true);
226
+ });
227
+
228
+ it('returns false when the checksum is invalid', () => {
229
+ const excludedChecksums = [
230
+ twentiethCenturyChecksum,
231
+ twentyfirstCenturyChecksum,
232
+ ];
233
+ const toCheck = range.filter(x => !excludedChecksums.includes(x));
234
+ toCheck.forEach(cs => {
235
+ const string = `${baseString}${cs}`;
236
+ expect(validChecksum(string, toDob)).toEqual(false);
237
+ });
238
+ });
239
+ });
240
+ });
241
+ });
242
+
243
+ describe('toDateArray', () => {
244
+ it('works with a string of length 6', () => {
245
+ const string = '013150';
246
+ expect(toDateArray(string)).toEqual(['01', '31', '50']);
247
+ });
248
+
249
+ it('works with a string of length greater than 6', () => {
250
+ const string = '013150999';
251
+ expect(toDateArray(string)).toEqual(['01', '31', '50']);
252
+ });
253
+ });
254
+ });
@@ -0,0 +1,130 @@
1
+ import { strings, isValidDateCompactYYYYMMDD } from '../util';
2
+
3
+ function getApproximatelyNow() {
4
+ const ONE_DAY = 1000 * 60 * 60 * 24;
5
+ return new Date(Date.now() + ONE_DAY);
6
+ }
7
+
8
+ function isInPast(date: string | number): boolean {
9
+ return new Date(String(date)) <= getApproximatelyNow();
10
+ }
11
+
12
+ function getFullYears(yy: string | number): number[] {
13
+ const yval = typeof yy === 'string' ? parseInt(yy, 10) : yy;
14
+
15
+ return [1900 + yval, 2000 + yval];
16
+ }
17
+
18
+ function getFirstSix(number: string): string {
19
+ return strings.splitAt(number, 6)[0];
20
+ }
21
+
22
+ function getBaseNumber(number: string): string {
23
+ return strings.splitAt(number, 9)[0];
24
+ }
25
+
26
+ function getChecksum(number: string): number {
27
+ const checksumString = strings.splitAt(number, 9)[1];
28
+ return parseInt(checksumString, 10);
29
+ }
30
+
31
+ export function toDateArray(number: string): string[] {
32
+ const [yy, mm, dd] = strings.splitAt(number, 2, 4, 6);
33
+
34
+ return [yy, mm, dd];
35
+ }
36
+
37
+ function getValidPastDates(yymmdd: string): Array<string> {
38
+ const [yy, mm, dd] = toDateArray(yymmdd);
39
+
40
+ return getFullYears(yy)
41
+ .filter(yyyy => isValidDateCompactYYYYMMDD(`${yyyy}${mm}${dd}`))
42
+ .map(yyyy => `${yyyy}-${mm}-${dd}`)
43
+ .filter(isInPast);
44
+ }
45
+
46
+ function isUnknownDob(dob: string): boolean {
47
+ if (['000001', '002001', '004001'].includes(dob)) {
48
+ return true;
49
+ }
50
+
51
+ const [yy, mm, dd] = toDateArray(dob);
52
+
53
+ return strings.isdigits(yy) && mm === '00' && strings.isdigits(dd);
54
+ }
55
+
56
+ function toChecksumBasis(year: number, baseNumber: string): number {
57
+ return parseInt(year < 2000 ? baseNumber : `${2}${baseNumber}`, 10);
58
+ }
59
+
60
+ function isValidDob(dob: string): boolean {
61
+ return Boolean(getValidPastDates(dob).length);
62
+ }
63
+
64
+ function defaultToDob(origFirstSix: string): string {
65
+ return origFirstSix;
66
+ }
67
+
68
+ function isValidFirstSix(
69
+ firstSix: string,
70
+ toDob: typeof defaultToDob,
71
+ ): boolean {
72
+ const dob = toDob(firstSix);
73
+ return isUnknownDob(dob) || isValidDob(dob);
74
+ }
75
+
76
+ export function validStructure(
77
+ number: string,
78
+ toDob: typeof defaultToDob = defaultToDob,
79
+ ): boolean {
80
+ const firstSix = getFirstSix(number);
81
+ return isValidFirstSix(firstSix, toDob);
82
+ }
83
+
84
+ function getChecksumBasesUnknownDob(baseNumber: string): Array<number> {
85
+ const firstSix = getFirstSix(baseNumber);
86
+ const [yy] = toDateArray(firstSix);
87
+
88
+ return getFullYears(yy)
89
+ .filter(isInPast)
90
+ .map(year => toChecksumBasis(year, baseNumber));
91
+ }
92
+
93
+ function getChecksumBasesForStandardDob(
94
+ baseNumber: string,
95
+ toDob: typeof defaultToDob,
96
+ ): Array<number> {
97
+ const firstSix = getFirstSix(baseNumber);
98
+ const dob = toDob(firstSix);
99
+ const validPastDates = getValidPastDates(dob);
100
+ const extractYearFromDate = (date: string): number =>
101
+ parseInt(date.split('-')[0], 10);
102
+ const validPastYears = validPastDates.map(extractYearFromDate);
103
+ return validPastYears.map(year => toChecksumBasis(year, baseNumber));
104
+ }
105
+
106
+ function getChecksumBases(
107
+ number: string,
108
+ toDob: typeof defaultToDob,
109
+ ): Array<number> {
110
+ const firstSix = getFirstSix(number);
111
+ const dob = toDob(firstSix);
112
+ const baseNumber = getBaseNumber(number);
113
+
114
+ if (isUnknownDob(dob)) return getChecksumBasesUnknownDob(baseNumber);
115
+
116
+ return getChecksumBasesForStandardDob(baseNumber, toDob);
117
+ }
118
+
119
+ function isValidChecksumPair(checksumBasis: number, checksum: number): boolean {
120
+ return !((checksumBasis + checksum) % 97);
121
+ }
122
+
123
+ export function validChecksum(
124
+ number: string,
125
+ toDob: typeof defaultToDob = defaultToDob,
126
+ ): boolean {
127
+ const checksumBases = getChecksumBases(number, toDob);
128
+ const checksum = getChecksum(number);
129
+ return checksumBases.some(csb => isValidChecksumPair(csb, checksum));
130
+ }
@@ -0,0 +1,46 @@
1
+ import { validate, format } from './vat';
2
+ import { InvalidLength, InvalidChecksum } from '../exceptions';
3
+
4
+ describe('be/vat', () => {
5
+ it('format:403019261', () => {
6
+ const result = format('403019261');
7
+
8
+ expect(result).toEqual('0403019261');
9
+ });
10
+
11
+ it('validate:BE403019261', () => {
12
+ const result = validate('BE403019261');
13
+
14
+ expect(result.isValid && result.compact).toEqual('0403019261');
15
+ });
16
+
17
+ it('validate:(0)403019261', () => {
18
+ const result = validate('(0)403019261');
19
+
20
+ expect(result.isValid && result.compact).toEqual('0403019261');
21
+ });
22
+
23
+ it('validate:BE 428759497', () => {
24
+ const result = validate('BE 428759497');
25
+
26
+ expect(result.isValid && result.compact).toEqual('0428759497');
27
+ });
28
+
29
+ it('validate:BE 0417497106', () => {
30
+ const result = validate('BE 0417497106');
31
+
32
+ expect(result.isValid && result.compact).toEqual('0417497106');
33
+ });
34
+
35
+ it('validate:12345678', () => {
36
+ const result = validate('12345678');
37
+
38
+ expect(result.error).toBeInstanceOf(InvalidLength);
39
+ });
40
+
41
+ it('validate:BE431150351', () => {
42
+ const result = validate('BE431150351');
43
+
44
+ expect(result.error).toBeInstanceOf(InvalidChecksum);
45
+ });
46
+ });