Skip to content

Instantly share code, notes, and snippets.

@jord-goldberg
Created July 7, 2021 20:11
Show Gist options
  • Save jord-goldberg/dd3b62fa061186b8ba6ee11461a138ce to your computer and use it in GitHub Desktop.
Save jord-goldberg/dd3b62fa061186b8ba6ee11461a138ce to your computer and use it in GitHub Desktop.
create a SCIM patch request body based on diff between Javascript objects.
import isEqual from "lodash/isEqual";
import isObject from "lodash/isObject";
const flattenPaths = (value, path = []) => {
if (!isObject(value)) {
return { [path.join(".")]: value };
}
if (Array.isArray(value)) {
return value.reduce((cumulative, item) => {
cumulative[`${path.join(".")}[value eq "${item.value}"]`] = item;
return cumulative;
}, {});
}
return Object.keys(value).reduce((cumulative, key) => {
return {
...cumulative,
...flattenPaths(value[key], [...path, key])
};
}, {});
};
const getOperationsMap = (flattenedObject, flattenedBase, op) => {
return Object.keys(flattenedObject).reduce((operationsMap, path) => {
const value = flattenedObject[path];
if (!isEqual(value, flattenedBase[path])) {
const operation = {
path,
op: flattenedBase[path] == null ? op : "replace"
};
if (operation.op !== "remove") {
operation.value = value;
}
const addArrayBeginIndex =
operation.op === "add" ? path.indexOf("[") : -1;
if (addArrayBeginIndex === -1) {
operationsMap[path] = operation;
} else {
const addPath = path.substring(0, addArrayBeginIndex);
if (operationsMap[addPath] == null) {
operation.path = addPath;
operation.value = [operation.value];
operationsMap[addPath] = operation;
} else {
operationsMap[addPath].value.push(operation.value);
}
}
}
return operationsMap;
}, {});
};
export default class ScimPatch {
constructor(patched, original = {}) {
const flatPatched = flattenPaths(patched);
const flatOriginal = flattenPaths(original);
const removals = getOperationsMap(flatOriginal, flatPatched, "remove");
const additions = getOperationsMap(flatPatched, flatOriginal, "add");
this.schemas = ["urn:ietf:params:scim:api:messages:2.0:PatchOp"];
this.Operations = Object.values({ ...removals, ...additions });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment