@medplum/core 2.0.22 → 2.0.23

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.
@@ -18,10 +18,11 @@ const functions = {
18
18
  * Returns true if the input collection is empty ({ }) and false otherwise.
19
19
  *
20
20
  * See: https://hl7.org/fhirpath/#empty-boolean
21
+ * @param _context The evaluation context.
21
22
  * @param input The input collection.
22
23
  * @returns True if the input collection is empty ({ }) and false otherwise.
23
24
  */
24
- empty: (input) => {
25
+ empty: (_context, input) => {
25
26
  return booleanToTypedValue(input.length === 0);
26
27
  },
27
28
  /**
@@ -34,13 +35,14 @@ const functions = {
34
35
  * for where(criteria).exists().
35
36
  *
36
37
  * See: https://hl7.org/fhirpath/#existscriteria-expression-boolean
38
+ * @param context The evaluation context.
37
39
  * @param input The input collection.
38
- * @param criteria Optional criteria applied to the collection.
40
+ * @param criteria The evaluation criteria.
39
41
  * @returns True if the collection has unknown elements, and false otherwise.
40
42
  */
41
- exists: (input, criteria) => {
43
+ exists: (context, input, criteria) => {
42
44
  if (criteria) {
43
- return booleanToTypedValue(input.filter((e) => toJsBoolean(criteria.eval([e]))).length > 0);
45
+ return booleanToTypedValue(input.filter((e) => toJsBoolean(criteria.eval(context, [e]))).length > 0);
44
46
  }
45
47
  else {
46
48
  return booleanToTypedValue(input.length > 0);
@@ -53,12 +55,13 @@ const functions = {
53
55
  * If the input collection is empty ({ }), the result is true.
54
56
  *
55
57
  * See: https://hl7.org/fhirpath/#allcriteria-expression-boolean
58
+ * @param context The evaluation context.
56
59
  * @param input The input collection.
57
60
  * @param criteria The evaluation criteria.
58
61
  * @returns True if for every element in the input collection, criteria evaluates to true.
59
62
  */
60
- all: (input, criteria) => {
61
- return booleanToTypedValue(input.every((e) => toJsBoolean(criteria.eval([e]))));
63
+ all: (context, input, criteria) => {
64
+ return booleanToTypedValue(input.every((e) => toJsBoolean(criteria.eval(context, [e]))));
62
65
  },
63
66
  /**
64
67
  * Takes a collection of Boolean values and returns true if all the items are true.
@@ -66,10 +69,11 @@ const functions = {
66
69
  * If the input is empty ({ }), the result is true.
67
70
  *
68
71
  * See: https://hl7.org/fhirpath/#alltrue-boolean
72
+ * @param _context The evaluation context.
69
73
  * @param input The input collection.
70
74
  * @returns True if all the items are true.
71
75
  */
72
- allTrue: (input) => {
76
+ allTrue: (_context, input) => {
73
77
  for (const value of input) {
74
78
  if (!value.value) {
75
79
  return booleanToTypedValue(false);
@@ -82,10 +86,11 @@ const functions = {
82
86
  * If all the items are false, or if the input is empty ({ }), the result is false.
83
87
  *
84
88
  * See: https://hl7.org/fhirpath/#anytrue-boolean
89
+ * @param _context The evaluation context.
85
90
  * @param input The input collection.
86
91
  * @returns True if unknown of the items are true.
87
92
  */
88
- anyTrue: (input) => {
93
+ anyTrue: (_context, input) => {
89
94
  for (const value of input) {
90
95
  if (value.value) {
91
96
  return booleanToTypedValue(true);
@@ -99,10 +104,11 @@ const functions = {
99
104
  * If the input is empty ({ }), the result is true.
100
105
  *
101
106
  * See: https://hl7.org/fhirpath/#allfalse-boolean
107
+ * @param _context The evaluation context.
102
108
  * @param input The input collection.
103
109
  * @returns True if all the items are false.
104
110
  */
105
- allFalse: (input) => {
111
+ allFalse: (_context, input) => {
106
112
  for (const value of input) {
107
113
  if (value.value) {
108
114
  return booleanToTypedValue(false);
@@ -115,10 +121,11 @@ const functions = {
115
121
  * If all the items are true, or if the input is empty ({ }), the result is false.
116
122
  *
117
123
  * See: https://hl7.org/fhirpath/#anyfalse-boolean
124
+ * @param _context The evaluation context.
118
125
  * @param input The input collection.
119
126
  * @returns True if for every element in the input collection, criteria evaluates to true.
120
127
  */
121
- anyFalse: (input) => {
128
+ anyFalse: (_context, input) => {
122
129
  for (const value of input) {
123
130
  if (!value.value) {
124
131
  return booleanToTypedValue(true);
@@ -155,10 +162,11 @@ const functions = {
155
162
  * Returns 0 when the input collection is empty.
156
163
  *
157
164
  * See: https://hl7.org/fhirpath/#count-integer
165
+ * @param _context The evaluation context.
158
166
  * @param input The input collection.
159
167
  * @returns The integer count of the number of items in the input collection.
160
168
  */
161
- count: (input) => {
169
+ count: (_context, input) => {
162
170
  return [{ type: PropertyType.integer, value: input.length }];
163
171
  },
164
172
  /**
@@ -172,10 +180,11 @@ const functions = {
172
180
  * preserved in the result.
173
181
  *
174
182
  * See: https://hl7.org/fhirpath/#distinct-collection
183
+ * @param _context The evaluation context.
175
184
  * @param input The input collection.
176
185
  * @returns The integer count of the number of items in the input collection.
177
186
  */
178
- distinct: (input) => {
187
+ distinct: (_context, input) => {
179
188
  const result = [];
180
189
  for (const value of input) {
181
190
  if (!result.some((e) => e.value === value.value)) {
@@ -190,11 +199,12 @@ const functions = {
190
199
  * as defined below.
191
200
  *
192
201
  * See: https://hl7.org/fhirpath/#isdistinct-boolean
202
+ * @param context The evaluation context.
193
203
  * @param input The input collection.
194
204
  * @returns The integer count of the number of items in the input collection.
195
205
  */
196
- isDistinct: (input) => {
197
- return booleanToTypedValue(input.length === functions.distinct(input).length);
206
+ isDistinct: (context, input) => {
207
+ return booleanToTypedValue(input.length === functions.distinct(context, input).length);
198
208
  },
199
209
  /*
200
210
  * 5.2 Filtering and projection
@@ -212,12 +222,13 @@ const functions = {
212
222
  * consistent with singleton evaluation of collections behavior.
213
223
  *
214
224
  * See: https://hl7.org/fhirpath/#wherecriteria-expression-collection
225
+ * @param context The evaluation context.
215
226
  * @param input The input collection.
216
227
  * @param criteria The condition atom.
217
228
  * @returns A collection containing only those elements in the input collection for which the stated criteria expression evaluates to true.
218
229
  */
219
- where: (input, criteria) => {
220
- return input.filter((e) => toJsBoolean(criteria.eval([e])));
230
+ where: (context, input, criteria) => {
231
+ return input.filter((e) => toJsBoolean(criteria.eval(context, [e])));
221
232
  },
222
233
  /**
223
234
  * Evaluates the projection expression for each item in the input collection.
@@ -229,12 +240,13 @@ const functions = {
229
240
  * the input collection is empty ({ }), the result is empty as well.
230
241
  *
231
242
  * See: http://hl7.org/fhirpath/#selectprojection-expression-collection
243
+ * @param context The evaluation context.
232
244
  * @param input The input collection.
233
245
  * @param criteria The condition atom.
234
246
  * @returns A collection containing only those elements in the input collection for which the stated criteria expression evaluates to true.
235
247
  */
236
- select: (input, criteria) => {
237
- return input.map((e) => criteria.eval([e])).flat();
248
+ select: (context, input, criteria) => {
249
+ return input.map((e) => criteria.eval(context, [e])).flat();
238
250
  },
239
251
  /**
240
252
  * A version of select that will repeat the projection and add it to the output
@@ -251,11 +263,12 @@ const functions = {
251
263
  * must resolve to the name of a type in a model
252
264
  *
253
265
  * See: http://hl7.org/fhirpath/#oftypetype-type-specifier-collection
266
+ * @param _context The evaluation context.
254
267
  * @param input The input collection.
255
268
  * @param criteria The condition atom.
256
269
  * @returns A collection containing only those elements in the input collection that are of the given type or a subclass thereof.
257
270
  */
258
- ofType: (input, criteria) => {
271
+ ofType: (_context, input, criteria) => {
259
272
  return input.filter((e) => e.type === criteria.name);
260
273
  },
261
274
  /*
@@ -269,10 +282,11 @@ const functions = {
269
282
  * about cardinality is violated at run-time.
270
283
  *
271
284
  * See: https://hl7.org/fhirpath/#single-collection
285
+ * @param _context The evaluation context.
272
286
  * @param input The input collection.
273
287
  * @returns The single item in the input if there is just one item.
274
288
  */
275
- single: (input) => {
289
+ single: (_context, input) => {
276
290
  if (input.length > 1) {
277
291
  throw new Error('Expected input length one for single()');
278
292
  }
@@ -283,10 +297,11 @@ const functions = {
283
297
  * This function is equivalent to item[0], so it will return an empty collection if the input collection has no items.
284
298
  *
285
299
  * See: https://hl7.org/fhirpath/#first-collection
300
+ * @param context The evaluation context.
286
301
  * @param input The input collection.
287
302
  * @returns A collection containing only the first item in the input collection.
288
303
  */
289
- first: (input) => {
304
+ first: (context, input) => {
290
305
  return input.length === 0 ? [] : input.slice(0, 1);
291
306
  },
292
307
  /**
@@ -294,10 +309,11 @@ const functions = {
294
309
  * Will return an empty collection if the input collection has no items.
295
310
  *
296
311
  * See: https://hl7.org/fhirpath/#last-collection
312
+ * @param context The evaluation context.
297
313
  * @param input The input collection.
298
314
  * @returns A collection containing only the last item in the input collection.
299
315
  */
300
- last: (input) => {
316
+ last: (context, input) => {
301
317
  return input.length === 0 ? [] : input.slice(input.length - 1, input.length);
302
318
  },
303
319
  /**
@@ -305,10 +321,11 @@ const functions = {
305
321
  * Will return an empty collection if the input collection has no items, or only one item.
306
322
  *
307
323
  * See: https://hl7.org/fhirpath/#tail-collection
324
+ * @param context The evaluation context.
308
325
  * @param input The input collection.
309
326
  * @returns A collection containing all but the first item in the input collection.
310
327
  */
311
- tail: (input) => {
328
+ tail: (context, input) => {
312
329
  return input.length === 0 ? [] : input.slice(1, input.length);
313
330
  },
314
331
  /**
@@ -318,12 +335,13 @@ const functions = {
318
335
  * If num is less than or equal to zero, the input collection is simply returned.
319
336
  *
320
337
  * See: https://hl7.org/fhirpath/#skipnum-integer-collection
338
+ * @param context The evaluation context.
321
339
  * @param input The input collection.
322
340
  * @param num The atom representing the number of elements to skip.
323
341
  * @returns A collection containing all but the first item in the input collection.
324
342
  */
325
- skip: (input, num) => {
326
- const numValue = num.eval(input)[0]?.value;
343
+ skip: (context, input, num) => {
344
+ const numValue = num.eval(context, input)[0]?.value;
327
345
  if (typeof numValue !== 'number') {
328
346
  throw new Error('Expected a number for skip(num)');
329
347
  }
@@ -342,12 +360,13 @@ const functions = {
342
360
  * take returns an empty collection.
343
361
  *
344
362
  * See: https://hl7.org/fhirpath/#takenum-integer-collection
363
+ * @param context The evaluation context.
345
364
  * @param input The input collection.
346
365
  * @param num The atom representing the number of elements to take.
347
366
  * @returns A collection containing the first num items in the input collection.
348
367
  */
349
- take: (input, num) => {
350
- const numValue = num.eval(input)[0]?.value;
368
+ take: (context, input, num) => {
369
+ const numValue = num.eval(context, input)[0]?.value;
351
370
  if (typeof numValue !== 'number') {
352
371
  throw new Error('Expected a number for take(num)');
353
372
  }
@@ -365,15 +384,16 @@ const functions = {
365
384
  * Order of items is not guaranteed to be preserved in the result of this function.
366
385
  *
367
386
  * See: http://hl7.org/fhirpath/#intersectother-collection-collection
387
+ * @param context The evaluation context.
368
388
  * @param input The input collection.
369
389
  * @param other The atom representing the collection of elements to intersect.
370
390
  * @returns A collection containing the elements that are in both collections.
371
391
  */
372
- intersect: (input, other) => {
392
+ intersect: (context, input, other) => {
373
393
  if (!other) {
374
394
  return input;
375
395
  }
376
- const otherArray = other.eval(input);
396
+ const otherArray = other.eval(context, input);
377
397
  const result = [];
378
398
  for (const value of input) {
379
399
  if (!result.some((e) => e.value === value.value) && otherArray.some((e) => e.value === value.value)) {
@@ -389,15 +409,16 @@ const functions = {
389
409
  * e.g. (1 | 2 | 3).exclude(2) returns (1 | 3).
390
410
  *
391
411
  * See: http://hl7.org/fhirpath/#excludeother-collection-collection
412
+ * @param context The evaluation context.
392
413
  * @param input The input collection.
393
414
  * @param other The atom representing the collection of elements to exclude.
394
415
  * @returns A collection containing the elements that are in the input collection but not the other collection.
395
416
  */
396
- exclude: (input, other) => {
417
+ exclude: (context, input, other) => {
397
418
  if (!other) {
398
419
  return input;
399
420
  }
400
- const otherArray = other.eval(input);
421
+ const otherArray = other.eval(context, input);
401
422
  const result = [];
402
423
  for (const value of input) {
403
424
  if (!otherArray.some((e) => e.value === value.value)) {
@@ -419,15 +440,16 @@ const functions = {
419
440
  * In other words, this function returns the distinct list of elements from both inputs.
420
441
  *
421
442
  * See: http://hl7.org/fhirpath/#unionother-collection
443
+ * @param context The evaluation context.
422
444
  * @param input The input collection.
423
445
  * @param other The atom representing the collection of elements to merge.
424
446
  * @returns A collection containing the elements that represent the union of both collections.
425
447
  */
426
- union: (input, other) => {
448
+ union: (context, input, other) => {
427
449
  if (!other) {
428
450
  return input;
429
451
  }
430
- const otherArray = other.eval(input);
452
+ const otherArray = other.eval(context, input);
431
453
  return removeDuplicates([...input, ...otherArray]);
432
454
  },
433
455
  /**
@@ -438,15 +460,16 @@ const functions = {
438
460
  * There is no expectation of order in the resulting collection.
439
461
  *
440
462
  * See: http://hl7.org/fhirpath/#combineother-collection-collection
463
+ * @param context The evaluation context.
441
464
  * @param input The input collection.
442
465
  * @param other The atom representing the collection of elements to merge.
443
466
  * @returns A collection containing the elements that represent the combination of both collections including duplicates.
444
467
  */
445
- combine: (input, other) => {
468
+ combine: (context, input, other) => {
446
469
  if (!other) {
447
470
  return input;
448
471
  }
449
- const otherArray = other.eval(input);
472
+ const otherArray = other.eval(context, input);
450
473
  return [...input, ...otherArray];
451
474
  },
452
475
  /*
@@ -469,22 +492,23 @@ const functions = {
469
492
  * true-result should only be evaluated if the criterion evaluates to true,
470
493
  * and otherwise-result should only be evaluated otherwise. For implementations,
471
494
  * this means delaying evaluation of the arguments.
495
+ * @param context The evaluation context.
472
496
  * @param input The input collection.
473
497
  * @param criterion The atom representing the conditional.
474
498
  * @param trueResult The atom to be used if the conditional evaluates to true.
475
499
  * @param otherwiseResult Optional atom to be used if the conditional evaluates to false.
476
500
  * @returns The result of the iif function.
477
501
  */
478
- iif: (input, criterion, trueResult, otherwiseResult) => {
479
- const evalResult = criterion.eval(input);
502
+ iif: (context, input, criterion, trueResult, otherwiseResult) => {
503
+ const evalResult = criterion.eval(context, input);
480
504
  if (evalResult.length > 1 || (evalResult.length === 1 && typeof evalResult[0].value !== 'boolean')) {
481
505
  throw new Error('Expected criterion to evaluate to a Boolean');
482
506
  }
483
507
  if (toJsBoolean(evalResult)) {
484
- return trueResult.eval(input);
508
+ return trueResult.eval(context, input);
485
509
  }
486
510
  if (otherwiseResult) {
487
- return otherwiseResult.eval(input);
511
+ return otherwiseResult.eval(context, input);
488
512
  }
489
513
  return [];
490
514
  },
@@ -500,10 +524,11 @@ const functions = {
500
524
  * If the item is not one the above types, or the item is a String, Integer, or Decimal, but is not equal to one of the possible values convertible to a Boolean, the result is empty.
501
525
  *
502
526
  * See: https://hl7.org/fhirpath/#toboolean-boolean
527
+ * @param _context The evaluation context.
503
528
  * @param input The input collection.
504
529
  * @returns The input converted to boolean value.
505
530
  */
506
- toBoolean: (input) => {
531
+ toBoolean: (_context, input) => {
507
532
  if (input.length === 0) {
508
533
  return [];
509
534
  }
@@ -543,14 +568,15 @@ const functions = {
543
568
  * If the input collection is empty, the result is empty.
544
569
  *
545
570
  * See: http://hl7.org/fhirpath/#convertstoboolean-boolean
571
+ * @param context The evaluation context.
546
572
  * @param input The input collection.
547
573
  * @returns True if the input can be converted to boolean.
548
574
  */
549
- convertsToBoolean: (input) => {
575
+ convertsToBoolean: (context, input) => {
550
576
  if (input.length === 0) {
551
577
  return [];
552
578
  }
553
- return booleanToTypedValue(functions.toBoolean(input).length === 1);
579
+ return booleanToTypedValue(functions.toBoolean(context, input).length === 1);
554
580
  },
555
581
  /**
556
582
  * Returns the integer representation of the input.
@@ -569,10 +595,11 @@ const functions = {
569
595
  * If the input collection is empty, the result is empty.
570
596
  *
571
597
  * See: https://hl7.org/fhirpath/#tointeger-integer
598
+ * @param _context The evaluation context.
572
599
  * @param input The input collection.
573
600
  * @returns The string representation of the input.
574
601
  */
575
- toInteger: (input) => {
602
+ toInteger: (_context, input) => {
576
603
  if (input.length === 0) {
577
604
  return [];
578
605
  }
@@ -602,14 +629,15 @@ const functions = {
602
629
  * If the input collection is empty, the result is empty.
603
630
  *
604
631
  * See: https://hl7.org/fhirpath/#convertstointeger-boolean
632
+ * @param context The evaluation context.
605
633
  * @param input The input collection.
606
634
  * @returns True if the input can be converted to an integer.
607
635
  */
608
- convertsToInteger: (input) => {
636
+ convertsToInteger: (context, input) => {
609
637
  if (input.length === 0) {
610
638
  return [];
611
639
  }
612
- return booleanToTypedValue(functions.toInteger(input).length === 1);
640
+ return booleanToTypedValue(functions.toInteger(context, input).length === 1);
613
641
  },
614
642
  /**
615
643
  * If the input collection contains a single item, this function will return a single date if:
@@ -626,10 +654,11 @@ const functions = {
626
654
  * If the input collection is empty, the result is empty.
627
655
  *
628
656
  * See: https://hl7.org/fhirpath/#todate-date
657
+ * @param _context The evaluation context.
629
658
  * @param input The input collection.
630
659
  * @returns The value converted to a date if possible; otherwise empty array.
631
660
  */
632
- toDate: (input) => {
661
+ toDate: (_context, input) => {
633
662
  if (input.length === 0) {
634
663
  return [];
635
664
  }
@@ -654,14 +683,15 @@ const functions = {
654
683
  * If the input collection is empty, the result is empty.
655
684
  *
656
685
  * See: https://hl7.org/fhirpath/#convertstodate-boolean
686
+ * @param context The evaluation context.
657
687
  * @param input The input collection.
658
688
  * @returns True if the item can be converted to a date.
659
689
  */
660
- convertsToDate: (input) => {
690
+ convertsToDate: (context, input) => {
661
691
  if (input.length === 0) {
662
692
  return [];
663
693
  }
664
- return booleanToTypedValue(functions.toDate(input).length === 1);
694
+ return booleanToTypedValue(functions.toDate(context, input).length === 1);
665
695
  },
666
696
  /**
667
697
  * If the input collection contains a single item, this function will return a single datetime if:
@@ -680,10 +710,11 @@ const functions = {
680
710
  * If the input collection is empty, the result is empty.
681
711
  *
682
712
  * See: https://hl7.org/fhirpath/#todatetime-datetime
713
+ * @param _context The evaluation context.
683
714
  * @param input The input collection.
684
- * @returns The value converted to a dateTime if possible; otherwise empty array.
715
+ * @returns The value converted to a datetime if possible; otherwise empty array.
685
716
  */
686
- toDateTime: (input) => {
717
+ toDateTime: (_context, input) => {
687
718
  if (input.length === 0) {
688
719
  return [];
689
720
  }
@@ -706,14 +737,15 @@ const functions = {
706
737
  * If the input collection is empty, the result is empty.
707
738
  *
708
739
  * See: https://hl7.org/fhirpath/#convertstodatetime-boolean
740
+ * @param context The evaluation context.
709
741
  * @param input The input collection.
710
742
  * @returns True if the item can be converted to a dateTime.
711
743
  */
712
- convertsToDateTime: (input) => {
744
+ convertsToDateTime: (context, input) => {
713
745
  if (input.length === 0) {
714
746
  return [];
715
747
  }
716
- return booleanToTypedValue(functions.toDateTime(input).length === 1);
748
+ return booleanToTypedValue(functions.toDateTime(context, input).length === 1);
717
749
  },
718
750
  /**
719
751
  * If the input collection contains a single item, this function will return a single decimal if:
@@ -729,10 +761,11 @@ const functions = {
729
761
  * If the input collection is empty, the result is empty.
730
762
  *
731
763
  * See: https://hl7.org/fhirpath/#decimal-conversion-functions
764
+ * @param _context The evaluation context.
732
765
  * @param input The input collection.
733
766
  * @returns The value converted to a decimal if possible; otherwise empty array.
734
767
  */
735
- toDecimal: (input) => {
768
+ toDecimal: (_context, input) => {
736
769
  if (input.length === 0) {
737
770
  return [];
738
771
  }
@@ -761,14 +794,15 @@ const functions = {
761
794
  * If the input collection is empty, the result is empty.
762
795
  *
763
796
  * See: https://hl7.org/fhirpath/#convertstodecimal-boolean
797
+ * @param context The evaluation context.
764
798
  * @param input The input collection.
765
- * @returns True if the item can be converted to a decimal.
799
+ * @returns The value converted to a decimal if possible; otherwise empty array.
766
800
  */
767
- convertsToDecimal: (input) => {
801
+ convertsToDecimal: (context, input) => {
768
802
  if (input.length === 0) {
769
803
  return [];
770
804
  }
771
- return booleanToTypedValue(functions.toDecimal(input).length === 1);
805
+ return booleanToTypedValue(functions.toDecimal(context, input).length === 1);
772
806
  },
773
807
  /**
774
808
  * If the input collection contains a single item, this function will return a single quantity if:
@@ -780,10 +814,11 @@ const functions = {
780
814
  * If the item is not one of the above types, the result is empty.
781
815
  *
782
816
  * See: https://hl7.org/fhirpath/#quantity-conversion-functions
817
+ * @param _context The evaluation context.
783
818
  * @param input The input collection.
784
819
  * @returns The value converted to a quantity if possible; otherwise empty array.
785
820
  */
786
- toQuantity: (input) => {
821
+ toQuantity: (_context, input) => {
787
822
  if (input.length === 0) {
788
823
  return [];
789
824
  }
@@ -821,14 +856,15 @@ const functions = {
821
856
  * If the unit argument is provided, it must be the string representation of a UCUM code (or a FHIRPath calendar duration keyword), and is used to determine whether the input quantity can be converted to the given unit, according to the unit conversion rules specified by UCUM. If the input quantity can be converted, the result is true, otherwise, the result is false.
822
857
  *
823
858
  * See: https://hl7.org/fhirpath/#convertstoquantityunit-string-boolean
859
+ * @param context The evaluation context.
824
860
  * @param input The input collection.
825
861
  * @returns True if the item can be converted to a quantity.
826
862
  */
827
- convertsToQuantity: (input) => {
863
+ convertsToQuantity: (context, input) => {
828
864
  if (input.length === 0) {
829
865
  return [];
830
866
  }
831
- return booleanToTypedValue(functions.toQuantity(input).length === 1);
867
+ return booleanToTypedValue(functions.toQuantity(context, input).length === 1);
832
868
  },
833
869
  /**
834
870
  * Returns the string representation of the input.
@@ -842,10 +878,11 @@ const functions = {
842
878
  * If the item is not one of the above types, the result is false.
843
879
  *
844
880
  * See: https://hl7.org/fhirpath/#tostring-string
881
+ * @param _context The evaluation context.
845
882
  * @param input The input collection.
846
883
  * @returns The string representation of the input.
847
884
  */
848
- toString: (input) => {
885
+ toString: (_context, input) => {
849
886
  if (input.length === 0) {
850
887
  return [];
851
888
  }
@@ -874,14 +911,15 @@ const functions = {
874
911
  * If the input collection is empty, the result is empty.
875
912
  *
876
913
  * See: https://hl7.org/fhirpath/#tostring-string
914
+ * @param context The evaluation context.
877
915
  * @param input The input collection.
878
916
  * @returns True if the item can be converted to a string
879
917
  */
880
- convertsToString: (input) => {
918
+ convertsToString: (context, input) => {
881
919
  if (input.length === 0) {
882
920
  return [];
883
921
  }
884
- return booleanToTypedValue(functions.toString(input).length === 1);
922
+ return booleanToTypedValue(functions.toString(context, input).length === 1);
885
923
  },
886
924
  /**
887
925
  * If the input collection contains a single item, this function will return a single time if:
@@ -899,10 +937,11 @@ const functions = {
899
937
  * If the input collection is empty, the result is empty.
900
938
  *
901
939
  * See: https://hl7.org/fhirpath/#totime-time
940
+ * @param _context The evaluation context.
902
941
  * @param input The input collection.
903
942
  * @returns The value converted to a time if possible; otherwise empty array.
904
943
  */
905
- toTime: (input) => {
944
+ toTime: (_context, input) => {
906
945
  if (input.length === 0) {
907
946
  return [];
908
947
  }
@@ -927,14 +966,15 @@ const functions = {
927
966
  * If the input collection is empty, the result is empty.
928
967
  *
929
968
  * See: https://hl7.org/fhirpath/#convertstotime-boolean
969
+ * @param context The evaluation context.
930
970
  * @param input The input collection.
931
971
  * @returns True if the item can be converted to a time.
932
972
  */
933
- convertsToTime: (input) => {
973
+ convertsToTime: (context, input) => {
934
974
  if (input.length === 0) {
935
975
  return [];
936
976
  }
937
- return booleanToTypedValue(functions.toTime(input).length === 1);
977
+ return booleanToTypedValue(functions.toTime(context, input).length === 1);
938
978
  },
939
979
  /*
940
980
  * 5.6. String Manipulation.
@@ -951,12 +991,13 @@ const functions = {
951
991
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
952
992
  *
953
993
  * See: https://hl7.org/fhirpath/#indexofsubstring-string-integer
994
+ * @param context The evaluation context.
954
995
  * @param input The input collection.
955
- * @param searchStringAtom The substring to search for.
996
+ * @param substringAtom The substring to search for.
956
997
  * @returns The index of the substring.
957
998
  */
958
- indexOf: (input, searchStringAtom) => {
959
- return applyStringFunc((str, substring) => str.indexOf(substring), input, searchStringAtom);
999
+ indexOf: (context, input, substringAtom) => {
1000
+ return applyStringFunc((str, substring) => str.indexOf(substring), context, input, substringAtom);
960
1001
  },
961
1002
  /**
962
1003
  * Returns the part of the string starting at position start (zero-based). If length is given, will return at most length number of characters from the input string.
@@ -968,17 +1009,18 @@ const functions = {
968
1009
  * If an empty length is provided, the behavior is the same as if length had not been provided.
969
1010
  *
970
1011
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1012
+ * @param context The evaluation context.
971
1013
  * @param input The input collection.
972
1014
  * @param startAtom The start index atom.
973
1015
  * @param lengthAtom Optional length atom.
974
1016
  * @returns The substring.
975
1017
  */
976
- substring: (input, startAtom, lengthAtom) => {
1018
+ substring: (context, input, startAtom, lengthAtom) => {
977
1019
  return applyStringFunc((str, start, length) => {
978
1020
  const startIndex = start;
979
1021
  const endIndex = length ? startIndex + length : str.length;
980
1022
  return startIndex < 0 || startIndex >= str.length ? undefined : str.substring(startIndex, endIndex);
981
- }, input, startAtom, lengthAtom);
1023
+ }, context, input, startAtom, lengthAtom);
982
1024
  },
983
1025
  /**
984
1026
  * Returns true when the input string starts with the given prefix.
@@ -990,12 +1032,13 @@ const functions = {
990
1032
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
991
1033
  *
992
1034
  * See: https://hl7.org/fhirpath/#startswithprefix-string-boolean
1035
+ * @param context The evaluation context.
993
1036
  * @param input The input collection.
994
1037
  * @param prefixAtom The prefix substring to test.
995
1038
  * @returns True if the input string starts with the given prefix string.
996
1039
  */
997
- startsWith: (input, prefixAtom) => {
998
- return applyStringFunc((str, prefix) => str.startsWith(prefix), input, prefixAtom);
1040
+ startsWith: (context, input, prefixAtom) => {
1041
+ return applyStringFunc((str, prefix) => str.startsWith(prefix), context, input, prefixAtom);
999
1042
  },
1000
1043
  /**
1001
1044
  * Returns true when the input string ends with the given suffix.
@@ -1007,12 +1050,13 @@ const functions = {
1007
1050
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1008
1051
  *
1009
1052
  * See: https://hl7.org/fhirpath/#endswithsuffix-string-boolean
1053
+ * @param context The evaluation context.
1010
1054
  * @param input The input collection.
1011
1055
  * @param suffixAtom The suffix substring to test.
1012
1056
  * @returns True if the input string ends with the given suffix string.
1013
1057
  */
1014
- endsWith: (input, suffixAtom) => {
1015
- return applyStringFunc((str, suffix) => str.endsWith(suffix), input, suffixAtom);
1058
+ endsWith: (context, input, suffixAtom) => {
1059
+ return applyStringFunc((str, suffix) => str.endsWith(suffix), context, input, suffixAtom);
1016
1060
  },
1017
1061
  /**
1018
1062
  * Returns true when the given substring is a substring of the input string.
@@ -1024,26 +1068,27 @@ const functions = {
1024
1068
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1025
1069
  *
1026
1070
  * See: https://hl7.org/fhirpath/#containssubstring-string-boolean
1071
+ * @param context The evaluation context.
1027
1072
  * @param input The input collection.
1028
1073
  * @param substringAtom The substring to test.
1029
1074
  * @returns True if the input string contains the given substring.
1030
1075
  */
1031
- contains: (input, substringAtom) => {
1032
- return applyStringFunc((str, substring) => str.includes(substring), input, substringAtom);
1076
+ contains: (context, input, substringAtom) => {
1077
+ return applyStringFunc((str, substring) => str.includes(substring), context, input, substringAtom);
1033
1078
  },
1034
1079
  /**
1035
1080
  * Returns the input string with all characters converted to upper case.
1036
- *
1037
1081
  * If the input collection is empty, the result is empty.
1038
1082
  *
1039
1083
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1040
1084
  *
1041
1085
  * See: https://hl7.org/fhirpath/#upper-string
1086
+ * @param context The evaluation context.
1042
1087
  * @param input The input collection.
1043
1088
  * @returns The string converted to upper case.
1044
1089
  */
1045
- upper: (input) => {
1046
- return applyStringFunc((str) => str.toUpperCase(), input);
1090
+ upper: (context, input) => {
1091
+ return applyStringFunc((str) => str.toUpperCase(), context, input);
1047
1092
  },
1048
1093
  /**
1049
1094
  * Returns the input string with all characters converted to lower case.
@@ -1053,11 +1098,12 @@ const functions = {
1053
1098
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1054
1099
  *
1055
1100
  * See: https://hl7.org/fhirpath/#lower-string
1101
+ * @param context The evaluation context.
1056
1102
  * @param input The input collection.
1057
1103
  * @returns The string converted to lower case.
1058
1104
  */
1059
- lower: (input) => {
1060
- return applyStringFunc((str) => str.toLowerCase(), input);
1105
+ lower: (context, input) => {
1106
+ return applyStringFunc((str) => str.toLowerCase(), context, input);
1061
1107
  },
1062
1108
  /**
1063
1109
  * Returns the input string with all instances of pattern replaced with substitution. If the substitution is the empty string (''),
@@ -1069,13 +1115,14 @@ const functions = {
1069
1115
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1070
1116
  *
1071
1117
  * See: https://hl7.org/fhirpath/#replacepattern-string-substitution-string-string
1118
+ * @param context The evaluation context.
1072
1119
  * @param input The input collection.
1073
1120
  * @param patternAtom The pattern to search for.
1074
1121
  * @param substitionAtom The substition to replace with.
1075
1122
  * @returns The string with all instances of the search pattern replaced with the substitution string.
1076
1123
  */
1077
- replace: (input, patternAtom, substitionAtom) => {
1078
- return applyStringFunc((str, pattern, substition) => str.replaceAll(pattern, substition), input, patternAtom, substitionAtom);
1124
+ replace: (context, input, patternAtom, substitionAtom) => {
1125
+ return applyStringFunc((str, pattern, substition) => str.replaceAll(pattern, substition), context, input, patternAtom, substitionAtom);
1079
1126
  },
1080
1127
  /**
1081
1128
  * Returns true when the value matches the given regular expression. Regular expressions should function consistently, regardless of any culture- and locale-specific settings in the environment, should be case-sensitive, use 'single line' mode and allow Unicode characters.
@@ -1085,12 +1132,13 @@ const functions = {
1085
1132
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1086
1133
  *
1087
1134
  * See: https://hl7.org/fhirpath/#matchesregex-string-boolean
1135
+ * @param context The evaluation context.
1088
1136
  * @param input The input collection.
1089
1137
  * @param regexAtom The regular expression atom.
1090
1138
  * @returns True if the input string matches the given regular expression.
1091
1139
  */
1092
- matches: (input, regexAtom) => {
1093
- return applyStringFunc((str, regex) => !!str.match(regex), input, regexAtom);
1140
+ matches: (context, input, regexAtom) => {
1141
+ return applyStringFunc((str, regex) => !!str.match(regex), context, input, regexAtom);
1094
1142
  },
1095
1143
  /**
1096
1144
  * Matches the input using the regular expression in regex and replaces each match with the substitution string. The substitution may refer to identified match groups in the regular expression.
@@ -1100,30 +1148,33 @@ const functions = {
1100
1148
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1101
1149
  *
1102
1150
  * See: https://hl7.org/fhirpath/#replacematchesregex-string-substitution-string-string
1151
+ * @param context The evaluation context.
1103
1152
  * @param input The input collection.
1104
1153
  * @param regexAtom The regular expression atom.
1105
1154
  * @param substitionAtom The substition to replace with.
1106
1155
  * @returns The string with all instances of the search pattern replaced with the substitution string.
1107
1156
  */
1108
- replaceMatches: (input, regexAtom, substitionAtom) => {
1109
- return applyStringFunc((str, pattern, substition) => str.replaceAll(pattern, substition), input, regexAtom, substitionAtom);
1157
+ replaceMatches: (context, input, regexAtom, substitionAtom) => {
1158
+ return applyStringFunc((str, pattern, substition) => str.replaceAll(pattern, substition), context, input, regexAtom, substitionAtom);
1110
1159
  },
1111
1160
  /**
1161
+ * @param context The evaluation context.
1112
1162
  * @param input The input collection.
1113
1163
  * @returns The index of the substring.
1114
1164
  */
1115
- length: (input) => {
1116
- return applyStringFunc((str) => str.length, input);
1165
+ length: (context, input) => {
1166
+ return applyStringFunc((str) => str.length, context, input);
1117
1167
  },
1118
1168
  /**
1119
1169
  * Returns the list of characters in the input string. If the input collection is empty ({ }), the result is empty.
1120
1170
  *
1121
1171
  * See: https://hl7.org/fhirpath/#tochars-collection
1172
+ * @param context The evaluation context.
1122
1173
  * @param input The input collection.
1123
1174
  * @returns Array of characters.
1124
1175
  */
1125
- toChars: (input) => {
1126
- return applyStringFunc((str) => (str ? str.split('') : undefined), input);
1176
+ toChars: (context, input) => {
1177
+ return applyStringFunc((str) => (str ? str.split('') : undefined), context, input);
1127
1178
  },
1128
1179
  /*
1129
1180
  * 5.7. Math
@@ -1136,11 +1187,12 @@ const functions = {
1136
1187
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1137
1188
  *
1138
1189
  * See: https://hl7.org/fhirpath/#abs-integer-decimal-quantity
1190
+ * @param context The evaluation context.
1139
1191
  * @param input The input collection.
1140
1192
  * @returns A collection containing the result.
1141
1193
  */
1142
- abs: (input) => {
1143
- return applyMathFunc(Math.abs, input);
1194
+ abs: (context, input) => {
1195
+ return applyMathFunc(Math.abs, context, input);
1144
1196
  },
1145
1197
  /**
1146
1198
  * Returns the first integer greater than or equal to the input.
@@ -1150,11 +1202,12 @@ const functions = {
1150
1202
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1151
1203
  *
1152
1204
  * See: https://hl7.org/fhirpath/#ceiling-integer
1205
+ * @param context The evaluation context.
1153
1206
  * @param input The input collection.
1154
1207
  * @returns A collection containing the result.
1155
1208
  */
1156
- ceiling: (input) => {
1157
- return applyMathFunc(Math.ceil, input);
1209
+ ceiling: (context, input) => {
1210
+ return applyMathFunc(Math.ceil, context, input);
1158
1211
  },
1159
1212
  /**
1160
1213
  * Returns e raised to the power of the input.
@@ -1166,11 +1219,12 @@ const functions = {
1166
1219
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1167
1220
  *
1168
1221
  * See: https://hl7.org/fhirpath/#exp-decimal
1222
+ * @param context The evaluation context.
1169
1223
  * @param input The input collection.
1170
1224
  * @returns A collection containing the result.
1171
1225
  */
1172
- exp: (input) => {
1173
- return applyMathFunc(Math.exp, input);
1226
+ exp: (context, input) => {
1227
+ return applyMathFunc(Math.exp, context, input);
1174
1228
  },
1175
1229
  /**
1176
1230
  * Returns the first integer less than or equal to the input.
@@ -1180,11 +1234,12 @@ const functions = {
1180
1234
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1181
1235
  *
1182
1236
  * See: https://hl7.org/fhirpath/#floor-integer
1237
+ * @param context The evaluation context.
1183
1238
  * @param input The input collection.
1184
1239
  * @returns A collection containing the result.
1185
1240
  */
1186
- floor: (input) => {
1187
- return applyMathFunc(Math.floor, input);
1241
+ floor: (context, input) => {
1242
+ return applyMathFunc(Math.floor, context, input);
1188
1243
  },
1189
1244
  /**
1190
1245
  * Returns the natural logarithm of the input (i.e. the logarithm base e).
@@ -1196,11 +1251,12 @@ const functions = {
1196
1251
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1197
1252
  *
1198
1253
  * See: https://hl7.org/fhirpath/#ln-decimal
1254
+ * @param context The evaluation context.
1199
1255
  * @param input The input collection.
1200
1256
  * @returns A collection containing the result.
1201
1257
  */
1202
- ln: (input) => {
1203
- return applyMathFunc(Math.log, input);
1258
+ ln: (context, input) => {
1259
+ return applyMathFunc(Math.log, context, input);
1204
1260
  },
1205
1261
  /**
1206
1262
  * Returns the logarithm base base of the input number.
@@ -1214,12 +1270,13 @@ const functions = {
1214
1270
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1215
1271
  *
1216
1272
  * See: https://hl7.org/fhirpath/#logbase-decimal-decimal
1273
+ * @param context The evaluation context.
1217
1274
  * @param input The input collection.
1218
1275
  * @param baseAtom The logarithm base.
1219
1276
  * @returns A collection containing the result.
1220
1277
  */
1221
- log: (input, baseAtom) => {
1222
- return applyMathFunc((value, base) => Math.log(value) / Math.log(base), input, baseAtom);
1278
+ log: (context, input, baseAtom) => {
1279
+ return applyMathFunc((value, base) => Math.log(value) / Math.log(base), context, input, baseAtom);
1223
1280
  },
1224
1281
  /**
1225
1282
  * Raises a number to the exponent power. If this function is used with Integers, the result is an Integer. If the function is used with Decimals, the result is a Decimal. If the function is used with a mixture of Integer and Decimal, the Integer is implicitly converted to a Decimal and the result is a Decimal.
@@ -1231,12 +1288,13 @@ const functions = {
1231
1288
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1232
1289
  *
1233
1290
  * See: https://hl7.org/fhirpath/#powerexponent-integer-decimal-integer-decimal
1291
+ * @param context The evaluation context.
1234
1292
  * @param input The input collection.
1235
1293
  * @param expAtom The exponent power.
1236
1294
  * @returns A collection containing the result.
1237
1295
  */
1238
- power: (input, expAtom) => {
1239
- return applyMathFunc(Math.pow, input, expAtom);
1296
+ power: (context, input, expAtom) => {
1297
+ return applyMathFunc(Math.pow, context, input, expAtom);
1240
1298
  },
1241
1299
  /**
1242
1300
  * Rounds the decimal to the nearest whole number using a traditional round (i.e. 0.5 or higher will round to 1). If specified, the precision argument determines the decimal place at which the rounding will occur. If not specified, the rounding will default to 0 decimal places.
@@ -1250,11 +1308,12 @@ const functions = {
1250
1308
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1251
1309
  *
1252
1310
  * See: https://hl7.org/fhirpath/#roundprecision-integer-decimal
1311
+ * @param context The evaluation context.
1253
1312
  * @param input The input collection.
1254
1313
  * @returns A collection containing the result.
1255
1314
  */
1256
- round: (input) => {
1257
- return applyMathFunc(Math.round, input);
1315
+ round: (context, input) => {
1316
+ return applyMathFunc(Math.round, context, input);
1258
1317
  },
1259
1318
  /**
1260
1319
  * Returns the square root of the input number as a Decimal.
@@ -1268,11 +1327,12 @@ const functions = {
1268
1327
  * Note that this function is equivalent to raising a number of the power of 0.5 using the power() function.
1269
1328
  *
1270
1329
  * See: https://hl7.org/fhirpath/#sqrt-decimal
1330
+ * @param context The evaluation context.
1271
1331
  * @param input The input collection.
1272
1332
  * @returns A collection containing the result.
1273
1333
  */
1274
- sqrt: (input) => {
1275
- return applyMathFunc(Math.sqrt, input);
1334
+ sqrt: (context, input) => {
1335
+ return applyMathFunc(Math.sqrt, context, input);
1276
1336
  },
1277
1337
  /**
1278
1338
  * Returns the integer portion of the input.
@@ -1282,11 +1342,12 @@ const functions = {
1282
1342
  * If the input collection contains multiple items, the evaluation of the expression will end and signal an error to the calling environment.
1283
1343
  *
1284
1344
  * See: https://hl7.org/fhirpath/#truncate-integer
1345
+ * @param context The evaluation context.
1285
1346
  * @param input The input collection.
1286
1347
  * @returns A collection containing the result.
1287
1348
  */
1288
- truncate: (input) => {
1289
- return applyMathFunc((x) => x | 0, input);
1349
+ truncate: (context, input) => {
1350
+ return applyMathFunc((x) => x | 0, context, input);
1290
1351
  },
1291
1352
  /*
1292
1353
  * 5.8. Tree navigation
@@ -1307,11 +1368,12 @@ const functions = {
1307
1368
  * function unchanged.
1308
1369
  *
1309
1370
  * See: https://hl7.org/fhirpath/#tracename-string-projection-expression-collection
1371
+ * @param context The evaluation context.
1310
1372
  * @param input The input collection.
1311
1373
  * @param nameAtom The log name.
1312
1374
  * @returns The input collection.
1313
1375
  */
1314
- trace: (input, nameAtom) => {
1376
+ trace: (context, input, nameAtom) => {
1315
1377
  console.log('trace', input, nameAtom);
1316
1378
  return input;
1317
1379
  },
@@ -1349,22 +1411,23 @@ const functions = {
1349
1411
  *
1350
1412
  * IBM FHIR issue: https://github.com/IBM/FHIR/issues/1014
1351
1413
  * IBM FHIR PR: https://github.com/IBM/FHIR/pull/1023
1414
+ * @param context The evaluation context.
1352
1415
  * @param input The input collection.
1353
1416
  * @param startAtom The start date/time.
1354
1417
  * @param endAtom The end date/time.
1355
1418
  * @param unitsAtom Which units to return ("years", "months", or "days").
1356
1419
  * @returns The Quantity of time between the two dates.
1357
1420
  */
1358
- between: (input, startAtom, endAtom, unitsAtom) => {
1359
- const startDate = functions.toDateTime(startAtom.eval(input));
1421
+ between: (context, input, startAtom, endAtom, unitsAtom) => {
1422
+ const startDate = functions.toDateTime(context, startAtom.eval(context, input));
1360
1423
  if (startDate.length === 0) {
1361
1424
  throw new Error('Invalid start date');
1362
1425
  }
1363
- const endDate = functions.toDateTime(endAtom.eval(input));
1426
+ const endDate = functions.toDateTime(context, endAtom.eval(context, input));
1364
1427
  if (endDate.length === 0) {
1365
1428
  throw new Error('Invalid end date');
1366
1429
  }
1367
- const unit = unitsAtom.eval(input)[0]?.value;
1430
+ const unit = unitsAtom.eval(context, input)[0]?.value;
1368
1431
  if (unit !== 'years' && unit !== 'months' && unit !== 'days') {
1369
1432
  throw new Error('Invalid units');
1370
1433
  }
@@ -1382,11 +1445,12 @@ const functions = {
1382
1445
  * For implementations with compile-time typing, this requires special-case
1383
1446
  * handling when processing the argument to treat it as a type specifier rather
1384
1447
  * than an identifier expression:
1448
+ * @param _context The evaluation context.
1385
1449
  * @param input The input collection.
1386
1450
  * @param typeAtom The desired type.
1387
1451
  * @returns True if the input element is of the desired type.
1388
1452
  */
1389
- is: (input, typeAtom) => {
1453
+ is: (_context, input, typeAtom) => {
1390
1454
  let typeName = '';
1391
1455
  if (typeAtom instanceof SymbolAtom) {
1392
1456
  typeName = typeAtom.name;
@@ -1406,11 +1470,12 @@ const functions = {
1406
1470
  * 6.5.3. not() : Boolean
1407
1471
  *
1408
1472
  * Returns true if the input collection evaluates to false, and false if it evaluates to true. Otherwise, the result is empty ({ }):
1473
+ * @param context The evaluation context.
1409
1474
  * @param input The input collection.
1410
1475
  * @returns True if the input evaluates to false.
1411
1476
  */
1412
- not: (input) => {
1413
- return functions.toBoolean(input).map((value) => ({ type: PropertyType.boolean, value: !value.value }));
1477
+ not: (context, input) => {
1478
+ return functions.toBoolean(context, input).map((value) => ({ type: PropertyType.boolean, value: !value.value }));
1414
1479
  },
1415
1480
  /*
1416
1481
  * Additional functions
@@ -1419,10 +1484,11 @@ const functions = {
1419
1484
  /**
1420
1485
  * For each item in the collection, if it is a string that is a uri (or canonical or url), locate the target of the reference, and add it to the resulting collection. If the item does not resolve to a resource, the item is ignored and nothing is added to the output collection.
1421
1486
  * The items in the collection may also represent a Reference, in which case the Reference.reference is resolved.
1487
+ * @param _context The evaluation context.
1422
1488
  * @param input The input collection.
1423
1489
  * @returns The resolved resource.
1424
1490
  */
1425
- resolve: (input) => {
1491
+ resolve: (_context, input) => {
1426
1492
  return input
1427
1493
  .map((e) => {
1428
1494
  const value = e.value;
@@ -1456,10 +1522,11 @@ const functions = {
1456
1522
  },
1457
1523
  /**
1458
1524
  * The as operator can be used to treat a value as a specific type.
1525
+ * @param _context The evaluation context.
1459
1526
  * @param input The input value.
1460
1527
  * @returns The value as the specific type.
1461
1528
  */
1462
- as: (input) => {
1529
+ as: (_context, input) => {
1463
1530
  return input;
1464
1531
  },
1465
1532
  /*
@@ -1475,10 +1542,11 @@ const functions = {
1475
1542
  * https://hl7.org/fhirpath/modelinfo.xsd
1476
1543
  *
1477
1544
  * See: https://hl7.org/fhirpath/#model-information
1545
+ * @param _context The evaluation context.
1478
1546
  * @param input The input collection.
1479
1547
  * @returns The type of the input value.
1480
1548
  */
1481
- type: (input) => {
1549
+ type: (_context, input) => {
1482
1550
  return input.map(({ value }) => {
1483
1551
  if (typeof value === 'boolean') {
1484
1552
  return { type: PropertyType.BackboneElement, value: { namespace: 'System', name: 'Boolean' } };
@@ -1495,8 +1563,8 @@ const functions = {
1495
1563
  return { type: PropertyType.BackboneElement, value: null };
1496
1564
  });
1497
1565
  },
1498
- conformsTo: (input, systemAtom) => {
1499
- const system = systemAtom.eval(input)[0].value;
1566
+ conformsTo: (context, input, systemAtom) => {
1567
+ const system = systemAtom.eval(context, input)[0].value;
1500
1568
  if (!system.startsWith('http://hl7.org/fhir/StructureDefinition/')) {
1501
1569
  throw new Error('Expected a StructureDefinition URL');
1502
1570
  }
@@ -1510,7 +1578,7 @@ const functions = {
1510
1578
  /*
1511
1579
  * Helper utilities
1512
1580
  */
1513
- function applyStringFunc(func, input, ...argsAtoms) {
1581
+ function applyStringFunc(func, context, input, ...argsAtoms) {
1514
1582
  if (input.length === 0) {
1515
1583
  return [];
1516
1584
  }
@@ -1518,7 +1586,7 @@ function applyStringFunc(func, input, ...argsAtoms) {
1518
1586
  if (typeof value !== 'string') {
1519
1587
  throw new Error('String function cannot be called with non-string');
1520
1588
  }
1521
- const result = func(value, ...argsAtoms.map((atom) => atom && atom.eval(input)?.[0]?.value));
1589
+ const result = func(value, ...argsAtoms.map((atom) => atom && atom.eval(context, input)?.[0]?.value));
1522
1590
  if (result === undefined) {
1523
1591
  return [];
1524
1592
  }
@@ -1527,7 +1595,7 @@ function applyStringFunc(func, input, ...argsAtoms) {
1527
1595
  }
1528
1596
  return [toTypedValue(result)];
1529
1597
  }
1530
- function applyMathFunc(func, input, ...argsAtoms) {
1598
+ function applyMathFunc(func, context, input, ...argsAtoms) {
1531
1599
  if (input.length === 0) {
1532
1600
  return [];
1533
1601
  }
@@ -1537,7 +1605,7 @@ function applyMathFunc(func, input, ...argsAtoms) {
1537
1605
  if (typeof numberInput !== 'number') {
1538
1606
  throw new Error('Math function cannot be called with non-number');
1539
1607
  }
1540
- const result = func(numberInput, ...argsAtoms.map((atom) => atom.eval(input)?.[0]?.value));
1608
+ const result = func(numberInput, ...argsAtoms.map((atom) => atom.eval(context, input)?.[0]?.value));
1541
1609
  const type = quantity ? PropertyType.Quantity : input[0].type;
1542
1610
  const returnValue = quantity ? { ...value, value: result } : result;
1543
1611
  return [{ type, value: returnValue }];