@stll/stdnum 2.0.1 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -9
- package/dist/_checksums/keccak.d.ts +5 -0
- package/dist/_checksums/keccak.js +118 -0
- package/dist/_checksums/keccak.js.map +1 -0
- package/dist/_checksums/mod112.js.map +1 -1
- package/dist/_checksums/sha256.d.ts +5 -0
- package/dist/_checksums/sha256.js +164 -0
- package/dist/_checksums/sha256.js.map +1 -0
- package/dist/_checksums/verhoeff.js.map +1 -1
- package/dist/_util/arabic.js.map +1 -1
- package/dist/_util/clean.d.ts +6 -1
- package/dist/_util/clean.js +7 -2
- package/dist/_util/clean.js.map +1 -1
- package/dist/_util/date.js.map +1 -1
- package/dist/ad/nrt.js.map +1 -1
- package/dist/ae/eid.js.map +1 -1
- package/dist/ai/tin.js.map +1 -1
- package/dist/al/nipt.js.map +1 -1
- package/dist/am/tin.js.map +1 -1
- package/dist/ar/cbu.js.map +1 -1
- package/dist/ar/cuit.js.map +1 -1
- package/dist/ar/dni.js.map +1 -1
- package/dist/at/businessid.js.map +1 -1
- package/dist/at/vnr.js.map +1 -1
- package/dist/au/abn.js.map +1 -1
- package/dist/au/tfn.js.map +1 -1
- package/dist/az/voen.js.map +1 -1
- package/dist/ba/jmbg.js.map +1 -1
- package/dist/be/bis.js.map +1 -1
- package/dist/be/nn.js.map +1 -1
- package/dist/be/vat.js.map +1 -1
- package/dist/bg/egn.js.map +1 -1
- package/dist/bg/vat.js.map +1 -1
- package/dist/bh/cpr.js.map +1 -1
- package/dist/bic.js.map +1 -1
- package/dist/br/cnpj.js.map +1 -1
- package/dist/br/cpf.js.map +1 -1
- package/dist/by/unp.js.map +1 -1
- package/dist/bz/tin.js.map +1 -1
- package/dist/ch/uid.js.map +1 -1
- package/dist/ch/vat.js.map +1 -1
- package/dist/cl/rut.js.map +1 -1
- package/dist/cn/ric.js.map +1 -1
- package/dist/cn/uscc.js.map +1 -1
- package/dist/cr/cpf.js.map +1 -1
- package/dist/crypto/btcbase58.d.ts +11 -0
- package/dist/crypto/btcbase58.js +76 -0
- package/dist/crypto/btcbase58.js.map +1 -0
- package/dist/crypto/btcbech32.d.ts +19 -0
- package/dist/crypto/btcbech32.js +145 -0
- package/dist/crypto/btcbech32.js.map +1 -0
- package/dist/crypto/eth.d.ts +11 -0
- package/dist/crypto/eth.js +63 -0
- package/dist/crypto/eth.js.map +1 -0
- package/dist/crypto/mod.d.ts +12 -0
- package/dist/crypto/mod.js +16 -0
- package/dist/crypto/mod.js.map +1 -0
- package/dist/crypto/wallet.d.ts +10 -0
- package/dist/crypto/wallet.js +55 -0
- package/dist/crypto/wallet.js.map +1 -0
- package/dist/cu/ni.js.map +1 -1
- package/dist/cz/rc.js.map +1 -1
- package/dist/de/handelsreg.js.map +1 -1
- package/dist/de/idnr.js.map +1 -1
- package/dist/de/stnr.js.map +1 -1
- package/dist/de/svnr.js.map +1 -1
- package/dist/dk/cpr.js.map +1 -1
- package/dist/dk/cvr.js.map +1 -1
- package/dist/dk/vat.js.map +1 -1
- package/dist/do/rnc.js.map +1 -1
- package/dist/ec/ruc.js.map +1 -1
- package/dist/ee/ik.js.map +1 -1
- package/dist/ee/vat.js.map +1 -1
- package/dist/eg/tn.js.map +1 -1
- package/dist/es/dni.js.map +1 -1
- package/dist/es/nie.js.map +1 -1
- package/dist/es/nss.js.map +1 -1
- package/dist/eu/vat.js.map +1 -1
- package/dist/fi/hetu.js.map +1 -1
- package/dist/fi/vat.js.map +1 -1
- package/dist/fi/ytunnus.js.map +1 -1
- package/dist/fr/nif.js.map +1 -1
- package/dist/fr/nir.js.map +1 -1
- package/dist/fr/tva.js.map +1 -1
- package/dist/gb/mod.d.ts +3 -2
- package/dist/gb/mod.js +3 -1
- package/dist/gb/mod.js.map +1 -1
- package/dist/gb/nhs.d.ts +11 -0
- package/dist/gb/nhs.js +51 -0
- package/dist/gb/nhs.js.map +1 -0
- package/dist/gb/nino.js.map +1 -1
- package/dist/gb/sedol.js.map +1 -1
- package/dist/gb/utr.js.map +1 -1
- package/dist/gb/vat.js.map +1 -1
- package/dist/ge/pin.js.map +1 -1
- package/dist/gh/tin.js.map +1 -1
- package/dist/gr/amka.js.map +1 -1
- package/dist/gt/nit.js.map +1 -1
- package/dist/hk/hkid.js.map +1 -1
- package/dist/hu/vat.js.map +1 -1
- package/dist/iban.js.map +1 -1
- package/dist/id/npwp.js.map +1 -1
- package/dist/ie/pps.js.map +1 -1
- package/dist/ie/vat.js.map +1 -1
- package/dist/il/idnr.js.map +1 -1
- package/dist/in/aadhaar.js.map +1 -1
- package/dist/in/gstin.js.map +1 -1
- package/dist/in/pan.js.map +1 -1
- package/dist/index.d.ts +76 -75
- package/dist/index.js +2 -1
- package/dist/ir/nid.js.map +1 -1
- package/dist/is/kennitala.js.map +1 -1
- package/dist/isin.js.map +1 -1
- package/dist/it/codicefiscale.js.map +1 -1
- package/dist/it/iva.js.map +1 -1
- package/dist/kr/rrn.js.map +1 -1
- package/dist/kw/civil.js.map +1 -1
- package/dist/kz/iin.js.map +1 -1
- package/dist/lei.js.map +1 -1
- package/dist/li/peid.js.map +1 -1
- package/dist/lk/nic.js.map +1 -1
- package/dist/lt/asmens.js.map +1 -1
- package/dist/lt/vat.js.map +1 -1
- package/dist/lu/vat.js.map +1 -1
- package/dist/lv/vat.js.map +1 -1
- package/dist/ma/ice.js.map +1 -1
- package/dist/mc/tva.js.map +1 -1
- package/dist/mt/vat.js.map +1 -1
- package/dist/mu/brn.js.map +1 -1
- package/dist/mx/clabe.js.map +1 -1
- package/dist/mx/curp.js.map +1 -1
- package/dist/mx/rfc.js.map +1 -1
- package/dist/my/nric.js.map +1 -1
- package/dist/ni/ruc.js.map +1 -1
- package/dist/nl/bsn.js.map +1 -1
- package/dist/nl/vat.js.map +1 -1
- package/dist/no/fodselsnummer.js.map +1 -1
- package/dist/no/mva.js.map +1 -1
- package/dist/no/orgnr.js.map +1 -1
- package/dist/nz/ird.js.map +1 -1
- package/dist/pa/ruc.js.map +1 -1
- package/dist/patterns.js.map +1 -1
- package/dist/pe/ruc.js.map +1 -1
- package/dist/pl/pesel.js.map +1 -1
- package/dist/pl/regon.js.map +1 -1
- package/dist/pt/cc.js.map +1 -1
- package/dist/ro/cnp.js.map +1 -1
- package/dist/ro/vat.js.map +1 -1
- package/dist/rs/pib.js.map +1 -1
- package/dist/ru/inn.js.map +1 -1
- package/dist/se/personnummer.js.map +1 -1
- package/dist/sg/uen.js.map +1 -1
- package/dist/si/emso.js.map +1 -1
- package/dist/si/vat.js.map +1 -1
- package/dist/sk/dic.js.map +1 -1
- package/dist/tw/ubn.js.map +1 -1
- package/dist/ua/edrpou.js.map +1 -1
- package/dist/us/itin.js.map +1 -1
- package/dist/us/rtn.js.map +1 -1
- package/dist/us/ssn.js.map +1 -1
- package/dist/uy/rut.js.map +1 -1
- package/dist/ve/rif.js.map +1 -1
- package/dist/vn/mst.js.map +1 -1
- package/dist/za/idnr.js.map +1 -1
- package/package.json +31 -6
- package/src/_checksums/keccak.ts +145 -0
- package/src/_checksums/sha256.ts +125 -0
- package/src/_util/clean.ts +7 -2
- package/src/crypto/btcbase58.ts +144 -0
- package/src/crypto/btcbech32.ts +210 -0
- package/src/crypto/eth.ts +114 -0
- package/src/crypto/mod.ts +4 -0
- package/src/crypto/wallet.ts +67 -0
- package/src/gb/mod.ts +1 -0
- package/src/gb/nhs.ts +92 -0
- package/src/index.ts +1 -0
package/dist/fi/hetu.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hetu.js","names":[],"sources":["../../src/fi/hetu.ts"],"sourcesContent":["/**\n * HETU (Henkilötunnus).\n *\n * Finnish personal identity code. 11 characters in\n * format DDMMYY+CCC+X where the separator indicates\n * the century and X is a check character.\n *\n * @see https://dvv.fi/en/personal-identity-code\n */\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\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 CHECK_CHARS = \"0123456789ABCDEFHJKLMNPRSTUVWXY\";\n\nconst SEPARATORS_1800 = new Set([\"+\"]);\nconst SEPARATORS_1900 = new Set([\n \"-\",\n \"Y\",\n \"X\",\n \"W\",\n \"V\",\n \"U\",\n]);\nconst SEPARATORS_2000 = new Set([\n \"A\",\n \"B\",\n \"C\",\n \"D\",\n \"E\",\n \"F\",\n]);\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 !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"HETU must be exactly 11 characters\",\n );\n }\n\n const dd = v.slice(0, 2);\n const mm = v.slice(2, 4);\n const yy = v.slice(4, 6);\n const separator = v.charAt(6);\n const serial = v.slice(7, 10);\n const checkChar = v.charAt(10);\n\n if (!isdigits(dd) || !isdigits(mm) || !isdigits(yy)) {\n return err(\n \"INVALID_FORMAT\",\n \"HETU date part must be digits\",\n );\n }\n if (!isdigits(serial)) {\n return err(\n \"INVALID_FORMAT\",\n \"HETU serial must be digits\",\n );\n }\n\n let century: number;\n if (SEPARATORS_1800.has(separator)) {\n century = 1800;\n } else if (SEPARATORS_1900.has(separator)) {\n century = 1900;\n } else if (SEPARATORS_2000.has(separator)) {\n century = 2000;\n } else {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU separator is invalid\",\n );\n }\n\n const year = century + Number(yy);\n const month = Number(mm);\n const day = Number(dd);\n\n if (!isValidDate(year, month, day)) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU contains an invalid date\",\n );\n }\n\n // Individual number must be >= 002\n const serialNum = Number(serial);\n if (serialNum < 2) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU individual number must be >= 002\",\n );\n }\n // Temporary range 900-999 is not valid\n if (serialNum >= 900) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU temporary individual range 900-999\",\n );\n }\n\n const checkNum = Number(`${dd}${mm}${yy}${serial}`);\n const expected = CHECK_CHARS.charAt(checkNum % 31);\n if (checkChar !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"HETU check character does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a HETU.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const yy = Number(v.slice(4, 6));\n const separator = v.charAt(6);\n const serial = Number(v.slice(7, 10));\n\n let century: number;\n if (SEPARATORS_1800.has(separator)) {\n century = 1800;\n } else if (SEPARATORS_1900.has(separator)) {\n century = 1900;\n } else {\n century = 2000;\n }\n\n const year = century + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender: serial % 2 === 0 ? \"female\" : \"male\",\n };\n};\n\n/** Generate a random valid HETU. */\nconst generate = (): string => {\n const year = randomInt(1900, 2024);\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n const yy = String(year % 100).padStart(2, \"0\");\n const separator = year >= 2000 ? \"A\" : \"-\";\n const serial = String(randomInt(2, 899)).padStart(3, \"0\");\n const checkNum = Number(`${day}${month}${yy}${serial}`);\n const checkChar = CHECK_CHARS.charAt(checkNum % 31);\n return `${day}${month}${yy}${separator}${serial}${checkChar}`;\n};\n\n/** Finnish Personal Identity Code. */\nconst hetu: CountryValidator<\"FI\", ParsedPersonId> = {\n name: \"Finnish Personal ID\",\n localName: \"Henkilötunnus\",\n abbreviation: \"HETU\",\n aliases: [\n \"henkilötunnus\",\n \"HETU\",\n \"sosiaaliturvatunnus\",\n ] as const,\n candidatePattern: \"\\\\d{6}[-+A]\\\\d{3}[\\\\dA-Z]\",\n scope: \"country\",\n country: \"FI\",\n entityType: \"person\",\n sourceUrl: \"https://dvv.fi/en/personal-identity-code\",\n lengths: [11] as const,\n examples: [\"131052-308T\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default hetu;\nexport { compact, format, generate, parse, validate };\n"],"mappings":";;;;;;AAsBA,MAAM,cAAc;AAEpB,MAAM,kBAAkB,IAAI,IAAI,CAAC,GAAG,CAAC;AACrC,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AACD,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,WAAW,UACf,MAAM,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"hetu.js","names":[],"sources":["../../src/fi/hetu.ts"],"sourcesContent":["/**\n * HETU (Henkilötunnus).\n *\n * Finnish personal identity code. 11 characters in\n * format DDMMYY+CCC+X where the separator indicates\n * the century and X is a check character.\n *\n * @see https://dvv.fi/en/personal-identity-code\n */\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\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 CHECK_CHARS = \"0123456789ABCDEFHJKLMNPRSTUVWXY\";\n\nconst SEPARATORS_1800 = new Set([\"+\"]);\nconst SEPARATORS_1900 = new Set([\n \"-\",\n \"Y\",\n \"X\",\n \"W\",\n \"V\",\n \"U\",\n]);\nconst SEPARATORS_2000 = new Set([\n \"A\",\n \"B\",\n \"C\",\n \"D\",\n \"E\",\n \"F\",\n]);\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 !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"HETU must be exactly 11 characters\",\n );\n }\n\n const dd = v.slice(0, 2);\n const mm = v.slice(2, 4);\n const yy = v.slice(4, 6);\n const separator = v.charAt(6);\n const serial = v.slice(7, 10);\n const checkChar = v.charAt(10);\n\n if (!isdigits(dd) || !isdigits(mm) || !isdigits(yy)) {\n return err(\n \"INVALID_FORMAT\",\n \"HETU date part must be digits\",\n );\n }\n if (!isdigits(serial)) {\n return err(\n \"INVALID_FORMAT\",\n \"HETU serial must be digits\",\n );\n }\n\n let century: number;\n if (SEPARATORS_1800.has(separator)) {\n century = 1800;\n } else if (SEPARATORS_1900.has(separator)) {\n century = 1900;\n } else if (SEPARATORS_2000.has(separator)) {\n century = 2000;\n } else {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU separator is invalid\",\n );\n }\n\n const year = century + Number(yy);\n const month = Number(mm);\n const day = Number(dd);\n\n if (!isValidDate(year, month, day)) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU contains an invalid date\",\n );\n }\n\n // Individual number must be >= 002\n const serialNum = Number(serial);\n if (serialNum < 2) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU individual number must be >= 002\",\n );\n }\n // Temporary range 900-999 is not valid\n if (serialNum >= 900) {\n return err(\n \"INVALID_COMPONENT\",\n \"HETU temporary individual range 900-999\",\n );\n }\n\n const checkNum = Number(`${dd}${mm}${yy}${serial}`);\n const expected = CHECK_CHARS.charAt(checkNum % 31);\n if (checkChar !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"HETU check character does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/**\n * Extract birth date and gender from a HETU.\n * Returns null if the value is not valid.\n */\nconst parse = (value: string): ParsedPersonId | null => {\n const result = validate(value);\n if (!result.valid) return null;\n\n const v = result.compact;\n const dd = Number(v.slice(0, 2));\n const mm = Number(v.slice(2, 4));\n const yy = Number(v.slice(4, 6));\n const separator = v.charAt(6);\n const serial = Number(v.slice(7, 10));\n\n let century: number;\n if (SEPARATORS_1800.has(separator)) {\n century = 1800;\n } else if (SEPARATORS_1900.has(separator)) {\n century = 1900;\n } else {\n century = 2000;\n }\n\n const year = century + yy;\n\n return {\n birthDate: new Date(year, mm - 1, dd),\n gender: serial % 2 === 0 ? \"female\" : \"male\",\n };\n};\n\n/** Generate a random valid HETU. */\nconst generate = (): string => {\n const year = randomInt(1900, 2024);\n const month = String(randomInt(1, 12)).padStart(2, \"0\");\n const day = String(randomInt(1, 28)).padStart(2, \"0\");\n const yy = String(year % 100).padStart(2, \"0\");\n const separator = year >= 2000 ? \"A\" : \"-\";\n const serial = String(randomInt(2, 899)).padStart(3, \"0\");\n const checkNum = Number(`${day}${month}${yy}${serial}`);\n const checkChar = CHECK_CHARS.charAt(checkNum % 31);\n return `${day}${month}${yy}${separator}${serial}${checkChar}`;\n};\n\n/** Finnish Personal Identity Code. */\nconst hetu: CountryValidator<\"FI\", ParsedPersonId> = {\n name: \"Finnish Personal ID\",\n localName: \"Henkilötunnus\",\n abbreviation: \"HETU\",\n aliases: [\n \"henkilötunnus\",\n \"HETU\",\n \"sosiaaliturvatunnus\",\n ] as const,\n candidatePattern: \"\\\\d{6}[-+A]\\\\d{3}[\\\\dA-Z]\",\n scope: \"country\",\n country: \"FI\",\n entityType: \"person\",\n sourceUrl: \"https://dvv.fi/en/personal-identity-code\",\n lengths: [11] as const,\n examples: [\"131052-308T\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default hetu;\nexport { compact, format, generate, parse, validate };\n"],"mappings":";;;;;;AAsBA,MAAM,cAAc;AAEpB,MAAM,kBAAkB,IAAI,IAAI,CAAC,GAAG,CAAC;AACrC,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AACD,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,WAAW,UACf,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY;AAEhC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,oCACF;CAGF,MAAM,KAAK,EAAE,MAAM,GAAG,CAAC;CACvB,MAAM,KAAK,EAAE,MAAM,GAAG,CAAC;CACvB,MAAM,KAAK,EAAE,MAAM,GAAG,CAAC;CACvB,MAAM,YAAY,EAAE,OAAO,CAAC;CAC5B,MAAM,SAAS,EAAE,MAAM,GAAG,EAAE;CAC5B,MAAM,YAAY,EAAE,OAAO,EAAE;CAE7B,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,GAChD,OAAO,IACL,kBACA,+BACF;CAEF,IAAI,CAAC,SAAS,MAAM,GAClB,OAAO,IACL,kBACA,4BACF;CAGF,IAAI;CACJ,IAAI,gBAAgB,IAAI,SAAS,GAC/B,UAAU;MACL,IAAI,gBAAgB,IAAI,SAAS,GACtC,UAAU;MACL,IAAI,gBAAgB,IAAI,SAAS,GACtC,UAAU;MAEV,OAAO,IACL,qBACA,2BACF;CAOF,IAAI,CAAC,YAJQ,UAAU,OAAO,EAAE,GAClB,OAAO,EAGM,GAFf,OAAO,EAEa,CAAC,GAC/B,OAAO,IACL,qBACA,+BACF;CAIF,MAAM,YAAY,OAAO,MAAM;CAC/B,IAAI,YAAY,GACd,OAAO,IACL,qBACA,uCACF;CAGF,IAAI,aAAa,KACf,OAAO,IACL,qBACA,yCACF;CAGF,MAAM,WAAW,OAAO,GAAG,KAAK,KAAK,KAAK,QAAQ;CAElD,IAAI,cADa,YAAY,OAAO,WAAW,EACtB,GACvB,OAAO,IACL,oBACA,qCACF;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,YAAY,EAAE,OAAO,CAAC;CAC5B,MAAM,SAAS,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CAEpC,IAAI;CACJ,IAAI,gBAAgB,IAAI,SAAS,GAC/B,UAAU;MACL,IAAI,gBAAgB,IAAI,SAAS,GACtC,UAAU;MAEV,UAAU;CAGZ,MAAM,OAAO,UAAU;CAEvB,OAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,EAAE;EACpC,QAAQ,SAAS,MAAM,IAAI,WAAW;CACxC;AACF;;AAGA,MAAM,iBAAyB;CAC7B,MAAM,OAAO,UAAU,MAAM,IAAI;CACjC,MAAM,QAAQ,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;CACtD,MAAM,MAAM,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;CACpD,MAAM,KAAK,OAAO,OAAO,GAAG,CAAC,CAAC,SAAS,GAAG,GAAG;CAC7C,MAAM,YAAY,QAAQ,MAAO,MAAM;CACvC,MAAM,SAAS,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;CACxD,MAAM,WAAW,OAAO,GAAG,MAAM,QAAQ,KAAK,QAAQ;CAEtD,OAAO,GAAG,MAAM,QAAQ,KAAK,YAAY,SADvB,YAAY,OAAO,WAAW,EACU;AAC5D;;AAGA,MAAM,OAA+C;CACnD,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;CACA;AACF"}
|
package/dist/fi/vat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vat.js","names":[],"sources":["../../src/fi/vat.ts"],"sourcesContent":["/**\n * ALV nro (Finnish VAT number).\n *\n * 8 digits. Weights [7,9,10,5,8,4,2,1],\n * sum % 11 === 0.\n *\n * @see https://www.vatify.eu/finland-vat-number.html\n * @see https://www.ytj.fi/en/index/businessid.html\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 WEIGHTS = [7, 9, 10, 5, 8, 4, 2, 1];\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"FI\") || v.startsWith(\"fi\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"Finnish VAT number must be 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Finnish VAT number must contain only digits\",\n );\n }\n const sum = weightedSum(v, WEIGHTS, 11);\n if (sum !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Finnish VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `FI${compact(value)}`;\n\n/** Generate a random valid Finnish VAT number. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(8);\n if (validate(c).valid) return c;\n }\n};\n\n/** Finnish VAT Number. */\nconst vat: CountryValidator<\"FI\"> = {\n name: \"Finnish VAT Number\",\n localName: \"Arvonlisäveronumero\",\n abbreviation: \"ALV nro\",\n aliases: [\"ALV-numero\", \"Y-tunnus\"] as const,\n candidatePattern: \"FI\\\\d{8}\",\n scope: \"country\",\n country: \"FI\",\n entityType: \"company\",\n sourceUrl: \"https://www.ytj.fi/en/index/businessid.html\",\n lengths: [8] as const,\n examples: [\"20774740\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAqBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;CAAG;AAAC;AAExC,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,MAAM;CAC3B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO;AACT;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,qCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,6CACF;CAGF,IADY,YAAY,GAAG,SAAS,EAC9B,MAAM,GACV,OAAO,IACL,oBACA,yCACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,KAAK,QAAQ,KAAK;;AAGpB,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,CAAC;EACxB,IAAI,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"vat.js","names":[],"sources":["../../src/fi/vat.ts"],"sourcesContent":["/**\n * ALV nro (Finnish VAT number).\n *\n * 8 digits. Weights [7,9,10,5,8,4,2,1],\n * sum % 11 === 0.\n *\n * @see https://www.vatify.eu/finland-vat-number.html\n * @see https://www.ytj.fi/en/index/businessid.html\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 WEIGHTS = [7, 9, 10, 5, 8, 4, 2, 1];\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"FI\") || v.startsWith(\"fi\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"Finnish VAT number must be 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Finnish VAT number must contain only digits\",\n );\n }\n const sum = weightedSum(v, WEIGHTS, 11);\n if (sum !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Finnish VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `FI${compact(value)}`;\n\n/** Generate a random valid Finnish VAT number. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(8);\n if (validate(c).valid) return c;\n }\n};\n\n/** Finnish VAT Number. */\nconst vat: CountryValidator<\"FI\"> = {\n name: \"Finnish VAT Number\",\n localName: \"Arvonlisäveronumero\",\n abbreviation: \"ALV nro\",\n aliases: [\"ALV-numero\", \"Y-tunnus\"] as const,\n candidatePattern: \"FI\\\\d{8}\",\n scope: \"country\",\n country: \"FI\",\n entityType: \"company\",\n sourceUrl: \"https://www.ytj.fi/en/index/businessid.html\",\n lengths: [8] as const,\n examples: [\"20774740\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAqBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;CAAG;AAAC;AAExC,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,MAAM;CAC3B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO;AACT;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,qCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,6CACF;CAGF,IADY,YAAY,GAAG,SAAS,EAC9B,MAAM,GACV,OAAO,IACL,oBACA,yCACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,KAAK,QAAQ,KAAK;;AAGpB,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,CAAC;EACxB,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,cAAc,UAAU;CAClC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,CAAC;CACX,UAAU,CAAC,UAAU;CACrB;CACA;CACA;CACA;AACF"}
|
package/dist/fi/ytunnus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ytunnus.js","names":[],"sources":["../../src/fi/ytunnus.ts"],"sourcesContent":["/**\n * Y-tunnus (Finnish Business ID).\n *\n * 8 digits. Weights [7,9,10,5,8,4,2,1],\n * sum % 11 === 0. Same algorithm as FI VAT.\n * Display format: NNNNNNN-C.\n *\n * @see https://www.ytj.fi/en/index/businessid.html\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 WEIGHTS = [7, 9, 10, 5, 8, 4, 2, 1];\n\nconst compact = (value: string): string =>\n clean(value, \" -/.\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"Finnish Y-tunnus must be 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Finnish Y-tunnus must contain only digits\",\n );\n }\n const sum = weightedSum(v, WEIGHTS, 11);\n if (sum !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Finnish Y-tunnus 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, 7)}-${v[7]}`;\n};\n\n/** Generate a random valid Finnish Y-tunnus. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(8);\n if (validate(c).valid) return c;\n }\n};\n\n/** Finnish Business ID. */\nconst ytunnus: CountryValidator<\"FI\"> = {\n name: \"Finnish Business ID\",\n localName: \"Y-tunnus\",\n abbreviation: \"Y-tunnus\",\n aliases: [\n \"Y-tunnus\",\n \"yritystunnus\",\n \"FO-nummer\",\n ] as const,\n candidatePattern: \"\\\\d{7}-\\\\d\",\n scope: \"country\",\n country: \"FI\",\n entityType: \"company\",\n sourceUrl: \"https://www.ytj.fi/en/index/businessid.html\",\n examples: [\"20774740\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default ytunnus;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAqBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;CAAG;AAAC;AAExC,MAAM,WAAW,UACf,MAAM,OAAO,MAAM;AAErB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,mCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,2CACF;CAGF,IADY,YAAY,GAAG,SAAS,EAC9B,MAAM,GACV,OAAO,IACL,oBACA,uCACF;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;AAC/B;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,CAAC;EACxB,IAAI,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"ytunnus.js","names":[],"sources":["../../src/fi/ytunnus.ts"],"sourcesContent":["/**\n * Y-tunnus (Finnish Business ID).\n *\n * 8 digits. Weights [7,9,10,5,8,4,2,1],\n * sum % 11 === 0. Same algorithm as FI VAT.\n * Display format: NNNNNNN-C.\n *\n * @see https://www.ytj.fi/en/index/businessid.html\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 WEIGHTS = [7, 9, 10, 5, 8, 4, 2, 1];\n\nconst compact = (value: string): string =>\n clean(value, \" -/.\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"Finnish Y-tunnus must be 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Finnish Y-tunnus must contain only digits\",\n );\n }\n const sum = weightedSum(v, WEIGHTS, 11);\n if (sum !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Finnish Y-tunnus 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, 7)}-${v[7]}`;\n};\n\n/** Generate a random valid Finnish Y-tunnus. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(8);\n if (validate(c).valid) return c;\n }\n};\n\n/** Finnish Business ID. */\nconst ytunnus: CountryValidator<\"FI\"> = {\n name: \"Finnish Business ID\",\n localName: \"Y-tunnus\",\n abbreviation: \"Y-tunnus\",\n aliases: [\n \"Y-tunnus\",\n \"yritystunnus\",\n \"FO-nummer\",\n ] as const,\n candidatePattern: \"\\\\d{7}-\\\\d\",\n scope: \"country\",\n country: \"FI\",\n entityType: \"company\",\n sourceUrl: \"https://www.ytj.fi/en/index/businessid.html\",\n examples: [\"20774740\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default ytunnus;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAqBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;CAAG;AAAC;AAExC,MAAM,WAAW,UACf,MAAM,OAAO,MAAM;AAErB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,mCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,2CACF;CAGF,IADY,YAAY,GAAG,SAAS,EAC9B,MAAM,GACV,OAAO,IACL,oBACA,uCACF;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;AAC/B;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,CAAC;EACxB,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,UAAkC;CACtC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,UAAU;CACrB;CACA;CACA;CACA;AACF"}
|
package/dist/fr/nif.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nif.js","names":[],"sources":["../../src/fr/nif.ts"],"sourcesContent":["/**\n * NIF (Numéro d'Identification Fiscale).\n *\n * French tax identification number. 13 digits;\n * first digit is 0-3. Last 3 digits are a\n * check: first_10_digits % 511 == last_3.\n *\n * @see https://www.impots.gouv.fr/\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 if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"French NIF must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIF must contain only digits\",\n );\n }\n const first = v[0];\n if (\n first !== \"0\" &&\n first !== \"1\" &&\n first !== \"2\" &&\n first !== \"3\"\n ) {\n return err(\n \"INVALID_COMPONENT\",\n \"French NIF must start with 0-3\",\n );\n }\n const front = Number(v.slice(0, 10));\n const check = Number(v.slice(10));\n if (front % 511 !== check) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French NIF check digits 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, 4)} ${v.slice(4, 7)} ${v.slice(7, 10)} ${v.slice(10)}`;\n};\n\n/** Generate a random valid French NIF. */\nconst generate = (): string => {\n for (;;) {\n const c = String(randomInt(0, 3)) + randomDigits(12);\n if (validate(c).valid) return c;\n }\n};\n\n/** French Tax Identification Number. */\nconst nif: CountryValidator<\"FR\"> = {\n name: \"French Tax ID\",\n localName: \"Numéro d'Identification Fiscale\",\n abbreviation: \"NIF\",\n aliases: [\n \"numéro fiscal\",\n \"NIF\",\n \"numéro d'identification fiscale\",\n ] as const,\n candidatePattern: \"\\\\d{13}\",\n scope: \"country\",\n country: \"FR\",\n entityType: \"person\",\n sourceUrl: \"https://www.impots.gouv.fr/\",\n examples: [\"3023217600053\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nif;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAoBA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,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,qCACF;CAEF,MAAM,QAAQ,EAAE;CAChB,IACE,UAAU,OACV,UAAU,OACV,UAAU,OACV,UAAU,KAEV,OAAO,IACL,qBACA,gCACF;CAEF,MAAM,QAAQ,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CACnC,MAAM,QAAQ,OAAO,EAAE,MAAM,EAAE,CAAC;CAChC,IAAI,QAAQ,QAAQ,OAClB,OAAO,IACL,oBACA,kCACF;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,IAAI,OAAO,UAAU,GAAG,CAAC,CAAC,IAAI,aAAa,EAAE;EACnD,IAAI,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"nif.js","names":[],"sources":["../../src/fr/nif.ts"],"sourcesContent":["/**\n * NIF (Numéro d'Identification Fiscale).\n *\n * French tax identification number. 13 digits;\n * first digit is 0-3. Last 3 digits are a\n * check: first_10_digits % 511 == last_3.\n *\n * @see https://www.impots.gouv.fr/\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 if (v.length !== 13) {\n return err(\n \"INVALID_LENGTH\",\n \"French NIF must be exactly 13 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIF must contain only digits\",\n );\n }\n const first = v[0];\n if (\n first !== \"0\" &&\n first !== \"1\" &&\n first !== \"2\" &&\n first !== \"3\"\n ) {\n return err(\n \"INVALID_COMPONENT\",\n \"French NIF must start with 0-3\",\n );\n }\n const front = Number(v.slice(0, 10));\n const check = Number(v.slice(10));\n if (front % 511 !== check) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French NIF check digits 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, 4)} ${v.slice(4, 7)} ${v.slice(7, 10)} ${v.slice(10)}`;\n};\n\n/** Generate a random valid French NIF. */\nconst generate = (): string => {\n for (;;) {\n const c = String(randomInt(0, 3)) + randomDigits(12);\n if (validate(c).valid) return c;\n }\n};\n\n/** French Tax Identification Number. */\nconst nif: CountryValidator<\"FR\"> = {\n name: \"French Tax ID\",\n localName: \"Numéro d'Identification Fiscale\",\n abbreviation: \"NIF\",\n aliases: [\n \"numéro fiscal\",\n \"NIF\",\n \"numéro d'identification fiscale\",\n ] as const,\n candidatePattern: \"\\\\d{13}\",\n scope: \"country\",\n country: \"FR\",\n entityType: \"person\",\n sourceUrl: \"https://www.impots.gouv.fr/\",\n examples: [\"3023217600053\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nif;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAoBA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,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,qCACF;CAEF,MAAM,QAAQ,EAAE;CAChB,IACE,UAAU,OACV,UAAU,OACV,UAAU,OACV,UAAU,KAEV,OAAO,IACL,qBACA,gCACF;CAEF,MAAM,QAAQ,OAAO,EAAE,MAAM,GAAG,EAAE,CAAC;CACnC,MAAM,QAAQ,OAAO,EAAE,MAAM,EAAE,CAAC;CAChC,IAAI,QAAQ,QAAQ,OAClB,OAAO,IACL,oBACA,kCACF;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,IAAI,OAAO,UAAU,GAAG,CAAC,CAAC,IAAI,aAAa,EAAE;EACnD,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;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,eAAe;CAC1B;CACA;CACA;CACA;AACF"}
|
package/dist/fr/nir.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nir.js","names":[],"sources":["../../src/fr/nir.ts"],"sourcesContent":["/**\n * NIR (Numero d'Inscription au Repertoire).\n *\n * French social security number (numero de securite\n * sociale). 15 digits: 13 identity digits + 2 check\n * digits. Encodes gender, year/month of birth, and\n * department of birth.\n *\n * Corsican departments 2A/2B are encoded as 19/18\n * for the mod-97 checksum computation.\n *\n * @see https://en.wikipedia.org/wiki/INSEE_code\n */\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { resolveTwoDigitYear } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst compact = (value: string): string =>\n clean(value, \" -.\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value).toUpperCase();\n if (v.length !== 15) {\n return err(\n \"INVALID_LENGTH\",\n \"French NIR must be 15 characters\",\n );\n }\n\n const gender = v[0];\n if (gender !== \"1\" && gender !== \"2\") {\n return err(\n \"INVALID_COMPONENT\",\n \"French NIR first digit must be 1 or 2\",\n );\n }\n\n const yearPart = v.slice(1, 3);\n if (!/^\\d{2}$/.test(yearPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR year must be 2 digits\",\n );\n }\n\n const monthPart = v.slice(3, 5);\n if (!/^\\d{2}$/.test(monthPart) || monthPart === \"00\") {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR month must be 01-99\",\n );\n }\n\n const deptPart = v.slice(5, 7);\n const isCorsica = deptPart === \"2A\" || deptPart === \"2B\";\n if (!isCorsica && !/^\\d{2}$/.test(deptPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR department must be 2 digits or 2A/2B\",\n );\n }\n\n const communePart = v.slice(7, 10);\n if (!/^\\d{3}$/.test(communePart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR commune must be 3 digits\",\n );\n }\n\n const serialPart = v.slice(10, 13);\n if (!/^\\d{3}$/.test(serialPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR serial must be 3 digits\",\n );\n }\n\n const checkPart = v.slice(13, 15);\n if (!/^\\d{2}$/.test(checkPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR check must be 2 digits\",\n );\n }\n\n let numericBase: string;\n if (deptPart === \"2A\") {\n numericBase = v.slice(0, 5) + \"19\" + v.slice(7, 13);\n } else if (deptPart === \"2B\") {\n numericBase = v.slice(0, 5) + \"18\" + v.slice(7, 13);\n } else {\n numericBase = v.slice(0, 13);\n }\n\n const base = BigInt(numericBase);\n const expected = 97n - (base % 97n);\n const actual = BigInt(checkPart);\n\n if (expected !== actual) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French NIR check digits mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value).toUpperCase();\n return (\n `${v.slice(0, 1)} ${v.slice(1, 3)}` +\n ` ${v.slice(3, 5)} ${v.slice(5, 7)}` +\n ` ${v.slice(7, 10)} ${v.slice(10, 13)}` +\n ` ${v.slice(13)}`\n );\n};\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 genderDigit = v[0];\n const yy = Number(v.slice(1, 3));\n const mm = Number(v.slice(3, 5));\n\n if (mm < 1 || mm > 12) return null;\n\n const year = resolveTwoDigitYear(yy);\n const gender = genderDigit === \"1\" ? \"male\" : \"female\";\n\n return {\n birthDate: new Date(year, mm - 1, 1),\n gender,\n };\n};\n\n/** Generate a random valid French NIR. */\nconst generate = (): string => {\n for (;;) {\n const g = String(randomInt(1, 2));\n const yy = String(randomInt(50, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dept = String(randomInt(1, 95)).padStart(2, \"0\");\n const com = String(randomInt(1, 999)).padStart(3, \"0\");\n const s = String(randomInt(1, 999)).padStart(3, \"0\");\n const base = g + yy + mm + dept + com + s;\n const check = String(97 - (Number(base) % 97)).padStart(\n 2,\n \"0\",\n );\n const c = base + check;\n if (validate(c).valid) return c;\n }\n};\n\n/** French Social Security Number. */\nconst nir: CountryValidator<\"FR\", ParsedPersonId> = {\n name: \"French Social Security Number\",\n localName: \"Numero d'Inscription au Repertoire\",\n abbreviation: \"NIR\",\n aliases: [\n \"NIR\",\n \"numéro de sécurité sociale\",\n \"numéro SS\",\n \"sécu\",\n ] as const,\n candidatePattern:\n \"[12]\\\\s?\\\\d{2}\\\\s?\\\\d{2}\\\\s?\\\\d{2}\\\\s?\\\\d{3}\\\\s?\\\\d{3}\\\\s?\\\\d{2}\",\n scope: \"country\",\n country: \"FR\",\n entityType: \"person\",\n description:\n \"French social security number encoding \" +\n \"gender, birth date, and department\",\n sourceUrl: \"https://en.wikipedia.org/wiki/INSEE_code\",\n lengths: [15] as const,\n examples: [\"295117823456784\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default nir;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;AAyBA,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK,
|
|
1
|
+
{"version":3,"file":"nir.js","names":[],"sources":["../../src/fr/nir.ts"],"sourcesContent":["/**\n * NIR (Numero d'Inscription au Repertoire).\n *\n * French social security number (numero de securite\n * sociale). 15 digits: 13 identity digits + 2 check\n * digits. Encodes gender, year/month of birth, and\n * department of birth.\n *\n * Corsican departments 2A/2B are encoded as 19/18\n * for the mod-97 checksum computation.\n *\n * @see https://en.wikipedia.org/wiki/INSEE_code\n */\n\nimport type {\n ParsedPersonId,\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { resolveTwoDigitYear } from \"#util/date\";\nimport { randomInt } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst compact = (value: string): string =>\n clean(value, \" -.\");\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value).toUpperCase();\n if (v.length !== 15) {\n return err(\n \"INVALID_LENGTH\",\n \"French NIR must be 15 characters\",\n );\n }\n\n const gender = v[0];\n if (gender !== \"1\" && gender !== \"2\") {\n return err(\n \"INVALID_COMPONENT\",\n \"French NIR first digit must be 1 or 2\",\n );\n }\n\n const yearPart = v.slice(1, 3);\n if (!/^\\d{2}$/.test(yearPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR year must be 2 digits\",\n );\n }\n\n const monthPart = v.slice(3, 5);\n if (!/^\\d{2}$/.test(monthPart) || monthPart === \"00\") {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR month must be 01-99\",\n );\n }\n\n const deptPart = v.slice(5, 7);\n const isCorsica = deptPart === \"2A\" || deptPart === \"2B\";\n if (!isCorsica && !/^\\d{2}$/.test(deptPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR department must be 2 digits or 2A/2B\",\n );\n }\n\n const communePart = v.slice(7, 10);\n if (!/^\\d{3}$/.test(communePart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR commune must be 3 digits\",\n );\n }\n\n const serialPart = v.slice(10, 13);\n if (!/^\\d{3}$/.test(serialPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR serial must be 3 digits\",\n );\n }\n\n const checkPart = v.slice(13, 15);\n if (!/^\\d{2}$/.test(checkPart)) {\n return err(\n \"INVALID_FORMAT\",\n \"French NIR check must be 2 digits\",\n );\n }\n\n let numericBase: string;\n if (deptPart === \"2A\") {\n numericBase = v.slice(0, 5) + \"19\" + v.slice(7, 13);\n } else if (deptPart === \"2B\") {\n numericBase = v.slice(0, 5) + \"18\" + v.slice(7, 13);\n } else {\n numericBase = v.slice(0, 13);\n }\n\n const base = BigInt(numericBase);\n const expected = 97n - (base % 97n);\n const actual = BigInt(checkPart);\n\n if (expected !== actual) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French NIR check digits mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value).toUpperCase();\n return (\n `${v.slice(0, 1)} ${v.slice(1, 3)}` +\n ` ${v.slice(3, 5)} ${v.slice(5, 7)}` +\n ` ${v.slice(7, 10)} ${v.slice(10, 13)}` +\n ` ${v.slice(13)}`\n );\n};\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 genderDigit = v[0];\n const yy = Number(v.slice(1, 3));\n const mm = Number(v.slice(3, 5));\n\n if (mm < 1 || mm > 12) return null;\n\n const year = resolveTwoDigitYear(yy);\n const gender = genderDigit === \"1\" ? \"male\" : \"female\";\n\n return {\n birthDate: new Date(year, mm - 1, 1),\n gender,\n };\n};\n\n/** Generate a random valid French NIR. */\nconst generate = (): string => {\n for (;;) {\n const g = String(randomInt(1, 2));\n const yy = String(randomInt(50, 99)).padStart(2, \"0\");\n const mm = String(randomInt(1, 12)).padStart(2, \"0\");\n const dept = String(randomInt(1, 95)).padStart(2, \"0\");\n const com = String(randomInt(1, 999)).padStart(3, \"0\");\n const s = String(randomInt(1, 999)).padStart(3, \"0\");\n const base = g + yy + mm + dept + com + s;\n const check = String(97 - (Number(base) % 97)).padStart(\n 2,\n \"0\",\n );\n const c = base + check;\n if (validate(c).valid) return c;\n }\n};\n\n/** French Social Security Number. */\nconst nir: CountryValidator<\"FR\", ParsedPersonId> = {\n name: \"French Social Security Number\",\n localName: \"Numero d'Inscription au Repertoire\",\n abbreviation: \"NIR\",\n aliases: [\n \"NIR\",\n \"numéro de sécurité sociale\",\n \"numéro SS\",\n \"sécu\",\n ] as const,\n candidatePattern:\n \"[12]\\\\s?\\\\d{2}\\\\s?\\\\d{2}\\\\s?\\\\d{2}\\\\s?\\\\d{3}\\\\s?\\\\d{3}\\\\s?\\\\d{2}\",\n scope: \"country\",\n country: \"FR\",\n entityType: \"person\",\n description:\n \"French social security number encoding \" +\n \"gender, birth date, and department\",\n sourceUrl: \"https://en.wikipedia.org/wiki/INSEE_code\",\n lengths: [15] as const,\n examples: [\"295117823456784\"] as const,\n compact,\n format,\n parse,\n validate,\n generate,\n};\n\nexport default nir;\nexport { compact, format, parse, validate, generate };\n"],"mappings":";;;;;AAyBA,MAAM,WAAW,UACf,MAAM,OAAO,KAAK;AAEpB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK,CAAC,CAAC,YAAY;CACrC,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,kCACF;CAGF,MAAM,SAAS,EAAE;CACjB,IAAI,WAAW,OAAO,WAAW,KAC/B,OAAO,IACL,qBACA,uCACF;CAGF,MAAM,WAAW,EAAE,MAAM,GAAG,CAAC;CAC7B,IAAI,CAAC,UAAU,KAAK,QAAQ,GAC1B,OAAO,IACL,kBACA,kCACF;CAGF,MAAM,YAAY,EAAE,MAAM,GAAG,CAAC;CAC9B,IAAI,CAAC,UAAU,KAAK,SAAS,KAAK,cAAc,MAC9C,OAAO,IACL,kBACA,gCACF;CAGF,MAAM,WAAW,EAAE,MAAM,GAAG,CAAC;CAE7B,IAAI,EADc,aAAa,QAAQ,aAAa,SAClC,CAAC,UAAU,KAAK,QAAQ,GACxC,OAAO,IACL,kBACA,iDACF;CAGF,MAAM,cAAc,EAAE,MAAM,GAAG,EAAE;CACjC,IAAI,CAAC,UAAU,KAAK,WAAW,GAC7B,OAAO,IACL,kBACA,qCACF;CAGF,MAAM,aAAa,EAAE,MAAM,IAAI,EAAE;CACjC,IAAI,CAAC,UAAU,KAAK,UAAU,GAC5B,OAAO,IACL,kBACA,oCACF;CAGF,MAAM,YAAY,EAAE,MAAM,IAAI,EAAE;CAChC,IAAI,CAAC,UAAU,KAAK,SAAS,GAC3B,OAAO,IACL,kBACA,mCACF;CAGF,IAAI;CACJ,IAAI,aAAa,MACf,cAAc,EAAE,MAAM,GAAG,CAAC,IAAI,OAAO,EAAE,MAAM,GAAG,EAAE;MAC7C,IAAI,aAAa,MACtB,cAAc,EAAE,MAAM,GAAG,CAAC,IAAI,OAAO,EAAE,MAAM,GAAG,EAAE;MAElD,cAAc,EAAE,MAAM,GAAG,EAAE;CAO7B,IAHiB,MADJ,OAAO,WACO,IAAI,QAChB,OAAO,SAEA,GACpB,OAAO,IACL,oBACA,kCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK,CAAC,CAAC,YAAY;CACrC,OACE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAA,GAC5B,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAA,GAC7B,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,IAAI,EAAE,EAAA,GAChC,EAAE,MAAM,EAAE;AAElB;AAEA,MAAM,SAAS,UAAyC;CACtD,MAAM,SAAS,SAAS,KAAK;CAC7B,IAAI,CAAC,OAAO,OAAO,OAAO;CAE1B,MAAM,IAAI,OAAO;CACjB,MAAM,cAAc,EAAE;CACtB,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAE/B,IAAI,KAAK,KAAK,KAAK,IAAI,OAAO;CAE9B,MAAM,OAAO,oBAAoB,EAAE;CACnC,MAAM,SAAS,gBAAgB,MAAM,SAAS;CAE9C,OAAO;EACL,WAAW,IAAI,KAAK,MAAM,KAAK,GAAG,CAAC;EACnC;CACF;AACF;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,OAAO,UAAU,GAAG,CAAC,CAAC;EAChC,MAAM,KAAK,OAAO,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACpD,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,OAAO,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACrD,MAAM,MAAM,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACrD,MAAM,IAAI,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACnD,MAAM,OAAO,IAAI,KAAK,KAAK,OAAO,MAAM;EAKxC,MAAM,IAAI,OAJI,OAAO,KAAM,OAAO,IAAI,IAAI,EAAG,CAAC,CAAC,SAC7C,GACA,GAEmB;EACrB,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8C;CAClD,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;EACA;CACF;CACA,kBACE;CACF,OAAO;CACP,SAAS;CACT,YAAY;CACZ,aACE;CAEF,WAAW;CACX,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,iBAAiB;CAC5B;CACA;CACA;CACA;CACA;AACF"}
|
package/dist/fr/tva.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tva.js","names":[],"sources":["../../src/fr/tva.ts"],"sourcesContent":["/**\n * n° TVA (Numéro de TVA intracommunautaire).\n *\n * French VAT number. 11 characters: 2-char\n * check prefix + 9-digit SIREN. The prefix\n * can be numeric (old style) or alphanumeric\n * (new style, letters from a restricted\n * alphabet excluding I and O).\n *\n * @see https://www.economie.gouv.fr/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport {\n luhnValidate,\n luhnChecksum,\n} from \"#checksums/luhn\";\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst ALPHABET = \"0123456789ABCDEFGHJKLMNPQRSTUVWXYZ\";\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -.\");\n if (v.startsWith(\"FR\") || v.startsWith(\"fr\")) {\n v = v.slice(2);\n }\n return v.toUpperCase();\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"French TVA must be 11 characters\",\n );\n }\n\n const prefix = v.slice(0, 2);\n const siren = v.slice(2);\n\n if (!isdigits(siren)) {\n return err(\n \"INVALID_FORMAT\",\n \"French TVA SIREN part must be digits\",\n );\n }\n\n // Validate prefix characters are in alphabet\n const p0 = prefix[0] ?? \"\";\n const p1 = prefix[1] ?? \"\";\n if (\n ALPHABET.indexOf(p0) < 0 ||\n ALPHABET.indexOf(p1) < 0\n ) {\n return err(\n \"INVALID_FORMAT\",\n \"French TVA prefix contains invalid chars\",\n );\n }\n\n // SIREN validation (skip Monaco: starts with 000)\n if (!siren.startsWith(\"000\") && !luhnValidate(siren)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French TVA SIREN part fails Luhn check\",\n );\n }\n\n const c0 = ALPHABET.indexOf(p0);\n const c1 = ALPHABET.indexOf(p1);\n\n if (c0 < 10 && c1 < 10) {\n // Old-style: both digits numeric\n const check = Number(prefix);\n const expected = Number(siren + \"12\") % 97;\n if (check !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French TVA check digits mismatch\",\n );\n }\n } else {\n // New-style: at least one letter\n let cvalue: number;\n if (c0 < 10) {\n cvalue = c0 * 24 + c1 - 10;\n } else {\n cvalue = c0 * 34 + c1 - 100;\n }\n const sirenNum = Number(siren);\n if (\n (sirenNum + 1 + Math.floor(cvalue / 11)) % 11 !==\n cvalue % 11\n ) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French TVA check digits mismatch\",\n );\n }\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `FR${compact(value)}`;\n\n/** Generate a random valid French TVA. */\nconst generate = (): string => {\n const sp = randomDigits(8);\n const cs = luhnChecksum(sp + \"0\");\n const siren = sp + String((10 - cs) % 10);\n const prefix = String(\n (12 + 3 * (Number(siren) % 97)) % 97,\n ).padStart(2, \"0\");\n return prefix + siren;\n};\n\n/** French VAT Number. */\nconst tva: CountryValidator<\"FR\"> = {\n name: \"French VAT Number\",\n localName: \"Numéro de TVA intracommunautaire\",\n abbreviation: \"TVA\",\n aliases: [\n \"numéro de TVA\",\n \"TVA intracommunautaire\",\n \"FR VAT\",\n ] as const,\n candidatePattern: \"FR[A-Z0-9]{2}\\\\d{9}\",\n scope: \"country\",\n country: \"FR\",\n entityType: \"company\",\n sourceUrl: \"https://www.economie.gouv.fr/\",\n examples: [\"40303265045\", \"K7399859412\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default tva;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AA0BA,MAAM,WAAW;AAEjB,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,KAAK;CAC1B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO,EAAE,YAAY;AACvB;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,kCACF;CAGF,MAAM,SAAS,EAAE,MAAM,GAAG,CAAC;CAC3B,MAAM,QAAQ,EAAE,MAAM,CAAC;CAEvB,IAAI,CAAC,SAAS,KAAK,GACjB,OAAO,IACL,kBACA,sCACF;CAIF,MAAM,KAAK,OAAO,MAAM;CACxB,MAAM,KAAK,OAAO,MAAM;CACxB,IACE,SAAS,QAAQ,EAAE,IAAI,KACvB,SAAS,QAAQ,EAAE,IAAI,GAEvB,OAAO,IACL,kBACA,0CACF;CAIF,IAAI,CAAC,MAAM,WAAW,KAAK,KAAK,CAAC,aAAa,KAAK,GACjD,OAAO,IACL,oBACA,wCACF;CAGF,MAAM,KAAK,SAAS,QAAQ,EAAE;CAC9B,MAAM,KAAK,SAAS,QAAQ,EAAE;CAE9B,IAAI,KAAK,MAAM,KAAK;MAEJ,OAAO,MAEb,MADS,OAAO,QAAQ,IAAI,IAAI,IAEtC,OAAO,IACL,oBACA,kCACF;CAAA,OAEG;EAEL,IAAI;EACJ,IAAI,KAAK,IACP,SAAS,KAAK,KAAK,KAAK;OAExB,SAAS,KAAK,KAAK,KAAK;EAG1B,KADiB,OAAO,KAEd,IAAI,IAAI,KAAK,MAAM,SAAS,EAAE,KAAK,OAC3C,SAAS,IAET,OAAO,IACL,oBACA,kCACF;CAEJ;CAEA,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,KAAK,QAAQ,KAAK;;AAGpB,MAAM,iBAAyB;CAC7B,MAAM,KAAK,aAAa,CAAC;CACzB,MAAM,KAAK,aAAa,KAAK,GAAG;CAChC,MAAM,QAAQ,KAAK,QAAQ,KAAK,MAAM,EAAE;CAIxC,OAHe,QACZ,KAAK,KAAK,OAAO,KAAK,IAAI,OAAO,EACpC,
|
|
1
|
+
{"version":3,"file":"tva.js","names":[],"sources":["../../src/fr/tva.ts"],"sourcesContent":["/**\n * n° TVA (Numéro de TVA intracommunautaire).\n *\n * French VAT number. 11 characters: 2-char\n * check prefix + 9-digit SIREN. The prefix\n * can be numeric (old style) or alphanumeric\n * (new style, letters from a restricted\n * alphabet excluding I and O).\n *\n * @see https://www.economie.gouv.fr/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport {\n luhnValidate,\n luhnChecksum,\n} from \"#checksums/luhn\";\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst ALPHABET = \"0123456789ABCDEFGHJKLMNPQRSTUVWXYZ\";\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -.\");\n if (v.startsWith(\"FR\") || v.startsWith(\"fr\")) {\n v = v.slice(2);\n }\n return v.toUpperCase();\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"French TVA must be 11 characters\",\n );\n }\n\n const prefix = v.slice(0, 2);\n const siren = v.slice(2);\n\n if (!isdigits(siren)) {\n return err(\n \"INVALID_FORMAT\",\n \"French TVA SIREN part must be digits\",\n );\n }\n\n // Validate prefix characters are in alphabet\n const p0 = prefix[0] ?? \"\";\n const p1 = prefix[1] ?? \"\";\n if (\n ALPHABET.indexOf(p0) < 0 ||\n ALPHABET.indexOf(p1) < 0\n ) {\n return err(\n \"INVALID_FORMAT\",\n \"French TVA prefix contains invalid chars\",\n );\n }\n\n // SIREN validation (skip Monaco: starts with 000)\n if (!siren.startsWith(\"000\") && !luhnValidate(siren)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French TVA SIREN part fails Luhn check\",\n );\n }\n\n const c0 = ALPHABET.indexOf(p0);\n const c1 = ALPHABET.indexOf(p1);\n\n if (c0 < 10 && c1 < 10) {\n // Old-style: both digits numeric\n const check = Number(prefix);\n const expected = Number(siren + \"12\") % 97;\n if (check !== expected) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French TVA check digits mismatch\",\n );\n }\n } else {\n // New-style: at least one letter\n let cvalue: number;\n if (c0 < 10) {\n cvalue = c0 * 24 + c1 - 10;\n } else {\n cvalue = c0 * 34 + c1 - 100;\n }\n const sirenNum = Number(siren);\n if (\n (sirenNum + 1 + Math.floor(cvalue / 11)) % 11 !==\n cvalue % 11\n ) {\n return err(\n \"INVALID_CHECKSUM\",\n \"French TVA check digits mismatch\",\n );\n }\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `FR${compact(value)}`;\n\n/** Generate a random valid French TVA. */\nconst generate = (): string => {\n const sp = randomDigits(8);\n const cs = luhnChecksum(sp + \"0\");\n const siren = sp + String((10 - cs) % 10);\n const prefix = String(\n (12 + 3 * (Number(siren) % 97)) % 97,\n ).padStart(2, \"0\");\n return prefix + siren;\n};\n\n/** French VAT Number. */\nconst tva: CountryValidator<\"FR\"> = {\n name: \"French VAT Number\",\n localName: \"Numéro de TVA intracommunautaire\",\n abbreviation: \"TVA\",\n aliases: [\n \"numéro de TVA\",\n \"TVA intracommunautaire\",\n \"FR VAT\",\n ] as const,\n candidatePattern: \"FR[A-Z0-9]{2}\\\\d{9}\",\n scope: \"country\",\n country: \"FR\",\n entityType: \"company\",\n sourceUrl: \"https://www.economie.gouv.fr/\",\n examples: [\"40303265045\", \"K7399859412\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default tva;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AA0BA,MAAM,WAAW;AAEjB,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,KAAK;CAC1B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO,EAAE,YAAY;AACvB;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,kCACF;CAGF,MAAM,SAAS,EAAE,MAAM,GAAG,CAAC;CAC3B,MAAM,QAAQ,EAAE,MAAM,CAAC;CAEvB,IAAI,CAAC,SAAS,KAAK,GACjB,OAAO,IACL,kBACA,sCACF;CAIF,MAAM,KAAK,OAAO,MAAM;CACxB,MAAM,KAAK,OAAO,MAAM;CACxB,IACE,SAAS,QAAQ,EAAE,IAAI,KACvB,SAAS,QAAQ,EAAE,IAAI,GAEvB,OAAO,IACL,kBACA,0CACF;CAIF,IAAI,CAAC,MAAM,WAAW,KAAK,KAAK,CAAC,aAAa,KAAK,GACjD,OAAO,IACL,oBACA,wCACF;CAGF,MAAM,KAAK,SAAS,QAAQ,EAAE;CAC9B,MAAM,KAAK,SAAS,QAAQ,EAAE;CAE9B,IAAI,KAAK,MAAM,KAAK;MAEJ,OAAO,MAEb,MADS,OAAO,QAAQ,IAAI,IAAI,IAEtC,OAAO,IACL,oBACA,kCACF;CAAA,OAEG;EAEL,IAAI;EACJ,IAAI,KAAK,IACP,SAAS,KAAK,KAAK,KAAK;OAExB,SAAS,KAAK,KAAK,KAAK;EAG1B,KADiB,OAAO,KAEd,IAAI,IAAI,KAAK,MAAM,SAAS,EAAE,KAAK,OAC3C,SAAS,IAET,OAAO,IACL,oBACA,kCACF;CAEJ;CAEA,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,KAAK,QAAQ,KAAK;;AAGpB,MAAM,iBAAyB;CAC7B,MAAM,KAAK,aAAa,CAAC;CACzB,MAAM,KAAK,aAAa,KAAK,GAAG;CAChC,MAAM,QAAQ,KAAK,QAAQ,KAAK,MAAM,EAAE;CAIxC,OAHe,QACZ,KAAK,KAAK,OAAO,KAAK,IAAI,OAAO,EACpC,CAAC,CAAC,SAAS,GAAG,GACF,IAAI;AAClB;;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,eAAe,aAAa;CACvC;CACA;CACA;CACA;AACF"}
|
package/dist/gb/mod.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import nhs from "./nhs.js";
|
|
1
2
|
import nino from "./nino.js";
|
|
2
3
|
import sedol from "./sedol.js";
|
|
3
4
|
import utr from "./utr.js";
|
|
@@ -5,8 +6,8 @@ import vat from "./vat.js";
|
|
|
5
6
|
|
|
6
7
|
//#region src/gb/mod.d.ts
|
|
7
8
|
declare namespace mod_d_exports {
|
|
8
|
-
export { nino, sedol, utr, vat };
|
|
9
|
+
export { nhs, nino, sedol, utr, vat };
|
|
9
10
|
}
|
|
10
11
|
//#endregion
|
|
11
|
-
export { mod_d_exports, nino, sedol, utr, vat };
|
|
12
|
+
export { mod_d_exports, nhs, nino, sedol, utr, vat };
|
|
12
13
|
//# sourceMappingURL=mod.d.ts.map
|
package/dist/gb/mod.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import vat from "./vat.js";
|
|
3
|
+
import nhs from "./nhs.js";
|
|
3
4
|
import nino from "./nino.js";
|
|
4
5
|
import sedol from "./sedol.js";
|
|
5
6
|
import utr from "./utr.js";
|
|
6
7
|
//#region src/gb/mod.ts
|
|
7
8
|
var gb_exports = /* @__PURE__ */ __exportAll({
|
|
9
|
+
nhs: () => nhs,
|
|
8
10
|
nino: () => nino,
|
|
9
11
|
sedol: () => sedol,
|
|
10
12
|
utr: () => utr,
|
|
11
13
|
vat: () => vat
|
|
12
14
|
});
|
|
13
15
|
//#endregion
|
|
14
|
-
export { gb_exports, nino, sedol, utr, vat };
|
|
16
|
+
export { gb_exports, nhs, nino, sedol, utr, vat };
|
|
15
17
|
|
|
16
18
|
//# sourceMappingURL=mod.js.map
|
package/dist/gb/mod.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.js","names":[],"sources":["../../src/gb/mod.ts"],"sourcesContent":["export { default as nino } from \"./nino\";\nexport { default as sedol } from \"./sedol\";\nexport { default as utr } from \"./utr\";\nexport { default as vat } from \"./vat\";\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"mod.js","names":[],"sources":["../../src/gb/mod.ts"],"sourcesContent":["export { default as nhs } from \"./nhs\";\nexport { default as nino } from \"./nino\";\nexport { default as sedol } from \"./sedol\";\nexport { default as utr } from \"./utr\";\nexport { default as vat } from \"./vat\";\n"],"mappings":""}
|
package/dist/gb/nhs.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CountryValidator, ValidateResult } from "../types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/gb/nhs.d.ts
|
|
4
|
+
declare const compact: (value: string) => string;
|
|
5
|
+
declare const calcCheckDigit: (value: string) => number | null;
|
|
6
|
+
declare const validate: (value: string) => ValidateResult;
|
|
7
|
+
declare const format: (value: string) => string;
|
|
8
|
+
declare const nhs: CountryValidator<"GB">;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { calcCheckDigit, compact, nhs as default, format, validate };
|
|
11
|
+
//# sourceMappingURL=nhs.d.ts.map
|
package/dist/gb/nhs.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { clean } from "../_util/clean.js";
|
|
2
|
+
import { err } from "../_util/result.js";
|
|
3
|
+
import { isdigits } from "../_util/strings.js";
|
|
4
|
+
//#region src/gb/nhs.ts
|
|
5
|
+
const NHS_NUMBER_LENGTH = 10;
|
|
6
|
+
const CHECK_DIGIT_INDEX = 9;
|
|
7
|
+
const compact = (value) => clean(value, " ");
|
|
8
|
+
const calcCheckDigit = (value) => {
|
|
9
|
+
if (value.length !== NHS_NUMBER_LENGTH) return null;
|
|
10
|
+
if (!isdigits(value)) return null;
|
|
11
|
+
let total = 0;
|
|
12
|
+
for (let i = 0; i < CHECK_DIGIT_INDEX; i += 1) total += Number(value.charAt(i)) * (10 - i);
|
|
13
|
+
const check = 11 - total % 11;
|
|
14
|
+
if (check === 10) return null;
|
|
15
|
+
return check === 11 ? 0 : check;
|
|
16
|
+
};
|
|
17
|
+
const validate = (value) => {
|
|
18
|
+
const v = compact(value);
|
|
19
|
+
if (v.length !== NHS_NUMBER_LENGTH) return err("INVALID_LENGTH", "NHS number must be 10 digits");
|
|
20
|
+
if (!isdigits(v)) return err("INVALID_FORMAT", "NHS number must contain only digits");
|
|
21
|
+
const check = calcCheckDigit(v);
|
|
22
|
+
if (check === null || check !== Number(v.charAt(CHECK_DIGIT_INDEX))) return err("INVALID_CHECKSUM", "NHS number fails modulus 11 check");
|
|
23
|
+
return {
|
|
24
|
+
valid: true,
|
|
25
|
+
compact: v
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const format = (value) => {
|
|
29
|
+
const v = compact(value);
|
|
30
|
+
if (v.length !== NHS_NUMBER_LENGTH) return v;
|
|
31
|
+
return `${v.slice(0, 3)} ${v.slice(3, 6)} ${v.slice(6)}`;
|
|
32
|
+
};
|
|
33
|
+
const nhs = {
|
|
34
|
+
scope: "country",
|
|
35
|
+
country: "GB",
|
|
36
|
+
name: "UK NHS Number",
|
|
37
|
+
localName: "NHS number",
|
|
38
|
+
abbreviation: "NHS",
|
|
39
|
+
aliases: ["NHS number", "National Health Service number"],
|
|
40
|
+
candidatePattern: "\\d{3}\\s?\\d{3}\\s?\\d{4}",
|
|
41
|
+
entityType: "person",
|
|
42
|
+
lengths: [NHS_NUMBER_LENGTH],
|
|
43
|
+
examples: ["4010232137"],
|
|
44
|
+
compact,
|
|
45
|
+
format,
|
|
46
|
+
validate
|
|
47
|
+
};
|
|
48
|
+
//#endregion
|
|
49
|
+
export { calcCheckDigit, compact, nhs as default, format, validate };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=nhs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nhs.js","names":[],"sources":["../../src/gb/nhs.ts"],"sourcesContent":["/**\n * UK NHS Number.\n *\n * Validates the 10-digit NHS number using the\n * modulus 11 checksum used by NHS England.\n */\n\nimport type {\n CountryValidator,\n ValidateResult,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\nconst NHS_NUMBER_LENGTH = 10;\nconst CHECK_DIGIT_INDEX = 9;\n\nconst compact = (value: string): string =>\n clean(value, \" \");\n\nconst calcCheckDigit = (value: string): number | null => {\n if (value.length !== NHS_NUMBER_LENGTH) return null;\n if (!isdigits(value)) return null;\n\n let total = 0;\n for (let i = 0; i < CHECK_DIGIT_INDEX; i += 1) {\n total += Number(value.charAt(i)) * (10 - i);\n }\n\n const check = 11 - (total % 11);\n if (check === 10) return null;\n return check === 11 ? 0 : check;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== NHS_NUMBER_LENGTH) {\n return err(\n \"INVALID_LENGTH\",\n \"NHS number must be 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"NHS number must contain only digits\",\n );\n }\n\n const check = calcCheckDigit(v);\n if (\n check === null ||\n check !== Number(v.charAt(CHECK_DIGIT_INDEX))\n ) {\n return err(\n \"INVALID_CHECKSUM\",\n \"NHS number fails modulus 11 check\",\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 !== NHS_NUMBER_LENGTH) return v;\n return `${v.slice(0, 3)} ${v.slice(3, 6)} ${v.slice(6)}`;\n};\n\nconst nhs: CountryValidator<\"GB\"> = {\n scope: \"country\",\n country: \"GB\",\n name: \"UK NHS Number\",\n localName: \"NHS number\",\n abbreviation: \"NHS\",\n aliases: [\n \"NHS number\",\n \"National Health Service number\",\n ] as const,\n candidatePattern: \"\\\\d{3}\\\\s?\\\\d{3}\\\\s?\\\\d{4}\",\n entityType: \"person\",\n lengths: [NHS_NUMBER_LENGTH] as const,\n examples: [\"4010232137\"] as const,\n compact,\n format,\n validate,\n};\n\nexport default nhs;\nexport { calcCheckDigit, compact, format, validate };\n"],"mappings":";;;;AAgBA,MAAM,oBAAoB;AAC1B,MAAM,oBAAoB;AAE1B,MAAM,WAAW,UACf,MAAM,OAAO,GAAG;AAElB,MAAM,kBAAkB,UAAiC;CACvD,IAAI,MAAM,WAAW,mBAAmB,OAAO;CAC/C,IAAI,CAAC,SAAS,KAAK,GAAG,OAAO;CAE7B,IAAI,QAAQ;CACZ,KAAK,IAAI,IAAI,GAAG,IAAI,mBAAmB,KAAK,GAC1C,SAAS,OAAO,MAAM,OAAO,CAAC,CAAC,KAAK,KAAK;CAG3C,MAAM,QAAQ,KAAM,QAAQ;CAC5B,IAAI,UAAU,IAAI,OAAO;CACzB,OAAO,UAAU,KAAK,IAAI;AAC5B;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,mBACf,OAAO,IACL,kBACA,8BACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,qCACF;CAGF,MAAM,QAAQ,eAAe,CAAC;CAC9B,IACE,UAAU,QACV,UAAU,OAAO,EAAE,OAAO,iBAAiB,CAAC,GAE5C,OAAO,IACL,oBACA,mCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,mBAAmB,OAAO;CAC3C,OAAO,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AACvD;AAEA,MAAM,MAA8B;CAClC,OAAO;CACP,SAAS;CACT,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,cACA,gCACF;CACA,kBAAkB;CAClB,YAAY;CACZ,SAAS,CAAC,iBAAiB;CAC3B,UAAU,CAAC,YAAY;CACvB;CACA;CACA;AACF"}
|
package/dist/gb/nino.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nino.js","names":[],"sources":["../../src/gb/nino.ts"],"sourcesContent":["const NINO_VALID_FIRST = \"ABCEGHJKLMNOPRSTWXYZ\";\nconst NINO_VALID_SECOND = \"ABCEGHJKLMNPRSTWXYZ\";\nconst NINO_SUFFIXES = \"ABCD\";\n\n/** Generate a random valid UK NINO. */\nconst generate = (): string => {\n let first: string;\n let second: string;\n let prefix: string;\n do {\n first = randomChar(NINO_VALID_FIRST);\n second = randomChar(NINO_VALID_SECOND);\n prefix = first + second;\n } while (INVALID_PREFIX.has(prefix));\n const digits = randomDigits(6);\n const suffix = randomChar(NINO_SUFFIXES);\n return `${prefix}${digits}${suffix}`;\n};\n\n/**\n * NINO (National Insurance Number).\n *\n * UK National Insurance Number. Format: 2 letters\n * + 6 digits + 1 suffix letter (A, B, C, or D).\n * Validated by format and prefix rules only; there\n * is no checksum.\n *\n * @see https://www.gov.uk/hmrc-internal-manuals/national-insurance-manual/nim39110\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomChar, randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst INVALID_FIRST = new Set([\n \"D\",\n \"F\",\n \"I\",\n \"Q\",\n \"U\",\n \"V\",\n]);\n\nconst INVALID_SECOND = new Set([\n \"D\",\n \"F\",\n \"I\",\n \"O\",\n \"Q\",\n \"U\",\n \"V\",\n]);\n\nconst INVALID_PREFIX = new Set([\n \"BG\",\n \"GB\",\n \"NK\",\n \"KN\",\n \"TN\",\n \"NT\",\n \"ZZ\",\n]);\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 !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"UK NINO must be 9 characters\",\n );\n }\n\n if (!/^[A-Z]{2}\\d{6}[A-D]$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK NINO must be 2 letters, 6 digits, \" +\n \"then A/B/C/D\",\n );\n }\n\n // SAFETY: regex above guarantees v.length === 9.\n // eslint-disable-next-line no-non-null-assertion\n const first = v[0]!;\n // eslint-disable-next-line no-non-null-assertion\n const second = v[1]!;\n const prefix = v.slice(0, 2);\n\n if (INVALID_FIRST.has(first)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO first letter cannot be ${first}`,\n );\n }\n\n if (INVALID_SECOND.has(second)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO second letter cannot be ${second}`,\n );\n }\n\n if (INVALID_PREFIX.has(prefix)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO prefix ${prefix} is not allowed`,\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return (\n `${v.slice(0, 2)} ${v.slice(2, 4)}` +\n ` ${v.slice(4, 6)} ${v.slice(6, 8)}` +\n ` ${v.slice(8)}`\n );\n};\n\n/** UK National Insurance Number. */\nconst nino: CountryValidator<\"GB\"> = {\n name: \"UK National Insurance Number\",\n localName: \"National Insurance Number\",\n abbreviation: \"NINO\",\n aliases: [\n \"National Insurance number\",\n \"NINO\",\n \"NI number\",\n ] as const,\n candidatePattern: \"[A-Z]{2}\\\\d{6}[A-Z]\",\n scope: \"country\",\n country: \"GB\",\n entityType: \"person\",\n description:\n \"UK National Insurance Number for tax \" +\n \"and benefits\",\n sourceUrl:\n \"https://www.gov.uk/hmrc-internal-manuals/\" +\n \"national-insurance-manual/nim39110\",\n lengths: [9] as const,\n examples: [\"AB123456C\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nino;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAAA,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAC1B,MAAM,gBAAgB;;AAGtB,MAAM,iBAAyB;CAC7B,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,GAAG;EACD,QAAQ,WAAW,gBAAgB;EACnC,SAAS,WAAW,iBAAiB;EACrC,SAAS,QAAQ;CACnB,SAAS,eAAe,IAAI,MAAM;CAClC,MAAM,SAAS,aAAa,CAAC;CAC7B,MAAM,SAAS,WAAW,aAAa;CACvC,OAAO,GAAG,SAAS,SAAS;AAC9B;AAsBA,MAAM,gBAAgB,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,
|
|
1
|
+
{"version":3,"file":"nino.js","names":[],"sources":["../../src/gb/nino.ts"],"sourcesContent":["const NINO_VALID_FIRST = \"ABCEGHJKLMNOPRSTWXYZ\";\nconst NINO_VALID_SECOND = \"ABCEGHJKLMNPRSTWXYZ\";\nconst NINO_SUFFIXES = \"ABCD\";\n\n/** Generate a random valid UK NINO. */\nconst generate = (): string => {\n let first: string;\n let second: string;\n let prefix: string;\n do {\n first = randomChar(NINO_VALID_FIRST);\n second = randomChar(NINO_VALID_SECOND);\n prefix = first + second;\n } while (INVALID_PREFIX.has(prefix));\n const digits = randomDigits(6);\n const suffix = randomChar(NINO_SUFFIXES);\n return `${prefix}${digits}${suffix}`;\n};\n\n/**\n * NINO (National Insurance Number).\n *\n * UK National Insurance Number. Format: 2 letters\n * + 6 digits + 1 suffix letter (A, B, C, or D).\n * Validated by format and prefix rules only; there\n * is no checksum.\n *\n * @see https://www.gov.uk/hmrc-internal-manuals/national-insurance-manual/nim39110\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomChar, randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst INVALID_FIRST = new Set([\n \"D\",\n \"F\",\n \"I\",\n \"Q\",\n \"U\",\n \"V\",\n]);\n\nconst INVALID_SECOND = new Set([\n \"D\",\n \"F\",\n \"I\",\n \"O\",\n \"Q\",\n \"U\",\n \"V\",\n]);\n\nconst INVALID_PREFIX = new Set([\n \"BG\",\n \"GB\",\n \"NK\",\n \"KN\",\n \"TN\",\n \"NT\",\n \"ZZ\",\n]);\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 !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"UK NINO must be 9 characters\",\n );\n }\n\n if (!/^[A-Z]{2}\\d{6}[A-D]$/.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK NINO must be 2 letters, 6 digits, \" +\n \"then A/B/C/D\",\n );\n }\n\n // SAFETY: regex above guarantees v.length === 9.\n // eslint-disable-next-line no-non-null-assertion\n const first = v[0]!;\n // eslint-disable-next-line no-non-null-assertion\n const second = v[1]!;\n const prefix = v.slice(0, 2);\n\n if (INVALID_FIRST.has(first)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO first letter cannot be ${first}`,\n );\n }\n\n if (INVALID_SECOND.has(second)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO second letter cannot be ${second}`,\n );\n }\n\n if (INVALID_PREFIX.has(prefix)) {\n return err(\n \"INVALID_COMPONENT\",\n `UK NINO prefix ${prefix} is not allowed`,\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n return (\n `${v.slice(0, 2)} ${v.slice(2, 4)}` +\n ` ${v.slice(4, 6)} ${v.slice(6, 8)}` +\n ` ${v.slice(8)}`\n );\n};\n\n/** UK National Insurance Number. */\nconst nino: CountryValidator<\"GB\"> = {\n name: \"UK National Insurance Number\",\n localName: \"National Insurance Number\",\n abbreviation: \"NINO\",\n aliases: [\n \"National Insurance number\",\n \"NINO\",\n \"NI number\",\n ] as const,\n candidatePattern: \"[A-Z]{2}\\\\d{6}[A-Z]\",\n scope: \"country\",\n country: \"GB\",\n entityType: \"person\",\n description:\n \"UK National Insurance Number for tax \" +\n \"and benefits\",\n sourceUrl:\n \"https://www.gov.uk/hmrc-internal-manuals/\" +\n \"national-insurance-manual/nim39110\",\n lengths: [9] as const,\n examples: [\"AB123456C\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nino;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAAA,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAC1B,MAAM,gBAAgB;;AAGtB,MAAM,iBAAyB;CAC7B,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,GAAG;EACD,QAAQ,WAAW,gBAAgB;EACnC,SAAS,WAAW,iBAAiB;EACrC,SAAS,QAAQ;CACnB,SAAS,eAAe,IAAI,MAAM;CAClC,MAAM,SAAS,aAAa,CAAC;CAC7B,MAAM,SAAS,WAAW,aAAa;CACvC,OAAO,GAAG,SAAS,SAAS;AAC9B;AAsBA,MAAM,gBAAgB,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,CAAC,CAAC,YAAY;AAEjC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,8BACF;CAGF,IAAI,CAAC,uBAAuB,KAAK,CAAC,GAChC,OAAO,IACL,kBACA,mDAEF;CAKF,MAAM,QAAQ,EAAE;CAEhB,MAAM,SAAS,EAAE;CACjB,MAAM,SAAS,EAAE,MAAM,GAAG,CAAC;CAE3B,IAAI,cAAc,IAAI,KAAK,GACzB,OAAO,IACL,qBACA,kCAAkC,OACpC;CAGF,IAAI,eAAe,IAAI,MAAM,GAC3B,OAAO,IACL,qBACA,mCAAmC,QACrC;CAGF,IAAI,eAAe,IAAI,MAAM,GAC3B,OAAO,IACL,qBACA,kBAAkB,OAAO,gBAC3B;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OACE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAA,GAC5B,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAA,GAC7B,EAAE,MAAM,CAAC;AAEjB;;AAGA,MAAM,OAA+B;CACnC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,aACE;CAEF,WACE;CAEF,SAAS,CAAC,CAAC;CACX,UAAU,CAAC,WAAW;CACtB;CACA;CACA;CACA;AACF"}
|
package/dist/gb/sedol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sedol.js","names":[],"sources":["../../src/gb/sedol.ts"],"sourcesContent":["/**\n * SEDOL (Stock Exchange Daily Official List number).\n *\n * 7-character security identifier used in the UK and\n * Ireland, assigned by the London Stock Exchange.\n * Consists of 6 alphanumeric characters (vowels\n * excluded) followed by a weighted mod-10 check\n * digit.\n *\n * @see https://en.wikipedia.org/wiki/SEDOL\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomChar } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/**\n * Allowed characters in a SEDOL: digits and\n * consonants only (vowels are never used).\n * Spaces occupy vowel positions (A=10, E=14,\n * I=18, O=24, U=30) so that indexOf returns\n * the correct SEDOL weight for each consonant.\n */\nconst ALPHABET = \"0123456789 BCD FGH JKLMN PQRST VWXYZ\";\n\nconst WEIGHTS = [1, 3, 1, 7, 3, 9] as const;\n\nconst calcCheckDigit = (number: string): string => {\n if (number.length !== 6) {\n throw new Error(\n \"calcCheckDigit requires a 6-character \" +\n \"SEDOL prefix\",\n );\n }\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n const ch = number[i];\n if (ch === undefined) continue;\n const val = ALPHABET.indexOf(ch);\n if (val < 0) {\n throw new Error(`Invalid SEDOL character: ${ch}`);\n }\n sum += weight * val;\n }\n return String((10 - (sum % 10)) % 10);\n};\n\nconst compact = (value: string): string =>\n clean(value, \" \").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 7) {\n return err(\n \"INVALID_LENGTH\",\n \"SEDOL must be exactly 7 characters\",\n );\n }\n\n for (const ch of v) {\n if (!ALPHABET.includes(ch)) {\n return err(\n \"INVALID_FORMAT\",\n \"SEDOL contains invalid character: \" +\n \"vowels are not allowed\",\n );\n }\n }\n\n // Old-style SEDOLs are fully numeric; new-style\n // SEDOLs start with a letter. A number that starts\n // with a digit but contains letters is invalid.\n // SAFETY: v.length === 7 here.\n // eslint-disable-next-line no-non-null-assertion\n if (isdigits(v[0]!) && !isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Numeric-prefix SEDOL must be fully \" +\n \"numeric (old-style)\",\n );\n }\n\n if (calcCheckDigit(v.slice(0, 6)) !== v[6]) {\n return err(\n \"INVALID_CHECKSUM\",\n \"SEDOL check digit mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst SEDOL_CONSONANTS = \"BCDFGHJKLMNPQRSTVWXYZ\";\nconst SEDOL_CHARS = \"0123456789BCDFGHJKLMNPQRSTVWXYZ\";\n\n/** Generate a random valid SEDOL. */\nconst generate = (): string => {\n let payload = randomChar(SEDOL_CONSONANTS);\n for (let i = 1; i < 6; i++) {\n payload += randomChar(SEDOL_CHARS);\n }\n return payload + calcCheckDigit(payload);\n};\n\n/** Stock Exchange Daily Official List number. */\nconst sedol: CountryValidator<\"GB\"> = {\n name: \"Stock Exchange Daily Official List number\",\n localName: \"Stock Exchange Daily Official List number\",\n abbreviation: \"SEDOL\",\n aliases: [\n \"SEDOL\",\n \"Stock Exchange Daily Official List\",\n ] as const,\n candidatePattern: \"[B-DF-HJ-NP-TV-Z0-9]{6}\\\\d\",\n scope: \"country\",\n country: \"GB\",\n entityType: \"any\",\n sourceUrl: \"https://en.wikipedia.org/wiki/SEDOL\",\n lengths: [7] as const,\n examples: [\"B15KXQ8\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default sedol;\nexport {\n calcCheckDigit,\n compact,\n format,\n validate,\n generate,\n};\n"],"mappings":";;;;;;;;;;;;AA6BA,MAAM,WAAW;AAEjB,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAEjC,MAAM,kBAAkB,WAA2B;CACjD,IAAI,OAAO,WAAW,GACpB,MAAM,IAAI,MACR,oDAEF;CAEF,IAAI,MAAM;CACV,KAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,QAAQ,GAAG;EAC3C,MAAM,KAAK,OAAO;EAClB,IAAI,OAAO,KAAA,GAAW;EACtB,MAAM,MAAM,SAAS,QAAQ,EAAE;EAC/B,IAAI,MAAM,GACR,MAAM,IAAI,MAAM,4BAA4B,IAAI;EAElD,OAAO,SAAS;CAClB;CACA,OAAO,QAAQ,KAAM,MAAM,MAAO,EAAE;AACtC;AAEA,MAAM,WAAW,UACf,MAAM,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"sedol.js","names":[],"sources":["../../src/gb/sedol.ts"],"sourcesContent":["/**\n * SEDOL (Stock Exchange Daily Official List number).\n *\n * 7-character security identifier used in the UK and\n * Ireland, assigned by the London Stock Exchange.\n * Consists of 6 alphanumeric characters (vowels\n * excluded) followed by a weighted mod-10 check\n * digit.\n *\n * @see https://en.wikipedia.org/wiki/SEDOL\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomChar } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/**\n * Allowed characters in a SEDOL: digits and\n * consonants only (vowels are never used).\n * Spaces occupy vowel positions (A=10, E=14,\n * I=18, O=24, U=30) so that indexOf returns\n * the correct SEDOL weight for each consonant.\n */\nconst ALPHABET = \"0123456789 BCD FGH JKLMN PQRST VWXYZ\";\n\nconst WEIGHTS = [1, 3, 1, 7, 3, 9] as const;\n\nconst calcCheckDigit = (number: string): string => {\n if (number.length !== 6) {\n throw new Error(\n \"calcCheckDigit requires a 6-character \" +\n \"SEDOL prefix\",\n );\n }\n let sum = 0;\n for (const [i, weight] of WEIGHTS.entries()) {\n const ch = number[i];\n if (ch === undefined) continue;\n const val = ALPHABET.indexOf(ch);\n if (val < 0) {\n throw new Error(`Invalid SEDOL character: ${ch}`);\n }\n sum += weight * val;\n }\n return String((10 - (sum % 10)) % 10);\n};\n\nconst compact = (value: string): string =>\n clean(value, \" \").toUpperCase();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 7) {\n return err(\n \"INVALID_LENGTH\",\n \"SEDOL must be exactly 7 characters\",\n );\n }\n\n for (const ch of v) {\n if (!ALPHABET.includes(ch)) {\n return err(\n \"INVALID_FORMAT\",\n \"SEDOL contains invalid character: \" +\n \"vowels are not allowed\",\n );\n }\n }\n\n // Old-style SEDOLs are fully numeric; new-style\n // SEDOLs start with a letter. A number that starts\n // with a digit but contains letters is invalid.\n // SAFETY: v.length === 7 here.\n // eslint-disable-next-line no-non-null-assertion\n if (isdigits(v[0]!) && !isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Numeric-prefix SEDOL must be fully \" +\n \"numeric (old-style)\",\n );\n }\n\n if (calcCheckDigit(v.slice(0, 6)) !== v[6]) {\n return err(\n \"INVALID_CHECKSUM\",\n \"SEDOL check digit mismatch\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst SEDOL_CONSONANTS = \"BCDFGHJKLMNPQRSTVWXYZ\";\nconst SEDOL_CHARS = \"0123456789BCDFGHJKLMNPQRSTVWXYZ\";\n\n/** Generate a random valid SEDOL. */\nconst generate = (): string => {\n let payload = randomChar(SEDOL_CONSONANTS);\n for (let i = 1; i < 6; i++) {\n payload += randomChar(SEDOL_CHARS);\n }\n return payload + calcCheckDigit(payload);\n};\n\n/** Stock Exchange Daily Official List number. */\nconst sedol: CountryValidator<\"GB\"> = {\n name: \"Stock Exchange Daily Official List number\",\n localName: \"Stock Exchange Daily Official List number\",\n abbreviation: \"SEDOL\",\n aliases: [\n \"SEDOL\",\n \"Stock Exchange Daily Official List\",\n ] as const,\n candidatePattern: \"[B-DF-HJ-NP-TV-Z0-9]{6}\\\\d\",\n scope: \"country\",\n country: \"GB\",\n entityType: \"any\",\n sourceUrl: \"https://en.wikipedia.org/wiki/SEDOL\",\n lengths: [7] as const,\n examples: [\"B15KXQ8\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default sedol;\nexport {\n calcCheckDigit,\n compact,\n format,\n validate,\n generate,\n};\n"],"mappings":";;;;;;;;;;;;AA6BA,MAAM,WAAW;AAEjB,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAEjC,MAAM,kBAAkB,WAA2B;CACjD,IAAI,OAAO,WAAW,GACpB,MAAM,IAAI,MACR,oDAEF;CAEF,IAAI,MAAM;CACV,KAAK,MAAM,CAAC,GAAG,WAAW,QAAQ,QAAQ,GAAG;EAC3C,MAAM,KAAK,OAAO;EAClB,IAAI,OAAO,KAAA,GAAW;EACtB,MAAM,MAAM,SAAS,QAAQ,EAAE;EAC/B,IAAI,MAAM,GACR,MAAM,IAAI,MAAM,4BAA4B,IAAI;EAElD,OAAO,SAAS;CAClB;CACA,OAAO,QAAQ,KAAM,MAAM,MAAO,EAAE;AACtC;AAEA,MAAM,WAAW,UACf,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY;AAEhC,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,oCACF;CAGF,KAAK,MAAM,MAAM,GACf,IAAI,CAAC,SAAS,SAAS,EAAE,GACvB,OAAO,IACL,kBACA,0DAEF;CASJ,IAAI,SAAS,EAAE,EAAG,KAAK,CAAC,SAAS,CAAC,GAChC,OAAO,IACL,kBACA,wDAEF;CAGF,IAAI,eAAe,EAAE,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,IACtC,OAAO,IACL,oBACA,4BACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;AAEvD,MAAM,mBAAmB;AACzB,MAAM,cAAc;;AAGpB,MAAM,iBAAyB;CAC7B,IAAI,UAAU,WAAW,gBAAgB;CACzC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KACrB,WAAW,WAAW,WAAW;CAEnC,OAAO,UAAU,eAAe,OAAO;AACzC;;AAGA,MAAM,QAAgC;CACpC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CACP,SACA,oCACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,CAAC;CACX,UAAU,CAAC,SAAS;CACpB;CACA;CACA;CACA;AACF"}
|
package/dist/gb/utr.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utr.js","names":[],"sources":["../../src/gb/utr.ts"],"sourcesContent":["/**\n * UTR (Unique Taxpayer Reference).\n *\n * UK 10-digit tax reference number. The first\n * digit is a check digit computed using a\n * weighted sum with lookup table.\n *\n * @see https://www.gov.uk/find-utr-number\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 WEIGHTS = [6, 7, 8, 9, 10, 5, 4, 3, 2] as const;\nconst CHECK_LOOKUP = \"21987654321\";\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 \"UK UTR must be exactly 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK UTR must contain only digits\",\n );\n }\n const sum = weightedSum(v.slice(1), WEIGHTS, 11);\n const expected = CHECK_LOOKUP[sum];\n if (expected !== v[0]) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UK UTR 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, 5)} ${v.slice(5)}`;\n};\n\n/** Generate a random valid UK UTR. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(10);\n if (validate(c).valid) return c;\n }\n};\n\n/** UK Unique Taxpayer Reference. */\nconst utr: CountryValidator<\"GB\"> = {\n name: \"UK Unique Taxpayer Reference\",\n localName: \"Unique Taxpayer Reference\",\n abbreviation: \"UTR\",\n aliases: [\"Unique Taxpayer Reference\", \"UTR\"] as const,\n candidatePattern: \"\\\\d{10}\",\n scope: \"country\",\n country: \"GB\",\n entityType: \"any\",\n sourceUrl: \"https://www.gov.uk/find-utr-number\",\n examples: [\"1955839661\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default utr;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAqBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;AAAC;AAC3C,MAAM,eAAe;AAErB,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,kCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,iCACF;CAIF,IADiB,aADL,YAAY,EAAE,MAAM,CAAC,GAAG,SAAS,EACb,OACf,EAAE,IACjB,OAAO,IACL,oBACA,6BACF;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,CAAC;AACtC;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,EAAE;EACzB,IAAI,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"utr.js","names":[],"sources":["../../src/gb/utr.ts"],"sourcesContent":["/**\n * UTR (Unique Taxpayer Reference).\n *\n * UK 10-digit tax reference number. The first\n * digit is a check digit computed using a\n * weighted sum with lookup table.\n *\n * @see https://www.gov.uk/find-utr-number\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 WEIGHTS = [6, 7, 8, 9, 10, 5, 4, 3, 2] as const;\nconst CHECK_LOOKUP = \"21987654321\";\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 \"UK UTR must be exactly 10 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK UTR must contain only digits\",\n );\n }\n const sum = weightedSum(v.slice(1), WEIGHTS, 11);\n const expected = CHECK_LOOKUP[sum];\n if (expected !== v[0]) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UK UTR 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, 5)} ${v.slice(5)}`;\n};\n\n/** Generate a random valid UK UTR. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(10);\n if (validate(c).valid) return c;\n }\n};\n\n/** UK Unique Taxpayer Reference. */\nconst utr: CountryValidator<\"GB\"> = {\n name: \"UK Unique Taxpayer Reference\",\n localName: \"Unique Taxpayer Reference\",\n abbreviation: \"UTR\",\n aliases: [\"Unique Taxpayer Reference\", \"UTR\"] as const,\n candidatePattern: \"\\\\d{10}\",\n scope: \"country\",\n country: \"GB\",\n entityType: \"any\",\n sourceUrl: \"https://www.gov.uk/find-utr-number\",\n examples: [\"1955839661\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default utr;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAqBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAI;CAAG;CAAG;CAAG;AAAC;AAC3C,MAAM,eAAe;AAErB,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,kCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,iCACF;CAIF,IADiB,aADL,YAAY,EAAE,MAAM,CAAC,GAAG,SAAS,EACb,OACf,EAAE,IACjB,OAAO,IACL,oBACA,6BACF;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,CAAC;AACtC;;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,6BAA6B,KAAK;CAC5C,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,YAAY;CACvB;CACA;CACA;CACA;AACF"}
|
package/dist/gb/vat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vat.js","names":[],"sources":["../../src/gb/vat.ts"],"sourcesContent":["/**\n * VAT (Value Added Tax registration number).\n *\n * UK VAT number. Multiple formats: 9 or 12\n * digit standard, GD+3 (government), HA+3\n * (health authority). Standard numbers use a\n * weighted checksum mod 97.\n *\n * @see https://www.gov.uk/vat-registration\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 WEIGHTS = [8, 7, 6, 5, 4, 3, 2] as const;\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -.\");\n if (v.startsWith(\"GB\") || v.startsWith(\"gb\")) {\n v = v.slice(2);\n }\n return v.toUpperCase();\n};\n\nconst validateStandard = (v: string): ValidateResult => {\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK VAT must contain only digits\",\n );\n }\n // Weighted sum of first 7 digits\n const sum = weightedSum(v.slice(0, 7), WEIGHTS, 97);\n // Check digits are digits 8-9\n const checkPart = Number(v.slice(7, 9));\n const total = (sum + checkPart) % 97;\n\n const prefix = Number(v.slice(0, 3));\n if (prefix >= 100) {\n // Numbers >= 100 000 000: remainder must be\n // 0, 42, or 55\n if (total !== 0 && total !== 42 && total !== 55) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UK VAT check digits mismatch\",\n );\n }\n } else {\n if (total !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UK VAT check digits mismatch\",\n );\n }\n }\n return { valid: true, compact: v };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n // Government departments: GD + 3 digits (< 500)\n if (v.startsWith(\"GD\")) {\n const num = v.slice(2);\n if (num.length !== 3 || !isdigits(num)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK VAT GD number must be GD + 3 digits\",\n );\n }\n if (Number(num) >= 500) {\n return err(\n \"INVALID_COMPONENT\",\n \"UK VAT GD number must be < 500\",\n );\n }\n return { valid: true, compact: v };\n }\n\n // Health authorities: HA + 3 digits (>= 500)\n if (v.startsWith(\"HA\")) {\n const num = v.slice(2);\n if (num.length !== 3 || !isdigits(num)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK VAT HA number must be HA + 3 digits\",\n );\n }\n if (Number(num) < 500) {\n return err(\n \"INVALID_COMPONENT\",\n \"UK VAT HA number must be >= 500\",\n );\n }\n return { valid: true, compact: v };\n }\n\n // Standard: 9 or 12 digits\n if (v.length !== 9 && v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"UK VAT must be 9 or 12 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK VAT must contain only digits\",\n );\n }\n const result = validateStandard(v.slice(0, 9));\n if (!result.valid) return result;\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.startsWith(\"GD\") || v.startsWith(\"HA\")) {\n return `GB${v}`;\n }\n return `GB ${v.slice(0, 3)} ${v.slice(3, 7)} ${v.slice(7)}`;\n};\n\n/** Generate a random valid UK VAT number. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(9);\n if (validate(c).valid) return c;\n }\n};\n\n/** UK VAT Registration Number. */\nconst vat: CountryValidator<\"GB\"> = {\n name: \"UK VAT Number\",\n localName: \"VAT Registration Number\",\n abbreviation: \"VAT\",\n aliases: [\n \"VAT registration number\",\n \"VAT number\",\n ] as const,\n candidatePattern: \"GB\\\\d{9,12}\",\n scope: \"country\",\n country: \"GB\",\n entityType: \"company\",\n sourceUrl: \"https://www.gov.uk/vat-registration\",\n examples: [\"980780684\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAsBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAEpC,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,KAAK;CAC1B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO,EAAE,YAAY;AACvB;AAEA,MAAM,oBAAoB,MAA8B;CACtD,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,iCACF;CAMF,MAAM,SAHM,YAAY,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,EAG/B,IADC,OAAO,EAAE,MAAM,GAAG,CAAC,CACR,KAAK;CAGlC,IADe,OAAO,EAAE,MAAM,GAAG,CAAC,CACzB,KAAK;MAGR,UAAU,KAAK,UAAU,MAAM,UAAU,IAC3C,OAAO,IACL,oBACA,8BACF;CAAA,OAGF,IAAI,UAAU,GACZ,OAAO,IACL,oBACA,8BACF;CAGJ,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAGvB,IAAI,EAAE,WAAW,IAAI,GAAG;EACtB,MAAM,MAAM,EAAE,MAAM,CAAC;EACrB,IAAI,IAAI,WAAW,KAAK,CAAC,SAAS,GAAG,GACnC,OAAO,IACL,kBACA,wCACF;EAEF,IAAI,OAAO,GAAG,KAAK,KACjB,OAAO,IACL,qBACA,gCACF;EAEF,OAAO;GAAE,OAAO;GAAM,SAAS;EAAE;CACnC;CAGA,IAAI,EAAE,WAAW,IAAI,GAAG;EACtB,MAAM,MAAM,EAAE,MAAM,CAAC;EACrB,IAAI,IAAI,WAAW,KAAK,CAAC,SAAS,GAAG,GACnC,OAAO,IACL,kBACA,wCACF;EAEF,IAAI,OAAO,GAAG,IAAI,KAChB,OAAO,IACL,qBACA,iCACF;EAEF,OAAO;GAAE,OAAO;GAAM,SAAS;EAAE;CACnC;CAGA,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,IACjC,OAAO,IACL,kBACA,+BACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,iCACF;CAEF,MAAM,SAAS,iBAAiB,EAAE,MAAM,GAAG,CAAC,CAAC;CAC7C,IAAI,CAAC,OAAO,OAAO,OAAO;CAC1B,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,OAAO,KAAK;CAEd,OAAO,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AAC1D;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,CAAC;EACxB,IAAI,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"vat.js","names":[],"sources":["../../src/gb/vat.ts"],"sourcesContent":["/**\n * VAT (Value Added Tax registration number).\n *\n * UK VAT number. Multiple formats: 9 or 12\n * digit standard, GD+3 (government), HA+3\n * (health authority). Standard numbers use a\n * weighted checksum mod 97.\n *\n * @see https://www.gov.uk/vat-registration\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 WEIGHTS = [8, 7, 6, 5, 4, 3, 2] as const;\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -.\");\n if (v.startsWith(\"GB\") || v.startsWith(\"gb\")) {\n v = v.slice(2);\n }\n return v.toUpperCase();\n};\n\nconst validateStandard = (v: string): ValidateResult => {\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK VAT must contain only digits\",\n );\n }\n // Weighted sum of first 7 digits\n const sum = weightedSum(v.slice(0, 7), WEIGHTS, 97);\n // Check digits are digits 8-9\n const checkPart = Number(v.slice(7, 9));\n const total = (sum + checkPart) % 97;\n\n const prefix = Number(v.slice(0, 3));\n if (prefix >= 100) {\n // Numbers >= 100 000 000: remainder must be\n // 0, 42, or 55\n if (total !== 0 && total !== 42 && total !== 55) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UK VAT check digits mismatch\",\n );\n }\n } else {\n if (total !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"UK VAT check digits mismatch\",\n );\n }\n }\n return { valid: true, compact: v };\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n // Government departments: GD + 3 digits (< 500)\n if (v.startsWith(\"GD\")) {\n const num = v.slice(2);\n if (num.length !== 3 || !isdigits(num)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK VAT GD number must be GD + 3 digits\",\n );\n }\n if (Number(num) >= 500) {\n return err(\n \"INVALID_COMPONENT\",\n \"UK VAT GD number must be < 500\",\n );\n }\n return { valid: true, compact: v };\n }\n\n // Health authorities: HA + 3 digits (>= 500)\n if (v.startsWith(\"HA\")) {\n const num = v.slice(2);\n if (num.length !== 3 || !isdigits(num)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK VAT HA number must be HA + 3 digits\",\n );\n }\n if (Number(num) < 500) {\n return err(\n \"INVALID_COMPONENT\",\n \"UK VAT HA number must be >= 500\",\n );\n }\n return { valid: true, compact: v };\n }\n\n // Standard: 9 or 12 digits\n if (v.length !== 9 && v.length !== 12) {\n return err(\n \"INVALID_LENGTH\",\n \"UK VAT must be 9 or 12 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"UK VAT must contain only digits\",\n );\n }\n const result = validateStandard(v.slice(0, 9));\n if (!result.valid) return result;\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => {\n const v = compact(value);\n if (v.startsWith(\"GD\") || v.startsWith(\"HA\")) {\n return `GB${v}`;\n }\n return `GB ${v.slice(0, 3)} ${v.slice(3, 7)} ${v.slice(7)}`;\n};\n\n/** Generate a random valid UK VAT number. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(9);\n if (validate(c).valid) return c;\n }\n};\n\n/** UK VAT Registration Number. */\nconst vat: CountryValidator<\"GB\"> = {\n name: \"UK VAT Number\",\n localName: \"VAT Registration Number\",\n abbreviation: \"VAT\",\n aliases: [\n \"VAT registration number\",\n \"VAT number\",\n ] as const,\n candidatePattern: \"GB\\\\d{9,12}\",\n scope: \"country\",\n country: \"GB\",\n entityType: \"company\",\n sourceUrl: \"https://www.gov.uk/vat-registration\",\n examples: [\"980780684\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAsBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAEpC,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,KAAK;CAC1B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO,EAAE,YAAY;AACvB;AAEA,MAAM,oBAAoB,MAA8B;CACtD,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,iCACF;CAMF,MAAM,SAHM,YAAY,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,EAG/B,IADC,OAAO,EAAE,MAAM,GAAG,CAAC,CACR,KAAK;CAGlC,IADe,OAAO,EAAE,MAAM,GAAG,CAAC,CACzB,KAAK;MAGR,UAAU,KAAK,UAAU,MAAM,UAAU,IAC3C,OAAO,IACL,oBACA,8BACF;CAAA,OAGF,IAAI,UAAU,GACZ,OAAO,IACL,oBACA,8BACF;CAGJ,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAGvB,IAAI,EAAE,WAAW,IAAI,GAAG;EACtB,MAAM,MAAM,EAAE,MAAM,CAAC;EACrB,IAAI,IAAI,WAAW,KAAK,CAAC,SAAS,GAAG,GACnC,OAAO,IACL,kBACA,wCACF;EAEF,IAAI,OAAO,GAAG,KAAK,KACjB,OAAO,IACL,qBACA,gCACF;EAEF,OAAO;GAAE,OAAO;GAAM,SAAS;EAAE;CACnC;CAGA,IAAI,EAAE,WAAW,IAAI,GAAG;EACtB,MAAM,MAAM,EAAE,MAAM,CAAC;EACrB,IAAI,IAAI,WAAW,KAAK,CAAC,SAAS,GAAG,GACnC,OAAO,IACL,kBACA,wCACF;EAEF,IAAI,OAAO,GAAG,IAAI,KAChB,OAAO,IACL,qBACA,iCACF;EAEF,OAAO;GAAE,OAAO;GAAM,SAAS;EAAE;CACnC;CAGA,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,IACjC,OAAO,IACL,kBACA,+BACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,iCACF;CAEF,MAAM,SAAS,iBAAiB,EAAE,MAAM,GAAG,CAAC,CAAC;CAC7C,IAAI,CAAC,OAAO,OAAO,OAAO;CAC1B,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,OAAO,KAAK;CAEd,OAAO,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC;AAC1D;;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,CACP,2BACA,YACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,WAAW;CACtB;CACA;CACA;CACA;AACF"}
|
package/dist/ge/pin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pin.js","names":[],"sources":["../../src/ge/pin.ts"],"sourcesContent":["/** Generate a random valid Georgian PIN (11-digit). */\nconst generate = (): string => randomDigits(11);\n\n/**\n * PIN (Personal Identification Number, პირადი ნომერი).\n *\n * Georgian personal identification number issued by the\n * Public Service Development Agency. Citizens receive an\n * 11-digit number (also used as TIN); non-citizens and\n * entities receive a 9-digit number. The number is a\n * serial with no embedded semantics and no publicly\n * documented checksum algorithm.\n *\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Georgia-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 clean(value, \" -\").trim();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 9 && v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"Georgian PIN must be 9 or 11 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Georgian PIN must contain only digits\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Georgian Personal Identification Number. */\nconst pin: CountryValidator<\"GE\"> = {\n name: \"Georgian Personal ID\",\n localName: \"პირადი ნომერი\",\n abbreviation: \"PIN\",\n aliases: [\"პირადი ნომერი\", \"PIN\"] as const,\n candidatePattern: \"\\\\d{11}\",\n scope: \"country\",\n country: \"GE\",\n entityType: \"any\",\n lengths: [9, 11] as const,\n examples: [\"010043120\", \"01024030303\"] as const,\n compact,\n format,\n validate,\n sourceUrl:\n \"https://www.oecd.org/tax/automatic-exchange/\" +\n \"crs-implementation-and-assistance/\" +\n \"tax-identification-numbers/Georgia-TIN.pdf\",\n generate,\n};\n\nexport default pin;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AACA,MAAM,iBAAyB,aAAa,EAAE;AAyB9C,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,
|
|
1
|
+
{"version":3,"file":"pin.js","names":[],"sources":["../../src/ge/pin.ts"],"sourcesContent":["/** Generate a random valid Georgian PIN (11-digit). */\nconst generate = (): string => randomDigits(11);\n\n/**\n * PIN (Personal Identification Number, პირადი ნომერი).\n *\n * Georgian personal identification number issued by the\n * Public Service Development Agency. Citizens receive an\n * 11-digit number (also used as TIN); non-citizens and\n * entities receive a 9-digit number. The number is a\n * serial with no embedded semantics and no publicly\n * documented checksum algorithm.\n *\n * @see https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Georgia-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 clean(value, \" -\").trim();\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length !== 9 && v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"Georgian PIN must be 9 or 11 digits\",\n );\n }\n\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Georgian PIN must contain only digits\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\n/** Georgian Personal Identification Number. */\nconst pin: CountryValidator<\"GE\"> = {\n name: \"Georgian Personal ID\",\n localName: \"პირადი ნომერი\",\n abbreviation: \"PIN\",\n aliases: [\"პირადი ნომერი\", \"PIN\"] as const,\n candidatePattern: \"\\\\d{11}\",\n scope: \"country\",\n country: \"GE\",\n entityType: \"any\",\n lengths: [9, 11] as const,\n examples: [\"010043120\", \"01024030303\"] as const,\n compact,\n format,\n validate,\n sourceUrl:\n \"https://www.oecd.org/tax/automatic-exchange/\" +\n \"crs-implementation-and-assistance/\" +\n \"tax-identification-numbers/Georgia-TIN.pdf\",\n generate,\n};\n\nexport default pin;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AACA,MAAM,iBAAyB,aAAa,EAAE;AAyB9C,MAAM,WAAW,UACf,MAAM,OAAO,IAAI,CAAC,CAAC,KAAK;AAE1B,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,IACjC,OAAO,IACL,kBACA,qCACF;CAGF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,uCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;;AAGvD,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,iBAAiB,KAAK;CAChC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,GAAG,EAAE;CACf,UAAU,CAAC,aAAa,aAAa;CACrC;CACA;CACA;CACA,WACE;CAGF;AACF"}
|
package/dist/gh/tin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tin.js","names":[],"sources":["../../src/gh/tin.ts"],"sourcesContent":["/**\n * TIN (Tax Identification Number, Ghana).\n *\n * 11-character alphanumeric identifier. Structure:\n * - Position 1: type prefix (P/C/G/Q/V)\n * - Positions 2-3: always \"00\"\n * - Positions 4-10: digits\n * - Position 11: check digit (0-9 or X)\n *\n * Prefixes: P = individual, C = company,\n * G = government, Q = foreign mission,\n * V = public institution / trust.\n *\n * @see https://gra.gov.gh/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomPick } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst FORMAT_RE = /^[PCGQV]00[0-9]{7}[0-9X]$/;\n\nconst compact = (value: string): string =>\n clean(value, \" \").toUpperCase();\n\n/**\n * Calculate the expected check digit.\n * Uses positions 1-9 (0-indexed) with weights 1-9,\n * mod 11. Returns \"X\" when the remainder is 10.\n */\nconst calcCheckDigit = (value: string): string => {\n let sum = 0;\n for (let i = 1; i <= 9; i++) {\n sum += i * Number(value[i]);\n }\n const check = sum % 11;\n return check === 10 ? \"X\" : String(check);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"Ghanaian TIN must be exactly 11 characters\",\n );\n }\n if (!FORMAT_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Ghanaian TIN must match [PCGQV]00 + \" +\n \"7 digits + check digit\",\n );\n }\n if (v[10] !== calcCheckDigit(v)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Ghanaian TIN check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst TIN_PREFIXES = [\"P\", \"C\", \"G\", \"Q\", \"V\"] as const;\n\n/** Generate a random valid Ghana TIN. */\nconst generate = (): string => {\n for (;;) {\n const p = randomPick(TIN_PREFIXES);\n const d = randomDigits(9);\n const partial = p + d;\n const c = partial + calcCheckDigit(partial);\n if (validate(c).valid) return c;\n }\n};\n\n/** Ghanaian Tax Identification Number. */\nconst tin: CountryValidator<\"GH\"> = {\n name: \"Ghanaian Tax Identification Number\",\n localName: \"Tax Identification Number\",\n abbreviation: \"TIN\",\n aliases: [\"TIN\", \"Tax Identification Number\"] as const,\n candidatePattern: \"[A-Z]\\\\d{9,10}\",\n scope: \"country\",\n country: \"GH\",\n entityType: \"any\",\n compact,\n format,\n validate,\n description: \"Ghanaian tax identification number\",\n sourceUrl: \"https://gra.gov.gh/\",\n lengths: [11] as const,\n examples: [\"C0000803561\"] as const,\n generate,\n};\n\nexport default tin;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAyBA,MAAM,YAAY;AAElB,MAAM,WAAW,UACf,MAAM,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"tin.js","names":[],"sources":["../../src/gh/tin.ts"],"sourcesContent":["/**\n * TIN (Tax Identification Number, Ghana).\n *\n * 11-character alphanumeric identifier. Structure:\n * - Position 1: type prefix (P/C/G/Q/V)\n * - Positions 2-3: always \"00\"\n * - Positions 4-10: digits\n * - Position 11: check digit (0-9 or X)\n *\n * Prefixes: P = individual, C = company,\n * G = government, Q = foreign mission,\n * V = public institution / trust.\n *\n * @see https://gra.gov.gh/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits, randomPick } from \"#util/generate\";\nimport { err } from \"#util/result\";\n\nconst FORMAT_RE = /^[PCGQV]00[0-9]{7}[0-9X]$/;\n\nconst compact = (value: string): string =>\n clean(value, \" \").toUpperCase();\n\n/**\n * Calculate the expected check digit.\n * Uses positions 1-9 (0-indexed) with weights 1-9,\n * mod 11. Returns \"X\" when the remainder is 10.\n */\nconst calcCheckDigit = (value: string): string => {\n let sum = 0;\n for (let i = 1; i <= 9; i++) {\n sum += i * Number(value[i]);\n }\n const check = sum % 11;\n return check === 10 ? \"X\" : String(check);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"Ghanaian TIN must be exactly 11 characters\",\n );\n }\n if (!FORMAT_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Ghanaian TIN must match [PCGQV]00 + \" +\n \"7 digits + check digit\",\n );\n }\n if (v[10] !== calcCheckDigit(v)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Ghanaian TIN check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string => compact(value);\n\nconst TIN_PREFIXES = [\"P\", \"C\", \"G\", \"Q\", \"V\"] as const;\n\n/** Generate a random valid Ghana TIN. */\nconst generate = (): string => {\n for (;;) {\n const p = randomPick(TIN_PREFIXES);\n const d = randomDigits(9);\n const partial = p + d;\n const c = partial + calcCheckDigit(partial);\n if (validate(c).valid) return c;\n }\n};\n\n/** Ghanaian Tax Identification Number. */\nconst tin: CountryValidator<\"GH\"> = {\n name: \"Ghanaian Tax Identification Number\",\n localName: \"Tax Identification Number\",\n abbreviation: \"TIN\",\n aliases: [\"TIN\", \"Tax Identification Number\"] as const,\n candidatePattern: \"[A-Z]\\\\d{9,10}\",\n scope: \"country\",\n country: \"GH\",\n entityType: \"any\",\n compact,\n format,\n validate,\n description: \"Ghanaian tax identification number\",\n sourceUrl: \"https://gra.gov.gh/\",\n lengths: [11] as const,\n examples: [\"C0000803561\"] as const,\n generate,\n};\n\nexport default tin;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;AAyBA,MAAM,YAAY;AAElB,MAAM,WAAW,UACf,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY;;;;;;AAOhC,MAAM,kBAAkB,UAA0B;CAChD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KACtB,OAAO,IAAI,OAAO,MAAM,EAAE;CAE5B,MAAM,QAAQ,MAAM;CACpB,OAAO,UAAU,KAAK,MAAM,OAAO,KAAK;AAC1C;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,IACf,OAAO,IACL,kBACA,4CACF;CAEF,IAAI,CAAC,UAAU,KAAK,CAAC,GACnB,OAAO,IACL,kBACA,4DAEF;CAEF,IAAI,EAAE,QAAQ,eAAe,CAAC,GAC5B,OAAO,IACL,oBACA,mCACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;AAEvD,MAAM,eAAe;CAAC;CAAK;CAAK;CAAK;CAAK;AAAG;;AAG7C,MAAM,iBAAyB;CAC7B,SAAS;EAGP,MAAM,UAFI,WAAW,YAEL,IADN,aAAa,CACH;EACpB,MAAM,IAAI,UAAU,eAAe,OAAO;EAC1C,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,OAAO,2BAA2B;CAC5C,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ;CACA;CACA;CACA,aAAa;CACb,WAAW;CACX,SAAS,CAAC,EAAE;CACZ,UAAU,CAAC,aAAa;CACxB;AACF"}
|
package/dist/gr/amka.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"amka.js","names":[],"sources":["../../src/gr/amka.ts"],"sourcesContent":["/**\n * AMKA (Αριθμός Μητρώου Κοινωνικής Ασφάλισης).\n *\n * Greek social security number. 11 digits where the\n * first 6 are DDMMYY, followed by 4-digit serial and\n * a Luhn check digit.\n *\n * @see https://www.amka.gr/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport {\n luhnValidate,\n luhnChecksum,\n} from \"#checksums/luhn\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\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 if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"AMKA must be exactly 11 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"AMKA 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 yy = Number(v.slice(4, 6));\n\n // AMKA doesn't encode century explicitly;\n // validate the date for both 1900s and 2000s\n const valid1900 = isValidDate(1900 + yy, mm, dd);\n const valid2000 = isValidDate(2000 + yy, mm, dd);\n if (!valid1900 && !valid2000) {\n return err(\n \"INVALID_COMPONENT\",\n \"AMKA contains an invalid date\",\n );\n }\n\n if (!luhnValidate(v)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"AMKA Luhn 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/** Generate a random valid Greek AMKA. */\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 yy = String(randomInt(50, 99)).padStart(2, \"0\");\n const serial = randomDigits(4);\n const payload = dd + mm + yy + serial;\n const cs = luhnChecksum(payload + \"0\");\n const c = payload + String((10 - cs) % 10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Greek Social Security Number. */\nconst amka: CountryValidator<\"GR\"> = {\n name: \"Greek Social Security Number\",\n localName: \"Αριθμός Μητρώου Κοινωνικής Ασφάλισης\",\n abbreviation: \"ΑΜΚΑ\",\n aliases: [\n \"ΑΜΚΑ\",\n \"Αριθμός Μητρώου Κοινωνικής Ασφάλισης\",\n \"AMKA\",\n ] as const,\n candidatePattern: \"\\\\d{11}\",\n scope: \"country\",\n country: \"GR\",\n entityType: \"person\",\n sourceUrl: \"https://www.amka.gr/\",\n examples: [\"01013099997\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default amka;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;AAyBA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,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;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAI/B,MAAM,YAAY,YAAY,OAAO,IAAI,IAAI,EAAE;CAC/C,MAAM,YAAY,YAAY,MAAO,IAAI,IAAI,EAAE;CAC/C,IAAI,CAAC,aAAa,CAAC,WACjB,OAAO,IACL,qBACA,+BACF;CAGF,IAAI,CAAC,aAAa,CAAC,GACjB,OAAO,IACL,oBACA,sCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;;AAGvD,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,KAAK,OAAO,UAAU,GAAG,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"amka.js","names":[],"sources":["../../src/gr/amka.ts"],"sourcesContent":["/**\n * AMKA (Αριθμός Μητρώου Κοινωνικής Ασφάλισης).\n *\n * Greek social security number. 11 digits where the\n * first 6 are DDMMYY, followed by 4-digit serial and\n * a Luhn check digit.\n *\n * @see https://www.amka.gr/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport {\n luhnValidate,\n luhnChecksum,\n} from \"#checksums/luhn\";\nimport { clean } from \"#util/clean\";\nimport { isValidDate } from \"#util/date\";\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 if (v.length !== 11) {\n return err(\n \"INVALID_LENGTH\",\n \"AMKA must be exactly 11 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"AMKA 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 yy = Number(v.slice(4, 6));\n\n // AMKA doesn't encode century explicitly;\n // validate the date for both 1900s and 2000s\n const valid1900 = isValidDate(1900 + yy, mm, dd);\n const valid2000 = isValidDate(2000 + yy, mm, dd);\n if (!valid1900 && !valid2000) {\n return err(\n \"INVALID_COMPONENT\",\n \"AMKA contains an invalid date\",\n );\n }\n\n if (!luhnValidate(v)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"AMKA Luhn 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/** Generate a random valid Greek AMKA. */\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 yy = String(randomInt(50, 99)).padStart(2, \"0\");\n const serial = randomDigits(4);\n const payload = dd + mm + yy + serial;\n const cs = luhnChecksum(payload + \"0\");\n const c = payload + String((10 - cs) % 10);\n if (validate(c).valid) return c;\n }\n};\n\n/** Greek Social Security Number. */\nconst amka: CountryValidator<\"GR\"> = {\n name: \"Greek Social Security Number\",\n localName: \"Αριθμός Μητρώου Κοινωνικής Ασφάλισης\",\n abbreviation: \"ΑΜΚΑ\",\n aliases: [\n \"ΑΜΚΑ\",\n \"Αριθμός Μητρώου Κοινωνικής Ασφάλισης\",\n \"AMKA\",\n ] as const,\n candidatePattern: \"\\\\d{11}\",\n scope: \"country\",\n country: \"GR\",\n entityType: \"person\",\n sourceUrl: \"https://www.amka.gr/\",\n examples: [\"01013099997\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default amka;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;;AAyBA,MAAM,WAAW,UACf,MAAM,OAAO,IAAI;AAEnB,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;CAC/B,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;CAI/B,MAAM,YAAY,YAAY,OAAO,IAAI,IAAI,EAAE;CAC/C,MAAM,YAAY,YAAY,MAAO,IAAI,IAAI,EAAE;CAC/C,IAAI,CAAC,aAAa,CAAC,WACjB,OAAO,IACL,qBACA,+BACF;CAGF,IAAI,CAAC,aAAa,CAAC,GACjB,OAAO,IACL,oBACA,sCACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B,QAAQ,KAAK;;AAGvD,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,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;EACpD,MAAM,SAAS,aAAa,CAAC;EAC7B,MAAM,UAAU,KAAK,KAAK,KAAK;EAC/B,MAAM,KAAK,aAAa,UAAU,GAAG;EACrC,MAAM,IAAI,UAAU,QAAQ,KAAK,MAAM,EAAE;EACzC,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,OAA+B;CACnC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS;EACP;EACA;EACA;CACF;CACA,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,UAAU,CAAC,aAAa;CACxB;CACA;CACA;CACA;AACF"}
|
package/dist/gt/nit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nit.js","names":[],"sources":["../../src/gt/nit.ts"],"sourcesContent":["/**\n * NIT (Número de Identificación Tributaria,\n * Guatemala tax number).\n *\n * 2–12 characters: body digits followed by a check\n * character. The check character is computed via a\n * weighted sum mod 11; remainder 10 maps to 'K'.\n *\n * Ported from python-stdnum gt.nit module.\n *\n * @see https://portal.sat.gob.gt/portal/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/**\n * Compact: strip spaces, hyphens, leading zeros,\n * and uppercase.\n */\nconst compact = (value: string): string => {\n const v = clean(value, \" -\").trim().toUpperCase();\n return v.replace(/^0+/, \"\");\n};\n\n/**\n * Calculate the check character for a body string.\n * Weighted sum mod 11; remainder 10 yields 'K'.\n */\nconst calcCheckChar = (body: string): string => {\n let sum = 0;\n const len = body.length;\n for (let i = 0; i < len; i++) {\n sum += (len - i + 1) * Number(body[i]);\n }\n const remainder = ((-sum % 11) + 11) % 11;\n return remainder === 10 ? \"K\" : String(remainder);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length < 2 || v.length > 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Guatemala NIT must be 2–12 characters\",\n );\n }\n\n const body = v.slice(0, -1);\n const check = v.slice(-1);\n\n if (!isdigits(body)) {\n return err(\n \"INVALID_FORMAT\",\n \"Guatemala NIT body must contain only digits\",\n );\n }\n\n if (check !== \"K\" && !/^\\d$/.test(check)) {\n return err(\n \"INVALID_FORMAT\",\n \"Guatemala NIT check character must be a digit or K\",\n );\n }\n\n if (check !== calcCheckChar(body)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Guatemala NIT check character does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\n/**\n * Format: insert a hyphen before the check character.\n */\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, -1)}-${v.slice(-1)}`;\n};\n\n/** Generate a random valid NIT (7 body digits). */\nconst generate = (): string => {\n for (;;) {\n const body = randomDigits(7);\n if (body.startsWith(\"0\")) continue;\n const check = calcCheckChar(body);\n return `${body}${check}`;\n }\n};\n\n/** Guatemala tax identification number. */\nconst nit: CountryValidator<\"GT\"> = {\n name: \"Tax Identification Number\",\n localName: \"Número de Identificación Tributaria\",\n abbreviation: \"NIT\",\n aliases: [\"NIT\"] as const,\n candidatePattern: \"\\\\d{7,8}-?\\\\d\",\n scope: \"country\",\n country: \"GT\",\n entityType: \"any\",\n description: \"Tax identifier issued by Guatemala's SAT\",\n sourceUrl: \"https://portal.sat.gob.gt/portal/\",\n lengths: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] as const,\n examples: [\"576937K\", \"39525503\", \"71080\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nit;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;AA2BA,MAAM,WAAW,UAA0B;CAEzC,OADU,MAAM,OAAO,IAAI,
|
|
1
|
+
{"version":3,"file":"nit.js","names":[],"sources":["../../src/gt/nit.ts"],"sourcesContent":["/**\n * NIT (Número de Identificación Tributaria,\n * Guatemala tax number).\n *\n * 2–12 characters: body digits followed by a check\n * character. The check character is computed via a\n * weighted sum mod 11; remainder 10 maps to 'K'.\n *\n * Ported from python-stdnum gt.nit module.\n *\n * @see https://portal.sat.gob.gt/portal/\n */\n\nimport type {\n ValidateResult,\n CountryValidator,\n} from \"../types\";\n\nimport { clean } from \"#util/clean\";\nimport { randomDigits } from \"#util/generate\";\nimport { err } from \"#util/result\";\nimport { isdigits } from \"#util/strings\";\n\n/**\n * Compact: strip spaces, hyphens, leading zeros,\n * and uppercase.\n */\nconst compact = (value: string): string => {\n const v = clean(value, \" -\").trim().toUpperCase();\n return v.replace(/^0+/, \"\");\n};\n\n/**\n * Calculate the check character for a body string.\n * Weighted sum mod 11; remainder 10 yields 'K'.\n */\nconst calcCheckChar = (body: string): string => {\n let sum = 0;\n const len = body.length;\n for (let i = 0; i < len; i++) {\n sum += (len - i + 1) * Number(body[i]);\n }\n const remainder = ((-sum % 11) + 11) % 11;\n return remainder === 10 ? \"K\" : String(remainder);\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n\n if (v.length < 2 || v.length > 12) {\n return err(\n \"INVALID_LENGTH\",\n \"Guatemala NIT must be 2–12 characters\",\n );\n }\n\n const body = v.slice(0, -1);\n const check = v.slice(-1);\n\n if (!isdigits(body)) {\n return err(\n \"INVALID_FORMAT\",\n \"Guatemala NIT body must contain only digits\",\n );\n }\n\n if (check !== \"K\" && !/^\\d$/.test(check)) {\n return err(\n \"INVALID_FORMAT\",\n \"Guatemala NIT check character must be a digit or K\",\n );\n }\n\n if (check !== calcCheckChar(body)) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Guatemala NIT check character does not match\",\n );\n }\n\n return { valid: true, compact: v };\n};\n\n/**\n * Format: insert a hyphen before the check character.\n */\nconst format = (value: string): string => {\n const v = compact(value);\n return `${v.slice(0, -1)}-${v.slice(-1)}`;\n};\n\n/** Generate a random valid NIT (7 body digits). */\nconst generate = (): string => {\n for (;;) {\n const body = randomDigits(7);\n if (body.startsWith(\"0\")) continue;\n const check = calcCheckChar(body);\n return `${body}${check}`;\n }\n};\n\n/** Guatemala tax identification number. */\nconst nit: CountryValidator<\"GT\"> = {\n name: \"Tax Identification Number\",\n localName: \"Número de Identificación Tributaria\",\n abbreviation: \"NIT\",\n aliases: [\"NIT\"] as const,\n candidatePattern: \"\\\\d{7,8}-?\\\\d\",\n scope: \"country\",\n country: \"GT\",\n entityType: \"any\",\n description: \"Tax identifier issued by Guatemala's SAT\",\n sourceUrl: \"https://portal.sat.gob.gt/portal/\",\n lengths: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] as const,\n examples: [\"576937K\", \"39525503\", \"71080\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default nit;\nexport { compact, format, generate, validate };\n"],"mappings":";;;;;;;;;AA2BA,MAAM,WAAW,UAA0B;CAEzC,OADU,MAAM,OAAO,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,YAC7B,CAAC,CAAC,QAAQ,OAAO,EAAE;AAC5B;;;;;AAMA,MAAM,iBAAiB,SAAyB;CAC9C,IAAI,MAAM;CACV,MAAM,MAAM,KAAK;CACjB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KACvB,QAAQ,MAAM,IAAI,KAAK,OAAO,KAAK,EAAE;CAEvC,MAAM,aAAc,CAAC,MAAM,KAAM,MAAM;CACvC,OAAO,cAAc,KAAK,MAAM,OAAO,SAAS;AAClD;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CAEvB,IAAI,EAAE,SAAS,KAAK,EAAE,SAAS,IAC7B,OAAO,IACL,kBACA,uCACF;CAGF,MAAM,OAAO,EAAE,MAAM,GAAG,EAAE;CAC1B,MAAM,QAAQ,EAAE,MAAM,EAAE;CAExB,IAAI,CAAC,SAAS,IAAI,GAChB,OAAO,IACL,kBACA,6CACF;CAGF,IAAI,UAAU,OAAO,CAAC,OAAO,KAAK,KAAK,GACrC,OAAO,IACL,kBACA,oDACF;CAGF,IAAI,UAAU,cAAc,IAAI,GAC9B,OAAO,IACL,oBACA,8CACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;;;;AAKA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CACvB,OAAO,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;AACxC;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,OAAO,aAAa,CAAC;EAC3B,IAAI,KAAK,WAAW,GAAG,GAAG;EAE1B,OAAO,GAAG,OADI,cAAc,IACP;CACvB;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,KAAK;CACf,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,aAAa;CACb,WAAW;CACX,SAAS;EAAC;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAI;EAAI;CAAE;CAC5C,UAAU;EAAC;EAAW;EAAY;CAAO;CACzC;CACA;CACA;CACA;AACF"}
|
package/dist/hk/hkid.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hkid.js","names":[],"sources":["../../src/hk/hkid.ts"],"sourcesContent":["/**\n * HKID (Hong Kong Identity Card number).\n *\n * 1-2 letters + 6 digits + check digit in parentheses.\n * The check digit is computed via a weighted sum mod 11,\n * where letters have values A=10, B=11, ..., Z=35.\n * A remainder of 10 yields check digit 'A'.\n *\n * @see https://en.wikipedia.org/wiki/Hong_Kong_identity_card\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/** Strip spaces, parentheses, and dashes. */\nconst compact = (value: string): string =>\n clean(value, \" -()\").toUpperCase();\n\n/**\n * Compute the weighted check character.\n *\n * For a two-letter prefix the weights are 9,8,7,6,5,4,3,2\n * over the 8 characters (2 letters + 6 digits). For a\n * single-letter prefix, a space (value 36) is prepended\n * so the weights stay the same.\n */\nconst computeCheck = (body: string): string => {\n const padded = body.length === 7 ? ` ${body}` : body;\n\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n const ch = padded[i];\n if (ch === undefined) continue;\n let val: number;\n if (ch === \" \") {\n val = 36;\n } else if (ch >= \"A\" && ch <= \"Z\") {\n val = ch.charCodeAt(0) - 55; // A=10\n } else {\n val = Number(ch);\n }\n sum += val * (9 - i);\n }\n\n const remainder = sum % 11;\n if (remainder === 0) return \"0\";\n if (remainder === 1) return \"A\";\n return String(11 - remainder);\n};\n\nconst HKID_RE = /^[A-Z]{1,2}\\d{6}[0-9A]$/;\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8 && v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"HKID must be 8 or 9 characters\",\n );\n }\n if (!HKID_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"HKID must be 1-2 letters, 6 digits, \" +\n \"and a check character\",\n );\n }\n\n const body = v.slice(0, -1);\n const check = v.slice(-1);\n if (computeCheck(body) !== check) {\n return err(\n \"INVALID_CHECKSUM\",\n \"HKID 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 prefix = v.slice(0, -7);\n const digits = v.slice(-7, -1);\n const check = v.slice(-1);\n return `${prefix}${digits}(${check})`;\n};\n\n/** Generate a random valid HKID. */\nconst generate = (): string => {\n for (;;) {\n const letter = String.fromCharCode(\n 65 + randomInt(0, 25),\n );\n const digits = randomDigits(6);\n for (let d = 0; d <= 9; d++) {\n const c = letter + digits + String(d);\n if (validate(c).valid) return compact(c);\n }\n const cA = letter + digits + \"A\";\n if (validate(cA).valid) return compact(cA);\n }\n};\n\n/** Hong Kong Identity Card number. */\nconst hkid: CountryValidator<\"HK\"> = {\n name: \"Hong Kong Identity Card Number\",\n localName: \"Hong Kong Identity Card Number\",\n abbreviation: \"HKID\",\n aliases: [\"HKID\", \"香港身份證\"] as const,\n candidatePattern: \"[A-Z]{1,2}\\\\d{6}[\\\\dA]\",\n scope: \"country\",\n country: \"HK\",\n entityType: \"person\",\n lengths: [8, 9],\n examples: [\"G123456A\", \"AB9876543\"],\n description:\n \"Identity card number issued by the Hong Kong \" +\n \"Immigration Department\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/\" +\n \"Hong_Kong_identity_card\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default hkid;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAqBA,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"hkid.js","names":[],"sources":["../../src/hk/hkid.ts"],"sourcesContent":["/**\n * HKID (Hong Kong Identity Card number).\n *\n * 1-2 letters + 6 digits + check digit in parentheses.\n * The check digit is computed via a weighted sum mod 11,\n * where letters have values A=10, B=11, ..., Z=35.\n * A remainder of 10 yields check digit 'A'.\n *\n * @see https://en.wikipedia.org/wiki/Hong_Kong_identity_card\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/** Strip spaces, parentheses, and dashes. */\nconst compact = (value: string): string =>\n clean(value, \" -()\").toUpperCase();\n\n/**\n * Compute the weighted check character.\n *\n * For a two-letter prefix the weights are 9,8,7,6,5,4,3,2\n * over the 8 characters (2 letters + 6 digits). For a\n * single-letter prefix, a space (value 36) is prepended\n * so the weights stay the same.\n */\nconst computeCheck = (body: string): string => {\n const padded = body.length === 7 ? ` ${body}` : body;\n\n let sum = 0;\n for (let i = 0; i < 8; i++) {\n const ch = padded[i];\n if (ch === undefined) continue;\n let val: number;\n if (ch === \" \") {\n val = 36;\n } else if (ch >= \"A\" && ch <= \"Z\") {\n val = ch.charCodeAt(0) - 55; // A=10\n } else {\n val = Number(ch);\n }\n sum += val * (9 - i);\n }\n\n const remainder = sum % 11;\n if (remainder === 0) return \"0\";\n if (remainder === 1) return \"A\";\n return String(11 - remainder);\n};\n\nconst HKID_RE = /^[A-Z]{1,2}\\d{6}[0-9A]$/;\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8 && v.length !== 9) {\n return err(\n \"INVALID_LENGTH\",\n \"HKID must be 8 or 9 characters\",\n );\n }\n if (!HKID_RE.test(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"HKID must be 1-2 letters, 6 digits, \" +\n \"and a check character\",\n );\n }\n\n const body = v.slice(0, -1);\n const check = v.slice(-1);\n if (computeCheck(body) !== check) {\n return err(\n \"INVALID_CHECKSUM\",\n \"HKID 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 prefix = v.slice(0, -7);\n const digits = v.slice(-7, -1);\n const check = v.slice(-1);\n return `${prefix}${digits}(${check})`;\n};\n\n/** Generate a random valid HKID. */\nconst generate = (): string => {\n for (;;) {\n const letter = String.fromCharCode(\n 65 + randomInt(0, 25),\n );\n const digits = randomDigits(6);\n for (let d = 0; d <= 9; d++) {\n const c = letter + digits + String(d);\n if (validate(c).valid) return compact(c);\n }\n const cA = letter + digits + \"A\";\n if (validate(cA).valid) return compact(cA);\n }\n};\n\n/** Hong Kong Identity Card number. */\nconst hkid: CountryValidator<\"HK\"> = {\n name: \"Hong Kong Identity Card Number\",\n localName: \"Hong Kong Identity Card Number\",\n abbreviation: \"HKID\",\n aliases: [\"HKID\", \"香港身份證\"] as const,\n candidatePattern: \"[A-Z]{1,2}\\\\d{6}[\\\\dA]\",\n scope: \"country\",\n country: \"HK\",\n entityType: \"person\",\n lengths: [8, 9],\n examples: [\"G123456A\", \"AB9876543\"],\n description:\n \"Identity card number issued by the Hong Kong \" +\n \"Immigration Department\",\n sourceUrl:\n \"https://en.wikipedia.org/wiki/\" +\n \"Hong_Kong_identity_card\",\n compact,\n format,\n validate,\n generate,\n};\n\nexport default hkid;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;AAqBA,MAAM,WAAW,UACf,MAAM,OAAO,MAAM,CAAC,CAAC,YAAY;;;;;;;;;AAUnC,MAAM,gBAAgB,SAAyB;CAC7C,MAAM,SAAS,KAAK,WAAW,IAAI,IAAI,SAAS;CAEhD,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,MAAM,KAAK,OAAO;EAClB,IAAI,OAAO,KAAA,GAAW;EACtB,IAAI;EACJ,IAAI,OAAO,KACT,MAAM;OACD,IAAI,MAAM,OAAO,MAAM,KAC5B,MAAM,GAAG,WAAW,CAAC,IAAI;OAEzB,MAAM,OAAO,EAAE;EAEjB,OAAO,OAAO,IAAI;CACpB;CAEA,MAAM,YAAY,MAAM;CACxB,IAAI,cAAc,GAAG,OAAO;CAC5B,IAAI,cAAc,GAAG,OAAO;CAC5B,OAAO,OAAO,KAAK,SAAS;AAC9B;AAEA,MAAM,UAAU;AAEhB,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,KAAK,EAAE,WAAW,GACjC,OAAO,IACL,kBACA,gCACF;CAEF,IAAI,CAAC,QAAQ,KAAK,CAAC,GACjB,OAAO,IACL,kBACA,2DAEF;CAGF,MAAM,OAAO,EAAE,MAAM,GAAG,EAAE;CAC1B,MAAM,QAAQ,EAAE,MAAM,EAAE;CACxB,IAAI,aAAa,IAAI,MAAM,OACzB,OAAO,IACL,oBACA,2BACF;CAGF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UAA0B;CACxC,MAAM,IAAI,QAAQ,KAAK;CAIvB,OAAO,GAHQ,EAAE,MAAM,GAAG,EAGX,IAFA,EAAE,MAAM,IAAI,EAEH,EAAE,GADZ,EAAE,MAAM,EACW,EAAE;AACrC;;AAGA,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,SAAS,OAAO,aACpB,KAAK,UAAU,GAAG,EAAE,CACtB;EACA,MAAM,SAAS,aAAa,CAAC;EAC7B,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;GAC3B,MAAM,IAAI,SAAS,SAAS,OAAO,CAAC;GACpC,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO,QAAQ,CAAC;EACzC;EACA,MAAM,KAAK,SAAS,SAAS;EAC7B,IAAI,SAAS,EAAE,CAAC,CAAC,OAAO,OAAO,QAAQ,EAAE;CAC3C;AACF;;AAGA,MAAM,OAA+B;CACnC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,QAAQ,OAAO;CACzB,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,SAAS,CAAC,GAAG,CAAC;CACd,UAAU,CAAC,YAAY,WAAW;CAClC,aACE;CAEF,WACE;CAEF;CACA;CACA;CACA;AACF"}
|
package/dist/hu/vat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vat.js","names":[],"sources":["../../src/hu/vat.ts"],"sourcesContent":["/**\n * ANUM (Hungarian VAT number).\n *\n * 8 digits. Weights [9,7,3,1,9,7,3,1],\n * sum % 10 === 0.\n *\n * @see https://www.vatify.eu/hungary-vat-number.html\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/hungary-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 WEIGHTS = [9, 7, 3, 1, 9, 7, 3, 1];\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"HU\") || v.startsWith(\"hu\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"Hungarian VAT number must be 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Hungarian VAT number must contain only digits\",\n );\n }\n const sum = weightedSum(v, WEIGHTS, 10);\n if (sum !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Hungarian VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `HU${compact(value)}`;\n\n/** Generate a random valid Hungarian VAT number. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(8);\n if (validate(c).valid) return c;\n }\n};\n\n/** Hungarian VAT Number. */\nconst vat: CountryValidator<\"HU\"> = {\n name: \"Hungarian VAT Number\",\n localName: \"Adószám\",\n abbreviation: \"ANUM\",\n aliases: [\"adószám\", \"adóazonosító jel\"] as const,\n candidatePattern: \"\\\\d{8}-\\\\d-\\\\d{2}\",\n scope: \"country\",\n country: \"HU\",\n entityType: \"company\",\n sourceUrl: \"https://nav.gov.hu/\",\n lengths: [8] as const,\n examples: [\"12892312\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAqBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAEvC,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,MAAM;CAC3B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO;AACT;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,uCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,+CACF;CAGF,IADY,YAAY,GAAG,SAAS,EAC9B,MAAM,GACV,OAAO,IACL,oBACA,2CACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,KAAK,QAAQ,KAAK;;AAGpB,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,CAAC;EACxB,IAAI,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"vat.js","names":[],"sources":["../../src/hu/vat.ts"],"sourcesContent":["/**\n * ANUM (Hungarian VAT number).\n *\n * 8 digits. Weights [9,7,3,1,9,7,3,1],\n * sum % 10 === 0.\n *\n * @see https://www.vatify.eu/hungary-vat-number.html\n * @see https://www.oecd.org/content/dam/oecd/en/topics/policy-issue-focus/aeoi/hungary-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 WEIGHTS = [9, 7, 3, 1, 9, 7, 3, 1];\n\nconst compact = (value: string): string => {\n let v = clean(value, \" -/.\");\n if (v.startsWith(\"HU\") || v.startsWith(\"hu\")) {\n v = v.slice(2);\n }\n return v;\n};\n\nconst validate = (value: string): ValidateResult => {\n const v = compact(value);\n if (v.length !== 8) {\n return err(\n \"INVALID_LENGTH\",\n \"Hungarian VAT number must be 8 digits\",\n );\n }\n if (!isdigits(v)) {\n return err(\n \"INVALID_FORMAT\",\n \"Hungarian VAT number must contain only digits\",\n );\n }\n const sum = weightedSum(v, WEIGHTS, 10);\n if (sum !== 0) {\n return err(\n \"INVALID_CHECKSUM\",\n \"Hungarian VAT number check digit mismatch\",\n );\n }\n return { valid: true, compact: v };\n};\n\nconst format = (value: string): string =>\n `HU${compact(value)}`;\n\n/** Generate a random valid Hungarian VAT number. */\nconst generate = (): string => {\n for (;;) {\n const c = randomDigits(8);\n if (validate(c).valid) return c;\n }\n};\n\n/** Hungarian VAT Number. */\nconst vat: CountryValidator<\"HU\"> = {\n name: \"Hungarian VAT Number\",\n localName: \"Adószám\",\n abbreviation: \"ANUM\",\n aliases: [\"adószám\", \"adóazonosító jel\"] as const,\n candidatePattern: \"\\\\d{8}-\\\\d-\\\\d{2}\",\n scope: \"country\",\n country: \"HU\",\n entityType: \"company\",\n sourceUrl: \"https://nav.gov.hu/\",\n lengths: [8] as const,\n examples: [\"12892312\"] as const,\n compact,\n format,\n validate,\n generate,\n};\n\nexport default vat;\nexport { compact, format, validate, generate };\n"],"mappings":";;;;;;AAqBA,MAAM,UAAU;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;CAAG;AAAC;AAEvC,MAAM,WAAW,UAA0B;CACzC,IAAI,IAAI,MAAM,OAAO,MAAM;CAC3B,IAAI,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,GACzC,IAAI,EAAE,MAAM,CAAC;CAEf,OAAO;AACT;AAEA,MAAM,YAAY,UAAkC;CAClD,MAAM,IAAI,QAAQ,KAAK;CACvB,IAAI,EAAE,WAAW,GACf,OAAO,IACL,kBACA,uCACF;CAEF,IAAI,CAAC,SAAS,CAAC,GACb,OAAO,IACL,kBACA,+CACF;CAGF,IADY,YAAY,GAAG,SAAS,EAC9B,MAAM,GACV,OAAO,IACL,oBACA,2CACF;CAEF,OAAO;EAAE,OAAO;EAAM,SAAS;CAAE;AACnC;AAEA,MAAM,UAAU,UACd,KAAK,QAAQ,KAAK;;AAGpB,MAAM,iBAAyB;CAC7B,SAAS;EACP,MAAM,IAAI,aAAa,CAAC;EACxB,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,OAAO;CAChC;AACF;;AAGA,MAAM,MAA8B;CAClC,MAAM;CACN,WAAW;CACX,cAAc;CACd,SAAS,CAAC,WAAW,kBAAkB;CACvC,kBAAkB;CAClB,OAAO;CACP,SAAS;CACT,YAAY;CACZ,WAAW;CACX,SAAS,CAAC,CAAC;CACX,UAAU,CAAC,UAAU;CACrB;CACA;CACA;CACA;AACF"}
|