FHIRPatch

Commure's JavaScript implementation of the FHIRPatch specification

What is FHIRPatch?

FHIRPatch is a set of fhirpath based operations that alter a given value.

Variations

We provide two variations of fhirpatch

NameDescriptionDefault
fhirpatchMutates a given object in place.Yes
fhirpatchImmutableReturns a new object with patches applied (this new object will be an immer object)No

Which one should I use?

Generally use fhirpatchImmutable if your in a browser environment this plays nicely with React and other frontend frameworks. Use the default fhirpatch function if you do not want immer objects being returned or want to eke out a bit more performance.

Environments

Supports both Browser and Node environments.

FHIRPatch operations

The commure implementation supports all of the operations at https://www.hl7.org/fhir/fhirpatch.html.

Add

// [Description]: If element at path + name is a collection appends the operations value to the end of the collection. If element is a single item replaces it's value with value specified in operation.
// [Operation]:
// Add takes an operation with the following keys:
// type: "add"
// path: [Path to add the value]
// name: [Name of the property adding]
// value: [Value to add]
test("add", () => {
const patient = {
resourceType: "Patient",
active: false,
name: [
{
use: "official",
family: "Chalmers",
given: ["Peter", "James"],
},
{
use: "usual",
given: ["Jim"],
},
{
use: "maiden",
family: "Windsor",
given: ["Peter", "James"],
period: {
end: "2002",
},
},
],
};
const operation = {
type: "add",
path: "Patient.name[0]",
name: "value",
value: "added value",
};
fhirpatch(operation, patient);
expect(patient).toEqual({
active: false,
name: [
{
family: "Chalmers",
given: ["Peter", "James"],
value: "added value",
use: "official",
},
{ given: ["Jim"], use: "usual" },
{
family: "Windsor",
given: ["Peter", "James"],
period: { end: "2002" },
use: "maiden",
},
],
resourceType: "Patient",
});
const patient2 = {
resourceType: "Patient",
active: false,
name: [
{
use: "official",
family: "Chalmers",
given: ["Peter", "James"],
},
{
use: "usual",
given: ["Jim"],
},
{
use: "maiden",
family: "Windsor",
given: ["Peter", "James"],
period: {
end: "2002",
},
},
],
};
fhirpatch({ ...operation, path: "Patient.name[2]" }, patient2);
expect(patient2).toEqual({
active: false,
name: [
{
family: "Chalmers",
given: ["Peter", "James"],
use: "official",
},
{ given: ["Jim"], use: "usual" },
{
family: "Windsor",
given: ["Peter", "James"],
period: { end: "2002" },
value: "added value",
use: "maiden",
},
],
resourceType: "Patient",
});
});

Insert

// [Description]: Inserts a given value into the given collection [based on path].
// [Operation]:
// Insert takes an operation with the following keys:
// type: "insert"
// path: [Path of the collection to insert the value]
// index: [Index where value will be inserted in]
// value: [Value to insert]
test("insert", () => {
const patient = {
resourceType: "Patient",
active: false,
name: [
{
use: "official",
family: "Chalmers",
given: ["Peter", "James"],
},
{
use: "usual",
given: ["Jim"],
},
{
use: "maiden",
family: "Windsor",
given: ["Peter", "James"],
period: {
end: "2002",
},
},
],
};
const operation = {
type: "insert",
path: "Patient.name",
index: 3,
value: { family: "Blaire", use: "unknown", given: ["Jake", "Lamotta"] },
};
fhirpatch(operation, patient);
expect(patient).toEqual({
active: false,
name: [
{ family: "Chalmers", given: ["Peter", "James"], use: "official" },
{ given: ["Jim"], use: "usual" },
{
family: "Windsor",
given: ["Peter", "James"],
period: { end: "2002" },
use: "maiden",
},
{ family: "Blaire", given: ["Jake", "Lamotta"], use: "unknown" },
],
resourceType: "Patient",
});
});

Delete

// [Description]: Deletes an element from the object. Only one element can be deleted at a time.
// [Operation]:
// Delete takes an operation with the following keys:
// type: "delete"
// path: [Path of an element to delete]
test("delete", () => {
let patient = {
resourceType: "Patient",
active: false,
name: [
{
use: "official",
family: "Chalmers",
given: ["Peter", "James"],
},
{
use: "usual",
given: ["Jim"],
},
{
use: "maiden",
family: "Windsor",
given: ["Peter", "James"],
period: {
end: "2002",
},
},
],
};
fhirpatch(
{
type: "delete",
path: "Patient.name[0].use",
},
patient
);
expect(patient).toEqual({
resourceType: "Patient",
active: false,
name: [
{
family: "Chalmers",
given: ["Peter", "James"],
},
{
use: "usual",
given: ["Jim"],
},
{
use: "maiden",
family: "Windsor",
given: ["Peter", "James"],
period: {
end: "2002",
},
},
],
});
});

Replace

// [Description]: Replaces an element in the object. Only one element can be replaced at a time.
// [Operation]:
// Replace takes an operation with the following keys:
// type: "replace"
// path: [Path of an element to replace]
// value: [Replacement value for given element]
test("replace", () => {
const patient = testPatient();
fhirpatch(
[
{
type: "replace",
path: "Patient.name[2].period",
value: {
end: null,
},
},
{
type: "replace",
path: "Patient.name[0].use",
value: null,
},
],
patient
);
expect(patient).toEqual({
resourceType: "Patient",
active: false,
name: [
{
use: null,
family: "Chalmers",
given: ["Peter", "James"],
},
{
use: "usual",
given: ["Jim"],
},
{
use: "maiden",
family: "Windsor",
given: ["Peter", "James"],
period: {
end: null,
},
},
],
});
});

Move

// [Description]: Moves element from source index to destination for a given collection specified by path.
// [Operation]:
// Replace takes an operation with the following keys:
// path: [Path of an element to replace]
// value: [Replacement value for given element]
test("move", () => {
let patient = {
resourceType: "Patient",
name: [{ given: ["James", "Michael", "Miller", "Mik"] }],
};
let operation = [
{
type: "move",
path: "Patient.name[0].given",
source: 2,
destination: 0,
},
];
fhirpatch(operation, patient);
expect(patient).toEqual({
resourceType: "Patient",
name: [{ given: ["Miller", "James", "Michael", "Mik"] }],
});
fhirpatch(
[
{
type: "move",
path: "Patient.name[0].given",
source: 1,
destination: 3,
},
],
patient
);
expect(patient).toEqual({
resourceType: "Patient",
name: [{ given: ["Miller", "Michael", "Mik", "James"] }],
});
});