|
|
|
|
@@ -39,16 +39,34 @@ export function globalSvDb() {
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Options for custom serialization/deserialization of a field.
|
|
|
|
|
*/
|
|
|
|
|
export interface SvDbOptions {
|
|
|
|
|
/** Function to serialize the field value before saving to DB */
|
|
|
|
|
serialize?: (value: any) => any;
|
|
|
|
|
/** Function to deserialize the field value after reading from DB */
|
|
|
|
|
deserialize?: (value: any) => any;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* saveable - saveable decorator to be used on class properties
|
|
|
|
|
*/
|
|
|
|
|
export function svDb() {
|
|
|
|
|
export function svDb(options?: SvDbOptions) {
|
|
|
|
|
return (target: SmartDataDbDoc<unknown, unknown>, key: string) => {
|
|
|
|
|
console.log(`called svDb() on >${target.constructor.name}.${key}<`);
|
|
|
|
|
if (!target.saveableProperties) {
|
|
|
|
|
target.saveableProperties = [];
|
|
|
|
|
}
|
|
|
|
|
target.saveableProperties.push(key);
|
|
|
|
|
// attach custom serializer/deserializer options to the class constructor
|
|
|
|
|
const ctor = target.constructor as any;
|
|
|
|
|
if (!ctor._svDbOptions) {
|
|
|
|
|
ctor._svDbOptions = {};
|
|
|
|
|
}
|
|
|
|
|
if (options) {
|
|
|
|
|
ctor._svDbOptions[key] = options;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -189,7 +207,12 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
|
|
|
|
|
const newInstance = new this();
|
|
|
|
|
(newInstance as any).creationStatus = 'db';
|
|
|
|
|
for (const key of Object.keys(mongoDbNativeDocArg)) {
|
|
|
|
|
newInstance[key] = mongoDbNativeDocArg[key];
|
|
|
|
|
const rawValue = mongoDbNativeDocArg[key];
|
|
|
|
|
const optionsMap = (this as any)._svDbOptions || {};
|
|
|
|
|
const opts = optionsMap[key];
|
|
|
|
|
newInstance[key] = opts && typeof opts.deserialize === 'function'
|
|
|
|
|
? opts.deserialize(rawValue)
|
|
|
|
|
: rawValue;
|
|
|
|
|
}
|
|
|
|
|
return newInstance;
|
|
|
|
|
}
|
|
|
|
|
@@ -645,7 +668,12 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
|
|
|
|
|
public async updateFromDb() {
|
|
|
|
|
const mongoDbNativeDoc = await this.collection.findOne(await this.createIdentifiableObject());
|
|
|
|
|
for (const key of Object.keys(mongoDbNativeDoc)) {
|
|
|
|
|
this[key] = mongoDbNativeDoc[key];
|
|
|
|
|
const rawValue = mongoDbNativeDoc[key];
|
|
|
|
|
const optionsMap = (this.constructor as any)._svDbOptions || {};
|
|
|
|
|
const opts = optionsMap[key];
|
|
|
|
|
this[key] = opts && typeof opts.deserialize === 'function'
|
|
|
|
|
? opts.deserialize(rawValue)
|
|
|
|
|
: rawValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -655,8 +683,14 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
|
|
|
|
|
public async createSavableObject(): Promise<TImplements> {
|
|
|
|
|
const saveableObject: unknown = {}; // is not exposed to outside, so any is ok here
|
|
|
|
|
const saveableProperties = [...this.globalSaveableProperties, ...this.saveableProperties];
|
|
|
|
|
// apply custom serialization if configured
|
|
|
|
|
const optionsMap = (this.constructor as any)._svDbOptions || {};
|
|
|
|
|
for (const propertyNameString of saveableProperties) {
|
|
|
|
|
saveableObject[propertyNameString] = this[propertyNameString];
|
|
|
|
|
const rawValue = (this as any)[propertyNameString];
|
|
|
|
|
const opts = optionsMap[propertyNameString];
|
|
|
|
|
(saveableObject as any)[propertyNameString] = opts && typeof opts.serialize === 'function'
|
|
|
|
|
? opts.serialize(rawValue)
|
|
|
|
|
: rawValue;
|
|
|
|
|
}
|
|
|
|
|
return saveableObject as TImplements;
|
|
|
|
|
}
|
|
|
|
|
|