Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 3,919 Bytes
8969f81 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
import { Utils } from '../lib/Utils';
import db from '../models/Database';
import * as mongodb from 'mongodb';
import { ObjectID, Cursor } from 'mongodb';
export class ObjectFactory {
static create(__type: any, o: any): any {
if (__type.fromObject) {
return __type.fromObject(o);
}
const newObject = new __type();
return Object.assign(newObject, o);
}
}
export class MongoObject {
protected static __type; // The current class
protected static __collectionName: string; // The Mongo collection name
protected static __idField: string = "_id"; // Default id used to findOne
protected static __wlistJsonAttrs: string[] = []; // Whitelist of attributes to serialize.
// Json serialization.
private toJsonRepr(): object {
return Utils.pick(this, (<any>this.constructor).__wlistJsonAttrs);
}
toJson(): string {
return JSON.stringify(this.toJsonRepr());
}
/// Find family of methods
static async findOne<T>(id: string | ObjectID | mongodb.FilterQuery<T>, options?: mongodb.FindOneOptions): Promise<T | null> {
const q = (typeof id === 'string' || id instanceof ObjectID)
? { [this.__idField]: id }
: id;
const o = await db.collection(this.__collectionName).findOne(q, options);
if (o) {
return ObjectFactory.create(this.__type, o);
}
return null;
}
static async findOneAndUpdate<T>(filter: mongodb.FilterQuery<T>, update: Object, options?: mongodb.FindOneAndReplaceOption): Promise<T | null> {
const o = await db.collection(this.__collectionName).findOneAndUpdate(filter, update, options);
if (o && o.value) {
return ObjectFactory.create(this.__type, o.value);
}
return null;
}
static find<T>(query: mongodb.FilterQuery<T> = {}, options?: mongodb.FindOneOptions): HfCursor<T> {
const cursor = db.collection(this.__collectionName).find(query, options);
return HfCursor.cast<T>(cursor, this.__type);
}
}
export class HfCursor<T> extends Cursor<T> {
protected __type;
static cast<T>(cursor: Cursor<T>, type: any): HfCursor<T> {
// “The use of __proto__ is controversial, and has been discouraged.”
// see stackoverflow.com/a/32186367
// see developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
(<any>cursor).__proto__ = HfCursor.prototype;
(<any>cursor).__type = type;
return cursor as HfCursor<T>;
}
toArray(): Promise<T[]> {
return super.toArray().then((objs) => {
return objs.map((o) => {
return ObjectFactory.create(this.__type, o);
});
});
}
forEach(__iterator: mongodb.IteratorCallback<T>, __callback: mongodb.EndCallback = () => {}) {
super.forEach((o) => {
const newObject = ObjectFactory.create(this.__type, o);
__iterator(newObject);
}, __callback);
}
on(event: string, listener: (...args) => void): this {
if (event === 'data') {
super.on('data', (o) => {
const newObject = ObjectFactory.create(this.__type, o);
listener(newObject);
});
}
else {
super.on(event, listener);
}
return this;
}
once(event: string, listener: (...args) => void): this {
if (event === 'data') {
super.once('data', (o) => {
const newObject = ObjectFactory.create(this.__type, o);
listener(newObject);
});
}
else {
super.once(event, listener);
}
return this;
}
//
// Below: cursor methods are only here to make Typescript
// know that they return the HfCursor object itself.
// (We have checked that the mongo driver does the right thing underneath)
//
limit(value: number): HfCursor<T> {
return super.limit(value) as HfCursor<T>;
}
skip(value: number): HfCursor<T> {
return super.skip(value) as HfCursor<T>;
}
sort(keyOrList: string | Object[] | Object, direction?: number): HfCursor<T> {
return super.sort(keyOrList, direction) as HfCursor<T>;
}
stream(options?: { transform?: Function }): HfCursor<T> {
return super.stream(options) as HfCursor<T>;
}
}
|