@onivoro/isomorphic-fhir 24.28.1

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Onivoro
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,189 @@
1
+ # @onivoro/isomorphic-fhir
2
+
3
+ A library for transforming FHIR (Fast Healthcare Interoperability Resources) bundles into normalized database tables following Third Normal Form (3NF).
4
+
5
+ ## Overview
6
+
7
+ This library takes FHIR R4 bundles containing healthcare resources and transforms them into a set of normalized tables that can be used to populate a relational database. The transformation process:
8
+
9
+ - Eliminates data redundancy across FHIR resources
10
+ - Ensures referential integrity between healthcare entities
11
+ - Creates proper foreign key relationships
12
+ - Generates unique IDs for normalized records
13
+ - Preserves FHIR resource relationships through reference tables
14
+ - Handles complex nested structures like CodeableConcepts and Extensions
15
+
16
+ ## Supported FHIR Resources
17
+
18
+ The library currently supports normalization of the following FHIR R4 resources:
19
+
20
+ - **Patient**: Demographics, identifiers, names, contacts, addresses
21
+ - **Practitioner**: Healthcare providers, qualifications, contact information
22
+ - **Organization**: Healthcare organizations, types, contact details
23
+ - **Encounter**: Healthcare encounters, participants, locations
24
+ - **Condition**: Medical conditions, clinical status, evidence
25
+ - **Observation**: Clinical measurements, vital signs, lab results
26
+ - **MedicationRequest**: Medication prescriptions, dosage instructions
27
+ - **Procedure**: Medical procedures, performers, outcomes
28
+ - **Immunization**: Vaccinations, reactions, protocols
29
+ - **AllergyIntolerance**: Allergies, reactions, manifestations
30
+ - **DiagnosticReport**: Diagnostic test results, conclusions
31
+ - **Location**: Healthcare facilities, positions, contact info
32
+ - **Appointment**: Scheduled appointments, participants
33
+ - **CareTeam**: Care team members, roles, periods
34
+ - **CarePlan**: Care plans, activities, goals
35
+
36
+ ## Usage
37
+
38
+ ```typescript
39
+ import { normalizeFhirBundle } from '@onivoro/isomorphic-fhir';
40
+
41
+ const fhirBundle = {
42
+ resourceType: 'Bundle',
43
+ type: 'searchset',
44
+ entry: [
45
+ {
46
+ resource: {
47
+ resourceType: 'Patient',
48
+ id: 'patient-123',
49
+ name: [{ family: 'Doe', given: ['John'] }],
50
+ gender: 'male',
51
+ birthDate: '1985-03-15'
52
+ }
53
+ },
54
+ {
55
+ resource: {
56
+ resourceType: 'Observation',
57
+ id: 'observation-456',
58
+ status: 'final',
59
+ code: { coding: [{ code: '8867-4', display: 'Heart rate' }] },
60
+ subject: { reference: 'Patient/patient-123' },
61
+ valueQuantity: { value: 72, unit: 'beats/min' }
62
+ }
63
+ }
64
+ ]
65
+ };
66
+
67
+ const normalizedData = normalizeFhirBundle(fhirBundle);
68
+
69
+ // normalizedData contains normalized tables:
70
+ console.log(normalizedData.patients); // Patient demographics
71
+ console.log(normalizedData.patientNames); // Patient names (separate table)
72
+ console.log(normalizedData.observations); // Clinical observations
73
+ console.log(normalizedData.addresses); // Addresses (deduplicated)
74
+ console.log(normalizedData.telecoms); // Contact points
75
+ console.log(normalizedData.references); // Resource relationships
76
+ ```
77
+
78
+ ## Normalized Tables Generated
79
+
80
+ The library generates 30+ normalized tables following healthcare data patterns:
81
+
82
+ ### Core Resource Tables
83
+ - **bundles**: FHIR bundle metadata
84
+ - **bundleEntries**: Bundle entry information
85
+ - **patients**: Patient demographics
86
+ - **practitioners**: Healthcare provider information
87
+ - **organizations**: Healthcare organizations
88
+ - **encounters**: Healthcare encounters
89
+ - **conditions**: Medical conditions and diagnoses
90
+ - **observations**: Clinical measurements and findings
91
+ - **medicationRequests**: Medication prescriptions
92
+ - **procedures**: Medical procedures performed
93
+ - **immunizations**: Vaccination records
94
+ - **allergyIntolerances**: Allergy and intolerance information
95
+ - **diagnosticReports**: Diagnostic test reports
96
+ - **locations**: Healthcare facility information
97
+ - **appointments**: Scheduled appointments
98
+ - **careTeams**: Care team compositions
99
+ - **carePlans**: Patient care plans
100
+
101
+ ### Relationship and Detail Tables
102
+ - **patientIdentifiers**: Patient identifier systems
103
+ - **patientNames**: Patient name variations
104
+ - **patientContacts**: Emergency/family contacts
105
+ - **practitionerQualifications**: Provider credentials
106
+ - **organizationTypes**: Organization classifications
107
+ - **encounterParticipants**: Encounter participants
108
+ - **observationComponents**: Multi-component observations
109
+ - **medicationDosages**: Medication dosing instructions
110
+ - **procedurePerformers**: Procedure performers
111
+ - **allergyReactions**: Allergic reactions
112
+ - **allergyManifestations**: Reaction manifestations
113
+ - **diagnosticReportResults**: Report result references
114
+ - **appointmentParticipants**: Appointment participants
115
+ - **careTeamParticipants**: Care team member details
116
+ - **carePlanActivities**: Care plan activity details
117
+
118
+ ### Common Data Type Tables
119
+ - **addresses**: Physical addresses (deduplicated)
120
+ - **telecoms**: Contact points (phone, email, etc.)
121
+ - **codeableConcepts**: Coded concepts with text
122
+ - **codings**: Individual coding systems
123
+ - **notes**: Annotations and comments
124
+ - **attachments**: Binary attachments and documents
125
+ - **references**: Resource references and relationships
126
+
127
+ ## Key Features
128
+
129
+ ### FHIR Compliance
130
+ - Full FHIR R4 resource support
131
+ - Proper handling of FHIR data types (CodeableConcept, Reference, etc.)
132
+ - Preservation of clinical terminology and coding systems
133
+ - Support for complex nested structures
134
+
135
+ ### Data Integrity
136
+ - Referential integrity through normalized foreign keys
137
+ - Unique constraint handling for identifiers
138
+ - Proper temporal data handling (effective periods, timestamps)
139
+ - Clinical status and verification status preservation
140
+
141
+ ### Healthcare-Specific Patterns
142
+ - Support for multiple identifier systems per resource
143
+ - Proper handling of clinical hierarchies (conditions, observations)
144
+ - Care team and care plan relationship modeling
145
+ - Medication dosing and administration patterns
146
+ - Allergy and adverse reaction tracking
147
+
148
+ ### Performance Optimized
149
+ - Efficient deduplication of common entities (addresses, codings)
150
+ - Bulk insert-friendly table structures
151
+ - Indexed foreign key relationships
152
+ - Minimal data redundancy
153
+
154
+ ## Testing
155
+
156
+ The library includes comprehensive tests covering:
157
+ - Complete FHIR bundle normalization
158
+ - Individual resource type processing
159
+ - Complex nested structure handling
160
+ - Reference relationship preservation
161
+ - Edge cases and error conditions
162
+
163
+ Run tests with:
164
+ ```bash
165
+ nx test lib-isomorphic-fhir
166
+ ```
167
+
168
+ ## FHIR Standards Compliance
169
+
170
+ This library is designed to work with FHIR R4 resources and follows HL7 FHIR standards for:
171
+ - Resource structure and cardinality
172
+ - Data type handling and validation
173
+ - Reference resolution and integrity
174
+ - Clinical terminology bindings
175
+ - Healthcare workflow patterns
176
+
177
+ ## Use Cases
178
+
179
+ Perfect for:
180
+ - **EHR Data Warehousing**: Normalize FHIR data for analytics
181
+ - **Clinical Data Lakes**: Store FHIR resources in relational format
182
+ - **Interoperability Solutions**: Transform FHIR for legacy systems
183
+ - **Healthcare Analytics**: Enable SQL-based analysis of clinical data
184
+ - **Compliance Reporting**: Structure data for regulatory requirements
185
+ - **Research Databases**: Prepare clinical data for research queries
186
+
187
+ ## License
188
+
189
+ This library is licensed under the MIT License. See the LICENSE file in this package for details.
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@onivoro/isomorphic-fhir",
3
+ "version": "24.28.1",
4
+ "license": "MIT",
5
+ "type": "commonjs",
6
+ "main": "./src/index.js",
7
+ "types": "./src/index.d.ts",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/onivoro/monorepo.git"
11
+ },
12
+ "dependencies": {
13
+ "@nestjs/swagger": "*",
14
+ "tslib": "^2.3.0",
15
+ "uuid": "*"
16
+ },
17
+ "files": [
18
+ "**/*.js",
19
+ "**/*.d.ts",
20
+ "**/*.js.map",
21
+ "README.md"
22
+ ]
23
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './lib/interfaces/fhir-resources.interface';
2
+ export * from './lib/interfaces/fhir-normalized-tables.interface';
3
+ export * from './lib/functions/normalize-fhir-bundle.function';
package/src/index.js ADDED
@@ -0,0 +1,6 @@
1
+ // FHIR Resource Interfaces
2
+ export * from './lib/interfaces/fhir-resources.interface';
3
+ export * from './lib/interfaces/fhir-normalized-tables.interface';
4
+ // Functions
5
+ export * from './lib/functions/normalize-fhir-bundle.function';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/isomorphic/fhir/src/index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mDAAmD,CAAC;AAElE,YAAY;AACZ,cAAc,gDAAgD,CAAC"}
@@ -0,0 +1,127 @@
1
+ import { AxiosInstance } from 'axios';
2
+ /**
3
+ * Configuration and utilities for FHIR API integration tests
4
+ */
5
+ export declare class FhirTestConfig {
6
+ static readonly FHIR_BASE_URL = "http://hapi.fhir.org/baseR4";
7
+ static readonly TEST_TIMEOUT = 30000;
8
+ private static testAxiosInstance;
9
+ /**
10
+ * Get or create the test axios instance
11
+ */
12
+ static getAxiosInstance(): AxiosInstance;
13
+ /**
14
+ * Clean up the axios instance
15
+ */
16
+ static cleanup(): void;
17
+ /**
18
+ * Common FHIR resource types for testing
19
+ */
20
+ static readonly RESOURCE_TYPES: {
21
+ readonly PATIENT: "Patient";
22
+ readonly PRACTITIONER: "Practitioner";
23
+ readonly ORGANIZATION: "Organization";
24
+ readonly ENCOUNTER: "Encounter";
25
+ readonly OBSERVATION: "Observation";
26
+ readonly CONDITION: "Condition";
27
+ readonly MEDICATION_REQUEST: "MedicationRequest";
28
+ readonly PROCEDURE: "Procedure";
29
+ readonly LOCATION: "Location";
30
+ readonly APPOINTMENT: "Appointment";
31
+ readonly CARE_TEAM: "CareTeam";
32
+ readonly CARE_PLAN: "CarePlan";
33
+ readonly IMMUNIZATION: "Immunization";
34
+ readonly ALLERGY_INTOLERANCE: "AllergyIntolerance";
35
+ readonly DIAGNOSTIC_REPORT: "DiagnosticReport";
36
+ };
37
+ /**
38
+ * Common search parameters for testing
39
+ */
40
+ static readonly SEARCH_PARAMS: {
41
+ readonly COUNT: "_count";
42
+ readonly FORMAT: "_format";
43
+ readonly INCLUDE: "_include";
44
+ readonly SORT: "_sort";
45
+ readonly TEXT: "_text";
46
+ };
47
+ /**
48
+ * Initialize axios defaults for testing
49
+ */
50
+ static initializeAxios(): void;
51
+ /**
52
+ * Build a FHIR search URL with parameters
53
+ */
54
+ static buildSearchUrl(resourceType: string, params?: Record<string, string | number>): string;
55
+ /**
56
+ * Get a resource by ID
57
+ */
58
+ static buildResourceUrl(resourceType: string, id: string): string;
59
+ /**
60
+ * Common assertion helpers for FHIR resources
61
+ */
62
+ static validateFhirResource(resource: any, expectedType: string): void;
63
+ /**
64
+ * Validate FHIR Bundle structure
65
+ */
66
+ static validateFhirBundle(bundle: any): void;
67
+ /**
68
+ * Wait for a condition to be met (useful for async operations)
69
+ */
70
+ static waitFor(condition: () => boolean | Promise<boolean>, timeout?: number): Promise<void>;
71
+ /**
72
+ * Retry a function with exponential backoff
73
+ */
74
+ static retry<T>(fn: () => Promise<T>, maxAttempts?: number, initialDelay?: number): Promise<T>;
75
+ /**
76
+ * Check if the FHIR server is available
77
+ */
78
+ static checkServerAvailability(): Promise<boolean>;
79
+ /**
80
+ * Get server capability statement
81
+ */
82
+ static getServerCapabilities(): Promise<any>;
83
+ /**
84
+ * Clean up test data (if the server supports it)
85
+ */
86
+ /**
87
+ * Clean up test data (placeholder - HAPI test server doesn't support DELETE)
88
+ */
89
+ static cleanupTestData(resourceType: string, identifiers: string[]): Promise<void>;
90
+ /**
91
+ * Generate test data patterns
92
+ */
93
+ static getTestPatterns(): {
94
+ searchPatterns: ({
95
+ params: {
96
+ _count: number;
97
+ _sort?: undefined;
98
+ };
99
+ } | {
100
+ params: {
101
+ _count: number;
102
+ _sort: string;
103
+ };
104
+ })[];
105
+ resourceCombinations: (("Patient" | "Encounter")[] | ("Practitioner" | "Organization")[] | ("Patient" | "Observation")[])[];
106
+ errorScenarios: {
107
+ url: string;
108
+ expectedStatus: number;
109
+ }[];
110
+ };
111
+ }
112
+ /**
113
+ * Test utilities for performance monitoring
114
+ */
115
+ export declare class FhirTestPerformance {
116
+ private static measurements;
117
+ static startMeasurement(name: string): () => number;
118
+ static recordMeasurement(name: string, duration: number): void;
119
+ static getStatistics(name: string): {
120
+ avg: number;
121
+ min: number;
122
+ max: number;
123
+ count: number;
124
+ } | null;
125
+ static reset(): void;
126
+ static logStatistics(): void;
127
+ }
@@ -0,0 +1,276 @@
1
+ import { __awaiter } from "tslib";
2
+ import axios from 'axios';
3
+ import * as http from 'http';
4
+ import * as https from 'https';
5
+ /**
6
+ * Configuration and utilities for FHIR API integration tests
7
+ */
8
+ export class FhirTestConfig {
9
+ /**
10
+ * Get or create the test axios instance
11
+ */
12
+ static getAxiosInstance() {
13
+ if (!this.testAxiosInstance) {
14
+ // Create HTTP/HTTPS agents that don't keep connections alive
15
+ const httpAgent = new http.Agent({
16
+ keepAlive: false,
17
+ maxSockets: 5
18
+ });
19
+ const httpsAgent = new https.Agent({
20
+ keepAlive: false,
21
+ maxSockets: 5
22
+ });
23
+ this.testAxiosInstance = axios.create({
24
+ timeout: this.TEST_TIMEOUT,
25
+ httpAgent,
26
+ httpsAgent,
27
+ headers: {
28
+ 'Accept': 'application/fhir+json',
29
+ 'Connection': 'close'
30
+ }
31
+ });
32
+ }
33
+ return this.testAxiosInstance;
34
+ }
35
+ /**
36
+ * Clean up the axios instance
37
+ */
38
+ static cleanup() {
39
+ if (this.testAxiosInstance) {
40
+ // Destroy any remaining connections
41
+ if (this.testAxiosInstance.defaults.httpAgent) {
42
+ this.testAxiosInstance.defaults.httpAgent.destroy();
43
+ }
44
+ if (this.testAxiosInstance.defaults.httpsAgent) {
45
+ this.testAxiosInstance.defaults.httpsAgent.destroy();
46
+ }
47
+ }
48
+ }
49
+ /**
50
+ * Initialize axios defaults for testing
51
+ */
52
+ static initializeAxios() {
53
+ // Just ensure our test instance is created
54
+ this.getAxiosInstance();
55
+ }
56
+ /**
57
+ * Build a FHIR search URL with parameters
58
+ */
59
+ static buildSearchUrl(resourceType, params = {}) {
60
+ const url = new URL(`${this.FHIR_BASE_URL}/${resourceType}`);
61
+ // Add default format parameter
62
+ url.searchParams.set(this.SEARCH_PARAMS.FORMAT, 'json');
63
+ // Add custom parameters, filtering out undefined values
64
+ Object.entries(params).forEach(([key, value]) => {
65
+ if (value !== undefined) {
66
+ url.searchParams.set(key, value.toString());
67
+ }
68
+ });
69
+ return url.toString();
70
+ }
71
+ /**
72
+ * Get a resource by ID
73
+ */
74
+ static buildResourceUrl(resourceType, id) {
75
+ return `${this.FHIR_BASE_URL}/${resourceType}/${id}?_format=json`;
76
+ }
77
+ /**
78
+ * Common assertion helpers for FHIR resources
79
+ */
80
+ static validateFhirResource(resource, expectedType) {
81
+ expect(resource).toBeDefined();
82
+ expect(resource.resourceType).toBe(expectedType);
83
+ expect(resource.id).toBeDefined();
84
+ }
85
+ /**
86
+ * Validate FHIR Bundle structure
87
+ */
88
+ static validateFhirBundle(bundle) {
89
+ expect(bundle).toBeDefined();
90
+ expect(bundle.resourceType).toBe('Bundle');
91
+ expect(bundle.type).toBeDefined();
92
+ expect(['searchset', 'collection', 'document', 'message', 'transaction', 'transaction-response', 'batch', 'batch-response', 'history'].includes(bundle.type)).toBe(true);
93
+ }
94
+ /**
95
+ * Wait for a condition to be met (useful for async operations)
96
+ */
97
+ static waitFor(condition_1) {
98
+ return __awaiter(this, arguments, void 0, function* (condition, timeout = 5000) {
99
+ const start = Date.now();
100
+ while (Date.now() - start < timeout) {
101
+ if (yield condition()) {
102
+ return;
103
+ }
104
+ yield new Promise(resolve => setTimeout(resolve, 100));
105
+ }
106
+ throw new Error(`Condition not met within ${timeout}ms`);
107
+ });
108
+ }
109
+ /**
110
+ * Retry a function with exponential backoff
111
+ */
112
+ static retry(fn_1) {
113
+ return __awaiter(this, arguments, void 0, function* (fn, maxAttempts = 3, initialDelay = 1000) {
114
+ let lastError;
115
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
116
+ try {
117
+ return yield fn();
118
+ }
119
+ catch (error) {
120
+ lastError = error;
121
+ if (attempt === maxAttempts) {
122
+ throw lastError;
123
+ }
124
+ const delay = initialDelay * Math.pow(2, attempt - 1);
125
+ yield new Promise(resolve => setTimeout(resolve, delay));
126
+ }
127
+ }
128
+ throw lastError;
129
+ });
130
+ }
131
+ /**
132
+ * Check if the FHIR server is available
133
+ */
134
+ static checkServerAvailability() {
135
+ return __awaiter(this, void 0, void 0, function* () {
136
+ try {
137
+ const axiosInstance = this.getAxiosInstance();
138
+ const response = yield axiosInstance.get(`${this.FHIR_BASE_URL}/metadata`, { timeout: 5000 });
139
+ return response.status === 200 && response.data.resourceType === 'CapabilityStatement';
140
+ }
141
+ catch (error) {
142
+ return false;
143
+ }
144
+ });
145
+ }
146
+ /**
147
+ * Get server capability statement
148
+ */
149
+ static getServerCapabilities() {
150
+ return __awaiter(this, void 0, void 0, function* () {
151
+ const axiosInstance = this.getAxiosInstance();
152
+ const response = yield axiosInstance.get(`${this.FHIR_BASE_URL}/metadata?_format=json`);
153
+ return response.data;
154
+ });
155
+ }
156
+ /**
157
+ * Clean up test data (if the server supports it)
158
+ */
159
+ /**
160
+ * Clean up test data (placeholder - HAPI test server doesn't support DELETE)
161
+ */
162
+ static cleanupTestData(resourceType, identifiers) {
163
+ return __awaiter(this, void 0, void 0, function* () {
164
+ // Note: HAPI FHIR test server typically doesn't allow DELETE operations
165
+ // This is a placeholder for when testing against a server that does support cleanup
166
+ const axiosInstance = this.getAxiosInstance();
167
+ for (const id of identifiers) {
168
+ try {
169
+ yield axiosInstance.delete(`${this.FHIR_BASE_URL}/${resourceType}/${id}`);
170
+ }
171
+ catch (error) {
172
+ // Ignore errors during cleanup as test servers may not support DELETE
173
+ console.warn(`Could not delete ${resourceType}/${id}:`, error);
174
+ }
175
+ }
176
+ });
177
+ }
178
+ /**
179
+ * Generate test data patterns
180
+ */
181
+ static getTestPatterns() {
182
+ return {
183
+ // Common search patterns to test
184
+ searchPatterns: [
185
+ { params: { [FhirTestConfig.SEARCH_PARAMS.COUNT]: 5 } },
186
+ { params: { [FhirTestConfig.SEARCH_PARAMS.COUNT]: 1 } },
187
+ { params: { [FhirTestConfig.SEARCH_PARAMS.COUNT]: 10, [FhirTestConfig.SEARCH_PARAMS.SORT]: 'name' } },
188
+ ],
189
+ // Resource type combinations for mixed bundles
190
+ resourceCombinations: [
191
+ [FhirTestConfig.RESOURCE_TYPES.PATIENT, FhirTestConfig.RESOURCE_TYPES.ENCOUNTER],
192
+ [FhirTestConfig.RESOURCE_TYPES.PRACTITIONER, FhirTestConfig.RESOURCE_TYPES.ORGANIZATION],
193
+ [FhirTestConfig.RESOURCE_TYPES.PATIENT, FhirTestConfig.RESOURCE_TYPES.OBSERVATION],
194
+ ],
195
+ // Error scenarios to test
196
+ errorScenarios: [
197
+ { url: `${FhirTestConfig.FHIR_BASE_URL}/Patient/non-existent-id-123456`, expectedStatus: 404 },
198
+ { url: `${FhirTestConfig.FHIR_BASE_URL}/InvalidResourceType`, expectedStatus: 404 },
199
+ ]
200
+ };
201
+ }
202
+ }
203
+ FhirTestConfig.FHIR_BASE_URL = 'http://hapi.fhir.org/baseR4';
204
+ FhirTestConfig.TEST_TIMEOUT = 30000;
205
+ /**
206
+ * Common FHIR resource types for testing
207
+ */
208
+ FhirTestConfig.RESOURCE_TYPES = {
209
+ PATIENT: 'Patient',
210
+ PRACTITIONER: 'Practitioner',
211
+ ORGANIZATION: 'Organization',
212
+ ENCOUNTER: 'Encounter',
213
+ OBSERVATION: 'Observation',
214
+ CONDITION: 'Condition',
215
+ MEDICATION_REQUEST: 'MedicationRequest',
216
+ PROCEDURE: 'Procedure',
217
+ LOCATION: 'Location',
218
+ APPOINTMENT: 'Appointment',
219
+ CARE_TEAM: 'CareTeam',
220
+ CARE_PLAN: 'CarePlan',
221
+ IMMUNIZATION: 'Immunization',
222
+ ALLERGY_INTOLERANCE: 'AllergyIntolerance',
223
+ DIAGNOSTIC_REPORT: 'DiagnosticReport'
224
+ };
225
+ /**
226
+ * Common search parameters for testing
227
+ */
228
+ FhirTestConfig.SEARCH_PARAMS = {
229
+ COUNT: '_count',
230
+ FORMAT: '_format',
231
+ INCLUDE: '_include',
232
+ SORT: '_sort',
233
+ TEXT: '_text'
234
+ };
235
+ /**
236
+ * Test utilities for performance monitoring
237
+ */
238
+ export class FhirTestPerformance {
239
+ static startMeasurement(name) {
240
+ const start = performance.now();
241
+ return () => {
242
+ const duration = performance.now() - start;
243
+ this.recordMeasurement(name, duration);
244
+ return duration;
245
+ };
246
+ }
247
+ static recordMeasurement(name, duration) {
248
+ if (!this.measurements.has(name)) {
249
+ this.measurements.set(name, []);
250
+ }
251
+ this.measurements.get(name).push(duration);
252
+ }
253
+ static getStatistics(name) {
254
+ const measurements = this.measurements.get(name);
255
+ if (!measurements || measurements.length === 0) {
256
+ return null;
257
+ }
258
+ const avg = measurements.reduce((sum, val) => sum + val, 0) / measurements.length;
259
+ const min = Math.min(...measurements);
260
+ const max = Math.max(...measurements);
261
+ return { avg, min, max, count: measurements.length };
262
+ }
263
+ static reset() {
264
+ this.measurements.clear();
265
+ }
266
+ static logStatistics() {
267
+ for (const [name, measurements] of this.measurements.entries()) {
268
+ const stats = this.getStatistics(name);
269
+ if (stats) {
270
+ console.log(`${name}: avg=${stats.avg.toFixed(2)}ms, min=${stats.min.toFixed(2)}ms, max=${stats.max.toFixed(2)}ms, count=${stats.count}`);
271
+ }
272
+ }
273
+ }
274
+ }
275
+ FhirTestPerformance.measurements = new Map();
276
+ //# sourceMappingURL=fhir-test-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fhir-test-config.js","sourceRoot":"","sources":["../../../../../../../libs/isomorphic/fhir/src/lib/functions/fhir-test-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { IFhirBundle } from '../interfaces/fhir-resources.interface';
2
+ import { INormalizedFhirData } from '../interfaces/fhir-normalized-tables.interface';
3
+ export declare function normalizeFhirBundle(bundle: IFhirBundle): INormalizedFhirData;