FHIRPath

Commure's JavaScript implementation of the FHIRPath specification

What is FHIRPath?

FHIRPath is a language designed for path based navigation and extracting values from FHIR; however our implementation can work with any native JavaScript object.

Why does it matter?

With FHIR you often have no guarantees over what values are present. Many fields are optional and even fields that are required can be extended in such a way as to make them quasi-optional. Additionally you often want to select certain values that fit a criteria, for example: I want to select the value of an identifier that is an MRN. To safely answer these types of questions in native JavaScript, all values should be assumed optional and some type of logic is needed to safely filter values to fit your criteria. Working with nested FHIR values and adding more constraints over these values can add a significant amount of complexity to your code.

Using FHIRPath makes both safely accessing values and adding constraints idiomatic.

Environments

Supports both Browser and Node environments.

Examples

import fhirpath from "@commure/fhirpath";
const patient = {
resourceType: "Patient",
id: "f2831186-85c1-42af-aab8-61d7c715d57a",
identifier: [
{
use: "official",
type: {
coding: [
{
system: "http://terminology.hl7.org/CodeSystem/v2-0203",
code: "MR",
display: "Medical Record Number",
},
],
},
system: "UCSF Medical Center",
value: "09272017",
},
],
active: true,
};
// Accessing MRN using raw JavaScript
// --------------------------------------------------------------------------------------------------
function getMRNIdentifier(patient) {
const identifiers = patient.identifier ? patient.identifier : [];
const identifier = identifiers.filter((identifier) => {
if (!identifier.type) return false;
if (!identifier.type.coding) return false;
const v = identifier.type.coding.find((code) => {
return code.code === "MR";
});
return v !== undefined;
})[0];
if (identifier) return identifier.value;
else return undefined;
}
expect(getMRNIdentifier(patient)).toEqual("09272017");
// Accessing MRN using fhirpath
// --------------------------------------------------------------------------------------------------
// Using FHIRPath to safely extract an MRN.
let mrnValue = fhirpath(
"Patient.identifier.where(type.coding.code = 'MR').value",
patient
);
// The result from FHIRPath will always be an array to handle the case of several answers to a query.
expect(mrnValue).toEqual(["09272017"]);
// Additionally for more flexibility, passing in just a fhirpath will create a curried function that can be evaluated later.
// This will also have an added performance benefit of memoizing an AST from the FHIRPath expression.
// Creates a curried function that extracts an identifier value based on a passed in variable 'identifierType'.
const extractIdentifier = fhirpath(
"Patient.identifier.where(type.coding.code = %identifierType).value"
);
mrnValue = extractIdentifier(patient, { identifierType: "MR" });
// Produces the same output as above.
expect(mrnValue).toEqual(["09272017"]);

Handles some of the unique quirks of FHIR JSONs

As a FHIR native way to extract values FHIRPath also handles some of the unique quirks of FHIR like typechoices and extensions. Using FHIRPath you don't need to know many of the details of how FHIR serializes to JSON. Below is an example of a valid FHIR JSON with a FHIRPath evaluation:

const complicatedPatient = {
resourceType: "Patient",
deceasedBoolean: false,
_deceasedBoolean: {
id: "a1",
extension: [
{
url: "...",
_url: {
id: "urlId1",
extension: [{ url: "asdf" }],
},
valueXXX: "....",
},
{
url: "...",
_url: {
id: "urlId2",
extension: [{ url: "asdf" }],
},
valueXXX: "....",
},
],
},
};
expect(
fhirpath("Patient.deceased.extension[0].url.id", complicatedPatient)
).toEqual(["urlId1"]);