@stll/stdnum 2.0.1 → 2.1.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 (173) hide show
  1. package/README.md +11 -9
  2. package/dist/_checksums/keccak.d.ts +5 -0
  3. package/dist/_checksums/keccak.js +118 -0
  4. package/dist/_checksums/keccak.js.map +1 -0
  5. package/dist/_checksums/mod112.js.map +1 -1
  6. package/dist/_checksums/sha256.d.ts +5 -0
  7. package/dist/_checksums/sha256.js +164 -0
  8. package/dist/_checksums/sha256.js.map +1 -0
  9. package/dist/_checksums/verhoeff.js.map +1 -1
  10. package/dist/_util/arabic.js.map +1 -1
  11. package/dist/_util/clean.js.map +1 -1
  12. package/dist/_util/date.js.map +1 -1
  13. package/dist/ad/nrt.js.map +1 -1
  14. package/dist/ae/eid.js.map +1 -1
  15. package/dist/ai/tin.js.map +1 -1
  16. package/dist/al/nipt.js.map +1 -1
  17. package/dist/am/tin.js.map +1 -1
  18. package/dist/ar/cbu.js.map +1 -1
  19. package/dist/ar/cuit.js.map +1 -1
  20. package/dist/ar/dni.js.map +1 -1
  21. package/dist/at/businessid.js.map +1 -1
  22. package/dist/at/vnr.js.map +1 -1
  23. package/dist/au/abn.js.map +1 -1
  24. package/dist/au/tfn.js.map +1 -1
  25. package/dist/az/voen.js.map +1 -1
  26. package/dist/ba/jmbg.js.map +1 -1
  27. package/dist/be/bis.js.map +1 -1
  28. package/dist/be/nn.js.map +1 -1
  29. package/dist/be/vat.js.map +1 -1
  30. package/dist/bg/egn.js.map +1 -1
  31. package/dist/bg/vat.js.map +1 -1
  32. package/dist/bh/cpr.js.map +1 -1
  33. package/dist/bic.js.map +1 -1
  34. package/dist/br/cnpj.js.map +1 -1
  35. package/dist/br/cpf.js.map +1 -1
  36. package/dist/by/unp.js.map +1 -1
  37. package/dist/bz/tin.js.map +1 -1
  38. package/dist/ch/uid.js.map +1 -1
  39. package/dist/ch/vat.js.map +1 -1
  40. package/dist/cl/rut.js.map +1 -1
  41. package/dist/cn/ric.js.map +1 -1
  42. package/dist/cn/uscc.js.map +1 -1
  43. package/dist/cr/cpf.js.map +1 -1
  44. package/dist/crypto/btcbase58.d.ts +11 -0
  45. package/dist/crypto/btcbase58.js +76 -0
  46. package/dist/crypto/btcbase58.js.map +1 -0
  47. package/dist/crypto/btcbech32.d.ts +19 -0
  48. package/dist/crypto/btcbech32.js +145 -0
  49. package/dist/crypto/btcbech32.js.map +1 -0
  50. package/dist/crypto/eth.d.ts +11 -0
  51. package/dist/crypto/eth.js +63 -0
  52. package/dist/crypto/eth.js.map +1 -0
  53. package/dist/crypto/mod.d.ts +12 -0
  54. package/dist/crypto/mod.js +16 -0
  55. package/dist/crypto/mod.js.map +1 -0
  56. package/dist/crypto/wallet.d.ts +10 -0
  57. package/dist/crypto/wallet.js +55 -0
  58. package/dist/crypto/wallet.js.map +1 -0
  59. package/dist/cu/ni.js.map +1 -1
  60. package/dist/cz/rc.js.map +1 -1
  61. package/dist/de/handelsreg.js.map +1 -1
  62. package/dist/de/idnr.js.map +1 -1
  63. package/dist/de/stnr.js.map +1 -1
  64. package/dist/de/svnr.js.map +1 -1
  65. package/dist/dk/cpr.js.map +1 -1
  66. package/dist/dk/cvr.js.map +1 -1
  67. package/dist/dk/vat.js.map +1 -1
  68. package/dist/do/rnc.js.map +1 -1
  69. package/dist/ec/ruc.js.map +1 -1
  70. package/dist/ee/ik.js.map +1 -1
  71. package/dist/ee/vat.js.map +1 -1
  72. package/dist/eg/tn.js.map +1 -1
  73. package/dist/es/dni.js.map +1 -1
  74. package/dist/es/nie.js.map +1 -1
  75. package/dist/es/nss.js.map +1 -1
  76. package/dist/eu/vat.js.map +1 -1
  77. package/dist/fi/hetu.js.map +1 -1
  78. package/dist/fi/vat.js.map +1 -1
  79. package/dist/fi/ytunnus.js.map +1 -1
  80. package/dist/fr/nif.js.map +1 -1
  81. package/dist/fr/nir.js.map +1 -1
  82. package/dist/fr/tva.js.map +1 -1
  83. package/dist/gb/mod.d.ts +3 -2
  84. package/dist/gb/mod.js +3 -1
  85. package/dist/gb/mod.js.map +1 -1
  86. package/dist/gb/nhs.d.ts +11 -0
  87. package/dist/gb/nhs.js +51 -0
  88. package/dist/gb/nhs.js.map +1 -0
  89. package/dist/gb/nino.js.map +1 -1
  90. package/dist/gb/sedol.js.map +1 -1
  91. package/dist/gb/utr.js.map +1 -1
  92. package/dist/gb/vat.js.map +1 -1
  93. package/dist/ge/pin.js.map +1 -1
  94. package/dist/gh/tin.js.map +1 -1
  95. package/dist/gr/amka.js.map +1 -1
  96. package/dist/gt/nit.js.map +1 -1
  97. package/dist/hk/hkid.js.map +1 -1
  98. package/dist/hu/vat.js.map +1 -1
  99. package/dist/iban.js.map +1 -1
  100. package/dist/id/npwp.js.map +1 -1
  101. package/dist/ie/pps.js.map +1 -1
  102. package/dist/ie/vat.js.map +1 -1
  103. package/dist/il/idnr.js.map +1 -1
  104. package/dist/in/aadhaar.js.map +1 -1
  105. package/dist/in/gstin.js.map +1 -1
  106. package/dist/in/pan.js.map +1 -1
  107. package/dist/index.d.ts +76 -75
  108. package/dist/index.js +2 -1
  109. package/dist/ir/nid.js.map +1 -1
  110. package/dist/is/kennitala.js.map +1 -1
  111. package/dist/isin.js.map +1 -1
  112. package/dist/it/codicefiscale.js.map +1 -1
  113. package/dist/it/iva.js.map +1 -1
  114. package/dist/kr/rrn.js.map +1 -1
  115. package/dist/kw/civil.js.map +1 -1
  116. package/dist/kz/iin.js.map +1 -1
  117. package/dist/lei.js.map +1 -1
  118. package/dist/li/peid.js.map +1 -1
  119. package/dist/lk/nic.js.map +1 -1
  120. package/dist/lt/asmens.js.map +1 -1
  121. package/dist/lt/vat.js.map +1 -1
  122. package/dist/lu/vat.js.map +1 -1
  123. package/dist/lv/vat.js.map +1 -1
  124. package/dist/ma/ice.js.map +1 -1
  125. package/dist/mc/tva.js.map +1 -1
  126. package/dist/mt/vat.js.map +1 -1
  127. package/dist/mu/brn.js.map +1 -1
  128. package/dist/mx/clabe.js.map +1 -1
  129. package/dist/mx/curp.js.map +1 -1
  130. package/dist/mx/rfc.js.map +1 -1
  131. package/dist/my/nric.js.map +1 -1
  132. package/dist/ni/ruc.js.map +1 -1
  133. package/dist/nl/bsn.js.map +1 -1
  134. package/dist/nl/vat.js.map +1 -1
  135. package/dist/no/fodselsnummer.js.map +1 -1
  136. package/dist/no/mva.js.map +1 -1
  137. package/dist/no/orgnr.js.map +1 -1
  138. package/dist/nz/ird.js.map +1 -1
  139. package/dist/pa/ruc.js.map +1 -1
  140. package/dist/patterns.js.map +1 -1
  141. package/dist/pe/ruc.js.map +1 -1
  142. package/dist/pl/pesel.js.map +1 -1
  143. package/dist/pl/regon.js.map +1 -1
  144. package/dist/pt/cc.js.map +1 -1
  145. package/dist/ro/cnp.js.map +1 -1
  146. package/dist/ro/vat.js.map +1 -1
  147. package/dist/rs/pib.js.map +1 -1
  148. package/dist/ru/inn.js.map +1 -1
  149. package/dist/se/personnummer.js.map +1 -1
  150. package/dist/sg/uen.js.map +1 -1
  151. package/dist/si/emso.js.map +1 -1
  152. package/dist/si/vat.js.map +1 -1
  153. package/dist/sk/dic.js.map +1 -1
  154. package/dist/tw/ubn.js.map +1 -1
  155. package/dist/ua/edrpou.js.map +1 -1
  156. package/dist/us/itin.js.map +1 -1
  157. package/dist/us/rtn.js.map +1 -1
  158. package/dist/us/ssn.js.map +1 -1
  159. package/dist/uy/rut.js.map +1 -1
  160. package/dist/ve/rif.js.map +1 -1
  161. package/dist/vn/mst.js.map +1 -1
  162. package/dist/za/idnr.js.map +1 -1
  163. package/package.json +31 -6
  164. package/src/_checksums/keccak.ts +145 -0
  165. package/src/_checksums/sha256.ts +125 -0
  166. package/src/crypto/btcbase58.ts +144 -0
  167. package/src/crypto/btcbech32.ts +210 -0
  168. package/src/crypto/eth.ts +114 -0
  169. package/src/crypto/mod.ts +4 -0
  170. package/src/crypto/wallet.ts +67 -0
  171. package/src/gb/mod.ts +1 -0
  172. package/src/gb/nhs.ts +92 -0
  173. package/src/index.ts +1 -0
@@ -1 +1 @@
1
- {"version":3,"file":"dni.js","names":[],"sources":["../../src/ar/dni.ts"],"sourcesContent":["/** Generate a random valid Argentine DNI. */\nconst generate = (): string => randomDigits(8);\n\n/**\n * DNI (Documento Nacional de Identidad).\n *\n * Argentine national identity card number. The DNI is\n * a 7 or 8-digit number assigned to all Argentine\n * citizens and permanent residents. No check digit.\n *\n * @see https://en.wikipedia.org/wiki/Documento_Nacional_de_Identidad_(Argentina)\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" -.\").trim();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length < 7 || v.length > 8) {\n return err(\n \"INVALID_LENGTH\",\n \"DNI must be 7 or 8 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"DNI must contain only digits\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 8) {\n return `${v.slice(0, 2)}.${v.slice(2, 5)}.${v.slice(5)}`;\n }\n if (v.length === 7) {\n return `${v.slice(0, 1)}.${v.slice(1, 4)}.${v.slice(4)}`;\n }\n return v;\n};\n\n/** Argentine National Identity Document. */\nconst dni: CountryValidator<\"AR\"> = {\n name: \"Argentine Identity Card\",\n localName: \"Documento Nacional de Identidad\",\n abbreviation: \"DNI\",\n aliases: [\n \"DNI\",\n \"Documento Nacional de Identidad\",\n \"Documento de Identidad\",\n ] as const,\n candidatePattern: \"\\\\d{1,2}\\\\.?\\\\d{3}\\\\.?\\\\d{3}\",\n scope: \"country\",\n country: \"AR\",\n entityType: \"person\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/Documento_Nacional_de_Identidad_(Argentina)\",\n lengths: [7, 8] as const,\n examples: [\"20123456\", \"12345678\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default dni;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AACA,MAAM,iBAAyB,aAAa,CAAC;AAsB7C,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,EAAE,KAAK;AAE3B,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,SAAS,KAAK,EAAE,SAAS,GAC7B,OAAO,IACL,kBACA,2BACF;CAGF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAEvD,IAAI,EAAE,WAAW,GACf,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAEvD,OAAO;AACT;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WACE;CACF,SAAS,CAAC,GAAG,CAAC;CACd,UAAU,CAAC,YAAY,UAAU;CACjC;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"dni.js","names":[],"sources":["../../src/ar/dni.ts"],"sourcesContent":["/** Generate a random valid Argentine DNI. */\nconst generate = (): string => randomDigits(8);\n\n/**\n * DNI (Documento Nacional de Identidad).\n *\n * Argentine national identity card number. The DNI is\n * a 7 or 8-digit number assigned to all Argentine\n * citizens and permanent residents. No check digit.\n *\n * @see https://en.wikipedia.org/wiki/Documento_Nacional_de_Identidad_(Argentina)\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" -.\").trim();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length < 7 || v.length > 8) {\n return err(\n \"INVALID_LENGTH\",\n \"DNI must be 7 or 8 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"DNI must contain only digits\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 8) {\n return `${v.slice(0, 2)}.${v.slice(2, 5)}.${v.slice(5)}`;\n }\n if (v.length === 7) {\n return `${v.slice(0, 1)}.${v.slice(1, 4)}.${v.slice(4)}`;\n }\n return v;\n};\n\n/** Argentine National Identity Document. */\nconst dni: CountryValidator<\"AR\"> = {\n name: \"Argentine Identity Card\",\n localName: \"Documento Nacional de Identidad\",\n abbreviation: \"DNI\",\n aliases: [\n \"DNI\",\n \"Documento Nacional de Identidad\",\n \"Documento de Identidad\",\n ] as const,\n candidatePattern: \"\\\\d{1,2}\\\\.?\\\\d{3}\\\\.?\\\\d{3}\",\n scope: \"country\",\n country: \"AR\",\n entityType: \"person\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/Documento_Nacional_de_Identidad_(Argentina)\",\n lengths: [7, 8] as const,\n examples: [\"20123456\", \"12345678\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default dni;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AACA,MAAM,iBAAyB,aAAa,CAAC;AAsB7C,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,CAAC,CAAC,KAAK;AAE3B,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,SAAS,KAAK,EAAE,SAAS,GAC7B,OAAO,IACL,kBACA,2BACF;CAGF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAEvD,IAAI,EAAE,WAAW,GACf,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAEvD,OAAO;AACT;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WACE;CACF,SAAS,CAAC,GAAG,CAAC;CACd,UAAU,CAAC,YAAY,UAAU;CACjC;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"businessid.js","names":[],"sources":["../../src/at/businessid.ts"],"sourcesContent":["/** Generate a random valid Austrian Firmenbuchnummer. */\nconst generate = (): string => {\n const digits = randomDigits(randomInt(5, 6));\n const letter = String.fromCodePoint(\n 97 + randomInt(0, 25),\n ); // a-z (compact lowercases)\n return `${digits}${letter}`;\n};\n\n/**\n * Firmenbuchnummer (Austrian company register number).\n *\n * Digits followed by a single trailing letter.\n * Optional \"FN\" prefix. No checksum.\n *\n * @see https://www.justiz.gv.at/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst FN_RE = /^\\d+[a-z]$/i;\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.slice(0, 2).toUpperCase() === \"FN\") {\n v = v.slice(2);\n }\n return v.toLowerCase();\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length < 2) {\n return err(\n \"INVALID_LENGTH\",\n \"Austrian Firmenbuchnummer is too short\",\n );\n }\n if (!FN_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Austrian Firmenbuchnummer must be digits\" +\n \" followed by a letter\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `FN ${compact(value)}`;\n\n/** Austrian Company Register Number. */\nconst businessid: CountryValidator<\"AT\"> = {\n name: \"Austrian Company Register Number\",\n localName: \"Firmenbuchnummer\",\n abbreviation: \"FN\",\n aliases: [\"Firmenbuchnummer\", \"FN\", \"FBN\"] as const,\n candidatePattern: \"FN\\\\s?\\\\d{5,6}[a-z]?\",\n scope: \"country\",\n country: \"AT\",\n entityType: \"company\",\n sourceUrl: \"https://www.justiz.gv.at/\",\n examples: [\"122119m\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default businessid;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AACA,MAAM,iBAAyB;CAK7B,OAAO,GAJQ,aAAa,UAAU,GAAG,CAAC,CAI3B,IAHA,OAAO,cACpB,KAAK,UAAU,GAAG,EAAE,CAEE;AAC1B;AAoBA,MAAM,QAAQ;AAEd,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,MAAM;CAC3B,IAAI,EAAE,MAAM,GAAG,CAAC,EAAE,YAAY,MAAM,MAClC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO,EAAE,YAAY;AACvB;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,SAAS,GACb,OAAO,IACL,kBACA,wCACF;CAEF,IAAI,CAAC,MAAM,KAAK,CAAC,GACf,OAAO,IACL,kBACA,+DAEF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,MAAM,QAAQ,KAAK;;AAGrB,MAAM,aAAqC;CACzC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EAAC;EAAoB;EAAM;CAAK;CACzC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,SAAS;CACpB;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"businessid.js","names":[],"sources":["../../src/at/businessid.ts"],"sourcesContent":["/** Generate a random valid Austrian Firmenbuchnummer. */\nconst generate = (): string => {\n const digits = randomDigits(randomInt(5, 6));\n const letter = String.fromCodePoint(\n 97 + randomInt(0, 25),\n ); // a-z (compact lowercases)\n return `${digits}${letter}`;\n};\n\n/**\n * Firmenbuchnummer (Austrian company register number).\n *\n * Digits followed by a single trailing letter.\n * Optional \"FN\" prefix. No checksum.\n *\n * @see https://www.justiz.gv.at/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst FN_RE = /^\\d+[a-z]$/i;\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.slice(0, 2).toUpperCase() === \"FN\") {\n v = v.slice(2);\n }\n return v.toLowerCase();\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length < 2) {\n return err(\n \"INVALID_LENGTH\",\n \"Austrian Firmenbuchnummer is too short\",\n );\n }\n if (!FN_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Austrian Firmenbuchnummer must be digits\" +\n \" followed by a letter\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `FN ${compact(value)}`;\n\n/** Austrian Company Register Number. */\nconst businessid: CountryValidator<\"AT\"> = {\n name: \"Austrian Company Register Number\",\n localName: \"Firmenbuchnummer\",\n abbreviation: \"FN\",\n aliases: [\"Firmenbuchnummer\", \"FN\", \"FBN\"] as const,\n candidatePattern: \"FN\\\\s?\\\\d{5,6}[a-z]?\",\n scope: \"country\",\n country: \"AT\",\n entityType: \"company\",\n sourceUrl: \"https://www.justiz.gv.at/\",\n examples: [\"122119m\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default businessid;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AACA,MAAM,iBAAyB;CAK7B,OAAO,GAJQ,aAAa,UAAU,GAAG,CAAC,CAI3B,IAHA,OAAO,cACpB,KAAK,UAAU,GAAG,EAAE,CAEE;AAC1B;AAoBA,MAAM,QAAQ;AAEd,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,MAAM;CAC3B,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY,MAAM,MAClC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO,EAAE,YAAY;AACvB;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,SAAS,GACb,OAAO,IACL,kBACA,wCACF;CAEF,IAAI,CAAC,MAAM,KAAK,CAAC,GACf,OAAO,IACL,kBACA,+DAEF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,MAAM,QAAQ,KAAK;;AAGrB,MAAM,aAAqC;CACzC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EAAC;EAAoB;EAAM;CAAK;CACzC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,SAAS;CACpB;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"vnr.js","names":[],"sources":["../../src/at/vnr.ts"],"sourcesContent":["/**\n * VNR (Versicherungsnummer).\n *\n * Austrian social insurance number. 10 digits: 3-digit\n * serial + 1 check digit + 6-digit birth date (DDMMYY).\n * The check digit is computed using a weighted sum\n * mod 11 over the 9 non-check digits.\n *\n * The 6-digit \"birth date\" field is not always a real\n * calendar date. Sozialversicherung.at documents that\n * persons with unknown date of birth are issued\n * substitute values (01.01. or 01.07.), and that\n * months 13, 14, etc. are issued when the daily serial\n * pool for a given substitute date is exhausted. We\n * therefore do not enforce a calendar-valid month here.\n * The day field, however, is always within 01-31 — even\n * in the documented overflow cases the day stays \"01\"\n * — so we keep the day-bounds check.\n *\n * @see https://de.wikipedia.org/wiki/Sozialversicherungsnummer#%C3%96sterreich\n * @see https://www.sozialversicherung.at/cdscontent/?contentid=10007.820902&viewmode=content\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/**\n * Weights for the 9 non-check digits (positions\n * 0,1,2, then 4,5,6,7,8,9). Check digit is at\n * position 3 and equals the weighted sum mod 11.\n */\nconst WEIGHTS = [3, 7, 9, 5, 8, 4, 2, 1, 6] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -/\").trim();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Austrian VNR must be 10 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Austrian VNR must contain only digits\",\n );\n }\n\n // Per sozialversicherung.at, the 3-digit serial\n // (positions 0-2) never starts with zero.\n if (v[0] === \"0\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Austrian VNR serial must not start with zero\",\n );\n }\n\n // Day (positions 4-5) is always within 01-31, even\n // in the documented substitute and overflow cases\n // where the month is shifted. The month is left\n // unchecked per the source.\n const day = Number(v.slice(4, 6));\n if (day < 1 || day > 31) {\n return err(\n \"INVALID_COMPONENT\",\n \"Austrian VNR day field must be within 01-31\",\n );\n }\n\n // Check digit at position 3: weighted sum of the\n // other 9 digits mod 11. If remainder is 10 the\n // number is invalid.\n const digits = v.slice(0, 3) + v.slice(4);\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n sum += Number(digits[i]) * weight;\n }\n const check = sum % 11;\n if (check === 10) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Austrian VNR check digit is invalid (mod 11 \" +\n \"remainder is 10)\",\n );\n }\n if (check !== Number(v[3])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Austrian VNR check digit mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 4)} ${v.slice(4, 6)}${v.slice(6, 8)}${v.slice(8)}`;\n};\n\n/** Generate a random valid Austrian VNR. */\nconst generate = (): string => {\n for (;;) {\n // Serial must not start with zero (see validate).\n const serial =\n String(randomInt(1, 9)) + randomDigits(2);\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const year = String(randomInt(0, 99)).padStart(2, \"0\");\n const digits = `${serial}${day}${month}${year}`;\n\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n sum += Number(digits[i]) * weight;\n }\n\n const check = sum % 11;\n if (check === 10) continue;\n return `${serial}${String(check)}${day}${month}${year}`;\n }\n};\n\n/** Austrian Social Insurance Number. */\nconst vnr: CountryValidator<\"AT\"> = {\n name: \"Austrian Social Insurance Number\",\n localName: \"Versicherungsnummer\",\n abbreviation: \"VNR\",\n aliases: [\n \"VNR\",\n \"SVNR\",\n \"Versicherungsnummer\",\n \"Sozialversicherungsnummer\",\n ] as const,\n candidatePattern: \"\\\\d{4}\\\\s?\\\\d{6}\",\n scope: \"country\",\n country: \"AT\",\n entityType: \"person\",\n sourceUrl:\n \"https://de.wikipedia.org/wiki/Sozialversicherungsnummer\",\n lengths: [10] as const,\n examples: [\"1237010180\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vnr;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;;AAsCA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAE1C,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,EAAE,KAAK;AAE3B,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,gCACF;CAGF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,uCACF;CAKF,IAAI,EAAE,OAAO,KACX,OAAO,IACL,qBACA,8CACF;CAOF,MAAM,MAAM,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAChC,IAAI,MAAM,KAAK,MAAM,IACnB,OAAO,IACL,qBACA,6CACF;CAMF,MAAM,SAAS,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;CACxC,IAAI,MAAM;CACV,KAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,QAAQ,GACxC,OAAO,OAAO,OAAO,EAAE,IAAI;CAE7B,MAAM,QAAQ,MAAM;CACpB,IAAI,UAAU,IACZ,OAAO,IACL,oBACA,8DAEF;CAEF,IAAI,UAAU,OAAO,EAAE,EAAE,GACvB,OAAO,IACL,oBACA,mCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;AACtE;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EAEP,MAAM,SACJ,OAAO,UAAU,GAAG,CAAC,CAAC,IAAI,aAAa,CAAC;EAC1C,MAAM,MAAM,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACpD,MAAM,QAAQ,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACtD,MAAM,OAAO,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACrD,MAAM,SAAS,GAAG,SAAS,MAAM,QAAQ;EAEzC,IAAI,MAAM;EACV,KAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,QAAQ,GACxC,OAAO,OAAO,OAAO,EAAE,IAAI;EAG7B,MAAM,QAAQ,MAAM;EACpB,IAAI,UAAU,IAAI;EAClB,OAAO,GAAG,SAAS,OAAO,KAAK,IAAI,MAAM,QAAQ;CACnD;AACF;;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,WACE;CACF,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"vnr.js","names":[],"sources":["../../src/at/vnr.ts"],"sourcesContent":["/**\n * VNR (Versicherungsnummer).\n *\n * Austrian social insurance number. 10 digits: 3-digit\n * serial + 1 check digit + 6-digit birth date (DDMMYY).\n * The check digit is computed using a weighted sum\n * mod 11 over the 9 non-check digits.\n *\n * The 6-digit \"birth date\" field is not always a real\n * calendar date. Sozialversicherung.at documents that\n * persons with unknown date of birth are issued\n * substitute values (01.01. or 01.07.), and that\n * months 13, 14, etc. are issued when the daily serial\n * pool for a given substitute date is exhausted. We\n * therefore do not enforce a calendar-valid month here.\n * The day field, however, is always within 01-31 — even\n * in the documented overflow cases the day stays \"01\"\n * — so we keep the day-bounds check.\n *\n * @see https://de.wikipedia.org/wiki/Sozialversicherungsnummer#%C3%96sterreich\n * @see https://www.sozialversicherung.at/cdscontent/?contentid=10007.820902&viewmode=content\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/**\n * Weights for the 9 non-check digits (positions\n * 0,1,2, then 4,5,6,7,8,9). Check digit is at\n * position 3 and equals the weighted sum mod 11.\n */\nconst WEIGHTS = [3, 7, 9, 5, 8, 4, 2, 1, 6] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -/\").trim();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Austrian VNR must be 10 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Austrian VNR must contain only digits\",\n );\n }\n\n // Per sozialversicherung.at, the 3-digit serial\n // (positions 0-2) never starts with zero.\n if (v[0] === \"0\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Austrian VNR serial must not start with zero\",\n );\n }\n\n // Day (positions 4-5) is always within 01-31, even\n // in the documented substitute and overflow cases\n // where the month is shifted. The month is left\n // unchecked per the source.\n const day = Number(v.slice(4, 6));\n if (day < 1 || day > 31) {\n return err(\n \"INVALID_COMPONENT\",\n \"Austrian VNR day field must be within 01-31\",\n );\n }\n\n // Check digit at position 3: weighted sum of the\n // other 9 digits mod 11. If remainder is 10 the\n // number is invalid.\n const digits = v.slice(0, 3) + v.slice(4);\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n sum += Number(digits[i]) * weight;\n }\n const check = sum % 11;\n if (check === 10) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Austrian VNR check digit is invalid (mod 11 \" +\n \"remainder is 10)\",\n );\n }\n if (check !== Number(v[3])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Austrian VNR check digit mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 4)} ${v.slice(4, 6)}${v.slice(6, 8)}${v.slice(8)}`;\n};\n\n/** Generate a random valid Austrian VNR. */\nconst generate = (): string => {\n for (;;) {\n // Serial must not start with zero (see validate).\n const serial =\n String(randomInt(1, 9)) + randomDigits(2);\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const year = String(randomInt(0, 99)).padStart(2, \"0\");\n const digits = `${serial}${day}${month}${year}`;\n\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n sum += Number(digits[i]) * weight;\n }\n\n const check = sum % 11;\n if (check === 10) continue;\n return `${serial}${String(check)}${day}${month}${year}`;\n }\n};\n\n/** Austrian Social Insurance Number. */\nconst vnr: CountryValidator<\"AT\"> = {\n name: \"Austrian Social Insurance Number\",\n localName: \"Versicherungsnummer\",\n abbreviation: \"VNR\",\n aliases: [\n \"VNR\",\n \"SVNR\",\n \"Versicherungsnummer\",\n \"Sozialversicherungsnummer\",\n ] as const,\n candidatePattern: \"\\\\d{4}\\\\s?\\\\d{6}\",\n scope: \"country\",\n country: \"AT\",\n entityType: \"person\",\n sourceUrl:\n \"https://de.wikipedia.org/wiki/Sozialversicherungsnummer\",\n lengths: [10] as const,\n examples: [\"1237010180\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vnr;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;;AAsCA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAE1C,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,CAAC,CAAC,KAAK;AAE3B,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,gCACF;CAGF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,uCACF;CAKF,IAAI,EAAE,OAAO,KACX,OAAO,IACL,qBACA,8CACF;CAOF,MAAM,MAAM,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAChC,IAAI,MAAM,KAAK,MAAM,IACnB,OAAO,IACL,qBACA,6CACF;CAMF,MAAM,SAAS,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;CACxC,IAAI,MAAM;CACV,KAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,QAAQ,GACxC,OAAO,OAAO,OAAO,EAAE,IAAI;CAE7B,MAAM,QAAQ,MAAM;CACpB,IAAI,UAAU,IACZ,OAAO,IACL,oBACA,8DAEF;CAEF,IAAI,UAAU,OAAO,EAAE,EAAE,GACvB,OAAO,IACL,oBACA,mCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;AACtE;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EAEP,MAAM,SACJ,OAAO,UAAU,GAAG,CAAC,CAAC,IAAI,aAAa,CAAC;EAC1C,MAAM,MAAM,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACpD,MAAM,QAAQ,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACtD,MAAM,OAAO,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACrD,MAAM,SAAS,GAAG,SAAS,MAAM,QAAQ;EAEzC,IAAI,MAAM;EACV,KAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,QAAQ,GACxC,OAAO,OAAO,OAAO,EAAE,IAAI;EAG7B,MAAM,QAAQ,MAAM;EACpB,IAAI,UAAU,IAAI;EAClB,OAAO,GAAG,SAAS,OAAO,KAAK,IAAI,MAAM,QAAQ;CACnD;AACF;;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,WACE;CACF,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"abn.js","names":[],"sources":["../../src/au/abn.ts"],"sourcesContent":["/**\n * ABN (Australian Business Number).\n *\n * 11-digit identifier. Subtract 1 from the first\n * digit, then apply weights [10,1,3,5,7,9,11,13,\n * 15,17,19]; sum mod 89 must equal 0.\n *\n * @see https://en.wikipedia.org/wiki/Australian_Business_Number\n * @see https://abr.business.gov.au/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [\n 10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19,\n] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"ABN must contain only digits\",\n );\n }\n if (v.length !== 11) {\n return err(\"INVALID_LENGTH\", \"ABN must be 11 digits\");\n }\n\n let sum = 0;\n for (let i = 0; i < 11; i++) {\n let d = Number(v.charAt(i));\n if (i === 0) d -= 1;\n sum += d * (WEIGHTS[i] ?? 0);\n }\n if (sum % 89 !== 0) {\n return err(\"INVALID_CHECKSUM\", \"ABN checksum mismatch\");\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 11) {\n return `${v.slice(0, 2)} ${v.slice(2, 5)} ${v.slice(5, 8)} ${v.slice(8)}`;\n }\n return v;\n};\n\n/** Generate a random valid ABN. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(11);\n if (validate(c).valid) return c;\n }\n};\n\n/** Australian Business Number. */\nconst abn: CountryValidator<\"AU\"> = {\n name: \"Australian Business Number\",\n localName: \"Australian Business Number\",\n abbreviation: \"ABN\",\n aliases: [\"ABN\", \"Australian Business Number\"] as const,\n candidatePattern: \"\\\\d{2}\\\\s?\\\\d{3}\\\\s?\\\\d{3}\\\\s?\\\\d{3}\",\n scope: \"country\",\n country: \"AU\",\n entityType: \"company\",\n sourceUrl: \"https://abr.business.gov.au/\",\n examples: [\"83914571673\", \"51824753556\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default abn;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAqBA,MAAM,UAAU;CACd;CAAI;CAAG;CAAG;CAAG;CAAG;CAAG;CAAI;CAAI;CAAI;CAAI;AACrC;AAEA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAEF,IAAI,EAAE,WAAW,IACf,OAAO,IAAI,kBAAkB,uBAAuB;CAGtD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;EAC3B,IAAI,IAAI,OAAO,EAAE,OAAO,CAAC,CAAC;EAC1B,IAAI,MAAM,GAAG,KAAK;EAClB,OAAO,KAAK,QAAQ,MAAM;CAC5B;CACA,IAAI,MAAM,OAAO,GACf,OAAO,IAAI,oBAAoB,uBAAuB;CAGxD,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAExE,OAAO;AACT;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,EAAE;EACzB,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,4BAA4B;CAC7C,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,eAAe,aAAa;CACvC;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"abn.js","names":[],"sources":["../../src/au/abn.ts"],"sourcesContent":["/**\n * ABN (Australian Business Number).\n *\n * 11-digit identifier. Subtract 1 from the first\n * digit, then apply weights [10,1,3,5,7,9,11,13,\n * 15,17,19]; sum mod 89 must equal 0.\n *\n * @see https://en.wikipedia.org/wiki/Australian_Business_Number\n * @see https://abr.business.gov.au/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [\n 10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19,\n] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"ABN must contain only digits\",\n );\n }\n if (v.length !== 11) {\n return err(\"INVALID_LENGTH\", \"ABN must be 11 digits\");\n }\n\n let sum = 0;\n for (let i = 0; i < 11; i++) {\n let d = Number(v.charAt(i));\n if (i === 0) d -= 1;\n sum += d * (WEIGHTS[i] ?? 0);\n }\n if (sum % 89 !== 0) {\n return err(\"INVALID_CHECKSUM\", \"ABN checksum mismatch\");\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 11) {\n return `${v.slice(0, 2)} ${v.slice(2, 5)} ${v.slice(5, 8)} ${v.slice(8)}`;\n }\n return v;\n};\n\n/** Generate a random valid ABN. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(11);\n if (validate(c).valid) return c;\n }\n};\n\n/** Australian Business Number. */\nconst abn: CountryValidator<\"AU\"> = {\n name: \"Australian Business Number\",\n localName: \"Australian Business Number\",\n abbreviation: \"ABN\",\n aliases: [\"ABN\", \"Australian Business Number\"] as const,\n candidatePattern: \"\\\\d{2}\\\\s?\\\\d{3}\\\\s?\\\\d{3}\\\\s?\\\\d{3}\",\n scope: \"country\",\n country: \"AU\",\n entityType: \"company\",\n sourceUrl: \"https://abr.business.gov.au/\",\n examples: [\"83914571673\", \"51824753556\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default abn;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAqBA,MAAM,UAAU;CACd;CAAI;CAAG;CAAG;CAAG;CAAG;CAAG;CAAI;CAAI;CAAI;CAAI;AACrC;AAEA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAEF,IAAI,EAAE,WAAW,IACf,OAAO,IAAI,kBAAkB,uBAAuB;CAGtD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;EAC3B,IAAI,IAAI,OAAO,EAAE,OAAO,CAAC,CAAC;EAC1B,IAAI,MAAM,GAAG,KAAK;EAClB,OAAO,KAAK,QAAQ,MAAM;CAC5B;CACA,IAAI,MAAM,OAAO,GACf,OAAO,IAAI,oBAAoB,uBAAuB;CAGxD,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAExE,OAAO;AACT;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,EAAE;EACzB,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,4BAA4B;CAC7C,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,eAAe,aAAa;CACvC;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"tfn.js","names":[],"sources":["../../src/au/tfn.ts"],"sourcesContent":["/**\n * TFN (Australian Tax File Number).\n *\n * 8 or 9 digit identifier. Weighted checksum with\n * weights [1,4,3,7,5,8,6,9,10]; sum mod 11\n * must equal 0.\n *\n * @see https://en.wikipedia.org/wiki/Tax_file_number\n * @see https://www.ato.gov.au/Individuals/Tax-file-number/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [1, 4, 3, 7, 5, 8, 6, 9, 10] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"TFN must contain only digits\",\n );\n }\n if (v.length !== 8 && v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"TFN must be 8 or 9 digits\",\n );\n }\n\n let sum = 0;\n for (let i = 0; i < v.length; i++) {\n sum += Number(v.charAt(i)) * (WEIGHTS[i] ?? 0);\n }\n if (sum % 11 !== 0) {\n return err(\"INVALID_CHECKSUM\", \"TFN checksum mismatch\");\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 8 || v.length === 9) {\n return `${v.slice(0, 3)} ${v.slice(3, 6)} ${v.slice(6)}`;\n }\n return v;\n};\n\n/** Generate a random valid TFN. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(9);\n if (validate(c).valid) return c;\n }\n};\n\n/** Australian Tax File Number. */\nconst tfn: CountryValidator<\"AU\"> = {\n name: \"Tax File Number\",\n localName: \"Tax File Number\",\n abbreviation: \"TFN\",\n aliases: [\"TFN\", \"Tax File Number\"] as const,\n candidatePattern: \"\\\\d{8,9}\",\n scope: \"country\",\n country: \"AU\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.ato.gov.au/individuals-and-families/tax-file-number\",\n examples: [\"87650006\", \"123456782\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default tfn;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAqBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAE;AAE3C,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAEF,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,OAAO,IACL,kBACA,2BACF;CAGF,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAC5B,OAAO,OAAO,EAAE,OAAO,CAAC,CAAC,KAAK,QAAQ,MAAM;CAE9C,IAAI,MAAM,OAAO,GACf,OAAO,IAAI,oBAAoB,uBAAuB;CAGxD,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAEvD,OAAO;AACT;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,CAAC;EACxB,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,iBAAiB;CAClC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,YAAY,WAAW;CAClC;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"tfn.js","names":[],"sources":["../../src/au/tfn.ts"],"sourcesContent":["/**\n * TFN (Australian Tax File Number).\n *\n * 8 or 9 digit identifier. Weighted checksum with\n * weights [1,4,3,7,5,8,6,9,10]; sum mod 11\n * must equal 0.\n *\n * @see https://en.wikipedia.org/wiki/Tax_file_number\n * @see https://www.ato.gov.au/Individuals/Tax-file-number/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [1, 4, 3, 7, 5, 8, 6, 9, 10] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"TFN must contain only digits\",\n );\n }\n if (v.length !== 8 && v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"TFN must be 8 or 9 digits\",\n );\n }\n\n let sum = 0;\n for (let i = 0; i < v.length; i++) {\n sum += Number(v.charAt(i)) * (WEIGHTS[i] ?? 0);\n }\n if (sum % 11 !== 0) {\n return err(\"INVALID_CHECKSUM\", \"TFN checksum mismatch\");\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 8 || v.length === 9) {\n return `${v.slice(0, 3)} ${v.slice(3, 6)} ${v.slice(6)}`;\n }\n return v;\n};\n\n/** Generate a random valid TFN. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(9);\n if (validate(c).valid) return c;\n }\n};\n\n/** Australian Tax File Number. */\nconst tfn: CountryValidator<\"AU\"> = {\n name: \"Tax File Number\",\n localName: \"Tax File Number\",\n abbreviation: \"TFN\",\n aliases: [\"TFN\", \"Tax File Number\"] as const,\n candidatePattern: \"\\\\d{8,9}\",\n scope: \"country\",\n country: \"AU\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.ato.gov.au/individuals-and-families/tax-file-number\",\n examples: [\"87650006\", \"123456782\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default tfn;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAqBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAE;AAE3C,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAEF,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,OAAO,IACL,kBACA,2BACF;CAGF,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAC5B,OAAO,OAAO,EAAE,OAAO,CAAC,CAAC,KAAK,QAAQ,MAAM;CAE9C,IAAI,MAAM,OAAO,GACf,OAAO,IAAI,oBAAoB,uBAAuB;CAGxD,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAEvD,OAAO;AACT;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,CAAC;EACxB,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,iBAAiB;CAClC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,YAAY,WAAW;CAClC;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"voen.js","names":[],"sources":["../../src/az/voen.ts"],"sourcesContent":["/**\n * VÖEN (Vergi Ödəyicisinin Eyniləşdirmə Nömrəsi,\n * Azerbaijani tax identification number).\n *\n * 10 digits: TTSSSSSSCD where:\n * - TT = territorial unit code\n * - SSSSSS = serial number\n * - C = check digit (weighted sum mod 11)\n * - D = legal status (1=legal person, 2=natural person)\n *\n * Ported from python-stdnum az.voen module.\n *\n * @see https://www.taxes.gov.az/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\n/** Weights for check digit computation (positions 0-7). */\nconst WEIGHTS = [4, 1, 8, 6, 2, 7, 5, 3] as const;\n\n/**\n * Compact: strip spaces, prepend '0' if 9 digits.\n */\nconst compact = (value: string): string => {\n let number = clean(value, \" \").trim();\n if (number.length === 9) {\n number = \"0\" + number;\n }\n return number;\n};\n\n/**\n * Calculate the check digit (position 8) using\n * weighted sum of the first 8 digits mod 11.\n */\nconst calcCheckDigit = (value: string): string | null => {\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n sum += (WEIGHTS[i] ?? 0) * Number(value.charAt(i));\n }\n const result = sum % 11;\n return result === 10 ? null : String(result);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Azerbaijani VÖEN must be 10 digits\",\n );\n }\n\n if (!/^\\d{10}$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Azerbaijani VÖEN must contain only digits\",\n );\n }\n\n // SAFETY: regex above guarantees length === 10.\n // eslint-disable-next-line no-non-null-assertion\n const lastDigit = v[9]!;\n if (lastDigit !== \"1\" && lastDigit !== \"2\") {\n return err(\n \"INVALID_COMPONENT\",\n \"VÖEN last digit must be 1 or 2\",\n );\n }\n\n const expected = calcCheckDigit(v);\n if (expected === null || v[8] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"VÖEN check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 3)} ${v.slice(3, 6)} ${v.slice(6, 10)}`;\n};\n\n/** Generate a random valid VOEN. */\nconst generate = (): string => {\n for (let i = 0; i < 100; i++) {\n const payload = randomDigits(8);\n const check = calcCheckDigit(payload);\n if (check === null) continue;\n const status = Math.random() < 0.5 ? \"1\" : \"2\";\n return payload + check + status;\n }\n throw new Error(\"Failed to generate valid VOEN\");\n};\n\n/**\n * Azerbaijani tax identification number (VÖEN).\n *\n * Examples sourced from python-stdnum test suite.\n */\nconst voen: CountryValidator<\"AZ\"> = {\n name: \"Azerbaijani Tax ID\",\n localName: \"Vergi Ödəyicisinin Eyniləşdirmə Nömrəsi\",\n abbreviation: \"VÖEN\",\n aliases: [\"VÖEN\"] as const,\n candidatePattern: \"\\\\d{10}\",\n scope: \"country\",\n country: \"AZ\",\n entityType: \"any\",\n lengths: [10] as const,\n examples: [\"1401555071\", \"1400057421\"] as const,\n compact,\n format,\n validate,\n sourceUrl: \"https://www.taxes.gov.az/\",\n generate,\n};\n\nexport default voen;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAyBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;;;;AAKvC,MAAM,WAAW,UAA0B;CACzC,IAAI,SAAS,MAAM,OAAO,GAAG,EAAE,KAAK;CACpC,IAAI,OAAO,WAAW,GACpB,SAAS,MAAM;CAEjB,OAAO;AACT;;;;;AAMA,MAAM,kBAAkB,UAAiC;CACvD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,QAAQ,QAAQ,MAAM,KAAK,OAAO,MAAM,OAAO,CAAC,CAAC;CAEnD,MAAM,SAAS,MAAM;CACrB,OAAO,WAAW,KAAK,OAAO,OAAO,MAAM;AAC7C;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,oCACF;CAGF,IAAI,CAAC,WAAW,KAAK,CAAC,GACpB,OAAO,IACL,kBACA,2CACF;CAKF,MAAM,YAAY,EAAE;CACpB,IAAI,cAAc,OAAO,cAAc,KACrC,OAAO,IACL,qBACA,gCACF;CAGF,MAAM,WAAW,eAAe,CAAC;CACjC,IAAI,aAAa,QAAQ,EAAE,OAAO,UAChC,OAAO,IACL,oBACA,iCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE;AAC3D;;AAGA,MAAM,iBAAyB;CAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK;EAC5B,MAAM,UAAU,aAAa,CAAC;EAC9B,MAAM,QAAQ,eAAe,OAAO;EACpC,IAAI,UAAU,MAAM;EACpB,MAAM,SAAS,KAAK,OAAO,IAAI,KAAM,MAAM;EAC3C,OAAO,UAAU,QAAQ;CAC3B;CACA,MAAM,IAAI,MAAM,+BAA+B;AACjD;;;;;;AAOA,MAAM,OAA+B;CACnC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,MAAM;CAChB,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,cAAc,YAAY;CACrC;CACA;CACA;CACA,WAAW;CACX;AACF"}
1
+ {"version":3,"file":"voen.js","names":[],"sources":["../../src/az/voen.ts"],"sourcesContent":["/**\n * VÖEN (Vergi Ödəyicisinin Eyniləşdirmə Nömrəsi,\n * Azerbaijani tax identification number).\n *\n * 10 digits: TTSSSSSSCD where:\n * - TT = territorial unit code\n * - SSSSSS = serial number\n * - C = check digit (weighted sum mod 11)\n * - D = legal status (1=legal person, 2=natural person)\n *\n * Ported from python-stdnum az.voen module.\n *\n * @see https://www.taxes.gov.az/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\n/** Weights for check digit computation (positions 0-7). */\nconst WEIGHTS = [4, 1, 8, 6, 2, 7, 5, 3] as const;\n\n/**\n * Compact: strip spaces, prepend '0' if 9 digits.\n */\nconst compact = (value: string): string => {\n let number = clean(value, \" \").trim();\n if (number.length === 9) {\n number = \"0\" + number;\n }\n return number;\n};\n\n/**\n * Calculate the check digit (position 8) using\n * weighted sum of the first 8 digits mod 11.\n */\nconst calcCheckDigit = (value: string): string | null => {\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n sum += (WEIGHTS[i] ?? 0) * Number(value.charAt(i));\n }\n const result = sum % 11;\n return result === 10 ? null : String(result);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Azerbaijani VÖEN must be 10 digits\",\n );\n }\n\n if (!/^\\d{10}$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Azerbaijani VÖEN must contain only digits\",\n );\n }\n\n // SAFETY: regex above guarantees length === 10.\n // eslint-disable-next-line no-non-null-assertion\n const lastDigit = v[9]!;\n if (lastDigit !== \"1\" && lastDigit !== \"2\") {\n return err(\n \"INVALID_COMPONENT\",\n \"VÖEN last digit must be 1 or 2\",\n );\n }\n\n const expected = calcCheckDigit(v);\n if (expected === null || v[8] !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"VÖEN check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 3)} ${v.slice(3, 6)} ${v.slice(6, 10)}`;\n};\n\n/** Generate a random valid VOEN. */\nconst generate = (): string => {\n for (let i = 0; i < 100; i++) {\n const payload = randomDigits(8);\n const check = calcCheckDigit(payload);\n if (check === null) continue;\n const status = Math.random() < 0.5 ? \"1\" : \"2\";\n return payload + check + status;\n }\n throw new Error(\"Failed to generate valid VOEN\");\n};\n\n/**\n * Azerbaijani tax identification number (VÖEN).\n *\n * Examples sourced from python-stdnum test suite.\n */\nconst voen: CountryValidator<\"AZ\"> = {\n name: \"Azerbaijani Tax ID\",\n localName: \"Vergi Ödəyicisinin Eyniləşdirmə Nömrəsi\",\n abbreviation: \"VÖEN\",\n aliases: [\"VÖEN\"] as const,\n candidatePattern: \"\\\\d{10}\",\n scope: \"country\",\n country: \"AZ\",\n entityType: \"any\",\n lengths: [10] as const,\n examples: [\"1401555071\", \"1400057421\"] as const,\n compact,\n format,\n validate,\n sourceUrl: \"https://www.taxes.gov.az/\",\n generate,\n};\n\nexport default voen;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAyBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;;;;AAKvC,MAAM,WAAW,UAA0B;CACzC,IAAI,SAAS,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK;CACpC,IAAI,OAAO,WAAW,GACpB,SAAS,MAAM;CAEjB,OAAO;AACT;;;;;AAMA,MAAM,kBAAkB,UAAiC;CACvD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,QAAQ,QAAQ,MAAM,KAAK,OAAO,MAAM,OAAO,CAAC,CAAC;CAEnD,MAAM,SAAS,MAAM;CACrB,OAAO,WAAW,KAAK,OAAO,OAAO,MAAM;AAC7C;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,oCACF;CAGF,IAAI,CAAC,WAAW,KAAK,CAAC,GACpB,OAAO,IACL,kBACA,2CACF;CAKF,MAAM,YAAY,EAAE;CACpB,IAAI,cAAc,OAAO,cAAc,KACrC,OAAO,IACL,qBACA,gCACF;CAGF,MAAM,WAAW,eAAe,CAAC;CACjC,IAAI,aAAa,QAAQ,EAAE,OAAO,UAChC,OAAO,IACL,oBACA,iCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE;AAC3D;;AAGA,MAAM,iBAAyB;CAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK;EAC5B,MAAM,UAAU,aAAa,CAAC;EAC9B,MAAM,QAAQ,eAAe,OAAO;EACpC,IAAI,UAAU,MAAM;EACpB,MAAM,SAAS,KAAK,OAAO,IAAI,KAAM,MAAM;EAC3C,OAAO,UAAU,QAAQ;CAC3B;CACA,MAAM,IAAI,MAAM,+BAA+B;AACjD;;;;;;AAOA,MAAM,OAA+B;CACnC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,MAAM;CAChB,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,cAAc,YAAY;CACrC;CACA;CACA;CACA,WAAW;CACX;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"jmbg.js","names":[],"sources":["../../src/ba/jmbg.ts"],"sourcesContent":["/**\n * JMBG (Jedinstveni matični broj građana).\n *\n * Bosnian 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 */\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\nconst resolveYear = (yyy: number): number =>\n yyy < 900 ? yyy + 2000 : yyy + 1000;\n\nconst calcCheckDigit = (v: string): number => {\n const total = weightedSum(v.slice(0, 12), WEIGHTS, 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 \"JMBG must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"JMBG must contain only digits\",\n );\n }\n\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const yyyy = resolveYear(Number(v.slice(4, 7)));\n if (!isValidDate(yyyy, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"JMBG contains an invalid date\",\n );\n }\n\n if (calcCheckDigit(v) !== Number(v[12])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"JMBG check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst 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 const yyyy = resolveYear(Number(v.slice(4, 7)));\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 JMBG. */\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(10, 99));\n const sss = String(randomInt(0, 999)).padStart(3, \"0\");\n const partial = dd + mm + yyy + rr + sss;\n const check = calcCheckDigit(partial);\n const c = partial + String(check);\n if (validate(c).valid) return c;\n }\n};\n\n/** Bosnian Unique Master Citizen Number. */\nconst jmbg: CountryValidator<\"BA\", ParsedPersonId> = {\n name: \"Bosnian Personal ID\",\n localName: \"Jedinstveni matični broj građana\",\n abbreviation: \"JMBG\",\n aliases: [\"JMBG\", \"matični broj\"] as const,\n candidatePattern: \"\\\\d{13}\",\n scope: \"country\",\n country: \"BA\",\n entityType: \"person\",\n lengths: [13] as const,\n sourceUrl:\n \"https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/\",\n examples: [\"0101006500006\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default jmbg;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;AAuBA,MAAM,UAAU;CACd;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AACnC;AAEA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,eAAe,QACnB,MAAM,MAAM,MAAM,MAAO,MAAM;AAEjC,MAAM,kBAAkB,MAAsB;CAE5C,QAAS,KADK,YAAY,EAAE,MAAM,GAAG,EAAE,GAAG,SAAS,EACjC,KAAK,KAAM;AAC/B;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,gCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,+BACF;CAGF,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAE/B,IAAI,CAAC,YADQ,YAAY,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,CACzB,GAAG,IAAI,EAAE,GAC3B,OAAO,IACL,qBACA,+BACF;CAGF,IAAI,eAAe,CAAC,MAAM,OAAO,EAAE,GAAG,GACpC,OAAO,IACL,oBACA,iCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;AAEvD,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,KAAK;CAC7B,IAAI,CAAC,OAAO,OAAO,OAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,OAAO,YAAY,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;CAE9C,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAEpC,OAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,EAAE;EACpC,QAAQ,SAAS,MAAM,SAAS;CAClC;AACF;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,MAAM,OAAO,UAAU,KAAK,GAAG,CAAC;EACtC,MAAM,KAAK,OAAO,UAAU,IAAI,EAAE,CAAC;EACnC,MAAM,MAAM,OAAO,UAAU,GAAG,GAAG,CAAC,EAAE,SAAS,GAAG,GAAG;EACrD,MAAM,UAAU,KAAK,KAAK,MAAM,KAAK;EACrC,MAAM,QAAQ,eAAe,OAAO;EACpC,MAAM,IAAI,UAAU,OAAO,KAAK;EAChC,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,OAA+C;CACnD,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,QAAQ,cAAc;CAChC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,EAAE;CACZ,WACE;CACF,UAAU,CAAC,eAAe;CAC1B;CACA;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"jmbg.js","names":[],"sources":["../../src/ba/jmbg.ts"],"sourcesContent":["/**\n * JMBG (Jedinstveni matični broj građana).\n *\n * Bosnian 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 */\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\nconst resolveYear = (yyy: number): number =>\n yyy < 900 ? yyy + 2000 : yyy + 1000;\n\nconst calcCheckDigit = (v: string): number => {\n const total = weightedSum(v.slice(0, 12), WEIGHTS, 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 \"JMBG must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"JMBG must contain only digits\",\n );\n }\n\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const yyyy = resolveYear(Number(v.slice(4, 7)));\n if (!isValidDate(yyyy, mm, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"JMBG contains an invalid date\",\n );\n }\n\n if (calcCheckDigit(v) !== Number(v[12])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"JMBG check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst 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 const yyyy = resolveYear(Number(v.slice(4, 7)));\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 JMBG. */\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(10, 99));\n const sss = String(randomInt(0, 999)).padStart(3, \"0\");\n const partial = dd + mm + yyy + rr + sss;\n const check = calcCheckDigit(partial);\n const c = partial + String(check);\n if (validate(c).valid) return c;\n }\n};\n\n/** Bosnian Unique Master Citizen Number. */\nconst jmbg: CountryValidator<\"BA\", ParsedPersonId> = {\n name: \"Bosnian Personal ID\",\n localName: \"Jedinstveni matični broj građana\",\n abbreviation: \"JMBG\",\n aliases: [\"JMBG\", \"matični broj\"] as const,\n candidatePattern: \"\\\\d{13}\",\n scope: \"country\",\n country: \"BA\",\n entityType: \"person\",\n lengths: [13] as const,\n sourceUrl:\n \"https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/\",\n examples: [\"0101006500006\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default jmbg;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;AAuBA,MAAM,UAAU;CACd;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AACnC;AAEA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,eAAe,QACnB,MAAM,MAAM,MAAM,MAAO,MAAM;AAEjC,MAAM,kBAAkB,MAAsB;CAE5C,QAAS,KADK,YAAY,EAAE,MAAM,GAAG,EAAE,GAAG,SAAS,EACjC,KAAK,KAAM;AAC/B;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,gCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,+BACF;CAGF,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAE/B,IAAI,CAAC,YADQ,YAAY,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,CACzB,GAAG,IAAI,EAAE,GAC3B,OAAO,IACL,qBACA,+BACF;CAGF,IAAI,eAAe,CAAC,MAAM,OAAO,EAAE,GAAG,GACpC,OAAO,IACL,oBACA,iCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;AAEvD,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,KAAK;CAC7B,IAAI,CAAC,OAAO,OAAO,OAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,OAAO,YAAY,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;CAE9C,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAEpC,OAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,EAAE;EACpC,QAAQ,SAAS,MAAM,SAAS;CAClC;AACF;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,MAAM,OAAO,UAAU,KAAK,GAAG,CAAC;EACtC,MAAM,KAAK,OAAO,UAAU,IAAI,EAAE,CAAC;EACnC,MAAM,MAAM,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACrD,MAAM,UAAU,KAAK,KAAK,MAAM,KAAK;EACrC,MAAM,QAAQ,eAAe,OAAO;EACpC,MAAM,IAAI,UAAU,OAAO,KAAK;EAChC,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,OAA+C;CACnD,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,QAAQ,cAAc;CAChC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,EAAE;CACZ,WACE;CACF,UAAU,CAAC,eAAe;CAC1B;CACA;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"bis.js","names":["nnFormat"],"sources":["../../src/be/bis.ts"],"sourcesContent":["/**\n * BIS (BIS-nummer / Numéro BIS).\n *\n * Belgian BIS number for individuals not in the\n * National Register. 11 digits, structured like the\n * NN but with the month offset by 20 (gender unknown)\n * or 40 (gender known).\n *\n * @see https://sma-help.bosa.belgium.be/en/faq/where-can-i-find-my-bis-number\n * @see https://nl.wikipedia.org/wiki/Rijksregisternummer\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\nimport { checksum, format as nnFormat } from \"./nn\";\n\nimport { clean } from \"#util/clean\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" .-\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"BIS must be exactly 11 digits\",\n );\n }\n if (!isdigits(v) || Number(v) === 0) {\n return err(\n \"INVALID_FORMAT\",\n \"BIS must contain only digits\",\n );\n }\n\n if (checksum(v) === null) {\n return err(\n \"INVALID_CHECKSUM\",\n \"BIS check digits do not match\",\n );\n }\n\n // Month must be in 20..32 or 40..52\n const rawMonth = Number(v.slice(2, 4));\n const inRange20 = rawMonth >= 20 && rawMonth <= 32;\n const inRange40 = rawMonth >= 40 && rawMonth <= 52;\n if (!inRange20 && !inRange40) {\n return err(\n \"INVALID_COMPONENT\",\n \"Month must be in 20..32 or 40..52\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n nnFormat(compact(value));\n\n/** Generate a random valid BIS number. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const offset = Math.random() < 0.5 ? 20 : 40;\n const mm = String(randomInt(1, 12) + offset).padStart(\n 2,\n \"0\",\n );\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const serial = String(randomInt(1, 997)).padStart(\n 3,\n \"0\",\n );\n const base = yy + mm + dd + serial;\n const n2 = Number(\"2\" + base);\n const check2 = 97 - (n2 % 97);\n const c = base + String(check2).padStart(2, \"0\");\n if (validate(c).valid) return c;\n }\n};\n\n/** Belgian BIS Number. */\nconst bis: CountryValidator<\"BE\"> = {\n name: \"Belgian BIS Number\",\n localName: \"BIS-nummer\",\n abbreviation: \"BIS\",\n aliases: [\"BIS-nummer\", \"numéro BIS\"] as const,\n candidatePattern:\n \"\\\\d{2}\\\\.?\\\\d{2}\\\\.?\\\\d{2}-?\\\\d{3}\\\\.?\\\\d{2}\",\n scope: \"country\",\n country: \"BE\",\n entityType: \"person\",\n sourceUrl:\n \"https://sma-help.bosa.belgium.be/en/faq/where-can-i-find-my-bis-number\",\n examples: [\"98472899765\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default bis;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAuBA,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,+BACF;CAEF,IAAI,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,MAAM,GAChC,OAAO,IACL,kBACA,8BACF;CAGF,IAAI,SAAS,CAAC,MAAM,MAClB,OAAO,IACL,oBACA,+BACF;CAIF,MAAM,WAAW,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAGrC,IAAI,EAFc,YAAY,MAAM,YAAY,OAE9B,EADA,YAAY,MAAM,YAAY,KAE9C,OAAO,IACL,qBACA,mCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACdA,SAAS,QAAQ,KAAK,CAAC;;AAGzB,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,SAAS,KAAK,OAAO,IAAI,KAAM,KAAK;EAC1C,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,IAAI,MAAM,EAAE,SAC3C,GACA,GACF;EACA,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,SAAS,OAAO,UAAU,GAAG,GAAG,CAAC,EAAE,SACvC,GACA,GACF;EACA,MAAM,OAAO,KAAK,KAAK,KAAK;EAE5B,MAAM,SAAS,KADJ,OAAO,MAAM,IACF,IAAI;EAC1B,MAAM,IAAI,OAAO,OAAO,MAAM,EAAE,SAAS,GAAG,GAAG;EAC/C,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,cAAc,YAAY;CACpC,kBACE;CACF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"bis.js","names":["nnFormat"],"sources":["../../src/be/bis.ts"],"sourcesContent":["/**\n * BIS (BIS-nummer / Numéro BIS).\n *\n * Belgian BIS number for individuals not in the\n * National Register. 11 digits, structured like the\n * NN but with the month offset by 20 (gender unknown)\n * or 40 (gender known).\n *\n * @see https://sma-help.bosa.belgium.be/en/faq/where-can-i-find-my-bis-number\n * @see https://nl.wikipedia.org/wiki/Rijksregisternummer\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\nimport { checksum, format as nnFormat } from \"./nn\";\n\nimport { clean } from \"#util/clean\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" .-\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"BIS must be exactly 11 digits\",\n );\n }\n if (!isdigits(v) || Number(v) === 0) {\n return err(\n \"INVALID_FORMAT\",\n \"BIS must contain only digits\",\n );\n }\n\n if (checksum(v) === null) {\n return err(\n \"INVALID_CHECKSUM\",\n \"BIS check digits do not match\",\n );\n }\n\n // Month must be in 20..32 or 40..52\n const rawMonth = Number(v.slice(2, 4));\n const inRange20 = rawMonth >= 20 && rawMonth <= 32;\n const inRange40 = rawMonth >= 40 && rawMonth <= 52;\n if (!inRange20 && !inRange40) {\n return err(\n \"INVALID_COMPONENT\",\n \"Month must be in 20..32 or 40..52\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n nnFormat(compact(value));\n\n/** Generate a random valid BIS number. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const offset = Math.random() < 0.5 ? 20 : 40;\n const mm = String(randomInt(1, 12) + offset).padStart(\n 2,\n \"0\",\n );\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const serial = String(randomInt(1, 997)).padStart(\n 3,\n \"0\",\n );\n const base = yy + mm + dd + serial;\n const n2 = Number(\"2\" + base);\n const check2 = 97 - (n2 % 97);\n const c = base + String(check2).padStart(2, \"0\");\n if (validate(c).valid) return c;\n }\n};\n\n/** Belgian BIS Number. */\nconst bis: CountryValidator<\"BE\"> = {\n name: \"Belgian BIS Number\",\n localName: \"BIS-nummer\",\n abbreviation: \"BIS\",\n aliases: [\"BIS-nummer\", \"numéro BIS\"] as const,\n candidatePattern:\n \"\\\\d{2}\\\\.?\\\\d{2}\\\\.?\\\\d{2}-?\\\\d{3}\\\\.?\\\\d{2}\",\n scope: \"country\",\n country: \"BE\",\n entityType: \"person\",\n sourceUrl:\n \"https://sma-help.bosa.belgium.be/en/faq/where-can-i-find-my-bis-number\",\n examples: [\"98472899765\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default bis;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAuBA,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,+BACF;CAEF,IAAI,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,MAAM,GAChC,OAAO,IACL,kBACA,8BACF;CAGF,IAAI,SAAS,CAAC,MAAM,MAClB,OAAO,IACL,oBACA,+BACF;CAIF,MAAM,WAAW,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAGrC,IAAI,EAFc,YAAY,MAAM,YAAY,OAE9B,EADA,YAAY,MAAM,YAAY,KAE9C,OAAO,IACL,qBACA,mCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACdA,SAAS,QAAQ,KAAK,CAAC;;AAGzB,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,SAAS,KAAK,OAAO,IAAI,KAAM,KAAK;EAC1C,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,IAAI,MAAM,CAAC,CAAC,SAC3C,GACA,GACF;EACA,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,SAAS,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,SACvC,GACA,GACF;EACA,MAAM,OAAO,KAAK,KAAK,KAAK;EAE5B,MAAM,SAAS,KADJ,OAAO,MAAM,IACF,IAAI;EAC1B,MAAM,IAAI,OAAO,OAAO,MAAM,CAAC,CAAC,SAAS,GAAG,GAAG;EAC/C,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,cAAc,YAAY;CACpC,kBACE;CACF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;AACF"}
package/dist/be/nn.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"nn.js","names":[],"sources":["../../src/be/nn.ts"],"sourcesContent":["/**\n * NN (Numéro national / Rijksregisternummer).\n *\n * Belgian national identification number. 11 digits\n * encoding date of birth, serial number, and a\n * check digit pair. The first 6 digits are YYMMDD,\n * followed by a 3-digit serial and 2 check digits.\n *\n * @see https://fr.wikipedia.org/wiki/Numéro_de_registre_national\n * @see https://www.ibz.rrn.fgov.be/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" .-\");\n\n/**\n * Verify the mod-97 checksum and return the detected\n * century (1900 or 2000). Returns null on mismatch.\n * Matches python-stdnum's _checksum logic: the 2000s\n * century is only attempted when YY+2000 <= current year.\n */\nconst checksum = (v: string): number | null => {\n const first9 = Number(v.slice(0, 9));\n const check = Number(v.slice(9, 11));\n\n if (97 - (first9 % 97) === check) return 1900;\n\n const yy = Number(v.slice(0, 2));\n if (yy + 2000 <= new Date().getFullYear()) {\n const with2 = Number(`2${v.slice(0, 9)}`);\n if (97 - (with2 % 97) === check) return 2000;\n }\n\n return null;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"NN must be exactly 11 digits\",\n );\n }\n if (!isdigits(v) || Number(v) === 0) {\n return err(\n \"INVALID_FORMAT\",\n \"NN must contain only digits\",\n );\n }\n\n if (checksum(v) === null) {\n return err(\n \"INVALID_CHECKSUM\",\n \"NN check digits do not match\",\n );\n }\n\n // Raw month digits must be 0..12 (values 13+ are\n // invalid; counter-exhaustion uses 00, not 20+).\n const rawMonth = Number(v.slice(2, 4));\n if (rawMonth > 12) {\n return err(\n \"INVALID_COMPONENT\",\n \"Month must be in 0..12\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 2)}.${v.slice(2, 4)}.${v.slice(4, 6)}-${v.slice(6, 9)}.${v.slice(9)}`;\n};\n\n/** Generate a random valid Belgian NN. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const serial = String(randomInt(1, 997)).padStart(\n 3,\n \"0\",\n );\n const base = yy + mm + dd + serial;\n const n1 = Number(base);\n const check1 = 97 - (n1 % 97);\n const c = base + String(check1).padStart(2, \"0\");\n if (validate(c).valid) return c;\n }\n};\n\n/** Belgian National Number. */\nconst nn: CountryValidator<\"BE\"> = {\n name: \"Belgian National Number\",\n localName: \"Numéro national\",\n abbreviation: \"NN\",\n aliases: [\n \"rijksregisternummer\",\n \"numéro national\",\n \"NN\",\n ] as const,\n candidatePattern:\n \"\\\\d{2}\\\\.?\\\\d{2}\\\\.?\\\\d{2}-?\\\\d{3}\\\\.?\\\\d{2}\",\n scope: \"country\",\n country: \"BE\",\n entityType: \"person\",\n sourceUrl: \"https://www.ibz.rrn.fgov.be/\",\n examples: [\"93051822361\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nn;\nexport { checksum, compact, format, validate, generate };\n"],"mappings":";;;;;AAsBA,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;;;;;;;AAQpB,MAAM,YAAY,MAA6B;CAC7C,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CACnC,MAAM,QAAQ,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAEnC,IAAI,KAAM,SAAS,OAAQ,OAAO,OAAO;CAGzC,IADW,OAAO,EAAE,MAAM,GAAG,CAAC,CACzB,IAAI,wBAAQ,IAAI,KAAK,GAAE,YAAY;MAElC,KADU,OAAO,IAAI,EAAE,MAAM,GAAG,CAAC,GACvB,IAAI,OAAQ,OAAO,OAAO;CAAA;CAG1C,OAAO;AACT;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,8BACF;CAEF,IAAI,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,MAAM,GAChC,OAAO,IACL,kBACA,6BACF;CAGF,IAAI,SAAS,CAAC,MAAM,MAClB,OAAO,IACL,oBACA,8BACF;CAMF,IADiB,OAAO,EAAE,MAAM,GAAG,CAAC,CACzB,IAAI,IACb,OAAO,IACL,qBACA,wBACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACzF;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,SAAS,OAAO,UAAU,GAAG,GAAG,CAAC,EAAE,SACvC,GACA,GACF;EACA,MAAM,OAAO,KAAK,KAAK,KAAK;EAE5B,MAAM,SAAS,KADJ,OAAO,IACI,IAAI;EAC1B,MAAM,IAAI,OAAO,OAAO,MAAM,EAAE,SAAS,GAAG,GAAG;EAC/C,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,KAA6B;CACjC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBACE;CACF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"nn.js","names":[],"sources":["../../src/be/nn.ts"],"sourcesContent":["/**\n * NN (Numéro national / Rijksregisternummer).\n *\n * Belgian national identification number. 11 digits\n * encoding date of birth, serial number, and a\n * check digit pair. The first 6 digits are YYMMDD,\n * followed by a 3-digit serial and 2 check digits.\n *\n * @see https://fr.wikipedia.org/wiki/Numéro_de_registre_national\n * @see https://www.ibz.rrn.fgov.be/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" .-\");\n\n/**\n * Verify the mod-97 checksum and return the detected\n * century (1900 or 2000). Returns null on mismatch.\n * Matches python-stdnum's _checksum logic: the 2000s\n * century is only attempted when YY+2000 <= current year.\n */\nconst checksum = (v: string): number | null => {\n const first9 = Number(v.slice(0, 9));\n const check = Number(v.slice(9, 11));\n\n if (97 - (first9 % 97) === check) return 1900;\n\n const yy = Number(v.slice(0, 2));\n if (yy + 2000 <= new Date().getFullYear()) {\n const with2 = Number(`2${v.slice(0, 9)}`);\n if (97 - (with2 % 97) === check) return 2000;\n }\n\n return null;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"NN must be exactly 11 digits\",\n );\n }\n if (!isdigits(v) || Number(v) === 0) {\n return err(\n \"INVALID_FORMAT\",\n \"NN must contain only digits\",\n );\n }\n\n if (checksum(v) === null) {\n return err(\n \"INVALID_CHECKSUM\",\n \"NN check digits do not match\",\n );\n }\n\n // Raw month digits must be 0..12 (values 13+ are\n // invalid; counter-exhaustion uses 00, not 20+).\n const rawMonth = Number(v.slice(2, 4));\n if (rawMonth > 12) {\n return err(\n \"INVALID_COMPONENT\",\n \"Month must be in 0..12\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 2)}.${v.slice(2, 4)}.${v.slice(4, 6)}-${v.slice(6, 9)}.${v.slice(9)}`;\n};\n\n/** Generate a random valid Belgian NN. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const serial = String(randomInt(1, 997)).padStart(\n 3,\n \"0\",\n );\n const base = yy + mm + dd + serial;\n const n1 = Number(base);\n const check1 = 97 - (n1 % 97);\n const c = base + String(check1).padStart(2, \"0\");\n if (validate(c).valid) return c;\n }\n};\n\n/** Belgian National Number. */\nconst nn: CountryValidator<\"BE\"> = {\n name: \"Belgian National Number\",\n localName: \"Numéro national\",\n abbreviation: \"NN\",\n aliases: [\n \"rijksregisternummer\",\n \"numéro national\",\n \"NN\",\n ] as const,\n candidatePattern:\n \"\\\\d{2}\\\\.?\\\\d{2}\\\\.?\\\\d{2}-?\\\\d{3}\\\\.?\\\\d{2}\",\n scope: \"country\",\n country: \"BE\",\n entityType: \"person\",\n sourceUrl: \"https://www.ibz.rrn.fgov.be/\",\n examples: [\"93051822361\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nn;\nexport { checksum, compact, format, validate, generate };\n"],"mappings":";;;;;AAsBA,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;;;;;;;AAQpB,MAAM,YAAY,MAA6B;CAC7C,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CACnC,MAAM,QAAQ,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAEnC,IAAI,KAAM,SAAS,OAAQ,OAAO,OAAO;CAGzC,IADW,OAAO,EAAE,MAAM,GAAG,CAAC,CACzB,IAAI,wBAAQ,IAAI,KAAK,EAAA,CAAE,YAAY;MAElC,KADU,OAAO,IAAI,EAAE,MAAM,GAAG,CAAC,GACvB,IAAI,OAAQ,OAAO,OAAO;CAAA;CAG1C,OAAO;AACT;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,8BACF;CAEF,IAAI,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,MAAM,GAChC,OAAO,IACL,kBACA,6BACF;CAGF,IAAI,SAAS,CAAC,MAAM,MAClB,OAAO,IACL,oBACA,8BACF;CAMF,IADiB,OAAO,EAAE,MAAM,GAAG,CAAC,CACzB,IAAI,IACb,OAAO,IACL,qBACA,wBACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACzF;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,SAAS,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,SACvC,GACA,GACF;EACA,MAAM,OAAO,KAAK,KAAK,KAAK;EAE5B,MAAM,SAAS,KADJ,OAAO,IACI,IAAI;EAC1B,MAAM,IAAI,OAAO,OAAO,MAAM,CAAC,CAAC,SAAS,GAAG,GAAG;EAC/C,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,KAA6B;CACjC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBACE;CACF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"vat.js","names":[],"sources":["../../src/be/vat.ts"],"sourcesContent":["/**\n * BTW/TVA/MWSt (Belgian VAT number).\n *\n * 10 digits, first must be 0 or 1.\n * Checksum: (first 8 digits + last 2) % 97 === 0.\n *\n * @see https://www.vatify.eu/belgium-vat-number.html\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/belgium-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\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"BE\") || v.startsWith(\"be\")) {\n v = v.slice(2);\n }\n // Old 9-digit format: zero-pad to 10\n if (v.length === 9) {\n v = `0${v}`;\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Belgian VAT number must be 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Belgian VAT number must contain only digits\",\n );\n }\n if (Number(v) === 0) {\n return err(\n \"INVALID_FORMAT\",\n \"Belgian VAT number cannot be all zeros\",\n );\n }\n if (v[0] !== \"0\" && v[0] !== \"1\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Belgian VAT number must start with 0 or 1\",\n );\n }\n const front = Number.parseInt(v.slice(0, 8), 10);\n const check = Number.parseInt(v.slice(8, 10), 10);\n if ((front + check) % 97 !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Belgian VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `BE${v}`;\n};\n\n/** Generate a random valid Belgian VAT number. */\nconst generate = (): string => {\n for (;;) {\n const prefix = Math.random() < 0.5 ? \"0\" : \"1\";\n const front = prefix + randomDigits(7);\n const rem = Number.parseInt(front, 10) % 97;\n const check = rem === 0 ? 97 : 97 - rem;\n const c = front + String(check).padStart(2, \"0\");\n if (validate(c).valid) return c;\n }\n};\n\n/** Belgian VAT Number. */\nconst vat: CountryValidator<\"BE\"> = {\n name: \"Belgian VAT Number\",\n localName: \"BTW-identificatienummer\",\n abbreviation: \"BTW\",\n aliases: [\n \"BTW\",\n \"TVA\",\n \"numéro d'entreprise\",\n \"ondernemingsnummer\",\n ] as const,\n candidatePattern: \"BE0?\\\\d{9,10}\",\n scope: \"country\",\n country: \"BE\",\n entityType: \"company\",\n sourceUrl: \"https://finances.belgium.be/\",\n examples: [\"0776091951\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAoBA,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,MAAM;CAC3B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAGf,IAAI,EAAE,WAAW,GACf,IAAI,IAAI;CAEV,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,OAAO,CAAC,MAAM,GAChB,OAAO,IACL,kBACA,wCACF;CAEF,IAAI,EAAE,OAAO,OAAO,EAAE,OAAO,KAC3B,OAAO,IACL,qBACA,2CACF;CAIF,KAFc,OAAO,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAEpC,IADK,OAAO,SAAS,EAAE,MAAM,GAAG,EAAE,GAAG,EAC7B,KAAK,OAAO,GAC3B,OAAO,IACL,oBACA,yCACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CAExC,OAAO,KADG,QAAQ,KACN;AACd;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EAEP,MAAM,SADS,KAAK,OAAO,IAAI,KAAM,MAAM,OACpB,aAAa,CAAC;EACrC,MAAM,MAAM,OAAO,SAAS,OAAO,EAAE,IAAI;EACzC,MAAM,QAAQ,QAAQ,IAAI,KAAK,KAAK;EACpC,MAAM,IAAI,QAAQ,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG;EAC/C,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;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,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"vat.js","names":[],"sources":["../../src/be/vat.ts"],"sourcesContent":["/**\n * BTW/TVA/MWSt (Belgian VAT number).\n *\n * 10 digits, first must be 0 or 1.\n * Checksum: (first 8 digits + last 2) % 97 === 0.\n *\n * @see https://www.vatify.eu/belgium-vat-number.html\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/belgium-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\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"BE\") || v.startsWith(\"be\")) {\n v = v.slice(2);\n }\n // Old 9-digit format: zero-pad to 10\n if (v.length === 9) {\n v = `0${v}`;\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Belgian VAT number must be 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Belgian VAT number must contain only digits\",\n );\n }\n if (Number(v) === 0) {\n return err(\n \"INVALID_FORMAT\",\n \"Belgian VAT number cannot be all zeros\",\n );\n }\n if (v[0] !== \"0\" && v[0] !== \"1\") {\n return err(\n \"INVALID_COMPONENT\",\n \"Belgian VAT number must start with 0 or 1\",\n );\n }\n const front = Number.parseInt(v.slice(0, 8), 10);\n const check = Number.parseInt(v.slice(8, 10), 10);\n if ((front + check) % 97 !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Belgian VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `BE${v}`;\n};\n\n/** Generate a random valid Belgian VAT number. */\nconst generate = (): string => {\n for (;;) {\n const prefix = Math.random() < 0.5 ? \"0\" : \"1\";\n const front = prefix + randomDigits(7);\n const rem = Number.parseInt(front, 10) % 97;\n const check = rem === 0 ? 97 : 97 - rem;\n const c = front + String(check).padStart(2, \"0\");\n if (validate(c).valid) return c;\n }\n};\n\n/** Belgian VAT Number. */\nconst vat: CountryValidator<\"BE\"> = {\n name: \"Belgian VAT Number\",\n localName: \"BTW-identificatienummer\",\n abbreviation: \"BTW\",\n aliases: [\n \"BTW\",\n \"TVA\",\n \"numéro d'entreprise\",\n \"ondernemingsnummer\",\n ] as const,\n candidatePattern: \"BE0?\\\\d{9,10}\",\n scope: \"country\",\n country: \"BE\",\n entityType: \"company\",\n sourceUrl: \"https://finances.belgium.be/\",\n examples: [\"0776091951\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAoBA,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,MAAM;CAC3B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAGf,IAAI,EAAE,WAAW,GACf,IAAI,IAAI;CAEV,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,OAAO,CAAC,MAAM,GAChB,OAAO,IACL,kBACA,wCACF;CAEF,IAAI,EAAE,OAAO,OAAO,EAAE,OAAO,KAC3B,OAAO,IACL,qBACA,2CACF;CAIF,KAFc,OAAO,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAEpC,IADK,OAAO,SAAS,EAAE,MAAM,GAAG,EAAE,GAAG,EAC7B,KAAK,OAAO,GAC3B,OAAO,IACL,oBACA,yCACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CAExC,OAAO,KADG,QAAQ,KACN;AACd;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EAEP,MAAM,SADS,KAAK,OAAO,IAAI,KAAM,MAAM,OACpB,aAAa,CAAC;EACrC,MAAM,MAAM,OAAO,SAAS,OAAO,EAAE,IAAI;EACzC,MAAM,QAAQ,QAAQ,IAAI,KAAK,KAAK;EACpC,MAAM,IAAI,QAAQ,OAAO,KAAK,CAAC,CAAC,SAAS,GAAG,GAAG;EAC/C,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;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,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"egn.js","names":[],"sources":["../../src/bg/egn.ts"],"sourcesContent":["/**\n * EGN (Единен граждански номер).\n *\n * Bulgarian personal identification number.\n * 10 digits encoding date of birth, serial number,\n * and a check digit.\n *\n * Canonical source:\n * - GRAO regulation PDF describing the EGN structure.\n *\n * We treat this as authoritative over third-party\n * oracle libraries when the checksum or date rules\n * disagree.\n *\n * @see https://www.grao.bg/normact/NaredbaFunkcESGR.pdf\n */\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [2, 4, 8, 5, 10, 9, 7, 3, 6] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"EGN must be exactly 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"EGN must contain only digits\",\n );\n }\n\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n\n let year: number;\n let month: number;\n if (mm > 40) {\n year = 2000 + yy;\n month = mm - 40;\n } else if (mm > 20) {\n year = 1800 + yy;\n month = mm - 20;\n } else {\n year = 1900 + yy;\n month = mm;\n }\n\n if (!isValidDate(year, month, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"EGN contains an invalid date\",\n );\n }\n\n const sum = weightedSum(v.slice(0, 9), WEIGHTS, 11);\n const check = sum % 10;\n if (check !== Number(v[9])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"EGN check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from an EGN.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n const serial = Number(v.slice(6, 9));\n\n let year: number;\n let month: number;\n if (mm > 40) {\n year = 2000 + yy;\n month = mm - 40;\n } else if (mm > 20) {\n year = 1800 + yy;\n month = mm - 20;\n } else {\n year = 1900 + yy;\n month = mm;\n }\n\n return {\n birthDate: new Date(year, month - 1, dd),\n gender: serial % 2 === 0 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid EGN. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const serial = String(randomInt(0, 999)).padStart(\n 3,\n \"0\",\n );\n const payload = yy + mm + dd + serial;\n const sum = weightedSum(payload, WEIGHTS, 11);\n const c = payload + String(sum % 10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Bulgarian Personal Identification Number. */\nconst egn: CountryValidator<\"BG\", ParsedPersonId> = {\n name: \"Bulgarian Personal ID\",\n localName: \"Единен граждански номер\",\n abbreviation: \"ЕГН\",\n aliases: [\n \"ЕГН\",\n \"единен граждански номер\",\n \"EGN\",\n ] as const,\n candidatePattern: \"\\\\d{10}\",\n scope: \"country\",\n country: \"BG\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.grao.bg/normact/NaredbaFunkcESGR.pdf\",\n examples: [\"7523169263\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default egn;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;AA8BA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;AAAC;AAE3C,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,+BACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAGF,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAE/B,IAAI;CACJ,IAAI;CACJ,IAAI,KAAK,IAAI;EACX,OAAO,MAAO;EACd,QAAQ,KAAK;CACf,OAAO,IAAI,KAAK,IAAI;EAClB,OAAO,OAAO;EACd,QAAQ,KAAK;CACf,OAAO;EACL,OAAO,OAAO;EACd,QAAQ;CACV;CAEA,IAAI,CAAC,YAAY,MAAM,OAAO,EAAE,GAC9B,OAAO,IACL,qBACA,8BACF;CAKF,IAFY,YAAY,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,EAChC,IAAI,OACN,OAAO,EAAE,EAAE,GACvB,OAAO,IACL,oBACA,gCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;;;;;AAMvD,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,KAAK;CAC7B,IAAI,CAAC,OAAO,OAAO,OAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAEnC,IAAI;CACJ,IAAI;CACJ,IAAI,KAAK,IAAI;EACX,OAAO,MAAO;EACd,QAAQ,KAAK;CACf,OAAO,IAAI,KAAK,IAAI;EAClB,OAAO,OAAO;EACd,QAAQ,KAAK;CACf,OAAO;EACL,OAAO,OAAO;EACd,QAAQ;CACV;CAEA,OAAO;EACL,WAAW,IAAI,KAAK,MAAM,QAAQ,GAAG,EAAE;EACvC,QAAQ,SAAS,MAAM,IAAI,SAAS;CACtC;AACF;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAAG;EACnD,MAAM,SAAS,OAAO,UAAU,GAAG,GAAG,CAAC,EAAE,SACvC,GACA,GACF;EACA,MAAM,UAAU,KAAK,KAAK,KAAK;EAC/B,MAAM,MAAM,YAAY,SAAS,SAAS,EAAE;EAC5C,MAAM,IAAI,UAAU,OAAO,MAAM,EAAE;EACnC,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8C;CAClD,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"egn.js","names":[],"sources":["../../src/bg/egn.ts"],"sourcesContent":["/**\n * EGN (Единен граждански номер).\n *\n * Bulgarian personal identification number.\n * 10 digits encoding date of birth, serial number,\n * and a check digit.\n *\n * Canonical source:\n * - GRAO regulation PDF describing the EGN structure.\n *\n * We treat this as authoritative over third-party\n * oracle libraries when the checksum or date rules\n * disagree.\n *\n * @see https://www.grao.bg/normact/NaredbaFunkcESGR.pdf\n */\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [2, 4, 8, 5, 10, 9, 7, 3, 6] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"EGN must be exactly 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"EGN must contain only digits\",\n );\n }\n\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n\n let year: number;\n let month: number;\n if (mm > 40) {\n year = 2000 + yy;\n month = mm - 40;\n } else if (mm > 20) {\n year = 1800 + yy;\n month = mm - 20;\n } else {\n year = 1900 + yy;\n month = mm;\n }\n\n if (!isValidDate(year, month, dd)) {\n return err(\n \"INVALID_COMPONENT\",\n \"EGN contains an invalid date\",\n );\n }\n\n const sum = weightedSum(v.slice(0, 9), WEIGHTS, 11);\n const check = sum % 10;\n if (check !== Number(v[9])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"EGN check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from an EGN.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const yy = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const dd = Number(v.slice(4, 6));\n const serial = Number(v.slice(6, 9));\n\n let year: number;\n let month: number;\n if (mm > 40) {\n year = 2000 + yy;\n month = mm - 40;\n } else if (mm > 20) {\n year = 1800 + yy;\n month = mm - 20;\n } else {\n year = 1900 + yy;\n month = mm;\n }\n\n return {\n birthDate: new Date(year, month - 1, dd),\n gender: serial % 2 === 0 ? \"male\" : \"female\",\n };\n};\n\n/** Generate a random valid EGN. */\nconst generate = (): string => {\n for (;;) {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dd = String(randomInt(1, 28)).padStart(2, \"0\");\n const serial = String(randomInt(0, 999)).padStart(\n 3,\n \"0\",\n );\n const payload = yy + mm + dd + serial;\n const sum = weightedSum(payload, WEIGHTS, 11);\n const c = payload + String(sum % 10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Bulgarian Personal Identification Number. */\nconst egn: CountryValidator<\"BG\", ParsedPersonId> = {\n name: \"Bulgarian Personal ID\",\n localName: \"Единен граждански номер\",\n abbreviation: \"ЕГН\",\n aliases: [\n \"ЕГН\",\n \"единен граждански номер\",\n \"EGN\",\n ] as const,\n candidatePattern: \"\\\\d{10}\",\n scope: \"country\",\n country: \"BG\",\n entityType: \"person\",\n sourceUrl:\n \"https://www.grao.bg/normact/NaredbaFunkcESGR.pdf\",\n examples: [\"7523169263\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default egn;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;;;AA8BA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;AAAC;AAE3C,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,+BACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAGF,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAE/B,IAAI;CACJ,IAAI;CACJ,IAAI,KAAK,IAAI;EACX,OAAO,MAAO;EACd,QAAQ,KAAK;CACf,OAAO,IAAI,KAAK,IAAI;EAClB,OAAO,OAAO;EACd,QAAQ,KAAK;CACf,OAAO;EACL,OAAO,OAAO;EACd,QAAQ;CACV;CAEA,IAAI,CAAC,YAAY,MAAM,OAAO,EAAE,GAC9B,OAAO,IACL,qBACA,8BACF;CAKF,IAFY,YAAY,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,EAChC,IAAI,OACN,OAAO,EAAE,EAAE,GACvB,OAAO,IACL,oBACA,gCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;;;;;AAMvD,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,KAAK;CAC7B,IAAI,CAAC,OAAO,OAAO,OAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAEnC,IAAI;CACJ,IAAI;CACJ,IAAI,KAAK,IAAI;EACX,OAAO,MAAO;EACd,QAAQ,KAAK;CACf,OAAO,IAAI,KAAK,IAAI;EAClB,OAAO,OAAO;EACd,QAAQ,KAAK;CACf,OAAO;EACL,OAAO,OAAO;EACd,QAAQ;CACV;CAEA,OAAO;EACL,WAAW,IAAI,KAAK,MAAM,QAAQ,GAAG,EAAE;EACvC,QAAQ,SAAS,MAAM,IAAI,SAAS;CACtC;AACF;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,SAAS,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,SACvC,GACA,GACF;EACA,MAAM,UAAU,KAAK,KAAK,KAAK;EAC/B,MAAM,MAAM,YAAY,SAAS,SAAS,EAAE;EAC5C,MAAM,IAAI,UAAU,OAAO,MAAM,EAAE;EACnC,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8C;CAClD,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WACE;CACF,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"vat.js","names":[],"sources":["../../src/bg/vat.ts"],"sourcesContent":["/**\n * ИН по ДДС (Bulgarian VAT number).\n *\n * 9 or 10 digits with weighted checksum.\n *\n * @see https://www.vatify.eu/bulgaria-vat-number.html\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/bulgaria-tin.pdf\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"BG\") || v.startsWith(\"bg\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst d = (v: string, i: number): number => Number(v[i]);\n\nconst WEIGHTS_9_PASS1 = [1, 2, 3, 4, 5, 6, 7, 8];\nconst WEIGHTS_9_PASS2 = [3, 4, 5, 6, 7, 8, 9, 10];\nconst WEIGHTS_EGN = [2, 4, 8, 5, 10, 9, 7, 3, 6];\nconst WEIGHTS_PNF = [21, 19, 17, 13, 11, 9, 7, 3, 1];\nconst WEIGHTS_OTHER = [4, 3, 2, 7, 6, 5, 4, 3, 2];\n\nconst validate9 = (v: string): boolean => {\n let check = weightedSum(\n v.slice(0, 8),\n WEIGHTS_9_PASS1,\n 11,\n );\n if (check === 10) {\n check = weightedSum(v.slice(0, 8), WEIGHTS_9_PASS2, 11);\n }\n return check % 10 === d(v, 8);\n};\n\n/**\n * Validate a 10-digit EGN (personal code).\n * First 6 digits encode birth date (YYMMDD with month\n * offsets: +20 for 1800s, +40 for 2000s). Check digit\n * uses weights [2,4,8,5,10,9,7,3,6], sum % 11 % 10.\n */\nconst validateEgn = (v: string): boolean => {\n const year = d(v, 0) * 10 + d(v, 1);\n let month = d(v, 2) * 10 + d(v, 3);\n const day = d(v, 4) * 10 + d(v, 5);\n let fullYear = year + 1900;\n if (month > 40) {\n fullYear += 100;\n month -= 40;\n } else if (month > 20) {\n fullYear -= 100;\n month -= 20;\n }\n // Validate the birth date\n const date = new Date(fullYear, month - 1, day);\n if (\n date.getFullYear() !== fullYear ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day\n ) {\n return false;\n }\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_EGN, 11);\n return sum % 10 === d(v, 9);\n};\n\n/**\n * Validate a 10-digit PNF (foreigner personal number).\n * Weights [21,19,17,13,11,9,7,3,1], sum % 10.\n */\nconst validatePnf = (v: string): boolean => {\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_PNF, 10);\n return sum === d(v, 9);\n};\n\n/**\n * Validate a 10-digit \"other\" VAT number.\n * Weights [4,3,2,7,6,5,4,3,2], (11 - sum%11) % 11.\n */\nconst validateOther = (v: string): boolean => {\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_OTHER, 11);\n return (11 - sum) % 11 === d(v, 9);\n};\n\nconst validate10 = (v: string): boolean =>\n validateEgn(v) || validatePnf(v) || validateOther(v);\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 9 && v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Bulgarian VAT number must be 9 or 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Bulgarian VAT number must contain only digits\",\n );\n }\n const valid =\n v.length === 9 ? validate9(v) : validate10(v);\n if (!valid) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Bulgarian VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `BG${compact(value)}`;\n\n/** Generate a random valid 9-digit Bulgarian VAT. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(9);\n if (validate(c).valid) return c;\n }\n};\n\n/** Bulgarian VAT Number. */\nconst vat: CountryValidator<\"BG\"> = {\n name: \"Bulgarian VAT Number\",\n localName: \"ИН по ДДС\",\n abbreviation: \"ИН по ДДС\",\n aliases: [\n \"ДДС\",\n \"идентификационен номер по ДДС\",\n ] as const,\n candidatePattern: \"BG\\\\d{9,10}\",\n scope: \"country\",\n country: \"BG\",\n entityType: \"any\",\n sourceUrl: \"https://www.nra.bg/\",\n lengths: [9, 10] as const,\n examples: [\"175074752\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":"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"}
1
+ {"version":3,"file":"vat.js","names":[],"sources":["../../src/bg/vat.ts"],"sourcesContent":["/**\n * ИН по ДДС (Bulgarian VAT number).\n *\n * 9 or 10 digits with weighted checksum.\n *\n * @see https://www.vatify.eu/bulgaria-vat-number.html\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/bulgaria-tin.pdf\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { weightedSum } from \"#checksums/weighted-sum\";\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"BG\") || v.startsWith(\"bg\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst d = (v: string, i: number): number => Number(v[i]);\n\nconst WEIGHTS_9_PASS1 = [1, 2, 3, 4, 5, 6, 7, 8];\nconst WEIGHTS_9_PASS2 = [3, 4, 5, 6, 7, 8, 9, 10];\nconst WEIGHTS_EGN = [2, 4, 8, 5, 10, 9, 7, 3, 6];\nconst WEIGHTS_PNF = [21, 19, 17, 13, 11, 9, 7, 3, 1];\nconst WEIGHTS_OTHER = [4, 3, 2, 7, 6, 5, 4, 3, 2];\n\nconst validate9 = (v: string): boolean => {\n let check = weightedSum(\n v.slice(0, 8),\n WEIGHTS_9_PASS1,\n 11,\n );\n if (check === 10) {\n check = weightedSum(v.slice(0, 8), WEIGHTS_9_PASS2, 11);\n }\n return check % 10 === d(v, 8);\n};\n\n/**\n * Validate a 10-digit EGN (personal code).\n * First 6 digits encode birth date (YYMMDD with month\n * offsets: +20 for 1800s, +40 for 2000s). Check digit\n * uses weights [2,4,8,5,10,9,7,3,6], sum % 11 % 10.\n */\nconst validateEgn = (v: string): boolean => {\n const year = d(v, 0) * 10 + d(v, 1);\n let month = d(v, 2) * 10 + d(v, 3);\n const day = d(v, 4) * 10 + d(v, 5);\n let fullYear = year + 1900;\n if (month > 40) {\n fullYear += 100;\n month -= 40;\n } else if (month > 20) {\n fullYear -= 100;\n month -= 20;\n }\n // Validate the birth date\n const date = new Date(fullYear, month - 1, day);\n if (\n date.getFullYear() !== fullYear ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day\n ) {\n return false;\n }\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_EGN, 11);\n return sum % 10 === d(v, 9);\n};\n\n/**\n * Validate a 10-digit PNF (foreigner personal number).\n * Weights [21,19,17,13,11,9,7,3,1], sum % 10.\n */\nconst validatePnf = (v: string): boolean => {\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_PNF, 10);\n return sum === d(v, 9);\n};\n\n/**\n * Validate a 10-digit \"other\" VAT number.\n * Weights [4,3,2,7,6,5,4,3,2], (11 - sum%11) % 11.\n */\nconst validateOther = (v: string): boolean => {\n const sum = weightedSum(v.slice(0, 9), WEIGHTS_OTHER, 11);\n return (11 - sum) % 11 === d(v, 9);\n};\n\nconst validate10 = (v: string): boolean =>\n validateEgn(v) || validatePnf(v) || validateOther(v);\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 9 && v.length !== 10) {\n return err(\n \"INVALID_LENGTH\",\n \"Bulgarian VAT number must be 9 or 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Bulgarian VAT number must contain only digits\",\n );\n }\n const valid =\n v.length === 9 ? validate9(v) : validate10(v);\n if (!valid) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Bulgarian VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `BG${compact(value)}`;\n\n/** Generate a random valid 9-digit Bulgarian VAT. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(9);\n if (validate(c).valid) return c;\n }\n};\n\n/** Bulgarian VAT Number. */\nconst vat: CountryValidator<\"BG\"> = {\n name: \"Bulgarian VAT Number\",\n localName: \"ИН по ДДС\",\n abbreviation: \"ИН по ДДС\",\n aliases: [\n \"ДДС\",\n \"идентификационен номер по ДДС\",\n ] as const,\n candidatePattern: \"BG\\\\d{9,10}\",\n scope: \"country\",\n country: \"BG\",\n entityType: \"any\",\n sourceUrl: \"https://www.nra.bg/\",\n lengths: [9, 10] as const,\n examples: [\"175074752\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"cpr.js","names":[],"sources":["../../src/bh/cpr.ts"],"sourcesContent":["/**\n * CPR (Central Population Registration number, Bahrain).\n *\n * 9-digit personal identification number:\n * YYMM = year and month of birth\n * NNNN = serial number\n * C = check digit\n *\n * The check digit algorithm is not publicly\n * documented; validation is structural only\n * (length, digits, and valid birth month).\n *\n * Note: a minority of older CPR numbers do not\n * follow the YYMMNNNNC format.\n *\n * @see https://www.bahrain.bh/wps/portal/IDInfo_en\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"Bahrain CPR must be 9 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Bahrain CPR must contain only digits\",\n );\n }\n\n // Validate birth month (digits 3-4) is 01-12\n const mm = Number(v.slice(2, 4));\n if (mm < 1 || mm > 12) {\n return err(\n \"INVALID_COMPONENT\",\n \"CPR birth month must be 01-12\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 2)}-${v.slice(2, 4)}-${v.slice(4)}`;\n};\n\n/** Generate a random structurally valid Bahrain CPR. */\nconst generate = (): string => {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n return `${yy}${mm}${randomDigits(5)}`;\n};\n\n/** Bahrain Central Population Registration number. */\nconst cpr: CountryValidator<\"BH\"> = {\n name: \"Central Population Registration Number\",\n localName: \"الرقم السكاني\",\n abbreviation: \"CPR\",\n aliases: [\"CPR\", \"الرقم السكاني\"] as const,\n candidatePattern: \"\\\\d{9}\",\n scope: \"country\",\n country: \"BH\",\n entityType: \"person\",\n lengths: [9] as const,\n examples: [\"890112345\", \"000612345\"] as const,\n description: \"9-digit personal identification number\",\n sourceUrl: \"https://www.bahrain.bh/wps/portal/IDInfo_en\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cpr;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;AA4BA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,8BACF;CAGF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,sCACF;CAIF,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,IAAI,KAAK,KAAK,KAAK,IACjB,OAAO,IACL,qBACA,+BACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACvD;;AAGA,MAAM,iBAAyB;CAG7B,OAAO,GAFI,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAErC,IADA,OAAO,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,GAAG,GAChC,IAAI,aAAa,CAAC;AACpC;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,eAAe;CAChC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,CAAC;CACX,UAAU,CAAC,aAAa,WAAW;CACnC,aAAa;CACb,WAAW;CACX;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"cpr.js","names":[],"sources":["../../src/bh/cpr.ts"],"sourcesContent":["/**\n * CPR (Central Population Registration number, Bahrain).\n *\n * 9-digit personal identification number:\n * YYMM = year and month of birth\n * NNNN = serial number\n * C = check digit\n *\n * The check digit algorithm is not publicly\n * documented; validation is structural only\n * (length, digits, and valid birth month).\n *\n * Note: a minority of older CPR numbers do not\n * follow the YYMMNNNNC format.\n *\n * @see https://www.bahrain.bh/wps/portal/IDInfo_en\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" -\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"Bahrain CPR must be 9 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Bahrain CPR must contain only digits\",\n );\n }\n\n // Validate birth month (digits 3-4) is 01-12\n const mm = Number(v.slice(2, 4));\n if (mm < 1 || mm > 12) {\n return err(\n \"INVALID_COMPONENT\",\n \"CPR birth month must be 01-12\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 2)}-${v.slice(2, 4)}-${v.slice(4)}`;\n};\n\n/** Generate a random structurally valid Bahrain CPR. */\nconst generate = (): string => {\n const yy = String(randomInt(0, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n return `${yy}${mm}${randomDigits(5)}`;\n};\n\n/** Bahrain Central Population Registration number. */\nconst cpr: CountryValidator<\"BH\"> = {\n name: \"Central Population Registration Number\",\n localName: \"الرقم السكاني\",\n abbreviation: \"CPR\",\n aliases: [\"CPR\", \"الرقم السكاني\"] as const,\n candidatePattern: \"\\\\d{9}\",\n scope: \"country\",\n country: \"BH\",\n entityType: \"person\",\n lengths: [9] as const,\n examples: [\"890112345\", \"000612345\"] as const,\n description: \"9-digit personal identification number\",\n sourceUrl: \"https://www.bahrain.bh/wps/portal/IDInfo_en\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cpr;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;AA4BA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,8BACF;CAGF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,sCACF;CAIF,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,IAAI,KAAK,KAAK,KAAK,IACjB,OAAO,IACL,qBACA,+BACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACvD;;AAGA,MAAM,iBAAyB;CAG7B,OAAO,GAFI,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAErC,IADA,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAChC,IAAI,aAAa,CAAC;AACpC;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,eAAe;CAChC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,CAAC;CACX,UAAU,CAAC,aAAa,WAAW;CACnC,aAAa;CACb,WAAW;CACX;CACA;CACA;CACA;AACF"}
package/dist/bic.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bic.js","names":[],"sources":["../src/bic.ts"],"sourcesContent":["const BIC_ALPHANUM = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\";\nconst BIC_COUNTRIES = [\n \"DE\",\n \"GB\",\n \"US\",\n \"FR\",\n \"CH\",\n \"NL\",\n \"AT\",\n] as const;\n\n/** Generate a random valid BIC (8-character). */\nconst generate = (): string => {\n const randomLetter = (): string =>\n String.fromCodePoint(65 + randomInt(0, 25));\n const country = randomPick(BIC_COUNTRIES);\n const bank =\n randomLetter() +\n randomLetter() +\n randomLetter() +\n randomLetter();\n const location =\n randomChar(BIC_ALPHANUM) + randomChar(BIC_ALPHANUM);\n return `${bank}${country}${location}`;\n};\n\n/**\n * BIC (Business Identifier Code).\n *\n * ISO 9362. 8 or 11 character code identifying\n * financial institutions. Format:\n * [A-Z]{4} (institution) + [A-Z]{2} (country) +\n * [0-9A-Z]{2} (location) + [0-9A-Z]{3} (branch,\n * optional).\n *\n * @see https://www.swift.com/\n */\n\nimport type {\n ValidateResult,\n GlobalValidator,\n} from \"./types\";\n\nimport { clean } from \"#util/clean\";\nimport {\n randomChar,\n randomInt,\n randomPick,\n} from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst BIC_RE =\n /^[A-Z]{4}[A-Z]{2}[0-9A-Z]{2}([0-9A-Z]{3})?$/;\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8 && v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"BIC must be 8 or 11 characters\",\n );\n }\n if (!BIC_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"BIC must be 8 or 11 alphanumeric characters\",\n );\n }\n // Country code at positions 4-5 is already\n // validated as [A-Z]{2} by the regex above.\n // SWIFT accepts all ISO 3166-1 alpha-2 codes\n // plus XK (Kosovo); we don't restrict further.\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 11) {\n return `${v.slice(0, 4)} ${v.slice(4, 6)} ${v.slice(6, 8)} ${v.slice(8)}`;\n }\n return `${v.slice(0, 4)} ${v.slice(4, 6)} ${v.slice(6)}`;\n};\n\n/** Business Identifier Code (SWIFT/BIC). */\nconst bic: GlobalValidator = {\n scope: \"global\",\n name: \"Business Identifier Code\",\n localName: \"Business Identifier Code\",\n abbreviation: \"BIC\",\n aliases: [\"BIC\", \"SWIFT\", \"BIC/SWIFT\"] as const,\n candidatePattern: \"[A-Z]{6}[A-Z0-9]{2}(?:[A-Z0-9]{3})?\",\n entityType: \"company\",\n sourceUrl: \"https://www.swift.com/\",\n examples: [\"DEUTDEFF\", \"DEUTDEFF500\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default bic;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAAA,MAAM,eAAe;AACrB,MAAM,gBAAgB;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAM,iBAAyB;CAC7B,MAAM,qBACJ,OAAO,cAAc,KAAK,UAAU,GAAG,EAAE,CAAC;CAC5C,MAAM,UAAU,WAAW,aAAa;CAQxC,OAAO,GANL,aAAa,IACb,aAAa,IACb,aAAa,IACb,aAAa,IAGE,UADf,WAAW,YAAY,IAAI,WAAW,YAAY;AAEtD;AA2BA,MAAM,SACJ;AAEF,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,EAAE,YAAY;AAEjC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,IACjC,OAAO,IACL,kBACA,gCACF;CAEF,IAAI,CAAC,OAAO,KAAK,CAAC,GAChB,OAAO,IACL,kBACA,6CACF;CAMF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAExE,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACvD;;AAGA,MAAM,MAAuB;CAC3B,OAAO;CACP,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EAAC;EAAO;EAAS;CAAW;CACrC,kBAAkB;CAClB,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,YAAY,aAAa;CACpC;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"bic.js","names":[],"sources":["../src/bic.ts"],"sourcesContent":["const BIC_ALPHANUM = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\";\nconst BIC_COUNTRIES = [\n \"DE\",\n \"GB\",\n \"US\",\n \"FR\",\n \"CH\",\n \"NL\",\n \"AT\",\n] as const;\n\n/** Generate a random valid BIC (8-character). */\nconst generate = (): string => {\n const randomLetter = (): string =>\n String.fromCodePoint(65 + randomInt(0, 25));\n const country = randomPick(BIC_COUNTRIES);\n const bank =\n randomLetter() +\n randomLetter() +\n randomLetter() +\n randomLetter();\n const location =\n randomChar(BIC_ALPHANUM) + randomChar(BIC_ALPHANUM);\n return `${bank}${country}${location}`;\n};\n\n/**\n * BIC (Business Identifier Code).\n *\n * ISO 9362. 8 or 11 character code identifying\n * financial institutions. Format:\n * [A-Z]{4} (institution) + [A-Z]{2} (country) +\n * [0-9A-Z]{2} (location) + [0-9A-Z]{3} (branch,\n * optional).\n *\n * @see https://www.swift.com/\n */\n\nimport type {\n ValidateResult,\n GlobalValidator,\n} from \"./types\";\n\nimport { clean } from \"#util/clean\";\nimport {\n randomChar,\n randomInt,\n randomPick,\n} from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst BIC_RE =\n /^[A-Z]{4}[A-Z]{2}[0-9A-Z]{2}([0-9A-Z]{3})?$/;\n\nconst compact = (value: string): string =>\n clean(value, \" -\").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8 && v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"BIC must be 8 or 11 characters\",\n );\n }\n if (!BIC_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"BIC must be 8 or 11 alphanumeric characters\",\n );\n }\n // Country code at positions 4-5 is already\n // validated as [A-Z]{2} by the regex above.\n // SWIFT accepts all ISO 3166-1 alpha-2 codes\n // plus XK (Kosovo); we don't restrict further.\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length === 11) {\n return `${v.slice(0, 4)} ${v.slice(4, 6)} ${v.slice(6, 8)} ${v.slice(8)}`;\n }\n return `${v.slice(0, 4)} ${v.slice(4, 6)} ${v.slice(6)}`;\n};\n\n/** Business Identifier Code (SWIFT/BIC). */\nconst bic: GlobalValidator = {\n scope: \"global\",\n name: \"Business Identifier Code\",\n localName: \"Business Identifier Code\",\n abbreviation: \"BIC\",\n aliases: [\"BIC\", \"SWIFT\", \"BIC/SWIFT\"] as const,\n candidatePattern: \"[A-Z]{6}[A-Z0-9]{2}(?:[A-Z0-9]{3})?\",\n entityType: \"company\",\n sourceUrl: \"https://www.swift.com/\",\n examples: [\"DEUTDEFF\", \"DEUTDEFF500\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default bic;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAAA,MAAM,eAAe;AACrB,MAAM,gBAAgB;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAM,iBAAyB;CAC7B,MAAM,qBACJ,OAAO,cAAc,KAAK,UAAU,GAAG,EAAE,CAAC;CAC5C,MAAM,UAAU,WAAW,aAAa;CAQxC,OAAO,GANL,aAAa,IACb,aAAa,IACb,aAAa,IACb,aAAa,IAGE,UADf,WAAW,YAAY,IAAI,WAAW,YAAY;AAEtD;AA2BA,MAAM,SACJ;AAEF,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,CAAC,CAAC,YAAY;AAEjC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,IACjC,OAAO,IACL,kBACA,gCACF;CAEF,IAAI,CAAC,OAAO,KAAK,CAAC,GAChB,OAAO,IACL,kBACA,6CACF;CAMF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;CAExE,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACvD;;AAGA,MAAM,MAAuB;CAC3B,OAAO;CACP,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EAAC;EAAO;EAAS;CAAW;CACrC,kBAAkB;CAClB,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,YAAY,aAAa;CACpC;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"cnpj.js","names":[],"sources":["../../src/br/cnpj.ts"],"sourcesContent":["/**\n * CNPJ (Cadastro Nacional da Pessoa Jurídica).\n *\n * Brazilian company tax identification number assigned by\n * the Receita Federal (Federal Revenue Service). The\n * number consists of 14 characters: 8 identifying the\n * company, 4 identifying the establishment (0001 for\n * headquarters), and 2 check digits computed using a\n * weighted modulo 11 algorithm.\n *\n * As of July 2026 the Receita Federal will begin issuing\n * alphanumeric CNPJs (letters A-Z in place of some\n * digits). The check digit algorithm uses ordinal values\n * (0-9 = 0-9, A-Z = 17-42) to support this.\n *\n * Format: NN.NNN.NNN/NNNN-DD (14 characters).\n *\n * @see https://www.gov.br/en/categories/finance-taxes-and-public-management/cpf-cnpj-and-other-records\n * @see https://en.wikipedia.org/wiki/CNPJ\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst CNPJ_RE = /^[\\dA-Z]+$/;\n\nconst compact = (value: string): string =>\n clean(value, \" -./\").trim().toUpperCase();\n\n/**\n * Convert a CNPJ character to its numeric value.\n * Digits 0-9 map to 0-9; letters A-Z map to their\n * char code minus 48 (matching python-stdnum's\n * `ord(n) - 48` convention: A=17, B=18, ..., Z=42).\n */\nconst charToValue = (ch: string): number =>\n ch.charCodeAt(0) - 48;\n\n/**\n * Calculate the two CNPJ check digits using the\n * Receita Federal modulo 11 algorithm.\n *\n * First check digit: weights [5,4,3,2,9,8,7,6,5,4,3,2]\n * applied to the first 12 characters.\n *\n * Second check digit: weights [6,5,4,3,2,9,8,7,6,5,4,3,2]\n * applied to the first 12 characters plus the first\n * check digit.\n */\nconst calcCheckDigits = (number: string): string => {\n const w1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];\n let sum = 0;\n for (let i = 0; i < 12; i++) {\n sum += (w1[i] ?? 0) * charToValue(number.charAt(i));\n }\n const d1 = ((11 - (sum % 11)) % 11) % 10;\n\n const w2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];\n sum = 0;\n for (let i = 0; i < 12; i++) {\n sum += (w2[i] ?? 0) * charToValue(number.charAt(i));\n }\n // Use the computed d1 (not the stored digit at\n // number[12]) so both check digits are derived\n // from the base alone.\n sum += (w2[12] ?? 0) * d1;\n const d2 = ((11 - (sum % 11)) % 11) % 10;\n\n return `${d1}${d2}`;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 14) {\n return err(\n \"INVALID_LENGTH\",\n \"CNPJ must be 14 characters\",\n );\n }\n if (!CNPJ_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CNPJ must contain only digits and uppercase letters\",\n );\n }\n // Reject all-zero base (first 12 chars).\n // Unlike CPF, we do not reject all-same-digit CNPJs;\n // python-stdnum only blocks the all-zero base, and\n // there is no official Receita Federal list of\n // blocked same-digit CNPJ sequences.\n if (v.startsWith(\"000000000000\")) {\n return err(\n \"INVALID_FORMAT\",\n \"CNPJ base must not be all zeros\",\n );\n }\n if (calcCheckDigits(v) !== v.slice(12)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CNPJ check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 2)}.${v.slice(2, 5)}.${v.slice(5, 8)}/${v.slice(8, 12)}-${v.slice(12)}`;\n};\n\n/** Generate a random valid CNPJ. */\nconst generate = (): string => {\n for (;;) {\n const base = randomDigits(12);\n if (base === \"000000000000\") continue;\n return base + calcCheckDigits(base);\n }\n};\n\n/**\n * Brazilian CNPJ (company tax ID).\n *\n * Examples sourced from publicly available Brazilian\n * corporate registries:\n * - Petrobras: 33.000.167/0001-01\n * - Banco do Brasil: 00.000.000/0001-91\n */\nconst cnpj: CountryValidator<\"BR\"> = {\n name: \"Brazilian CNPJ\",\n localName: \"Cadastro Nacional da Pessoa Jurídica\",\n abbreviation: \"CNPJ\",\n aliases: [\n \"CNPJ\",\n \"Cadastro Nacional da Pessoa Jurídica\",\n ] as const,\n candidatePattern:\n \"\\\\d{2}\\\\.?\\\\d{3}\\\\.?\\\\d{3}/?\\\\d{4}-?\\\\d{2}\",\n scope: \"country\",\n country: \"BR\",\n entityType: \"company\",\n sourceUrl: \"https://www.gov.br/receitafederal/\",\n examples: [\"33000167000101\", \"00000000000191\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cnpj;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AA8BA,MAAM,UAAU;AAEhB,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,EAAE,KAAK,EAAE,YAAY;;;;;;;AAQ1C,MAAM,eAAe,OACnB,GAAG,WAAW,CAAC,IAAI;;;;;;;;;;;;AAarB,MAAM,mBAAmB,WAA2B;CAClD,MAAM,KAAK;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;CAAC;CAC9C,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KACtB,QAAQ,GAAG,MAAM,KAAK,YAAY,OAAO,OAAO,CAAC,CAAC;CAEpD,MAAM,MAAO,KAAM,MAAM,MAAO,KAAM;CAEtC,MAAM,KAAK;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;CAAC;CACjD,MAAM;CACN,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KACtB,QAAQ,GAAG,MAAM,KAAK,YAAY,OAAO,OAAO,CAAC,CAAC;CAKpD,QAAQ,GAAG,OAAO,KAAK;CAGvB,OAAO,GAAG,MAFG,KAAM,MAAM,MAAO,KAAM;AAGxC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,4BACF;CAEF,IAAI,CAAC,QAAQ,KAAK,CAAC,GACjB,OAAO,IACL,kBACA,qDACF;CAOF,IAAI,EAAE,WAAW,cAAc,GAC7B,OAAO,IACL,kBACA,iCACF;CAEF,IAAI,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GACnC,OAAO,IACL,oBACA,2BACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;AAC3F;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,OAAO,aAAa,EAAE;EAC5B,IAAI,SAAS,gBAAgB;EAC7B,OAAO,OAAO,gBAAgB,IAAI;CACpC;AACF;;;;;;;;;AAUA,MAAM,OAA+B;CACnC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,QACA,sCACF;CACA,kBACE;CACF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,kBAAkB,gBAAgB;CAC7C;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"cnpj.js","names":[],"sources":["../../src/br/cnpj.ts"],"sourcesContent":["/**\n * CNPJ (Cadastro Nacional da Pessoa Jurídica).\n *\n * Brazilian company tax identification number assigned by\n * the Receita Federal (Federal Revenue Service). The\n * number consists of 14 characters: 8 identifying the\n * company, 4 identifying the establishment (0001 for\n * headquarters), and 2 check digits computed using a\n * weighted modulo 11 algorithm.\n *\n * As of July 2026 the Receita Federal will begin issuing\n * alphanumeric CNPJs (letters A-Z in place of some\n * digits). The check digit algorithm uses ordinal values\n * (0-9 = 0-9, A-Z = 17-42) to support this.\n *\n * Format: NN.NNN.NNN/NNNN-DD (14 characters).\n *\n * @see https://www.gov.br/en/categories/finance-taxes-and-public-management/cpf-cnpj-and-other-records\n * @see https://en.wikipedia.org/wiki/CNPJ\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst CNPJ_RE = /^[\\dA-Z]+$/;\n\nconst compact = (value: string): string =>\n clean(value, \" -./\").trim().toUpperCase();\n\n/**\n * Convert a CNPJ character to its numeric value.\n * Digits 0-9 map to 0-9; letters A-Z map to their\n * char code minus 48 (matching python-stdnum's\n * `ord(n) - 48` convention: A=17, B=18, ..., Z=42).\n */\nconst charToValue = (ch: string): number =>\n ch.charCodeAt(0) - 48;\n\n/**\n * Calculate the two CNPJ check digits using the\n * Receita Federal modulo 11 algorithm.\n *\n * First check digit: weights [5,4,3,2,9,8,7,6,5,4,3,2]\n * applied to the first 12 characters.\n *\n * Second check digit: weights [6,5,4,3,2,9,8,7,6,5,4,3,2]\n * applied to the first 12 characters plus the first\n * check digit.\n */\nconst calcCheckDigits = (number: string): string => {\n const w1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];\n let sum = 0;\n for (let i = 0; i < 12; i++) {\n sum += (w1[i] ?? 0) * charToValue(number.charAt(i));\n }\n const d1 = ((11 - (sum % 11)) % 11) % 10;\n\n const w2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];\n sum = 0;\n for (let i = 0; i < 12; i++) {\n sum += (w2[i] ?? 0) * charToValue(number.charAt(i));\n }\n // Use the computed d1 (not the stored digit at\n // number[12]) so both check digits are derived\n // from the base alone.\n sum += (w2[12] ?? 0) * d1;\n const d2 = ((11 - (sum % 11)) % 11) % 10;\n\n return `${d1}${d2}`;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 14) {\n return err(\n \"INVALID_LENGTH\",\n \"CNPJ must be 14 characters\",\n );\n }\n if (!CNPJ_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CNPJ must contain only digits and uppercase letters\",\n );\n }\n // Reject all-zero base (first 12 chars).\n // Unlike CPF, we do not reject all-same-digit CNPJs;\n // python-stdnum only blocks the all-zero base, and\n // there is no official Receita Federal list of\n // blocked same-digit CNPJ sequences.\n if (v.startsWith(\"000000000000\")) {\n return err(\n \"INVALID_FORMAT\",\n \"CNPJ base must not be all zeros\",\n );\n }\n if (calcCheckDigits(v) !== v.slice(12)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CNPJ check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 2)}.${v.slice(2, 5)}.${v.slice(5, 8)}/${v.slice(8, 12)}-${v.slice(12)}`;\n};\n\n/** Generate a random valid CNPJ. */\nconst generate = (): string => {\n for (;;) {\n const base = randomDigits(12);\n if (base === \"000000000000\") continue;\n return base + calcCheckDigits(base);\n }\n};\n\n/**\n * Brazilian CNPJ (company tax ID).\n *\n * Examples sourced from publicly available Brazilian\n * corporate registries:\n * - Petrobras: 33.000.167/0001-01\n * - Banco do Brasil: 00.000.000/0001-91\n */\nconst cnpj: CountryValidator<\"BR\"> = {\n name: \"Brazilian CNPJ\",\n localName: \"Cadastro Nacional da Pessoa Jurídica\",\n abbreviation: \"CNPJ\",\n aliases: [\n \"CNPJ\",\n \"Cadastro Nacional da Pessoa Jurídica\",\n ] as const,\n candidatePattern:\n \"\\\\d{2}\\\\.?\\\\d{3}\\\\.?\\\\d{3}/?\\\\d{4}-?\\\\d{2}\",\n scope: \"country\",\n country: \"BR\",\n entityType: \"company\",\n sourceUrl: \"https://www.gov.br/receitafederal/\",\n examples: [\"33000167000101\", \"00000000000191\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cnpj;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AA8BA,MAAM,UAAU;AAEhB,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY;;;;;;;AAQ1C,MAAM,eAAe,OACnB,GAAG,WAAW,CAAC,IAAI;;;;;;;;;;;;AAarB,MAAM,mBAAmB,WAA2B;CAClD,MAAM,KAAK;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;CAAC;CAC9C,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KACtB,QAAQ,GAAG,MAAM,KAAK,YAAY,OAAO,OAAO,CAAC,CAAC;CAEpD,MAAM,MAAO,KAAM,MAAM,MAAO,KAAM;CAEtC,MAAM,KAAK;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;CAAC;CACjD,MAAM;CACN,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KACtB,QAAQ,GAAG,MAAM,KAAK,YAAY,OAAO,OAAO,CAAC,CAAC;CAKpD,QAAQ,GAAG,OAAO,KAAK;CAGvB,OAAO,GAAG,MAFG,KAAM,MAAM,MAAO,KAAM;AAGxC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,4BACF;CAEF,IAAI,CAAC,QAAQ,KAAK,CAAC,GACjB,OAAO,IACL,kBACA,qDACF;CAOF,IAAI,EAAE,WAAW,cAAc,GAC7B,OAAO,IACL,kBACA,iCACF;CAEF,IAAI,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GACnC,OAAO,IACL,oBACA,2BACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;AAC3F;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,OAAO,aAAa,EAAE;EAC5B,IAAI,SAAS,gBAAgB;EAC7B,OAAO,OAAO,gBAAgB,IAAI;CACpC;AACF;;;;;;;;;AAUA,MAAM,OAA+B;CACnC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,QACA,sCACF;CACA,kBACE;CACF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,kBAAkB,gBAAgB;CAC7C;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"cpf.js","names":[],"sources":["../../src/br/cpf.ts"],"sourcesContent":["/**\n * CPF (Cadastro de Pessoas Físicas).\n *\n * Brazilian personal tax identification number assigned\n * by the Receita Federal (Federal Revenue Service) to\n * individuals. The number consists of 11 digits: 9 base\n * digits followed by 2 check digits computed using a\n * weighted modulo 11 algorithm.\n *\n * Format: NNN.NNN.NNN-DD (11 digits, purely numeric).\n *\n * @see https://www.gov.br/en/categories/finance-taxes-and-public-management/cpf-cnpj-and-other-records\n * @see https://en.wikipedia.org/wiki/CPF_number\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" -.\").trim();\n\n/**\n * Calculate the two CPF check digits using the\n * Receita Federal modulo 11 algorithm.\n *\n * First check digit: multiply digits 0..8 by weights\n * 10..2, sum, then (11 - sum % 11) % 11 % 10.\n *\n * Second check digit: multiply digits 0..8 by weights\n * 11..3, add 2 * first check digit, then\n * (11 - sum % 11) % 11 % 10.\n */\nconst calcCheckDigits = (number: string): string => {\n let sum = 0;\n for (let i = 0; i < 9; i++) {\n sum += (10 - i) * Number(number[i]);\n }\n const d1 = ((11 - (sum % 11)) % 11) % 10;\n\n sum = 0;\n for (let i = 0; i < 9; i++) {\n sum += (11 - i) * Number(number[i]);\n }\n sum += 2 * d1;\n const d2 = ((11 - (sum % 11)) % 11) % 10;\n\n return `${d1}${d2}`;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\"INVALID_LENGTH\", \"CPF must be 11 digits\");\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CPF must contain only digits\",\n );\n }\n // All-same-digit CPFs (e.g. 000.000.000-00) pass the\n // checksum but are not valid registrations.\n if (/^(\\d)\\1{10}$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CPF must not be a repeated digit sequence\",\n );\n }\n if (calcCheckDigits(v) !== v.slice(9)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CPF check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 3)}.${v.slice(3, 6)}.${v.slice(6, 9)}-${v.slice(9)}`;\n};\n\n/** Generate a random valid CPF. */\nconst generate = (): string => {\n for (;;) {\n const base = randomDigits(9);\n if (/^(\\d)\\1{8}$/.test(base)) continue;\n return base + calcCheckDigits(base);\n }\n};\n\n/** Brazilian CPF (personal tax ID). */\nconst cpf: CountryValidator<\"BR\"> = {\n name: \"Brazilian CPF\",\n localName: \"Cadastro de Pessoas Físicas\",\n abbreviation: \"CPF\",\n aliases: [\"CPF\", \"Cadastro de Pessoas Físicas\"] as const,\n candidatePattern: \"\\\\d{3}\\\\.?\\\\d{3}\\\\.?\\\\d{3}-?\\\\d{2}\",\n scope: \"country\",\n country: \"BR\",\n entityType: \"person\",\n sourceUrl: \"https://www.gov.br/receitafederal/\",\n examples: [\"39053344705\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cpf;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAyBA,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,EAAE,KAAK;;;;;;;;;;;;AAa3B,MAAM,mBAAmB,WAA2B;CAClD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,QAAQ,KAAK,KAAK,OAAO,OAAO,EAAE;CAEpC,MAAM,MAAO,KAAM,MAAM,MAAO,KAAM;CAEtC,MAAM;CACN,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,QAAQ,KAAK,KAAK,OAAO,OAAO,EAAE;CAEpC,OAAO,IAAI;CAGX,OAAO,GAAG,MAFG,KAAM,MAAM,MAAO,KAAM;AAGxC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IAAI,kBAAkB,uBAAuB;CAEtD,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAIF,IAAI,eAAe,KAAK,CAAC,GACvB,OAAO,IACL,kBACA,2CACF;CAEF,IAAI,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,OAAO,IACL,oBACA,0BACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACxE;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,OAAO,aAAa,CAAC;EAC3B,IAAI,cAAc,KAAK,IAAI,GAAG;EAC9B,OAAO,OAAO,gBAAgB,IAAI;CACpC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,6BAA6B;CAC9C,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"cpf.js","names":[],"sources":["../../src/br/cpf.ts"],"sourcesContent":["/**\n * CPF (Cadastro de Pessoas Físicas).\n *\n * Brazilian personal tax identification number assigned\n * by the Receita Federal (Federal Revenue Service) to\n * individuals. The number consists of 11 digits: 9 base\n * digits followed by 2 check digits computed using a\n * weighted modulo 11 algorithm.\n *\n * Format: NNN.NNN.NNN-DD (11 digits, purely numeric).\n *\n * @see https://www.gov.br/en/categories/finance-taxes-and-public-management/cpf-cnpj-and-other-records\n * @see https://en.wikipedia.org/wiki/CPF_number\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst compact = (value: string): string =>\n clean(value, \" -.\").trim();\n\n/**\n * Calculate the two CPF check digits using the\n * Receita Federal modulo 11 algorithm.\n *\n * First check digit: multiply digits 0..8 by weights\n * 10..2, sum, then (11 - sum % 11) % 11 % 10.\n *\n * Second check digit: multiply digits 0..8 by weights\n * 11..3, add 2 * first check digit, then\n * (11 - sum % 11) % 11 % 10.\n */\nconst calcCheckDigits = (number: string): string => {\n let sum = 0;\n for (let i = 0; i < 9; i++) {\n sum += (10 - i) * Number(number[i]);\n }\n const d1 = ((11 - (sum % 11)) % 11) % 10;\n\n sum = 0;\n for (let i = 0; i < 9; i++) {\n sum += (11 - i) * Number(number[i]);\n }\n sum += 2 * d1;\n const d2 = ((11 - (sum % 11)) % 11) % 10;\n\n return `${d1}${d2}`;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\"INVALID_LENGTH\", \"CPF must be 11 digits\");\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CPF must contain only digits\",\n );\n }\n // All-same-digit CPFs (e.g. 000.000.000-00) pass the\n // checksum but are not valid registrations.\n if (/^(\\d)\\1{10}$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"CPF must not be a repeated digit sequence\",\n );\n }\n if (calcCheckDigits(v) !== v.slice(9)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"CPF check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, 3)}.${v.slice(3, 6)}.${v.slice(6, 9)}-${v.slice(9)}`;\n};\n\n/** Generate a random valid CPF. */\nconst generate = (): string => {\n for (;;) {\n const base = randomDigits(9);\n if (/^(\\d)\\1{8}$/.test(base)) continue;\n return base + calcCheckDigits(base);\n }\n};\n\n/** Brazilian CPF (personal tax ID). */\nconst cpf: CountryValidator<\"BR\"> = {\n name: \"Brazilian CPF\",\n localName: \"Cadastro de Pessoas Físicas\",\n abbreviation: \"CPF\",\n aliases: [\"CPF\", \"Cadastro de Pessoas Físicas\"] as const,\n candidatePattern: \"\\\\d{3}\\\\.?\\\\d{3}\\\\.?\\\\d{3}-?\\\\d{2}\",\n scope: \"country\",\n country: \"BR\",\n entityType: \"person\",\n sourceUrl: \"https://www.gov.br/receitafederal/\",\n examples: [\"39053344705\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default cpf;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAyBA,MAAM,WAAW,UACf,MAAM,OAAO,KAAK,CAAC,CAAC,KAAK;;;;;;;;;;;;AAa3B,MAAM,mBAAmB,WAA2B;CAClD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,QAAQ,KAAK,KAAK,OAAO,OAAO,EAAE;CAEpC,MAAM,MAAO,KAAM,MAAM,MAAO,KAAM;CAEtC,MAAM;CACN,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,QAAQ,KAAK,KAAK,OAAO,OAAO,EAAE;CAEpC,OAAO,IAAI;CAGX,OAAO,GAAG,MAFG,KAAM,MAAM,MAAO,KAAM;AAGxC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IAAI,kBAAkB,uBAAuB;CAEtD,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,8BACF;CAIF,IAAI,eAAe,KAAK,CAAC,GACvB,OAAO,IACL,kBACA,2CACF;CAEF,IAAI,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,OAAO,IACL,oBACA,0BACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACxE;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,OAAO,aAAa,CAAC;EAC3B,IAAI,cAAc,KAAK,IAAI,GAAG;EAC9B,OAAO,OAAO,gBAAgB,IAAI;CACpC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,6BAA6B;CAC9C,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"unp.js","names":[],"sources":["../../src/by/unp.ts"],"sourcesContent":["/**\n * UNP (Учётный номер плательщика, Belarus tax number).\n *\n * 9 characters: the first two identify the region (numeric\n * for organisations, letters from ABCEHKMOPT for\n * individuals), followed by 7 digits. The last digit is a\n * weighted check digit (mod 11; if remainder > 9 the\n * number is invalid).\n *\n * @see https://be.wikipedia.org/wiki/Уліковы_нумар_плацельшчыка\n * @see https://www.nalog.gov.by/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/** Cyrillic to Latin mapping for the letter positions. */\nconst CYRILLIC_TO_LATIN: Record<string, string> = {\n А: \"A\",\n В: \"B\",\n Е: \"E\",\n К: \"K\",\n М: \"M\",\n Н: \"H\",\n О: \"O\",\n Р: \"P\",\n С: \"C\",\n Т: \"T\",\n};\n\nconst WEIGHTS = [29, 23, 19, 17, 13, 7, 5, 3] as const;\nconst ALPHA_SET = \"ABCEHKMOPT\";\nconst VALID_FIRST = \"1234567ABCEHKM\";\nconst ALPHABET = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\nconst compact = (value: string): string => {\n let v = clean(value, \" \").toUpperCase().trim();\n if (v.startsWith(\"УНП\")) {\n v = v.slice(3);\n } else if (v.startsWith(\"UNP\")) {\n v = v.slice(3);\n }\n return v\n .split(\"\")\n .map((ch) => CYRILLIC_TO_LATIN[ch] ?? ch)\n .join(\"\");\n};\n\nconst calcCheckDigit = (number: string): number | null => {\n let work = number;\n if (!isdigits(number)) {\n const second = number[1];\n if (second === undefined) return null;\n const idx = ALPHA_SET.indexOf(second);\n if (idx === -1) return null;\n work = number[0] + String(idx) + number.slice(2);\n }\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n const ch = work[i];\n if (ch === undefined) return null;\n const val = ALPHABET.indexOf(ch);\n if (val === -1) return null;\n sum += weight * val;\n }\n const remainder = sum % 11;\n if (remainder > 9) return null;\n return remainder;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"Belarus UNP must be 9 characters\",\n );\n }\n if (!isdigits(v.slice(2))) {\n return err(\n \"INVALID_FORMAT\",\n \"Belarus UNP positions 3-9 must be digits\",\n );\n }\n const first2 = v.slice(0, 2);\n if (\n !isdigits(first2) &&\n !first2.split(\"\").every((ch) => ALPHA_SET.includes(ch))\n ) {\n return err(\n \"INVALID_FORMAT\",\n \"Belarus UNP first two characters must be\" +\n \" digits or letters from ABCEHKMOPT\",\n );\n }\n // SAFETY: v.length === 9 guarantees v[0] exists.\n // eslint-disable-next-line no-non-null-assertion\n if (!VALID_FIRST.includes(v[0]!)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Belarus UNP has an invalid region prefix\",\n );\n }\n const expected = calcCheckDigit(v);\n if (expected === null) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Belarus UNP check digit is invalid\" +\n \" (mod 11 remainder > 9)\",\n );\n }\n if (v[8] !== String(expected)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Belarus UNP check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Belarus UNP. */\nconst generate = (): string => {\n for (let i = 0; i < 100; i++) {\n const prefix = String(randomInt(1, 7));\n const rest = randomDigits(7);\n const payload = prefix + rest;\n const check = calcCheckDigit(payload);\n if (check === null) continue;\n const c = payload.slice(0, 8) + String(check);\n if (validate(c).valid) return c;\n }\n throw new Error(\"Failed to generate valid UNP\");\n};\n\n/** Belarus UNP (Учётный номер плательщика). */\nconst unp: CountryValidator<\"BY\"> = {\n name: \"Belarus Tax Number\",\n localName: \"Учётный номер плательщика\",\n abbreviation: \"УНП\",\n aliases: [\"УНП\", \"UNP\"] as const,\n candidatePattern: \"\\\\d{9}\",\n scope: \"country\",\n country: \"BY\",\n entityType: \"any\",\n sourceUrl: \"https://www.nalog.gov.by/\",\n examples: [\"200988541\", \"MA1953684\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default unp;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAwBA,MAAM,oBAA4C;CAChD,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;AACL;AAEA,MAAM,UAAU;CAAC;CAAI;CAAI;CAAI;CAAI;CAAI;CAAG;CAAG;AAAC;AAC5C,MAAM,YAAY;AAClB,MAAM,cAAc;AACpB,MAAM,WAAW;AAEjB,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,GAAG,EAAE,YAAY,EAAE,KAAK;CAC7C,IAAI,EAAE,WAAW,KAAK,GACpB,IAAI,EAAE,MAAM,CAAC;MACR,IAAI,EAAE,WAAW,KAAK,GAC3B,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO,EACJ,MAAM,EAAE,EACR,KAAK,OAAO,kBAAkB,OAAO,EAAE,EACvC,KAAK,EAAE;AACZ;AAEA,MAAM,kBAAkB,WAAkC;CACxD,IAAI,OAAO;CACX,IAAI,CAAC,SAAS,MAAM,GAAG;EACrB,MAAM,SAAS,OAAO;EACtB,IAAI,WAAW,KAAA,GAAW,OAAO;EACjC,MAAM,MAAM,UAAU,QAAQ,MAAM;EACpC,IAAI,QAAQ,IAAI,OAAO;EACvB,OAAO,OAAO,KAAK,OAAO,GAAG,IAAI,OAAO,MAAM,CAAC;CACjD;CACA,IAAI,MAAM;CACV,KAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,QAAQ,GAAG;EAC3C,MAAM,KAAK,KAAK;EAChB,IAAI,OAAO,KAAA,GAAW,OAAO;EAC7B,MAAM,MAAM,SAAS,QAAQ,EAAE;EAC/B,IAAI,QAAQ,IAAI,OAAO;EACvB,OAAO,SAAS;CAClB;CACA,MAAM,YAAY,MAAM;CACxB,IAAI,YAAY,GAAG,OAAO;CAC1B,OAAO;AACT;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,kCACF;CAEF,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,GACtB,OAAO,IACL,kBACA,0CACF;CAEF,MAAM,SAAS,EAAE,MAAM,GAAG,CAAC;CAC3B,IACE,CAAC,SAAS,MAAM,KAChB,CAAC,OAAO,MAAM,EAAE,EAAE,OAAO,OAAO,UAAU,SAAS,EAAE,CAAC,GAEtD,OAAO,IACL,kBACA,4EAEF;CAIF,IAAI,CAAC,YAAY,SAAS,EAAE,EAAG,GAC7B,OAAO,IACL,qBACA,0CACF;CAEF,MAAM,WAAW,eAAe,CAAC;CACjC,IAAI,aAAa,MACf,OAAO,IACL,oBACA,2DAEF;CAEF,IAAI,EAAE,OAAO,OAAO,QAAQ,GAC1B,OAAO,IACL,oBACA,kCACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;;AAGvD,MAAM,iBAAyB;CAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK;EAG5B,MAAM,UAFS,OAAO,UAAU,GAAG,CAAC,CAEf,IADR,aAAa,CACE;EAC5B,MAAM,QAAQ,eAAe,OAAO;EACpC,IAAI,UAAU,MAAM;EACpB,MAAM,IAAI,QAAQ,MAAM,GAAG,CAAC,IAAI,OAAO,KAAK;EAC5C,IAAI,SAAS,CAAC,EAAE,OAAO,OAAO;CAChC;CACA,MAAM,IAAI,MAAM,8BAA8B;AAChD;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,KAAK;CACtB,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,aAAa,WAAW;CACnC;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"unp.js","names":[],"sources":["../../src/by/unp.ts"],"sourcesContent":["/**\n * UNP (Учётный номер плательщика, Belarus tax number).\n *\n * 9 characters: the first two identify the region (numeric\n * for organisations, letters from ABCEHKMOPT for\n * individuals), followed by 7 digits. The last digit is a\n * weighted check digit (mod 11; if remainder > 9 the\n * number is invalid).\n *\n * @see https://be.wikipedia.org/wiki/Уліковы_нумар_плацельшчыка\n * @see https://www.nalog.gov.by/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/** Cyrillic to Latin mapping for the letter positions. */\nconst CYRILLIC_TO_LATIN: Record<string, string> = {\n А: \"A\",\n В: \"B\",\n Е: \"E\",\n К: \"K\",\n М: \"M\",\n Н: \"H\",\n О: \"O\",\n Р: \"P\",\n С: \"C\",\n Т: \"T\",\n};\n\nconst WEIGHTS = [29, 23, 19, 17, 13, 7, 5, 3] as const;\nconst ALPHA_SET = \"ABCEHKMOPT\";\nconst VALID_FIRST = \"1234567ABCEHKM\";\nconst ALPHABET = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\nconst compact = (value: string): string => {\n let v = clean(value, \" \").toUpperCase().trim();\n if (v.startsWith(\"УНП\")) {\n v = v.slice(3);\n } else if (v.startsWith(\"UNP\")) {\n v = v.slice(3);\n }\n return v\n .split(\"\")\n .map((ch) => CYRILLIC_TO_LATIN[ch] ?? ch)\n .join(\"\");\n};\n\nconst calcCheckDigit = (number: string): number | null => {\n let work = number;\n if (!isdigits(number)) {\n const second = number[1];\n if (second === undefined) return null;\n const idx = ALPHA_SET.indexOf(second);\n if (idx === -1) return null;\n work = number[0] + String(idx) + number.slice(2);\n }\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n const ch = work[i];\n if (ch === undefined) return null;\n const val = ALPHABET.indexOf(ch);\n if (val === -1) return null;\n sum += weight * val;\n }\n const remainder = sum % 11;\n if (remainder > 9) return null;\n return remainder;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"Belarus UNP must be 9 characters\",\n );\n }\n if (!isdigits(v.slice(2))) {\n return err(\n \"INVALID_FORMAT\",\n \"Belarus UNP positions 3-9 must be digits\",\n );\n }\n const first2 = v.slice(0, 2);\n if (\n !isdigits(first2) &&\n !first2.split(\"\").every((ch) => ALPHA_SET.includes(ch))\n ) {\n return err(\n \"INVALID_FORMAT\",\n \"Belarus UNP first two characters must be\" +\n \" digits or letters from ABCEHKMOPT\",\n );\n }\n // SAFETY: v.length === 9 guarantees v[0] exists.\n // eslint-disable-next-line no-non-null-assertion\n if (!VALID_FIRST.includes(v[0]!)) {\n return err(\n \"INVALID_COMPONENT\",\n \"Belarus UNP has an invalid region prefix\",\n );\n }\n const expected = calcCheckDigit(v);\n if (expected === null) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Belarus UNP check digit is invalid\" +\n \" (mod 11 remainder > 9)\",\n );\n }\n if (v[8] !== String(expected)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Belarus UNP check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Generate a random valid Belarus UNP. */\nconst generate = (): string => {\n for (let i = 0; i < 100; i++) {\n const prefix = String(randomInt(1, 7));\n const rest = randomDigits(7);\n const payload = prefix + rest;\n const check = calcCheckDigit(payload);\n if (check === null) continue;\n const c = payload.slice(0, 8) + String(check);\n if (validate(c).valid) return c;\n }\n throw new Error(\"Failed to generate valid UNP\");\n};\n\n/** Belarus UNP (Учётный номер плательщика). */\nconst unp: CountryValidator<\"BY\"> = {\n name: \"Belarus Tax Number\",\n localName: \"Учётный номер плательщика\",\n abbreviation: \"УНП\",\n aliases: [\"УНП\", \"UNP\"] as const,\n candidatePattern: \"\\\\d{9}\",\n scope: \"country\",\n country: \"BY\",\n entityType: \"any\",\n sourceUrl: \"https://www.nalog.gov.by/\",\n examples: [\"200988541\", \"MA1953684\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default unp;\nexport { compact, format, validate, generate };\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tin.js","names":[],"sources":["../../src/bz/tin.ts"],"sourcesContent":["/**\n * TIN (Belize Tax Identification Number).\n *\n * Issued by the Belize Tax Service Department to\n * individuals, sole proprietors, partnerships, and\n * companies. The base number is 6 digits generated\n * by the Revenue Management System. A 2-digit\n * suffix code may be appended to indicate entity\n * type:\n * - 10: individual\n * - 13: company\n * - 66: company (alternate)\n *\n * The OECD spec mentions a 7th check digit that is\n * not visible to the taxpayer; in practice the\n * number circulates as 6 or 8 digits (6 + suffix).\n *\n * Formatted as NNNNNN-SS (when suffix is present).\n *\n * Source: OECD CRS TIN information sheet; Belize\n * Tax Service (https://bts.gov.bz/).\n *\n * PERSON/ENTITY\n *\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Belize-TIN.pdf\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\n/** Valid 2-digit suffix codes. */\nconst SUFFIX_CODES = [\"10\", \"13\", \"66\"] as const;\n\nconst compact = (value: string): string => {\n return clean(value, \" -\").trim();\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 6 && v.length !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"Belize TIN must be 6 or 8 digits\",\n );\n }\n\n if (!/^\\d+$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Belize TIN must contain only digits\",\n );\n }\n\n if (v.length === 8) {\n const suffix = v.slice(6);\n if (\n !SUFFIX_CODES.includes(\n suffix as (typeof SUFFIX_CODES)[number],\n )\n ) {\n return err(\n \"INVALID_COMPONENT\",\n \"Belize TIN suffix must be 10, 13, or 66\",\n );\n }\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length <= 6) {\n return v;\n }\n return `${v.slice(0, 6)}-${v.slice(6)}`;\n};\n\n/** Generate a random valid Belize TIN. */\nconst generate = (): string => {\n const base = randomDigits(6);\n const suffixes = [\"\", ...SUFFIX_CODES] as const;\n const suffix =\n suffixes[randomInt(0, suffixes.length - 1)] ?? \"\";\n return `${base}${suffix}`;\n};\n\n/**\n * Belize Tax Identification Number.\n *\n * Examples derived from stdnum-js test suite.\n */\nconst tin: CountryValidator<\"BZ\"> = {\n name: \"Belize Tax Identification Number\",\n localName: \"Tax Identification Number\",\n abbreviation: \"TIN\",\n aliases: [\"TIN\"] as const,\n candidatePattern: \"\\\\d{6}\",\n scope: \"country\",\n country: \"BZ\",\n entityType: \"any\",\n lengths: [6, 8] as const,\n examples: [\"000005\", \"00000510\", \"00000513\"] as const,\n compact,\n format,\n validate,\n generate,\n description:\n \"Belize tax number issued by the Belize Tax Service Department\",\n sourceUrl:\n \"https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Belize-TIN.pdf\",\n};\n\nexport default tin;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;AAqCA,MAAM,eAAe;CAAC;CAAM;CAAM;AAAI;AAEtC,MAAM,WAAW,UAA0B;CACzC,OAAO,MAAM,OAAO,IAAI,EAAE,KAAK;AACjC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,OAAO,IACL,kBACA,kCACF;CAGF,IAAI,CAAC,QAAQ,KAAK,CAAC,GACjB,OAAO,IACL,kBACA,qCACF;CAGF,IAAI,EAAE,WAAW,GAAG;EAClB,MAAM,SAAS,EAAE,MAAM,CAAC;EACxB,IACE,CAAC,aAAa,SACZ,MACF,GAEA,OAAO,IACL,qBACA,yCACF;CAEJ;CAEA,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,UAAU,GACd,OAAO;CAET,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACtC;;AAGA,MAAM,iBAAyB;CAC7B,MAAM,OAAO,aAAa,CAAC;CAC3B,MAAM,WAAW,CAAC,IAAI,GAAG,YAAY;CAGrC,OAAO,GAAG,OADR,SAAS,UAAU,GAAG,SAAS,SAAS,CAAC,MAAM;AAEnD;;;;;;AAOA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,KAAK;CACf,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,GAAG,CAAC;CACd,UAAU;EAAC;EAAU;EAAY;CAAU;CAC3C;CACA;CACA;CACA;CACA,aACE;CACF,WACE;AACJ"}
1
+ {"version":3,"file":"tin.js","names":[],"sources":["../../src/bz/tin.ts"],"sourcesContent":["/**\n * TIN (Belize Tax Identification Number).\n *\n * Issued by the Belize Tax Service Department to\n * individuals, sole proprietors, partnerships, and\n * companies. The base number is 6 digits generated\n * by the Revenue Management System. A 2-digit\n * suffix code may be appended to indicate entity\n * type:\n * - 10: individual\n * - 13: company\n * - 66: company (alternate)\n *\n * The OECD spec mentions a 7th check digit that is\n * not visible to the taxpayer; in practice the\n * number circulates as 6 or 8 digits (6 + suffix).\n *\n * Formatted as NNNNNN-SS (when suffix is present).\n *\n * Source: OECD CRS TIN information sheet; Belize\n * Tax Service (https://bts.gov.bz/).\n *\n * PERSON/ENTITY\n *\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Belize-TIN.pdf\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\n/** Valid 2-digit suffix codes. */\nconst SUFFIX_CODES = [\"10\", \"13\", \"66\"] as const;\n\nconst compact = (value: string): string => {\n return clean(value, \" -\").trim();\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 6 && v.length !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"Belize TIN must be 6 or 8 digits\",\n );\n }\n\n if (!/^\\d+$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Belize TIN must contain only digits\",\n );\n }\n\n if (v.length === 8) {\n const suffix = v.slice(6);\n if (\n !SUFFIX_CODES.includes(\n suffix as (typeof SUFFIX_CODES)[number],\n )\n ) {\n return err(\n \"INVALID_COMPONENT\",\n \"Belize TIN suffix must be 10, 13, or 66\",\n );\n }\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.length <= 6) {\n return v;\n }\n return `${v.slice(0, 6)}-${v.slice(6)}`;\n};\n\n/** Generate a random valid Belize TIN. */\nconst generate = (): string => {\n const base = randomDigits(6);\n const suffixes = [\"\", ...SUFFIX_CODES] as const;\n const suffix =\n suffixes[randomInt(0, suffixes.length - 1)] ?? \"\";\n return `${base}${suffix}`;\n};\n\n/**\n * Belize Tax Identification Number.\n *\n * Examples derived from stdnum-js test suite.\n */\nconst tin: CountryValidator<\"BZ\"> = {\n name: \"Belize Tax Identification Number\",\n localName: \"Tax Identification Number\",\n abbreviation: \"TIN\",\n aliases: [\"TIN\"] as const,\n candidatePattern: \"\\\\d{6}\",\n scope: \"country\",\n country: \"BZ\",\n entityType: \"any\",\n lengths: [6, 8] as const,\n examples: [\"000005\", \"00000510\", \"00000513\"] as const,\n compact,\n format,\n validate,\n generate,\n description:\n \"Belize tax number issued by the Belize Tax Service Department\",\n sourceUrl:\n \"https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Belize-TIN.pdf\",\n};\n\nexport default tin;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;AAqCA,MAAM,eAAe;CAAC;CAAM;CAAM;AAAI;AAEtC,MAAM,WAAW,UAA0B;CACzC,OAAO,MAAM,OAAO,IAAI,CAAC,CAAC,KAAK;AACjC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,OAAO,IACL,kBACA,kCACF;CAGF,IAAI,CAAC,QAAQ,KAAK,CAAC,GACjB,OAAO,IACL,kBACA,qCACF;CAGF,IAAI,EAAE,WAAW,GAAG;EAClB,MAAM,SAAS,EAAE,MAAM,CAAC;EACxB,IACE,CAAC,aAAa,SACZ,MACF,GAEA,OAAO,IACL,qBACA,yCACF;CAEJ;CAEA,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,UAAU,GACd,OAAO;CAET,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACtC;;AAGA,MAAM,iBAAyB;CAC7B,MAAM,OAAO,aAAa,CAAC;CAC3B,MAAM,WAAW,CAAC,IAAI,GAAG,YAAY;CAGrC,OAAO,GAAG,OADR,SAAS,UAAU,GAAG,SAAS,SAAS,CAAC,MAAM;AAEnD;;;;;;AAOA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,KAAK;CACf,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,GAAG,CAAC;CACd,UAAU;EAAC;EAAU;EAAY;CAAU;CAC3C;CACA;CACA;CACA;CACA,aACE;CACF,WACE;AACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"uid.js","names":[],"sources":["../../src/ch/uid.ts"],"sourcesContent":["/**\n * UID (Unternehmens-Identifikationsnummer).\n *\n * Swiss business identification number. 12 characters:\n * \"CHE\" prefix + 9 digits. Check digit uses weights\n * [5,4,3,2,7,6,5,4] on the first 8 digits.\n *\n * @see https://www.uid.admin.ch/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [5, 4, 3, 2, 7, 6, 5, 4] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -./\").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Swiss UID must be CHE + 9 digits\",\n );\n }\n if (!v.startsWith(\"CHE\")) {\n return err(\n \"INVALID_COMPONENT\",\n \"Swiss UID must start with CHE\",\n );\n }\n const digits = v.slice(3);\n if (!isdigits(digits)) {\n return err(\n \"INVALID_FORMAT\",\n \"Swiss UID must be CHE + 9 digits\",\n );\n }\n\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n sum += Number(digits.charAt(i)) * (WEIGHTS[i] ?? 0);\n }\n const check = (11 - (sum % 11)) % 11;\n if (check === 10) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Swiss UID check digit is invalid\",\n );\n }\n if (check !== Number(digits[8])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Swiss UID check digit mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n const d = v.slice(3);\n return `CHE-${d.slice(0, 3)}.${d.slice(3, 6)}.${d.slice(6)}`;\n};\n\n/** Generate a random valid Swiss UID. */\nconst generate = (): string => {\n for (let i = 0; i < 100; i++) {\n const payload = randomDigits(8);\n let sum = 0;\n for (let j = 0; j < 8; j++)\n sum += Number(payload.charAt(j)) * (WEIGHTS[j] ?? 0);\n const check = (11 - (sum % 11)) % 11;\n if (check === 10) continue;\n return \"CHE\" + payload + String(check);\n }\n throw new Error(\"Failed to generate valid Swiss UID\");\n};\n\n/** Swiss Business Identification Number. */\nconst uid: CountryValidator<\"CH\"> = {\n name: \"Swiss Business ID\",\n localName: \"Unternehmens-Identifikationsnummer\",\n abbreviation: \"UID\",\n aliases: [\n \"Unternehmens-Identifikationsnummer\",\n \"UID\",\n \"IDE\",\n ] as const,\n candidatePattern: \"CHE-?\\\\d{3}\\\\.?\\\\d{3}\\\\.?\\\\d{3}\",\n scope: \"country\",\n country: \"CH\",\n entityType: \"company\",\n sourceUrl: \"https://www.uid.admin.ch/\",\n examples: [\"CHE100155212\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default uid;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAoBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAEvC,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,EAAE,YAAY;AAEnC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,kCACF;CAEF,IAAI,CAAC,EAAE,WAAW,KAAK,GACrB,OAAO,IACL,qBACA,+BACF;CAEF,MAAM,SAAS,EAAE,MAAM,CAAC;CACxB,IAAI,CAAC,SAAS,MAAM,GAClB,OAAO,IACL,kBACA,kCACF;CAGF,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,OAAO,OAAO,OAAO,OAAO,CAAC,CAAC,KAAK,QAAQ,MAAM;CAEnD,MAAM,SAAS,KAAM,MAAM,MAAO;CAClC,IAAI,UAAU,IACZ,OAAO,IACL,oBACA,kCACF;CAEF,IAAI,UAAU,OAAO,OAAO,EAAE,GAC5B,OAAO,IACL,oBACA,gCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CAExC,MAAM,IADI,QAAQ,KACR,EAAE,MAAM,CAAC;CACnB,OAAO,OAAO,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AAC3D;;AAGA,MAAM,iBAAyB;CAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK;EAC5B,MAAM,UAAU,aAAa,CAAC;EAC9B,IAAI,MAAM;EACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,OAAO,OAAO,QAAQ,OAAO,CAAC,CAAC,KAAK,QAAQ,MAAM;EACpD,MAAM,SAAS,KAAM,MAAM,MAAO;EAClC,IAAI,UAAU,IAAI;EAClB,OAAO,QAAQ,UAAU,OAAO,KAAK;CACvC;CACA,MAAM,IAAI,MAAM,oCAAoC;AACtD;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,cAAc;CACzB;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"uid.js","names":[],"sources":["../../src/ch/uid.ts"],"sourcesContent":["/**\n * UID (Unternehmens-Identifikationsnummer).\n *\n * Swiss business identification number. 12 characters:\n * \"CHE\" prefix + 9 digits. Check digit uses weights\n * [5,4,3,2,7,6,5,4] on the first 8 digits.\n *\n * @see https://www.uid.admin.ch/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst WEIGHTS = [5, 4, 3, 2, 7, 6, 5, 4] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -./\").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Swiss UID must be CHE + 9 digits\",\n );\n }\n if (!v.startsWith(\"CHE\")) {\n return err(\n \"INVALID_COMPONENT\",\n \"Swiss UID must start with CHE\",\n );\n }\n const digits = v.slice(3);\n if (!isdigits(digits)) {\n return err(\n \"INVALID_FORMAT\",\n \"Swiss UID must be CHE + 9 digits\",\n );\n }\n\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n sum += Number(digits.charAt(i)) * (WEIGHTS[i] ?? 0);\n }\n const check = (11 - (sum % 11)) % 11;\n if (check === 10) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Swiss UID check digit is invalid\",\n );\n }\n if (check !== Number(digits[8])) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Swiss UID check digit mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n const d = v.slice(3);\n return `CHE-${d.slice(0, 3)}.${d.slice(3, 6)}.${d.slice(6)}`;\n};\n\n/** Generate a random valid Swiss UID. */\nconst generate = (): string => {\n for (let i = 0; i < 100; i++) {\n const payload = randomDigits(8);\n let sum = 0;\n for (let j = 0; j < 8; j++)\n sum += Number(payload.charAt(j)) * (WEIGHTS[j] ?? 0);\n const check = (11 - (sum % 11)) % 11;\n if (check === 10) continue;\n return \"CHE\" + payload + String(check);\n }\n throw new Error(\"Failed to generate valid Swiss UID\");\n};\n\n/** Swiss Business Identification Number. */\nconst uid: CountryValidator<\"CH\"> = {\n name: \"Swiss Business ID\",\n localName: \"Unternehmens-Identifikationsnummer\",\n abbreviation: \"UID\",\n aliases: [\n \"Unternehmens-Identifikationsnummer\",\n \"UID\",\n \"IDE\",\n ] as const,\n candidatePattern: \"CHE-?\\\\d{3}\\\\.?\\\\d{3}\\\\.?\\\\d{3}\",\n scope: \"country\",\n country: \"CH\",\n entityType: \"company\",\n sourceUrl: \"https://www.uid.admin.ch/\",\n examples: [\"CHE100155212\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default uid;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAoBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAEvC,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,CAAC,CAAC,YAAY;AAEnC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,kCACF;CAEF,IAAI,CAAC,EAAE,WAAW,KAAK,GACrB,OAAO,IACL,qBACA,+BACF;CAEF,MAAM,SAAS,EAAE,MAAM,CAAC;CACxB,IAAI,CAAC,SAAS,MAAM,GAClB,OAAO,IACL,kBACA,kCACF;CAGF,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,OAAO,OAAO,OAAO,OAAO,CAAC,CAAC,KAAK,QAAQ,MAAM;CAEnD,MAAM,SAAS,KAAM,MAAM,MAAO;CAClC,IAAI,UAAU,IACZ,OAAO,IACL,oBACA,kCACF;CAEF,IAAI,UAAU,OAAO,OAAO,EAAE,GAC5B,OAAO,IACL,oBACA,gCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CAExC,MAAM,IADI,QAAQ,KACR,CAAC,CAAC,MAAM,CAAC;CACnB,OAAO,OAAO,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AAC3D;;AAGA,MAAM,iBAAyB;CAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK;EAC5B,MAAM,UAAU,aAAa,CAAC;EAC9B,IAAI,MAAM;EACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,OAAO,OAAO,QAAQ,OAAO,CAAC,CAAC,KAAK,QAAQ,MAAM;EACpD,MAAM,SAAS,KAAM,MAAM,MAAO;EAClC,IAAI,UAAU,IAAI;EAClB,OAAO,QAAQ,UAAU,OAAO,KAAK;CACvC;CACA,MAAM,IAAI,MAAM,oCAAoC;AACtD;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,cAAc;CACzB;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"vat.js","names":["validateUid","generateUid"],"sources":["../../src/ch/vat.ts"],"sourcesContent":["/**\n * Swiss VAT number.\n *\n * Format: CHE + 9 digits + suffix (MWST|TVA|IVA|TPV).\n * The numeric part is validated as a UID.\n *\n * @see https://www.ch.ch/en/value-added-tax-number-und-business-identification-number/\n * @see https://www.estv.admin.ch/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\nimport {\n validate as validateUid,\n generate as generateUid,\n} from \"./uid\";\n\nimport { clean } from \"#util/clean\";\nimport { err } from \"#util/result\";\n\nconst SUFFIXES = [\"MWST\", \"TVA\", \"IVA\", \"TPV\"] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -./\").toUpperCase();\n\nconst extractParts = (\n v: string,\n): { uid: string; suffix: string } | undefined => {\n for (const s of SUFFIXES) {\n if (v.endsWith(s)) {\n return { uid: v.slice(0, -s.length), suffix: s };\n }\n }\n return undefined;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n const parts = extractParts(v);\n if (!parts) {\n return err(\n \"INVALID_FORMAT\",\n \"Swiss VAT must end with MWST, TVA, IVA, or TPV\",\n );\n }\n\n const uidResult = validateUid(parts.uid);\n if (!uidResult.valid) {\n return uidResult;\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n const parts = extractParts(v);\n if (!parts) return v;\n const d = parts.uid.slice(3);\n return `CHE-${d.slice(0, 3)}.${d.slice(3, 6)}.${d.slice(6)} ${parts.suffix}`;\n};\n\n/** Generate a random valid Swiss VAT number. */\nconst generate = (): string => generateUid() + \"MWST\";\n\n/** Swiss VAT Number. */\nconst vat: CountryValidator<\"CH\"> = {\n name: \"Swiss VAT Number\",\n localName: \"Mehrwertsteuernummer\",\n abbreviation: \"MWST\",\n aliases: [\"MWST\", \"TVA\", \"IVA\"] as const,\n candidatePattern:\n \"CHE-?\\\\d{3}\\\\.?\\\\d{3}\\\\.?\\\\d{3}\\\\s?(?:MWST|TVA|IVA)\",\n scope: \"country\",\n country: \"CH\",\n entityType: \"company\",\n sourceUrl: \"https://www.estv.admin.ch/\",\n examples: [\"CHE107787577IVA\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAsBA,MAAM,WAAW;CAAC;CAAQ;CAAO;CAAO;AAAK;AAE7C,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,EAAE,YAAY;AAEnC,MAAM,gBACJ,MACgD;CAChD,KAAK,MAAM,KAAK,UACd,IAAI,EAAE,SAAS,CAAC,GACd,OAAO;EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,MAAM;EAAG,QAAQ;CAAE;AAIrD;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,MAAM,QAAQ,aAAa,CAAC;CAC5B,IAAI,CAAC,OACH,OAAO,IACL,kBACA,gDACF;CAGF,MAAM,YAAYA,WAAY,MAAM,GAAG;CACvC,IAAI,CAAC,UAAU,OACb,OAAO;CAGT,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,MAAM,QAAQ,aAAa,CAAC;CAC5B,IAAI,CAAC,OAAO,OAAO;CACnB,MAAM,IAAI,MAAM,IAAI,MAAM,CAAC;CAC3B,OAAO,OAAO,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,MAAM;AACtE;;AAGA,MAAM,iBAAyBC,WAAY,IAAI;;AAG/C,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EAAC;EAAQ;EAAO;CAAK;CAC9B,kBACE;CACF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,iBAAiB;CAC5B;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"vat.js","names":["validateUid","generateUid"],"sources":["../../src/ch/vat.ts"],"sourcesContent":["/**\n * Swiss VAT number.\n *\n * Format: CHE + 9 digits + suffix (MWST|TVA|IVA|TPV).\n * The numeric part is validated as a UID.\n *\n * @see https://www.ch.ch/en/value-added-tax-number-und-business-identification-number/\n * @see https://www.estv.admin.ch/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\nimport {\n validate as validateUid,\n generate as generateUid,\n} from \"./uid\";\n\nimport { clean } from \"#util/clean\";\nimport { err } from \"#util/result\";\n\nconst SUFFIXES = [\"MWST\", \"TVA\", \"IVA\", \"TPV\"] as const;\n\nconst compact = (value: string): string =>\n clean(value, \" -./\").toUpperCase();\n\nconst extractParts = (\n v: string,\n): { uid: string; suffix: string } | undefined => {\n for (const s of SUFFIXES) {\n if (v.endsWith(s)) {\n return { uid: v.slice(0, -s.length), suffix: s };\n }\n }\n return undefined;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n const parts = extractParts(v);\n if (!parts) {\n return err(\n \"INVALID_FORMAT\",\n \"Swiss VAT must end with MWST, TVA, IVA, or TPV\",\n );\n }\n\n const uidResult = validateUid(parts.uid);\n if (!uidResult.valid) {\n return uidResult;\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n const parts = extractParts(v);\n if (!parts) return v;\n const d = parts.uid.slice(3);\n return `CHE-${d.slice(0, 3)}.${d.slice(3, 6)}.${d.slice(6)} ${parts.suffix}`;\n};\n\n/** Generate a random valid Swiss VAT number. */\nconst generate = (): string => generateUid() + \"MWST\";\n\n/** Swiss VAT Number. */\nconst vat: CountryValidator<\"CH\"> = {\n name: \"Swiss VAT Number\",\n localName: \"Mehrwertsteuernummer\",\n abbreviation: \"MWST\",\n aliases: [\"MWST\", \"TVA\", \"IVA\"] as const,\n candidatePattern:\n \"CHE-?\\\\d{3}\\\\.?\\\\d{3}\\\\.?\\\\d{3}\\\\s?(?:MWST|TVA|IVA)\",\n scope: \"country\",\n country: \"CH\",\n entityType: \"company\",\n sourceUrl: \"https://www.estv.admin.ch/\",\n examples: [\"CHE107787577IVA\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAsBA,MAAM,WAAW;CAAC;CAAQ;CAAO;CAAO;AAAK;AAE7C,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,CAAC,CAAC,YAAY;AAEnC,MAAM,gBACJ,MACgD;CAChD,KAAK,MAAM,KAAK,UACd,IAAI,EAAE,SAAS,CAAC,GACd,OAAO;EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,MAAM;EAAG,QAAQ;CAAE;AAIrD;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,MAAM,QAAQ,aAAa,CAAC;CAC5B,IAAI,CAAC,OACH,OAAO,IACL,kBACA,gDACF;CAGF,MAAM,YAAYA,WAAY,MAAM,GAAG;CACvC,IAAI,CAAC,UAAU,OACb,OAAO;CAGT,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,MAAM,QAAQ,aAAa,CAAC;CAC5B,IAAI,CAAC,OAAO,OAAO;CACnB,MAAM,IAAI,MAAM,IAAI,MAAM,CAAC;CAC3B,OAAO,OAAO,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,MAAM;AACtE;;AAGA,MAAM,iBAAyBC,WAAY,IAAI;;AAG/C,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EAAC;EAAQ;EAAO;CAAK;CAC9B,kBACE;CACF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,iBAAiB;CAC5B;CACA;CACA;CACA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"rut.js","names":[],"sources":["../../src/cl/rut.ts"],"sourcesContent":["/**\n * RUT (Rol Único Tributario).\n *\n * Chilean tax identification number assigned by the SII\n * (Servicio de Impuestos Internos). The number consists\n * of 7 or 8 digits followed by a check digit (0-9 or K),\n * computed using a modulo 11 algorithm with weights\n * [2, 3, 4, 5, 6, 7] cycling right-to-left.\n *\n * Format: XX.XXX.XXX-C (7-8 digits + check digit).\n *\n * @see https://www.sii.cl/\n * @see https://en.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst RUT_RE = /^\\d{7,8}[\\dK]$/;\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -.\").trim().toUpperCase();\n if (v.startsWith(\"CL\")) v = v.slice(2);\n return v;\n};\n\n/**\n * Compute the RUT check digit using mod 11 with\n * weights [2, 3, 4, 5, 6, 7] cycling right-to-left.\n *\n * remainder = 11 - (weighted sum % 11)\n * 11 -> \"0\", 10 -> \"K\", else the digit as string.\n */\nconst calcCheckDigit = (body: string): string => {\n const weights = [2, 3, 4, 5, 6, 7] as const;\n let sum = 0;\n for (let i = body.length - 1, w = 0; i >= 0; i--, w++) {\n // SAFETY: w % weights.length is a valid index.\n // eslint-disable-next-line no-non-null-assertion\n sum += Number(body[i]) * weights[w % weights.length]!;\n }\n const remainder = 11 - (sum % 11);\n if (remainder === 11) return \"0\";\n if (remainder === 10) return \"K\";\n return String(remainder);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 8 && v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"RUT must be 8 or 9 characters\",\n );\n }\n\n if (!RUT_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"RUT must contain only digits and optionally K\",\n );\n }\n\n const body = v.slice(0, -1);\n const expected = calcCheckDigit(body);\n if (v.at(-1) !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"RUT check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n const check = v.at(-1);\n const body = v.slice(0, -1);\n return (\n `${body.slice(0, -6)}.${body.slice(-6, -3)}` +\n `.${body.slice(-3)}-${check}`\n );\n};\n\n/** Generate a random valid Chilean RUT. */\nconst generate = (): string => {\n const body = randomDigits(8);\n return body + calcCheckDigit(body);\n};\n\n/**\n * Chilean RUT (tax identification number).\n *\n * Examples sourced from python-stdnum test suite\n * (cl.rut module).\n */\nconst rut: CountryValidator<\"CL\"> = {\n name: \"Chilean Tax ID\",\n localName: \"Rol Único Tributario\",\n abbreviation: \"RUT\",\n aliases: [\"RUT\", \"Rol Único Tributario\"] as const,\n candidatePattern: \"\\\\d{1,2}\\\\.?\\\\d{3}\\\\.?\\\\d{3}-?[\\\\dkK]\",\n scope: \"country\",\n country: \"CL\",\n entityType: \"any\",\n compact,\n format,\n validate,\n sourceUrl: \"https://www.sii.cl/\",\n lengths: [8, 9] as const,\n examples: [\"760864285\", \"125319092\"] as const,\n generate,\n};\n\nexport default rut;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAwBA,MAAM,SAAS;AAEf,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY;CAC/C,IAAI,EAAE,WAAW,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC;CACrC,OAAO;AACT;;;;;;;;AASA,MAAM,kBAAkB,SAAyB;CAC/C,MAAM,UAAU;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;CAAC;CACjC,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,KAAK,SAAS,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,KAGhD,OAAO,OAAO,KAAK,EAAE,IAAI,QAAQ,IAAI,QAAQ;CAE/C,MAAM,YAAY,KAAM,MAAM;CAC9B,IAAI,cAAc,IAAI,OAAO;CAC7B,IAAI,cAAc,IAAI,OAAO;CAC7B,OAAO,OAAO,SAAS;AACzB;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,OAAO,IACL,kBACA,+BACF;CAGF,IAAI,CAAC,OAAO,KAAK,CAAC,GAChB,OAAO,IACL,kBACA,+CACF;CAIF,MAAM,WAAW,eADJ,EAAE,MAAM,GAAG,EACW,CAAC;CACpC,IAAI,EAAE,GAAG,EAAE,MAAM,UACf,OAAO,IACL,oBACA,gCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,MAAM,QAAQ,EAAE,GAAG,EAAE;CACrB,MAAM,OAAO,EAAE,MAAM,GAAG,EAAE;CAC1B,OACE,GAAG,KAAK,MAAM,GAAG,EAAE,EAAE,GAAG,KAAK,MAAM,IAAI,EAAE,EAAA,GACrC,KAAK,MAAM,EAAE,EAAE,GAAG;AAE1B;;AAGA,MAAM,iBAAyB;CAC7B,MAAM,OAAO,aAAa,CAAC;CAC3B,OAAO,OAAO,eAAe,IAAI;AACnC;;;;;;;AAQA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,sBAAsB;CACvC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ;CACA;CACA;CACA,WAAW;CACX,SAAS,CAAC,GAAG,CAAC;CACd,UAAU,CAAC,aAAa,WAAW;CACnC;AACF"}
1
+ {"version":3,"file":"rut.js","names":[],"sources":["../../src/cl/rut.ts"],"sourcesContent":["/**\n * RUT (Rol Único Tributario).\n *\n * Chilean tax identification number assigned by the SII\n * (Servicio de Impuestos Internos). The number consists\n * of 7 or 8 digits followed by a check digit (0-9 or K),\n * computed using a modulo 11 algorithm with weights\n * [2, 3, 4, 5, 6, 7] cycling right-to-left.\n *\n * Format: XX.XXX.XXX-C (7-8 digits + check digit).\n *\n * @see https://www.sii.cl/\n * @see https://en.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst RUT_RE = /^\\d{7,8}[\\dK]$/;\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -.\").trim().toUpperCase();\n if (v.startsWith(\"CL\")) v = v.slice(2);\n return v;\n};\n\n/**\n * Compute the RUT check digit using mod 11 with\n * weights [2, 3, 4, 5, 6, 7] cycling right-to-left.\n *\n * remainder = 11 - (weighted sum % 11)\n * 11 -> \"0\", 10 -> \"K\", else the digit as string.\n */\nconst calcCheckDigit = (body: string): string => {\n const weights = [2, 3, 4, 5, 6, 7] as const;\n let sum = 0;\n for (let i = body.length - 1, w = 0; i >= 0; i--, w++) {\n // SAFETY: w % weights.length is a valid index.\n // eslint-disable-next-line no-non-null-assertion\n sum += Number(body[i]) * weights[w % weights.length]!;\n }\n const remainder = 11 - (sum % 11);\n if (remainder === 11) return \"0\";\n if (remainder === 10) return \"K\";\n return String(remainder);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 8 && v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"RUT must be 8 or 9 characters\",\n );\n }\n\n if (!RUT_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"RUT must contain only digits and optionally K\",\n );\n }\n\n const body = v.slice(0, -1);\n const expected = calcCheckDigit(body);\n if (v.at(-1) !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"RUT check digit does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n const check = v.at(-1);\n const body = v.slice(0, -1);\n return (\n `${body.slice(0, -6)}.${body.slice(-6, -3)}` +\n `.${body.slice(-3)}-${check}`\n );\n};\n\n/** Generate a random valid Chilean RUT. */\nconst generate = (): string => {\n const body = randomDigits(8);\n return body + calcCheckDigit(body);\n};\n\n/**\n * Chilean RUT (tax identification number).\n *\n * Examples sourced from python-stdnum test suite\n * (cl.rut module).\n */\nconst rut: CountryValidator<\"CL\"> = {\n name: \"Chilean Tax ID\",\n localName: \"Rol Único Tributario\",\n abbreviation: \"RUT\",\n aliases: [\"RUT\", \"Rol Único Tributario\"] as const,\n candidatePattern: \"\\\\d{1,2}\\\\.?\\\\d{3}\\\\.?\\\\d{3}-?[\\\\dkK]\",\n scope: \"country\",\n country: \"CL\",\n entityType: \"any\",\n compact,\n format,\n validate,\n sourceUrl: \"https://www.sii.cl/\",\n lengths: [8, 9] as const,\n examples: [\"760864285\", \"125319092\"] as const,\n generate,\n};\n\nexport default rut;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAwBA,MAAM,SAAS;AAEf,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY;CAC/C,IAAI,EAAE,WAAW,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC;CACrC,OAAO;AACT;;;;;;;;AASA,MAAM,kBAAkB,SAAyB;CAC/C,MAAM,UAAU;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;CAAC;CACjC,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,KAAK,SAAS,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,KAGhD,OAAO,OAAO,KAAK,EAAE,IAAI,QAAQ,IAAI,QAAQ;CAE/C,MAAM,YAAY,KAAM,MAAM;CAC9B,IAAI,cAAc,IAAI,OAAO;CAC7B,IAAI,cAAc,IAAI,OAAO;CAC7B,OAAO,OAAO,SAAS;AACzB;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,OAAO,IACL,kBACA,+BACF;CAGF,IAAI,CAAC,OAAO,KAAK,CAAC,GAChB,OAAO,IACL,kBACA,+CACF;CAIF,MAAM,WAAW,eADJ,EAAE,MAAM,GAAG,EACW,CAAC;CACpC,IAAI,EAAE,GAAG,EAAE,MAAM,UACf,OAAO,IACL,oBACA,gCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,MAAM,QAAQ,EAAE,GAAG,EAAE;CACrB,MAAM,OAAO,EAAE,MAAM,GAAG,EAAE;CAC1B,OACE,GAAG,KAAK,MAAM,GAAG,EAAE,EAAE,GAAG,KAAK,MAAM,IAAI,EAAE,EAAA,GACrC,KAAK,MAAM,EAAE,EAAE,GAAG;AAE1B;;AAGA,MAAM,iBAAyB;CAC7B,MAAM,OAAO,aAAa,CAAC;CAC3B,OAAO,OAAO,eAAe,IAAI;AACnC;;;;;;;AAQA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,sBAAsB;CACvC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ;CACA;CACA;CACA,WAAW;CACX,SAAS,CAAC,GAAG,CAAC;CACd,UAAU,CAAC,aAAa,WAAW;CACnC;AACF"}