You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.8 KiB
JavaScript
98 lines
2.8 KiB
JavaScript
'use strict';
|
|
|
|
const dotty = require("dotty");
|
|
const deepAssign = require("deep-assign");
|
|
|
|
module.exports = function createPropertyMapper(propertyMap) {
|
|
let mappings = Object.keys(propertyMap).map((sourceProperty) => {
|
|
let destinationPath = propertyMap[sourceProperty];
|
|
|
|
if (typeof destinationPath === "function") {
|
|
return {
|
|
sourceProperty: sourceProperty,
|
|
transformer: destinationPath
|
|
}
|
|
} else {
|
|
let destinationObject, destinationProperty;
|
|
|
|
if (destinationPath.includes(".")) {
|
|
let destinationPathParts = destinationPath.split(".");
|
|
|
|
destinationObject = destinationPathParts[0];
|
|
destinationProperty = destinationPathParts.slice(1).join(".");
|
|
} else {
|
|
destinationObject = destinationPath;
|
|
destinationProperty = sourceProperty;
|
|
}
|
|
|
|
return {
|
|
sourceProperty: sourceProperty,
|
|
destinationObject: destinationObject,
|
|
destinationProperty: destinationProperty
|
|
}
|
|
}
|
|
}).reduce((mappings, item) => {
|
|
mappings[item.sourceProperty] = item;
|
|
return mappings;
|
|
}, {});
|
|
|
|
return function mapProperties(properties) {
|
|
return Object.keys(properties).map((propertyName) => {
|
|
let propertyValue = properties[propertyName];
|
|
|
|
if (propertyName.includes(".")) {
|
|
/* Property names with a dot are attempts to directly access an
|
|
* object within a composite object; they need to be handled
|
|
* specially since they essentially bypass the mapping step.
|
|
* If there is *more* than a single dot, then this is an attempt
|
|
* to access a *nested* composite object, and therefore we should
|
|
* keep the entire property name after the first dot intact. */
|
|
|
|
let propertyNameSegments = propertyName.split(".");
|
|
let destinationObject = propertyNameSegments[0];
|
|
let realPropertyName = propertyNameSegments.slice(1).join(".");
|
|
|
|
return {
|
|
sourceProperty: propertyName,
|
|
destinationObject: destinationObject,
|
|
destinationProperty: realPropertyName,
|
|
value: propertyValue
|
|
}
|
|
} else if (mappings[propertyName] != null) {
|
|
return Object.assign({
|
|
value: propertyValue
|
|
}, mappings[propertyName]);
|
|
} else {
|
|
return {
|
|
sourceProperty: propertyName,
|
|
destinationObject: "_",
|
|
destinationProperty: propertyName,
|
|
value: propertyValue
|
|
}
|
|
}
|
|
}).filter((item) => {
|
|
return (item != null);
|
|
}).reduce((objects, item) => {
|
|
function ensureObject(object) {
|
|
if (objects[object] == null) {
|
|
objects[object] = {};
|
|
}
|
|
}
|
|
|
|
if (item.destinationProperty != null) {
|
|
ensureObject(item.destinationObject);
|
|
dotty.put(objects[item.destinationObject], item.destinationProperty, item.value);
|
|
} else {
|
|
let results = item.transformer(item.value);
|
|
|
|
Object.keys(results).forEach((object) => {
|
|
ensureObject(object);
|
|
deepAssign(objects[object], results[object]);
|
|
});
|
|
}
|
|
|
|
return objects;
|
|
}, {})
|
|
}
|
|
};
|