UNPKG

@atomic-ehr/fhirpath

Version:

A TypeScript implementation of FHIRPath

69 lines (57 loc) 2.58 kB
import type { FunctionDefinition, FunctionEvaluator } from '../types'; import { Errors } from '../errors'; import { RuntimeContextManager } from '../interpreter'; import { box, unbox } from '../boxing'; export const evaluate: FunctionEvaluator = async (input, context, args, evaluator) => { // all() requires exactly one argument (the criteria expression) if (!args || args.length !== 1) { throw Errors.invalidOperation('all requires exactly one argument'); } // If the input collection is empty, the result is true per spec if (input.length === 0) { return { value: [box(true, { type: 'Boolean', singleton: true })], context }; } const criteriaExpression = args[0]; if (!criteriaExpression) { throw Errors.invalidOperation('all requires a criteria expression'); } // Evaluate the criteria for each element in the input collection for (let i = 0; i < input.length; i++) { const boxedItem = input[i]; if (!boxedItem) continue; const item = unbox(boxedItem); // Create iterator context with $this and $index let tempContext = RuntimeContextManager.withIterator(context, item, i); tempContext = RuntimeContextManager.setVariable(tempContext, '$total', input.length); // Evaluate the criteria expression with the current item as context const result = await evaluator(criteriaExpression, [boxedItem], tempContext); // Check if the result is truthy // If the result is empty or contains a falsy value, return false if (result.value.length === 0) { return { value: [box(false, { type: 'Boolean', singleton: true })], context }; } const resultValue = unbox(result.value[0]!); if (resultValue !== true) { return { value: [box(false, { type: 'Boolean', singleton: true })], context }; } } // All criteria evaluations were true return { value: [box(true, { type: 'Boolean', singleton: true })], context }; }; export const allFunction: FunctionDefinition & { evaluate: FunctionEvaluator } = { name: 'all', category: ['existence'], description: 'Returns true if for every element in the input collection, criteria evaluates to true. Otherwise, the result is false. If the input collection is empty, the result is true.', examples: [ "generalPractitioner.all($this.resolve() is Practitioner)" ], signatures: [{ name: 'all', input: { type: 'Any', singleton: false }, parameters: [ { name: 'criteria', type: { type: 'Any', singleton: false } } ], result: { type: 'Boolean', singleton: true } }], evaluate };