@stll/stdnum 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (704) hide show
  1. package/dist/_checksums/luhn.js.map +1 -1
  2. package/dist/_checksums/mod1110.js +1 -1
  3. package/dist/_checksums/mod1110.js.map +1 -1
  4. package/dist/_checksums/mod112.js.map +1 -1
  5. package/dist/_checksums/mod97.js.map +1 -1
  6. package/dist/_checksums/verhoeff.js.map +1 -1
  7. package/dist/_checksums/weighted-sum.js.map +1 -1
  8. package/dist/_util/arabic.js.map +1 -1
  9. package/dist/_util/clean.js.map +1 -1
  10. package/dist/_util/date.js.map +1 -1
  11. package/dist/_util/generate.js.map +1 -1
  12. package/dist/_util/result.js.map +1 -1
  13. package/dist/_util/strings.js.map +1 -1
  14. package/dist/ad/nrt.d.ts +16 -2
  15. package/dist/ad/nrt.js +1 -14
  16. package/dist/ad/nrt.js.map +1 -1
  17. package/dist/ae/eid.d.ts +2 -2
  18. package/dist/ae/eid.js +2 -12
  19. package/dist/ae/eid.js.map +1 -1
  20. package/dist/ai/tin.d.ts +20 -2
  21. package/dist/ai/tin.js +1 -18
  22. package/dist/ai/tin.js.map +1 -1
  23. package/dist/al/nipt.d.ts +13 -2
  24. package/dist/al/nipt.js +1 -11
  25. package/dist/al/nipt.js.map +1 -1
  26. package/dist/am/tin.d.ts +16 -2
  27. package/dist/am/tin.js +1 -14
  28. package/dist/am/tin.js.map +1 -1
  29. package/dist/ar/cbu.d.ts +2 -2
  30. package/dist/ar/cbu.js +1 -9
  31. package/dist/ar/cbu.js.map +1 -1
  32. package/dist/ar/cuit.d.ts +2 -2
  33. package/dist/ar/cuit.js +1 -17
  34. package/dist/ar/cuit.js.map +1 -1
  35. package/dist/ar/dni.d.ts +11 -2
  36. package/dist/ar/dni.js +1 -9
  37. package/dist/ar/dni.js.map +1 -1
  38. package/dist/at/businessid.d.ts +10 -2
  39. package/dist/at/businessid.js +1 -8
  40. package/dist/at/businessid.js.map +1 -1
  41. package/dist/at/tin.d.ts +2 -2
  42. package/dist/at/tin.js +1 -11
  43. package/dist/at/tin.js.map +1 -1
  44. package/dist/at/uid.d.ts +2 -2
  45. package/dist/at/uid.js +2 -10
  46. package/dist/at/uid.js.map +1 -1
  47. package/dist/at/vnr.d.ts +2 -2
  48. package/dist/at/vnr.js +4 -14
  49. package/dist/at/vnr.js.map +1 -1
  50. package/dist/au/abn.d.ts +2 -2
  51. package/dist/au/abn.js +1 -10
  52. package/dist/au/abn.js.map +1 -1
  53. package/dist/au/acn.d.ts +2 -2
  54. package/dist/au/acn.js +1 -10
  55. package/dist/au/acn.js.map +1 -1
  56. package/dist/au/tfn.d.ts +2 -2
  57. package/dist/au/tfn.js +1 -10
  58. package/dist/au/tfn.js.map +1 -1
  59. package/dist/az/voen.d.ts +2 -2
  60. package/dist/az/voen.js +1 -14
  61. package/dist/az/voen.js.map +1 -1
  62. package/dist/ba/jmbg.d.ts +2 -2
  63. package/dist/ba/jmbg.js +3 -11
  64. package/dist/ba/jmbg.js.map +1 -1
  65. package/dist/bd/nid.d.ts +23 -2
  66. package/dist/bd/nid.js +1 -21
  67. package/dist/bd/nid.js.map +1 -1
  68. package/dist/be/bis.d.ts +2 -2
  69. package/dist/be/bis.js +1 -11
  70. package/dist/be/bis.js.map +1 -1
  71. package/dist/be/nn.d.ts +2 -2
  72. package/dist/be/nn.js +1 -11
  73. package/dist/be/nn.js.map +1 -1
  74. package/dist/be/vat.d.ts +2 -2
  75. package/dist/be/vat.js +1 -9
  76. package/dist/be/vat.js.map +1 -1
  77. package/dist/bg/egn.d.ts +2 -2
  78. package/dist/bg/egn.js +3 -18
  79. package/dist/bg/egn.js.map +1 -1
  80. package/dist/bg/pnf.d.ts +2 -2
  81. package/dist/bg/pnf.js +1 -8
  82. package/dist/bg/pnf.js.map +1 -1
  83. package/dist/bg/vat.d.ts +2 -2
  84. package/dist/bg/vat.js +3 -9
  85. package/dist/bg/vat.js.map +1 -1
  86. package/dist/bh/cpr.d.ts +2 -2
  87. package/dist/bh/cpr.js +1 -17
  88. package/dist/bh/cpr.js.map +1 -1
  89. package/dist/bic.d.ts +13 -2
  90. package/dist/bic.js +1 -11
  91. package/dist/bic.js.map +1 -1
  92. package/dist/br/cnpj.d.ts +2 -2
  93. package/dist/br/cnpj.js +1 -20
  94. package/dist/br/cnpj.js.map +1 -1
  95. package/dist/br/cpf.d.ts +2 -2
  96. package/dist/br/cpf.js +1 -14
  97. package/dist/br/cpf.js.map +1 -1
  98. package/dist/by/unp.d.ts +2 -2
  99. package/dist/by/unp.js +3 -14
  100. package/dist/by/unp.js.map +1 -1
  101. package/dist/bz/tin.d.ts +2 -2
  102. package/dist/bz/tin.js +1 -26
  103. package/dist/bz/tin.js.map +1 -1
  104. package/dist/ca/bn.d.ts +2 -2
  105. package/dist/ca/bn.js +2 -10
  106. package/dist/ca/bn.js.map +1 -1
  107. package/dist/ca/sin.d.ts +2 -2
  108. package/dist/ca/sin.js +2 -10
  109. package/dist/ca/sin.js.map +1 -1
  110. package/dist/ch/ssn.d.ts +2 -2
  111. package/dist/ch/ssn.js +1 -9
  112. package/dist/ch/ssn.js.map +1 -1
  113. package/dist/ch/uid.d.ts +2 -2
  114. package/dist/ch/uid.js +1 -9
  115. package/dist/ch/uid.js.map +1 -1
  116. package/dist/ch/vat.d.ts +2 -2
  117. package/dist/ch/vat.js +1 -9
  118. package/dist/ch/vat.js.map +1 -1
  119. package/dist/cl/rut.d.ts +2 -2
  120. package/dist/cl/rut.js +1 -14
  121. package/dist/cl/rut.js.map +1 -1
  122. package/dist/cn/ric.d.ts +2 -2
  123. package/dist/cn/ric.js +3 -14
  124. package/dist/cn/ric.js.map +1 -1
  125. package/dist/cn/uscc.d.ts +2 -2
  126. package/dist/cn/uscc.js +1 -10
  127. package/dist/cn/uscc.js.map +1 -1
  128. package/dist/co/nit.d.ts +2 -2
  129. package/dist/co/nit.js +2 -12
  130. package/dist/co/nit.js.map +1 -1
  131. package/dist/cr/cpf.d.ts +18 -2
  132. package/dist/cr/cpf.js +1 -16
  133. package/dist/cr/cpf.js.map +1 -1
  134. package/dist/creditcard.d.ts +2 -2
  135. package/dist/creditcard.js +5 -14
  136. package/dist/creditcard.js.map +1 -1
  137. package/dist/cu/ni.d.ts +2 -2
  138. package/dist/cu/ni.js +2 -17
  139. package/dist/cu/ni.js.map +1 -1
  140. package/dist/cy/vat.d.ts +2 -2
  141. package/dist/cy/vat.js +1 -8
  142. package/dist/cy/vat.js.map +1 -1
  143. package/dist/cz/dic.d.ts +2 -2
  144. package/dist/cz/dic.js +7 -13
  145. package/dist/cz/dic.js.map +1 -1
  146. package/dist/cz/ico.d.ts +2 -2
  147. package/dist/cz/ico.js +2 -10
  148. package/dist/cz/ico.js.map +1 -1
  149. package/dist/cz/rc.d.ts +2 -2
  150. package/dist/cz/rc.js +2 -26
  151. package/dist/cz/rc.js.map +1 -1
  152. package/dist/de/handelsreg.d.ts +19 -2
  153. package/dist/de/handelsreg.js +1 -17
  154. package/dist/de/handelsreg.js.map +1 -1
  155. package/dist/de/idnr.d.ts +2 -2
  156. package/dist/de/idnr.js +2 -12
  157. package/dist/de/idnr.js.map +1 -1
  158. package/dist/de/stnr.d.ts +17 -2
  159. package/dist/de/stnr.js +1 -15
  160. package/dist/de/stnr.js.map +1 -1
  161. package/dist/de/svnr.d.ts +2 -2
  162. package/dist/de/svnr.js +2 -11
  163. package/dist/de/svnr.js.map +1 -1
  164. package/dist/de/vat.d.ts +2 -2
  165. package/dist/de/vat.js +2 -11
  166. package/dist/de/vat.js.map +1 -1
  167. package/dist/dk/cpr.d.ts +2 -2
  168. package/dist/dk/cpr.js +2 -10
  169. package/dist/dk/cpr.js.map +1 -1
  170. package/dist/dk/cvr.d.ts +2 -2
  171. package/dist/dk/cvr.js +2 -15
  172. package/dist/dk/cvr.js.map +1 -1
  173. package/dist/dk/vat.d.ts +2 -2
  174. package/dist/dk/vat.js +3 -13
  175. package/dist/dk/vat.js.map +1 -1
  176. package/dist/do/rnc.d.ts +2 -2
  177. package/dist/do/rnc.js +2 -16
  178. package/dist/do/rnc.js.map +1 -1
  179. package/dist/ec/ruc.d.ts +2 -2
  180. package/dist/ec/ruc.js +1 -18
  181. package/dist/ec/ruc.js.map +1 -1
  182. package/dist/ee/ik.d.ts +2 -2
  183. package/dist/ee/ik.js +3 -20
  184. package/dist/ee/ik.js.map +1 -1
  185. package/dist/ee/registrikood.d.ts +2 -2
  186. package/dist/ee/registrikood.js +1 -8
  187. package/dist/ee/registrikood.js.map +1 -1
  188. package/dist/ee/vat.d.ts +2 -2
  189. package/dist/ee/vat.js +2 -10
  190. package/dist/ee/vat.js.map +1 -1
  191. package/dist/eg/tn.d.ts +11 -2
  192. package/dist/eg/tn.js +1 -9
  193. package/dist/eg/tn.js.map +1 -1
  194. package/dist/es/cif.d.ts +2 -2
  195. package/dist/es/cif.js +1 -10
  196. package/dist/es/cif.js.map +1 -1
  197. package/dist/es/dni.d.ts +2 -2
  198. package/dist/es/dni.js +1 -9
  199. package/dist/es/dni.js.map +1 -1
  200. package/dist/es/nie.d.ts +2 -2
  201. package/dist/es/nie.js +1 -9
  202. package/dist/es/nie.js.map +1 -1
  203. package/dist/es/nss.d.ts +2 -2
  204. package/dist/es/nss.js +1 -16
  205. package/dist/es/nss.js.map +1 -1
  206. package/dist/es/vat.d.ts +2 -2
  207. package/dist/es/vat.js +5 -10
  208. package/dist/es/vat.js.map +1 -1
  209. package/dist/eu/vat.d.ts +2 -2
  210. package/dist/eu/vat.js +1 -0
  211. package/dist/eu/vat.js.map +1 -1
  212. package/dist/fi/hetu.d.ts +2 -2
  213. package/dist/fi/hetu.js +2 -10
  214. package/dist/fi/hetu.js.map +1 -1
  215. package/dist/fi/vat.d.ts +2 -2
  216. package/dist/fi/vat.js +3 -10
  217. package/dist/fi/vat.js.map +1 -1
  218. package/dist/fi/ytunnus.d.ts +2 -2
  219. package/dist/fi/ytunnus.js +2 -10
  220. package/dist/fi/ytunnus.js.map +1 -1
  221. package/dist/fr/nif.d.ts +2 -2
  222. package/dist/fr/nif.js +1 -9
  223. package/dist/fr/nif.js.map +1 -1
  224. package/dist/fr/nir.d.ts +2 -2
  225. package/dist/fr/nir.js +2 -14
  226. package/dist/fr/nir.js.map +1 -1
  227. package/dist/fr/siren.d.ts +2 -2
  228. package/dist/fr/siren.js +2 -10
  229. package/dist/fr/siren.js.map +1 -1
  230. package/dist/fr/siret.d.ts +2 -2
  231. package/dist/fr/siret.js +2 -11
  232. package/dist/fr/siret.js.map +1 -1
  233. package/dist/fr/tva.d.ts +2 -2
  234. package/dist/fr/tva.js +2 -12
  235. package/dist/fr/tva.js.map +1 -1
  236. package/dist/gb/nino.d.ts +12 -2
  237. package/dist/gb/nino.js +1 -10
  238. package/dist/gb/nino.js.map +1 -1
  239. package/dist/gb/sedol.d.ts +2 -2
  240. package/dist/gb/sedol.js +1 -11
  241. package/dist/gb/sedol.js.map +1 -1
  242. package/dist/gb/utr.d.ts +2 -2
  243. package/dist/gb/utr.js +2 -10
  244. package/dist/gb/utr.js.map +1 -1
  245. package/dist/gb/vat.d.ts +2 -2
  246. package/dist/gb/vat.js +2 -11
  247. package/dist/gb/vat.js.map +1 -1
  248. package/dist/ge/pin.d.ts +14 -2
  249. package/dist/ge/pin.js +1 -12
  250. package/dist/ge/pin.js.map +1 -1
  251. package/dist/gh/tin.d.ts +2 -2
  252. package/dist/gh/tin.js +1 -15
  253. package/dist/gh/tin.js.map +1 -1
  254. package/dist/gr/amka.d.ts +2 -2
  255. package/dist/gr/amka.js +3 -11
  256. package/dist/gr/amka.js.map +1 -1
  257. package/dist/gr/vat.d.ts +2 -2
  258. package/dist/gr/vat.js +1 -10
  259. package/dist/gr/vat.js.map +1 -1
  260. package/dist/gt/nit.d.ts +2 -2
  261. package/dist/gt/nit.js +1 -12
  262. package/dist/gt/nit.js.map +1 -1
  263. package/dist/hk/hkid.d.ts +2 -2
  264. package/dist/hk/hkid.js +1 -10
  265. package/dist/hk/hkid.js.map +1 -1
  266. package/dist/hr/vat.d.ts +2 -2
  267. package/dist/hr/vat.js +2 -9
  268. package/dist/hr/vat.js.map +1 -1
  269. package/dist/hu/vat.d.ts +2 -2
  270. package/dist/hu/vat.js +3 -10
  271. package/dist/hu/vat.js.map +1 -1
  272. package/dist/iban.d.ts +2 -2
  273. package/dist/iban.js +2 -8
  274. package/dist/iban.js.map +1 -1
  275. package/dist/id/npwp.d.ts +2 -2
  276. package/dist/id/npwp.js +3 -13
  277. package/dist/id/npwp.js.map +1 -1
  278. package/dist/ie/pps.d.ts +2 -2
  279. package/dist/ie/pps.js +1 -10
  280. package/dist/ie/pps.js.map +1 -1
  281. package/dist/ie/vat.d.ts +2 -2
  282. package/dist/ie/vat.js +1 -9
  283. package/dist/ie/vat.js.map +1 -1
  284. package/dist/il/idnr.d.ts +2 -2
  285. package/dist/il/idnr.js +2 -9
  286. package/dist/il/idnr.js.map +1 -1
  287. package/dist/in/aadhaar.d.ts +2 -2
  288. package/dist/in/aadhaar.js +2 -12
  289. package/dist/in/aadhaar.js.map +1 -1
  290. package/dist/in/gstin.d.ts +2 -2
  291. package/dist/in/gstin.js +1 -10
  292. package/dist/in/gstin.js.map +1 -1
  293. package/dist/in/pan.d.ts +15 -2
  294. package/dist/in/pan.js +1 -13
  295. package/dist/in/pan.js.map +1 -1
  296. package/dist/index.d.ts +2 -2
  297. package/dist/index.js +6 -6
  298. package/dist/iq/nid.d.ts +16 -2
  299. package/dist/iq/nid.js +2 -15
  300. package/dist/iq/nid.js.map +1 -1
  301. package/dist/ir/nid.d.ts +2 -2
  302. package/dist/ir/nid.js +2 -24
  303. package/dist/ir/nid.js.map +1 -1
  304. package/dist/is/kennitala.d.ts +2 -2
  305. package/dist/is/kennitala.js +2 -13
  306. package/dist/is/kennitala.js.map +1 -1
  307. package/dist/is/vsk.d.ts +9 -2
  308. package/dist/is/vsk.js +1 -7
  309. package/dist/is/vsk.js.map +1 -1
  310. package/dist/isin.d.ts +2 -2
  311. package/dist/isin.js +2 -12
  312. package/dist/isin.js.map +1 -1
  313. package/dist/it/codicefiscale.d.ts +2 -2
  314. package/dist/it/codicefiscale.js +1 -21
  315. package/dist/it/codicefiscale.js.map +1 -1
  316. package/dist/it/iva.d.ts +2 -2
  317. package/dist/it/iva.js +2 -9
  318. package/dist/it/iva.js.map +1 -1
  319. package/dist/jp/cn.d.ts +2 -2
  320. package/dist/jp/cn.js +1 -9
  321. package/dist/jp/cn.js.map +1 -1
  322. package/dist/jp/mynumber.d.ts +2 -2
  323. package/dist/jp/mynumber.js +1 -10
  324. package/dist/jp/mynumber.js.map +1 -1
  325. package/dist/kr/brn.d.ts +11 -2
  326. package/dist/kr/brn.js +1 -9
  327. package/dist/kr/brn.js.map +1 -1
  328. package/dist/kr/rrn.d.ts +2 -2
  329. package/dist/kr/rrn.js +2 -11
  330. package/dist/kr/rrn.js.map +1 -1
  331. package/dist/kw/civil.d.ts +2 -2
  332. package/dist/kw/civil.js +2 -14
  333. package/dist/kw/civil.js.map +1 -1
  334. package/dist/kz/iin.d.ts +2 -2
  335. package/dist/kz/iin.js +3 -18
  336. package/dist/kz/iin.js.map +1 -1
  337. package/dist/lei.d.ts +2 -2
  338. package/dist/lei.js +2 -11
  339. package/dist/lei.js.map +1 -1
  340. package/dist/li/peid.d.ts +11 -2
  341. package/dist/li/peid.js +1 -9
  342. package/dist/li/peid.js.map +1 -1
  343. package/dist/lk/nic.d.ts +2 -2
  344. package/dist/lk/nic.js +2 -14
  345. package/dist/lk/nic.js.map +1 -1
  346. package/dist/lt/asmens.d.ts +2 -2
  347. package/dist/lt/asmens.js +2 -1
  348. package/dist/lt/asmens.js.map +1 -1
  349. package/dist/lt/vat.d.ts +2 -2
  350. package/dist/lt/vat.js +2 -10
  351. package/dist/lt/vat.js.map +1 -1
  352. package/dist/lu/vat.d.ts +2 -2
  353. package/dist/lu/vat.js +2 -8
  354. package/dist/lu/vat.js.map +1 -1
  355. package/dist/luhn.d.ts +2 -2
  356. package/dist/luhn.js +2 -9
  357. package/dist/luhn.js.map +1 -1
  358. package/dist/lv/vat.d.ts +2 -2
  359. package/dist/lv/vat.js +2 -28
  360. package/dist/lv/vat.js.map +1 -1
  361. package/dist/ma/ice.d.ts +2 -2
  362. package/dist/ma/ice.js +2 -11
  363. package/dist/ma/ice.js.map +1 -1
  364. package/dist/mc/tva.d.ts +2 -2
  365. package/dist/mc/tva.js +1 -0
  366. package/dist/mc/tva.js.map +1 -1
  367. package/dist/md/idno.d.ts +2 -2
  368. package/dist/md/idno.js +1 -10
  369. package/dist/md/idno.js.map +1 -1
  370. package/dist/me/pib.d.ts +2 -2
  371. package/dist/me/pib.js +2 -10
  372. package/dist/me/pib.js.map +1 -1
  373. package/dist/mk/edb.d.ts +2 -2
  374. package/dist/mk/edb.js +2 -11
  375. package/dist/mk/edb.js.map +1 -1
  376. package/dist/mt/vat.d.ts +2 -2
  377. package/dist/mt/vat.js +3 -10
  378. package/dist/mt/vat.js.map +1 -1
  379. package/dist/mu/brn.d.ts +23 -2
  380. package/dist/mu/brn.js +1 -21
  381. package/dist/mu/brn.js.map +1 -1
  382. package/dist/mx/clabe.d.ts +2 -2
  383. package/dist/mx/clabe.js +1 -14
  384. package/dist/mx/clabe.js.map +1 -1
  385. package/dist/mx/curp.d.ts +2 -2
  386. package/dist/mx/curp.js +3 -17
  387. package/dist/mx/curp.js.map +1 -1
  388. package/dist/mx/rfc.d.ts +2 -2
  389. package/dist/mx/rfc.js +3 -19
  390. package/dist/mx/rfc.js.map +1 -1
  391. package/dist/my/nric.d.ts +2 -2
  392. package/dist/my/nric.js +2 -14
  393. package/dist/my/nric.js.map +1 -1
  394. package/dist/ng/nin.d.ts +13 -2
  395. package/dist/ng/nin.js +1 -11
  396. package/dist/ng/nin.js.map +1 -1
  397. package/dist/ni/ruc.d.ts +2 -2
  398. package/dist/ni/ruc.js +1 -23
  399. package/dist/ni/ruc.js.map +1 -1
  400. package/dist/nl/bsn.d.ts +2 -2
  401. package/dist/nl/bsn.js +2 -10
  402. package/dist/nl/bsn.js.map +1 -1
  403. package/dist/nl/kvk.d.ts +9 -2
  404. package/dist/nl/kvk.js +1 -7
  405. package/dist/nl/kvk.js.map +1 -1
  406. package/dist/nl/vat.d.ts +2 -2
  407. package/dist/nl/vat.js +1 -13
  408. package/dist/nl/vat.js.map +1 -1
  409. package/dist/no/fodselsnummer.d.ts +2 -2
  410. package/dist/no/fodselsnummer.js +2 -10
  411. package/dist/no/fodselsnummer.js.map +1 -1
  412. package/dist/no/mva.d.ts +2 -2
  413. package/dist/no/mva.js +1 -8
  414. package/dist/no/mva.js.map +1 -1
  415. package/dist/no/orgnr.d.ts +2 -2
  416. package/dist/no/orgnr.js +2 -8
  417. package/dist/no/orgnr.js.map +1 -1
  418. package/dist/nz/ird.d.ts +2 -2
  419. package/dist/nz/ird.js +2 -11
  420. package/dist/nz/ird.js.map +1 -1
  421. package/dist/pa/ruc.d.ts +2 -2
  422. package/dist/pa/ruc.js +1 -18
  423. package/dist/pa/ruc.js.map +1 -1
  424. package/dist/patterns.d.ts +8 -7
  425. package/dist/patterns.js +3 -5
  426. package/dist/patterns.js.map +1 -1
  427. package/dist/pe/ruc.d.ts +2 -2
  428. package/dist/pe/ruc.js +1 -15
  429. package/dist/pe/ruc.js.map +1 -1
  430. package/dist/ph/philid.d.ts +14 -2
  431. package/dist/ph/philid.js +1 -12
  432. package/dist/ph/philid.js.map +1 -1
  433. package/dist/pk/cnic.d.ts +14 -2
  434. package/dist/pk/cnic.js +1 -12
  435. package/dist/pk/cnic.js.map +1 -1
  436. package/dist/pl/nip.d.ts +2 -2
  437. package/dist/pl/nip.js +2 -10
  438. package/dist/pl/nip.js.map +1 -1
  439. package/dist/pl/pesel.d.ts +2 -2
  440. package/dist/pl/pesel.js +3 -13
  441. package/dist/pl/pesel.js.map +1 -1
  442. package/dist/pl/regon.d.ts +2 -2
  443. package/dist/pl/regon.js +2 -11
  444. package/dist/pl/regon.js.map +1 -1
  445. package/dist/pt/cc.d.ts +2 -2
  446. package/dist/pt/cc.js +1 -9
  447. package/dist/pt/cc.js.map +1 -1
  448. package/dist/pt/vat.d.ts +2 -2
  449. package/dist/pt/vat.js +3 -11
  450. package/dist/pt/vat.js.map +1 -1
  451. package/dist/ro/cnp.d.ts +2 -2
  452. package/dist/ro/cnp.js +4 -14
  453. package/dist/ro/cnp.js.map +1 -1
  454. package/dist/ro/vat.d.ts +2 -2
  455. package/dist/ro/vat.js +13 -11
  456. package/dist/ro/vat.js.map +1 -1
  457. package/dist/rs/pib.d.ts +2 -2
  458. package/dist/rs/pib.js +1 -9
  459. package/dist/rs/pib.js.map +1 -1
  460. package/dist/ru/inn.d.ts +2 -2
  461. package/dist/ru/inn.js +1 -11
  462. package/dist/ru/inn.js.map +1 -1
  463. package/dist/se/orgnr.d.ts +2 -2
  464. package/dist/se/orgnr.js +2 -9
  465. package/dist/se/orgnr.js.map +1 -1
  466. package/dist/se/personnummer.d.ts +2 -2
  467. package/dist/se/personnummer.js +7 -15
  468. package/dist/se/personnummer.js.map +1 -1
  469. package/dist/se/vat.d.ts +2 -2
  470. package/dist/se/vat.js +3 -10
  471. package/dist/se/vat.js.map +1 -1
  472. package/dist/sg/uen.d.ts +2 -2
  473. package/dist/sg/uen.js +1 -15
  474. package/dist/sg/uen.js.map +1 -1
  475. package/dist/si/emso.d.ts +2 -2
  476. package/dist/si/emso.js +3 -18
  477. package/dist/si/emso.js.map +1 -1
  478. package/dist/si/vat.d.ts +2 -2
  479. package/dist/si/vat.js +3 -12
  480. package/dist/si/vat.js.map +1 -1
  481. package/dist/sk/dic.d.ts +2 -2
  482. package/dist/sk/dic.js +1 -0
  483. package/dist/sk/dic.js.map +1 -1
  484. package/dist/sk/ico.d.ts +2 -2
  485. package/dist/sk/ico.js +1 -0
  486. package/dist/sk/ico.js.map +1 -1
  487. package/dist/sk/rc.d.ts +2 -2
  488. package/dist/sk/rc.js +1 -0
  489. package/dist/sk/rc.js.map +1 -1
  490. package/dist/th/tin.d.ts +2 -2
  491. package/dist/th/tin.js +1 -11
  492. package/dist/th/tin.js.map +1 -1
  493. package/dist/tr/tckimlik.d.ts +2 -2
  494. package/dist/tr/tckimlik.js +1 -20
  495. package/dist/tr/tckimlik.js.map +1 -1
  496. package/dist/tr/vkn.d.ts +2 -2
  497. package/dist/tr/vkn.js +1 -20
  498. package/dist/tr/vkn.js.map +1 -1
  499. package/dist/tw/ubn.d.ts +2 -2
  500. package/dist/tw/ubn.js +1 -11
  501. package/dist/tw/ubn.js.map +1 -1
  502. package/dist/types.d.ts +26 -4
  503. package/dist/ua/edrpou.d.ts +2 -2
  504. package/dist/ua/edrpou.js +1 -11
  505. package/dist/ua/edrpou.js.map +1 -1
  506. package/dist/us/ein.d.ts +12 -2
  507. package/dist/us/ein.js +1 -10
  508. package/dist/us/ein.js.map +1 -1
  509. package/dist/us/itin.d.ts +13 -2
  510. package/dist/us/itin.js +1 -11
  511. package/dist/us/itin.js.map +1 -1
  512. package/dist/us/rtn.d.ts +2 -2
  513. package/dist/us/rtn.js +3 -18
  514. package/dist/us/rtn.js.map +1 -1
  515. package/dist/us/ssn.d.ts +13 -2
  516. package/dist/us/ssn.js +1 -11
  517. package/dist/us/ssn.js.map +1 -1
  518. package/dist/uy/rut.d.ts +2 -2
  519. package/dist/uy/rut.js +1 -14
  520. package/dist/uy/rut.js.map +1 -1
  521. package/dist/ve/rif.d.ts +2 -2
  522. package/dist/ve/rif.js +2 -15
  523. package/dist/ve/rif.js.map +1 -1
  524. package/dist/vn/mst.d.ts +2 -2
  525. package/dist/vn/mst.js +1 -12
  526. package/dist/vn/mst.js.map +1 -1
  527. package/dist/za/idnr.d.ts +2 -2
  528. package/dist/za/idnr.js +3 -16
  529. package/dist/za/idnr.js.map +1 -1
  530. package/package.json +22 -12
  531. package/src/_checksums/mod1110.ts +1 -1
  532. package/src/ad/nrt.ts +7 -3
  533. package/src/ae/eid.ts +7 -3
  534. package/src/ai/tin.ts +7 -3
  535. package/src/al/nipt.ts +7 -3
  536. package/src/am/tin.ts +7 -3
  537. package/src/ar/cbu.ts +7 -3
  538. package/src/ar/cuit.ts +7 -3
  539. package/src/ar/dni.ts +7 -3
  540. package/src/at/businessid.ts +7 -3
  541. package/src/at/tin.ts +7 -3
  542. package/src/at/uid.ts +7 -3
  543. package/src/at/vnr.ts +37 -9
  544. package/src/au/abn.ts +7 -3
  545. package/src/au/acn.ts +7 -3
  546. package/src/au/tfn.ts +7 -3
  547. package/src/az/voen.ts +7 -3
  548. package/src/ba/jmbg.ts +8 -7
  549. package/src/bd/nid.ts +7 -3
  550. package/src/be/bis.ts +8 -4
  551. package/src/be/nn.ts +7 -3
  552. package/src/be/vat.ts +7 -3
  553. package/src/bg/egn.ts +8 -7
  554. package/src/bg/pnf.ts +7 -3
  555. package/src/bg/vat.ts +8 -3
  556. package/src/bh/cpr.ts +7 -3
  557. package/src/bic.ts +7 -3
  558. package/src/br/cnpj.ts +7 -3
  559. package/src/br/cpf.ts +7 -3
  560. package/src/by/unp.ts +10 -5
  561. package/src/bz/tin.ts +7 -3
  562. package/src/ca/bn.ts +7 -3
  563. package/src/ca/sin.ts +7 -3
  564. package/src/ch/ssn.ts +7 -3
  565. package/src/ch/uid.ts +7 -3
  566. package/src/ch/vat.ts +9 -5
  567. package/src/cl/rut.ts +7 -3
  568. package/src/cn/ric.ts +8 -7
  569. package/src/cn/uscc.ts +7 -3
  570. package/src/co/nit.ts +8 -4
  571. package/src/cr/cpf.ts +7 -3
  572. package/src/creditcard.ts +10 -6
  573. package/src/cu/ni.ts +8 -7
  574. package/src/cy/vat.ts +7 -3
  575. package/src/cz/dic.ts +9 -4
  576. package/src/cz/ico.ts +7 -3
  577. package/src/cz/rc.ts +8 -7
  578. package/src/de/handelsreg.ts +7 -3
  579. package/src/de/idnr.ts +7 -3
  580. package/src/de/stnr.ts +7 -3
  581. package/src/de/svnr.ts +7 -3
  582. package/src/de/vat.ts +7 -3
  583. package/src/dk/cpr.ts +8 -7
  584. package/src/dk/cvr.ts +7 -3
  585. package/src/dk/vat.ts +8 -3
  586. package/src/do/rnc.ts +7 -3
  587. package/src/ec/ruc.ts +7 -3
  588. package/src/ee/ik.ts +8 -7
  589. package/src/ee/registrikood.ts +8 -4
  590. package/src/ee/vat.ts +7 -3
  591. package/src/eg/tn.ts +7 -3
  592. package/src/es/cif.ts +8 -4
  593. package/src/es/dni.ts +7 -3
  594. package/src/es/nie.ts +8 -4
  595. package/src/es/nss.ts +7 -3
  596. package/src/es/vat.ts +13 -5
  597. package/src/eu/vat.ts +10 -6
  598. package/src/fi/hetu.ts +8 -7
  599. package/src/fi/vat.ts +8 -3
  600. package/src/fi/ytunnus.ts +7 -3
  601. package/src/fr/nif.ts +7 -3
  602. package/src/fr/nir.ts +8 -7
  603. package/src/fr/siren.ts +7 -3
  604. package/src/fr/siret.ts +7 -3
  605. package/src/fr/tva.ts +7 -3
  606. package/src/gb/nino.ts +7 -3
  607. package/src/gb/sedol.ts +7 -3
  608. package/src/gb/utr.ts +7 -3
  609. package/src/gb/vat.ts +7 -3
  610. package/src/ge/pin.ts +7 -3
  611. package/src/gh/tin.ts +7 -3
  612. package/src/gr/amka.ts +7 -3
  613. package/src/gr/vat.ts +7 -3
  614. package/src/gt/nit.ts +7 -3
  615. package/src/hk/hkid.ts +7 -3
  616. package/src/hr/vat.ts +7 -3
  617. package/src/hu/vat.ts +8 -3
  618. package/src/iban.ts +7 -3
  619. package/src/id/npwp.ts +7 -3
  620. package/src/ie/pps.ts +7 -3
  621. package/src/ie/vat.ts +7 -3
  622. package/src/il/idnr.ts +7 -3
  623. package/src/in/aadhaar.ts +7 -3
  624. package/src/in/gstin.ts +7 -3
  625. package/src/in/pan.ts +7 -3
  626. package/src/index.ts +3 -0
  627. package/src/iq/nid.ts +7 -3
  628. package/src/ir/nid.ts +7 -3
  629. package/src/is/kennitala.ts +7 -3
  630. package/src/is/vsk.ts +7 -3
  631. package/src/isin.ts +7 -3
  632. package/src/it/codicefiscale.ts +11 -7
  633. package/src/it/iva.ts +7 -3
  634. package/src/jp/cn.ts +7 -3
  635. package/src/jp/mynumber.ts +7 -3
  636. package/src/kr/brn.ts +7 -3
  637. package/src/kr/rrn.ts +8 -7
  638. package/src/kw/civil.ts +8 -7
  639. package/src/kz/iin.ts +8 -8
  640. package/src/lei.ts +7 -3
  641. package/src/li/peid.ts +7 -3
  642. package/src/lk/nic.ts +8 -7
  643. package/src/lt/asmens.ts +8 -4
  644. package/src/lt/vat.ts +8 -3
  645. package/src/lu/vat.ts +8 -3
  646. package/src/luhn.ts +7 -3
  647. package/src/lv/vat.ts +7 -3
  648. package/src/ma/ice.ts +7 -3
  649. package/src/mc/tva.ts +9 -5
  650. package/src/md/idno.ts +7 -3
  651. package/src/me/pib.ts +7 -3
  652. package/src/mk/edb.ts +7 -3
  653. package/src/mt/vat.ts +8 -3
  654. package/src/mu/brn.ts +7 -3
  655. package/src/mx/clabe.ts +7 -3
  656. package/src/mx/curp.ts +9 -8
  657. package/src/mx/rfc.ts +8 -4
  658. package/src/my/nric.ts +8 -7
  659. package/src/ng/nin.ts +7 -3
  660. package/src/ni/ruc.ts +7 -3
  661. package/src/nl/bsn.ts +7 -3
  662. package/src/nl/kvk.ts +7 -3
  663. package/src/nl/vat.ts +7 -3
  664. package/src/no/fodselsnummer.ts +11 -7
  665. package/src/no/mva.ts +9 -5
  666. package/src/no/orgnr.ts +7 -3
  667. package/src/nz/ird.ts +8 -4
  668. package/src/pa/ruc.ts +7 -3
  669. package/src/patterns.ts +49 -18
  670. package/src/pe/ruc.ts +7 -3
  671. package/src/ph/philid.ts +7 -3
  672. package/src/pk/cnic.ts +7 -3
  673. package/src/pl/nip.ts +7 -3
  674. package/src/pl/pesel.ts +8 -7
  675. package/src/pl/regon.ts +7 -3
  676. package/src/pt/cc.ts +7 -3
  677. package/src/pt/vat.ts +8 -3
  678. package/src/ro/cnp.ts +15 -8
  679. package/src/ro/vat.ts +8 -3
  680. package/src/rs/pib.ts +7 -3
  681. package/src/ru/inn.ts +7 -3
  682. package/src/se/orgnr.ts +7 -3
  683. package/src/se/personnummer.ts +35 -33
  684. package/src/se/vat.ts +8 -3
  685. package/src/sg/uen.ts +7 -3
  686. package/src/si/emso.ts +8 -7
  687. package/src/si/vat.ts +8 -3
  688. package/src/sk/dic.ts +8 -4
  689. package/src/sk/ico.ts +3 -2
  690. package/src/sk/rc.ts +6 -2
  691. package/src/th/tin.ts +7 -3
  692. package/src/tr/tckimlik.ts +7 -3
  693. package/src/tr/vkn.ts +7 -3
  694. package/src/tw/ubn.ts +7 -3
  695. package/src/types.ts +34 -3
  696. package/src/ua/edrpou.ts +7 -3
  697. package/src/us/ein.ts +7 -3
  698. package/src/us/itin.ts +7 -3
  699. package/src/us/rtn.ts +16 -8
  700. package/src/us/ssn.ts +7 -3
  701. package/src/uy/rut.ts +7 -3
  702. package/src/ve/rif.ts +8 -6
  703. package/src/vn/mst.ts +7 -3
  704. package/src/za/idnr.ts +8 -7
@@ -1,26 +1,17 @@
1
+ import { luhnChecksum, luhnValidate } from "../_checksums/luhn.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
- import { luhnChecksum, luhnValidate } from "../_checksums/luhn.js";
5
6
  import { isdigits } from "../_util/strings.js";
6
- import { isValidDate } from "../_util/date.js";
7
7
  //#region src/se/personnummer.ts
8
8
  /**
9
- * Personnummer (Personal Identity Number).
10
- *
11
- * Swedish personal identification number. 10 digits
12
- * in compact form (YYMMDDNNNC) with a Luhn checksum
13
- * on all 10 digits.
14
- *
15
- * @see https://www.skatteverket.se/privat/folkbokforing/personnummer.4.3810a01c150939e893f18c29.html
16
- */
17
- /**
18
9
  * Match python-stdnum's compact: preserve the '-' or '+'
19
10
  * separator at position -5, and strip any others.
20
11
  */
21
12
  const compact = (value) => {
22
13
  let v = clean(value, " :");
23
- if ((v.length === 10 || v.length === 12) && v[v.length - 5] !== "-" && v[v.length - 5] !== "+") v = `${v.slice(0, -4)}-${v.slice(-4)}`;
14
+ if ((v.length === 10 || v.length === 12) && v.at(-5) !== "-" && v.at(-5) !== "+") v = `${v.slice(0, -4)}-${v.slice(-4)}`;
24
15
  return `${v.slice(0, -5).replace(/-/g, "").replace(/\+/g, "")}${v.slice(-5)}`;
25
16
  };
26
17
  /**
@@ -40,7 +31,7 @@ const getBirthDate = (v) => {
40
31
  let century = Math.floor(currentYear / 100);
41
32
  const yy = Number(v.slice(0, 2));
42
33
  if (yy > currentYear % 100) century -= 1;
43
- if (v[v.length - 5] === "+") century -= 1;
34
+ if (v.at(-5) === "+") century -= 1;
44
35
  year = century * 100 + yy;
45
36
  month = Number(v.slice(2, 4));
46
37
  day = Number(v.slice(4, 6));
@@ -56,7 +47,7 @@ const validate = (value) => {
56
47
  const v = compact(value);
57
48
  if (v.length !== 11 && v.length !== 13) return err("INVALID_LENGTH", "Personnummer must be 10 or 12 digits");
58
49
  const digits = v.slice(0, -5) + v.slice(-4);
59
- const sep = v[v.length - 5];
50
+ const sep = v.at(-5);
60
51
  if (sep !== "-" && sep !== "+" || !isdigits(digits)) return err("INVALID_FORMAT", "Personnummer has invalid format");
61
52
  if (getBirthDate(v) === null) return err("INVALID_COMPONENT", "Personnummer contains an invalid date");
62
53
  if (!luhnValidate(digits.slice(-10))) return err("INVALID_CHECKSUM", "Personnummer Luhn check does not match");
@@ -76,7 +67,7 @@ const parse = (value) => {
76
67
  const v = result.compact;
77
68
  const birthDate = getBirthDate(v);
78
69
  if (birthDate === null) return null;
79
- const genderDigit = Number(v[v.length - 2]);
70
+ const genderDigit = Number(v.at(-2));
80
71
  return {
81
72
  birthDate: new Date(birthDate.year, birthDate.month - 1, birthDate.day),
82
73
  gender: genderDigit % 2 === 0 ? "female" : "male"
@@ -107,6 +98,7 @@ const personnummer = {
107
98
  "personal identity number"
108
99
  ],
109
100
  candidatePattern: "\\d{6,8}-\\d{4}",
101
+ scope: "country",
110
102
  country: "SE",
111
103
  entityType: "person",
112
104
  sourceUrl: "https://www.skatteverket.se/privat/folkbokforing/personnummer.4.3810a01c150939e893f18c29.html",
@@ -1 +1 @@
1
- {"version":3,"file":"personnummer.js","names":[],"sources":["../../src/se/personnummer.ts"],"sourcesContent":["/**\n * Personnummer (Personal Identity Number).\n *\n * Swedish personal identification number. 10 digits\n * in compact form (YYMMDDNNNC) with a Luhn checksum\n * on all 10 digits.\n *\n * @see https://www.skatteverket.se/privat/folkbokforing/personnummer.4.3810a01c150939e893f18c29.html\n */\n\nimport {\n luhnValidate,\n luhnChecksum,\n} from \"#checksums/luhn\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n Validator,\n} from \"../types\";\n\n/**\n * Match python-stdnum's compact: preserve the '-' or '+'\n * separator at position -5, and strip any others.\n */\nconst compact = (value: string): string => {\n let v = clean(value, \" :\");\n if (\n (v.length === 10 || v.length === 12) &&\n v[v.length - 5] !== \"-\" &&\n v[v.length - 5] !== \"+\"\n ) {\n v = `${v.slice(0, -4)}-${v.slice(-4)}`;\n }\n const prefix = v\n .slice(0, -5)\n .replace(/-/g, \"\")\n .replace(/\\+/g, \"\");\n return `${prefix}${v.slice(-5)}`;\n};\n\n/**\n * Extract the birth date from the compacted number.\n * Matches python-stdnum's get_birth_date.\n */\nconst getBirthDate = (\n v: string,\n): { year: number; month: number; day: number } | null => {\n let year: number;\n let month: number;\n let day: number;\n\n if (v.length === 13) {\n year = Number(v.slice(0, 4));\n month = Number(v.slice(4, 6));\n day = Number(v.slice(6, 8));\n } else {\n const currentYear = new Date().getFullYear();\n let century = Math.floor(currentYear / 100);\n const yy = Number(v.slice(0, 2));\n if (yy > currentYear % 100) century -= 1;\n if (v[v.length - 5] === \"+\") century -= 1;\n year = century * 100 + yy;\n month = Number(v.slice(2, 4));\n day = Number(v.slice(4, 6));\n }\n\n if (!isValidDate(year, month, day)) return null;\n return { year, month, day };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11 && v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"Personnummer must be 10 or 12 digits\",\n );\n }\n\n const digits = v.slice(0, -5) + v.slice(-4);\n const sep = v[v.length - 5];\n if ((sep !== \"-\" && sep !== \"+\") || !isdigits(digits)) {\n return err(\n \"INVALID_FORMAT\",\n \"Personnummer has invalid format\",\n );\n }\n\n if (getBirthDate(v) === null) {\n return err(\n \"INVALID_COMPONENT\",\n \"Personnummer contains an invalid date\",\n );\n }\n\n if (!luhnValidate(digits.slice(-10))) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Personnummer Luhn check does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a Personnummer.\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 birthDate = getBirthDate(v);\n if (birthDate === null) return null;\n\n const genderDigit = Number(v[v.length - 2]);\n\n return {\n birthDate: new Date(\n birthDate.year,\n birthDate.month - 1,\n birthDate.day,\n ),\n gender: genderDigit % 2 === 0 ? \"female\" : \"male\",\n };\n};\n\n/** Generate a random valid Swedish personnummer. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(50, 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 cs = luhnChecksum(payload + \"0\");\n const c = payload + String((10 - cs) % 10);\n const result = validate(c);\n if (result.valid) return result.compact;\n }\n};\n\n/** Swedish Personal Identity Number. */\nconst personnummer: Validator<ParsedPersonId> = {\n name: \"Swedish Personal ID\",\n localName: \"Personnummer\",\n abbreviation: \"PN\",\n aliases: [\n \"personnummer\",\n \"personnr\",\n \"pers.nr\",\n \"personal identity number\",\n ] as const,\n candidatePattern: \"\\\\d{6,8}-\\\\d{4}\",\n country: \"SE\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.skatteverket.se/privat/folkbokforing/personnummer.4.3810a01c150939e893f18c29.html\",\n examples: [\"880320-0016\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default personnummer;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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"}
1
+ {"version":3,"file":"personnummer.js","names":[],"sources":["../../src/se/personnummer.ts"],"sourcesContent":["/**\n * Personnummer (Personal Identity Number).\n *\n * Swedish personal identification number. 10 digits\n * in compact form (YYMMDDNNNC) with a Luhn checksum\n * on all 10 digits.\n *\n * @see https://www.skatteverket.se/privat/folkbokforing/personnummer.4.3810a01c150939e893f18c29.html\n */\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport {\n luhnValidate,\n luhnChecksum,\n} from \"#checksums/luhn\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/**\n * Match python-stdnum's compact: preserve the '-' or '+'\n * separator at position -5, and strip any others.\n */\nconst compact = (value: string): string => {\n let v = clean(value, \" :\");\n if (\n (v.length === 10 || v.length === 12) &&\n v.at(-5) !== \"-\" &&\n v.at(-5) !== \"+\"\n ) {\n v = `${v.slice(0, -4)}-${v.slice(-4)}`;\n }\n const prefix = v\n .slice(0, -5)\n .replace(/-/g, \"\")\n .replace(/\\+/g, \"\");\n return `${prefix}${v.slice(-5)}`;\n};\n\n/**\n * Extract the birth date from the compacted number.\n * Matches python-stdnum's get_birth_date.\n */\nconst getBirthDate = (\n v: string,\n): { year: number; month: number; day: number } | null => {\n let year: number;\n let month: number;\n let day: number;\n\n if (v.length === 13) {\n year = Number(v.slice(0, 4));\n month = Number(v.slice(4, 6));\n day = Number(v.slice(6, 8));\n } else {\n const currentYear = new Date().getFullYear();\n let century = Math.floor(currentYear / 100);\n const yy = Number(v.slice(0, 2));\n if (yy > currentYear % 100) century -= 1;\n if (v.at(-5) === \"+\") century -= 1;\n year = century * 100 + yy;\n month = Number(v.slice(2, 4));\n day = Number(v.slice(4, 6));\n }\n\n if (!isValidDate(year, month, day)) return null;\n return { year, month, day };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11 && v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"Personnummer must be 10 or 12 digits\",\n );\n }\n\n const digits = v.slice(0, -5) + v.slice(-4);\n const sep = v.at(-5);\n if ((sep !== \"-\" && sep !== \"+\") || !isdigits(digits)) {\n return err(\n \"INVALID_FORMAT\",\n \"Personnummer has invalid format\",\n );\n }\n\n if (getBirthDate(v) === null) {\n return err(\n \"INVALID_COMPONENT\",\n \"Personnummer contains an invalid date\",\n );\n }\n\n if (!luhnValidate(digits.slice(-10))) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Personnummer Luhn check does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a Personnummer.\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 birthDate = getBirthDate(v);\n if (birthDate === null) return null;\n\n const genderDigit = Number(v.at(-2));\n\n return {\n birthDate: new Date(\n birthDate.year,\n birthDate.month - 1,\n birthDate.day,\n ),\n gender: genderDigit % 2 === 0 ? \"female\" : \"male\",\n };\n};\n\n/** Generate a random valid Swedish personnummer. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(50, 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 cs = luhnChecksum(payload + \"0\");\n const c = payload + String((10 - cs) % 10);\n const result = validate(c);\n if (result.valid) return result.compact;\n }\n};\n\n/** Swedish Personal Identity Number. */\nconst personnummer: CountryValidator<\"SE\", ParsedPersonId> =\n {\n name: \"Swedish Personal ID\",\n localName: \"Personnummer\",\n abbreviation: \"PN\",\n aliases: [\n \"personnummer\",\n \"personnr\",\n \"pers.nr\",\n \"personal identity number\",\n ] as const,\n candidatePattern: \"\\\\d{6,8}-\\\\d{4}\",\n scope: \"country\",\n country: \"SE\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.skatteverket.se/privat/folkbokforing/personnummer.4.3810a01c150939e893f18c29.html\",\n examples: [\"880320-0016\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n };\n\nexport default personnummer;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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"}
package/dist/se/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/se/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 Swedish VAT number. */
8
8
  declare const generate: () => string;
9
9
  /** Swedish VAT Number. */
10
- declare const vat: Validator;
10
+ declare const vat: CountryValidator<"SE">;
11
11
  //#endregion
12
12
  export { compact, vat as default, format, generate, validate };
13
13
  //# sourceMappingURL=vat.d.ts.map
package/dist/se/vat.js CHANGED
@@ -1,18 +1,9 @@
1
+ import { luhnChecksum, luhnValidate } from "../_checksums/luhn.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
- import { luhnChecksum, luhnValidate } from "../_checksums/luhn.js";
5
5
  import { isdigits } from "../_util/strings.js";
6
6
  //#region src/se/vat.ts
7
- /**
8
- * Momsnr. (Swedish VAT number).
9
- *
10
- * 12 digits, last 2 must be "01".
11
- * Luhn check on first 10 digits.
12
- *
13
- * @see https://www.vatify.eu/sweden-vat-number.html
14
- * @see https://www.skatteverket.se/
15
- */
16
7
  const compact = (value) => {
17
8
  let v = clean(value, " -/.");
18
9
  if (v.startsWith("SE") || v.startsWith("se")) v = v.slice(2);
@@ -48,9 +39,11 @@ const vat = {
48
39
  "SE VAT"
49
40
  ],
50
41
  candidatePattern: "SE\\s?\\d{10}01",
42
+ scope: "country",
51
43
  country: "SE",
52
44
  entityType: "company",
53
45
  sourceUrl: "https://www.skatteverket.se/",
46
+ lengths: [12],
54
47
  examples: ["556188840401"],
55
48
  compact,
56
49
  format,
@@ -1 +1 @@
1
- {"version":3,"file":"vat.js","names":[],"sources":["../../src/se/vat.ts"],"sourcesContent":["/**\n * Momsnr. (Swedish VAT number).\n *\n * 12 digits, last 2 must be \"01\".\n * Luhn check on first 10 digits.\n *\n * @see https://www.vatify.eu/sweden-vat-number.html\n * @see https://www.skatteverket.se/\n */\n\nimport {\n luhnValidate,\n luhnChecksum,\n} from \"#checksums/luhn\";\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(\"SE\") || v.startsWith(\"se\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Swedish VAT number must be 12 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Swedish VAT number must contain only digits\",\n );\n }\n if (v.slice(10, 12) !== \"01\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Swedish VAT number must end with 01\",\n );\n }\n if (!luhnValidate(v.slice(0, 10))) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Swedish VAT number Luhn check failed\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `SE${compact(value)}`;\n\n/** Generate a random valid Swedish VAT number. */\nconst generate = (): string => {\n const p = randomDigits(9);\n const cs = luhnChecksum(p + \"0\");\n return p + String((10 - cs) % 10) + \"01\";\n};\n\n/** Swedish VAT Number. */\nconst vat: Validator = {\n name: \"Swedish VAT Number\",\n localName: \"Momsregistreringsnummer\",\n abbreviation: \"Momsnr.\",\n aliases: [\n \"Momsnr.\",\n \"Momsregistreringsnummer\",\n \"Swedish VAT Number\",\n \"SE VAT\",\n ] as const,\n candidatePattern: \"SE\\\\s?\\\\d{10}01\",\n country: \"SE\",\n entityType: \"company\",\n sourceUrl: \"https://www.skatteverket.se/\",\n examples: [\"556188840401\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,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,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,uCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,8CACD;AAEH,KAAI,EAAE,MAAM,IAAI,GAAG,KAAK,KACtB,QAAO,IACL,qBACA,sCACD;AAEH,KAAI,CAAC,aAAa,EAAE,MAAM,GAAG,GAAG,CAAC,CAC/B,QAAO,IACL,oBACA,uCACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UACd,KAAK,QAAQ,MAAM;;AAGrB,MAAM,iBAAyB;CAC7B,MAAM,IAAI,aAAa,EAAE;CACzB,MAAM,KAAK,aAAa,IAAI,IAAI;AAChC,QAAO,IAAI,QAAQ,KAAK,MAAM,GAAG,GAAG;;;AAItC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACA;EACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,eAAe;CAC1B;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"vat.js","names":[],"sources":["../../src/se/vat.ts"],"sourcesContent":["/**\n * Momsnr. (Swedish VAT number).\n *\n * 12 digits, last 2 must be \"01\".\n * Luhn check on first 10 digits.\n *\n * @see https://www.vatify.eu/sweden-vat-number.html\n * @see https://www.skatteverket.se/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport {\n luhnValidate,\n luhnChecksum,\n} from \"#checksums/luhn\";\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(\"SE\") || v.startsWith(\"se\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Swedish VAT number must be 12 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Swedish VAT number must contain only digits\",\n );\n }\n if (v.slice(10, 12) !== \"01\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Swedish VAT number must end with 01\",\n );\n }\n if (!luhnValidate(v.slice(0, 10))) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Swedish VAT number Luhn check failed\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `SE${compact(value)}`;\n\n/** Generate a random valid Swedish VAT number. */\nconst generate = (): string => {\n const p = randomDigits(9);\n const cs = luhnChecksum(p + \"0\");\n return p + String((10 - cs) % 10) + \"01\";\n};\n\n/** Swedish VAT Number. */\nconst vat: CountryValidator<\"SE\"> = {\n name: \"Swedish VAT Number\",\n localName: \"Momsregistreringsnummer\",\n abbreviation: \"Momsnr.\",\n aliases: [\n \"Momsnr.\",\n \"Momsregistreringsnummer\",\n \"Swedish VAT Number\",\n \"SE VAT\",\n ] as const,\n candidatePattern: \"SE\\\\s?\\\\d{10}01\",\n scope: \"country\",\n country: \"SE\",\n entityType: \"company\",\n sourceUrl: \"https://www.skatteverket.se/\",\n lengths: [12] as const,\n examples: [\"556188840401\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAwBA,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,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,sCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,6CACF;CAEF,IAAI,EAAE,MAAM,IAAI,EAAE,MAAM,MACtB,OAAO,IACL,qBACA,qCACF;CAEF,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,EAAE,CAAC,GAC9B,OAAO,IACL,oBACA,sCACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,KAAK,QAAQ,KAAK;;AAGpB,MAAM,iBAAyB;CAC7B,MAAM,IAAI,aAAa,CAAC;CACxB,MAAM,KAAK,aAAa,IAAI,GAAG;CAC/B,OAAO,IAAI,QAAQ,KAAK,MAAM,EAAE,IAAI;AACtC;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,cAAc;CACzB;CACA;CACA;CACA;AACF"}
package/dist/sg/uen.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/sg/uen.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 Singapore UEN (business format). */
8
8
  declare const generate: () => string;
9
9
  /** Singapore Unique Entity Number. */
10
- declare const uen: Validator;
10
+ declare const uen: CountryValidator<"SG">;
11
11
  //#endregion
12
12
  export { compact, uen as default, format, generate, validate };
13
13
  //# sourceMappingURL=uen.d.ts.map
package/dist/sg/uen.js CHANGED
@@ -3,21 +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/sg/uen.ts
6
- /**
7
- * UEN (Singapore Unique Entity Number).
8
- *
9
- * 9 or 10 characters identifying businesses and
10
- * entities registered in Singapore. Three formats:
11
- *
12
- * - Business (ROB): 8 digits + 1 check letter
13
- * - Local company (ROC): 4-digit year + 5 digits
14
- * + 1 check letter
15
- * - Other entities: R/S/T + 2-digit year + 2-letter
16
- * entity type + 4 digits + 1 check letter
17
- *
18
- * @see https://www.uen.gov.sg/
19
- * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Singapore-TIN.pdf
20
- */
21
6
  /** Check letter alphabet for "Other" format. */
22
7
  const OTHER_ALPHA = "ABCDEFGHJKLMNPQRSTUVWX0123456789";
23
8
  const ENTITY_TYPES = new Set([
@@ -177,6 +162,7 @@ const uen = {
177
162
  abbreviation: "UEN",
178
163
  aliases: ["UEN", "Unique Entity Number"],
179
164
  candidatePattern: "[\\dSTR]\\d{7}[A-Z]",
165
+ scope: "country",
180
166
  country: "SG",
181
167
  entityType: "company",
182
168
  description: "9 or 10-character business identifier issued by ACRA",
@@ -1 +1 @@
1
- {"version":3,"file":"uen.js","names":[],"sources":["../../src/sg/uen.ts"],"sourcesContent":["/**\n * UEN (Singapore Unique Entity Number).\n *\n * 9 or 10 characters identifying businesses and\n * entities registered in Singapore. Three formats:\n *\n * - Business (ROB): 8 digits + 1 check letter\n * - Local company (ROC): 4-digit year + 5 digits\n * + 1 check letter\n * - Other entities: R/S/T + 2-digit year + 2-letter\n * entity type + 4 digits + 1 check letter\n *\n * @see https://www.uen.gov.sg/\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Singapore-TIN.pdf\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport type { ValidateResult, Validator } from \"../types\";\n\n/** Check letter alphabet for \"Other\" format. */\nconst OTHER_ALPHA = \"ABCDEFGHJKLMNPQRSTUVWX0123456789\";\n\nconst ENTITY_TYPES = new Set([\n \"CC\",\n \"CD\",\n \"CH\",\n \"CL\",\n \"CM\",\n \"CP\",\n \"CS\",\n \"CX\",\n \"DP\",\n \"FB\",\n \"FC\",\n \"FM\",\n \"FN\",\n \"GA\",\n \"GB\",\n \"GS\",\n \"HS\",\n \"LL\",\n \"LP\",\n \"MB\",\n \"MC\",\n \"MD\",\n \"MH\",\n \"MM\",\n \"MQ\",\n \"NB\",\n \"NR\",\n \"PA\",\n \"PB\",\n \"PF\",\n \"RF\",\n \"RP\",\n \"SM\",\n \"SS\",\n \"TC\",\n \"TU\",\n \"VH\",\n \"XL\",\n]);\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\n/**\n * Validate Business (ROB) UEN (9 chars):\n * 8 digits + 1 check letter.\n */\nconst BUSINESS_WEIGHTS = [10, 4, 9, 3, 8, 2, 7, 1] as const;\nconst BUSINESS_CHECK_ALPHA = \"XMKECAWLJDB\";\n\nconst validateBusiness = (v: string): ValidateResult => {\n if (!isdigits(v.slice(0, 8))) {\n return err(\n \"INVALID_FORMAT\",\n \"Business UEN must start with 8 digits\",\n );\n }\n // SAFETY: caller routes to this only when\n // v.length === 9.\n // eslint-disable-next-line no-non-null-assertion\n if (!/^[A-Z]$/.test(v[8]!)) {\n return err(\n \"INVALID_FORMAT\",\n \"Business UEN must end with a letter\",\n );\n }\n\n let sum = 0;\n for (const [i, weight] of BUSINESS_WEIGHTS.entries()) {\n sum += Number(v[i]) * weight;\n }\n const expected = BUSINESS_CHECK_ALPHA[sum % 11];\n if (v[8] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UEN check letter does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\n/**\n * Validate Local Company (ROC) UEN (10 chars):\n * 9 digits (year prefix) + 1 check letter.\n */\nconst LOCAL_WEIGHTS = [10, 8, 6, 4, 9, 7, 5, 3, 1] as const;\nconst LOCAL_CHECK_ALPHA = \"ZKCMDNERGWH\";\n\nconst validateLocalCompany = (\n v: string,\n): ValidateResult => {\n if (!isdigits(v.slice(0, 9))) {\n return err(\n \"INVALID_FORMAT\",\n \"Company UEN must have 9 digits\",\n );\n }\n // SAFETY: caller routes to this only when\n // v.length === 10.\n // eslint-disable-next-line no-non-null-assertion\n if (!/^[A-Z]$/.test(v[9]!)) {\n return err(\n \"INVALID_FORMAT\",\n \"Company UEN must end with a letter\",\n );\n }\n\n let sum = 0;\n for (const [i, weight] of LOCAL_WEIGHTS.entries()) {\n sum += Number(v[i]) * weight;\n }\n const expected = LOCAL_CHECK_ALPHA[sum % 11];\n if (v[9] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UEN check letter does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\n/**\n * Validate Other entity UEN (10 chars):\n * R/S/T + 2 digits + 2-letter type + 4 digits\n * + 1 check letter.\n */\nconst OTHER_WEIGHTS = [4, 3, 5, 3, 10, 2, 2, 5, 7] as const;\n\nconst validateOther = (v: string): ValidateResult => {\n // SAFETY: caller routes to this only when\n // v.length === 10.\n // eslint-disable-next-line no-non-null-assertion\n const prefix = v[0]!;\n if (prefix !== \"R\" && prefix !== \"S\" && prefix !== \"T\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Other UEN must start with R, S, or T\",\n );\n }\n if (!isdigits(v.slice(1, 3))) {\n return err(\n \"INVALID_FORMAT\",\n \"Other UEN positions 2-3 must be digits\",\n );\n }\n const entityType = v.slice(3, 5);\n if (!ENTITY_TYPES.has(entityType)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Unknown entity type: \" + entityType,\n );\n }\n if (!isdigits(v.slice(5, 9))) {\n return err(\n \"INVALID_FORMAT\",\n \"Other UEN positions 6-9 must be digits\",\n );\n }\n\n let sum = 0;\n for (const [i, weight] of OTHER_WEIGHTS.entries()) {\n const ch = v[i];\n if (ch === undefined) continue;\n const idx = OTHER_ALPHA.indexOf(ch);\n if (idx === -1) {\n return err(\n \"INVALID_FORMAT\",\n `Unexpected character at position ${i + 1}: ${ch}`,\n );\n }\n sum += idx * weight;\n }\n const expected =\n OTHER_ALPHA[(((sum - 5) % 11) + 11) % 11];\n if (v[9] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UEN check letter does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 9 && v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"UEN must be 9 or 10 characters\",\n );\n }\n\n if (!/^[A-Z0-9]+$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UEN must contain only digits and letters\",\n );\n }\n\n // 9 chars: business (ROB)\n if (v.length === 9) {\n return validateBusiness(v);\n }\n\n // 10 chars: first char digit => local company,\n // otherwise \"other\" entity\n // SAFETY: v.length === 10 here.\n // eslint-disable-next-line no-non-null-assertion\n if (isdigits(v[0]!)) {\n return validateLocalCompany(v);\n }\n return validateOther(v);\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Singapore UEN (business format). */\nconst generate = (): string => {\n const body = randomDigits(8);\n let sum = 0;\n for (const [i, weight] of BUSINESS_WEIGHTS.entries()) {\n sum += Number(body[i]) * weight;\n }\n // SAFETY: sum % 11 is in 0..10 and BUSINESS_CHECK_ALPHA\n // has 11 characters.\n // eslint-disable-next-line no-non-null-assertion\n const check = BUSINESS_CHECK_ALPHA[sum % 11]!;\n return body + check;\n};\n\n/** Singapore Unique Entity Number. */\nconst uen: Validator = {\n name: \"Singapore Unique Entity Number\",\n localName: \"Unique Entity Number\",\n abbreviation: \"UEN\",\n aliases: [\"UEN\", \"Unique Entity Number\"] as const,\n candidatePattern: \"[\\\\dSTR]\\\\d{7}[A-Z]\",\n country: \"SG\",\n entityType: \"company\",\n description:\n \"9 or 10-character business identifier issued by ACRA\",\n sourceUrl: \"https://www.uen.gov.sg/\",\n lengths: [9, 10] as const,\n examples: [\n \"00192200M\",\n \"197401143C\",\n \"S16FC0121D\",\n ] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default uen;\nexport { compact, format, validate, generate };\n"],"mappings":"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"}
1
+ {"version":3,"file":"uen.js","names":[],"sources":["../../src/sg/uen.ts"],"sourcesContent":["/**\n * UEN (Singapore Unique Entity Number).\n *\n * 9 or 10 characters identifying businesses and\n * entities registered in Singapore. Three formats:\n *\n * - Business (ROB): 8 digits + 1 check letter\n * - Local company (ROC): 4-digit year + 5 digits\n * + 1 check letter\n * - Other entities: R/S/T + 2-digit year + 2-letter\n * entity type + 4 digits + 1 check letter\n *\n * @see https://www.uen.gov.sg/\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Singapore-TIN.pdf\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/** Check letter alphabet for \"Other\" format. */\nconst OTHER_ALPHA = \"ABCDEFGHJKLMNPQRSTUVWX0123456789\";\n\nconst ENTITY_TYPES = new Set([\n \"CC\",\n \"CD\",\n \"CH\",\n \"CL\",\n \"CM\",\n \"CP\",\n \"CS\",\n \"CX\",\n \"DP\",\n \"FB\",\n \"FC\",\n \"FM\",\n \"FN\",\n \"GA\",\n \"GB\",\n \"GS\",\n \"HS\",\n \"LL\",\n \"LP\",\n \"MB\",\n \"MC\",\n \"MD\",\n \"MH\",\n \"MM\",\n \"MQ\",\n \"NB\",\n \"NR\",\n \"PA\",\n \"PB\",\n \"PF\",\n \"RF\",\n \"RP\",\n \"SM\",\n \"SS\",\n \"TC\",\n \"TU\",\n \"VH\",\n \"XL\",\n]);\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\n/**\n * Validate Business (ROB) UEN (9 chars):\n * 8 digits + 1 check letter.\n */\nconst BUSINESS_WEIGHTS = [10, 4, 9, 3, 8, 2, 7, 1] as const;\nconst BUSINESS_CHECK_ALPHA = \"XMKECAWLJDB\";\n\nconst validateBusiness = (v: string): ValidateResult => {\n if (!isdigits(v.slice(0, 8))) {\n return err(\n \"INVALID_FORMAT\",\n \"Business UEN must start with 8 digits\",\n );\n }\n // SAFETY: caller routes to this only when\n // v.length === 9.\n // eslint-disable-next-line no-non-null-assertion\n if (!/^[A-Z]$/.test(v[8]!)) {\n return err(\n \"INVALID_FORMAT\",\n \"Business UEN must end with a letter\",\n );\n }\n\n let sum = 0;\n for (const [i, weight] of BUSINESS_WEIGHTS.entries()) {\n sum += Number(v[i]) * weight;\n }\n const expected = BUSINESS_CHECK_ALPHA[sum % 11];\n if (v[8] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UEN check letter does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\n/**\n * Validate Local Company (ROC) UEN (10 chars):\n * 9 digits (year prefix) + 1 check letter.\n */\nconst LOCAL_WEIGHTS = [10, 8, 6, 4, 9, 7, 5, 3, 1] as const;\nconst LOCAL_CHECK_ALPHA = \"ZKCMDNERGWH\";\n\nconst validateLocalCompany = (\n v: string,\n): ValidateResult => {\n if (!isdigits(v.slice(0, 9))) {\n return err(\n \"INVALID_FORMAT\",\n \"Company UEN must have 9 digits\",\n );\n }\n // SAFETY: caller routes to this only when\n // v.length === 10.\n // eslint-disable-next-line no-non-null-assertion\n if (!/^[A-Z]$/.test(v[9]!)) {\n return err(\n \"INVALID_FORMAT\",\n \"Company UEN must end with a letter\",\n );\n }\n\n let sum = 0;\n for (const [i, weight] of LOCAL_WEIGHTS.entries()) {\n sum += Number(v[i]) * weight;\n }\n const expected = LOCAL_CHECK_ALPHA[sum % 11];\n if (v[9] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UEN check letter does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\n/**\n * Validate Other entity UEN (10 chars):\n * R/S/T + 2 digits + 2-letter type + 4 digits\n * + 1 check letter.\n */\nconst OTHER_WEIGHTS = [4, 3, 5, 3, 10, 2, 2, 5, 7] as const;\n\nconst validateOther = (v: string): ValidateResult => {\n // SAFETY: caller routes to this only when\n // v.length === 10.\n // eslint-disable-next-line no-non-null-assertion\n const prefix = v[0]!;\n if (prefix !== \"R\" && prefix !== \"S\" && prefix !== \"T\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Other UEN must start with R, S, or T\",\n );\n }\n if (!isdigits(v.slice(1, 3))) {\n return err(\n \"INVALID_FORMAT\",\n \"Other UEN positions 2-3 must be digits\",\n );\n }\n const entityType = v.slice(3, 5);\n if (!ENTITY_TYPES.has(entityType)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Unknown entity type: \" + entityType,\n );\n }\n if (!isdigits(v.slice(5, 9))) {\n return err(\n \"INVALID_FORMAT\",\n \"Other UEN positions 6-9 must be digits\",\n );\n }\n\n let sum = 0;\n for (const [i, weight] of OTHER_WEIGHTS.entries()) {\n const ch = v[i];\n if (ch === undefined) continue;\n const idx = OTHER_ALPHA.indexOf(ch);\n if (idx === -1) {\n return err(\n \"INVALID_FORMAT\",\n `Unexpected character at position ${i + 1}: ${ch}`,\n );\n }\n sum += idx * weight;\n }\n const expected =\n OTHER_ALPHA[(((sum - 5) % 11) + 11) % 11];\n if (v[9] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UEN check letter does not match\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 9 && v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"UEN must be 9 or 10 characters\",\n );\n }\n\n if (!/^[A-Z0-9]+$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UEN must contain only digits and letters\",\n );\n }\n\n // 9 chars: business (ROB)\n if (v.length === 9) {\n return validateBusiness(v);\n }\n\n // 10 chars: first char digit => local company,\n // otherwise \"other\" entity\n // SAFETY: v.length === 10 here.\n // eslint-disable-next-line no-non-null-assertion\n if (isdigits(v[0]!)) {\n return validateLocalCompany(v);\n }\n return validateOther(v);\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Singapore UEN (business format). */\nconst generate = (): string => {\n const body = randomDigits(8);\n let sum = 0;\n for (const [i, weight] of BUSINESS_WEIGHTS.entries()) {\n sum += Number(body[i]) * weight;\n }\n // SAFETY: sum % 11 is in 0..10 and BUSINESS_CHECK_ALPHA\n // has 11 characters.\n // eslint-disable-next-line no-non-null-assertion\n const check = BUSINESS_CHECK_ALPHA[sum % 11]!;\n return body + check;\n};\n\n/** Singapore Unique Entity Number. */\nconst uen: CountryValidator<\"SG\"> = {\n name: \"Singapore Unique Entity Number\",\n localName: \"Unique Entity Number\",\n abbreviation: \"UEN\",\n aliases: [\"UEN\", \"Unique Entity Number\"] as const,\n candidatePattern: \"[\\\\dSTR]\\\\d{7}[A-Z]\",\n scope: \"country\",\n country: \"SG\",\n entityType: \"company\",\n description:\n \"9 or 10-character business identifier issued by ACRA\",\n sourceUrl: \"https://www.uen.gov.sg/\",\n lengths: [9, 10] as const,\n examples: [\n \"00192200M\",\n \"197401143C\",\n \"S16FC0121D\",\n ] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default uen;\nexport { compact, format, validate, generate };\n"],"mappings":"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"}
package/dist/si/emso.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ParsedPersonId, ValidateResult, Validator } from "../types.js";
1
+ import { CountryValidator, ParsedPersonId, ValidateResult } from "../types.js";
2
2
 
3
3
  //#region src/si/emso.d.ts
4
4
  declare const compact: (value: string) => string;
@@ -12,7 +12,7 @@ declare const parse: (value: string) => ParsedPersonId | null;
12
12
  /** Generate a random valid Slovenian EMSO. */
13
13
  declare const generate: () => string;
14
14
  /** Slovenian Unique Master Citizen Number. */
15
- declare const emso: Validator<ParsedPersonId>;
15
+ declare const emso: CountryValidator<"SI", ParsedPersonId>;
16
16
  //#endregion
17
17
  export { compact, emso as default, format, generate, parse, validate };
18
18
  //# sourceMappingURL=emso.d.ts.map
package/dist/si/emso.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/si/emso.ts
8
- /**
9
- * EMŠO (Enotna matična številka občana).
10
- *
11
- * Slovenian unique master citizen number. 13 digits
12
- * encoding DDMMYYY (7-digit birth year), region code,
13
- * serial number, and a check digit.
14
- *
15
- * Canonical source:
16
- * - Slovenia government registry overview
17
- *
18
- * This is the source behind the stricter register
19
- * code check (50-59) and the decision to reject
20
- * future birth dates in the embedded date field.
21
- *
22
- * @see https://www.gov.si/teme/registri-in-evidence-prebivalstva/
23
- */
24
8
  const WEIGHTS = [
25
9
  7,
26
10
  6,
@@ -105,6 +89,7 @@ const emso = {
105
89
  abbreviation: "EMŠO",
106
90
  aliases: ["EMŠO", "enotna matična številka občana"],
107
91
  candidatePattern: "\\d{13}",
92
+ scope: "country",
108
93
  country: "SI",
109
94
  entityType: "person",
110
95
  sourceUrl: "https://www.gov.si/teme/registri-in-evidence-prebivalstva/",
@@ -1 +1 @@
1
- {"version":3,"file":"emso.js","names":[],"sources":["../../src/si/emso.ts"],"sourcesContent":["/**\n * EMŠO (Enotna matična številka občana).\n *\n * Slovenian unique master citizen number. 13 digits\n * encoding DDMMYYY (7-digit birth year), region code,\n * serial number, and a check digit.\n *\n * Canonical source:\n * - Slovenia government registry overview\n *\n * This is the source behind the stricter register\n * code check (50-59) and the decision to reject\n * future birth dates in the embedded date field.\n *\n * @see https://www.gov.si/teme/registri-in-evidence-prebivalstva/\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 = [\n 7, 6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2,\n] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\n/**\n * Compute the check digit matching python-stdnum:\n * `str(-total % 11 % 10)`.\n */\nconst calcCheckDigit = (v: string): number => {\n const total = weightedSum(v.slice(0, 12), WEIGHTS, 11);\n // Python's (-total % 11 % 10) — always 0..9\n // weightedSum already returns (sum % 11 + 11) % 11,\n // so total is 0..10. Negate within mod 11:\n return ((11 - total) % 11) % 10;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"EMŠO must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"EMŠO must contain only digits\",\n );\n }\n\n // Validate embedded birth date (DDMMYYY)\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n let yyyy = Number(v.slice(4, 7));\n // JMBG standard: 900-999 → 1900s, 000-899 → 2000s\n // Note: python-stdnum uses 800 as threshold, but\n // the official JMBG spec uses 900. No practical\n // difference (800-899 range has no living citizens).\n if (yyyy < 900) {\n yyyy += 2000;\n } else {\n yyyy += 1000;\n }\n if (!isValidDate(yyyy, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"EMŠO contains an invalid date\",\n );\n }\n const birthDate = new Date(yyyy, mm - 1, dd);\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n if (birthDate > today) {\n return err(\n \"INVALID_COMPONENT\",\n \"EMŠO cannot contain a future birth date\",\n );\n }\n\n const register = Number(v.slice(7, 9));\n if (register < 50 || register > 59) {\n return err(\n \"INVALID_COMPONENT\",\n \"EMSO register code must be between 50 and 59\",\n );\n }\n\n if (calcCheckDigit(v) !== Number(v[12])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"EMŠO 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 EMSO.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n let yyyy = Number(v.slice(4, 7));\n if (yyyy < 900) {\n yyyy += 2000;\n } else {\n yyyy += 1000;\n }\n\n const serial = Number(v.slice(9, 12));\n\n return {\n birthDate: new Date(yyyy, mm - 1, dd),\n gender: serial < 500 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid Slovenian EMSO. */\nconst generate = (): string => {\n for (;;) {\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const yyy = String(randomInt(900, 999));\n const rr = String(randomInt(50, 59));\n const sss = String(randomInt(0, 999)).padStart(3, \"0\");\n const partial = dd + mm + yyy + rr + sss;\n const c = partial + String(calcCheckDigit(partial));\n if (validate(c).valid) return c;\n }\n};\n\n/** Slovenian Unique Master Citizen Number. */\nconst emso: Validator<ParsedPersonId> = {\n name: \"Slovenian Personal ID\",\n localName: \"Enotna matična številka občana\",\n abbreviation: \"EMŠO\",\n aliases: [\n \"EMŠO\",\n \"enotna matična številka občana\",\n ] as const,\n candidatePattern: \"\\\\d{13}\",\n country: \"SI\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.gov.si/teme/registri-in-evidence-prebivalstva/\",\n examples: [\"0101006500006\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default emso;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,UAAU;CACd;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAClC;AAED,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;;;;;AAMpB,MAAM,kBAAkB,MAAsB;AAK5C,SAAS,KAJK,YAAY,EAAE,MAAM,GAAG,GAAG,EAAE,SAAS,GAAG,IAI/B,KAAM;;AAG/B,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,iCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,gCACD;CAIH,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAChC,IAAI,OAAO,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AAKhC,KAAI,OAAO,IACT,SAAQ;KAER,SAAQ;AAEV,KAAI,CAAC,YAAY,MAAM,IAAI,GAAG,CAC5B,QAAO,IACL,qBACA,gCACD;CAEH,MAAM,YAAY,IAAI,KAAK,MAAM,KAAK,GAAG,GAAG;CAC5C,MAAM,wBAAQ,IAAI,MAAM;AACxB,OAAM,SAAS,GAAG,GAAG,GAAG,EAAE;AAC1B,KAAI,YAAY,MACd,QAAO,IACL,qBACA,0CACD;CAGH,MAAM,WAAW,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AACtC,KAAI,WAAW,MAAM,WAAW,GAC9B,QAAO,IACL,qBACA,+CACD;AAGH,KAAI,eAAe,EAAE,KAAK,OAAO,EAAE,IAAI,CACrC,QAAO,IACL,oBACA,kCACD;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,IAAI,OAAO,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;AAChC,KAAI,OAAO,IACT,SAAQ;KAER,SAAQ;CAGV,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;AAErC,QAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,GAAG;EACrC,QAAQ,SAAS,MAAM,SAAS;EACjC;;;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,MAAM,OAAO,UAAU,KAAK,IAAI,CAAC;EACvC,MAAM,KAAK,OAAO,UAAU,IAAI,GAAG,CAAC;EACpC,MAAM,MAAM,OAAO,UAAU,GAAG,IAAI,CAAC,CAAC,SAAS,GAAG,IAAI;EACtD,MAAM,UAAU,KAAK,KAAK,MAAM,KAAK;EACrC,MAAM,IAAI,UAAU,OAAO,eAAe,QAAQ,CAAC;AACnD,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,OAAkC;CACtC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,QACA,iCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"emso.js","names":[],"sources":["../../src/si/emso.ts"],"sourcesContent":["/**\n * EMŠO (Enotna matična številka občana).\n *\n * Slovenian unique master citizen number. 13 digits\n * encoding DDMMYYY (7-digit birth year), region code,\n * serial number, and a check digit.\n *\n * Canonical source:\n * - Slovenia government registry overview\n *\n * This is the source behind the stricter register\n * code check (50-59) and the decision to reject\n * future birth dates in the embedded date field.\n *\n * @see https://www.gov.si/teme/registri-in-evidence-prebivalstva/\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 = [\n 7, 6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 2,\n] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\n/**\n * Compute the check digit matching python-stdnum:\n * `str(-total % 11 % 10)`.\n */\nconst calcCheckDigit = (v: string): number => {\n const total = weightedSum(v.slice(0, 12), WEIGHTS, 11);\n // Python's (-total % 11 % 10) — always 0..9\n // weightedSum already returns (sum % 11 + 11) % 11,\n // so total is 0..10. Negate within mod 11:\n return ((11 - total) % 11) % 10;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"EMŠO must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"EMŠO must contain only digits\",\n );\n }\n\n // Validate embedded birth date (DDMMYYY)\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n let yyyy = Number(v.slice(4, 7));\n // JMBG standard: 900-999 → 1900s, 000-899 → 2000s\n // Note: python-stdnum uses 800 as threshold, but\n // the official JMBG spec uses 900. No practical\n // difference (800-899 range has no living citizens).\n if (yyyy < 900) {\n yyyy += 2000;\n } else {\n yyyy += 1000;\n }\n if (!isValidDate(yyyy, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"EMŠO contains an invalid date\",\n );\n }\n const birthDate = new Date(yyyy, mm - 1, dd);\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n if (birthDate > today) {\n return err(\n \"INVALID_COMPONENT\",\n \"EMŠO cannot contain a future birth date\",\n );\n }\n\n const register = Number(v.slice(7, 9));\n if (register < 50 || register > 59) {\n return err(\n \"INVALID_COMPONENT\",\n \"EMSO register code must be between 50 and 59\",\n );\n }\n\n if (calcCheckDigit(v) !== Number(v[12])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"EMŠO 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 EMSO.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n let yyyy = Number(v.slice(4, 7));\n if (yyyy < 900) {\n yyyy += 2000;\n } else {\n yyyy += 1000;\n }\n\n const serial = Number(v.slice(9, 12));\n\n return {\n birthDate: new Date(yyyy, mm - 1, dd),\n gender: serial < 500 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid Slovenian EMSO. */\nconst generate = (): string => {\n for (;;) {\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const yyy = String(randomInt(900, 999));\n const rr = String(randomInt(50, 59));\n const sss = String(randomInt(0, 999)).padStart(3, \"0\");\n const partial = dd + mm + yyy + rr + sss;\n const c = partial + String(calcCheckDigit(partial));\n if (validate(c).valid) return c;\n }\n};\n\n/** Slovenian Unique Master Citizen Number. */\nconst emso: CountryValidator<\"SI\", ParsedPersonId> = {\n name: \"Slovenian Personal ID\",\n localName: \"Enotna matična številka občana\",\n abbreviation: \"EMŠO\",\n aliases: [\n \"EMŠO\",\n \"enotna matična številka občana\",\n ] as const,\n candidatePattern: \"\\\\d{13}\",\n scope: \"country\",\n country: \"SI\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.gov.si/teme/registri-in-evidence-prebivalstva/\",\n examples: [\"0101006500006\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default emso;\nexport { compact, format, parse, validate, generate };\n"],"mappings":"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"}
package/dist/si/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/si/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 Slovenian VAT number. */
8
8
  declare const generate: () => string;
9
9
  /** Slovenian VAT Number. */
10
- declare const vat: Validator;
10
+ declare const vat: CountryValidator<"SI">;
11
11
  //#endregion
12
12
  export { compact, vat as default, format, generate, validate };
13
13
  //# sourceMappingURL=vat.d.ts.map
package/dist/si/vat.js CHANGED
@@ -1,20 +1,9 @@
1
+ import { weightedSum } from "../_checksums/weighted-sum.js";
1
2
  import { clean } from "../_util/clean.js";
2
3
  import { randomDigits, randomInt } 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/si/vat.ts
7
- /**
8
- * DDV (Slovenian VAT number).
9
- *
10
- * 8 digits, no leading 0.
11
- * Weights [8,7,6,5,4,3,2], check = 11 - sum % 11.
12
- * If check === 10 invalid; if 11 the number is
13
- * invalid (spec says no valid number yields 11).
14
- *
15
- * @see https://www.vatify.eu/slovenia-vat-number.html
16
- * @see https://spot.gov.si/en/info/taxes/value-added-tax-vat
17
- */
18
7
  const WEIGHTS = [
19
8
  8,
20
9
  7,
@@ -59,9 +48,11 @@ const vat = {
59
48
  abbreviation: "DDV",
60
49
  aliases: ["DDV", "identifikacijska številka za DDV"],
61
50
  candidatePattern: "SI\\d{8}",
51
+ scope: "country",
62
52
  country: "SI",
63
53
  entityType: "company",
64
54
  sourceUrl: "https://www.fu.gov.si/",
55
+ lengths: [8],
65
56
  examples: ["15012557"],
66
57
  compact,
67
58
  format,
@@ -1 +1 @@
1
- {"version":3,"file":"vat.js","names":[],"sources":["../../src/si/vat.ts"],"sourcesContent":["/**\n * DDV (Slovenian VAT number).\n *\n * 8 digits, no leading 0.\n * Weights [8,7,6,5,4,3,2], check = 11 - sum % 11.\n * If check === 10 invalid; if 11 the number is\n * invalid (spec says no valid number yields 11).\n *\n * @see https://www.vatify.eu/slovenia-vat-number.html\n * @see https://spot.gov.si/en/info/taxes/value-added-tax-vat\n */\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\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 WEIGHTS = [8, 7, 6, 5, 4, 3, 2];\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"SI\") || v.startsWith(\"si\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"Slovenian VAT number must be 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Slovenian VAT number must contain only digits\",\n );\n }\n if (v[0] === \"0\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Slovenian VAT number cannot start with 0\",\n );\n }\n const remainder = weightedSum(v.slice(0, 7), WEIGHTS, 11);\n const check = 11 - remainder;\n if (check === 11) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Slovenian VAT number check digit invalid\",\n );\n }\n if (check === 10) {\n // check digit 10 means 0\n if (Number(v[7]) !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Slovenian VAT number check digit mismatch\",\n );\n }\n } else if (check !== Number(v[7])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Slovenian VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `SI${compact(value)}`;\n\n/** Generate a random valid Slovenian VAT number. */\nconst generate = (): string => {\n for (;;) {\n const c = String(randomInt(1, 9)) + randomDigits(7);\n if (validate(c).valid) return c;\n }\n};\n\n/** Slovenian VAT Number. */\nconst vat: Validator = {\n name: \"Slovenian VAT Number\",\n localName: \"Davčna številka\",\n abbreviation: \"DDV\",\n aliases: [\n \"DDV\",\n \"identifikacijska številka za DDV\",\n ] as const,\n candidatePattern: \"SI\\\\d{8}\",\n country: \"SI\",\n entityType: \"company\",\n sourceUrl: \"https://www.fu.gov.si/\",\n examples: [\"15012557\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAE;AAErC,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,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,EACf,QAAO,IACL,kBACA,wCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,gDACD;AAEH,KAAI,EAAE,OAAO,IACX,QAAO,IACL,qBACA,2CACD;CAGH,MAAM,QAAQ,KADI,YAAY,EAAE,MAAM,GAAG,EAAE,EAAE,SAAS,GAAG;AAEzD,KAAI,UAAU,GACZ,QAAO,IACL,oBACA,2CACD;AAEH,KAAI,UAAU;MAER,OAAO,EAAE,GAAG,KAAK,EACnB,QAAO,IACL,oBACA,4CACD;YAEM,UAAU,OAAO,EAAE,GAAG,CAC/B,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,OAAO,UAAU,GAAG,EAAE,CAAC,GAAG,aAAa,EAAE;AACnD,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,mCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,WAAW;CACtB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"vat.js","names":[],"sources":["../../src/si/vat.ts"],"sourcesContent":["/**\n * DDV (Slovenian VAT number).\n *\n * 8 digits, no leading 0.\n * Weights [8,7,6,5,4,3,2], check = 11 - sum % 11.\n * If check === 10 invalid; if 11 the number is\n * invalid (spec says no valid number yields 11).\n *\n * @see https://www.vatify.eu/slovenia-vat-number.html\n * @see https://spot.gov.si/en/info/taxes/value-added-tax-vat\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, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [8, 7, 6, 5, 4, 3, 2];\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"SI\") || v.startsWith(\"si\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"Slovenian VAT number must be 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Slovenian VAT number must contain only digits\",\n );\n }\n if (v[0] === \"0\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Slovenian VAT number cannot start with 0\",\n );\n }\n const remainder = weightedSum(v.slice(0, 7), WEIGHTS, 11);\n const check = 11 - remainder;\n if (check === 11) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Slovenian VAT number check digit invalid\",\n );\n }\n if (check === 10) {\n // check digit 10 means 0\n if (Number(v[7]) !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Slovenian VAT number check digit mismatch\",\n );\n }\n } else if (check !== Number(v[7])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Slovenian VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `SI${compact(value)}`;\n\n/** Generate a random valid Slovenian VAT number. */\nconst generate = (): string => {\n for (;;) {\n const c = String(randomInt(1, 9)) + randomDigits(7);\n if (validate(c).valid) return c;\n }\n};\n\n/** Slovenian VAT Number. */\nconst vat: CountryValidator<\"SI\"> = {\n name: \"Slovenian VAT Number\",\n localName: \"Davčna številka\",\n abbreviation: \"DDV\",\n aliases: [\n \"DDV\",\n \"identifikacijska številka za DDV\",\n ] as const,\n candidatePattern: \"SI\\\\d{8}\",\n scope: \"country\",\n country: \"SI\",\n entityType: \"company\",\n sourceUrl: \"https://www.fu.gov.si/\",\n lengths: [8] as const,\n examples: [\"15012557\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAuBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAEpC,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,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,uCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,+CACF;CAEF,IAAI,EAAE,OAAO,KACX,OAAO,IACL,qBACA,0CACF;CAGF,MAAM,QAAQ,KADI,YAAY,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,EAC3B;CAC3B,IAAI,UAAU,IACZ,OAAO,IACL,oBACA,0CACF;CAEF,IAAI,UAAU;MAER,OAAO,EAAE,EAAE,MAAM,GACnB,OAAO,IACL,oBACA,2CACF;CAAA,OAEG,IAAI,UAAU,OAAO,EAAE,EAAE,GAC9B,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,OAAO,UAAU,GAAG,CAAC,CAAC,IAAI,aAAa,CAAC;EAClD,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,kCACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,CAAC;CACX,UAAU,CAAC,UAAU;CACrB;CACA;CACA;CACA;AACF"}
package/dist/sk/dic.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/sk/dic.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 Slovak DIČ. */
8
8
  declare const generate: () => string;
9
9
  /** Slovak VAT Number. */
10
- declare const dic: Validator;
10
+ declare const dic: CountryValidator<"SK">;
11
11
  //#endregion
12
12
  export { compact, dic as default, format, generate, validate };
13
13
  //# sourceMappingURL=dic.d.ts.map
package/dist/sk/dic.js CHANGED
@@ -51,6 +51,7 @@ const dic = {
51
51
  abbreviation: "IČ DPH",
52
52
  aliases: ["DIČ", "daňové identifikačné číslo"],
53
53
  candidatePattern: "SK\\d{10}",
54
+ scope: "country",
54
55
  country: "SK",
55
56
  entityType: "company",
56
57
  sourceUrl: "https://www.financnasprava.sk/",
@@ -1 +1 @@
1
- {"version":3,"file":"dic.js","names":["validateRc"],"sources":["../../src/sk/dic.ts"],"sourcesContent":["/**\n * IČ DPH (Identifikačné číslo pre daň z\n * pridanej hodnoty).\n *\n * Slovak VAT number. Format: \"SK\" + 10 digits.\n * The 10-digit number must be divisible by 11.\n * First digit is 1-9.\n *\n * @see https://www.financnasprava.sk/\n */\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nimport { validate as validateRc } from \"../cz/rc\";\nimport type { ValidateResult, Validator } from \"../types\";\n\nconst compact = (value: string): string => {\n const v = clean(value, \" -\");\n if (v.startsWith(\"SK\") || v.startsWith(\"sk\")) {\n return v.slice(2);\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Slovak VAT number must be 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Slovak VAT number must contain only digits\",\n );\n }\n // A valid birth number is also accepted as DPH\n if (validateRc(v).valid) {\n return { valid: true, compact: v };\n }\n if (v[0] === \"0\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Slovak VAT number cannot start with 0\",\n );\n }\n // Third digit must be 2, 3, 4, 7, 8, or 9\n const d3 = Number(v[2]);\n if (\n d3 !== 2 &&\n d3 !== 3 &&\n d3 !== 4 &&\n d3 !== 7 &&\n d3 !== 8 &&\n d3 !== 9\n ) {\n return err(\n \"INVALID_FORMAT\",\n \"Slovak VAT number has invalid third digit\",\n );\n }\n if (Number(v) % 11 !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Slovak VAT number is not divisible by 11\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `SK${compact(value)}`;\n\n/** Generate a random valid Slovak DIČ. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Slovak VAT Number. */\nconst dic: Validator = {\n name: \"Slovak VAT Number\",\n localName:\n \"Identifikačné číslo pre daň z pridanej hodnoty\",\n abbreviation: \"IČ DPH\",\n aliases: [\"DIČ\", \"daňové identifikačné číslo\"] as const,\n candidatePattern: \"SK\\\\d{10}\",\n country: \"SK\",\n entityType: \"company\",\n sourceUrl: \"https://www.financnasprava.sk/\",\n examples: [\"2021853504\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default dic;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,MAAM,WAAW,UAA0B;CACzC,MAAM,IAAI,MAAM,OAAO,KAAK;AAC5B,KAAI,EAAE,WAAW,KAAK,IAAI,EAAE,WAAW,KAAK,CAC1C,QAAO,EAAE,MAAM,EAAE;AAEnB,QAAO;;AAGT,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,MAAM;AACxB,KAAI,EAAE,WAAW,GACf,QAAO,IACL,kBACA,sCACD;AAEH,KAAI,CAAC,SAAS,EAAE,CACd,QAAO,IACL,kBACA,6CACD;AAGH,KAAIA,WAAW,EAAE,CAAC,MAChB,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;AAEpC,KAAI,EAAE,OAAO,IACX,QAAO,IACL,qBACA,wCACD;CAGH,MAAM,KAAK,OAAO,EAAE,GAAG;AACvB,KACE,OAAO,KACP,OAAO,KACP,OAAO,KACP,OAAO,KACP,OAAO,KACP,OAAO,EAEP,QAAO,IACL,kBACA,4CACD;AAEH,KAAI,OAAO,EAAE,GAAG,OAAO,EACrB,QAAO,IACL,oBACA,2CACD;AAEH,QAAO;EAAE,OAAO;EAAM,SAAS;EAAG;;AAGpC,MAAM,UAAU,UACd,KAAK,QAAQ,MAAM;;AAGrB,MAAM,iBAAyB;AAC7B,UAAS;EACP,MAAM,IAAI,aAAa,GAAG;AAC1B,MAAI,SAAS,EAAE,CAAC,MAAO,QAAO;;;;AAKlC,MAAM,MAAiB;CACrB,MAAM;CACN,WACE;CACF,cAAc;CACd,SAAS,CAAC,OAAO,6BAA6B;CAC9C,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"dic.js","names":["validateRc"],"sources":["../../src/sk/dic.ts"],"sourcesContent":["/**\n * IČ DPH (Identifikačné číslo pre daň z\n * pridanej hodnoty).\n *\n * Slovak VAT number. Format: \"SK\" + 10 digits.\n * The 10-digit number must be divisible by 11.\n * First digit is 1-9.\n *\n * @see https://www.financnasprava.sk/\n */\n\nimport { validate as validateRc } from \"../cz/rc\";\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 const v = clean(value, \" -\");\n if (v.startsWith(\"SK\") || v.startsWith(\"sk\")) {\n return v.slice(2);\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Slovak VAT number must be 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Slovak VAT number must contain only digits\",\n );\n }\n // A valid birth number is also accepted as DPH\n if (validateRc(v).valid) {\n return { valid: true, compact: v };\n }\n if (v[0] === \"0\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Slovak VAT number cannot start with 0\",\n );\n }\n // Third digit must be 2, 3, 4, 7, 8, or 9\n const d3 = Number(v[2]);\n if (\n d3 !== 2 &&\n d3 !== 3 &&\n d3 !== 4 &&\n d3 !== 7 &&\n d3 !== 8 &&\n d3 !== 9\n ) {\n return err(\n \"INVALID_FORMAT\",\n \"Slovak VAT number has invalid third digit\",\n );\n }\n if (Number(v) % 11 !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Slovak VAT number is not divisible by 11\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `SK${compact(value)}`;\n\n/** Generate a random valid Slovak DIČ. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Slovak VAT Number. */\nconst dic: CountryValidator<\"SK\"> = {\n name: \"Slovak VAT Number\",\n localName:\n \"Identifikačné číslo pre daň z pridanej hodnoty\",\n abbreviation: \"IČ DPH\",\n aliases: [\"DIČ\", \"daňové identifikačné číslo\"] as const,\n candidatePattern: \"SK\\\\d{10}\",\n scope: \"country\",\n country: \"SK\",\n entityType: \"company\",\n sourceUrl: \"https://www.financnasprava.sk/\",\n examples: [\"2021853504\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default dic;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;AAsBA,MAAM,WAAW,UAA0B;CACzC,MAAM,IAAI,MAAM,OAAO,IAAI;CAC3B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,OAAO,EAAE,MAAM,CAAC;CAElB,OAAO;AACT;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,qCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,4CACF;CAGF,IAAIA,WAAW,CAAC,EAAE,OAChB,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;CAEnC,IAAI,EAAE,OAAO,KACX,OAAO,IACL,qBACA,uCACF;CAGF,MAAM,KAAK,OAAO,EAAE,EAAE;CACtB,IACE,OAAO,KACP,OAAO,KACP,OAAO,KACP,OAAO,KACP,OAAO,KACP,OAAO,GAEP,OAAO,IACL,kBACA,2CACF;CAEF,IAAI,OAAO,CAAC,IAAI,OAAO,GACrB,OAAO,IACL,oBACA,0CACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,KAAK,QAAQ,KAAK;;AAGpB,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,EAAE;EACzB,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WACE;CACF,cAAc;CACd,SAAS,CAAC,OAAO,4BAA4B;CAC7C,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;AACF"}
package/dist/sk/ico.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { Validator } from "../types.js";
1
+ import { CountryValidator } from "../types.js";
2
2
  import { compact, format, generate, validate } from "../cz/ico.js";
3
3
 
4
4
  //#region src/sk/ico.d.ts
5
5
  /** Slovak Company Identification Number. */
6
- declare const ico: Validator;
6
+ declare const ico: CountryValidator<"SK">;
7
7
  //#endregion
8
8
  export { compact, ico as default, format, generate, validate };
9
9
  //# sourceMappingURL=ico.d.ts.map
package/dist/sk/ico.js CHANGED
@@ -15,6 +15,7 @@ const ico = {
15
15
  abbreviation: "IČO",
16
16
  aliases: ["IČO", "identifikačné číslo organizácie"],
17
17
  candidatePattern: "\\d{8}",
18
+ scope: "country",
18
19
  country: "SK",
19
20
  entityType: "company",
20
21
  sourceUrl: "https://www.statistics.sk/",
@@ -1 +1 @@
1
- {"version":3,"file":"ico.js","names":[],"sources":["../../src/sk/ico.ts"],"sourcesContent":["/**\n * IČO (Identifikačné číslo organizácie).\n *\n * Slovak company identification number. Same\n * 8-digit weighted checksum as the Czech IČO.\n *\n * @see https://www.statistics.sk/\n */\n\nimport {\n compact,\n format,\n generate,\n validate,\n} from \"../cz/ico\";\nimport type { Validator } from \"../types\";\n\n/** Slovak Company Identification Number. */\nconst ico: Validator = {\n name: \"Slovak Company ID\",\n localName: \"Identifikačné číslo organizácie\",\n abbreviation: \"IČO\",\n aliases: [\n \"IČO\",\n \"identifikačné číslo organizácie\",\n ] as const,\n candidatePattern: \"\\\\d{8}\",\n country: \"SK\",\n entityType: \"company\",\n sourceUrl: \"https://www.statistics.sk/\",\n examples: [\"25123891\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default ico;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;AAkBA,MAAM,MAAiB;CACrB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,kCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,WAAW;CACtB;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"ico.js","names":[],"sources":["../../src/sk/ico.ts"],"sourcesContent":["/**\n * IČO (Identifikačné číslo organizácie).\n *\n * Slovak company identification number. Same\n * 8-digit weighted checksum as the Czech IČO.\n *\n * @see https://www.statistics.sk/\n */\n\nimport {\n compact,\n format,\n generate,\n validate,\n} from \"../cz/ico\";\nimport type { CountryValidator } from \"../types\";\n\n/** Slovak Company Identification Number. */\nconst ico: CountryValidator<\"SK\"> = {\n name: \"Slovak Company ID\",\n localName: \"Identifikačné číslo organizácie\",\n abbreviation: \"IČO\",\n aliases: [\n \"IČO\",\n \"identifikačné číslo organizácie\",\n ] as const,\n candidatePattern: \"\\\\d{8}\",\n scope: \"country\",\n country: \"SK\",\n entityType: \"company\",\n sourceUrl: \"https://www.statistics.sk/\",\n examples: [\"25123891\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default ico;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;;;;;AAkBA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,OACA,iCACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,UAAU;CACrB;CACA;CACA;CACA;AACF"}
package/dist/sk/rc.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { ParsedPersonId, Validator } from "../types.js";
1
+ import { CountryValidator, ParsedPersonId } from "../types.js";
2
2
  import { compact, format, generate, parse, validate } from "../cz/rc.js";
3
3
 
4
4
  //#region src/sk/rc.d.ts
5
5
  /** Slovak Birth Number. */
6
- declare const rc: Validator<ParsedPersonId>;
6
+ declare const rc: CountryValidator<"SK", ParsedPersonId>;
7
7
  //#endregion
8
8
  export { compact, rc as default, format, generate, parse, validate };
9
9
  //# sourceMappingURL=rc.d.ts.map
package/dist/sk/rc.js CHANGED
@@ -16,6 +16,7 @@ const rc = {
16
16
  abbreviation: "RČ",
17
17
  aliases: ["rodné číslo", "RČ"],
18
18
  candidatePattern: "\\d{6}/\\d{3,4}",
19
+ scope: "country",
19
20
  country: "SK",
20
21
  entityType: "person",
21
22
  sourceUrl: "https://www.minv.sk/",
package/dist/sk/rc.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"rc.js","names":[],"sources":["../../src/sk/rc.ts"],"sourcesContent":["/**\n * RČ (Rodné číslo).\n *\n * Slovak birth number. Identical algorithm to\n * the Czech birth number.\n *\n * @see https://www.mvcr.cz/mvcren/docDetail.aspx?docid=21975362&doctype=ART\n * @see https://www.minv.sk/\n */\n\nimport {\n compact,\n format,\n generate,\n parse,\n validate,\n} from \"../cz/rc\";\nimport type { ParsedPersonId, Validator } from \"../types\";\n\n/** Slovak Birth Number. */\nconst rc: Validator<ParsedPersonId> = {\n name: \"Slovak Birth Number\",\n localName: \"Rodné číslo\",\n abbreviation: \"RČ\",\n aliases: [\"rodné číslo\", \"RČ\"] as const,\n candidatePattern: \"\\\\d{6}/\\\\d{3,4}\",\n country: \"SK\",\n entityType: \"person\",\n sourceUrl: \"https://www.minv.sk/\",\n lengths: [9, 10] as const,\n examples: [\"7103192745\"] as const,\n compact,\n format,\n generate,\n parse,\n validate,\n};\n\nexport default rc;\nexport { compact, format, generate, parse, validate };\n"],"mappings":";;;;;;;;;;;;AAoBA,MAAM,KAAgC;CACpC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,eAAe,KAAK;CAC9B,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,GAAG,GAAG;CAChB,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"rc.js","names":[],"sources":["../../src/sk/rc.ts"],"sourcesContent":["/**\n * RČ (Rodné číslo).\n *\n * Slovak birth number. Identical algorithm to\n * the Czech birth number.\n *\n * @see https://www.mvcr.cz/mvcren/docDetail.aspx?docid=21975362&doctype=ART\n * @see https://www.minv.sk/\n */\n\nimport {\n compact,\n format,\n generate,\n parse,\n validate,\n} from \"../cz/rc\";\nimport type {\n ParsedPersonId,\n CountryValidator,\n} from \"../types\";\n\n/** Slovak Birth Number. */\nconst rc: CountryValidator<\"SK\", ParsedPersonId> = {\n name: \"Slovak Birth Number\",\n localName: \"Rodné číslo\",\n abbreviation: \"RČ\",\n aliases: [\"rodné číslo\", \"RČ\"] as const,\n candidatePattern: \"\\\\d{6}/\\\\d{3,4}\",\n scope: \"country\",\n country: \"SK\",\n entityType: \"person\",\n sourceUrl: \"https://www.minv.sk/\",\n lengths: [9, 10] as const,\n examples: [\"7103192745\"] as const,\n compact,\n format,\n generate,\n parse,\n validate,\n};\n\nexport default rc;\nexport { compact, format, generate, parse, validate };\n"],"mappings":";;;;;;;;;;;;AAuBA,MAAM,KAA6C;CACjD,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,eAAe,IAAI;CAC7B,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,GAAG,EAAE;CACf,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACA;AACF"}
package/dist/th/tin.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/th/tin.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 Thai TIN. */
8
8
  declare const generate: () => string;
9
9
  /** Thai Tax Identification Number. */
10
- declare const tin: Validator;
10
+ declare const tin: CountryValidator<"TH">;
11
11
  //#endregion
12
12
  export { compact, tin as default, format, generate, validate };
13
13
  //# sourceMappingURL=tin.d.ts.map