@metriport/fhir-sdk 1.2.5

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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +124 -0
  3. package/dist/__tests__/env-setup.d.ts +2 -0
  4. package/dist/__tests__/env-setup.d.ts.map +1 -0
  5. package/dist/__tests__/env-setup.js +37 -0
  6. package/dist/__tests__/env-setup.js.map +1 -0
  7. package/dist/__tests__/fhir-bundle-sdk-basic.test.d.ts +2 -0
  8. package/dist/__tests__/fhir-bundle-sdk-basic.test.d.ts.map +1 -0
  9. package/dist/__tests__/fhir-bundle-sdk-basic.test.js +19 -0
  10. package/dist/__tests__/fhir-bundle-sdk-basic.test.js.map +1 -0
  11. package/dist/__tests__/fhir-bundle-sdk.test.d.ts +2 -0
  12. package/dist/__tests__/fhir-bundle-sdk.test.d.ts.map +1 -0
  13. package/dist/__tests__/fhir-bundle-sdk.test.js +433 -0
  14. package/dist/__tests__/fhir-bundle-sdk.test.js.map +1 -0
  15. package/dist/__tests__/fixtures/fhir-bundles.d.ts +31 -0
  16. package/dist/__tests__/fixtures/fhir-bundles.d.ts.map +1 -0
  17. package/dist/__tests__/fixtures/fhir-bundles.js +369 -0
  18. package/dist/__tests__/fixtures/fhir-bundles.js.map +1 -0
  19. package/dist/__tests__/phase1-verification.test.d.ts +2 -0
  20. package/dist/__tests__/phase1-verification.test.d.ts.map +1 -0
  21. package/dist/__tests__/phase1-verification.test.js +141 -0
  22. package/dist/__tests__/phase1-verification.test.js.map +1 -0
  23. package/dist/__tests__/phase2-verification.test.d.ts +2 -0
  24. package/dist/__tests__/phase2-verification.test.d.ts.map +1 -0
  25. package/dist/__tests__/phase2-verification.test.js +234 -0
  26. package/dist/__tests__/phase2-verification.test.js.map +1 -0
  27. package/dist/__tests__/phase3-verification.test.d.ts +2 -0
  28. package/dist/__tests__/phase3-verification.test.d.ts.map +1 -0
  29. package/dist/__tests__/phase3-verification.test.js +121 -0
  30. package/dist/__tests__/phase3-verification.test.js.map +1 -0
  31. package/dist/__tests__/phase4-verification.test.d.ts +2 -0
  32. package/dist/__tests__/phase4-verification.test.d.ts.map +1 -0
  33. package/dist/__tests__/phase4-verification.test.js +168 -0
  34. package/dist/__tests__/phase4-verification.test.js.map +1 -0
  35. package/dist/__tests__/phase5-verification.test.d.ts +2 -0
  36. package/dist/__tests__/phase5-verification.test.d.ts.map +1 -0
  37. package/dist/__tests__/phase5-verification.test.js +200 -0
  38. package/dist/__tests__/phase5-verification.test.js.map +1 -0
  39. package/dist/index.d.ts +245 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +681 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/types/smart-resources.d.ts +219 -0
  44. package/dist/types/smart-resources.d.ts.map +1 -0
  45. package/dist/types/smart-resources.js +140 -0
  46. package/dist/types/smart-resources.js.map +1 -0
  47. package/package.json +69 -0
package/dist/index.js ADDED
@@ -0,0 +1,681 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FhirBundleSdk = void 0;
4
+ const smart_resources_1 = require("./types/smart-resources");
5
+ function getResourceIdentifier(entry) {
6
+ if (entry.resource?.id) {
7
+ return entry.resource.id;
8
+ }
9
+ if (entry.fullUrl) {
10
+ return entry.fullUrl;
11
+ }
12
+ return undefined;
13
+ }
14
+ /**
15
+ * FHIR Bundle SDK for parsing, querying, and manipulating FHIR bundles with reference resolution
16
+ */
17
+ class FhirBundleSdk {
18
+ constructor(bundle) {
19
+ this.resourcesById = new Map();
20
+ this.resourcesByFullUrl = new Map();
21
+ this.resourcesByType = new Map();
22
+ // Smart resource caching to maintain object identity
23
+ this.smartResourceCache = new WeakMap();
24
+ // Array caching for type-specific getters to maintain reference identity
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ this.smartResourceArrayCache = new Map();
27
+ // Circular reference protection
28
+ this.resolutionStack = new Set();
29
+ // FR-1.1, FR-1.4: Initialize bundle and create indexes
30
+ this.bundle = bundle;
31
+ this.bundle.total = bundle.entry?.length ?? 0;
32
+ this.buildResourceIndexes();
33
+ }
34
+ get total() {
35
+ if (!this.bundle.entry) {
36
+ throw new Error("No valid total - bundle property `entry` is undefined");
37
+ }
38
+ return this.bundle.entry.length;
39
+ }
40
+ get entry() {
41
+ if (!this.bundle.entry) {
42
+ console.error("Bundle property `entry` is undefined");
43
+ return [];
44
+ }
45
+ return this.bundle.entry;
46
+ }
47
+ toObject() {
48
+ return this.bundle;
49
+ }
50
+ /**
51
+ * Create a new FhirBundleSdk instance (async for backwards compatibility)
52
+ * FR-1.2: Validate bundle resourceType
53
+ */
54
+ static async create(bundle) {
55
+ return FhirBundleSdk.createSync(bundle);
56
+ }
57
+ /**
58
+ * Create a new FhirBundleSdk instance synchronously
59
+ * FR-1.2: Validate bundle resourceType
60
+ */
61
+ static createSync(bundle) {
62
+ // FR-1.2: Validate bundle resourceType
63
+ if (bundle.resourceType !== "Bundle") {
64
+ throw new Error("Invalid bundle: resourceType must be 'Bundle'");
65
+ }
66
+ return new FhirBundleSdk(bundle);
67
+ }
68
+ /**
69
+ * Build O(1) indexes for resource lookup
70
+ */
71
+ buildResourceIndexes() {
72
+ if (!this.bundle.entry) {
73
+ return;
74
+ }
75
+ for (const entry of this.bundle.entry) {
76
+ if (!entry.resource) {
77
+ continue;
78
+ }
79
+ const resource = entry.resource;
80
+ // Index by resource.id if it exists
81
+ if (resource.id) {
82
+ this.resourcesById.set(resource.id, resource);
83
+ }
84
+ // Index by fullUrl if it exists
85
+ if (entry.fullUrl) {
86
+ this.resourcesByFullUrl.set(entry.fullUrl, resource);
87
+ }
88
+ // Index by resource type for type-specific getters
89
+ const resourceType = resource.resourceType;
90
+ if (!this.resourcesByType.has(resourceType)) {
91
+ this.resourcesByType.set(resourceType, []);
92
+ }
93
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
94
+ this.resourcesByType.get(resourceType).push(resource);
95
+ }
96
+ }
97
+ /**
98
+ * Create a smart resource with reference resolution methods
99
+ * FR-5.1: Resources returned by SDK have additional getter methods for each Reference field
100
+ * FR-5.7: Reference resolution operates in O(1) time complexity per reference
101
+ * FR-5.8: Original reference fields remain unchanged
102
+ */
103
+ createSmartResource(resource) {
104
+ // Check cache first to maintain object identity
105
+ const cached = this.smartResourceCache.get(resource);
106
+ if (cached) {
107
+ return cached;
108
+ }
109
+ const smartResource = new Proxy(resource, {
110
+ get: (target, prop, receiver) => {
111
+ // Handle the smart resource marker
112
+ if (prop === "__isSmartResource") {
113
+ return true;
114
+ }
115
+ // Check if this is a reference method call
116
+ if (typeof prop === "string" && (0, smart_resources_1.isReferenceMethod)(prop, target.resourceType)) {
117
+ return () => this.resolveReference(prop, target);
118
+ }
119
+ // Return original property
120
+ return Reflect.get(target, prop, receiver);
121
+ },
122
+ // Ensure JSON serialization works correctly (FR-5.8)
123
+ ownKeys: target => {
124
+ return Reflect.ownKeys(target).filter(key => key !== "__isSmartResource");
125
+ },
126
+ getOwnPropertyDescriptor: (target, prop) => {
127
+ if (prop === "__isSmartResource") {
128
+ return undefined;
129
+ }
130
+ return Reflect.getOwnPropertyDescriptor(target, prop);
131
+ },
132
+ });
133
+ // Cache the smart resource
134
+ this.smartResourceCache.set(resource, smartResource);
135
+ return smartResource;
136
+ }
137
+ /**
138
+ * Resolve a reference method call to actual resources
139
+ * FR-5.2-5.6: Handle different reference types and patterns
140
+ */
141
+ resolveReference(methodName, resource) {
142
+ const referenceField = (0, smart_resources_1.getReferenceField)(methodName, resource.resourceType);
143
+ if (!referenceField) {
144
+ return undefined;
145
+ }
146
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
147
+ const referenceValue = resource[referenceField];
148
+ if (!referenceValue) {
149
+ // FR-5.6: Return appropriate empty value for missing references
150
+ return this.isArrayReferenceField(referenceField, resource.resourceType) ? [] : undefined;
151
+ }
152
+ // Handle array references
153
+ if (Array.isArray(referenceValue)) {
154
+ const resolvedResources = [];
155
+ for (const ref of referenceValue) {
156
+ const resolved = this.resolveReferenceObject(ref);
157
+ if (resolved) {
158
+ resolvedResources.push(this.createSmartResource(resolved));
159
+ }
160
+ }
161
+ return resolvedResources;
162
+ }
163
+ // Handle single reference - we know it's not an array at this point
164
+ const resolved = this.resolveReferenceObject(referenceValue);
165
+ if (resolved) {
166
+ // Type assertion is safe here because we've established this is the single reference path
167
+ return this.createSmartResource(resolved);
168
+ }
169
+ return undefined;
170
+ }
171
+ /**
172
+ * Resolve a single reference object to a resource
173
+ * FR-5.5: Reference resolution methods handle both resource.id and fullUrl matching
174
+ */
175
+ resolveReferenceObject(referenceObj) {
176
+ if (!referenceObj || typeof referenceObj !== "object" || !("reference" in referenceObj)) {
177
+ return undefined;
178
+ }
179
+ const reference = referenceObj.reference;
180
+ // Circular reference protection
181
+ if (this.resolutionStack.has(reference)) {
182
+ return undefined;
183
+ }
184
+ this.resolutionStack.add(reference);
185
+ try {
186
+ // Try to resolve by resource ID (e.g., "Patient/123")
187
+ if (reference.includes("/")) {
188
+ const [, resourceId] = reference.split("/");
189
+ if (resourceId && this.resourcesById.has(resourceId)) {
190
+ return this.resourcesById.get(resourceId);
191
+ }
192
+ }
193
+ // Try to resolve by fullUrl (e.g., "urn:uuid:123")
194
+ if (this.resourcesByFullUrl.has(reference)) {
195
+ return this.resourcesByFullUrl.get(reference);
196
+ }
197
+ return undefined;
198
+ }
199
+ finally {
200
+ this.resolutionStack.delete(reference);
201
+ }
202
+ }
203
+ /**
204
+ * Check if a reference field expects an array of references
205
+ */
206
+ isArrayReferenceField(fieldName, resourceType) {
207
+ // Known array reference fields
208
+ const arrayFields = new Set(["performer", "participant", "result", "generalPractitioner"]);
209
+ return arrayFields.has(fieldName);
210
+ }
211
+ /**
212
+ * Find all Reference fields in a resource recursively
213
+ */
214
+ findAllReferences(resource) {
215
+ const references = [];
216
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
217
+ function searchObject(obj, path = "") {
218
+ if (!obj || typeof obj !== "object") {
219
+ return;
220
+ }
221
+ // Check if this object is a Reference
222
+ if (obj.reference && typeof obj.reference === "string") {
223
+ references.push({
224
+ field: path || "reference",
225
+ reference: obj.reference,
226
+ });
227
+ return;
228
+ }
229
+ // Recursively search object properties
230
+ for (const [key, value] of Object.entries(obj)) {
231
+ const currentPath = path ? `${path}.${key}` : key;
232
+ if (Array.isArray(value)) {
233
+ value.forEach((item, index) => {
234
+ searchObject(item, `${currentPath}[${index}]`);
235
+ });
236
+ }
237
+ else if (value && typeof value === "object") {
238
+ searchObject(value, currentPath);
239
+ }
240
+ }
241
+ }
242
+ searchObject(resource);
243
+ return references;
244
+ }
245
+ /**
246
+ * Check if a reference can be resolved within the bundle
247
+ */
248
+ canResolveReference(reference) {
249
+ // Try to resolve by resource ID (e.g., "Patient/123")
250
+ if (reference.includes("/")) {
251
+ const [, resourceId] = reference.split("/");
252
+ if (resourceId && this.resourcesById.has(resourceId)) {
253
+ return true;
254
+ }
255
+ }
256
+ // Try to resolve by fullUrl (e.g., "urn:uuid:123")
257
+ if (this.resourcesByFullUrl.has(reference)) {
258
+ return true;
259
+ }
260
+ return false;
261
+ }
262
+ /**
263
+ * FR-2.1: Validate all references in the bundle
264
+ * FR-2.2: Identifies references by Resource/id pattern and fullUrl references
265
+ * FR-2.3: Handles both relative and absolute references
266
+ * FR-2.4: Returns validation result with broken reference details
267
+ */
268
+ lookForBrokenReferences() {
269
+ const brokenReferences = [];
270
+ if (!this.bundle.entry) {
271
+ return { hasBrokenReferences: false, brokenReferences: [] };
272
+ }
273
+ for (const entry of this.bundle.entry) {
274
+ if (!entry.resource) {
275
+ continue;
276
+ }
277
+ const resource = entry.resource;
278
+ const resourceReferences = this.findAllReferences(resource);
279
+ for (const { field, reference } of resourceReferences) {
280
+ if (!this.canResolveReference(reference)) {
281
+ brokenReferences.push({
282
+ sourceResourceId: resource.id || entry.fullUrl || "unknown",
283
+ sourceResourceType: resource.resourceType,
284
+ referenceField: field,
285
+ reference: reference,
286
+ });
287
+ }
288
+ }
289
+ }
290
+ return {
291
+ hasBrokenReferences: brokenReferences.length > 0,
292
+ brokenReferences: brokenReferences,
293
+ };
294
+ }
295
+ /**
296
+ * FR-3.1: Get resource by ID with type parameter support
297
+ * FR-3.2: Method searches both resource.id and entry.fullUrl for matches
298
+ * FR-3.4: Method returns undefined if resource not found
299
+ * FR-3.5: Lookup operates in O(1) time complexity
300
+ * FR-5.1: Returns smart resource with reference resolution methods
301
+ */
302
+ getResourceById(id) {
303
+ // First try to find by resource.id
304
+ const resourceById = this.resourcesById.get(id);
305
+ if (resourceById) {
306
+ return this.createSmartResource(resourceById);
307
+ }
308
+ // Then try to find by fullUrl
309
+ const resourceByFullUrl = this.resourcesByFullUrl.get(id);
310
+ if (resourceByFullUrl) {
311
+ return this.createSmartResource(resourceByFullUrl);
312
+ }
313
+ // Return undefined if not found (FR-3.4)
314
+ return undefined;
315
+ }
316
+ /**
317
+ * Generic helper method to get a resource by ID with type validation
318
+ */
319
+ getResourceByIdAndType(id, resourceType) {
320
+ const resource = this.getResourceById(id);
321
+ if (resource && resource.resourceType === resourceType) {
322
+ return resource;
323
+ }
324
+ return undefined;
325
+ }
326
+ /**
327
+ * Generic helper method to get all resources of a specific type
328
+ * FR-10.1: Returns references to cached objects, not copies
329
+ */
330
+ getResourcesByType(resourceType) {
331
+ // Check cache first to maintain array reference identity
332
+ const cached = this.smartResourceArrayCache.get(resourceType);
333
+ if (cached) {
334
+ return cached;
335
+ }
336
+ const resources = (this.resourcesByType.get(resourceType) || []);
337
+ const smartResources = resources.map(resource => this.createSmartResource(resource));
338
+ // Cache the array to maintain reference identity
339
+ this.smartResourceArrayCache.set(resourceType, smartResources);
340
+ return smartResources;
341
+ }
342
+ /**
343
+ * Create a new bundle entry from an existing entry, preserving fullUrl
344
+ */
345
+ createBundleEntry(originalEntry, resource) {
346
+ if (originalEntry.fullUrl) {
347
+ return {
348
+ fullUrl: originalEntry.fullUrl,
349
+ resource: resource,
350
+ };
351
+ }
352
+ return {
353
+ resource: resource,
354
+ };
355
+ }
356
+ /**
357
+ * Create a new bundle with specified entries, maintaining original metadata
358
+ */
359
+ createExportBundle(entries) {
360
+ const exportBundle = {
361
+ resourceType: "Bundle",
362
+ type: this.bundle.type || "collection",
363
+ total: entries.length,
364
+ entry: entries,
365
+ };
366
+ // Preserve original bundle metadata (FR-6.4)
367
+ if (this.bundle.id) {
368
+ exportBundle.id = this.bundle.id;
369
+ }
370
+ if (this.bundle.meta) {
371
+ exportBundle.meta = { ...this.bundle.meta };
372
+ }
373
+ if (this.bundle.identifier) {
374
+ exportBundle.identifier = this.bundle.identifier;
375
+ }
376
+ if (this.bundle.timestamp) {
377
+ exportBundle.timestamp = this.bundle.timestamp;
378
+ }
379
+ return exportBundle;
380
+ }
381
+ /**
382
+ * Find original bundle entry for a given resource
383
+ */
384
+ findOriginalEntry(resource) {
385
+ if (!this.bundle.entry) {
386
+ return undefined;
387
+ }
388
+ return this.bundle.entry.find(entry => entry.resource === resource || (entry.resource?.id && entry.resource.id === resource.id));
389
+ }
390
+ /**
391
+ * FR-6.1: Export subset of resources by their IDs
392
+ * FR-6.4: Exported bundles maintain original bundle metadata but update total count
393
+ * FR-6.5: Exported bundles include only resources that exist in the original bundle
394
+ * FR-6.6: Exported bundles preserve original entry.fullUrl values
395
+ */
396
+ exportSubset(resourceIds) {
397
+ const exportEntries = [];
398
+ for (const resourceId of resourceIds) {
399
+ const resource = this.getResourceById(resourceId);
400
+ if (resource) {
401
+ const originalEntry = this.findOriginalEntry(resource);
402
+ if (originalEntry) {
403
+ exportEntries.push(this.createBundleEntry(originalEntry, resource));
404
+ }
405
+ }
406
+ // FR-6.5: Silently skip resources that don't exist
407
+ }
408
+ return this.createExportBundle(exportEntries);
409
+ }
410
+ /**
411
+ * FR-6.2: Export all resources of a specific type
412
+ * FR-6.4: Exported bundles maintain original bundle metadata but update total count
413
+ * FR-6.6: Exported bundles preserve original entry.fullUrl values
414
+ */
415
+ exportByType(resourceType) {
416
+ const resources = this.resourcesByType.get(resourceType) || [];
417
+ const exportEntries = [];
418
+ for (const resource of resources) {
419
+ const originalEntry = this.findOriginalEntry(resource);
420
+ if (originalEntry) {
421
+ exportEntries.push(this.createBundleEntry(originalEntry, resource));
422
+ }
423
+ }
424
+ return this.createExportBundle(exportEntries);
425
+ }
426
+ /**
427
+ * FR-6.3: Export all resources of specified types
428
+ * FR-6.4: Exported bundles maintain original bundle metadata but update total count
429
+ * FR-6.6: Exported bundles preserve original entry.fullUrl values
430
+ */
431
+ exportByTypes(resourceTypes) {
432
+ const exportEntries = [];
433
+ for (const resourceType of resourceTypes) {
434
+ const resources = this.resourcesByType.get(resourceType) || [];
435
+ for (const resource of resources) {
436
+ const originalEntry = this.findOriginalEntry(resource);
437
+ if (originalEntry) {
438
+ exportEntries.push(this.createBundleEntry(originalEntry, resource));
439
+ }
440
+ }
441
+ }
442
+ return this.createExportBundle(exportEntries);
443
+ }
444
+ /**
445
+ * Concatenate entries from another FhirBundleSdk with this bundle
446
+ * Returns a new bundle with combined entries while preserving original metadata
447
+ */
448
+ async concatEntries(otherSdk) {
449
+ const currentEntries = this.bundle.entry || [];
450
+ const otherEntries = otherSdk.bundle.entry || [];
451
+ const combinedEntries = [...currentEntries, ...otherEntries];
452
+ const resultBundle = this.createExportBundle(combinedEntries);
453
+ return await FhirBundleSdk.create(resultBundle);
454
+ }
455
+ /**
456
+ * Diff this bundle with another bundle or FhirBundleSdk by comparing resource ids.
457
+ * Returns three FhirBundleSdk instances: common, baseOnly, parameterOnly.
458
+ */
459
+ async diff(other) {
460
+ const baseBundle = this.bundle;
461
+ const parameterBundle = other instanceof FhirBundleSdk ? other.bundle : other;
462
+ const commonEntries = [];
463
+ const baseOnlyEntries = [];
464
+ const parameterOnlyEntries = [];
465
+ // Create maps with resource identifiers (prefer resource.id, fallback to fullUrl)
466
+ const baseResourceIdentifiers = new Map();
467
+ const parameterResourceIdentifiers = new Map();
468
+ // Populate base bundle identifiers
469
+ for (const entry of baseBundle?.entry ?? []) {
470
+ const identifier = getResourceIdentifier(entry);
471
+ if (identifier) {
472
+ baseResourceIdentifiers.set(identifier, entry);
473
+ }
474
+ }
475
+ // Populate parameter bundle identifiers
476
+ for (const entry of parameterBundle?.entry ?? []) {
477
+ const identifier = getResourceIdentifier(entry);
478
+ if (identifier) {
479
+ parameterResourceIdentifiers.set(identifier, entry);
480
+ }
481
+ }
482
+ // Find common and base-only resources
483
+ for (const [identifier, entry] of baseResourceIdentifiers.entries()) {
484
+ if (parameterResourceIdentifiers.has(identifier)) {
485
+ commonEntries.push(entry);
486
+ }
487
+ else {
488
+ baseOnlyEntries.push(entry);
489
+ }
490
+ }
491
+ // Find parameter-only resources
492
+ for (const [identifier, entry] of parameterResourceIdentifiers.entries()) {
493
+ if (!baseResourceIdentifiers.has(identifier)) {
494
+ parameterOnlyEntries.push(entry);
495
+ }
496
+ }
497
+ return {
498
+ common: await FhirBundleSdk.create(this.createExportBundle(commonEntries)),
499
+ baseOnly: await FhirBundleSdk.create(this.createExportBundle(baseOnlyEntries)),
500
+ parameterOnly: await FhirBundleSdk.create(this.createExportBundle(parameterOnlyEntries)),
501
+ };
502
+ }
503
+ }
504
+ exports.FhirBundleSdk = FhirBundleSdk;
505
+ /**
506
+ * Configuration for dynamically generated resource getter methods.
507
+ *
508
+ * Each entry in this array automatically generates both single and collection getter methods.
509
+ *
510
+ * **Example:**
511
+ * ```typescript
512
+ * {
513
+ * resourceType: 'Patient',
514
+ * singleGetterMethodName: 'getPatientById',
515
+ * collectionGetterMethodName: 'getPatients'
516
+ * }
517
+ * ```
518
+ *
519
+ * **Generates the equivalent of:**
520
+ * ```typescript
521
+ * // Single resource getter
522
+ * getPatientById(id: string): Smart<Patient> | undefined {
523
+ * return this.getResourceByIdAndType<Patient>(id, 'Patient');
524
+ * }
525
+ *
526
+ * // Collection getter
527
+ * getPatients(): Smart<Patient>[] {
528
+ * return this.getResourcesByType<Patient>('Patient');
529
+ * }
530
+ * ```
531
+ *
532
+ * **Usage:**
533
+ * ```typescript
534
+ * const sdk = await FhirBundleSdk.create(bundle);
535
+ * const patient = sdk.getPatientById('patient-123'); // Smart<Patient> | undefined
536
+ * const allPatients = sdk.getPatients(); // Smart<Patient>[]
537
+ * ```
538
+ *
539
+ * To add a new resource type, simply add a new entry to this array and declare
540
+ * the corresponding method signatures in the class body.
541
+ */
542
+ FhirBundleSdk.RESOURCE_METHODS = [
543
+ {
544
+ resourceType: "Patient",
545
+ singleGetterMethodName: "getPatientById",
546
+ collectionGetterMethodName: "getPatients",
547
+ },
548
+ {
549
+ resourceType: "Observation",
550
+ singleGetterMethodName: "getObservationById",
551
+ collectionGetterMethodName: "getObservations",
552
+ },
553
+ {
554
+ resourceType: "Encounter",
555
+ singleGetterMethodName: "getEncounterById",
556
+ collectionGetterMethodName: "getEncounters",
557
+ },
558
+ {
559
+ resourceType: "AllergyIntolerance",
560
+ singleGetterMethodName: "getAllergyIntoleranceById",
561
+ collectionGetterMethodName: "getAllergyIntolerances",
562
+ },
563
+ {
564
+ resourceType: "Condition",
565
+ singleGetterMethodName: "getConditionById",
566
+ collectionGetterMethodName: "getConditions",
567
+ },
568
+ {
569
+ resourceType: "Organization",
570
+ singleGetterMethodName: "getOrganizationById",
571
+ collectionGetterMethodName: "getOrganizations",
572
+ },
573
+ {
574
+ resourceType: "Location",
575
+ singleGetterMethodName: "getLocationById",
576
+ collectionGetterMethodName: "getLocations",
577
+ },
578
+ {
579
+ resourceType: "Practitioner",
580
+ singleGetterMethodName: "getPractitionerById",
581
+ collectionGetterMethodName: "getPractitioners",
582
+ },
583
+ {
584
+ resourceType: "DiagnosticReport",
585
+ singleGetterMethodName: "getDiagnosticReportById",
586
+ collectionGetterMethodName: "getDiagnosticReports",
587
+ },
588
+ {
589
+ resourceType: "Composition",
590
+ singleGetterMethodName: "getCompositionById",
591
+ collectionGetterMethodName: "getCompositions",
592
+ },
593
+ {
594
+ resourceType: "Coverage",
595
+ singleGetterMethodName: "getCoverageById",
596
+ collectionGetterMethodName: "getCoverages",
597
+ },
598
+ {
599
+ resourceType: "DocumentReference",
600
+ singleGetterMethodName: "getDocumentReferenceById",
601
+ collectionGetterMethodName: "getDocumentReferences",
602
+ },
603
+ {
604
+ resourceType: "Immunization",
605
+ singleGetterMethodName: "getImmunizationById",
606
+ collectionGetterMethodName: "getImmunizations",
607
+ },
608
+ {
609
+ resourceType: "Medication",
610
+ singleGetterMethodName: "getMedicationById",
611
+ collectionGetterMethodName: "getMedications",
612
+ },
613
+ {
614
+ resourceType: "MedicationRequest",
615
+ singleGetterMethodName: "getMedicationRequestById",
616
+ collectionGetterMethodName: "getMedicationRequests",
617
+ },
618
+ {
619
+ resourceType: "Procedure",
620
+ singleGetterMethodName: "getProcedureById",
621
+ collectionGetterMethodName: "getProcedures",
622
+ },
623
+ {
624
+ resourceType: "FamilyMemberHistory",
625
+ singleGetterMethodName: "getFamilyMemberHistoryById",
626
+ collectionGetterMethodName: "getFamilyMemberHistories",
627
+ },
628
+ {
629
+ resourceType: "MedicationAdministration",
630
+ singleGetterMethodName: "getMedicationAdministrationById",
631
+ collectionGetterMethodName: "getMedicationAdministrations",
632
+ },
633
+ {
634
+ resourceType: "MedicationDispense",
635
+ singleGetterMethodName: "getMedicationDispenseById",
636
+ collectionGetterMethodName: "getMedicationDispenses",
637
+ },
638
+ {
639
+ resourceType: "MedicationStatement",
640
+ singleGetterMethodName: "getMedicationStatementById",
641
+ collectionGetterMethodName: "getMedicationStatements",
642
+ },
643
+ {
644
+ resourceType: "RelatedPerson",
645
+ singleGetterMethodName: "getRelatedPersonById",
646
+ collectionGetterMethodName: "getRelatedPersons",
647
+ },
648
+ {
649
+ resourceType: "RiskAssessment",
650
+ singleGetterMethodName: "getRiskAssessmentById",
651
+ collectionGetterMethodName: "getRiskAssessments",
652
+ },
653
+ {
654
+ resourceType: "ServiceRequest",
655
+ singleGetterMethodName: "getServiceRequestById",
656
+ collectionGetterMethodName: "getServiceRequests",
657
+ },
658
+ ];
659
+ // Static initialization block to generate methods
660
+ (() => {
661
+ // Generate both single and collection getter methods from unified configuration
662
+ for (const { resourceType, singleGetterMethodName, collectionGetterMethodName, } of FhirBundleSdk.RESOURCE_METHODS) {
663
+ // Generate single resource getter (e.g., getPatientById)
664
+ Object.defineProperty(FhirBundleSdk.prototype, singleGetterMethodName, {
665
+ value: function (id) {
666
+ return this.getResourceByIdAndType(id, resourceType);
667
+ },
668
+ writable: false,
669
+ configurable: false,
670
+ });
671
+ // Generate collection getter (e.g., getPatients)
672
+ Object.defineProperty(FhirBundleSdk.prototype, collectionGetterMethodName, {
673
+ value: function () {
674
+ return this.getResourcesByType(resourceType);
675
+ },
676
+ writable: false,
677
+ configurable: false,
678
+ });
679
+ }
680
+ })();
681
+ //# sourceMappingURL=index.js.map