@atomic-ehr/fhirpath
Version:
A TypeScript implementation of FHIRPath
66 lines (56 loc) • 2.27 kB
text/typescript
import type { FunctionDefinition, LiteralNode } from '../types';
import { Errors } from '../errors';
import { RuntimeContextManager } from '../interpreter';
import { type FunctionEvaluator } from '../types';
import { box, unbox } from '../boxing';
export const evaluate: FunctionEvaluator = async (input, context, args, evaluator) => {
if (args.length < 1) {
throw Errors.invalidOperation('defineVariable requires at least 1 argument');
}
const nameNode = args[0] as LiteralNode;
if (nameNode.valueType !== 'string') {
throw Errors.invalidOperation('Variable name must be a string');
}
const varName = nameNode.value as string;
let value: any[];
if (args.length === 1) {
// Single argument: defineVariable(name) - use input as value
value = input;
} else {
// Two arguments: defineVariable(name, value) - evaluate value expression
const tempContext = RuntimeContextManager.setVariable(context, '$this', input);
const valueExpr = args[1];
if (!valueExpr) {
throw Errors.invalidOperation('defineVariable requires a value expression');
}
const valueResult = await evaluator(valueExpr, input, tempContext);
value = valueResult.value;
}
// Set the variable using RuntimeContextManager (handles prefixes and checks)
const newContext = RuntimeContextManager.setVariable(context, varName, value);
// If newContext is same as context, variable already existed - return empty
if (newContext === context) {
return { value: [], context };
}
// Pass through input unchanged
return { value: input, context: newContext };
};
export const defineVariableFunction: FunctionDefinition & { evaluate: FunctionEvaluator } = {
name: 'defineVariable',
category: ['context'],
description: 'Defines a variable in the evaluation context',
examples: [
'Patient.defineVariable("patientName", name.first())',
'Patient.name.defineVariable("names")'
],
signatures: [{
name: 'defineVariable',
input: { type: 'Any', singleton: false },
parameters: [
{ name: 'name', type: { type: 'String', singleton: true } },
{ name: 'value', type: { type: 'Any', singleton: false }, optional: true },
],
result: { type: 'Any', singleton: false },
}],
evaluate
};