@indodev/toolkit 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/email-validator/index.cjs +10 -0
  2. package/dist/email-validator/index.cjs.map +1 -1
  3. package/dist/email-validator/index.d.cts +1 -1
  4. package/dist/email-validator/index.d.ts +1 -1
  5. package/dist/email-validator/index.js +10 -1
  6. package/dist/email-validator/index.js.map +1 -1
  7. package/dist/{parse-BmmsNlJt.d.cts → errors--47zprcf.d.cts} +41 -7
  8. package/dist/{parse-BmmsNlJt.d.ts → errors--47zprcf.d.ts} +41 -7
  9. package/dist/{email-validator-R9L5unIw.d.cts → errors-DdutHLae.d.cts} +23 -1
  10. package/dist/{email-validator-R9L5unIw.d.ts → errors-DdutHLae.d.ts} +23 -1
  11. package/dist/index.cjs +317 -38
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +7 -7
  14. package/dist/index.d.ts +7 -7
  15. package/dist/index.js +310 -39
  16. package/dist/index.js.map +1 -1
  17. package/dist/{compare-Ku_8OhuU.d.cts → mask-CToJqmrd.d.cts} +79 -1
  18. package/dist/{compare-Ku_8OhuU.d.ts → mask-CToJqmrd.d.ts} +79 -1
  19. package/dist/nik/index.cjs +177 -24
  20. package/dist/nik/index.cjs.map +1 -1
  21. package/dist/nik/index.d.cts +24 -330
  22. package/dist/nik/index.d.ts +24 -330
  23. package/dist/nik/index.js +174 -25
  24. package/dist/nik/index.js.map +1 -1
  25. package/dist/npwp/index.cjs +10 -0
  26. package/dist/npwp/index.cjs.map +1 -1
  27. package/dist/npwp/index.d.cts +23 -1
  28. package/dist/npwp/index.d.ts +23 -1
  29. package/dist/npwp/index.js +10 -1
  30. package/dist/npwp/index.js.map +1 -1
  31. package/dist/parse-B3UzEHq3.d.cts +155 -0
  32. package/dist/parse-B3UzEHq3.d.ts +155 -0
  33. package/dist/parse-DlrgrRfY.d.cts +155 -0
  34. package/dist/parse-DlrgrRfY.d.ts +155 -0
  35. package/dist/phone/index.cjs +36 -12
  36. package/dist/phone/index.cjs.map +1 -1
  37. package/dist/phone/index.d.cts +1 -1
  38. package/dist/phone/index.d.ts +1 -1
  39. package/dist/phone/index.js +36 -13
  40. package/dist/phone/index.js.map +1 -1
  41. package/dist/plate/index.cjs +57 -0
  42. package/dist/plate/index.cjs.map +1 -1
  43. package/dist/plate/index.d.cts +1 -1
  44. package/dist/plate/index.d.ts +1 -1
  45. package/dist/plate/index.js +56 -1
  46. package/dist/plate/index.js.map +1 -1
  47. package/dist/text/index.cjs +31 -8
  48. package/dist/text/index.cjs.map +1 -1
  49. package/dist/text/index.d.cts +2 -63
  50. package/dist/text/index.d.ts +2 -63
  51. package/dist/text/index.js +31 -8
  52. package/dist/text/index.js.map +1 -1
  53. package/dist/utils-D4A4ro8M.d.cts +507 -0
  54. package/dist/utils-D4A4ro8M.d.ts +507 -0
  55. package/dist/vin/index.cjs +64 -0
  56. package/dist/vin/index.cjs.map +1 -1
  57. package/dist/vin/index.d.cts +1 -1
  58. package/dist/vin/index.d.ts +1 -1
  59. package/dist/vin/index.js +63 -1
  60. package/dist/vin/index.js.map +1 -1
  61. package/package.json +1 -1
  62. package/dist/types-i5e6R0AS.d.cts +0 -39
  63. package/dist/types-i5e6R0AS.d.ts +0 -39
  64. package/dist/utils-DDVlOusI.d.cts +0 -30
  65. package/dist/utils-DDVlOusI.d.ts +0 -30
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/nik/constants.ts","../../src/nik/utils/date.ts","../../src/nik/validate.ts","../../src/nik/parse.ts","../../src/nik/format.ts","../../src/nik/utils.ts","../../src/nik/types.ts"],"names":["NIK_PATTERN"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Indonesian province codes and names\n * Based on Dukcapil Kemendagri data\n */\nexport const PROVINCES: Record<string, string> = {\n '11': 'Aceh',\n '12': 'Sumatera Utara',\n '13': 'Sumatera Barat',\n '14': 'Riau',\n '15': 'Jambi',\n '16': 'Sumatera Selatan',\n '17': 'Bengkulu',\n '18': 'Lampung',\n '19': 'Kepulauan Bangka Belitung',\n '21': 'Kepulauan Riau',\n '31': 'DKI Jakarta',\n '32': 'Jawa Barat',\n '33': 'Jawa Tengah',\n '34': 'DI Yogyakarta',\n '35': 'Jawa Timur',\n '36': 'Banten',\n '51': 'Bali',\n '52': 'Nusa Tenggara Barat',\n '53': 'Nusa Tenggara Timur',\n '61': 'Kalimantan Barat',\n '62': 'Kalimantan Tengah',\n '63': 'Kalimantan Selatan',\n '64': 'Kalimantan Timur',\n '65': 'Kalimantan Utara',\n '71': 'Sulawesi Utara',\n '72': 'Sulawesi Tengah',\n '73': 'Sulawesi Selatan',\n '74': 'Sulawesi Tenggara',\n '75': 'Gorontalo',\n '76': 'Sulawesi Barat',\n '81': 'Maluku',\n '82': 'Maluku Utara',\n '91': 'Papua',\n '92': 'Papua Barat',\n '93': 'Papua Selatan',\n '94': 'Papua Tengah',\n '95': 'Papua Pegunungan',\n '96': 'Papua Barat Daya',\n};\n\n/**\n * Regency codes for each province (simplified - only major ones)\n * In a real implementation, you'd have complete data\n */\nexport const REGENCIES: Record<string, Record<string, string>> = {\n '32': {\n '01': 'Kab. Bogor',\n '02': 'Kab. Sukabumi',\n '03': 'Kab. Cianjur',\n '71': 'Kota Bandung',\n '72': 'Kota Bekasi',\n '73': 'Kota Depok',\n },\n '31': { \n '01': 'Kota Jakarta Selatan',\n '02': 'Kota Jakarta Timur',\n '03': 'Kota Jakarta Pusat',\n '04': 'Kota Jakarta Barat',\n '05': 'Kota Jakarta Utara',\n },\n};","/**\n * Shared date parsing and validation utilities for NIK module.\n *\n * @module nik/utils/date\n * @packageDocumentation\n */\n\n/**\n * Result of parsing date components from a NIK string.\n *\n * @public\n */\nexport interface ParsedNIKDate {\n /** 2-digit year code (00-99) from NIK positions 7-8 */\n year: number;\n /** Full 4-digit year (1900-1999 or 2000-2099) */\n fullYear: number;\n /** Month (1-12) from NIK positions 9-10 */\n month: number;\n /** Actual day (1-31), decoded from encoded day */\n day: number;\n /** Gender derived from day encoding */\n gender: 'male' | 'female';\n /** Original encoded day (1-31 for male, 41-71 for female) */\n dayEncoded: number;\n}\n\n/**\n * Parses date components from a NIK string.\n *\n * Extracts year, month, and encoded day from positions 7-12 of the NIK.\n * For females, the day is encoded as (actual day + 40).\n *\n * @param nik - 16-digit NIK string\n * @returns ParsedNIKDate or null if NIK format is invalid\n *\n * @example\n * ```typescript\n * const result = parseNIKDate('3201018901310123');\n * // { year: 89, fullYear: 1989, month: 1, day: 31, gender: 'male', dayEncoded: 31 }\n * ```\n *\n * @public\n */\nexport function parseNIKDate(nik: string): ParsedNIKDate | null {\n if (nik.length !== 16) {\n return null;\n }\n\n const yearStr = nik.substring(6, 8);\n const monthStr = nik.substring(8, 10);\n const dayEncodedStr = nik.substring(10, 12);\n\n const year = parseInt(yearStr, 10);\n if (isNaN(year)) return null;\n\n const fullYear = year > 30 ? 1900 + year : 2000 + year;\n\n const month = parseInt(monthStr, 10);\n if (isNaN(month)) return null;\n\n const dayEncoded = parseInt(dayEncodedStr, 10);\n if (isNaN(dayEncoded)) return null;\n\n const gender: 'male' | 'female' = dayEncoded > 40 ? 'female' : 'male';\n const day = dayEncoded > 40 ? dayEncoded - 40 : dayEncoded;\n\n return { year, fullYear, month, day, gender, dayEncoded };\n}\n\n/**\n * Validates if year/month/day form a valid calendar date.\n *\n * Uses JavaScript's Date object to check if the date actually exists\n * (handles leap years, invalid month/day combinations).\n *\n * @param year - Full 4-digit year\n * @param month - Month (1-12)\n * @param day - Day (1-31)\n * @returns true if valid calendar date\n *\n * @example\n * ```typescript\n * validateNIKDateComponents(2024, 2, 29); // true (leap year)\n * validateNIKDateComponents(2023, 2, 29); // false\n * validateNIKDateComponents(2024, 13, 1); // false\n * ```\n *\n * @public\n */\nexport function validateNIKDateComponents(\n year: number,\n month: number,\n day: number\n): boolean {\n if (month < 1 || month > 12) return false;\n if (day < 1 || day > 31) return false;\n\n const testDate = new Date(year, month - 1, day);\n return (\n testDate.getFullYear() === year &&\n testDate.getMonth() === month - 1 &&\n testDate.getDate() === day\n );\n}\n","import { PROVINCES } from './constants';\nimport { parseNIKDate, validateNIKDateComponents } from './utils/date';\n\nconst NIK_PATTERN = /^\\d{16}$/;\n\n/**\n * Validates a NIK (Nomor Induk Kependudukan) format.\n *\n * A valid NIK must:\n * - Be exactly 16 digits\n * - Have a valid province code (positions 1-2)\n * - Have a valid date (positions 7-12)\n * - Not be in the future\n * - Not be before 1900\n *\n * For female NIKs, the day is encoded as (actual day + 40).\n * For example, a female born on the 15th would have day = 55.\n *\n * @param nik - The 16-digit NIK string to validate\n * @returns `true` if the NIK is valid, `false` otherwise\n *\n * @example\n * ```typescript\n * validateNIK('3201234567890123'); // true - valid NIK\n * validateNIK('1234'); // false - wrong length\n * validateNIK('9912345678901234'); // false - invalid province\n * ```\n *\n * @public\n */\nexport function validateNIK(nik: string): boolean {\n if (!NIK_PATTERN.test(nik)) {\n return false;\n }\n\n const provinceCode = nik.substring(0, 2);\n if (!PROVINCES[provinceCode]) {\n return false;\n }\n\n const parsed = parseNIKDate(nik);\n if (!parsed) {\n return false;\n }\n\n const { fullYear, month, day } = parsed;\n\n if (!validateNIKDateComponents(fullYear, month, day)) {\n return false;\n }\n\n const now = new Date();\n if (new Date(fullYear, month - 1, day) > now || fullYear < 1900) {\n return false;\n }\n\n return true;\n}\n","import { PROVINCES, REGENCIES } from './constants';\nimport { NIKInfo } from './types';\nimport { parseNIKDate, validateNIKDateComponents } from './utils/date';\n\nconst NIK_PATTERN = /^\\d{16}$/;\n\n/**\n * Parses a NIK and extracts all embedded information.\n *\n * Extracts province, regency, district codes, birth date, gender,\n * and serial number from a 16-digit NIK string.\n *\n * @param nik - The 16-digit NIK string to parse\n * @returns Parsed NIK information, or `null` if the NIK format is invalid\n *\n * @example\n * Parse a valid male NIK:\n * ```typescript\n * const info = parseNIK('3201018901310123');\n * console.log(info);\n * // {\n * // province: { code: '32', name: 'Jawa Barat' },\n * // regency: { code: '01', name: 'Kab. Bogor' },\n * // district: { code: '01', name: null },\n * // birthDate: Date(1989, 0, 31), // Jan 31, 1989\n * // gender: 'male',\n * // serialNumber: '0123',\n * // isValid: true\n * // }\n * ```\n *\n * @example\n * Parse a female NIK (day + 40):\n * ```typescript\n * const info = parseNIK('3201019508550123');\n * console.log(info.gender); // 'female'\n * console.log(info.birthDate); // Date(1995, 7, 15) - Aug 15, 1995\n * ```\n *\n * @example\n * Invalid NIK returns null:\n * ```typescript\n * const info = parseNIK('invalid');\n * console.log(info); // null\n * ```\n *\n * @public\n */\nexport function parseNIK(nik: string): NIKInfo | null {\n if (!NIK_PATTERN.test(nik)) {\n return null;\n }\n\n const provinceCode = nik.substring(0, 2);\n const regencyCode = nik.substring(2, 4);\n const districtCode = nik.substring(4, 6);\n const serialNumber = nik.substring(12, 16);\n\n const province = PROVINCES[provinceCode];\n if (!province) {\n return null;\n }\n\n const regencies = REGENCIES[provinceCode] || {};\n const regency = regencies[regencyCode] || 'Unknown';\n\n const parsed = parseNIKDate(nik);\n if (!parsed) {\n return null;\n }\n\n const { fullYear, month, day, gender } = parsed;\n\n if (!validateNIKDateComponents(fullYear, month, day)) {\n return null;\n }\n\n const birthDate = new Date(fullYear, month - 1, day);\n\n return {\n province: {\n code: provinceCode,\n name: province,\n },\n regency: {\n code: regencyCode,\n name: regency,\n },\n district: {\n code: districtCode,\n name: null,\n },\n birthDate,\n gender,\n serialNumber,\n isValid: true,\n };\n}\n","import { MaskOptions } from './types';\n\n/**\n * Formats a NIK with separators for better readability.\n *\n * Groups the NIK into logical segments: province, regency, district,\n * year, month, day, and serial number.\n *\n * @param nik - The 16-digit NIK string to format\n * @param separator - Character to use as separator\n * @returns Formatted NIK string, or original string if invalid format\n *\n * @example\n * Default separator (dash):\n * ```typescript\n * formatNIK('3201234567890123');\n * // '32-01-23-45-67-89-0123'\n * ```\n *\n * @example\n * Custom separator:\n * ```typescript\n * formatNIK('3201234567890123', ' ');\n * // '32 01 23 45 67 89 0123'\n * ```\n *\n * @example\n * Invalid NIK returns as-is:\n * ```typescript\n * formatNIK('1234');\n * // '1234'\n * ```\n *\n * @public\n */\nexport function formatNIK(nik: string, separator: string = '-'): string {\n if (!/^\\d{16}$/.test(nik)) {\n return nik;\n }\n\n // Format: PP-KK-DD-YY-MM-DD-XXXX\n // PP = Province (2 digits)\n // KK = Regency (2 digits)\n // DD = District (2 digits)\n // YY = Year (2 digits)\n // MM = Month (2 digits)\n // DD = Day (2 digits, +40 for female)\n // XXXX = Serial number (4 digits)\n return [\n nik.substring(0, 2), // Province\n nik.substring(2, 4), // Regency\n nik.substring(4, 6), // District\n nik.substring(6, 8), // Year\n nik.substring(8, 10), // Month\n nik.substring(10, 12), // Day\n nik.substring(12, 16), // Serial\n ].join(separator);\n}\n\n/**\n * Masks a NIK to protect privacy while keeping partial visibility.\n *\n * By default, shows the first 4 and last 4 digits, masking the middle 8.\n * Optionally formats the masked NIK with separators.\n *\n * @param nik - The 16-digit NIK string to mask\n * @param options - Masking configuration options\n * @returns Masked NIK string, or original string if invalid format\n *\n * @example\n * Default masking (first 4, last 4):\n * ```typescript\n * maskNIK('3201234567890123');\n * // '3201********0123'\n * ```\n *\n * @example\n * Custom mask character:\n * ```typescript\n * maskNIK('3201234567890123', { char: 'X' });\n * // '3201XXXXXXXX0123'\n * ```\n *\n * @example\n * With separator:\n * ```typescript\n * maskNIK('3201234567890123', { separator: '-' });\n * // '32-01-**-**-**-**-0123'\n * ```\n *\n * @example\n * Custom start and end:\n * ```typescript\n * maskNIK('3201234567890123', { start: 6, end: 4 });\n * // '320123******0123'\n * ```\n *\n * @public\n */\nexport function maskNIK(nik: string, options: MaskOptions = {}): string {\n if (!/^\\d{16}$/.test(nik)) {\n return nik;\n }\n\n const { start = 4, end = 4, char = '*', separator } = options;\n\n if (start + end >= 16) {\n return nik;\n }\n\n if (separator) {\n // Format with separator first, then apply masking\n const formatted = formatNIK(nik, separator);\n const parts = formatted.split(separator);\n\n // Calculate which parts to mask\n // Format: PP-KK-DD-YY-MM-DD-XXXX (7 parts)\n // Mask parts based on character positions\n let charCount = 0;\n const maskedParts = parts.map((part) => {\n const partStart = charCount;\n const partEnd = charCount + part.length;\n charCount += part.length;\n\n // Check if this part should be fully/partially masked\n if (partEnd <= start) {\n // Fully visible (before start)\n return part;\n } else if (partStart >= 16 - end) {\n // Fully visible (after end)\n return part;\n } else if (partStart >= start && partEnd <= 16 - end) {\n // Fully masked\n return char.repeat(part.length);\n } else {\n // Partially masked\n return part\n .split('')\n .map((ch, idx) => {\n const pos = partStart + idx;\n if (pos < start || pos >= 16 - end) {\n return ch;\n }\n return char;\n })\n .join('');\n }\n });\n\n return maskedParts.join(separator);\n }\n\n // Without separator: simple masking\n const startPart = nik.substring(0, start);\n const endPart = nik.substring(16 - end);\n const maskLength = 16 - start - end;\n return startPart + char.repeat(maskLength) + endPart;\n}","import { parseNIK } from './parse';\n\n/**\n * Calculates the age of a person based on their NIK.\n *\n * @param nik - The 16-digit NIK string\n * @param referenceDate - The date to calculate age from (default: current date)\n * @returns The age in years, or null if the NIK is invalid or birth date cannot be parsed\n *\n * @example\n * ```typescript\n * getAge('3201018901310123'); // 35 (as of 2024)\n * ```\n */\nexport function getAge(\n nik: string,\n referenceDate: Date = new Date()\n): number | null {\n const info = parseNIK(nik);\n if (!info || !info.birthDate) {\n return null;\n }\n\n const birthDate = info.birthDate;\n let age = referenceDate.getFullYear() - birthDate.getFullYear();\n const m = referenceDate.getMonth() - birthDate.getMonth();\n\n if (m < 0 || (m === 0 && referenceDate.getDate() < birthDate.getDate())) {\n age--;\n }\n\n return age;\n}\n\n/**\n * Formats the birth date from a NIK into a human-readable string.\n *\n * @param nik - The 16-digit NIK string\n * @param locale - The locale to use for formatting (default: 'id-ID')\n * @returns Formatted birth date string, or null if invalid\n *\n * @example\n * ```typescript\n * formatBirthDate('3201018901310123'); // '31 Januari 1989'\n * ```\n */\nexport function formatBirthDate(\n nik: string,\n options: Intl.DateTimeFormatOptions = {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n },\n locale: string = 'id-ID'\n): string | null {\n const info = parseNIK(nik);\n if (!info || !info.birthDate) {\n return null;\n }\n\n return new Intl.DateTimeFormat(locale, options).format(info.birthDate);\n}\n\n/**\n * Checks if a NIK matches a specific gender.\n *\n * @param nik - The 16-digit NIK string\n * @param gender - The gender to check ('male' | 'female')\n * @returns True if the NIK matches the gender, false otherwise\n */\nexport function isValidForGender(\n nik: string,\n gender: 'male' | 'female'\n): boolean {\n const info = parseNIK(nik);\n if (!info) {\n return false;\n }\n return info.gender === gender;\n}\n\n/**\n * Checks if a NIK matches a specific birth date.\n *\n * @param nik - The 16-digit NIK string\n * @param birthDate - The birth date to check\n * @returns True if the NIK matches the birth date, false otherwise\n */\nexport function isValidForBirthDate(nik: string, birthDate: Date): boolean {\n const info = parseNIK(nik);\n if (!info || !info.birthDate) {\n return false;\n }\n\n return (\n info.birthDate.getFullYear() === birthDate.getFullYear() &&\n info.birthDate.getMonth() === birthDate.getMonth() &&\n info.birthDate.getDate() === birthDate.getDate()\n );\n}\n","/**\n * Information extracted from a valid NIK.\n *\n * Contains parsed data including location codes, birth date, gender,\n * and serial number from a 16-digit NIK string.\n *\n * @public\n */\nexport interface NIKInfo {\n /**\n * Province information extracted from positions 1-2 of the NIK.\n *\n * @example\n * ```typescript\n * { code: '32', name: 'Jawa Barat' }\n * ```\n */\n province: {\n /** Two-digit province code (e.g., '32') */\n code: string;\n /** Full province name (e.g., 'Jawa Barat') */\n name: string;\n };\n\n /**\n * Regency (Kabupaten/Kota) information extracted from positions 3-4 of the NIK.\n *\n * @example\n * ```typescript\n * { code: '01', name: 'Kab. Bogor' }\n * ```\n */\n regency: {\n /** Two-digit regency code (e.g., '01') */\n code: string;\n /** Full regency name (e.g., 'Kab. Bogor') */\n name: string;\n };\n\n /**\n * District (Kecamatan) information extracted from positions 5-6 of the NIK.\n * May be `null` if district data is not available.\n *\n * @example\n * ```typescript\n * { code: '23', name: 'Ciawi' }\n * ```\n */\n district: {\n /** Two-digit district code (e.g., '23') */\n code: string;\n /** Full district name, or `null` if data unavailable */\n name: string | null;\n };\n\n /**\n * Birth date extracted from positions 7-12 of the NIK.\n * For females, the day is encoded as (actual day + 40).\n * Returns `null` if the date is invalid.\n *\n * @example\n * ```typescript\n * new Date(1989, 0, 31) // January 31, 1989\n * ```\n */\n birthDate: Date | null;\n\n /**\n * Gender derived from the day encoding in the NIK.\n * - 'male': day is 1-31\n * - 'female': day is 41-71 (actual day + 40)\n * - `null`: if unable to determine\n */\n gender: 'male' | 'female' | null;\n\n /**\n * Serial number from positions 13-16 of the NIK.\n * Uniquely identifies individuals with the same location and birth date.\n * Returns `null` if unable to extract.\n *\n * @example\n * ```typescript\n * '0123'\n * ```\n */\n serialNumber: string | null;\n\n /**\n * Whether the NIK passed validation checks.\n * If `false`, other fields may be `null` or contain partial data.\n */\n isValid: boolean;\n}\n\n/**\n * Options for masking a NIK to protect privacy.\n *\n * Controls how many characters to show at the start and end,\n * what character to use for masking, and optional separators.\n *\n * @example\n * ```typescript\n * // Default: shows first 4 and last 4 digits\n * { start: 4, end: 4, char: '*' }\n * // Result: '3201********0123'\n *\n * // With separator\n * { start: 4, end: 4, char: '*', separator: '-' }\n * // Result: '3201-****-****-0123'\n * ```\n *\n * @public\n */\nexport interface MaskOptions {\n /**\n * Number of characters to show at the start.\n *\n * @defaultValue 4\n */\n start?: number;\n\n /**\n * Number of characters to show at the end.\n *\n * @defaultValue 4\n */\n end?: number;\n\n /**\n * Character to use for masking hidden digits.\n *\n * @defaultValue '*'\n */\n char?: string;\n\n /**\n * Optional separator to add between groups of digits.\n * If provided, the NIK will be formatted with separators.\n *\n * @defaultValue undefined (no separator)\n *\n * @example\n * ```typescript\n * '-' // Results in format: '3201-****-****-0123'\n * ' ' // Results in format: '3201 **** **** 0123'\n * ```\n */\n separator?: string;\n}\n\n/**\n * Error thrown when an invalid NIK is provided to a function.\n * Extends native Error with a `code` property for programmatic error handling.\n *\n * @example\n * ```typescript\n * try {\n * requireNIK('invalid');\n * } catch (error) {\n * if (error instanceof InvalidNIKError) {\n * console.log(error.code); // 'INVALID_NIK'\n * }\n * }\n * ```\n *\n * @public\n */\nexport class InvalidNIKError extends Error {\n /** Error code for programmatic identification */\n readonly code = 'INVALID_NIK' as const;\n\n constructor(message: string = 'Invalid NIK provided') {\n super(message);\n this.name = 'InvalidNIKError';\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/nik/constants.ts","../../src/nik/utils/date.ts","../../src/nik/validate.ts","../../src/nik/parse.ts","../../src/nik/format.ts","../../src/nik/clean.ts","../../src/nik/validate-detailed.ts","../../src/nik/utils.ts","../../src/nik/types.ts"],"names":["NIK_PATTERN"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Indonesian province codes and names\n * Based on Dukcapil Kemendagri data\n */\nexport const PROVINCES: Record<string, string> = {\n '11': 'Aceh',\n '12': 'Sumatera Utara',\n '13': 'Sumatera Barat',\n '14': 'Riau',\n '15': 'Jambi',\n '16': 'Sumatera Selatan',\n '17': 'Bengkulu',\n '18': 'Lampung',\n '19': 'Kepulauan Bangka Belitung',\n '21': 'Kepulauan Riau',\n '31': 'DKI Jakarta',\n '32': 'Jawa Barat',\n '33': 'Jawa Tengah',\n '34': 'DI Yogyakarta',\n '35': 'Jawa Timur',\n '36': 'Banten',\n '51': 'Bali',\n '52': 'Nusa Tenggara Barat',\n '53': 'Nusa Tenggara Timur',\n '61': 'Kalimantan Barat',\n '62': 'Kalimantan Tengah',\n '63': 'Kalimantan Selatan',\n '64': 'Kalimantan Timur',\n '65': 'Kalimantan Utara',\n '71': 'Sulawesi Utara',\n '72': 'Sulawesi Tengah',\n '73': 'Sulawesi Selatan',\n '74': 'Sulawesi Tenggara',\n '75': 'Gorontalo',\n '76': 'Sulawesi Barat',\n '81': 'Maluku',\n '82': 'Maluku Utara',\n '91': 'Papua',\n '92': 'Papua Barat',\n '93': 'Papua Selatan',\n '94': 'Papua Tengah',\n '95': 'Papua Pegunungan',\n '96': 'Papua Barat Daya',\n};\n\n/**\n * Regency codes for each province (simplified - only major ones)\n * In a real implementation, you'd have complete data\n */\nexport const REGENCIES: Record<string, Record<string, string>> = {\n '32': {\n '01': 'Kab. Bogor',\n '02': 'Kab. Sukabumi',\n '03': 'Kab. Cianjur',\n '71': 'Kota Bandung',\n '72': 'Kota Bekasi',\n '73': 'Kota Depok',\n },\n '31': { \n '01': 'Kota Jakarta Selatan',\n '02': 'Kota Jakarta Timur',\n '03': 'Kota Jakarta Pusat',\n '04': 'Kota Jakarta Barat',\n '05': 'Kota Jakarta Utara',\n },\n};","/**\n * Shared date parsing and validation utilities for NIK module.\n *\n * @module nik/utils/date\n * @packageDocumentation\n */\n\n/**\n * Result of parsing date components from a NIK string.\n *\n * @public\n */\nexport interface ParsedNIKDate {\n /** 2-digit year code (00-99) from NIK positions 7-8 */\n year: number;\n /** Full 4-digit year (1900-1999 or 2000-2099) */\n fullYear: number;\n /** Month (1-12) from NIK positions 9-10 */\n month: number;\n /** Actual day (1-31), decoded from encoded day */\n day: number;\n /** Gender derived from day encoding */\n gender: 'male' | 'female';\n /** Original encoded day (1-31 for male, 41-71 for female) */\n dayEncoded: number;\n}\n\n/**\n * Parses date components from a NIK string.\n *\n * Extracts year, month, and encoded day from positions 7-12 of the NIK.\n * For females, the day is encoded as (actual day + 40).\n *\n * @param nik - 16-digit NIK string\n * @returns ParsedNIKDate or null if NIK format is invalid\n *\n * @example\n * ```typescript\n * const result = parseNIKDate('3201018901310123');\n * // { year: 89, fullYear: 1989, month: 1, day: 31, gender: 'male', dayEncoded: 31 }\n * ```\n *\n * @public\n */\nexport function parseNIKDate(nik: string): ParsedNIKDate | null {\n if (nik.length !== 16) {\n return null;\n }\n\n const yearStr = nik.substring(6, 8);\n const monthStr = nik.substring(8, 10);\n const dayEncodedStr = nik.substring(10, 12);\n\n const year = parseInt(yearStr, 10);\n if (isNaN(year)) return null;\n\n const fullYear = year > 30 ? 1900 + year : 2000 + year;\n\n const month = parseInt(monthStr, 10);\n if (isNaN(month)) return null;\n\n const dayEncoded = parseInt(dayEncodedStr, 10);\n if (isNaN(dayEncoded)) return null;\n\n const gender: 'male' | 'female' = dayEncoded > 40 ? 'female' : 'male';\n const day = dayEncoded > 40 ? dayEncoded - 40 : dayEncoded;\n\n return { year, fullYear, month, day, gender, dayEncoded };\n}\n\n/**\n * Validates if year/month/day form a valid calendar date.\n *\n * Uses JavaScript's Date object to check if the date actually exists\n * (handles leap years, invalid month/day combinations).\n *\n * @param year - Full 4-digit year\n * @param month - Month (1-12)\n * @param day - Day (1-31)\n * @returns true if valid calendar date\n *\n * @example\n * ```typescript\n * validateNIKDateComponents(2024, 2, 29); // true (leap year)\n * validateNIKDateComponents(2023, 2, 29); // false\n * validateNIKDateComponents(2024, 13, 1); // false\n * ```\n *\n * @public\n */\nexport function validateNIKDateComponents(\n year: number,\n month: number,\n day: number\n): boolean {\n if (month < 1 || month > 12) return false;\n if (day < 1 || day > 31) return false;\n\n const testDate = new Date(year, month - 1, day);\n return (\n testDate.getFullYear() === year &&\n testDate.getMonth() === month - 1 &&\n testDate.getDate() === day\n );\n}\n","import { PROVINCES } from './constants';\nimport { parseNIKDate, validateNIKDateComponents } from './utils/date';\n\nconst NIK_PATTERN = /^\\d{16}$/;\n\n/**\n * Validates a NIK (Nomor Induk Kependudukan) format.\n *\n * A valid NIK must:\n * - Be exactly 16 digits\n * - Have a valid province code (positions 1-2)\n * - Have a valid date (positions 7-12)\n * - Not be in the future\n * - Not be before 1900\n *\n * For female NIKs, the day is encoded as (actual day + 40).\n * For example, a female born on the 15th would have day = 55.\n *\n * @param nik - The 16-digit NIK string to validate\n * @returns `true` if the NIK is valid, `false` otherwise\n *\n * @example\n * ```typescript\n * validateNIK('3201234567890123'); // true - valid NIK\n * validateNIK('1234'); // false - wrong length\n * validateNIK('9912345678901234'); // false - invalid province\n * ```\n *\n * @public\n */\nexport function validateNIK(nik: string): boolean {\n if (!NIK_PATTERN.test(nik)) {\n return false;\n }\n\n const provinceCode = nik.substring(0, 2);\n if (!PROVINCES[provinceCode]) {\n return false;\n }\n\n const parsed = parseNIKDate(nik);\n if (!parsed) {\n return false;\n }\n\n const { fullYear, month, day } = parsed;\n\n if (!validateNIKDateComponents(fullYear, month, day)) {\n return false;\n }\n\n const now = new Date();\n if (new Date(fullYear, month - 1, day) > now || fullYear < 1900) {\n return false;\n }\n\n return true;\n}\n","import { PROVINCES, REGENCIES } from './constants';\nimport { NIKInfo } from './types';\nimport { parseNIKDate, validateNIKDateComponents } from './utils/date';\n\nconst NIK_PATTERN = /^\\d{16}$/;\n\n/**\n * Parses a NIK and extracts all embedded information.\n *\n * Extracts province, regency, district codes, birth date, gender,\n * and serial number from a 16-digit NIK string.\n *\n * @param nik - The 16-digit NIK string to parse\n * @returns Parsed NIK information, or `null` if the NIK format is invalid\n *\n * @example\n * Parse a valid male NIK:\n * ```typescript\n * const info = parseNIK('3201018901310123');\n * console.log(info);\n * // {\n * // province: { code: '32', name: 'Jawa Barat' },\n * // regency: { code: '01', name: 'Kab. Bogor' },\n * // district: { code: '01', name: null },\n * // birthDate: Date(1989, 0, 31), // Jan 31, 1989\n * // gender: 'male',\n * // serialNumber: '0123',\n * // isValid: true\n * // }\n * ```\n *\n * @example\n * Parse a female NIK (day + 40):\n * ```typescript\n * const info = parseNIK('3201019508550123');\n * console.log(info.gender); // 'female'\n * console.log(info.birthDate); // Date(1995, 7, 15) - Aug 15, 1995\n * ```\n *\n * @example\n * Invalid NIK returns null:\n * ```typescript\n * const info = parseNIK('invalid');\n * console.log(info); // null\n * ```\n *\n * @public\n */\nexport function parseNIK(nik: string): NIKInfo | null {\n if (!NIK_PATTERN.test(nik)) {\n return null;\n }\n\n const provinceCode = nik.substring(0, 2);\n const regencyCode = nik.substring(2, 4);\n const districtCode = nik.substring(4, 6);\n const serialNumber = nik.substring(12, 16);\n\n const province = PROVINCES[provinceCode];\n if (!province) {\n return null;\n }\n\n const regencies = REGENCIES[provinceCode] || {};\n const regency = regencies[regencyCode] || 'Unknown';\n\n const parsed = parseNIKDate(nik);\n if (!parsed) {\n return null;\n }\n\n const { fullYear, month, day, gender } = parsed;\n\n if (!validateNIKDateComponents(fullYear, month, day)) {\n return null;\n }\n\n const birthDate = new Date(fullYear, month - 1, day);\n\n return {\n province: {\n code: provinceCode,\n name: province,\n },\n regency: {\n code: regencyCode,\n name: regency,\n },\n district: {\n code: districtCode,\n name: null,\n },\n birthDate,\n gender,\n serialNumber,\n isValid: true,\n };\n}\n","import { MaskOptions } from './types';\n\n/**\n * Formats a NIK with separators for better readability.\n *\n * Groups the NIK into logical segments: province, regency, district,\n * year, month, day, and serial number.\n *\n * @param nik - The 16-digit NIK string to format\n * @param separator - Character to use as separator\n * @returns Formatted NIK string, or original string if invalid format\n *\n * @example\n * Default separator (dash):\n * ```typescript\n * formatNIK('3201234567890123');\n * // '32-01-23-45-67-89-0123'\n * ```\n *\n * @example\n * Custom separator:\n * ```typescript\n * formatNIK('3201234567890123', ' ');\n * // '32 01 23 45 67 89 0123'\n * ```\n *\n * @example\n * Invalid NIK returns as-is:\n * ```typescript\n * formatNIK('1234');\n * // '1234'\n * ```\n *\n * @public\n */\nexport function formatNIK(nik: string, separator: string = '-'): string {\n if (!/^\\d{16}$/.test(nik)) {\n return nik;\n }\n\n // Format: PP-KK-DD-YY-MM-DD-XXXX\n // PP = Province (2 digits)\n // KK = Regency (2 digits)\n // DD = District (2 digits)\n // YY = Year (2 digits)\n // MM = Month (2 digits)\n // DD = Day (2 digits, +40 for female)\n // XXXX = Serial number (4 digits)\n return [\n nik.substring(0, 2), // Province\n nik.substring(2, 4), // Regency\n nik.substring(4, 6), // District\n nik.substring(6, 8), // Year\n nik.substring(8, 10), // Month\n nik.substring(10, 12), // Day\n nik.substring(12, 16), // Serial\n ].join(separator);\n}\n\n/**\n * Masks a NIK to protect privacy while keeping partial visibility.\n *\n * By default, shows the first 4 and last 4 digits, masking the middle 8.\n * Optionally formats the masked NIK with separators.\n *\n * @param nik - The 16-digit NIK string to mask\n * @param options - Masking configuration options\n * @returns Masked NIK string, or original string if invalid format\n *\n * @example\n * Default masking (first 4, last 4):\n * ```typescript\n * maskNIK('3201234567890123');\n * // '3201********0123'\n * ```\n *\n * @example\n * Custom mask character:\n * ```typescript\n * maskNIK('3201234567890123', { maskChar: 'X' });\n * // '3201XXXXXXXX0123'\n * ```\n *\n * @example\n * With separator:\n * ```typescript\n * maskNIK('3201234567890123', { separator: '-' });\n * // '32-01-**-**-**-**-0123'\n * ```\n *\n * @example\n * Custom visibleStart and visibleEnd:\n * ```typescript\n * maskNIK('3201234567890123', { visibleStart: 6, visibleEnd: 4 });\n * // '320123******0123'\n * ```\n *\n * @public\n */\nexport function maskNIK(nik: string, options: MaskOptions = {}): string {\n if (!/^\\d{16}$/.test(nik)) {\n return nik;\n }\n\n const { visibleStart, visibleEnd, maskChar, separator, start, end, char } =\n options;\n\n const hasLegacyOptions =\n start !== undefined || end !== undefined || char !== undefined;\n\n if (hasLegacyOptions) {\n console.warn(\n '[DEPRECATED] Mask options start/end/char are deprecated. ' +\n 'Use visibleStart/visibleEnd/maskChar instead. ' +\n 'These old names will be removed in v1.0.0.'\n );\n }\n\n const effectiveStart =\n visibleStart !== undefined ? visibleStart : start !== undefined ? start : 4;\n const effectiveEnd =\n visibleEnd !== undefined ? visibleEnd : end !== undefined ? end : 4;\n const effectiveChar =\n maskChar !== undefined ? maskChar : char !== undefined ? char : '*';\n\n if (effectiveStart + effectiveEnd >= 16) {\n return nik;\n }\n\n if (separator) {\n const formatted = formatNIK(nik, separator);\n const parts = formatted.split(separator);\n\n let charCount = 0;\n const maskedParts = parts.map((part) => {\n const partStart = charCount;\n const partEnd = charCount + part.length;\n charCount += part.length;\n\n if (partEnd <= effectiveStart) {\n return part;\n } else if (partStart >= 16 - effectiveEnd) {\n return part;\n } else if (partStart >= effectiveStart && partEnd <= 16 - effectiveEnd) {\n return effectiveChar.repeat(part.length);\n } else {\n return part\n .split('')\n .map((ch, idx) => {\n const pos = partStart + idx;\n if (pos < effectiveStart || pos >= 16 - effectiveEnd) {\n return ch;\n }\n return effectiveChar;\n })\n .join('');\n }\n });\n\n return maskedParts.join(separator);\n }\n\n const startPart = nik.substring(0, effectiveStart);\n const endPart = nik.substring(16 - effectiveEnd);\n const maskLength = 16 - effectiveStart - effectiveEnd;\n return startPart + effectiveChar.repeat(maskLength) + endPart;\n}\n","/**\n * Cleans a NIK by removing all non-digit characters.\n *\n * Accepts NIK in any format (with separators like `.`, `-`, ` `) and\n * returns a clean 16-digit string. Returns empty string for invalid inputs.\n *\n * @param nik - NIK in any format\n * @returns Clean 16-digit NIK or empty string if invalid\n *\n * @example\n * ```typescript\n * cleanNIK('32-01-01-89-01-31-0123'); // '3201018901310123'\n * cleanNIK('3201.8901.3101.23'); // '32018901310123' (only 14 digits - invalid)\n * cleanNIK('invalid'); // ''\n * ```\n *\n * @public\n */\nexport function cleanNIK(nik: string): string {\n if (typeof nik !== 'string') {\n return '';\n }\n\n const cleaned = nik.replace(/\\D/g, '');\n\n if (cleaned.length !== 16) {\n return '';\n }\n\n return cleaned;\n}\n","import { PROVINCES } from './constants';\nimport { NIKValidationResult, NIKValidationError, NIKErrorCode } from './types';\nimport { cleanNIK } from './clean';\nimport { parseNIK } from './parse';\n\nfunction createError(code: NIKErrorCode, message: string): NIKValidationError {\n return { code, message };\n}\n\n/**\n * Validates a NIK and returns detailed error information.\n *\n * Unlike `validateNIK` which returns a boolean, this function provides\n * structured error reporting for form validation use cases.\n *\n * @param nik - The NIK string to validate (accepts any format with separators)\n * @returns Detailed validation result with errors array\n *\n * @example\n * ```typescript\n * const result = validateNIKDetailed('3201018901310123');\n * if (!result.isValid) {\n * result.errors.forEach(err => {\n * console.log(`${err.code}: ${err.message}`);\n * });\n * }\n * ```\n *\n * @public\n */\nexport function validateNIKDetailed(nik: string): NIKValidationResult {\n const cleaned = cleanNIK(nik);\n\n if (cleaned === '') {\n return {\n isValid: false,\n errors: [createError('INVALID_FORMAT', 'NIK must be exactly 16 digits')],\n nik: null,\n };\n }\n\n const provinceCode = cleaned.substring(0, 2);\n if (!PROVINCES[provinceCode]) {\n return {\n isValid: false,\n errors: [\n createError(\n 'INVALID_PROVINCE',\n `Province code ${provinceCode} not found`\n ),\n ],\n nik: null,\n };\n }\n\n const info = parseNIK(cleaned);\n if (!info) {\n return {\n isValid: false,\n errors: [createError('INVALID_DATE', 'Invalid date components')],\n nik: null,\n };\n }\n\n const birthDate = info.birthDate;\n if (!birthDate) {\n return {\n isValid: false,\n errors: [createError('INVALID_DATE', 'Invalid birth date')],\n nik: null,\n };\n }\n\n const now = new Date();\n if (birthDate > now) {\n return {\n isValid: false,\n errors: [\n createError('FUTURE_DATE', 'Birth date cannot be in the future'),\n ],\n nik: null,\n };\n }\n\n return {\n isValid: true,\n errors: [],\n nik: cleaned,\n };\n}\n","import { parseNIK } from './parse';\nimport { cleanNIK } from './clean';\nimport { Age, GetAgeOptions } from './types';\n\n/**\n * Calculates the age of a person based on their NIK.\n *\n * Returns detailed age breakdown with years, months, and days, or a\n * formatted Indonesian string. This is consistent with `datetime.getAge()`.\n *\n * @param nik - The 16-digit NIK string\n * @param options - Options object with `referenceDate` and `asString`\n * @returns Age object `{ years, months, days }`, formatted string, or null if invalid\n *\n * @example\n * ```typescript\n * // Returns object by default\n * getAge('3201018901310123');\n * // { years: 35, months: 2, days: 6 } (as of 2026-04-06)\n *\n * // Returns formatted string\n * getAge('3201018901310123', { asString: true });\n * // '35 Tahun 2 Bulan 6 Hari'\n *\n * // Custom reference date\n * getAge('3201018901310123', { referenceDate: new Date('2025-01-01') });\n * // { years: 35, months: 11, days: 1 }\n * ```\n *\n * @public\n */\nexport function getAge(\n nik: string,\n options: GetAgeOptions = {}\n): Age | string | null {\n const { referenceDate = new Date(), asString = false } = options;\n\n const info = parseNIK(nik);\n if (!info || !info.birthDate) {\n return null;\n }\n\n const birthDate = info.birthDate;\n let years = referenceDate.getFullYear() - birthDate.getFullYear();\n let months = referenceDate.getMonth() - birthDate.getMonth();\n let days = referenceDate.getDate() - birthDate.getDate();\n\n if (days < 0) {\n months--;\n const prevMonth = new Date(\n referenceDate.getFullYear(),\n referenceDate.getMonth(),\n 0\n );\n days += prevMonth.getDate();\n }\n\n if (months < 0) {\n years--;\n months += 12;\n }\n\n if (asString) {\n const parts: string[] = [];\n if (years > 0) parts.push(`${years} Tahun`);\n if (months > 0) parts.push(`${months} Bulan`);\n if (days > 0 || parts.length === 0) parts.push(`${days} Hari`);\n return parts.join(' ');\n }\n\n return { years, months, days };\n}\n\n/**\n * Compares two NIKs to check if they belong to the same person.\n *\n * Two NIKs are considered the same person if they have identical:\n * - Province code (positions 1-2)\n * - Regency code (positions 3-4)\n * - District code (positions 5-6)\n * - Birth date (year + month + day)\n * - Gender (derived from day encoding)\n * - Serial number (positions 13-16)\n *\n * @param nik1 - First NIK (accepts any format)\n * @param nik2 - Second NIK (accepts any format)\n * @returns True if both NIKs belong to the same person, false otherwise\n *\n * @example\n * ```typescript\n * // Same person, same format\n * compareNIK('3201018901310123', '3201018901310123'); // true\n *\n * // Same person, different format\n * compareNIK('3201018901310123', '3201-01-89-01-31-0123'); // true\n *\n * // Different serial number\n * compareNIK('3201018901310123', '3201018901310124'); // false\n *\n * // Invalid NIK\n * compareNIK('invalid', '3201018901310123'); // false\n * ```\n *\n * @public\n */\nexport function compareNIK(nik1: string, nik2: string): boolean {\n const cleaned1 = cleanNIK(nik1);\n const cleaned2 = cleanNIK(nik2);\n\n if (\n cleaned1 === '' ||\n cleaned2 === '' ||\n cleaned1.length !== 16 ||\n cleaned2.length !== 16\n ) {\n return false;\n }\n\n if (cleaned1 === cleaned2) {\n return true;\n }\n\n const pos1_6_1 = cleaned1.substring(0, 6);\n const pos1_6_2 = cleaned2.substring(0, 6);\n\n if (pos1_6_1 !== pos1_6_2) {\n return false;\n }\n\n const birthDate1 = cleaned1.substring(6, 12);\n const birthDate2 = cleaned2.substring(6, 12);\n\n if (birthDate1 !== birthDate2) {\n return false;\n }\n\n const serial1 = cleaned1.substring(12, 16);\n const serial2 = cleaned2.substring(12, 16);\n\n return serial1 === serial2;\n}\n\n/**\n * Checks if a person is an adult based on their NIK.\n *\n * By default, uses 17 years as the threshold (Indonesian KTP eligibility age).\n * Indonesian law allows KTP at age 17, or upon marriage, or already married.\n *\n * @param nik - The 16-digit NIK string\n * @param minAge - Minimum age threshold (default: 17)\n * @returns True if the person is at least minAge years old, false otherwise\n *\n * @example\n * ```typescript\n * // Born 1995-01-01, reference 2026-04-06 (age 31)\n * isAdult('3201950101950123'); // true (31 >= 17)\n * isAdult('3201950101950123', 21); // true (31 >= 21)\n *\n * // Born 2010-01-01, reference 2026-04-06 (age 16)\n * isAdult('3210010101950123'); // false (16 < 17)\n * isAdult('3210010101950123', 16); // true (16 >= 16)\n *\n * // Invalid NIK\n * isAdult('invalid'); // false\n * ```\n *\n * @public\n */\nexport function isAdult(nik: string, minAge: number = 17): boolean {\n const age = getAge(nik);\n if (age === null) {\n return false;\n }\n\n if (typeof age === 'string') {\n const yearsMatch = age.match(/^(\\d+)/);\n if (yearsMatch) {\n return parseInt(yearsMatch[1], 10) >= minAge;\n }\n return false;\n }\n\n return age.years >= minAge;\n}\n\n/**\n * Formats the birth date from a NIK into a human-readable string.\n *\n * @param nik - The 16-digit NIK string\n * @param locale - The locale to use for formatting (default: 'id-ID')\n * @returns Formatted birth date string, or null if invalid\n *\n * @example\n * ```typescript\n * formatBirthDate('3201018901310123'); // '31 Januari 1989'\n * ```\n */\nexport function formatBirthDate(nik: string): string | null {\n const info = parseNIK(nik);\n if (!info || !info.birthDate) {\n return null;\n }\n\n const day = info.birthDate.getDate();\n const month = info.birthDate.getMonth();\n const year = info.birthDate.getFullYear();\n\n const monthNames = [\n 'Januari',\n 'Februari',\n 'Maret',\n 'April',\n 'Mei',\n 'Juni',\n 'Juli',\n 'Agustus',\n 'September',\n 'Oktober',\n 'November',\n 'Desember',\n ];\n\n return `${day} ${monthNames[month]} ${year}`;\n}\n\n/**\n * Checks if a NIK matches a specific gender.\n *\n * @param nik - The 16-digit NIK string\n * @param gender - The gender to check ('male' | 'female')\n * @returns True if the NIK matches the gender, false otherwise\n */\nexport function isValidForGender(\n nik: string,\n gender: 'male' | 'female'\n): boolean {\n const info = parseNIK(nik);\n if (!info) {\n return false;\n }\n return info.gender === gender;\n}\n\n/**\n * Checks if a NIK matches a specific birth date.\n *\n * @param nik - The 16-digit NIK string\n * @param birthDate - The birth date to check\n * @returns True if the NIK matches the birth date, false otherwise\n */\nexport function isValidForBirthDate(nik: string, birthDate: Date): boolean {\n const info = parseNIK(nik);\n if (!info || !info.birthDate) {\n return false;\n }\n\n return (\n info.birthDate.getFullYear() === birthDate.getFullYear() &&\n info.birthDate.getMonth() === birthDate.getMonth() &&\n info.birthDate.getDate() === birthDate.getDate()\n );\n}\n","/**\n * Information extracted from a valid NIK.\n *\n * Contains parsed data including location codes, birth date, gender,\n * and serial number from a 16-digit NIK string.\n *\n * @public\n */\nexport interface NIKInfo {\n /**\n * Province information extracted from positions 1-2 of the NIK.\n *\n * @example\n * ```typescript\n * { code: '32', name: 'Jawa Barat' }\n * ```\n */\n province: {\n /** Two-digit province code (e.g., '32') */\n code: string;\n /** Full province name (e.g., 'Jawa Barat') */\n name: string;\n };\n\n /**\n * Regency (Kabupaten/Kota) information extracted from positions 3-4 of the NIK.\n *\n * @example\n * ```typescript\n * { code: '01', name: 'Kab. Bogor' }\n * ```\n */\n regency: {\n /** Two-digit regency code (e.g., '01') */\n code: string;\n /** Full regency name (e.g., 'Kab. Bogor') */\n name: string;\n };\n\n /**\n * District (Kecamatan) information extracted from positions 5-6 of the NIK.\n * May be `null` if district data is not available.\n *\n * @example\n * ```typescript\n * { code: '23', name: 'Ciawi' }\n * ```\n */\n district: {\n /** Two-digit district code (e.g., '23') */\n code: string;\n /** Full district name, or `null` if data unavailable */\n name: string | null;\n };\n\n /**\n * Birth date extracted from positions 7-12 of the NIK.\n * For females, the day is encoded as (actual day + 40).\n * Returns `null` if the date is invalid.\n *\n * @example\n * ```typescript\n * new Date(1989, 0, 31) // January 31, 1989\n * ```\n */\n birthDate: Date | null;\n\n /**\n * Gender derived from the day encoding in the NIK.\n * - 'male': day is 1-31\n * - 'female': day is 41-71 (actual day + 40)\n * - `null`: if unable to determine\n */\n gender: 'male' | 'female' | null;\n\n /**\n * Serial number from positions 13-16 of the NIK.\n * Uniquely identifies individuals with the same location and birth date.\n * Returns `null` if unable to extract.\n *\n * @example\n * ```typescript\n * '0123'\n * ```\n */\n serialNumber: string | null;\n\n /**\n * Whether the NIK passed validation checks.\n * If `false`, other fields may be `null` or contain partial data.\n */\n isValid: boolean;\n}\n\n/**\n * Options for masking a NIK to protect privacy.\n *\n * Controls how many characters to show at the start and end,\n * what character to use for masking, and optional separators.\n *\n * @example\n * Default masking:\n * ```typescript\n * { visibleStart: 4, visibleEnd: 4, maskChar: '*' }\n * // Result: '3201********0123'\n *\n * // With separator\n * { visibleStart: 4, visibleEnd: 4, maskChar: '*', separator: '-' }\n * // Result: '3201-****-****-0123'\n * ```\n *\n * @public\n */\nexport interface MaskOptions {\n /**\n * Number of characters to show at the start.\n *\n * @defaultValue 4\n */\n visibleStart?: number;\n\n /**\n * Number of characters to show at the end.\n *\n * @defaultValue 4\n */\n visibleEnd?: number;\n\n /**\n * Character to use for masking hidden digits.\n *\n * @defaultValue '*'\n */\n maskChar?: string;\n\n /**\n * Optional separator to add between groups of digits.\n * If provided, the NIK will be formatted with separators.\n *\n * @defaultValue undefined (no separator)\n *\n * @example\n * ```typescript\n * '-' // Results in format: '3201-****-****-0123'\n * ' ' // Results in format: '3201 **** **** 0123'\n * ```\n */\n separator?: string;\n\n /**\n * @deprecated Use `visibleStart` instead. Deprecated in v0.7.0.\n */\n start?: number;\n\n /**\n * @deprecated Use `visibleEnd` instead. Deprecated in v0.7.0.\n */\n end?: number;\n\n /**\n * @deprecated Use `maskChar` instead. Deprecated in v0.7.0.\n */\n char?: string;\n}\n\n/**\n * Error thrown when an invalid NIK is provided to a function.\n * Extends native Error with a `code` property for programmatic error handling.\n *\n * @example\n * ```typescript\n * try {\n * requireNIK('invalid');\n * } catch (error) {\n * if (error instanceof InvalidNIKError) {\n * console.log(error.code); // 'INVALID_NIK'\n * }\n * }\n * ```\n *\n * @public\n */\nexport class InvalidNIKError extends Error {\n /** Error code for programmatic identification */\n readonly code = 'INVALID_NIK' as const;\n\n constructor(message: string = 'Invalid NIK provided') {\n super(message);\n this.name = 'InvalidNIKError';\n }\n}\n\n/**\n * Error codes for detailed NIK validation.\n *\n * @public\n */\nexport type NIKErrorCode =\n | 'INVALID_FORMAT'\n | 'INVALID_PROVINCE'\n | 'INVALID_MONTH'\n | 'INVALID_DAY'\n | 'INVALID_DATE'\n | 'FUTURE_DATE';\n\n/**\n * A single validation error with code and message.\n *\n * @public\n */\nexport interface NIKValidationError {\n /** Error code for programmatic handling */\n code: NIKErrorCode;\n /** Human-readable error message */\n message: string;\n}\n\n/**\n * Detailed validation result for NIK with structured error reporting.\n *\n * Use this for form validation where you need to show specific error\n * messages per field.\n *\n * @example\n * ```typescript\n * const result = validateNIKDetailed('1234');\n * if (!result.isValid) {\n * result.errors.forEach(err => {\n * console.log(err.code, err.message);\n * });\n * }\n * ```\n *\n * @public\n */\nexport interface NIKValidationResult {\n /** Whether the NIK is valid */\n isValid: boolean;\n /** List of validation errors (empty if valid) */\n errors: NIKValidationError[];\n /** Cleaned 16-digit NIK if valid, null otherwise */\n nik: string | null;\n}\n\n/**\n * Options for getAge function.\n *\n * @public\n */\nexport interface GetAgeOptions {\n /** Date to calculate age from (default: current date) */\n referenceDate?: Date;\n /** Return formatted Indonesian string instead of object */\n asString?: boolean;\n}\n\n/**\n * Age result object with years, months, and days.\n *\n * @public\n */\nexport interface Age {\n /** Full years */\n years: number;\n /** Remaining months after full years */\n months: number;\n /** Remaining days after full months */\n days: number;\n}\n"]}
@@ -87,6 +87,16 @@ function maskNPWP(npwp, options) {
87
87
  return `${start}${middle}${end}`;
88
88
  }
89
89
 
90
+ // src/npwp/errors.ts
91
+ var InvalidNPWPError = class extends Error {
92
+ constructor(message = "Invalid NPWP provided") {
93
+ super(message);
94
+ this.code = "INVALID_NPWP";
95
+ this.name = "InvalidNPWPError";
96
+ }
97
+ };
98
+
99
+ exports.InvalidNPWPError = InvalidNPWPError;
90
100
  exports.formatNPWP = formatNPWP;
91
101
  exports.maskNPWP = maskNPWP;
92
102
  exports.parseNPWP = parseNPWP;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/npwp/validate.ts","../../src/npwp/format.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Validates an Indonesian NPWP (Nomor Pokok Wajib Pajak).\n *\n * Supports both 15-digit (standard) and 16-digit (new NIK-based) formats.\n *\n * @param npwp - The NPWP string to validate\n * @returns `true` if valid, `false` otherwise\n *\n * @example\n * ```typescript\n * validateNPWP('01.234.567.8-012.000'); // true\n * validateNPWP('012345678012000'); // true\n * ```\n */\nexport function validateNPWP(npwp: string): boolean {\n if (!npwp || typeof npwp !== 'string') {\n return false;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n // Must be 15 or 16 digits\n if (cleaned.length !== 15 && cleaned.length !== 16) {\n return false;\n }\n\n // Basic check: all numeric\n if (!/^\\d+$/.test(cleaned)) {\n return false;\n }\n\n return true;\n}\n","import { validateNPWP } from './validate';\nimport { NPWPInfo, MaskOptions } from './types';\n\n/**\n * Formats an NPWP string into standard Indonesian format (99.999.999.9-999.999).\n *\n * @param npwp - The NPWP string to format\n * @returns Formatted NPWP string, or original if invalid\n *\n * @example\n * ```typescript\n * formatNPWP('012345678012000'); // '01.234.567.8-012.000'\n * ```\n */\nexport function formatNPWP(npwp: string): string {\n if (!validateNPWP(npwp)) {\n return npwp;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length === 15) {\n return `${cleaned.substring(0, 2)}.${cleaned.substring(\n 2,\n 5\n )}.${cleaned.substring(5, 8)}.${cleaned.substring(8, 9)}-${cleaned.substring(\n 9,\n 12\n )}.${cleaned.substring(12, 15)}`;\n }\n\n // 16-digit NPWP (NIK) usually doesn't have a standard \"dots\" format like 15-digit\n // but if it's NIK, it might be formatted as NIK elsewhere.\n // For now, return as is or implement a simple format.\n return cleaned;\n}\n\n/**\n * Parses an NPWP string into its components.\n *\n * @param npwp - The NPWP string to parse\n * @returns NPWPInfo object, or null if invalid\n */\nexport function parseNPWP(npwp: string): NPWPInfo | null {\n if (!validateNPWP(npwp)) {\n return null;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n const isNikBased = cleaned.length === 16;\n\n if (isNikBased) {\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 16),\n isNikBased: true,\n };\n }\n\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 15),\n isNikBased: false,\n };\n}\n\n/**\n * Masks an NPWP string for privacy.\n *\n * @param npwp - The NPWP string to mask\n * @param options - Masking options\n * @returns Masked NPWP string\n */\nexport function maskNPWP(npwp: string, options?: MaskOptions): string {\n if (!npwp) return '';\n\n const { visibleStart = 2, visibleEnd = 3, maskChar = '*' } = options || {};\n\n // If input is formatted, we mask the digits but keep the symbols in place\n if (npwp.includes('.') || npwp.includes('-')) {\n let digitCount = 0;\n const digitsOnly = npwp.replace(/[^\\d]/g, '');\n const totalDigits = digitsOnly.length;\n\n return npwp\n .split('')\n .map((char) => {\n if (/\\d/.test(char)) {\n digitCount++;\n if (\n digitCount <= visibleStart ||\n digitCount > totalDigits - visibleEnd\n ) {\n return char;\n }\n return maskChar;\n }\n return char;\n })\n .join('');\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length < visibleStart + visibleEnd) {\n return cleaned.replace(/./g, maskChar);\n }\n\n const start = cleaned.substring(0, visibleStart);\n const end = cleaned.substring(cleaned.length - visibleEnd);\n const middle = maskChar.repeat(cleaned.length - visibleStart - visibleEnd);\n\n return `${start}${middle}${end}`;\n}\n"]}
1
+ {"version":3,"sources":["../../src/npwp/validate.ts","../../src/npwp/format.ts","../../src/npwp/errors.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Validates an Indonesian NPWP (Nomor Pokok Wajib Pajak).\n *\n * Supports both 15-digit (standard) and 16-digit (new NIK-based) formats.\n *\n * @param npwp - The NPWP string to validate\n * @returns `true` if valid, `false` otherwise\n *\n * @example\n * ```typescript\n * validateNPWP('01.234.567.8-012.000'); // true\n * validateNPWP('012345678012000'); // true\n * ```\n */\nexport function validateNPWP(npwp: string): boolean {\n if (!npwp || typeof npwp !== 'string') {\n return false;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n // Must be 15 or 16 digits\n if (cleaned.length !== 15 && cleaned.length !== 16) {\n return false;\n }\n\n // Basic check: all numeric\n if (!/^\\d+$/.test(cleaned)) {\n return false;\n }\n\n return true;\n}\n","import { validateNPWP } from './validate';\nimport { NPWPInfo, MaskOptions } from './types';\n\n/**\n * Formats an NPWP string into standard Indonesian format (99.999.999.9-999.999).\n *\n * @param npwp - The NPWP string to format\n * @returns Formatted NPWP string, or original if invalid\n *\n * @example\n * ```typescript\n * formatNPWP('012345678012000'); // '01.234.567.8-012.000'\n * ```\n */\nexport function formatNPWP(npwp: string): string {\n if (!validateNPWP(npwp)) {\n return npwp;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length === 15) {\n return `${cleaned.substring(0, 2)}.${cleaned.substring(\n 2,\n 5\n )}.${cleaned.substring(5, 8)}.${cleaned.substring(8, 9)}-${cleaned.substring(\n 9,\n 12\n )}.${cleaned.substring(12, 15)}`;\n }\n\n // 16-digit NPWP (NIK) usually doesn't have a standard \"dots\" format like 15-digit\n // but if it's NIK, it might be formatted as NIK elsewhere.\n // For now, return as is or implement a simple format.\n return cleaned;\n}\n\n/**\n * Parses an NPWP string into its components.\n *\n * @param npwp - The NPWP string to parse\n * @returns NPWPInfo object, or null if invalid\n */\nexport function parseNPWP(npwp: string): NPWPInfo | null {\n if (!validateNPWP(npwp)) {\n return null;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n const isNikBased = cleaned.length === 16;\n\n if (isNikBased) {\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 16),\n isNikBased: true,\n };\n }\n\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 15),\n isNikBased: false,\n };\n}\n\n/**\n * Masks an NPWP string for privacy.\n *\n * @param npwp - The NPWP string to mask\n * @param options - Masking options\n * @returns Masked NPWP string\n */\nexport function maskNPWP(npwp: string, options?: MaskOptions): string {\n if (!npwp) return '';\n\n const { visibleStart = 2, visibleEnd = 3, maskChar = '*' } = options || {};\n\n // If input is formatted, we mask the digits but keep the symbols in place\n if (npwp.includes('.') || npwp.includes('-')) {\n let digitCount = 0;\n const digitsOnly = npwp.replace(/[^\\d]/g, '');\n const totalDigits = digitsOnly.length;\n\n return npwp\n .split('')\n .map((char) => {\n if (/\\d/.test(char)) {\n digitCount++;\n if (\n digitCount <= visibleStart ||\n digitCount > totalDigits - visibleEnd\n ) {\n return char;\n }\n return maskChar;\n }\n return char;\n })\n .join('');\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length < visibleStart + visibleEnd) {\n return cleaned.replace(/./g, maskChar);\n }\n\n const start = cleaned.substring(0, visibleStart);\n const end = cleaned.substring(cleaned.length - visibleEnd);\n const middle = maskChar.repeat(cleaned.length - visibleStart - visibleEnd);\n\n return `${start}${middle}${end}`;\n}\n","/**\n * Error thrown when an invalid NPWP is provided to a function.\n * Extends native Error with a `code` property for programmatic error handling.\n *\n * @example\n * ```typescript\n * try {\n * requireNPWP('invalid');\n * } catch (error) {\n * if (error instanceof InvalidNPWPError) {\n * console.log(error.code); // 'INVALID_NPWP'\n * }\n * }\n * ```\n *\n * @public\n */\nexport class InvalidNPWPError extends Error {\n readonly code = 'INVALID_NPWP' as const;\n\n constructor(message: string = 'Invalid NPWP provided') {\n super(message);\n this.name = 'InvalidNPWPError';\n }\n}\n"]}
@@ -73,4 +73,26 @@ declare function parseNPWP(npwp: string): NPWPInfo | null;
73
73
  */
74
74
  declare function maskNPWP(npwp: string, options?: MaskOptions): string;
75
75
 
76
- export { type MaskOptions, type NPWPInfo, formatNPWP, maskNPWP, parseNPWP, validateNPWP };
76
+ /**
77
+ * Error thrown when an invalid NPWP is provided to a function.
78
+ * Extends native Error with a `code` property for programmatic error handling.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * try {
83
+ * requireNPWP('invalid');
84
+ * } catch (error) {
85
+ * if (error instanceof InvalidNPWPError) {
86
+ * console.log(error.code); // 'INVALID_NPWP'
87
+ * }
88
+ * }
89
+ * ```
90
+ *
91
+ * @public
92
+ */
93
+ declare class InvalidNPWPError extends Error {
94
+ readonly code: "INVALID_NPWP";
95
+ constructor(message?: string);
96
+ }
97
+
98
+ export { InvalidNPWPError, type MaskOptions, type NPWPInfo, formatNPWP, maskNPWP, parseNPWP, validateNPWP };
@@ -73,4 +73,26 @@ declare function parseNPWP(npwp: string): NPWPInfo | null;
73
73
  */
74
74
  declare function maskNPWP(npwp: string, options?: MaskOptions): string;
75
75
 
76
- export { type MaskOptions, type NPWPInfo, formatNPWP, maskNPWP, parseNPWP, validateNPWP };
76
+ /**
77
+ * Error thrown when an invalid NPWP is provided to a function.
78
+ * Extends native Error with a `code` property for programmatic error handling.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * try {
83
+ * requireNPWP('invalid');
84
+ * } catch (error) {
85
+ * if (error instanceof InvalidNPWPError) {
86
+ * console.log(error.code); // 'INVALID_NPWP'
87
+ * }
88
+ * }
89
+ * ```
90
+ *
91
+ * @public
92
+ */
93
+ declare class InvalidNPWPError extends Error {
94
+ readonly code: "INVALID_NPWP";
95
+ constructor(message?: string);
96
+ }
97
+
98
+ export { InvalidNPWPError, type MaskOptions, type NPWPInfo, formatNPWP, maskNPWP, parseNPWP, validateNPWP };
@@ -85,6 +85,15 @@ function maskNPWP(npwp, options) {
85
85
  return `${start}${middle}${end}`;
86
86
  }
87
87
 
88
- export { formatNPWP, maskNPWP, parseNPWP, validateNPWP };
88
+ // src/npwp/errors.ts
89
+ var InvalidNPWPError = class extends Error {
90
+ constructor(message = "Invalid NPWP provided") {
91
+ super(message);
92
+ this.code = "INVALID_NPWP";
93
+ this.name = "InvalidNPWPError";
94
+ }
95
+ };
96
+
97
+ export { InvalidNPWPError, formatNPWP, maskNPWP, parseNPWP, validateNPWP };
89
98
  //# sourceMappingURL=index.js.map
90
99
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/npwp/validate.ts","../../src/npwp/format.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Validates an Indonesian NPWP (Nomor Pokok Wajib Pajak).\n *\n * Supports both 15-digit (standard) and 16-digit (new NIK-based) formats.\n *\n * @param npwp - The NPWP string to validate\n * @returns `true` if valid, `false` otherwise\n *\n * @example\n * ```typescript\n * validateNPWP('01.234.567.8-012.000'); // true\n * validateNPWP('012345678012000'); // true\n * ```\n */\nexport function validateNPWP(npwp: string): boolean {\n if (!npwp || typeof npwp !== 'string') {\n return false;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n // Must be 15 or 16 digits\n if (cleaned.length !== 15 && cleaned.length !== 16) {\n return false;\n }\n\n // Basic check: all numeric\n if (!/^\\d+$/.test(cleaned)) {\n return false;\n }\n\n return true;\n}\n","import { validateNPWP } from './validate';\nimport { NPWPInfo, MaskOptions } from './types';\n\n/**\n * Formats an NPWP string into standard Indonesian format (99.999.999.9-999.999).\n *\n * @param npwp - The NPWP string to format\n * @returns Formatted NPWP string, or original if invalid\n *\n * @example\n * ```typescript\n * formatNPWP('012345678012000'); // '01.234.567.8-012.000'\n * ```\n */\nexport function formatNPWP(npwp: string): string {\n if (!validateNPWP(npwp)) {\n return npwp;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length === 15) {\n return `${cleaned.substring(0, 2)}.${cleaned.substring(\n 2,\n 5\n )}.${cleaned.substring(5, 8)}.${cleaned.substring(8, 9)}-${cleaned.substring(\n 9,\n 12\n )}.${cleaned.substring(12, 15)}`;\n }\n\n // 16-digit NPWP (NIK) usually doesn't have a standard \"dots\" format like 15-digit\n // but if it's NIK, it might be formatted as NIK elsewhere.\n // For now, return as is or implement a simple format.\n return cleaned;\n}\n\n/**\n * Parses an NPWP string into its components.\n *\n * @param npwp - The NPWP string to parse\n * @returns NPWPInfo object, or null if invalid\n */\nexport function parseNPWP(npwp: string): NPWPInfo | null {\n if (!validateNPWP(npwp)) {\n return null;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n const isNikBased = cleaned.length === 16;\n\n if (isNikBased) {\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 16),\n isNikBased: true,\n };\n }\n\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 15),\n isNikBased: false,\n };\n}\n\n/**\n * Masks an NPWP string for privacy.\n *\n * @param npwp - The NPWP string to mask\n * @param options - Masking options\n * @returns Masked NPWP string\n */\nexport function maskNPWP(npwp: string, options?: MaskOptions): string {\n if (!npwp) return '';\n\n const { visibleStart = 2, visibleEnd = 3, maskChar = '*' } = options || {};\n\n // If input is formatted, we mask the digits but keep the symbols in place\n if (npwp.includes('.') || npwp.includes('-')) {\n let digitCount = 0;\n const digitsOnly = npwp.replace(/[^\\d]/g, '');\n const totalDigits = digitsOnly.length;\n\n return npwp\n .split('')\n .map((char) => {\n if (/\\d/.test(char)) {\n digitCount++;\n if (\n digitCount <= visibleStart ||\n digitCount > totalDigits - visibleEnd\n ) {\n return char;\n }\n return maskChar;\n }\n return char;\n })\n .join('');\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length < visibleStart + visibleEnd) {\n return cleaned.replace(/./g, maskChar);\n }\n\n const start = cleaned.substring(0, visibleStart);\n const end = cleaned.substring(cleaned.length - visibleEnd);\n const middle = maskChar.repeat(cleaned.length - visibleStart - visibleEnd);\n\n return `${start}${middle}${end}`;\n}\n"]}
1
+ {"version":3,"sources":["../../src/npwp/validate.ts","../../src/npwp/format.ts","../../src/npwp/errors.ts"],"names":[],"mappings":";AAcO,SAAS,aAAa,IAAA,EAAuB;AAClD,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AAGzC,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,EAAA,IAAM,OAAA,CAAQ,WAAW,EAAA,EAAI;AAClD,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,IAAI,CAAC,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA,EAAG;AAC1B,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAA;AACT;;;AClBO,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,IAAI,CAAC,YAAA,CAAa,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AAEzC,EAAA,IAAI,OAAA,CAAQ,WAAW,EAAA,EAAI;AACzB,IAAA,OAAO,GAAG,OAAA,CAAQ,SAAA,CAAU,GAAG,CAAC,CAAC,IAAI,OAAA,CAAQ,SAAA;AAAA,MAC3C,CAAA;AAAA,MACA;AAAA,KACD,CAAA,CAAA,EAAI,OAAA,CAAQ,SAAA,CAAU,GAAG,CAAC,CAAC,CAAA,CAAA,EAAI,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,CAAC,CAAC,IAAI,OAAA,CAAQ,SAAA;AAAA,MACjE,CAAA;AAAA,MACA;AAAA,KACD,CAAA,CAAA,EAAI,OAAA,CAAQ,SAAA,CAAU,EAAA,EAAI,EAAE,CAAC,CAAA,CAAA;AAAA,EAChC;AAKA,EAAA,OAAO,OAAA;AACT;AAQO,SAAS,UAAU,IAAA,EAA+B;AACvD,EAAA,IAAI,CAAC,YAAA,CAAa,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AACzC,EAAA,MAAM,UAAA,GAAa,QAAQ,MAAA,KAAW,EAAA;AAEtC,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,OAAA;AAAA,MACN,IAAA,EAAM,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AAAA,MAC5B,MAAA,EAAQ,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AAAA,MAC9B,QAAA,EAAU,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AAAA,MAChC,aAAA,EAAe,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,EAAE,CAAA;AAAA,MACtC,UAAA,EAAY,OAAA,CAAQ,SAAA,CAAU,EAAA,EAAI,EAAE,CAAA;AAAA,MACpC,UAAA,EAAY;AAAA,KACd;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,IAAA,EAAM,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AAAA,IAC5B,MAAA,EAAQ,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AAAA,IAC9B,QAAA,EAAU,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AAAA,IAChC,aAAA,EAAe,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,EAAE,CAAA;AAAA,IACtC,UAAA,EAAY,OAAA,CAAQ,SAAA,CAAU,EAAA,EAAI,EAAE,CAAA;AAAA,IACpC,UAAA,EAAY;AAAA,GACd;AACF;AASO,SAAS,QAAA,CAAS,MAAc,OAAA,EAA+B;AACpE,EAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAElB,EAAA,MAAM,EAAE,eAAe,CAAA,EAAG,UAAA,GAAa,GAAG,QAAA,GAAW,GAAA,EAAI,GAAI,OAAA,IAAW,EAAC;AAGzE,EAAA,IAAI,KAAK,QAAA,CAAS,GAAG,KAAK,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG;AAC5C,IAAA,IAAI,UAAA,GAAa,CAAA;AACjB,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AAC5C,IAAA,MAAM,cAAc,UAAA,CAAW,MAAA;AAE/B,IAAA,OAAO,KACJ,KAAA,CAAM,EAAE,CAAA,CACR,GAAA,CAAI,CAAC,IAAA,KAAS;AACb,MAAA,IAAI,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,EAAG;AACnB,QAAA,UAAA,EAAA;AACA,QAAA,IACE,UAAA,IAAc,YAAA,IACd,UAAA,GAAa,WAAA,GAAc,UAAA,EAC3B;AACA,UAAA,OAAO,IAAA;AAAA,QACT;AACA,QAAA,OAAO,QAAA;AAAA,MACT;AACA,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA,CACA,IAAA,CAAK,EAAE,CAAA;AAAA,EACZ;AAEA,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AAEzC,EAAA,IAAI,OAAA,CAAQ,MAAA,GAAS,YAAA,GAAe,UAAA,EAAY;AAC9C,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,EAAM,QAAQ,CAAA;AAAA,EACvC;AAEA,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,YAAY,CAAA;AAC/C,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,SAAA,CAAU,OAAA,CAAQ,SAAS,UAAU,CAAA;AACzD,EAAA,MAAM,SAAS,QAAA,CAAS,MAAA,CAAO,OAAA,CAAQ,MAAA,GAAS,eAAe,UAAU,CAAA;AAEzE,EAAA,OAAO,CAAA,EAAG,KAAK,CAAA,EAAG,MAAM,GAAG,GAAG,CAAA,CAAA;AAChC;;;ACxGO,IAAM,gBAAA,GAAN,cAA+B,KAAA,CAAM;AAAA,EAG1C,WAAA,CAAY,UAAkB,uBAAA,EAAyB;AACrD,IAAA,KAAA,CAAM,OAAO,CAAA;AAHf,IAAA,IAAA,CAAS,IAAA,GAAO,cAAA;AAId,IAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AAAA,EACd;AACF","file":"index.js","sourcesContent":["/**\n * Validates an Indonesian NPWP (Nomor Pokok Wajib Pajak).\n *\n * Supports both 15-digit (standard) and 16-digit (new NIK-based) formats.\n *\n * @param npwp - The NPWP string to validate\n * @returns `true` if valid, `false` otherwise\n *\n * @example\n * ```typescript\n * validateNPWP('01.234.567.8-012.000'); // true\n * validateNPWP('012345678012000'); // true\n * ```\n */\nexport function validateNPWP(npwp: string): boolean {\n if (!npwp || typeof npwp !== 'string') {\n return false;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n // Must be 15 or 16 digits\n if (cleaned.length !== 15 && cleaned.length !== 16) {\n return false;\n }\n\n // Basic check: all numeric\n if (!/^\\d+$/.test(cleaned)) {\n return false;\n }\n\n return true;\n}\n","import { validateNPWP } from './validate';\nimport { NPWPInfo, MaskOptions } from './types';\n\n/**\n * Formats an NPWP string into standard Indonesian format (99.999.999.9-999.999).\n *\n * @param npwp - The NPWP string to format\n * @returns Formatted NPWP string, or original if invalid\n *\n * @example\n * ```typescript\n * formatNPWP('012345678012000'); // '01.234.567.8-012.000'\n * ```\n */\nexport function formatNPWP(npwp: string): string {\n if (!validateNPWP(npwp)) {\n return npwp;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length === 15) {\n return `${cleaned.substring(0, 2)}.${cleaned.substring(\n 2,\n 5\n )}.${cleaned.substring(5, 8)}.${cleaned.substring(8, 9)}-${cleaned.substring(\n 9,\n 12\n )}.${cleaned.substring(12, 15)}`;\n }\n\n // 16-digit NPWP (NIK) usually doesn't have a standard \"dots\" format like 15-digit\n // but if it's NIK, it might be formatted as NIK elsewhere.\n // For now, return as is or implement a simple format.\n return cleaned;\n}\n\n/**\n * Parses an NPWP string into its components.\n *\n * @param npwp - The NPWP string to parse\n * @returns NPWPInfo object, or null if invalid\n */\nexport function parseNPWP(npwp: string): NPWPInfo | null {\n if (!validateNPWP(npwp)) {\n return null;\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n const isNikBased = cleaned.length === 16;\n\n if (isNikBased) {\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 16),\n isNikBased: true,\n };\n }\n\n return {\n npwp: cleaned,\n type: cleaned.substring(0, 2),\n serial: cleaned.substring(2, 8),\n checksum: cleaned.substring(8, 9),\n taxOfficeCode: cleaned.substring(9, 12),\n branchCode: cleaned.substring(12, 15),\n isNikBased: false,\n };\n}\n\n/**\n * Masks an NPWP string for privacy.\n *\n * @param npwp - The NPWP string to mask\n * @param options - Masking options\n * @returns Masked NPWP string\n */\nexport function maskNPWP(npwp: string, options?: MaskOptions): string {\n if (!npwp) return '';\n\n const { visibleStart = 2, visibleEnd = 3, maskChar = '*' } = options || {};\n\n // If input is formatted, we mask the digits but keep the symbols in place\n if (npwp.includes('.') || npwp.includes('-')) {\n let digitCount = 0;\n const digitsOnly = npwp.replace(/[^\\d]/g, '');\n const totalDigits = digitsOnly.length;\n\n return npwp\n .split('')\n .map((char) => {\n if (/\\d/.test(char)) {\n digitCount++;\n if (\n digitCount <= visibleStart ||\n digitCount > totalDigits - visibleEnd\n ) {\n return char;\n }\n return maskChar;\n }\n return char;\n })\n .join('');\n }\n\n const cleaned = npwp.replace(/[^\\d]/g, '');\n\n if (cleaned.length < visibleStart + visibleEnd) {\n return cleaned.replace(/./g, maskChar);\n }\n\n const start = cleaned.substring(0, visibleStart);\n const end = cleaned.substring(cleaned.length - visibleEnd);\n const middle = maskChar.repeat(cleaned.length - visibleStart - visibleEnd);\n\n return `${start}${middle}${end}`;\n}\n","/**\n * Error thrown when an invalid NPWP is provided to a function.\n * Extends native Error with a `code` property for programmatic error handling.\n *\n * @example\n * ```typescript\n * try {\n * requireNPWP('invalid');\n * } catch (error) {\n * if (error instanceof InvalidNPWPError) {\n * console.log(error.code); // 'INVALID_NPWP'\n * }\n * }\n * ```\n *\n * @public\n */\nexport class InvalidNPWPError extends Error {\n readonly code = 'INVALID_NPWP' as const;\n\n constructor(message: string = 'Invalid NPWP provided') {\n super(message);\n this.name = 'InvalidNPWPError';\n }\n}\n"]}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Validates an Indonesian license plate number format.
3
+ * Format: [1-2 letters] [1-4 digits] [1-3 letters]
4
+ *
5
+ * @param plate - The plate number string to validate
6
+ * @returns `true` if valid, `false` otherwise
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * validatePlate('B 1234 ABC'); // true
11
+ * validatePlate('AB 1 CD'); // true
12
+ * ```
13
+ */
14
+ declare function validatePlate(plate: string): boolean;
15
+ /**
16
+ * Gets the region name from a license plate number.
17
+ *
18
+ * @param plate - The plate number
19
+ * @returns Region name or null if not found
20
+ */
21
+ declare function getRegionFromPlate(plate: string): string | null;
22
+ /**
23
+ * Formats a license plate number with spaces (e.g., B 1234 ABC).
24
+ *
25
+ * @param plate - The plate number
26
+ * @returns Formatted plate string
27
+ */
28
+ declare function formatPlate(plate: string): string;
29
+
30
+ /**
31
+ * Error thrown when an invalid vehicle plate is provided to a function.
32
+ * Extends native Error with a `code` property for programmatic error handling.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * try {
37
+ * requirePlate('invalid');
38
+ * } catch (error) {
39
+ * if (error instanceof InvalidPlateError) {
40
+ * console.log(error.code); // 'INVALID_PLATE'
41
+ * }
42
+ * }
43
+ * ```
44
+ *
45
+ * @public
46
+ */
47
+ declare class InvalidPlateError extends Error {
48
+ readonly code: "INVALID_PLATE";
49
+ constructor(message?: string);
50
+ }
51
+
52
+ /**
53
+ * Information extracted from a valid Indonesian license plate number.
54
+ *
55
+ * Contains parsed data including the plate prefix, number, suffix,
56
+ * type classification, and formatted representation.
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const info: PlateInfo = {
61
+ * prefix: 'B',
62
+ * number: '1234',
63
+ * suffix: 'ABC',
64
+ * type: 'private',
65
+ * formatted: 'B 1234 ABC',
66
+ * isValid: true,
67
+ * };
68
+ * ```
69
+ *
70
+ * @public
71
+ */
72
+ interface PlateInfo {
73
+ /**
74
+ * Plate prefix (letters before number).
75
+ * Indicates the region where the vehicle is registered.
76
+ */
77
+ prefix: string;
78
+ /**
79
+ * Plate number (digits).
80
+ */
81
+ number: string;
82
+ /**
83
+ * Plate suffix (letters after number, if any).
84
+ */
85
+ suffix: string;
86
+ /**
87
+ * Type of vehicle registration.
88
+ * - 'private': Private vehicle
89
+ * - 'public': Public transportation
90
+ * - 'diplomat': Diplomatic vehicle
91
+ * - `null`: Unknown or invalid type
92
+ */
93
+ type: 'private' | 'public' | 'diplomat' | null;
94
+ /**
95
+ * Formatted plate string with proper spacing.
96
+ * @example 'B 1234 ABC'
97
+ */
98
+ formatted: string;
99
+ /**
100
+ * Whether the plate passed validation.
101
+ * If `false`, other fields may contain partial data.
102
+ */
103
+ isValid: boolean;
104
+ }
105
+
106
+ /**
107
+ * Parses an Indonesian license plate number into its component parts.
108
+ *
109
+ * Extracts the prefix (region code), number, and suffix (optional letters)
110
+ * from a plate number. Also determines the plate type and returns a
111
+ * formatted representation.
112
+ *
113
+ * @param plate - The plate string to parse
114
+ * @returns PlateInfo object with extracted components, or null if invalid
115
+ *
116
+ * @example
117
+ * Private plate:
118
+ * ```typescript
119
+ * parsePlate('B 1234 ABC');
120
+ * // {
121
+ * // prefix: 'B',
122
+ * // number: '1234',
123
+ * // suffix: 'ABC',
124
+ * // type: 'private',
125
+ * // formatted: 'B 1234 ABC',
126
+ * // isValid: true
127
+ * // }
128
+ * ```
129
+ *
130
+ * @example
131
+ * Public transport plate:
132
+ * ```typescript
133
+ * parsePlate('AB 1 CD');
134
+ * // {
135
+ * // prefix: 'AB',
136
+ * // number: '1',
137
+ * // suffix: 'CD',
138
+ * // type: 'public',
139
+ * // formatted: 'AB 1 CD',
140
+ * // isValid: true
141
+ * // }
142
+ * ```
143
+ *
144
+ * @example
145
+ * Invalid plate returns null:
146
+ * ```typescript
147
+ * parsePlate('invalid');
148
+ * // null
149
+ * ```
150
+ *
151
+ * @public
152
+ */
153
+ declare function parsePlate(plate: string): PlateInfo | null;
154
+
155
+ export { InvalidPlateError as I, type PlateInfo as P, formatPlate as f, getRegionFromPlate as g, parsePlate as p, validatePlate as v };