2018-07-08 21:48:14 +00:00
|
|
|
import * as plugins from './smartdata.plugins';
|
2016-09-13 20:53:21 +00:00
|
|
|
|
2019-01-07 01:50:09 +00:00
|
|
|
import { Objectmap } from '@pushrocks/lik';
|
2017-02-25 10:37:05 +00:00
|
|
|
|
2018-07-08 21:48:14 +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
|
|
|
|
2018-07-08 21:48:14 +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() {
|
2018-07-09 22:02:04 +00:00
|
|
|
return (target: SmartDataDbDoc<any>, key: string) => {
|
2018-07-10 19:27:16 +00:00
|
|
|
console.log(`called svDb() on ${key}`);
|
2018-01-14 16:32:04 +00:00
|
|
|
if (!target.saveableProperties) {
|
|
|
|
target.saveableProperties = [];
|
|
|
|
}
|
|
|
|
target.saveableProperties.push(key);
|
|
|
|
};
|
2016-11-17 23:42:25 +00:00
|
|
|
}
|
2016-09-13 23:02:11 +00:00
|
|
|
|
2018-07-10 19:27:16 +00:00
|
|
|
/**
|
|
|
|
* unique index - decorator to mark a unique index
|
|
|
|
*/
|
|
|
|
export function unI() {
|
|
|
|
return (target: SmartDataDbDoc<any>, 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
|
|
|
}
|
2018-07-10 19:27:16 +00:00
|
|
|
|
2018-07-09 22:02:04 +00:00
|
|
|
export class SmartDataDbDoc<T> {
|
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
|
|
|
|
2018-07-10 19:27:16 +00:00
|
|
|
/**
|
|
|
|
* unique indexes
|
|
|
|
*/
|
2019-09-02 14:42:29 +00:00
|
|
|
public uniqueIndexes: string[];
|
2018-07-10 19:27:16 +00:00
|
|
|
|
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
|
|
|
|
2018-01-12 00:22:58 +00:00
|
|
|
/**
|
|
|
|
* primary id in the database
|
|
|
|
*/
|
2019-09-02 14:42:29 +00:00
|
|
|
public dbDocUniqueId: string;
|
2018-01-12 00:22:58 +00:00
|
|
|
|
2017-02-25 10:37:05 +00:00
|
|
|
/**
|
|
|
|
* class constructor
|
|
|
|
*/
|
2018-01-14 16:32:04 +00:00
|
|
|
constructor() {
|
2018-07-08 21:48:14 +00:00
|
|
|
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');
|
|
|
|
}
|
2018-01-14 16:32:04 +00:00
|
|
|
}
|
|
|
|
|
2019-09-02 14:42:29 +00:00
|
|
|
public static async getInstances<T>(filterArg): Promise<T[]> {
|
|
|
|
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);
|
2018-01-14 16:32:04 +00:00
|
|
|
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 in item) {
|
2018-07-08 21:48:14 +00:00
|
|
|
if (key !== 'id') {
|
2018-01-14 16:32:04 +00:00
|
|
|
newInstance[key] = item[key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
returnArray.push(newInstance);
|
|
|
|
}
|
|
|
|
return returnArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
static async getInstance<T>(filterArg): Promise<T> {
|
2019-09-02 14:42:29 +00:00
|
|
|
const result = await this.getInstances<T>(filterArg);
|
2018-07-08 21:48:14 +00:00
|
|
|
if (result && result.length > 0) {
|
|
|
|
return result[0];
|
2018-01-14 16:32:04 +00:00
|
|
|
}
|
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;
|
2018-01-12 00:22:58 +00:00
|
|
|
switch (this.creationStatus) {
|
2018-07-08 21:48:14 +00:00
|
|
|
case 'db':
|
2018-01-14 16:32:04 +00:00
|
|
|
await this.collection.update(self);
|
|
|
|
break;
|
2018-07-08 21:48:14 +00:00
|
|
|
case 'new':
|
2019-09-02 14:42:29 +00:00
|
|
|
const writeResult = await this.collection.insert(self);
|
2018-07-08 21:48:14 +00:00
|
|
|
this.creationStatus = 'db';
|
2018-01-12 00:22:58 +00:00
|
|
|
break;
|
|
|
|
default:
|
2018-07-08 21:48:14 +00:00
|
|
|
console.error('neither new nor in db?');
|
2017-02-25 10:37:05 +00:00
|
|
|
}
|
|
|
|
}
|
2016-09-13 23:02:11 +00:00
|
|
|
|
2019-01-08 17:45:30 +00:00
|
|
|
/**
|
|
|
|
* deletes a document from the database
|
|
|
|
*/
|
2019-09-02 14:42:29 +00:00
|
|
|
public async delete() {}
|
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
|
|
|
|
*/
|
2019-09-02 14:42:29 +00:00
|
|
|
public saveDeep(savedMapArg: Objectmap<SmartDataDbDoc<any>> = null) {
|
2017-02-25 10:37:05 +00:00
|
|
|
if (!savedMapArg) {
|
2018-07-09 22:02:04 +00:00
|
|
|
savedMapArg = new Objectmap<SmartDataDbDoc<any>>();
|
2017-02-25 10:37:05 +00:00
|
|
|
}
|
2018-01-14 16:32:04 +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)) {
|
2018-01-14 16:32:04 +00:00
|
|
|
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
|
|
|
}
|
2018-01-12 00:22:58 +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
|
|
|
|
*/
|
|
|
|
public async createSavableObject() {
|
|
|
|
const saveableObject: any = {}; // is not exposed to outside, so any is ok here
|
|
|
|
for (const propertyNameString of this.saveableProperties) {
|
2018-01-14 16:32:04 +00:00
|
|
|
saveableObject[propertyNameString] = this[propertyNameString];
|
2018-01-12 00:22:58 +00:00
|
|
|
}
|
2018-01-14 16:32:04 +00:00
|
|
|
return saveableObject;
|
2018-01-12 00:22:58 +00:00
|
|
|
}
|
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
|
|
|
}
|