fix(core): update
This commit is contained in:
		
							
								
								
									
										15
									
								
								test/test.ts
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								test/test.ts
									
									
									
									
									
								
							@@ -200,14 +200,19 @@ class Truck extends smartdata.SmartDataDbDoc<Car, Car> {
 | 
			
		||||
tap.test('should store a new Truck', async () => {
 | 
			
		||||
  const truck = new Truck('blue', 'MAN');
 | 
			
		||||
  await truck.save();
 | 
			
		||||
  const myTruck = await Truck.getInstance({ color: 'blue' });
 | 
			
		||||
  myTruck.id = 'foo';
 | 
			
		||||
  await myTruck.save();
 | 
			
		||||
  const myTruck2 = await Truck.getInstance({ color: 'blue' });
 | 
			
		||||
  console.log(myTruck2);
 | 
			
		||||
  myTruck2.color = 'red';
 | 
			
		||||
  await myTruck2.save();
 | 
			
		||||
  const myTruck3 = await Truck.getInstance({ color: 'blue' });
 | 
			
		||||
  console.log(myTruck3);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should ', async () => {});
 | 
			
		||||
tap.test('should use a cursor', async () => {
 | 
			
		||||
  const cursor = await Truck.getCursor({});
 | 
			
		||||
  cursor.forEach(async truckArg => {
 | 
			
		||||
    console.log(truckArg.id);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// =======================================
 | 
			
		||||
// close the database connection
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import * as plugins from './smartdata.plugins';
 | 
			
		||||
import { SmartdataDb } from './smartdata.classes.db';
 | 
			
		||||
import { SmartdataDbCursor } from './smartdata.classes.cursor';
 | 
			
		||||
import { SmartDataDbDoc } from './smartdata.classes.doc';
 | 
			
		||||
import { CollectionFactory } from './smartdata.classes.collectionfactory';
 | 
			
		||||
 | 
			
		||||
@@ -170,9 +171,28 @@ export class SmartdataCollection<T> {
 | 
			
		||||
  /**
 | 
			
		||||
   * finds an object in the DbCollection
 | 
			
		||||
   */
 | 
			
		||||
  public async find(filterObject: any): Promise<any> {
 | 
			
		||||
   public async findOne(filterObject: any): Promise<any> {
 | 
			
		||||
    await this.init();
 | 
			
		||||
    const result = await this.mongoDbCollection.find(filterObject).toArray();
 | 
			
		||||
    const cursor = this.mongoDbCollection.find(filterObject);
 | 
			
		||||
    const result = await cursor.next();
 | 
			
		||||
    cursor.close();
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async getCursor(filterObject: any): Promise<SmartdataDbCursor<any>> {
 | 
			
		||||
    await this.init();
 | 
			
		||||
    const cursor = this.mongoDbCollection.find(filterObject);
 | 
			
		||||
    return new SmartdataDbCursor(cursor);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * finds an object in the DbCollection
 | 
			
		||||
   */
 | 
			
		||||
  public async findAll(filterObject: any): Promise<any[]> {
 | 
			
		||||
    await this.init();
 | 
			
		||||
    const cursor = this.mongoDbCollection.find(filterObject);
 | 
			
		||||
    const result = await cursor.toArray();
 | 
			
		||||
    cursor.close();
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										39
									
								
								ts/smartdata.classes.cursor.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								ts/smartdata.classes.cursor.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
import * as plugins from './smartdata.plugins';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * a wrapper for the native mongodb cursor. Exposes better 
 | 
			
		||||
 */
 | 
			
		||||
export class SmartdataDbCursor<T = any> {
 | 
			
		||||
  // STATIC
 | 
			
		||||
 | 
			
		||||
  // INSTANCE
 | 
			
		||||
  public mongodbCursor: plugins.mongodb.Cursor<T>;
 | 
			
		||||
  constructor(cursorArg: plugins.mongodb.Cursor<T>) {
 | 
			
		||||
    this.mongodbCursor = cursorArg
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  public async next(closeAtEnd = true) {
 | 
			
		||||
    const result = await this.mongodbCursor.next();
 | 
			
		||||
    if (!result && closeAtEnd) {
 | 
			
		||||
      await this.close();
 | 
			
		||||
    };
 | 
			
		||||
    return result;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  public async forEach(forEachFuncArg: (itemArg: T) => Promise<any>, closeCursorAtEnd = true) {
 | 
			
		||||
    let currentValue: T;
 | 
			
		||||
    do {
 | 
			
		||||
      currentValue = await this.mongodbCursor.next();
 | 
			
		||||
      if (currentValue) {
 | 
			
		||||
        await forEachFuncArg(currentValue);
 | 
			
		||||
      }
 | 
			
		||||
    } while (currentValue);
 | 
			
		||||
    if (closeCursorAtEnd) {
 | 
			
		||||
      await this.close();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async close() {
 | 
			
		||||
    await this.mongodbCursor.close();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,6 +3,7 @@ import * as plugins from './smartdata.plugins';
 | 
			
		||||
import { ObjectMap } from '@pushrocks/lik';
 | 
			
		||||
 | 
			
		||||
import { SmartdataDb } from './smartdata.classes.db';
 | 
			
		||||
import { SmartdataDbCursor } from './smartdata.classes.cursor';
 | 
			
		||||
import { IManager, SmartdataCollection } from './smartdata.classes.collection';
 | 
			
		||||
 | 
			
		||||
export type TDocCreation = 'db' | 'new' | 'mixed';
 | 
			
		||||
@@ -41,6 +42,31 @@ export function unI() {
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const convertFilterForMongoDb = (filterArg: { [key: string]: any }) => {
 | 
			
		||||
  const convertedFilter: { [key: string]: any } = {};
 | 
			
		||||
  const convertFilterArgument = (keyPathArg2: string, filterArg2: any) => {
 | 
			
		||||
    if (typeof filterArg2 === 'object') {
 | 
			
		||||
      for (const key of Object.keys(filterArg2)) {
 | 
			
		||||
        if (key.startsWith('$')) {
 | 
			
		||||
          convertedFilter[keyPathArg2] = filterArg2;
 | 
			
		||||
          return;
 | 
			
		||||
        } else if (key.includes('.')) {
 | 
			
		||||
          throw new Error('keys cannot contain dots');
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      for (const key of Object.keys(filterArg2)) {
 | 
			
		||||
        convertFilterArgument(`${keyPathArg2}.${key}`, filterArg2[key]);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      convertedFilter[keyPathArg2] = filterArg2;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  for (const key of Object.keys(filterArg)) {
 | 
			
		||||
    convertFilterArgument(key, filterArg[key]);
 | 
			
		||||
  }
 | 
			
		||||
  return convertedFilter;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends IManager = any> {
 | 
			
		||||
  /**
 | 
			
		||||
   * the collection object an Doc belongs to
 | 
			
		||||
@@ -81,54 +107,81 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
 | 
			
		||||
   */
 | 
			
		||||
  constructor() {}
 | 
			
		||||
 | 
			
		||||
  public static createInstanceFromMongoDbNativeDoc<T>(
 | 
			
		||||
    this: plugins.tsclass.typeFest.Class<T>,
 | 
			
		||||
    mongoDbNativeDocArg: any
 | 
			
		||||
  ): T {
 | 
			
		||||
    const newInstance = new this();
 | 
			
		||||
    (newInstance as any).creationStatus = 'db';
 | 
			
		||||
    for (const key of Object.keys(mongoDbNativeDocArg)) {
 | 
			
		||||
      newInstance[key] = mongoDbNativeDocArg[key];
 | 
			
		||||
    }
 | 
			
		||||
    return newInstance;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * gets all instances as array
 | 
			
		||||
   * @param this
 | 
			
		||||
   * @param filterArg
 | 
			
		||||
   * @returns
 | 
			
		||||
   */
 | 
			
		||||
  public static async getInstances<T>(
 | 
			
		||||
    this: plugins.tsclass.typeFest.Class<T>,
 | 
			
		||||
    filterArg: plugins.tsclass.typeFest.PartialDeep<T>
 | 
			
		||||
  ): Promise<T[]> {
 | 
			
		||||
    const convertedFilter: any = {};
 | 
			
		||||
    const convertFilterArgument = (keyPathArg: string, filterArg2: any) => {
 | 
			
		||||
      if (typeof filterArg2 === 'object') {
 | 
			
		||||
        for (const key of Object.keys(filterArg2)) {
 | 
			
		||||
          if (key.startsWith('$')) {
 | 
			
		||||
            convertedFilter[keyPathArg] = filterArg2;
 | 
			
		||||
            return;
 | 
			
		||||
          } else if (key.includes('.')) {
 | 
			
		||||
            throw new Error('keys cannot contain dots');
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        for (const key of Object.keys(filterArg2)) {
 | 
			
		||||
          convertFilterArgument(`${keyPathArg}.${key}`, filterArg2[key]);
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        convertedFilter[keyPathArg] = filterArg2;
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
    for (const key of Object.keys(filterArg)) {
 | 
			
		||||
      convertFilterArgument(key, filterArg[key]);
 | 
			
		||||
    }
 | 
			
		||||
    const foundDocs = await (this as any).collection.find(convertedFilter);
 | 
			
		||||
    const foundDocs = await (this as any).collection.findAll(convertFilterForMongoDb(filterArg));
 | 
			
		||||
    const returnArray = [];
 | 
			
		||||
    for (const item of foundDocs) {
 | 
			
		||||
      const newInstance = new this();
 | 
			
		||||
      (newInstance as any).creationStatus = 'db';
 | 
			
		||||
      for (const key of Object.keys(item)) {
 | 
			
		||||
        newInstance[key] = item[key];
 | 
			
		||||
      }
 | 
			
		||||
    for (const foundDoc of foundDocs) {
 | 
			
		||||
      const newInstance: T = (this as any).createInstanceFromMongoDbNativeDoc(foundDoc);
 | 
			
		||||
      returnArray.push(newInstance);
 | 
			
		||||
    }
 | 
			
		||||
    return returnArray;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * gets the first matching instance
 | 
			
		||||
   * @param this
 | 
			
		||||
   * @param filterArg
 | 
			
		||||
   * @returns
 | 
			
		||||
   */
 | 
			
		||||
  public static async getInstance<T>(
 | 
			
		||||
    this: plugins.tsclass.typeFest.Class<T>,
 | 
			
		||||
    filterArg: plugins.tsclass.typeFest.PartialDeep<T>
 | 
			
		||||
  ): Promise<T> {
 | 
			
		||||
    const result = await (this as any).getInstances(filterArg);
 | 
			
		||||
    if (result && result.length > 0) {
 | 
			
		||||
      return result[0];
 | 
			
		||||
    const foundDoc = await (this as any).collection.findOne(convertFilterForMongoDb(filterArg));
 | 
			
		||||
    if (foundDoc) {
 | 
			
		||||
      const newInstance: T = (this as any).createInstanceFromMongoDbNativeDoc(foundDoc);
 | 
			
		||||
      return newInstance;
 | 
			
		||||
    } else {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * get cursor
 | 
			
		||||
   * @returns
 | 
			
		||||
   */
 | 
			
		||||
  public static async getCursor<T>(
 | 
			
		||||
    this: plugins.tsclass.typeFest.Class<T>,
 | 
			
		||||
    filterArg: plugins.tsclass.typeFest.PartialDeep<T>
 | 
			
		||||
  ) {
 | 
			
		||||
    const cursor: SmartdataDbCursor<T> = await (this as any).collection.getCursor(convertFilterForMongoDb(filterArg));
 | 
			
		||||
    return cursor;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * run a function for all instances
 | 
			
		||||
   * @returns
 | 
			
		||||
   */
 | 
			
		||||
  public static async forEach<T>(
 | 
			
		||||
    this: plugins.tsclass.typeFest.Class<T>,
 | 
			
		||||
    filterArg: plugins.tsclass.typeFest.PartialDeep<T>,
 | 
			
		||||
    forEachFunction: (itemArg: T) => Promise<any>
 | 
			
		||||
  ) {
 | 
			
		||||
    const cursor: SmartdataDbCursor<T> = await (this as any).getCursor(filterArg);
 | 
			
		||||
    await cursor.forEach(forEachFunction)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * saves this instance but not any connected items
 | 
			
		||||
   * may lead to data inconsistencies, but is faster
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user