{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "iranian-bank",
  "title": "Iranian Bank",
  "description": "Iranian card and Shaba normalization, checksum validation, and bank detection.",
  "registryDependencies": [
    "https://ui.persian-labs.ir/r/normalize-persian-digits.json"
  ],
  "files": [
    {
      "path": "registry/base/lib/iranian-bank.ts",
      "content": "import { normalizePersianDigits } from \"@/lib/normalize-persian-digits\"\n\nexport type IranianBankId =\n  | \"blubank\"\n  | \"dey\"\n  | \"eghtesad_novin\"\n  | \"gardeshgari\"\n  | \"ghavvamin\"\n  | \"hekmat\"\n  | \"iranzamin\"\n  | \"kar_afarin\"\n  | \"keshavarzi\"\n  | \"khavarmianeh\"\n  | \"maskan\"\n  | \"mehr_e_iranian\"\n  | \"meli\"\n  | \"mellat\"\n  | \"melli\"\n  | \"parsian\"\n  | \"pasargad\"\n  | \"post_bank\"\n  | \"refah\"\n  | \"resalat\"\n  | \"saderat\"\n  | \"saman\"\n  | \"sarmayeh\"\n  | \"sepah\"\n  | \"shahr\"\n  | \"sina\"\n  | \"tejarat\"\n  | \"tosee_saderat\"\n  | \"tosee_taavon\"\n\nexport interface IranianBank {\n  id: IranianBankId\n  name: string\n  cardPrefixes: string[]\n  ibanCodes: string[]\n}\n\nexport const iranianBanks: IranianBank[] = [\n  [\"sepah\", \"بانک سپه\", \"627381,589210\", \"015\"],\n  [\"melli\", \"بانک ملی ایران\", \"603799,636214\", \"017,062\"],\n  [\"blubank\", \"بلوبانک\", \"62198618,62198619\", \"056\"],\n  [\"dey\", \"بانک دی\", \"502938\", \"017\"],\n  [\"eghtesad_novin\", \"بانک اقتصادنوین\", \"627412\", \"055\"],\n  [\"gardeshgari\", \"بانک گردشگری\", \"505416\", \"064\"],\n  [\"ghavvamin\", \"بانک قوامین\", \"639599\", \"052\"],\n  [\"kar_afarin\", \"بانک کارآفرین\", \"627488,502910\", \"053\"],\n  [\"keshavarzi\", \"بانک کشاورزی\", \"603770,639217\", \"016\"],\n  [\"maskan\", \"بانک مسکن\", \"628023\", \"014\"],\n  [\"mehr_e_iranian\", \"بانک مهر ایران\", \"606373\", \"060\"],\n  [\"meli\", \"موسسه اعتباری ملل\", \"606256\", \"075\"],\n  [\"mellat\", \"بانک ملت\", \"610433,991975\", \"012\"],\n  [\"parsian\", \"بانک پارسیان\", \"622106\", \"054\"],\n  [\"pasargad\", \"بانک پاسارگاد\", \"502229,639347\", \"057\"],\n  [\"post_bank\", \"پست بانک ایران\", \"627760\", \"021\"],\n  [\"refah\", \"بانک رفاه\", \"589463\", \"013\"],\n  [\"saderat\", \"بانک صادرات\", \"603769\", \"019\"],\n  [\"saman\", \"بانک سامان\", \"621986\", \"056\"],\n  [\"sarmayeh\", \"بانک سرمایه\", \"639607\", \"058\"],\n  [\"shahr\", \"بانک شهر\", \"504706,502806\", \"061\"],\n  [\"sina\", \"بانک سینا\", \"639346\", \"059\"],\n  [\"tejarat\", \"بانک تجارت\", \"627353,585983\", \"018\"],\n  [\"hekmat\", \"بانک حکمت ایرانیان\", \"636949\", \"065\"],\n  [\"tosee_saderat\", \"بانک توسعه صادرات\", \"627648\", \"020\"],\n  [\"tosee_taavon\", \"بانک توسعه تعاون\", \"502908\", \"051\"],\n  [\"iranzamin\", \"بانک ایران زمین\", \"505785\", \"069\"],\n  [\"khavarmianeh\", \"بانک خاورمیانه\", \"588947\", \"080\"],\n  [\"resalat\", \"بانک قرض الحسنه رسالت\", \"504172\", \"060\"],\n].map(([id, name, cardPrefixes, ibanCodes]) => ({\n  id: id as IranianBankId,\n  name,\n  cardPrefixes: cardPrefixes.split(\",\"),\n  ibanCodes: ibanCodes.split(\",\"),\n}))\n\nexport function normalizeCardNumber(value: string | number | null | undefined) {\n  return normalizePersianDigits(String(value ?? \"\"))\n    .replace(/\\D/g, \"\")\n    .slice(0, 16)\n}\nexport function formatCardNumber(\n  value: string | number | null | undefined,\n  separator = \" \"\n) {\n  return (\n    normalizeCardNumber(value)\n      .match(/.{1,4}/g)\n      ?.join(separator) ?? \"\"\n  )\n}\nexport function normalizeShaba(value: string | null | undefined) {\n  return normalizePersianDigits(value ?? \"\")\n    .toUpperCase()\n    .replace(/^IR/i, \"\")\n    .replace(/\\D/g, \"\")\n    .slice(0, 24)\n}\nexport function formatShaba(value: string | null | undefined, separator = \" \") {\n  return (\n    normalizeShaba(value)\n      .match(/.{1,4}/g)\n      ?.join(separator) ?? \"\"\n  )\n}\nexport function getIranianBankByCardNumber(\n  value: string | number | null | undefined\n) {\n  const digits = normalizeCardNumber(value)\n  return iranianBanks.find((bank) =>\n    bank.cardPrefixes.some((prefix) => digits.startsWith(prefix))\n  )\n}\nexport function getIranianBankByShaba(value: string | null | undefined) {\n  const digits = normalizeShaba(value)\n  return iranianBanks.find((bank) =>\n    bank.ibanCodes.includes(digits.slice(2, 5))\n  )\n}\nexport function validateIranianCard(value: string | number | null | undefined) {\n  const digits = normalizeCardNumber(value)\n  if (digits.length !== 16 || /^0+$/.test(digits)) return false\n  const sum = digits.split(\"\").reduce((total, character, index) => {\n    let digit = Number(character)\n    if (index % 2 === 0) {\n      digit *= 2\n      if (digit > 9) digit -= 9\n    }\n    return total + digit\n  }, 0)\n  return sum % 10 === 0\n}\nexport function validateIranianShaba(value: string | null | undefined) {\n  const normalized = `IR${normalizeShaba(value)}`\n  if (!/^IR\\d{24}$/.test(normalized)) return false\n  let remainder = \"\"\n  for (const character of normalized.slice(4) + normalized.slice(0, 4)) {\n    remainder += /\\d/.test(character)\n      ? character\n      : String(character.charCodeAt(0) - 55)\n    remainder = String(Number(remainder) % 97)\n  }\n  return Number(remainder) === 1\n}\n",
      "type": "registry:lib"
    }
  ],
  "type": "registry:lib"
}