{"version":3,"sources":["../../src/bpjs/constants.ts","../../src/bpjs/clean.ts","../../src/bpjs/validate.ts","../../src/bpjs/types.ts","../../src/bpjs/format.ts","../../src/bpjs/parse.ts","../../src/bpjs/mask.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/** Digit count for BPJS Kesehatan numbers */\nexport const KESEHATAN_LENGTH = 13;\n\n/** Digit count for BPJS Ketenagakerjaan numbers */\nexport const KETENAGAKERJAAN_LENGTH = 11;\n","/**\n * Strips all non-numeric characters from a BPJS number string.\n *\n * @param number - Raw input string\n * @returns Digits-only string, or empty string for null/empty input\n *\n * @example\n * cleanBPJS('0001-2345-67890') // '0001234567890'\n * cleanBPJS('BPJS: 12345678901') // '12345678901'\n * cleanBPJS('') // ''\n */\nexport function cleanBPJS(number: string): string {\n  if (!number || typeof number !== 'string') return '';\n  return number.replace(/[^\\d]/g, '');\n}\n","import { KESEHATAN_LENGTH, KETENAGAKERJAAN_LENGTH } from './constants';\nimport { BPJSType } from './types';\nimport { cleanBPJS } from './clean';\n\n/**\n * Validates a BPJS number for the given type.\n * Cleans non-numeric characters before validating.\n *\n * @param number - BPJS number (raw or formatted)\n * @param type - 'kesehatan' (13 digits) or 'ketenagakerjaan' (11 digits)\n * @returns true if valid, false otherwise — never throws\n *\n * @example\n * validateBPJS('0001234567890', 'kesehatan') // true\n * validateBPJS('0001-2345-67890', 'kesehatan') // true (cleans first)\n * validateBPJS('12345678901', 'ketenagakerjaan') // true\n * validateBPJS('123456789', 'kesehatan') // false\n */\nexport function validateBPJS(number: string, type: BPJSType): boolean {\n  if (!number || typeof number !== 'string') return false;\n  const cleaned = cleanBPJS(number);\n  const expectedLength =\n    type === 'kesehatan' ? KESEHATAN_LENGTH : KETENAGAKERJAAN_LENGTH;\n  return cleaned.length === expectedLength;\n}\n\n/**\n * Validates a BPJS Kesehatan number (13 numeric digits).\n *\n * @example\n * validateBPJSKesehatan('0001234567890') // true\n * validateBPJSKesehatan('000123456789') // false — 12 digits\n */\nexport function validateBPJSKesehatan(number: string): boolean {\n  return validateBPJS(number, 'kesehatan');\n}\n\n/**\n * Validates a BPJS Ketenagakerjaan number (11 numeric digits).\n *\n * @example\n * validateBPJSKetenagakerjaan('12345678901') // true\n * validateBPJSKetenagakerjaan('1234567890') // false — 10 digits\n */\nexport function validateBPJSKetenagakerjaan(number: string): boolean {\n  return validateBPJS(number, 'ketenagakerjaan');\n}\n\n/**\n * Detects BPJS type from digit length.\n * Returns null if the cleaned input length matches neither type.\n *\n * @example\n * detectBPJSType('0001234567890') // 'kesehatan'\n * detectBPJSType('12345678901')   // 'ketenagakerjaan'\n * detectBPJSType('123456789')     // null\n */\nexport function detectBPJSType(number: string): BPJSType | null {\n  if (!number || typeof number !== 'string') return null;\n  const cleaned = cleanBPJS(number);\n  if (cleaned.length === KESEHATAN_LENGTH) return 'kesehatan';\n  if (cleaned.length === KETENAGAKERJAAN_LENGTH) return 'ketenagakerjaan';\n  return null;\n}\n","export type BPJSType = 'kesehatan' | 'ketenagakerjaan';\n\nexport interface BPJSInfo {\n  type: BPJSType;\n  /** Digits-only string, no separators */\n  raw: string;\n  /** Formatted with standard separators */\n  formatted: string;\n}\n\nexport interface BPJSMaskOptions {\n  /** Characters to keep visible at start. Default: 4 */\n  visibleStart?: number;\n  /** Characters to keep visible at end. Default: 2 */\n  visibleEnd?: number;\n  /** Replacement character. Default: '*' */\n  maskChar?: string;\n}\n\nexport class InvalidBPJSError extends Error {\n  readonly code = 'INVALID_BPJS' as const;\n\n  constructor(message = 'Invalid BPJS number') {\n    super(message);\n    this.name = 'InvalidBPJSError';\n  }\n}\n","import { cleanBPJS } from './clean';\nimport { validateBPJS } from './validate';\nimport { BPJSType, InvalidBPJSError } from './types';\n\n/**\n * Formats a BPJS number with standard separators.\n *\n * - kesehatan:        XXXX-XXXX-XXXXX  (4-4-5 groups)\n * - ketenagakerjaan:  XXXX-XXX-XXXX    (4-3-4 groups)\n *\n * Accepts pre-formatted input (idempotent).\n *\n * @throws {InvalidBPJSError} if the cleaned number fails validation for the given type\n *\n * @example\n * formatBPJS('0001234567890', 'kesehatan')    // '0001-2345-67890'\n * formatBPJS('12345678901', 'ketenagakerjaan') // '1234-567-8901'\n * formatBPJS('0001-2345-67890', 'kesehatan')  // '0001-2345-67890' (idempotent)\n */\nexport function formatBPJS(number: string, type: BPJSType): string {\n  const cleaned = cleanBPJS(number);\n\n  if (!validateBPJS(cleaned, type)) {\n    throw new InvalidBPJSError(\n      `Invalid BPJS ${type} number: \"${number}\"`\n    );\n  }\n\n  if (type === 'kesehatan') {\n    return `${cleaned.slice(0, 4)}-${cleaned.slice(4, 8)}-${cleaned.slice(8)}`;\n  }\n\n  // ketenagakerjaan: 4-3-4\n  return `${cleaned.slice(0, 4)}-${cleaned.slice(4, 7)}-${cleaned.slice(7)}`;\n}\n","import { cleanBPJS } from './clean';\nimport { detectBPJSType } from './validate';\nimport { formatBPJS } from './format';\nimport { BPJSInfo } from './types';\n\n/**\n * Parses a BPJS number of either type. Auto-detects type from digit length.\n * Returns null if the number is invalid for both types.\n *\n * @example\n * parseBPJS('0001234567890')\n * // { type: 'kesehatan', raw: '0001234567890', formatted: '0001-2345-67890' }\n *\n * parseBPJS('0001-2345-67890')\n * // { type: 'kesehatan', raw: '0001234567890', formatted: '0001-2345-67890' }\n *\n * parseBPJS('12345678901')\n * // { type: 'ketenagakerjaan', raw: '12345678901', formatted: '1234-567-8901' }\n *\n * parseBPJS('12345')\n * // null\n */\nexport function parseBPJS(number: string): BPJSInfo | null {\n  if (!number || typeof number !== 'string') return null;\n\n  const raw = cleanBPJS(number);\n  const type = detectBPJSType(raw);\n  if (!type) return null;\n\n  return {\n    type,\n    raw,\n    formatted: formatBPJS(raw, type),\n  };\n}\n","import { cleanBPJS } from './clean';\nimport { BPJSMaskOptions } from './types';\n\n/**\n * Masks a BPJS number for privacy-safe display.\n * Always operates on the raw (digits-only) string.\n *\n * Defaults: visibleStart=4, visibleEnd=2, maskChar='*'\n *\n * If visibleStart + visibleEnd >= raw.length, returns the full raw string unmasked.\n *\n * @example\n * maskBPJS('0001234567890')\n * // '0001*******90'\n *\n * maskBPJS('0001234567890', { visibleStart: 4, visibleEnd: 4, maskChar: 'X' })\n * // '0001XXXXXR7890'  — note: 13 - 4 - 4 = 5 mask chars\n *\n * maskBPJS('0001-2345-67890')  // accepts formatted input\n * // '0001*******90'\n *\n * maskBPJS('')\n * // ''\n */\nexport function maskBPJS(number: string, options: BPJSMaskOptions = {}): string {\n  if (!number || typeof number !== 'string') return '';\n\n  const raw = cleanBPJS(number);\n  if (!raw) return '';\n\n  const { visibleStart = 4, visibleEnd = 2, maskChar = '*' } = options;\n\n  if (visibleStart + visibleEnd >= raw.length) return raw;\n\n  const maskLength = raw.length - visibleStart - visibleEnd;\n  return (\n    raw.slice(0, visibleStart) +\n    maskChar.repeat(maskLength) +\n    raw.slice(raw.length - visibleEnd)\n  );\n}\n"]}