UNPKG

nhcx-fhir-coverage-eligibility

Version:

NHCX FHIR CoverageEligibilityRequest resource creation and validation library.

198 lines (197 loc) 7.54 kB
"use strict"; // fhir/coverageEligibilityRequest/createCoverageEligibilityRequest.ts Object.defineProperty(exports, "__esModule", { value: true }); exports.createCoverageEligibilityRequest = createCoverageEligibilityRequest; // --- NHCX FHIR Profile Definitions --- const ALLOWED_STATUS = ["active", "cancelled", "draft", "entered-in-error"]; const ALLOWED_PURPOSE = [ "auth-requirements", "benefits", "discovery", "validation", ]; // Cardinality and allowed fields for each structure const PROFILE_FIELDS = { id: { min: 0, max: 1 }, meta: { min: 0, max: 1 }, implicitRules: { min: 0, max: 1 }, language: { min: 0, max: 1 }, text: { min: 0, max: 1 }, contained: { min: 0, max: Infinity }, extension: { min: 0, max: Infinity }, modifierExtension: { min: 0, max: Infinity }, identifier: { min: 1, max: 1 }, status: { min: 1, max: 1 }, priority: { min: 1, max: 1 }, purpose: { min: 1, max: Infinity }, patient: { min: 1, max: 1 }, servicedDate: { min: 0, max: 1 }, servicedPeriod: { min: 0, max: 1 }, created: { min: 1, max: 1 }, enterer: { min: 1, max: 1 }, provider: { min: 1, max: 1 }, insurer: { min: 1, max: 1 }, facility: { min: 1, max: 1 }, supportingInfo: { min: 0, max: Infinity }, insurance: { min: 1, max: Infinity }, item: { min: 0, max: Infinity }, }; const SUPPORTING_INFO_FIELDS = { id: { min: 0, max: 1 }, extension: { min: 0, max: Infinity }, modifierExtension: { min: 0, max: Infinity }, sequence: { min: 1, max: 1 }, information: { min: 1, max: 1 }, appliesToAll: { min: 0, max: 1 }, }; const INSURANCE_FIELDS = { id: { min: 0, max: 1 }, extension: { min: 0, max: Infinity }, modifierExtension: { min: 0, max: Infinity }, focal: { min: 0, max: 1 }, coverage: { min: 1, max: 1 }, businessArrangement: { min: 0, max: 1 }, }; const ITEM_FIELDS = { id: { min: 0, max: 1 }, extension: { min: 0, max: Infinity }, modifierExtension: { min: 0, max: Infinity }, supportingInfoSequence: { min: 0, max: Infinity }, category: { min: 0, max: 1 }, productOrService: { min: 1, max: 1 }, modifier: { min: 0, max: Infinity }, provider: { min: 0, max: 1 }, quantity: { min: 0, max: 1 }, unitPrice: { min: 0, max: 1 }, facility: { min: 0, max: 1 }, diagnosis: { min: 0, max: Infinity }, detail: { min: 0, max: Infinity }, }; const ITEM_DIAGNOSIS_FIELDS = { id: { min: 0, max: 1 }, extension: { min: 0, max: Infinity }, modifierExtension: { min: 0, max: Infinity }, diagnosisCodeableConcept: { min: 0, max: 1 }, diagnosisReference: { min: 0, max: 1 }, }; // --- Utility: Field Validation --- function validateFields(input, profile, path = "") { // Check for unsupported fields for (const key of Object.keys(input)) { if (!profile[key]) { throw new Error(`Unsupported field '${path}${key}' in input`); } } // Check cardinality and required fields for (const [key, { min, max }] of Object.entries(profile)) { const value = input[key]; if (min > 0 && (value === undefined || value === null || (Array.isArray(value) && value.length < min))) { throw new Error(`Missing required field '${path}${key}'`); } if (value !== undefined) { if (Array.isArray(value)) { if (value.length < min) throw new Error(`Field '${path}${key}' must have at least ${min} item(s)`); if (max !== Infinity && value.length > max) throw new Error(`Field '${path}${key}' must have at most ${max} item(s)`); } } } } function validateSupportingInfo(arr, path = "supportingInfo[") { arr.forEach((info, i) => { validateFields(info, SUPPORTING_INFO_FIELDS, `${path}${i}].`); }); } function validateInsurance(arr, path = "insurance[") { arr.forEach((ins, i) => { validateFields(ins, INSURANCE_FIELDS, `${path}${i}].`); }); } function validateItem(arr, path = "item[") { arr.forEach((item, i) => { validateFields(item, ITEM_FIELDS, `${path}${i}].`); if (item.diagnosis) { item.diagnosis.forEach((diag, j) => { validateFields(diag, ITEM_DIAGNOSIS_FIELDS, `${path}${i}].diagnosis[${j}].`); }); } }); } // Helper to generate UUID (uses crypto.randomUUID if available, else fallback) function generateUUID() { if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') { return crypto.randomUUID(); } // Fallback: RFC4122 version 4 compliant UUID return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { const r = (Math.random() * 16) | 0, v = c === 'x' ? r : (r & 0x3) | 0x8; return v.toString(16); }); } /** * Creates a valid NHCX FHIR CoverageEligibilityRequest resource. * @param input - The resource fields (see CoverageEligibilityRequestInput for details). * @returns The validated and defaulted FHIR resource. * @throws Error if required fields are missing or invalid. */ function createCoverageEligibilityRequest(input) { // Top-level validation validateFields(input, PROFILE_FIELDS); // Enum validation if (!ALLOWED_STATUS.includes(input.status)) { throw new Error(`Invalid status: '${input.status}'. Allowed: ${ALLOWED_STATUS.join(", ")}`); } if (!Array.isArray(input.purpose) || input.purpose.length === 0) { throw new Error(`'purpose' must be a non-empty array`); } const invalidPurposes = input.purpose.filter((p) => !ALLOWED_PURPOSE.includes(p)); if (invalidPurposes.length > 0) { throw new Error(`Invalid purpose(s): ${invalidPurposes.join(", ")}. Allowed: ${ALLOWED_PURPOSE.join(", ")}`); } if (input.servicedDate && input.servicedPeriod) { throw new Error(`Only one of 'servicedDate' or 'servicedPeriod' may be provided`); } // Business logic: priority is required, no default if (!input.priority) { throw new Error(`Missing required field 'priority'`); } // Nested validation if (input.supportingInfo) validateSupportingInfo(input.supportingInfo); if (input.insurance) validateInsurance(input.insurance); if (input.item) validateItem(input.item); // Set defaults const created = input.created || new Date().toISOString(); const id = input.id || generateUUID(); let meta = input.meta; if (!meta) { meta = { profile: [ "https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityRequest" ], versionId: "1", lastUpdated: new Date().toISOString() }; } else { if (!meta.profile) { meta.profile = [ "https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityRequest" ]; } if (!meta.versionId) { meta.versionId = "1"; } if (!meta.lastUpdated) { meta.lastUpdated = new Date().toISOString(); } } // Ensure meta fields are not undefined const safeMeta = Object.assign(Object.assign({}, meta), { profile: meta.profile, versionId: meta.versionId, lastUpdated: meta.lastUpdated }); // Build resource const resource = Object.assign(Object.assign({}, input), { resourceType: "CoverageEligibilityRequest", id, meta: safeMeta, created }); return resource; }