@stll/stdnum 0.0.1 → 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 (808) hide show
  1. package/LICENSE +1 -5
  2. package/README.md +28 -4
  3. package/dist/_checksums/luhn.js.map +1 -1
  4. package/dist/_checksums/mod1110.js +1 -1
  5. package/dist/_checksums/mod1110.js.map +1 -1
  6. package/dist/_checksums/mod112.js +5 -5
  7. package/dist/_checksums/mod112.js.map +1 -1
  8. package/dist/_checksums/mod97.js.map +1 -1
  9. package/dist/_checksums/verhoeff.js.map +1 -1
  10. package/dist/_checksums/weighted-sum.js.map +1 -1
  11. package/dist/_util/arabic.js.map +1 -1
  12. package/dist/_util/clean.js.map +1 -1
  13. package/dist/_util/date.js.map +1 -1
  14. package/dist/_util/generate.d.ts +13 -1
  15. package/dist/_util/generate.js +23 -1
  16. package/dist/_util/generate.js.map +1 -1
  17. package/dist/_util/result.js.map +1 -1
  18. package/dist/_util/strings.js.map +1 -1
  19. package/dist/ad/mod.d.ts +3 -2
  20. package/dist/ad/nrt.d.ts +16 -2
  21. package/dist/ad/nrt.js +4 -16
  22. package/dist/ad/nrt.js.map +1 -1
  23. package/dist/ae/eid.d.ts +2 -3
  24. package/dist/ae/eid.js +2 -12
  25. package/dist/ae/eid.js.map +1 -1
  26. package/dist/ae/mod.d.ts +3 -2
  27. package/dist/ai/mod.d.ts +3 -2
  28. package/dist/ai/tin.d.ts +20 -2
  29. package/dist/ai/tin.js +1 -18
  30. package/dist/ai/tin.js.map +1 -1
  31. package/dist/al/mod.d.ts +3 -2
  32. package/dist/al/nipt.d.ts +13 -2
  33. package/dist/al/nipt.js +1 -11
  34. package/dist/al/nipt.js.map +1 -1
  35. package/dist/am/mod.d.ts +3 -2
  36. package/dist/am/tin.d.ts +16 -2
  37. package/dist/am/tin.js +1 -14
  38. package/dist/am/tin.js.map +1 -1
  39. package/dist/ar/cbu.d.ts +2 -3
  40. package/dist/ar/cbu.js +2 -10
  41. package/dist/ar/cbu.js.map +1 -1
  42. package/dist/ar/cuit.d.ts +2 -3
  43. package/dist/ar/cuit.js +13 -29
  44. package/dist/ar/cuit.js.map +1 -1
  45. package/dist/ar/dni.d.ts +11 -2
  46. package/dist/ar/dni.js +1 -9
  47. package/dist/ar/dni.js.map +1 -1
  48. package/dist/ar/mod.d.ts +3 -2
  49. package/dist/at/businessid.d.ts +10 -2
  50. package/dist/at/businessid.js +1 -8
  51. package/dist/at/businessid.js.map +1 -1
  52. package/dist/at/mod.d.ts +3 -2
  53. package/dist/at/tin.d.ts +2 -3
  54. package/dist/at/tin.js +1 -11
  55. package/dist/at/tin.js.map +1 -1
  56. package/dist/at/uid.d.ts +2 -3
  57. package/dist/at/uid.js +2 -10
  58. package/dist/at/uid.js.map +1 -1
  59. package/dist/at/vnr.d.ts +5 -4
  60. package/dist/at/vnr.js +23 -16
  61. package/dist/at/vnr.js.map +1 -1
  62. package/dist/au/abn.d.ts +2 -3
  63. package/dist/au/abn.js +1 -10
  64. package/dist/au/abn.js.map +1 -1
  65. package/dist/au/acn.d.ts +2 -3
  66. package/dist/au/acn.js +1 -10
  67. package/dist/au/acn.js.map +1 -1
  68. package/dist/au/mod.d.ts +3 -2
  69. package/dist/au/tfn.d.ts +2 -3
  70. package/dist/au/tfn.js +1 -10
  71. package/dist/au/tfn.js.map +1 -1
  72. package/dist/az/mod.d.ts +3 -2
  73. package/dist/az/voen.d.ts +2 -3
  74. package/dist/az/voen.js +1 -14
  75. package/dist/az/voen.js.map +1 -1
  76. package/dist/ba/jmbg.d.ts +2 -3
  77. package/dist/ba/jmbg.js +4 -11
  78. package/dist/ba/jmbg.js.map +1 -1
  79. package/dist/ba/mod.d.ts +3 -2
  80. package/dist/bd/mod.d.ts +3 -2
  81. package/dist/bd/nid.d.ts +23 -2
  82. package/dist/bd/nid.js +11 -32
  83. package/dist/bd/nid.js.map +1 -1
  84. package/dist/be/bis.d.ts +2 -3
  85. package/dist/be/bis.js +1 -11
  86. package/dist/be/bis.js.map +1 -1
  87. package/dist/be/mod.d.ts +3 -2
  88. package/dist/be/nn.d.ts +2 -3
  89. package/dist/be/nn.js +1 -11
  90. package/dist/be/nn.js.map +1 -1
  91. package/dist/be/vat.d.ts +2 -3
  92. package/dist/be/vat.js +1 -9
  93. package/dist/be/vat.js.map +1 -1
  94. package/dist/bg/egn.d.ts +2 -3
  95. package/dist/bg/egn.js +5 -13
  96. package/dist/bg/egn.js.map +1 -1
  97. package/dist/bg/mod.d.ts +3 -2
  98. package/dist/bg/pnf.d.ts +2 -3
  99. package/dist/bg/pnf.js +1 -8
  100. package/dist/bg/pnf.js.map +1 -1
  101. package/dist/bg/vat.d.ts +2 -3
  102. package/dist/bg/vat.js +3 -9
  103. package/dist/bg/vat.js.map +1 -1
  104. package/dist/bh/cpr.d.ts +5 -4
  105. package/dist/bh/cpr.js +9 -19
  106. package/dist/bh/cpr.js.map +1 -1
  107. package/dist/bh/mod.d.ts +3 -2
  108. package/dist/bic.d.ts +13 -2
  109. package/dist/bic.js +14 -26
  110. package/dist/bic.js.map +1 -1
  111. package/dist/br/cnpj.d.ts +2 -3
  112. package/dist/br/cnpj.js +1 -20
  113. package/dist/br/cnpj.js.map +1 -1
  114. package/dist/br/cpf.d.ts +2 -3
  115. package/dist/br/cpf.js +1 -14
  116. package/dist/br/cpf.js.map +1 -1
  117. package/dist/br/mod.d.ts +3 -2
  118. package/dist/by/mod.d.ts +3 -2
  119. package/dist/by/unp.d.ts +2 -3
  120. package/dist/by/unp.js +9 -17
  121. package/dist/by/unp.js.map +1 -1
  122. package/dist/bz/mod.d.ts +3 -2
  123. package/dist/bz/tin.d.ts +5 -4
  124. package/dist/bz/tin.js +10 -27
  125. package/dist/bz/tin.js.map +1 -1
  126. package/dist/ca/bn.d.ts +2 -3
  127. package/dist/ca/bn.js +2 -10
  128. package/dist/ca/bn.js.map +1 -1
  129. package/dist/ca/mod.d.ts +3 -2
  130. package/dist/ca/sin.d.ts +2 -3
  131. package/dist/ca/sin.js +2 -10
  132. package/dist/ca/sin.js.map +1 -1
  133. package/dist/ch/mod.d.ts +3 -2
  134. package/dist/ch/ssn.d.ts +2 -3
  135. package/dist/ch/ssn.js +1 -9
  136. package/dist/ch/ssn.js.map +1 -1
  137. package/dist/ch/uid.d.ts +2 -3
  138. package/dist/ch/uid.js +1 -9
  139. package/dist/ch/uid.js.map +1 -1
  140. package/dist/ch/vat.d.ts +2 -3
  141. package/dist/ch/vat.js +1 -9
  142. package/dist/ch/vat.js.map +1 -1
  143. package/dist/cl/mod.d.ts +3 -2
  144. package/dist/cl/rut.d.ts +2 -3
  145. package/dist/cl/rut.js +2 -15
  146. package/dist/cl/rut.js.map +1 -1
  147. package/dist/cn/mod.d.ts +3 -2
  148. package/dist/cn/ric.d.ts +2 -3
  149. package/dist/cn/ric.js +4 -14
  150. package/dist/cn/ric.js.map +1 -1
  151. package/dist/cn/uscc.d.ts +2 -3
  152. package/dist/cn/uscc.js +8 -16
  153. package/dist/cn/uscc.js.map +1 -1
  154. package/dist/co/mod.d.ts +3 -2
  155. package/dist/co/nit.d.ts +2 -3
  156. package/dist/co/nit.js +6 -13
  157. package/dist/co/nit.js.map +1 -1
  158. package/dist/cr/cpf.d.ts +18 -2
  159. package/dist/cr/cpf.js +5 -19
  160. package/dist/cr/cpf.js.map +1 -1
  161. package/dist/cr/mod.d.ts +3 -2
  162. package/dist/creditcard.d.ts +2 -3
  163. package/dist/creditcard.js +5 -14
  164. package/dist/creditcard.js.map +1 -1
  165. package/dist/cu/mod.d.ts +3 -2
  166. package/dist/cu/ni.d.ts +5 -4
  167. package/dist/cu/ni.js +13 -18
  168. package/dist/cu/ni.js.map +1 -1
  169. package/dist/cy/mod.d.ts +3 -2
  170. package/dist/cy/vat.d.ts +2 -3
  171. package/dist/cy/vat.js +1 -8
  172. package/dist/cy/vat.js.map +1 -1
  173. package/dist/cz/dic.d.ts +2 -3
  174. package/dist/cz/dic.js +7 -13
  175. package/dist/cz/dic.js.map +1 -1
  176. package/dist/cz/ico.d.ts +2 -3
  177. package/dist/cz/ico.js +2 -10
  178. package/dist/cz/ico.js.map +1 -1
  179. package/dist/cz/mod.d.ts +3 -2
  180. package/dist/cz/rc.d.ts +2 -3
  181. package/dist/cz/rc.js +22 -21
  182. package/dist/cz/rc.js.map +1 -1
  183. package/dist/de/handelsreg.d.ts +19 -2
  184. package/dist/de/handelsreg.js +10 -26
  185. package/dist/de/handelsreg.js.map +1 -1
  186. package/dist/de/idnr.d.ts +2 -3
  187. package/dist/de/idnr.js +2 -12
  188. package/dist/de/idnr.js.map +1 -1
  189. package/dist/de/mod.d.ts +3 -2
  190. package/dist/de/stnr.d.ts +17 -3
  191. package/dist/de/stnr.js +1 -15
  192. package/dist/de/stnr.js.map +1 -1
  193. package/dist/de/svnr.d.ts +2 -3
  194. package/dist/de/svnr.js +4 -13
  195. package/dist/de/svnr.js.map +1 -1
  196. package/dist/de/vat.d.ts +2 -3
  197. package/dist/de/vat.js +2 -11
  198. package/dist/de/vat.js.map +1 -1
  199. package/dist/dk/cpr.d.ts +5 -4
  200. package/dist/dk/cpr.js +14 -12
  201. package/dist/dk/cpr.js.map +1 -1
  202. package/dist/dk/cvr.d.ts +2 -3
  203. package/dist/dk/cvr.js +2 -15
  204. package/dist/dk/cvr.js.map +1 -1
  205. package/dist/dk/mod.d.ts +3 -2
  206. package/dist/dk/vat.d.ts +2 -3
  207. package/dist/dk/vat.js +3 -13
  208. package/dist/dk/vat.js.map +1 -1
  209. package/dist/do/mod.d.ts +3 -2
  210. package/dist/do/rnc.d.ts +2 -3
  211. package/dist/do/rnc.js +3 -17
  212. package/dist/do/rnc.js.map +1 -1
  213. package/dist/ec/mod.d.ts +3 -2
  214. package/dist/ec/ruc.d.ts +2 -3
  215. package/dist/ec/ruc.js +2 -19
  216. package/dist/ec/ruc.js.map +1 -1
  217. package/dist/ee/ik.d.ts +2 -3
  218. package/dist/ee/ik.js +6 -15
  219. package/dist/ee/ik.js.map +1 -1
  220. package/dist/ee/mod.d.ts +3 -2
  221. package/dist/ee/registrikood.d.ts +2 -3
  222. package/dist/ee/registrikood.js +9 -15
  223. package/dist/ee/registrikood.js.map +1 -1
  224. package/dist/ee/vat.d.ts +2 -3
  225. package/dist/ee/vat.js +2 -10
  226. package/dist/ee/vat.js.map +1 -1
  227. package/dist/eg/mod.d.ts +3 -2
  228. package/dist/eg/tn.d.ts +11 -2
  229. package/dist/eg/tn.js +1 -9
  230. package/dist/eg/tn.js.map +1 -1
  231. package/dist/es/cif.d.ts +2 -3
  232. package/dist/es/cif.js +3 -12
  233. package/dist/es/cif.js.map +1 -1
  234. package/dist/es/dni.d.ts +2 -3
  235. package/dist/es/dni.js +1 -9
  236. package/dist/es/dni.js.map +1 -1
  237. package/dist/es/mod.d.ts +3 -2
  238. package/dist/es/nie.d.ts +2 -3
  239. package/dist/es/nie.js +14 -22
  240. package/dist/es/nie.js.map +1 -1
  241. package/dist/es/nss.d.ts +2 -3
  242. package/dist/es/nss.js +1 -16
  243. package/dist/es/nss.js.map +1 -1
  244. package/dist/es/vat.d.ts +2 -3
  245. package/dist/es/vat.js +5 -10
  246. package/dist/es/vat.js.map +1 -1
  247. package/dist/eu/mod.d.ts +3 -2
  248. package/dist/eu/vat.d.ts +5 -4
  249. package/dist/eu/vat.js +44 -2
  250. package/dist/eu/vat.js.map +1 -1
  251. package/dist/fi/hetu.d.ts +5 -4
  252. package/dist/fi/hetu.js +19 -12
  253. package/dist/fi/hetu.js.map +1 -1
  254. package/dist/fi/mod.d.ts +3 -2
  255. package/dist/fi/vat.d.ts +2 -3
  256. package/dist/fi/vat.js +3 -10
  257. package/dist/fi/vat.js.map +1 -1
  258. package/dist/fi/ytunnus.d.ts +2 -3
  259. package/dist/fi/ytunnus.js +2 -10
  260. package/dist/fi/ytunnus.js.map +1 -1
  261. package/dist/fr/mod.d.ts +3 -2
  262. package/dist/fr/nif.d.ts +2 -3
  263. package/dist/fr/nif.js +1 -9
  264. package/dist/fr/nif.js.map +1 -1
  265. package/dist/fr/nir.d.ts +2 -3
  266. package/dist/fr/nir.js +3 -14
  267. package/dist/fr/nir.js.map +1 -1
  268. package/dist/fr/siren.d.ts +2 -3
  269. package/dist/fr/siren.js +2 -10
  270. package/dist/fr/siren.js.map +1 -1
  271. package/dist/fr/siret.d.ts +2 -3
  272. package/dist/fr/siret.js +2 -11
  273. package/dist/fr/siret.js.map +1 -1
  274. package/dist/fr/tva.d.ts +2 -3
  275. package/dist/fr/tva.js +2 -12
  276. package/dist/fr/tva.js.map +1 -1
  277. package/dist/gb/mod.d.ts +3 -2
  278. package/dist/gb/nino.d.ts +12 -2
  279. package/dist/gb/nino.js +8 -17
  280. package/dist/gb/nino.js.map +1 -1
  281. package/dist/gb/sedol.d.ts +2 -3
  282. package/dist/gb/sedol.js +9 -18
  283. package/dist/gb/sedol.js.map +1 -1
  284. package/dist/gb/utr.d.ts +2 -3
  285. package/dist/gb/utr.js +2 -10
  286. package/dist/gb/utr.js.map +1 -1
  287. package/dist/gb/vat.d.ts +2 -3
  288. package/dist/gb/vat.js +2 -11
  289. package/dist/gb/vat.js.map +1 -1
  290. package/dist/ge/mod.d.ts +3 -2
  291. package/dist/ge/pin.d.ts +14 -2
  292. package/dist/ge/pin.js +1 -12
  293. package/dist/ge/pin.js.map +1 -1
  294. package/dist/gh/mod.d.ts +3 -2
  295. package/dist/gh/tin.d.ts +2 -3
  296. package/dist/gh/tin.js +10 -24
  297. package/dist/gh/tin.js.map +1 -1
  298. package/dist/gr/amka.d.ts +2 -3
  299. package/dist/gr/amka.js +3 -11
  300. package/dist/gr/amka.js.map +1 -1
  301. package/dist/gr/mod.d.ts +3 -2
  302. package/dist/gr/vat.d.ts +2 -3
  303. package/dist/gr/vat.js +1 -10
  304. package/dist/gr/vat.js.map +1 -1
  305. package/dist/gt/mod.d.ts +3 -2
  306. package/dist/gt/nit.d.ts +2 -3
  307. package/dist/gt/nit.js +6 -14
  308. package/dist/gt/nit.js.map +1 -1
  309. package/dist/hk/hkid.d.ts +2 -3
  310. package/dist/hk/hkid.js +2 -10
  311. package/dist/hk/hkid.js.map +1 -1
  312. package/dist/hk/mod.d.ts +3 -2
  313. package/dist/hr/mod.d.ts +3 -2
  314. package/dist/hr/vat.d.ts +2 -3
  315. package/dist/hr/vat.js +2 -9
  316. package/dist/hr/vat.js.map +1 -1
  317. package/dist/hu/mod.d.ts +3 -2
  318. package/dist/hu/vat.d.ts +2 -3
  319. package/dist/hu/vat.js +3 -10
  320. package/dist/hu/vat.js.map +1 -1
  321. package/dist/iban.d.ts +2 -3
  322. package/dist/iban.js +2 -8
  323. package/dist/iban.js.map +1 -1
  324. package/dist/id/mod.d.ts +3 -2
  325. package/dist/id/npwp.d.ts +2 -3
  326. package/dist/id/npwp.js +3 -13
  327. package/dist/id/npwp.js.map +1 -1
  328. package/dist/ie/mod.d.ts +3 -2
  329. package/dist/ie/pps.d.ts +2 -3
  330. package/dist/ie/pps.js +1 -10
  331. package/dist/ie/pps.js.map +1 -1
  332. package/dist/ie/vat.d.ts +2 -3
  333. package/dist/ie/vat.js +1 -9
  334. package/dist/ie/vat.js.map +1 -1
  335. package/dist/il/idnr.d.ts +2 -3
  336. package/dist/il/idnr.js +2 -9
  337. package/dist/il/idnr.js.map +1 -1
  338. package/dist/il/mod.d.ts +3 -2
  339. package/dist/in/aadhaar.d.ts +2 -3
  340. package/dist/in/aadhaar.js +2 -12
  341. package/dist/in/aadhaar.js.map +1 -1
  342. package/dist/in/gstin.d.ts +2 -3
  343. package/dist/in/gstin.js +4 -11
  344. package/dist/in/gstin.js.map +1 -1
  345. package/dist/in/mod.d.ts +3 -2
  346. package/dist/in/pan.d.ts +15 -2
  347. package/dist/in/pan.js +3 -15
  348. package/dist/in/pan.js.map +1 -1
  349. package/dist/index.d.ts +2 -2
  350. package/dist/index.js +6 -6
  351. package/dist/iq/mod.d.ts +3 -2
  352. package/dist/iq/nid.d.ts +16 -2
  353. package/dist/iq/nid.js +2 -15
  354. package/dist/iq/nid.js.map +1 -1
  355. package/dist/ir/mod.d.ts +3 -2
  356. package/dist/ir/nid.d.ts +2 -3
  357. package/dist/ir/nid.js +2 -24
  358. package/dist/ir/nid.js.map +1 -1
  359. package/dist/is/kennitala.d.ts +2 -3
  360. package/dist/is/kennitala.js +2 -13
  361. package/dist/is/kennitala.js.map +1 -1
  362. package/dist/is/mod.d.ts +3 -2
  363. package/dist/is/vsk.d.ts +9 -2
  364. package/dist/is/vsk.js +1 -7
  365. package/dist/is/vsk.js.map +1 -1
  366. package/dist/isin.d.ts +2 -3
  367. package/dist/isin.js +11 -21
  368. package/dist/isin.js.map +1 -1
  369. package/dist/it/codicefiscale.d.ts +5 -4
  370. package/dist/it/codicefiscale.js +27 -23
  371. package/dist/it/codicefiscale.js.map +1 -1
  372. package/dist/it/iva.d.ts +2 -3
  373. package/dist/it/iva.js +2 -9
  374. package/dist/it/iva.js.map +1 -1
  375. package/dist/it/mod.d.ts +3 -2
  376. package/dist/jp/cn.d.ts +2 -3
  377. package/dist/jp/cn.js +1 -9
  378. package/dist/jp/cn.js.map +1 -1
  379. package/dist/jp/mod.d.ts +3 -2
  380. package/dist/jp/mynumber.d.ts +2 -3
  381. package/dist/jp/mynumber.js +1 -10
  382. package/dist/jp/mynumber.js.map +1 -1
  383. package/dist/kr/brn.d.ts +11 -2
  384. package/dist/kr/brn.js +1 -9
  385. package/dist/kr/brn.js.map +1 -1
  386. package/dist/kr/mod.d.ts +3 -2
  387. package/dist/kr/rrn.d.ts +5 -4
  388. package/dist/kr/rrn.js +15 -13
  389. package/dist/kr/rrn.js.map +1 -1
  390. package/dist/kw/civil.d.ts +6 -5
  391. package/dist/kw/civil.js +20 -17
  392. package/dist/kw/civil.js.map +1 -1
  393. package/dist/kw/mod.d.ts +3 -2
  394. package/dist/kz/iin.d.ts +2 -3
  395. package/dist/kz/iin.js +4 -18
  396. package/dist/kz/iin.js.map +1 -1
  397. package/dist/kz/mod.d.ts +3 -2
  398. package/dist/lei.d.ts +2 -3
  399. package/dist/lei.js +2 -11
  400. package/dist/lei.js.map +1 -1
  401. package/dist/li/mod.d.ts +3 -2
  402. package/dist/li/peid.d.ts +11 -2
  403. package/dist/li/peid.js +1 -9
  404. package/dist/li/peid.js.map +1 -1
  405. package/dist/lk/mod.d.ts +3 -2
  406. package/dist/lk/nic.d.ts +5 -4
  407. package/dist/lk/nic.js +16 -16
  408. package/dist/lk/nic.js.map +1 -1
  409. package/dist/lt/asmens.d.ts +2 -3
  410. package/dist/lt/asmens.js +2 -1
  411. package/dist/lt/asmens.js.map +1 -1
  412. package/dist/lt/mod.d.ts +3 -2
  413. package/dist/lt/vat.d.ts +2 -3
  414. package/dist/lt/vat.js +2 -10
  415. package/dist/lt/vat.js.map +1 -1
  416. package/dist/lu/mod.d.ts +3 -2
  417. package/dist/lu/vat.d.ts +2 -3
  418. package/dist/lu/vat.js +2 -8
  419. package/dist/lu/vat.js.map +1 -1
  420. package/dist/luhn.d.ts +2 -3
  421. package/dist/luhn.js +9 -9
  422. package/dist/luhn.js.map +1 -1
  423. package/dist/lv/mod.d.ts +3 -2
  424. package/dist/lv/vat.d.ts +2 -3
  425. package/dist/lv/vat.js +19 -18
  426. package/dist/lv/vat.js.map +1 -1
  427. package/dist/ma/ice.d.ts +2 -3
  428. package/dist/ma/ice.js +2 -11
  429. package/dist/ma/ice.js.map +1 -1
  430. package/dist/ma/mod.d.ts +3 -2
  431. package/dist/mc/mod.d.ts +3 -2
  432. package/dist/mc/tva.d.ts +2 -3
  433. package/dist/mc/tva.js +1 -0
  434. package/dist/mc/tva.js.map +1 -1
  435. package/dist/md/idno.d.ts +2 -3
  436. package/dist/md/idno.js +1 -10
  437. package/dist/md/idno.js.map +1 -1
  438. package/dist/md/mod.d.ts +3 -2
  439. package/dist/me/mod.d.ts +3 -2
  440. package/dist/me/pib.d.ts +2 -3
  441. package/dist/me/pib.js +2 -10
  442. package/dist/me/pib.js.map +1 -1
  443. package/dist/mk/edb.d.ts +2 -3
  444. package/dist/mk/edb.js +2 -11
  445. package/dist/mk/edb.js.map +1 -1
  446. package/dist/mk/mod.d.ts +3 -2
  447. package/dist/mt/mod.d.ts +3 -2
  448. package/dist/mt/vat.d.ts +2 -3
  449. package/dist/mt/vat.js +3 -10
  450. package/dist/mt/vat.js.map +1 -1
  451. package/dist/mu/brn.d.ts +23 -2
  452. package/dist/mu/brn.js +1 -21
  453. package/dist/mu/brn.js.map +1 -1
  454. package/dist/mu/mod.d.ts +3 -2
  455. package/dist/mx/clabe.d.ts +2 -3
  456. package/dist/mx/clabe.js +1 -14
  457. package/dist/mx/clabe.js.map +1 -1
  458. package/dist/mx/curp.d.ts +5 -4
  459. package/dist/mx/curp.js +27 -19
  460. package/dist/mx/curp.js.map +1 -1
  461. package/dist/mx/mod.d.ts +3 -2
  462. package/dist/mx/rfc.d.ts +5 -4
  463. package/dist/mx/rfc.js +23 -20
  464. package/dist/mx/rfc.js.map +1 -1
  465. package/dist/my/mod.d.ts +3 -2
  466. package/dist/my/nric.d.ts +5 -4
  467. package/dist/my/nric.js +18 -16
  468. package/dist/my/nric.js.map +1 -1
  469. package/dist/ng/mod.d.ts +3 -2
  470. package/dist/ng/nin.d.ts +13 -2
  471. package/dist/ng/nin.js +1 -11
  472. package/dist/ng/nin.js.map +1 -1
  473. package/dist/ni/mod.d.ts +3 -2
  474. package/dist/ni/ruc.d.ts +2 -3
  475. package/dist/ni/ruc.js +1 -23
  476. package/dist/ni/ruc.js.map +1 -1
  477. package/dist/nl/bsn.d.ts +2 -3
  478. package/dist/nl/bsn.js +2 -10
  479. package/dist/nl/bsn.js.map +1 -1
  480. package/dist/nl/kvk.d.ts +9 -2
  481. package/dist/nl/kvk.js +1 -7
  482. package/dist/nl/kvk.js.map +1 -1
  483. package/dist/nl/mod.d.ts +3 -2
  484. package/dist/nl/vat.d.ts +2 -3
  485. package/dist/nl/vat.js +4 -50
  486. package/dist/nl/vat.js.map +1 -1
  487. package/dist/no/fodselsnummer.d.ts +2 -3
  488. package/dist/no/fodselsnummer.js +3 -10
  489. package/dist/no/fodselsnummer.js.map +1 -1
  490. package/dist/no/mod.d.ts +3 -2
  491. package/dist/no/mva.d.ts +2 -3
  492. package/dist/no/mva.js +1 -8
  493. package/dist/no/mva.js.map +1 -1
  494. package/dist/no/orgnr.d.ts +2 -3
  495. package/dist/no/orgnr.js +2 -8
  496. package/dist/no/orgnr.js.map +1 -1
  497. package/dist/nz/ird.d.ts +2 -3
  498. package/dist/nz/ird.js +4 -13
  499. package/dist/nz/ird.js.map +1 -1
  500. package/dist/nz/mod.d.ts +3 -2
  501. package/dist/pa/mod.d.ts +3 -2
  502. package/dist/pa/ruc.d.ts +2 -3
  503. package/dist/pa/ruc.js +4 -19
  504. package/dist/pa/ruc.js.map +1 -1
  505. package/dist/patterns.d.ts +8 -10
  506. package/dist/patterns.js +83 -28
  507. package/dist/patterns.js.map +1 -1
  508. package/dist/pe/mod.d.ts +3 -2
  509. package/dist/pe/ruc.d.ts +2 -3
  510. package/dist/pe/ruc.js +10 -24
  511. package/dist/pe/ruc.js.map +1 -1
  512. package/dist/ph/mod.d.ts +3 -2
  513. package/dist/ph/philid.d.ts +14 -2
  514. package/dist/ph/philid.js +1 -12
  515. package/dist/ph/philid.js.map +1 -1
  516. package/dist/pk/cnic.d.ts +14 -2
  517. package/dist/pk/cnic.js +1 -12
  518. package/dist/pk/cnic.js.map +1 -1
  519. package/dist/pk/mod.d.ts +3 -2
  520. package/dist/pl/mod.d.ts +3 -2
  521. package/dist/pl/nip.d.ts +2 -3
  522. package/dist/pl/nip.js +2 -10
  523. package/dist/pl/nip.js.map +1 -1
  524. package/dist/pl/pesel.d.ts +2 -3
  525. package/dist/pl/pesel.js +4 -13
  526. package/dist/pl/pesel.js.map +1 -1
  527. package/dist/pl/regon.d.ts +2 -3
  528. package/dist/pl/regon.js +2 -11
  529. package/dist/pl/regon.js.map +1 -1
  530. package/dist/pt/cc.d.ts +2 -3
  531. package/dist/pt/cc.js +7 -13
  532. package/dist/pt/cc.js.map +1 -1
  533. package/dist/pt/mod.d.ts +3 -2
  534. package/dist/pt/vat.d.ts +2 -3
  535. package/dist/pt/vat.js +3 -11
  536. package/dist/pt/vat.js.map +1 -1
  537. package/dist/ro/cnp.d.ts +2 -3
  538. package/dist/ro/cnp.js +5 -14
  539. package/dist/ro/cnp.js.map +1 -1
  540. package/dist/ro/mod.d.ts +3 -2
  541. package/dist/ro/vat.d.ts +2 -3
  542. package/dist/ro/vat.js +13 -11
  543. package/dist/ro/vat.js.map +1 -1
  544. package/dist/rs/mod.d.ts +3 -2
  545. package/dist/rs/pib.d.ts +2 -3
  546. package/dist/rs/pib.js +1 -9
  547. package/dist/rs/pib.js.map +1 -1
  548. package/dist/ru/inn.d.ts +2 -3
  549. package/dist/ru/inn.js +2 -12
  550. package/dist/ru/inn.js.map +1 -1
  551. package/dist/ru/mod.d.ts +3 -2
  552. package/dist/se/mod.d.ts +3 -2
  553. package/dist/se/orgnr.d.ts +2 -3
  554. package/dist/se/orgnr.js +2 -9
  555. package/dist/se/orgnr.js.map +1 -1
  556. package/dist/se/personnummer.d.ts +2 -3
  557. package/dist/se/personnummer.js +8 -15
  558. package/dist/se/personnummer.js.map +1 -1
  559. package/dist/se/vat.d.ts +2 -3
  560. package/dist/se/vat.js +3 -10
  561. package/dist/se/vat.js.map +1 -1
  562. package/dist/sg/mod.d.ts +3 -2
  563. package/dist/sg/uen.d.ts +2 -3
  564. package/dist/sg/uen.js +47 -70
  565. package/dist/sg/uen.js.map +1 -1
  566. package/dist/si/emso.d.ts +2 -3
  567. package/dist/si/emso.js +12 -14
  568. package/dist/si/emso.js.map +1 -1
  569. package/dist/si/mod.d.ts +3 -2
  570. package/dist/si/vat.d.ts +2 -3
  571. package/dist/si/vat.js +3 -12
  572. package/dist/si/vat.js.map +1 -1
  573. package/dist/sk/dic.d.ts +2 -3
  574. package/dist/sk/dic.js +1 -0
  575. package/dist/sk/dic.js.map +1 -1
  576. package/dist/sk/ico.d.ts +2 -3
  577. package/dist/sk/ico.js +1 -0
  578. package/dist/sk/ico.js.map +1 -1
  579. package/dist/sk/mod.d.ts +3 -2
  580. package/dist/sk/rc.d.ts +4 -5
  581. package/dist/sk/rc.js +6 -2
  582. package/dist/sk/rc.js.map +1 -1
  583. package/dist/th/mod.d.ts +3 -2
  584. package/dist/th/tin.d.ts +2 -3
  585. package/dist/th/tin.js +1 -11
  586. package/dist/th/tin.js.map +1 -1
  587. package/dist/tr/mod.d.ts +3 -2
  588. package/dist/tr/tckimlik.d.ts +2 -3
  589. package/dist/tr/tckimlik.js +1 -20
  590. package/dist/tr/tckimlik.js.map +1 -1
  591. package/dist/tr/vkn.d.ts +2 -3
  592. package/dist/tr/vkn.js +1 -20
  593. package/dist/tr/vkn.js.map +1 -1
  594. package/dist/tw/mod.d.ts +3 -2
  595. package/dist/tw/ubn.d.ts +2 -3
  596. package/dist/tw/ubn.js +2 -12
  597. package/dist/tw/ubn.js.map +1 -1
  598. package/dist/types.d.ts +56 -21
  599. package/dist/ua/edrpou.d.ts +2 -3
  600. package/dist/ua/edrpou.js +5 -12
  601. package/dist/ua/edrpou.js.map +1 -1
  602. package/dist/ua/mod.d.ts +3 -2
  603. package/dist/us/ein.d.ts +12 -2
  604. package/dist/us/ein.js +88 -97
  605. package/dist/us/ein.js.map +1 -1
  606. package/dist/us/itin.d.ts +13 -2
  607. package/dist/us/itin.js +4 -15
  608. package/dist/us/itin.js.map +1 -1
  609. package/dist/us/mod.d.ts +3 -2
  610. package/dist/us/rtn.d.ts +2 -3
  611. package/dist/us/rtn.js +11 -23
  612. package/dist/us/rtn.js.map +1 -1
  613. package/dist/us/ssn.d.ts +13 -2
  614. package/dist/us/ssn.js +1 -11
  615. package/dist/us/ssn.js.map +1 -1
  616. package/dist/uy/mod.d.ts +3 -2
  617. package/dist/uy/rut.d.ts +2 -3
  618. package/dist/uy/rut.js +2 -15
  619. package/dist/uy/rut.js.map +1 -1
  620. package/dist/ve/mod.d.ts +3 -2
  621. package/dist/ve/rif.d.ts +2 -3
  622. package/dist/ve/rif.js +13 -26
  623. package/dist/ve/rif.js.map +1 -1
  624. package/dist/vn/mod.d.ts +3 -2
  625. package/dist/vn/mst.d.ts +2 -3
  626. package/dist/vn/mst.js +1 -12
  627. package/dist/vn/mst.js.map +1 -1
  628. package/dist/za/idnr.d.ts +2 -3
  629. package/dist/za/idnr.js +4 -16
  630. package/dist/za/idnr.js.map +1 -1
  631. package/dist/za/mod.d.ts +3 -2
  632. package/package.json +34 -21
  633. package/src/_checksums/mod1110.ts +1 -1
  634. package/src/_checksums/mod112.ts +7 -6
  635. package/src/_util/generate.ts +38 -0
  636. package/src/ad/nrt.ts +19 -7
  637. package/src/ae/eid.ts +7 -3
  638. package/src/ai/tin.ts +7 -3
  639. package/src/al/nipt.ts +7 -3
  640. package/src/am/tin.ts +7 -3
  641. package/src/ar/cbu.ts +9 -5
  642. package/src/ar/cuit.ts +22 -10
  643. package/src/ar/dni.ts +7 -3
  644. package/src/at/businessid.ts +7 -3
  645. package/src/at/tin.ts +7 -3
  646. package/src/at/uid.ts +7 -3
  647. package/src/at/vnr.ts +62 -12
  648. package/src/au/abn.ts +7 -3
  649. package/src/au/acn.ts +7 -3
  650. package/src/au/tfn.ts +7 -3
  651. package/src/az/voen.ts +9 -3
  652. package/src/ba/jmbg.ts +9 -7
  653. package/src/bd/nid.ts +11 -7
  654. package/src/be/bis.ts +8 -4
  655. package/src/be/nn.ts +7 -3
  656. package/src/be/vat.ts +7 -3
  657. package/src/bg/egn.ts +19 -10
  658. package/src/bg/pnf.ts +7 -3
  659. package/src/bg/vat.ts +8 -3
  660. package/src/bh/cpr.ts +17 -4
  661. package/src/bic.ts +26 -20
  662. package/src/br/cnpj.ts +7 -3
  663. package/src/br/cpf.ts +7 -3
  664. package/src/by/unp.ts +19 -9
  665. package/src/bz/tin.ts +19 -4
  666. package/src/ca/bn.ts +7 -3
  667. package/src/ca/sin.ts +7 -3
  668. package/src/ch/ssn.ts +7 -3
  669. package/src/ch/uid.ts +7 -3
  670. package/src/ch/vat.ts +9 -5
  671. package/src/cl/rut.ts +11 -5
  672. package/src/cn/ric.ts +11 -7
  673. package/src/cn/uscc.ts +27 -11
  674. package/src/co/nit.ts +14 -6
  675. package/src/cr/cpf.ts +11 -6
  676. package/src/creditcard.ts +10 -6
  677. package/src/cu/ni.ts +28 -7
  678. package/src/cy/vat.ts +7 -3
  679. package/src/cz/dic.ts +9 -4
  680. package/src/cz/ico.ts +7 -3
  681. package/src/cz/rc.ts +61 -29
  682. package/src/de/handelsreg.ts +21 -6
  683. package/src/de/idnr.ts +10 -3
  684. package/src/de/stnr.ts +11 -3
  685. package/src/de/svnr.ts +14 -5
  686. package/src/de/vat.ts +7 -3
  687. package/src/dk/cpr.ts +23 -8
  688. package/src/dk/cvr.ts +7 -3
  689. package/src/dk/vat.ts +8 -3
  690. package/src/do/rnc.ts +9 -5
  691. package/src/ec/ruc.ts +9 -5
  692. package/src/ee/ik.ts +21 -10
  693. package/src/ee/registrikood.ts +12 -7
  694. package/src/ee/vat.ts +7 -3
  695. package/src/eg/tn.ts +7 -3
  696. package/src/es/cif.ts +10 -7
  697. package/src/es/dni.ts +7 -3
  698. package/src/es/nie.ts +18 -9
  699. package/src/es/nss.ts +7 -3
  700. package/src/es/vat.ts +13 -5
  701. package/src/eu/vat.ts +55 -6
  702. package/src/fi/hetu.ts +26 -8
  703. package/src/fi/vat.ts +8 -3
  704. package/src/fi/ytunnus.ts +7 -3
  705. package/src/fr/nif.ts +7 -3
  706. package/src/fr/nir.ts +9 -7
  707. package/src/fr/siren.ts +7 -3
  708. package/src/fr/siret.ts +7 -3
  709. package/src/fr/tva.ts +7 -3
  710. package/src/gb/nino.ts +18 -13
  711. package/src/gb/sedol.ts +21 -15
  712. package/src/gb/utr.ts +7 -3
  713. package/src/gb/vat.ts +7 -3
  714. package/src/ge/pin.ts +7 -3
  715. package/src/gh/tin.ts +11 -6
  716. package/src/gr/amka.ts +7 -3
  717. package/src/gr/vat.ts +7 -3
  718. package/src/gt/nit.ts +13 -6
  719. package/src/hk/hkid.ts +9 -4
  720. package/src/hr/vat.ts +7 -3
  721. package/src/hu/vat.ts +8 -3
  722. package/src/iban.ts +7 -3
  723. package/src/id/npwp.ts +7 -3
  724. package/src/ie/pps.ts +7 -3
  725. package/src/ie/vat.ts +7 -3
  726. package/src/il/idnr.ts +7 -3
  727. package/src/in/aadhaar.ts +7 -3
  728. package/src/in/gstin.ts +10 -4
  729. package/src/in/pan.ts +15 -6
  730. package/src/index.ts +6 -0
  731. package/src/iq/nid.ts +7 -3
  732. package/src/ir/nid.ts +7 -3
  733. package/src/is/kennitala.ts +7 -3
  734. package/src/is/vsk.ts +7 -3
  735. package/src/isin.ts +17 -7
  736. package/src/it/codicefiscale.ts +49 -7
  737. package/src/it/iva.ts +7 -3
  738. package/src/jp/cn.ts +7 -3
  739. package/src/jp/mynumber.ts +7 -3
  740. package/src/kr/brn.ts +7 -3
  741. package/src/kr/rrn.ts +27 -8
  742. package/src/kw/civil.ts +31 -14
  743. package/src/kz/iin.ts +9 -8
  744. package/src/lei.ts +7 -3
  745. package/src/li/peid.ts +7 -3
  746. package/src/lk/nic.ts +31 -8
  747. package/src/lt/asmens.ts +8 -4
  748. package/src/lt/vat.ts +8 -3
  749. package/src/lu/vat.ts +8 -3
  750. package/src/luhn.ts +10 -3
  751. package/src/lv/vat.ts +53 -23
  752. package/src/ma/ice.ts +7 -3
  753. package/src/mc/tva.ts +9 -5
  754. package/src/md/idno.ts +7 -3
  755. package/src/me/pib.ts +7 -3
  756. package/src/mk/edb.ts +7 -3
  757. package/src/mt/vat.ts +8 -3
  758. package/src/mu/brn.ts +7 -3
  759. package/src/mx/clabe.ts +7 -3
  760. package/src/mx/curp.ts +47 -10
  761. package/src/mx/rfc.ts +42 -7
  762. package/src/my/nric.ts +33 -8
  763. package/src/ng/nin.ts +7 -3
  764. package/src/ni/ruc.ts +7 -3
  765. package/src/nl/bsn.ts +7 -3
  766. package/src/nl/kvk.ts +7 -3
  767. package/src/nl/vat.ts +18 -69
  768. package/src/no/fodselsnummer.ts +12 -7
  769. package/src/no/mva.ts +9 -5
  770. package/src/no/orgnr.ts +7 -3
  771. package/src/nz/ird.ts +12 -8
  772. package/src/pa/ruc.ts +39 -11
  773. package/src/patterns.ts +184 -46
  774. package/src/pe/ruc.ts +13 -10
  775. package/src/ph/philid.ts +7 -3
  776. package/src/pk/cnic.ts +9 -3
  777. package/src/pl/nip.ts +7 -3
  778. package/src/pl/pesel.ts +9 -7
  779. package/src/pl/regon.ts +7 -3
  780. package/src/pt/cc.ts +13 -7
  781. package/src/pt/vat.ts +8 -3
  782. package/src/ro/cnp.ts +16 -8
  783. package/src/ro/vat.ts +8 -3
  784. package/src/rs/pib.ts +7 -3
  785. package/src/ru/inn.ts +9 -5
  786. package/src/se/orgnr.ts +7 -3
  787. package/src/se/personnummer.ts +35 -32
  788. package/src/se/vat.ts +8 -3
  789. package/src/sg/uen.ts +44 -23
  790. package/src/si/emso.ts +37 -11
  791. package/src/si/vat.ts +8 -3
  792. package/src/sk/dic.ts +8 -4
  793. package/src/sk/ico.ts +3 -2
  794. package/src/sk/rc.ts +17 -4
  795. package/src/th/tin.ts +7 -3
  796. package/src/tr/tckimlik.ts +7 -3
  797. package/src/tr/vkn.ts +7 -3
  798. package/src/tw/ubn.ts +9 -5
  799. package/src/types.ts +69 -7
  800. package/src/ua/edrpou.ts +10 -5
  801. package/src/us/ein.ts +95 -91
  802. package/src/us/itin.ts +14 -11
  803. package/src/us/rtn.ts +32 -19
  804. package/src/us/ssn.ts +7 -3
  805. package/src/uy/rut.ts +9 -5
  806. package/src/ve/rif.ts +19 -12
  807. package/src/vn/mst.ts +7 -3
  808. package/src/za/idnr.ts +9 -7
@@ -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 = {\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 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,14 +1,13 @@
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
-
5
4
  declare const compact: (value: string) => string;
6
5
  declare const validate: (value: string) => ValidateResult;
7
6
  declare const format: (value: string) => string;
8
7
  /** Generate a random valid Swedish VAT number. */
9
8
  declare const generate: () => string;
10
9
  /** Swedish VAT Number. */
11
- declare const vat: Validator;
10
+ declare const vat: CountryValidator<"SE">;
12
11
  //#endregion
13
12
  export { compact, vat as default, format, generate, validate };
14
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/mod.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import uen from "./uen.js";
3
2
 
4
3
  //#region src/sg/mod.d.ts
5
-
4
+ declare namespace mod_d_exports {
5
+ export { uen };
6
+ }
6
7
  //#endregion
7
8
  export { mod_d_exports, uen };
8
9
  //# sourceMappingURL=mod.d.ts.map
package/dist/sg/uen.d.ts CHANGED
@@ -1,14 +1,13 @@
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
-
5
4
  declare const compact: (value: string) => string;
6
5
  declare const validate: (value: string) => ValidateResult;
7
6
  declare const format: (value: string) => string;
8
7
  /** Generate a random valid Singapore UEN (business format). */
9
8
  declare const generate: () => string;
10
9
  /** Singapore Unique Entity Number. */
11
- declare const uen: Validator;
10
+ declare const uen: CountryValidator<"SG">;
12
11
  //#endregion
13
12
  export { compact, uen as default, format, generate, validate };
14
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([
@@ -65,23 +50,23 @@ const compact = (value) => clean(value, " -").toUpperCase();
65
50
  * Validate Business (ROB) UEN (9 chars):
66
51
  * 8 digits + 1 check letter.
67
52
  */
53
+ const BUSINESS_WEIGHTS = [
54
+ 10,
55
+ 4,
56
+ 9,
57
+ 3,
58
+ 8,
59
+ 2,
60
+ 7,
61
+ 1
62
+ ];
63
+ const BUSINESS_CHECK_ALPHA = "XMKECAWLJDB";
68
64
  const validateBusiness = (v) => {
69
65
  if (!isdigits(v.slice(0, 8))) return err("INVALID_FORMAT", "Business UEN must start with 8 digits");
70
66
  if (!/^[A-Z]$/.test(v[8])) return err("INVALID_FORMAT", "Business UEN must end with a letter");
71
- const weights = [
72
- 10,
73
- 4,
74
- 9,
75
- 3,
76
- 8,
77
- 2,
78
- 7,
79
- 1
80
- ];
81
- const checkAlpha = "XMKECAWLJDB";
82
67
  let sum = 0;
83
- for (let i = 0; i < 8; i++) sum += Number(v[i]) * weights[i];
84
- const expected = checkAlpha[sum % 11];
68
+ for (const [i, weight] of BUSINESS_WEIGHTS.entries()) sum += Number(v[i]) * weight;
69
+ const expected = BUSINESS_CHECK_ALPHA[sum % 11];
85
70
  if (v[8] !== expected) return err("INVALID_CHECKSUM", "UEN check letter does not match");
86
71
  return {
87
72
  valid: true,
@@ -92,24 +77,24 @@ const validateBusiness = (v) => {
92
77
  * Validate Local Company (ROC) UEN (10 chars):
93
78
  * 9 digits (year prefix) + 1 check letter.
94
79
  */
80
+ const LOCAL_WEIGHTS = [
81
+ 10,
82
+ 8,
83
+ 6,
84
+ 4,
85
+ 9,
86
+ 7,
87
+ 5,
88
+ 3,
89
+ 1
90
+ ];
91
+ const LOCAL_CHECK_ALPHA = "ZKCMDNERGWH";
95
92
  const validateLocalCompany = (v) => {
96
93
  if (!isdigits(v.slice(0, 9))) return err("INVALID_FORMAT", "Company UEN must have 9 digits");
97
94
  if (!/^[A-Z]$/.test(v[9])) return err("INVALID_FORMAT", "Company UEN must end with a letter");
98
- const weights = [
99
- 10,
100
- 8,
101
- 6,
102
- 4,
103
- 9,
104
- 7,
105
- 5,
106
- 3,
107
- 1
108
- ];
109
- const checkAlpha = "ZKCMDNERGWH";
110
95
  let sum = 0;
111
- for (let i = 0; i < 9; i++) sum += Number(v[i]) * weights[i];
112
- const expected = checkAlpha[sum % 11];
96
+ for (const [i, weight] of LOCAL_WEIGHTS.entries()) sum += Number(v[i]) * weight;
97
+ const expected = LOCAL_CHECK_ALPHA[sum % 11];
113
98
  if (v[9] !== expected) return err("INVALID_CHECKSUM", "UEN check letter does not match");
114
99
  return {
115
100
  valid: true,
@@ -121,6 +106,17 @@ const validateLocalCompany = (v) => {
121
106
  * R/S/T + 2 digits + 2-letter type + 4 digits
122
107
  * + 1 check letter.
123
108
  */
109
+ const OTHER_WEIGHTS = [
110
+ 4,
111
+ 3,
112
+ 5,
113
+ 3,
114
+ 10,
115
+ 2,
116
+ 2,
117
+ 5,
118
+ 7
119
+ ];
124
120
  const validateOther = (v) => {
125
121
  const prefix = v[0];
126
122
  if (prefix !== "R" && prefix !== "S" && prefix !== "T") return err("INVALID_COMPONENT", "Other UEN must start with R, S, or T");
@@ -128,22 +124,13 @@ const validateOther = (v) => {
128
124
  const entityType = v.slice(3, 5);
129
125
  if (!ENTITY_TYPES.has(entityType)) return err("INVALID_COMPONENT", "Unknown entity type: " + entityType);
130
126
  if (!isdigits(v.slice(5, 9))) return err("INVALID_FORMAT", "Other UEN positions 6-9 must be digits");
131
- const weights = [
132
- 4,
133
- 3,
134
- 5,
135
- 3,
136
- 10,
137
- 2,
138
- 2,
139
- 5,
140
- 7
141
- ];
142
127
  let sum = 0;
143
- for (let i = 0; i < 9; i++) {
144
- const idx = OTHER_ALPHA.indexOf(v[i]);
145
- if (idx === -1) return err("INVALID_FORMAT", `Unexpected character at position ${i + 1}: ${v[i]}`);
146
- sum += idx * weights[i];
128
+ for (const [i, weight] of OTHER_WEIGHTS.entries()) {
129
+ const ch = v[i];
130
+ if (ch === void 0) continue;
131
+ const idx = OTHER_ALPHA.indexOf(ch);
132
+ if (idx === -1) return err("INVALID_FORMAT", `Unexpected character at position ${i + 1}: ${ch}`);
133
+ sum += idx * weight;
147
134
  }
148
135
  const expected = OTHER_ALPHA[((sum - 5) % 11 + 11) % 11];
149
136
  if (v[9] !== expected) return err("INVALID_CHECKSUM", "UEN check letter does not match");
@@ -163,21 +150,10 @@ const validate = (value) => {
163
150
  const format = (value) => compact(value);
164
151
  /** Generate a random valid Singapore UEN (business format). */
165
152
  const generate = () => {
166
- const weights = [
167
- 10,
168
- 4,
169
- 9,
170
- 3,
171
- 8,
172
- 2,
173
- 7,
174
- 1
175
- ];
176
- const checkAlpha = "XMKECAWLJDB";
177
153
  const body = randomDigits(8);
178
154
  let sum = 0;
179
- for (let i = 0; i < 8; i++) sum += Number(body[i]) * weights[i];
180
- return body + checkAlpha[sum % 11];
155
+ for (const [i, weight] of BUSINESS_WEIGHTS.entries()) sum += Number(body[i]) * weight;
156
+ return body + BUSINESS_CHECK_ALPHA[sum % 11];
181
157
  };
182
158
  /** Singapore Unique Entity Number. */
183
159
  const uen = {
@@ -186,6 +162,7 @@ const uen = {
186
162
  abbreviation: "UEN",
187
163
  aliases: ["UEN", "Unique Entity Number"],
188
164
  candidatePattern: "[\\dSTR]\\d{7}[A-Z]",
165
+ scope: "country",
189
166
  country: "SG",
190
167
  entityType: "company",
191
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 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 if (!/^[A-Z]$/.test(v[8]!)) {\n return err(\n \"INVALID_FORMAT\",\n \"Business UEN must end with a letter\",\n );\n }\n\n const weights = [10, 4, 9, 3, 8, 2, 7, 1];\n const checkAlpha = \"XMKECAWLJDB\";\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n sum += Number(v[i]) * weights[i]!;\n }\n const expected = checkAlpha[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 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 if (!/^[A-Z]$/.test(v[9]!)) {\n return err(\n \"INVALID_FORMAT\",\n \"Company UEN must end with a letter\",\n );\n }\n\n const weights = [10, 8, 6, 4, 9, 7, 5, 3, 1];\n const checkAlpha = \"ZKCMDNERGWH\";\n let sum = 0;\n for (let i = 0; i < 9; i++) {\n sum += Number(v[i]) * weights[i]!;\n }\n const expected = checkAlpha[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 validateOther = (v: string): ValidateResult => {\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 const weights = [4, 3, 5, 3, 10, 2, 2, 5, 7];\n let sum = 0;\n for (let i = 0; i < 9; i++) {\n const idx = OTHER_ALPHA.indexOf(v[i]!);\n if (idx === -1) {\n return err(\n \"INVALID_FORMAT\",\n `Unexpected character at position ${i + 1}: ${v[i]}`,\n );\n }\n sum += idx * weights[i]!;\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 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 weights = [10, 4, 9, 3, 8, 2, 7, 1];\n const checkAlpha = \"XMKECAWLJDB\";\n const body = randomDigits(8);\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n sum += Number(body[i]) * weights[i]!;\n }\n const check = checkAlpha[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,7 +1,6 @@
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
-
5
4
  declare const compact: (value: string) => string;
6
5
  declare const validate: (value: string) => ValidateResult;
7
6
  declare const format: (value: string) => string;
@@ -13,7 +12,7 @@ declare const parse: (value: string) => ParsedPersonId | null;
13
12
  /** Generate a random valid Slovenian EMSO. */
14
13
  declare const generate: () => string;
15
14
  /** Slovenian Unique Master Citizen Number. */
16
- declare const emso: Validator;
15
+ declare const emso: CountryValidator<"SI", ParsedPersonId>;
17
16
  //#endregion
18
17
  export { compact, emso as default, format, generate, parse, validate };
19
18
  //# sourceMappingURL=emso.d.ts.map
package/dist/si/emso.js CHANGED
@@ -1,20 +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
- * @see https://en.wikipedia.org/wiki/Unique_Master_Citizen_Number
16
- * @see https://www.gov.si/
17
- */
18
8
  const WEIGHTS = [
19
9
  7,
20
10
  6,
@@ -47,6 +37,12 @@ const validate = (value) => {
47
37
  if (yyyy < 900) yyyy += 2e3;
48
38
  else yyyy += 1e3;
49
39
  if (!isValidDate(yyyy, mm, dd)) return err("INVALID_COMPONENT", "EMŠO contains an invalid date");
40
+ const birthDate = new Date(yyyy, mm - 1, dd);
41
+ const today = /* @__PURE__ */ new Date();
42
+ today.setHours(0, 0, 0, 0);
43
+ if (birthDate > today) return err("INVALID_COMPONENT", "EMŠO cannot contain a future birth date");
44
+ const register = Number(v.slice(7, 9));
45
+ if (register < 50 || register > 59) return err("INVALID_COMPONENT", "EMSO register code must be between 50 and 59");
50
46
  if (calcCheckDigit(v) !== Number(v[12])) return err("INVALID_CHECKSUM", "EMŠO check digit does not match");
51
47
  return {
52
48
  valid: true,
@@ -79,7 +75,7 @@ const generate = () => {
79
75
  const dd = String(randomInt(1, 28)).padStart(2, "0");
80
76
  const mm = String(randomInt(1, 12)).padStart(2, "0");
81
77
  const yyy = String(randomInt(900, 999));
82
- const rr = String(randomInt(50, 99));
78
+ const rr = String(randomInt(50, 59));
83
79
  const sss = String(randomInt(0, 999)).padStart(3, "0");
84
80
  const partial = dd + mm + yyy + rr + sss;
85
81
  const c = partial + String(calcCheckDigit(partial));
@@ -93,12 +89,14 @@ const emso = {
93
89
  abbreviation: "EMŠO",
94
90
  aliases: ["EMŠO", "enotna matična številka občana"],
95
91
  candidatePattern: "\\d{13}",
92
+ scope: "country",
96
93
  country: "SI",
97
94
  entityType: "person",
98
- sourceUrl: "https://www.gov.si/",
95
+ sourceUrl: "https://www.gov.si/teme/registri-in-evidence-prebivalstva/",
99
96
  examples: ["0101006500006"],
100
97
  compact,
101
98
  format,
99
+ parse,
102
100
  validate,
103
101
  generate
104
102
  };
@@ -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 * @see https://en.wikipedia.org/wiki/Unique_Master_Citizen_Number\n * @see https://www.gov.si/\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\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, 99));\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 = {\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: \"https://www.gov.si/\",\n examples: [\"0101006500006\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default emso;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,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;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,OAAkB;CACtB,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,QACA,iCACD;CACD,kBAAkB;CAClB,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,gBAAgB;CAC3B;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/mod.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
1
  import emso from "./emso.js";
3
2
  import vat from "./vat.js";
4
3
 
5
4
  //#region src/si/mod.d.ts
6
-
5
+ declare namespace mod_d_exports {
6
+ export { emso, vat };
7
+ }
7
8
  //#endregion
8
9
  export { emso, mod_d_exports, vat };
9
10
  //# sourceMappingURL=mod.d.ts.map
package/dist/si/vat.d.ts CHANGED
@@ -1,14 +1,13 @@
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
-
5
4
  declare const compact: (value: string) => string;
6
5
  declare const validate: (value: string) => ValidateResult;
7
6
  declare const format: (value: string) => string;
8
7
  /** Generate a random valid Slovenian VAT number. */
9
8
  declare const generate: () => string;
10
9
  /** Slovenian VAT Number. */
11
- declare const vat: Validator;
10
+ declare const vat: CountryValidator<"SI">;
12
11
  //#endregion
13
12
  export { compact, vat as default, format, generate, validate };
14
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,14 +1,13 @@
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
-
5
4
  declare const compact: (value: string) => string;
6
5
  declare const validate: (value: string) => ValidateResult;
7
6
  declare const format: (value: string) => string;
8
7
  /** Generate a random valid Slovak DIČ. */
9
8
  declare const generate: () => string;
10
9
  /** Slovak VAT Number. */
11
- declare const dic: Validator;
10
+ declare const dic: CountryValidator<"SK">;
12
11
  //#endregion
13
12
  export { compact, dic as default, format, generate, validate };
14
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/",