smartdata/ts/smartdata.classes.doc.ts

189 lines
5.2 KiB
TypeScript
Raw Normal View History

import * as plugins from './smartdata.plugins';
2016-09-13 20:53:21 +00:00
2020-06-11 23:05:32 +00:00
import { ObjectMap } from '@pushrocks/lik';
2017-02-25 10:37:05 +00:00
import { SmartdataDb } from './smartdata.classes.db';
2018-07-09 22:02:04 +00:00
import { SmartdataCollection } from './smartdata.classes.collection';
2016-09-13 20:53:21 +00:00
export type TDocCreation = 'db' | 'new' | 'mixed';
2016-09-13 20:53:21 +00:00
2016-11-17 23:42:25 +00:00
/**
2016-11-17 23:59:57 +00:00
* saveable - saveable decorator to be used on class properties
2016-11-17 23:42:25 +00:00
*/
2016-11-18 12:56:15 +00:00
export function svDb() {
2020-02-19 18:30:34 +00:00
return (target: SmartDataDbDoc<unknown, unknown>, key: string) => {
console.log(`called svDb() on ${key}`);
if (!target.saveableProperties) {
target.saveableProperties = [];
}
target.saveableProperties.push(key);
};
2016-11-17 23:42:25 +00:00
}
/**
* unique index - decorator to mark a unique index
*/
export function unI() {
2020-02-19 18:30:34 +00:00
return (target: SmartDataDbDoc<unknown, unknown>, key: string) => {
console.log('called unI');
// mark the index as unique
if (!target.uniqueIndexes) {
target.uniqueIndexes = [];
}
target.uniqueIndexes.push(key);
// and also save it
if (!target.saveableProperties) {
target.saveableProperties = [];
}
target.saveableProperties.push(key);
};
2019-01-07 01:41:38 +00:00
}
2020-02-19 18:30:34 +00:00
export class SmartDataDbDoc<T, TImplements> {
2017-02-25 10:37:05 +00:00
/**
* the collection object an Doc belongs to
*/
2019-09-02 14:42:29 +00:00
public collection: SmartdataCollection<T>;
2016-11-17 23:42:25 +00:00
2017-02-25 10:37:05 +00:00
/**
* how the Doc in memory was created, may prove useful later.
*/
2019-09-02 14:42:29 +00:00
public creationStatus: TDocCreation = 'new';
2016-11-17 23:42:25 +00:00
/**
* unique indexes
*/
2019-09-02 14:42:29 +00:00
public uniqueIndexes: string[];
2017-02-25 10:37:05 +00:00
/**
* an array of saveable properties of a doc
*/
2019-09-02 14:42:29 +00:00
public saveableProperties: string[];
2016-11-17 23:42:25 +00:00
2017-06-18 17:52:54 +00:00
/**
* name
*/
2019-09-02 14:42:29 +00:00
public name: string;
2017-06-18 17:52:54 +00:00
/**
* primary id in the database
*/
2019-09-02 14:42:29 +00:00
public dbDocUniqueId: string;
2017-02-25 10:37:05 +00:00
/**
* class constructor
*/
constructor() {
this.name = this.constructor['name'];
2019-02-13 21:08:58 +00:00
if (this.constructor['smartdataCollection']) {
2019-01-08 13:37:17 +00:00
// tslint:disable-next-line: no-string-literal
this.collection = this.constructor['smartdataCollection'];
// tslint:disable-next-line: no-string-literal
2019-01-08 17:22:48 +00:00
} else if (typeof this.constructor['smartdataDelayedCollection'] === 'function') {
2019-01-08 13:37:17 +00:00
// tslint:disable-next-line: no-string-literal
2019-01-08 17:22:48 +00:00
this.collection = this.constructor['smartdataDelayedCollection']();
2019-01-08 13:37:17 +00:00
} else {
console.error('Could not determine collection for DbDoc');
}
}
2020-08-18 12:01:46 +00:00
public static async getInstances<T>(filterArg: Partial<T>): Promise<T[]> {
2019-09-02 14:42:29 +00:00
const self: any = this; // fool typesystem
2019-01-08 17:22:48 +00:00
let referenceMongoDBCollection: SmartdataCollection<T>;
2019-02-13 21:08:58 +00:00
2019-01-08 17:22:48 +00:00
if (self.smartdataCollection) {
referenceMongoDBCollection = self.smartdataCollection;
} else if (self.smartdataDelayedCollection) {
referenceMongoDBCollection = self.smartdataDelayedCollection();
2019-02-13 21:08:58 +00:00
}
2018-07-09 22:02:04 +00:00
const foundDocs = await referenceMongoDBCollection.find(filterArg);
const returnArray = [];
2019-09-02 14:42:29 +00:00
for (const item of foundDocs) {
const newInstance = new this();
newInstance.creationStatus = 'db';
for (const key of Object.keys(item)) {
newInstance[key] = item[key];
}
returnArray.push(newInstance);
}
return returnArray;
}
2020-08-18 12:01:46 +00:00
public static async getInstance<T>(filterArg: Partial<T>): Promise<T> {
2019-09-02 14:42:29 +00:00
const result = await this.getInstances<T>(filterArg);
if (result && result.length > 0) {
return result[0];
}
2017-02-25 10:37:05 +00:00
}
2016-11-17 23:42:25 +00:00
2017-02-25 10:37:05 +00:00
/**
* saves this instance but not any connected items
* may lead to data inconsistencies, but is faster
*/
2019-09-02 14:42:29 +00:00
public async save() {
2019-01-08 13:37:17 +00:00
// tslint:disable-next-line: no-this-assignment
2019-09-02 14:42:29 +00:00
const self: any = this;
switch (this.creationStatus) {
case 'db':
await this.collection.update(self);
break;
case 'new':
2019-09-02 14:42:29 +00:00
const writeResult = await this.collection.insert(self);
this.creationStatus = 'db';
break;
default:
console.error('neither new nor in db?');
2017-02-25 10:37:05 +00:00
}
}
2019-01-08 17:45:30 +00:00
/**
* deletes a document from the database
*/
2019-09-02 14:58:19 +00:00
public async delete() {
const self: any = this;
await this.collection.delete(self);
}
2019-01-08 17:45:30 +00:00
2017-02-25 10:37:05 +00:00
/**
* also store any referenced objects to DB
* better for data consistency
*/
2020-06-11 23:05:32 +00:00
public saveDeep(savedMapArg: ObjectMap<SmartDataDbDoc<any, any>> = null) {
2017-02-25 10:37:05 +00:00
if (!savedMapArg) {
2020-06-11 23:05:32 +00:00
savedMapArg = new ObjectMap<SmartDataDbDoc<any, any>>();
2017-02-25 10:37:05 +00:00
}
savedMapArg.add(this);
this.save();
2019-09-02 14:42:29 +00:00
for (const propertyKey of Object.keys(this)) {
const property: any = this[propertyKey];
2018-07-09 22:02:04 +00:00
if (property instanceof SmartDataDbDoc && !savedMapArg.checkForObject(property)) {
property.saveDeep(savedMapArg);
2017-02-25 10:37:05 +00:00
}
2016-09-13 20:53:21 +00:00
}
2017-02-25 10:37:05 +00:00
}
2019-01-08 17:45:30 +00:00
/**
* creates a saveable object so the instance can be persisted as json in the database
*/
2020-02-19 18:30:34 +00:00
public async createSavableObject(): Promise<TImplements> {
const saveableObject: unknown = {}; // is not exposed to outside, so any is ok here
2019-01-08 17:45:30 +00:00
for (const propertyNameString of this.saveableProperties) {
saveableObject[propertyNameString] = this[propertyNameString];
}
2020-02-19 18:30:34 +00:00
return saveableObject as TImplements;
}
2019-01-08 17:45:30 +00:00
/**
* creates an identifiable object for operations that require filtering
*/
public async createIdentifiableObject() {
const identifiableObject: any = {}; // is not exposed to outside, so any is ok here
for (const propertyNameString of this.uniqueIndexes) {
identifiableObject[propertyNameString] = this[propertyNameString];
}
return identifiableObject;
}
2016-09-13 20:53:21 +00:00
}