add NeDB support

This commit is contained in:
Philipp Kunz 2016-11-17 22:36:12 +01:00
parent 38446fc79b
commit dfce8cfcc0
13 changed files with 276 additions and 74 deletions

View File

@ -3,7 +3,7 @@
> Note: Still in Beta > Note: Still in Beta
smartdata is an ODM that adheres to TypeScript practices and uses classes to organize data. smartdata is an ODM that adheres to TypeScript practices and uses classes to organize data.
It uses MongoDB as persistent storage. It uses MongoDB or NeDb as persistent storage.
## Intention ## Intention
There are many ODMs out there, however when we searched for an ODM that uses TypeScript, There are many ODMs out there, however when we searched for an ODM that uses TypeScript,
@ -21,12 +21,16 @@ Document | smartdata.DbDoc
### class Db ### class Db
represents a Database. Naturally it has .connect() etc. methods on it. represents a Database. Naturally it has .connect() etc. methods on it.
Since it is a class you can have multiple DBs defined. Since it is a class you can have multiple DBs defined.
```typescript ```javascript
import * as smartdata from 'smartdata' import * as smartdata from 'smartdata'
// mongodb
let myDb1 = new smartdata.Db('someConnectionUrl') let myDb1 = new smartdata.Db('someConnectionUrl')
let myDb2 = new smartdata.Db('someConnectionUrl') let myDb2 = new smartdata.Db('someConnectionUrl')
// nedb
let myDb3 = new smartdata('/some/path/for/persistence', 'nedb') // you may set first argument to null for just in memory db
myDb1.connect() myDb1.connect()
myDb2.connect() myDb2.connect()
@ -38,7 +42,7 @@ represents a collection of objects.
A collection is defined by the object class (that is extending smartdata.dbdoc) it respresents A collection is defined by the object class (that is extending smartdata.dbdoc) it respresents
So to get to get access to a specific collection you document So to get to get access to a specific collection you document
```typescript ```javascript
// continues from the block before... // continues from the block before...
@Collection(myDb1) @Collection(myDb1)
@ -53,6 +57,8 @@ class myObject extends smartdata.DbDoc<myObject> { // read the next block about
} }
} }
let myCollection = myDb1.getCollectionByName<myObject>(myObject) let myCollection = myDb1.getCollectionByName<myObject>(myObject)
// start to instantiate classes from scratch or database
``` ```
> Alert: You NEVER instantiate a collection. > Alert: You NEVER instantiate a collection.

View File

@ -1,4 +1,3 @@
/// <reference types="nedb" />
/// <reference types="q" /> /// <reference types="q" />
import * as plugins from './smartdata.plugins'; import * as plugins from './smartdata.plugins';
import { Objectmap } from 'lik'; import { Objectmap } from 'lik';
@ -14,7 +13,7 @@ export declare type TConnectionStatus = 'disconnected' | 'connected' | 'failed';
export declare class Db { export declare class Db {
dbType: TDbType; dbType: TDbType;
dbUrl: string; dbUrl: string;
db: plugins.mongodb.Db | plugins.nedb; db: plugins.mongodb.Db;
status: TConnectionStatus; status: TConnectionStatus;
collections: Objectmap<DbCollection<any>>; collections: Objectmap<DbCollection<any>>;
constructor(dbUrlArg: string, dbTypeArg?: TDbType); constructor(dbUrlArg: string, dbTypeArg?: TDbType);

View File

@ -25,7 +25,7 @@ class Db {
}); });
} }
else if (this.dbType === 'nedb') { else if (this.dbType === 'nedb') {
this.db = new plugins.nedb(); this.db = null;
} }
return done.promise; return done.promise;
} }
@ -34,7 +34,9 @@ class Db {
*/ */
close() { close() {
let done = plugins.q.defer(); let done = plugins.q.defer();
this.db.close(); if (this.dbType === 'mongodb') {
this.db.close();
}
plugins.beautylog.ok(`disconnected to database at ${this.dbUrl}`); plugins.beautylog.ok(`disconnected to database at ${this.dbUrl}`);
done.resolve(); done.resolve();
return done.promise; return done.promise;
@ -59,4 +61,4 @@ class Db {
} }
} }
exports.Db = Db; exports.Db = Db;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEuY2xhc3Nlcy5kYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0NBQThDO0FBQzlDLDZCQUErQjtBQWMvQjtJQU9JLFlBQVksUUFBZ0IsRUFBRSxZQUFxQixTQUFTO1FBRjVELGdCQUFXLEdBQUcsSUFBSSxlQUFTLEVBQXFCLENBQUE7UUFHNUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUE7UUFDdkIsSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUE7SUFDekIsQ0FBQztJQUVELHdFQUF3RTtJQUV4RTs7T0FFRztJQUNILE9BQU87UUFDSCxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQzVCLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQztZQUM1QixPQUFPLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUNwRCxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7Z0JBQUMsQ0FBQztnQkFDN0IsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFBO2dCQUMvQixJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQTtnQkFDWixPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUE7Z0JBQ25FLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1lBQ3pCLENBQUMsQ0FBQyxDQUFBO1FBQ04sQ0FBQztRQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDaEMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUNoQyxDQUFDO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSztRQUNELElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDNUIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNmLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLCtCQUErQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQTtRQUNqRSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUE7UUFDZCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUN2QixDQUFDO0lBRUQsNEVBQTRFO0lBRTVFOztPQUVHO0lBQ0gsbUJBQW1CLENBQUksT0FBZTtRQUNsQyxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBcUIsQ0FBQTtRQUMvQyxJQUFJLGdCQUFnQixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsZUFBZTtZQUN6RCxNQUFNLENBQUMsZUFBZSxDQUFDLElBQUksS0FBSyxPQUFPLENBQUE7UUFDM0MsQ0FBQyxDQUFDLENBQUE7UUFDRixFQUFFLENBQUMsQ0FBQyxnQkFBZ0IsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzVCLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQTtRQUNsQyxDQUFDO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztJQUFBLENBQUM7SUFFRixhQUFhLENBQUMsZUFBa0M7UUFDNUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUE7SUFDekMsQ0FBQztDQUNKO0FBL0RELGdCQStEQyJ9 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLmNsYXNzZXMuZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEuY2xhc3Nlcy5kYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0NBQThDO0FBQzlDLDZCQUErQjtBQWMvQjtJQU9JLFlBQVksUUFBZ0IsRUFBRSxZQUFxQixTQUFTO1FBRjVELGdCQUFXLEdBQUcsSUFBSSxlQUFTLEVBQXFCLENBQUE7UUFHNUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUE7UUFDdkIsSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUE7SUFDekIsQ0FBQztJQUVELHdFQUF3RTtJQUV4RTs7T0FFRztJQUNILE9BQU87UUFDSCxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQzVCLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQztZQUM1QixPQUFPLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUNwRCxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7Z0JBQUMsQ0FBQztnQkFDN0IsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFBO2dCQUMvQixJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQTtnQkFDWixPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUE7Z0JBQ25FLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1lBQ3pCLENBQUMsQ0FBQyxDQUFBO1FBQ04sQ0FBQztRQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDaEMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUE7UUFDbEIsQ0FBQztRQUNELE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFBO0lBQ3ZCLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUs7UUFDRCxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQzVCLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQztZQUM1QixJQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ25CLENBQUM7UUFDRCxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQywrQkFBK0IsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUE7UUFDakUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQ2QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztJQUVELDRFQUE0RTtJQUU1RTs7T0FFRztJQUNILG1CQUFtQixDQUFJLE9BQWU7UUFDbEMsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQXFCLENBQUE7UUFDL0MsSUFBSSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLGVBQWU7WUFDekQsTUFBTSxDQUFDLGVBQWUsQ0FBQyxJQUFJLEtBQUssT0FBTyxDQUFBO1FBQzNDLENBQUMsQ0FBQyxDQUFBO1FBQ0YsRUFBRSxDQUFDLENBQUMsZ0JBQWdCLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQztZQUM1QixJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUE7UUFDbEMsQ0FBQztRQUNELE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFBO0lBQ3ZCLENBQUM7SUFBQSxDQUFDO0lBRUYsYUFBYSxDQUFDLGVBQWtDO1FBQzVDLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFBO0lBQ3pDLENBQUM7Q0FFSjtBQWxFRCxnQkFrRUMifQ==

View File

@ -4,29 +4,38 @@ import { Db } from './smartdata.classes.db';
export interface IFindOptions { export interface IFindOptions {
limit?: number; limit?: number;
} }
export interface IDocValidation<T> {
(doc: T): boolean;
}
export declare function Collection(db: Db): (constructor: any) => void; export declare function Collection(db: Db): (constructor: any) => void;
export declare class DbCollection<T> { export declare class DbCollection<T> {
/** /**
* the collection that is used * the collection that is used, defaults to mongodb collection,
* can be nedb datastore (sub api of mongodb)
*/ */
collection: plugins.mongodb.Collection; collection: plugins.mongodb.Collection;
name: string; name: string;
db: Db;
objectValidation: IDocValidation<T>;
constructor(nameArg: string, dbArg: Db); constructor(nameArg: string, dbArg: Db);
/** /**
* adds a validation function that all newly inserted and updated objects have to pass * adds a validation function that all newly inserted and updated objects have to pass
*/ */
addObjectValidation(funcArg: any): void; addDocValidation(funcArg: IDocValidation<T>): void;
/** /**
* finds an object in the DbCollection * finds an object in the DbCollection
*/ */
find(docMatchArg: T | any, optionsArg?: IFindOptions): plugins.q.Promise<T[]>; find(docMatchArg: T | any, optionsArg?: IFindOptions): plugins.q.Promise<T[]>;
/** /**
* inserts object into the DbCollection * inserts object into the DbCollection
*/ */
insertOne(docArg: T): plugins.q.Promise<void>; insertOne(docArg: T): plugins.q.Promise<void>;
/** /**
* inserts many objects at once into the DbCollection * inserts many objects at once into the DbCollection
*/ */
insertMany(docArrayArg: T[]): plugins.q.Promise<void>; insertMany(docArrayArg: T[]): plugins.q.Promise<void>;
private checkDoc(doc); /**
* checks a Doc for constraints
*/
private checkDoc(docArg);
} }

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,8 @@
import 'typings-global'; import 'typings-global';
export import assert = require('assert'); import * as assert from 'assert';
export import beautylog = require('beautylog'); import * as beautylog from 'beautylog';
export import mongodb = require('mongodb'); import * as lodash from 'lodash';
export import q = require('q'); import * as mongodb from 'mongodb';
export import nedb = require('nedb'); import * as q from 'q';
declare let nedb: any;
export { assert, beautylog, lodash, mongodb, q, nedb };

View File

@ -1,8 +1,15 @@
"use strict"; "use strict";
require("typings-global"); require("typings-global");
exports.assert = require("assert"); const assert = require("assert");
exports.beautylog = require("beautylog"); exports.assert = assert;
exports.mongodb = require("mongodb"); const beautylog = require("beautylog");
exports.q = require("q"); exports.beautylog = beautylog;
exports.nedb = require("nedb"); const lodash = require("lodash");
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEJBQXVCO0FBQ3ZCLG1DQUF3QztBQUN4Qyx5Q0FBOEM7QUFDOUMscUNBQTBDO0FBQzFDLHlCQUE4QjtBQUM5QiwrQkFBb0MifQ== exports.lodash = lodash;
const mongodb = require("mongodb");
exports.mongodb = mongodb;
const q = require("q");
exports.q = q;
let nedb = require('nedb');
exports.nedb = nedb;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRkYXRhLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGRhdGEucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEJBQXVCO0FBQ3ZCLGlDQUFnQztBQVE1Qix3QkFBTTtBQVBWLHVDQUFzQztBQVFsQyw4QkFBUztBQVBiLGlDQUFnQztBQVE1Qix3QkFBTTtBQVBWLG1DQUFrQztBQVE5QiwwQkFBTztBQVBYLHVCQUFzQjtBQVFsQixjQUFDO0FBUEwsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0FBUXRCLG9CQUFJIn0=

View File

@ -19,11 +19,13 @@
}, },
"homepage": "https://gitlab.com/pushrocks/smartdata#README", "homepage": "https://gitlab.com/pushrocks/smartdata#README",
"dependencies": { "dependencies": {
"@types/lodash": "^4.14.39",
"@types/mongodb": "^2.1.34", "@types/mongodb": "^2.1.34",
"@types/nedb": "0.0.31", "@types/nedb": "0.0.31",
"@types/q": "0.0.32", "@types/q": "0.0.32",
"beautylog": "^6.0.0", "beautylog": "^6.0.0",
"lik": "^1.0.24", "lik": "^1.0.24",
"lodash": "^4.17.2",
"mongodb": "^2.2.11", "mongodb": "^2.2.11",
"nedb": "^1.8.0", "nedb": "^1.8.0",
"q": "^1.4.1", "q": "^1.4.1",

File diff suppressed because one or more lines are too long

View File

@ -89,7 +89,7 @@ describe('smartdata', function () {
should(testCarInstance.collection).be.instanceof(smartdata.DbCollection) should(testCarInstance.collection).be.instanceof(smartdata.DbCollection)
should(testCarInstance).be.instanceof(smartdata.DbDoc) should(testCarInstance).be.instanceof(smartdata.DbDoc)
testCarInstance.save() testCarInstance.save()
it('should get a collection for testCar',function() { it('should get a collection for testCar', function () {
}) })
}) })
@ -107,3 +107,24 @@ describe('mongodb', function () {
mongoChildProcess.kill('SIGTERM') mongoChildProcess.kill('SIGTERM')
}) })
}) })
describe('smartdata with nedb', function () {
let testDb: smartdata.Db
let testCollection: smartdata.DbCollection<ITestObject1>
it('should create a DB with nedb', function () {
testDb = new smartdata.Db('any', 'nedb')
testDb.connect()
testCollection = new smartdata.DbCollection<ITestObject1>('anyName', testDb)
})
it('should insert a doc', function(done){
testCollection.insertOne({ value1: 'hi' }).then(() => {done()})
})
it('should find the inserted document', function(done){
testCollection.find({ value1: 'hi' }).then(x => {
console.log(x)
done()
})
})
})

View File

@ -16,7 +16,7 @@ export type TConnectionStatus = 'disconnected' | 'connected' | 'failed'
export class Db { export class Db {
dbType: TDbType dbType: TDbType
dbUrl: string dbUrl: string
db: plugins.mongodb.Db | plugins.nedb db: plugins.mongodb.Db
status: TConnectionStatus status: TConnectionStatus
collections = new Objectmap<DbCollection<any>>() collections = new Objectmap<DbCollection<any>>()
@ -41,7 +41,7 @@ export class Db {
done.resolve(this.db) done.resolve(this.db)
}) })
} else if (this.dbType === 'nedb') { } else if (this.dbType === 'nedb') {
this.db = new plugins.nedb() this.db = null
} }
return done.promise return done.promise
} }
@ -51,7 +51,9 @@ export class Db {
*/ */
close(): plugins.q.Promise<any> { close(): plugins.q.Promise<any> {
let done = plugins.q.defer() let done = plugins.q.defer()
this.db.close() if (this.dbType === 'mongodb') {
this.db.close()
}
plugins.beautylog.ok(`disconnected to database at ${this.dbUrl}`) plugins.beautylog.ok(`disconnected to database at ${this.dbUrl}`)
done.resolve() done.resolve()
return done.promise return done.promise
@ -76,4 +78,5 @@ export class Db {
addCollection(dbCollectionArg: DbCollection<any>) { addCollection(dbCollectionArg: DbCollection<any>) {
this.collections.add(dbCollectionArg) this.collections.add(dbCollectionArg)
} }
} }

View File

@ -5,53 +5,96 @@ export interface IFindOptions {
limit?: number limit?: number
} }
export interface IDocValidation<T> {
(doc: T): boolean
}
export function Collection(db: Db) { export function Collection(db: Db) {
return function(constructor){ return function (constructor) {
constructor['dbCollection'] = new DbCollection(constructor.name, db) constructor['dbCollection'] = new DbCollection(constructor.name, db)
} }
} }
export class DbCollection<T> { export class DbCollection<T> {
/** /**
* the collection that is used * the collection that is used, defaults to mongodb collection,
* can be nedb datastore (sub api of mongodb)
*/ */
collection: plugins.mongodb.Collection collection: plugins.mongodb.Collection
name: string name: string
db: Db
objectValidation: IDocValidation<T> = null
constructor(nameArg: string, dbArg: Db) { constructor(nameArg: string, dbArg: Db) {
this.name = nameArg this.name = nameArg
this.collection = dbArg.db.collection(nameArg) this.db = dbArg
if (this.db.dbType === 'mongodb') {
this.collection = dbArg.db.collection(nameArg)
} else {
this.collection = new plugins.nedb()
}
} }
/** /**
* adds a validation function that all newly inserted and updated objects have to pass * adds a validation function that all newly inserted and updated objects have to pass
*/ */
addObjectValidation(funcArg) { } addDocValidation(funcArg: IDocValidation<T>) {
this.objectValidation = funcArg
}
/** /**
* finds an object in the DbCollection * finds an object in the DbCollection
*/ */
find(docMatchArg: T | any, optionsArg?: IFindOptions): plugins.q.Promise<T[]> { find(docMatchArg: T | any, optionsArg?: IFindOptions): plugins.q.Promise<T[]> {
let done = plugins.q.defer<T[]>() let done = plugins.q.defer<T[]>()
let findCursor = this.collection.find(docMatchArg) if (this.db.dbType === 'mongodb') {
if (optionsArg) { let findCursor = this.collection.find(docMatchArg)
if ( optionsArg.limit ) { findCursor = findCursor.limit(1) } if (optionsArg) {
if (optionsArg.limit) { findCursor = findCursor.limit(1) }
}
findCursor.toArray((err, docs) => {
if (err) {
done.reject(err)
throw err
}
done.resolve(docs)
})
} else if (this.db.dbType === 'nedb') {
this.collection.find(docMatchArg, (err, docs) => {
if (err) {
done.reject(err)
throw err
}
done.resolve(docs)
})
} }
findCursor.toArray((err, docs) => {
if (err) { throw err }
done.resolve(docs)
})
return done.promise return done.promise
} }
/** /**
* inserts object into the DbCollection * inserts object into the DbCollection
*/ */
insertOne(docArg: T): plugins.q.Promise<void> { insertOne(docArg: T): plugins.q.Promise<void> {
let done = plugins.q.defer<void>() let done = plugins.q.defer<void>()
this.checkDoc(docArg).then(() => { this.checkDoc(docArg).then(
this.collection.insertOne(docArg) () => {
.then(() => { done.resolve() }) if (this.db.dbType === 'mongodb') {
}) this.collection.insertOne(docArg)
.then(() => { done.resolve() })
} else if (this.db.dbType === 'nedb') {
this.collection.insert(docArg, (err, newDoc) => {
if (err) {
done.reject(err)
throw err
}
done.resolve()
})
}
},
() => {
done.reject(new Error('one the docs did not pass validation'))
})
return done.promise return done.promise
} }
@ -61,19 +104,41 @@ export class DbCollection<T> {
insertMany(docArrayArg: T[]): plugins.q.Promise<void> { insertMany(docArrayArg: T[]): plugins.q.Promise<void> {
let done = plugins.q.defer<void>() let done = plugins.q.defer<void>()
let checkDocPromiseArray: plugins.q.Promise<void>[] = [] let checkDocPromiseArray: plugins.q.Promise<void>[] = []
for (let docArg of docArrayArg){ for (let docArg of docArrayArg) {
checkDocPromiseArray.push(this.checkDoc(docArg)) checkDocPromiseArray.push(this.checkDoc(docArg))
} }
plugins.q.all(checkDocPromiseArray).then(() => { plugins.q.all(checkDocPromiseArray).then(() => {
this.collection.insertMany(docArrayArg) if (this.db.dbType === 'mongodb') {
.then(() => { done.resolve() }) this.collection.insertMany(docArrayArg)
.then(() => { done.resolve() })
} else if (this.db.dbType === 'nedb') {
let paramArray = plugins.lodash.concat<any>(docArrayArg, (err, newDoc) => {
if (err) {
done.reject(err)
throw err
}
done.resolve()
})
this.collection.insert.apply(null, paramArray)
}
}) })
return done.promise return done.promise
} }
private checkDoc(doc: T): plugins.q.Promise<void> { /**
* checks a Doc for constraints
*/
private checkDoc(docArg: T): plugins.q.Promise<void> {
let done = plugins.q.defer<void>() let done = plugins.q.defer<void>()
done.resolve() let validationResult = true
if (this.objectValidation) {
validationResult = this.objectValidation(docArg)
}
if (validationResult) {
done.resolve()
} else {
done.reject('validation of object did not pass')
}
return done.promise return done.promise
} }
} }

View File

@ -1,6 +1,16 @@
import 'typings-global' import 'typings-global'
export import assert = require('assert') import * as assert from 'assert'
export import beautylog = require('beautylog') import * as beautylog from 'beautylog'
export import mongodb = require('mongodb') import * as lodash from 'lodash'
export import q = require('q') import * as mongodb from 'mongodb'
export import nedb = require('nedb') import * as q from 'q'
let nedb = require('nedb')
export {
assert,
beautylog,
lodash,
mongodb,
q,
nedb
}