import Personnummer from 'personnummer' import { normalizePidSearchValue } from '../composables/useIsPid' export interface SsnValidationOptions { allowCoordinationNumber?: boolean allowInterimNumber?: boolean } export interface SsnValidationResult { isValid: boolean /** Normalized value without separators; `null` when empty or invalid. */ digits: string | null } const INVALID_RESULT: SsnValidationResult = { isValid: false, digits: null, } const DEFAULT_SSN_VALIDATION_OPTIONS = { allowCoordinationNumber: true, allowInterimNumber: true, } as const function resolveSsnValidationOptions(options?: SsnValidationOptions) { return { ...DEFAULT_SSN_VALIDATION_OPTIONS, ...options, } } /** Strip separators; keeps alphanumeric characters for interim numbers. */ export function stripSsnSeparators(value: string): string { return normalizePidSearchValue(value) } /** Validate a Swedish personal identity number. */ export function validateSsnNumber(value: string, options?: SsnValidationOptions): SsnValidationResult { const trimmed = value.trim() if (!trimmed) { return INVALID_RESULT } const resolvedOptions = resolveSsnValidationOptions(options) const isValid = Personnummer.valid(trimmed, resolvedOptions) return { isValid, digits: isValid ? stripSsnSeparators(trimmed) : null, } } export function validateSsn(value: string, options?: SsnValidationOptions): boolean { return validateSsnNumber(value, options).isValid } /** `null` when empty, otherwise whether the value is a valid personnummer. */ export function getSsnValidationState(value: string, options?: SsnValidationOptions): boolean | null { if (!value.trim()) { return null } return validateSsn(value, options) }