UNPKG

typescript-object-helper

Version:

A simple dependency to aid in mapping and instantiating typescript classes

159 lines 5.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.copyObject = exports.copyArray = exports.instantiateFromJsonReverseParam = exports.instantiateFromJson = void 0; const class_cast_1 = require("./class-cast"); /** * Creates a class typed object from string input * * @param stringIn The json string we want to create a class object from * @param classCast The class constructor we want to create */ function instantiateFromJson(json, classCast) { if (json instanceof Array) { return copyArray(json, classCast); } return copyObject(json, classCast); } exports.instantiateFromJson = instantiateFromJson; // This should work better to do mass find and replace with regex on new myClass() instantiations. function instantiateFromJsonReverseParam(classCast, json) { return instantiateFromJson(json, classCast); } exports.instantiateFromJsonReverseParam = instantiateFromJsonReverseParam; /** * * @param arrayIn The array of generic objects we want to create class objects from * @param classCast The class constructor we want to create */ function copyArray(arrayIn, classCast) { const arr = []; arrayIn.forEach((val) => { if (typeof val === 'object') { arr.push(copyObject(val, classCast)); } else { arr.push(val); } }); return arr; } exports.copyArray = copyArray; /** * Does a full copy on an object including nested objects and arrays (deep copy) * Removes attributes that are not in the destination class model * Also support typing of attributes and arrays. If you want a nested attribute typed (for access * to it's functions) then add the @ClassCast decorator to the attribute in your model. example: * * @ClassCast(Employee) * public employee: Employee = undefined; * * @param objectIn The generic object we want to create a class object from * @param classCast The class constructor we want to create */ function copyObject(objectIn, classCast, allowExtras = true) { /* eslint-disable */ if (objectIn instanceof classCast) { return objectIn; } const newInstance = new classCast(); const originalEntries = Object.entries(newInstance); const descriptors = Object.getOwnPropertyDescriptors(classCast.prototype); const settableDescriptors = Object.keys(descriptors).filter(key => { const descriptor = descriptors[key]; return descriptor && (descriptor.set || (descriptor.writable && descriptor.enumerable)); }).sort((a, b) => { const aHasSet = descriptors[a].set; const bHasSet = descriptors[b].set; if (aHasSet && !bHasSet) { return 1; } if (!aHasSet && bHasSet) { return -1; } return 0; }).reduce((result, key) => { result[key] = descriptors[key]; return result; }, {}); const objectEntries = Object.entries(settableDescriptors); let allEntries = originalEntries.concat(objectEntries); // TODO: this is deprecated. This will place anything in the JSON into the instance, even if not in the model. if (allowExtras) { allEntries = Object.entries(objectIn).concat(allEntries); } const allNonPrivateEntries = allEntries.filter(entry => !entry[0].startsWith('_')); allNonPrivateEntries.forEach((entry) => { const propertyKey = entry[0]; const descriptor = entry[1]; const attributeValue = objectIn[propertyKey]; // check if the attribute is generic, custom object, or custom array // @ts-ignore if (attributeValue !== undefined) { // @ts-ignore if (!newInstance[class_cast_1.DNAME] || !newInstance[class_cast_1.DNAME][propertyKey]) { assignGenericAttribute(newInstance, propertyKey, attributeValue); } else { // @ts-ignore if (newInstance[class_cast_1.DNAME][propertyKey] instanceof Array && attributeValue instanceof Array) { assignArrayAttribute(newInstance, propertyKey, attributeValue); } else { assignObjectAttribute(newInstance, propertyKey, attributeValue); } } } }); // @ts-ignore if (!!newInstance['onInit'] && typeof newInstance['onInit'] === 'function') { //@ts-ignore newInstance.onInit(); } return newInstance; } exports.copyObject = copyObject; /** * The model did not define a class type - assign as a generic * * @param parent * @param attributeName */ function assignGenericAttribute(parent, attributeName, attributeValue) { parent[attributeName] = attributeValue; } /** * The model defined an class array. Create a full class object for each item in array * * @param parent * @param attributeName */ function assignArrayAttribute(parent, attributeName, attributeValue) { const arr = []; // for (const obj of attributeValue as any) { // arr.push(copyObject(obj, parent[DNAME][attributeName][0])); // } attributeValue.forEach((obj) => { arr.push(copyObject(obj, parent[class_cast_1.DNAME][attributeName][0])); }); parent[attributeName] = arr; } /** * The model defined a class attribute. Create a full class object for this attribute * * @param parent * @param attributeName */ function assignObjectAttribute(parent, attributeName, attributeValue) { // value is null when we modeled an object that is not present in the json string - set to null if (!attributeValue) { parent[attributeName] = null; } else if (attributeValue instanceof Array) { parent[attributeName] = copyArray(attributeValue, parent[class_cast_1.DNAME][attributeName]); } else { parent[attributeName] = copyObject(attributeValue, parent[class_cast_1.DNAME][attributeName]); } } // } //# sourceMappingURL=object-helper-functions.js.map