[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80454":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":13,"contributorsCount":13,"subscribersCount":13,"size":13,"stars1d":13,"stars7d":13,"stars30d":13,"stars90d":13,"forks30d":13,"starsTrendScore":13,"compositeScore":13,"rankGlobal":10,"rankLanguage":10,"license":15,"archived":16,"fork":16,"defaultBranch":17,"hasWiki":18,"hasPages":16,"topics":19,"createdAt":10,"pushedAt":10,"updatedAt":20,"readmeContent":21,"aiSummary":22,"trendingCount":13,"starSnapshotCount":13,"syncStatus":14,"lastSyncTime":23,"discoverSource":24},80454,"tr-validation","apideposu\u002Ftr-validation","apideposu","Local-only validation and normalization toolkit for Turkiye-specific form data. No backend calls, no telemetry, no registry lookup.","",null,"TypeScript",52,0,2,"MIT License",false,"main",true,[],"2026-06-12 02:04:02","# @apideposu\u002Ftr-validation\n\n`@apideposu\u002Ftr-validation` is a local-only validation and normalization toolkit for Turkiye-specific form data.\n\nTurkish documentation: [README.tr.md](.\u002FREADME.tr.md)\n\n## Local-Only and Privacy\n\n- The package runs completely inside the user's own project.\n- It does not call API Deposu backend.\n- It does not send data anywhere.\n- It does not perform registry lookup.\n- It does not include telemetry, analytics, or network calls.\n- It does not perform official person, company, tax, or bank-account verification.\n- It provides structural validation, known control algorithms, and normalization only.\n\n## Limitations\n\n- `validateIban` is TR-only.\n- `normalizePhone` does not verify the current operator and does not check portability records.\n- `possibleOriginalOperator` is a prefix-based hint only.\n- `normalizeProvince` and `normalizeDistrict` rely on bundled static data, not live government or address registries.\n- Ambiguous district names such as `Merkez` may require province context.\n- A successful result does not mean official verification. See [Out of Scope](#out-of-scope-no-official-verification) for the full list of registries this package never calls.\n\n## Installation\n\n```bash\nnpm install @apideposu\u002Ftr-validation\n```\n\n## Quick Start\n\n```ts\nimport {\n  normalizePhone,\n  validateIban,\n  validateTckn,\n} from \"@apideposu\u002Ftr-validation\";\n\nconst tckn = validateTckn(\"100 000 001-46\");\nconst iban = validateIban(\"tr62 0001 0012 3456 7890 1234 56\");\nconst phone = normalizePhone(\"0532 123 45 67\");\n```\n\n## Current Scope\n\nExports:\n\n- `validateTckn`\n- `validateVkn`\n- `validateIban`\n- `formatIban`\n- `validatePlate`\n- `validateCreditCard`\n- `validateMersis`\n- `validatePostalCode`\n- `validateBarcode`\n- `validateBatch`\n- `getReasonMessage`\n- `parseTurkishNumber`\n- `parseTurkishCurrency`\n- `resolveIbanBank`\n- `listTrBanks`\n- `titleCaseTurkish`\n- `normalizeTurkishText`\n- `slugifyTurkish`\n- `normalizePhone`\n- `getProvinces`\n- `getDistrictsByProvince`\n- `normalizeProvince`\n- `normalizeDistrict`\n\n## API Overview\n\nBase validation result shape:\n\n```ts\n{\n  ok: boolean;\n  input: string;\n  normalized: string;\n  reasons: string[];\n  mode: \"structural_validation\" | \"number_plan_parse\" | \"static_dataset\";\n  localOnly: true;\n  officialVerification: false;\n  registryLookup: false;\n}\n```\n\nFunction summary:\n\n| Function | Purpose | Notes |\n| --- | --- | --- |\n| `validateTckn(input)` | Structural validation for TCKN | Format + known control algorithm only |\n| `validateVkn(input)` | Structural validation for VKN | Format + known control algorithm only |\n| `validateIban(input)` | Structural validation for TR IBAN | TR-only, MOD-97 checksum |\n| `formatIban(input)` | Formats an IBAN in 4-character groups | Normalizes separators and casing |\n| `validatePlate(input)` | Structural validation for TR license plate | KGM block rules + province code cross-check |\n| `validateCreditCard(input)` | Luhn checksum + BIN-based scheme detection | Visa, Mastercard, Amex, Troy, Discover, JCB, Diners, UnionPay |\n| `validateMersis(input)` | Structural validation for 16-digit MERSIS number | Extracts the embedded VKN and reuses the VKN checksum |\n| `validatePostalCode(input)` | Structural validation for 5-digit TR postal code | First two digits cross-checked against the province dataset |\n| `validateBarcode(input)` | EAN-13 \u002F EAN-8 checksum validation | Detects type and flags Turkish GS1 prefixes (868, 869) |\n| `validateBatch(items)` | Runs mixed validators\u002Fparsers in order | Preserves input order and delegates to existing core functions |\n| `getReasonMessage(code, locale?)` | Maps reason codes to UI-friendly text | Localized `tr` \u002F `en` messages for form and import workflows |\n| `parseTurkishNumber(input)` | Locale-aware numeric parser | Detects TR (`1.234,56`) vs EN (`1,234.56`) grouping; flags ambiguous `1.234` |\n| `parseTurkishCurrency(input)` | Currency-aware numeric parser | Recognizes `₺`, `$`, `€`, `£`, `TL`, ISO 4217 codes (TRY, USD, EUR, GBP, ...) |\n| `resolveIbanBank(input)` | Resolves a bank from a valid TR IBAN | Uses bundled BDDK code table, returns `null` for unknown codes |\n| `listTrBanks()` | Returns the bundled TR bank list | Defensive copy, suitable for dropdowns |\n| `titleCaseTurkish(input)` | Title-cases text with Turkish I\u002Fİ rules | Treats whitespace, `-`, `\u002F` as word separators; keeps apostrophe-suffixed words single |\n| `normalizeTurkishText(input)` | Turkish-aware text normalization | Returns `trimmed`, `normalized`, `ascii`, `slug`, `searchKey` |\n| `slugifyTurkish(input)` | Slug helper for Turkish text | Consistent with `normalizeTurkishText(input).slug` |\n| `normalizePhone(input, options?)` | Local Turkish phone parsing and normalization | Adds `e164`, `national`, `country`, `type`, and prefix-based operator hint |\n| `getProvinces()` | Returns bundled province records | Static dataset only |\n| `getDistrictsByProvince(provinceCodeOrSlug)` | Returns districts for a province | Static dataset only |\n| `normalizeProvince(input)` | Matches a province by code, name, or slug | Returns `province` on success |\n| `normalizeDistrict(input, options?)` | Matches a district, optionally within a province | Returns `district` and `province` on success |\n\n## Extended Usage\n\n```ts\nimport {\n  formatIban,\n  getDistrictsByProvince,\n  getProvinces,\n  normalizeDistrict,\n  normalizePhone,\n  normalizeProvince,\n  normalizeTurkishText,\n  slugifyTurkish,\n  getReasonMessage,\n  validateBatch,\n  validateIban,\n  validateTckn,\n  validateVkn,\n} from \"@apideposu\u002Ftr-validation\";\n\nconst tckn = validateTckn(\"100 000 001-46\");\nconst vkn = validateVkn(\"734.033.4753\");\nconst iban = validateIban(\"tr62 0001 0012 3456 7890 1234 56\");\nconst formattedIban = formatIban(\"tr620001001234567890123456\");\nconst text = normalizeTurkishText(\"  ISTANBUL \u002F Kadikoy  \");\nconst slug = slugifyTurkish(\"Cekmekoy Belediyesi\");\n\nconst phone = normalizePhone(\"0532 123 45 67\");\nconst provinces = getProvinces();\nconst districts = getDistrictsByProvince(\"34\");\nconst province = normalizeProvince(\"Istanbul\");\nconst district = normalizeDistrict(\"Kadikoy\", { province: \"34\" });\nconst batch = validateBatch([\n  { type: \"tckn\", value: \"10000000146\" },\n  { type: \"iban\", value: \"TR62 0001 0012 3456 7890 1234 56\" },\n  { type: \"phone\", value: \"0532 123 45 67\" },\n]);\nconst message = getReasonMessage(\"INVALID_CHECKSUM\", \"tr\");\n```\n\nCommonJS:\n\n```js\nconst {\n  normalizePhone,\n  validateIban,\n  validateTckn,\n} = require(\"@apideposu\u002Ftr-validation\");\n\nconst result = normalizePhone(\"0532 123 45 67\");\n```\n\n## Example Results\n\n```ts\nnormalizePhone(\"0532 123 45 67\");\n\u002F\u002F {\n\u002F\u002F   ok: true,\n\u002F\u002F   input: \"0532 123 45 67\",\n\u002F\u002F   normalized: \"+905321234567\",\n\u002F\u002F   reasons: [],\n\u002F\u002F   mode: \"number_plan_parse\",\n\u002F\u002F   localOnly: true,\n\u002F\u002F   officialVerification: false,\n\u002F\u002F   registryLookup: false,\n\u002F\u002F   e164: \"+905321234567\",\n\u002F\u002F   national: \"0532 123 45 67\",\n\u002F\u002F   extension: null,\n\u002F\u002F   country: \"TR\",\n\u002F\u002F   type: \"mobile\",\n\u002F\u002F   possibleOriginalOperator: \"Turkcell\",\n\u002F\u002F   operatorConfidence: \"prefix_based\"\n\u002F\u002F }\n\nvalidatePlate(\"34 ABC 12\");\n\u002F\u002F {\n\u002F\u002F   ok: true,\n\u002F\u002F   input: \"34 ABC 12\",\n\u002F\u002F   normalized: \"34ABC12\",\n\u002F\u002F   reasons: [],\n\u002F\u002F   mode: \"structural_validation\",\n\u002F\u002F   localOnly: true,\n\u002F\u002F   officialVerification: false,\n\u002F\u002F   registryLookup: false,\n\u002F\u002F   province: { code: \"34\", name: \"İstanbul\" },\n\u002F\u002F   letters: \"ABC\",\n\u002F\u002F   digits: \"12\",\n\u002F\u002F   formatted: \"34 ABC 12\"\n\u002F\u002F }\n\nvalidateCreditCard(\"4111 1111 1111 1111\");\n\u002F\u002F {\n\u002F\u002F   ok: true,\n\u002F\u002F   input: \"4111 1111 1111 1111\",\n\u002F\u002F   normalized: \"4111111111111111\",\n\u002F\u002F   reasons: [],\n\u002F\u002F   mode: \"structural_validation\",\n\u002F\u002F   localOnly: true,\n\u002F\u002F   officialVerification: false,\n\u002F\u002F   registryLookup: false,\n\u002F\u002F   scheme: \"visa\",\n\u002F\u002F   bin: \"411111\",\n\u002F\u002F   last4: \"1111\"\n\u002F\u002F }\n\nnormalizeProvince(\"34\");\n\u002F\u002F {\n\u002F\u002F   ok: true,\n\u002F\u002F   input: \"34\",\n\u002F\u002F   normalized: \"istanbul\",\n\u002F\u002F   reasons: [],\n\u002F\u002F   mode: \"static_dataset\",\n\u002F\u002F   localOnly: true,\n\u002F\u002F   officialVerification: false,\n\u002F\u002F   registryLookup: false,\n\u002F\u002F   province: {\n\u002F\u002F     code: \"34\",\n\u002F\u002F     name: \"Istanbul\",\n\u002F\u002F     normalized: \"istanbul\",\n\u002F\u002F     phoneAreaCodes: [\"212\", \"216\"],\n\u002F\u002F     districtCount: 39\n\u002F\u002F   }\n\u002F\u002F }\n\nnormalizeDistrict(\"Merkez\");\n\u002F\u002F {\n\u002F\u002F   ok: false,\n\u002F\u002F   input: \"Merkez\",\n\u002F\u002F   normalized: \"merkez\",\n\u002F\u002F   reasons: [\"AMBIGUOUS_DISTRICT\"],\n\u002F\u002F   mode: \"static_dataset\",\n\u002F\u002F   localOnly: true,\n\u002F\u002F   officialVerification: false,\n\u002F\u002F   registryLookup: false,\n\u002F\u002F   district: null,\n\u002F\u002F   province: null\n\u002F\u002F }\n```\n\n## Reason Codes\n\nCommon reason codes:\n\n| Code | Meaning |\n| --- | --- |\n| `EMPTY_INPUT` | Input is empty after normalization |\n| `UNSUPPORTED_CHARACTERS` | Input contains unsupported characters |\n| `INVALID_LENGTH` | Input length does not match the expected structural length |\n| `INVALID_CHECKSUM` | Input fails a known control algorithm |\n\nTCKN-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `LEADING_ZERO` | First digit is `0` |\n| `REPEATED_DIGITS` | All digits are the same |\n\nVKN-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `REPEATED_DIGITS` | All digits are the same |\n\nIBAN-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `NON_TR_IBAN` | IBAN does not start with `TR` |\n\nPhone-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `INVALID_PHONE` | Input cannot be parsed as a valid phone number |\n| `NON_TR_PHONE` | Input is valid as a phone number but not a Turkish one |\n\nLocation-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `PROVINCE_NOT_FOUND` | Province match could not be resolved |\n| `DISTRICT_NOT_FOUND` | District match could not be resolved |\n| `AMBIGUOUS_DISTRICT` | District name matches multiple provinces |\n\nPlate-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `INVALID_FORMAT` | Plate does not match the `\u003C2-digit code>\u003C1-3 letters>\u003C1-4 digits>` structure |\n| `INVALID_PROVINCE_CODE` | First two digits are not a recognized province code (01-81) |\n| `INVALID_LETTER_BLOCK` | Letter block contains forbidden letters (Q\u002FW\u002FX) or wrong count |\n| `INVALID_DIGIT_BLOCK` | Digit count does not match the letter block (e.g. 1 letter requires 4 digits) |\n\nCard-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `UNKNOWN_SCHEME` | Card prefix does not match any known scheme (Visa, Mastercard, Amex, Troy, Discover, JCB, Diners, UnionPay) |\n| `INVALID_LENGTH_FOR_SCHEME` | Card length does not match the detected scheme's allowed lengths |\n\nMERSIS-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `INVALID_EMBEDDED_VKN` | The first 10 digits do not form a valid VKN (fail VKN checksum) |\n\nPostal-code-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `INVALID_PROVINCE_CODE` | First two digits are not a recognized province code (01-81) |\n\nBarcode-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `UNSUPPORTED_BARCODE_TYPE` | Length does not match any supported barcode type (currently EAN-13 and EAN-8) |\n\nNumber-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `INVALID_NUMBER_FORMAT` | Input does not parse as a valid number under either locale |\n| `AMBIGUOUS_GROUPING` | Input like `1.234` could be either thousands grouping or a decimal — caller must disambiguate |\n\nCurrency-specific:\n\n| Code | Meaning |\n| --- | --- |\n| `INVALID_CURRENCY_FORMAT` | Multiple currency tokens or otherwise malformed currency input |\n| `UNKNOWN_CURRENCY` | Currency token is not in the bundled ISO 4217 \u002F symbol set |\n\n## Notes\n\n- `normalizePhone` uses `libphonenumber-js` locally.\n- `possibleOriginalOperator` is derived from number prefixes only and may be outdated because of number portability.\n- `getProvinces` and `getDistrictsByProvince` use bundled static JSON data.\n- `normalizeProvince` and `normalizeDistrict` use the bundled static dataset plus Turkish text normalization.\n- `validateIban` performs structural validation plus MOD-97 checksum for TR IBAN values only.\n\n## Out of Scope (No Official Verification)\n\nThis package never performs:\n\n- NVI \u002F e-Devlet \u002F KPSPublic \u002F KPSPublicV2 lookup\n- Person identity verification by name, surname, mother or father name, or birth year\n- ID document (TCKK \u002F old wallet) serial number verification\n- BDDK or TCMB account-status lookup\n- EGM or KGM plate registry lookup\n- MERSIS or Trade Registry corporate-status lookup\n- GIB or e-Fatura active-taxpayer lookup\n- PTT or UAVT address registry lookup\n- Live currency exchange rate lookup\n\nA successful result from this package means the input is structurally valid and passes the published checksum or control algorithm. It does not mean the corresponding person, company, account, plate, address, or product exists in any official registry.\n\nSome synthetic inputs that satisfy the published algorithm are still accepted as structurally valid (for example, a TCKN whose digits follow a crafted pattern can pass the 10th and 11th check-digit math). Confirming whether such an input belongs to a real person, company, or account requires an authoritative registry lookup, which this package never performs.\n\n## Optional Adapters\n\nPublished ecosystem packages:\n\n- `@apideposu\u002Ftr-validation-zod`\n  - npm: https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@apideposu\u002Ftr-validation-zod\n  - GitHub: https:\u002F\u002Fgithub.com\u002Fapideposu\u002Ftr-validation-zod\n  - purpose: optional Zod schemas and helper wrappers for the stable core validators\n\n## Docs\n\n- Contribution guide: [CONTRIBUTING.md](.\u002FCONTRIBUTING.md)\n- Dataset maintenance: [DATASETS.md](.\u002FDATASETS.md)\n- Ecosystem roadmap: [ECOSYSTEM_ROADMAP.md](.\u002FECOSYSTEM_ROADMAP.md)\n- Examples: [examples\u002FREADME.md](.\u002Fexamples\u002FREADME.md)\n- Release notes: [RELEASE_NOTES.md](.\u002FRELEASE_NOTES.md)\n- Roadmap: [ROADMAP.md](.\u002FROADMAP.md)\n\n## Development\n\n```bash\nnpm run datasets:check\nnpm test\nnpm run build\nnpm run smoke:runtime\nnpm run size:check\nnpm run benchmark\n```\n","`@apideposu\u002Ftr-validation` 是一个针对土耳其特定表单数据的本地验证和规范化工具包。其核心功能包括结构化验证、已知控制算法的应用以及数据规范化，支持身份证号（TCKN）、税号（VKN）、IBAN等常见格式的校验与处理。该工具包完全在用户项目本地运行，不进行任何后端调用或数据传输，确保了隐私安全。适用于需要对土耳其相关数据进行前端验证而无需联网操作的场景，如表单输入检查、数据预处理等。采用TypeScript开发，遵循MIT许可协议。","2026-06-11 04:00:50","CREATED_QUERY"]