class-hydrator
Version:
Transformation typescript class instance to stringifiable(serializable) plain object
62 lines (60 loc) • 2.1 kB
text/typescript
import {OnHydrateMetadataKey} from "../../decorators";
import {Hydrator} from "../../index";
export function hydrateProp(targetProp, seenObj){
if(targetProp === null || targetProp === undefined || targetProp.constructor === Number || targetProp.constructor === Boolean){
//primitive types
return targetProp;
}else if(targetProp.constructor === String){
if(targetProp.indexOf('_i_') === 0){
//TODO remove below line when clear about it.
if(!seenObj[targetProp.slice(3)]) console.error("Hydrator:couldn't find seenObj");
//seenObjId
return seenObj[targetProp.slice(3)];
}else{
//String
return targetProp;
}
}else{
//Array || Class || Object
if(targetProp.constructor === Array){
//targetProp:Array
let newArr = new Array();
seenObj[targetProp.shift()] = newArr;
for(let i in targetProp){
newArr[i] = hydrateProp(targetProp[i], seenObj);
}
return newArr;
}else if(targetProp.constructor === Object && targetProp._c_){
//Class
let classOfTarget = Hydrator.classes[targetProp._c_];
if(!classOfTarget){
throw Error(`${targetProp._c_} was not provided to Hydrator`)
}
let newInst = new Object();
seenObj[targetProp._i_] = newInst;
for(let i in targetProp){
if(i==="_i_" || i==="_c_") continue;
else if(i==="_N_") newInst[i] = null;
else newInst[i] = hydrateProp(targetProp[i], seenObj);
}
(newInst as any).__proto__ = classOfTarget.prototype;
// apply @OnHydrate()
for(let i in newInst){
let onHydrateMetadata = Reflect.getMetadata(OnHydrateMetadataKey,classOfTarget.prototype,i);
if(onHydrateMetadata){
newInst[i] = onHydrateMetadata.callback(newInst);
}
}
return newInst;
}else{
//Object
let newObj = new Object();
seenObj[targetProp._i_] = newObj;
for(let i in targetProp){
if(i==="_i_" || i==="_c_") continue;
newObj[i] = hydrateProp(targetProp[i], seenObj);
}
return newObj
}
}
}