2016-09-11 16:01:46 +00:00
|
|
|
import * as plugins from './smartdata.plugins'
|
2016-09-12 21:47:57 +00:00
|
|
|
import { Db } from './smartdata.classes.db'
|
2016-09-11 16:01:46 +00:00
|
|
|
|
2016-09-13 20:53:21 +00:00
|
|
|
export interface IFindOptions {
|
|
|
|
limit?: number
|
|
|
|
}
|
|
|
|
|
2016-11-17 21:36:12 +00:00
|
|
|
export interface IDocValidation<T> {
|
|
|
|
(doc: T): boolean
|
|
|
|
}
|
|
|
|
|
2016-09-13 23:02:11 +00:00
|
|
|
export function Collection(db: Db) {
|
2016-11-17 21:36:12 +00:00
|
|
|
return function (constructor) {
|
2016-09-13 23:02:11 +00:00
|
|
|
constructor['dbCollection'] = new DbCollection(constructor.name, db)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-11 16:01:46 +00:00
|
|
|
export class DbCollection<T> {
|
2016-11-17 11:20:52 +00:00
|
|
|
/**
|
2016-11-17 21:36:12 +00:00
|
|
|
* the collection that is used, defaults to mongodb collection,
|
|
|
|
* can be nedb datastore (sub api of mongodb)
|
2016-11-17 11:20:52 +00:00
|
|
|
*/
|
2016-09-11 16:01:46 +00:00
|
|
|
collection: plugins.mongodb.Collection
|
2016-09-13 20:53:21 +00:00
|
|
|
name: string
|
2016-11-17 21:36:12 +00:00
|
|
|
db: Db
|
|
|
|
objectValidation: IDocValidation<T> = null
|
|
|
|
|
|
|
|
|
2016-09-12 21:47:57 +00:00
|
|
|
constructor(nameArg: string, dbArg: Db) {
|
2017-02-25 10:37:05 +00:00
|
|
|
// tell the collection where it belongs
|
2016-09-13 20:53:21 +00:00
|
|
|
this.name = nameArg
|
2016-11-17 21:36:12 +00:00
|
|
|
this.db = dbArg
|
2017-02-25 10:37:05 +00:00
|
|
|
|
|
|
|
// make sure it actually exists
|
2016-11-17 21:36:12 +00:00
|
|
|
if (this.db.dbType === 'mongodb') {
|
|
|
|
this.collection = dbArg.db.collection(nameArg)
|
|
|
|
} else {
|
|
|
|
this.collection = new plugins.nedb()
|
|
|
|
}
|
2017-02-25 10:37:05 +00:00
|
|
|
|
|
|
|
// tell the db class about it (important since Db uses different systems under the hood)
|
|
|
|
this.db.addCollection(this)
|
2016-09-11 16:01:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* adds a validation function that all newly inserted and updated objects have to pass
|
|
|
|
*/
|
2016-11-17 21:36:12 +00:00
|
|
|
addDocValidation(funcArg: IDocValidation<T>) {
|
|
|
|
this.objectValidation = funcArg
|
|
|
|
}
|
2016-09-11 16:01:46 +00:00
|
|
|
|
|
|
|
/**
|
2016-09-12 15:31:23 +00:00
|
|
|
* finds an object in the DbCollection
|
2016-09-11 16:01:46 +00:00
|
|
|
*/
|
2016-09-13 20:53:21 +00:00
|
|
|
find(docMatchArg: T | any, optionsArg?: IFindOptions): plugins.q.Promise<T[]> {
|
2016-09-12 16:14:01 +00:00
|
|
|
let done = plugins.q.defer<T[]>()
|
2016-11-17 21:36:12 +00:00
|
|
|
if (this.db.dbType === 'mongodb') {
|
|
|
|
let findCursor = this.collection.find(docMatchArg)
|
|
|
|
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)
|
|
|
|
})
|
2016-09-13 20:53:21 +00:00
|
|
|
}
|
2016-09-12 16:14:01 +00:00
|
|
|
return done.promise
|
2016-09-12 15:31:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-11-17 21:36:12 +00:00
|
|
|
* inserts object into the DbCollection
|
2016-09-12 15:31:23 +00:00
|
|
|
*/
|
2016-09-12 16:14:01 +00:00
|
|
|
insertOne(docArg: T): plugins.q.Promise<void> {
|
|
|
|
let done = plugins.q.defer<void>()
|
2016-11-17 21:36:12 +00:00
|
|
|
this.checkDoc(docArg).then(
|
|
|
|
() => {
|
|
|
|
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'))
|
|
|
|
})
|
2016-09-12 16:14:01 +00:00
|
|
|
return done.promise
|
2016-09-12 15:31:23 +00:00
|
|
|
}
|
2016-09-11 16:01:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* inserts many objects at once into the DbCollection
|
|
|
|
*/
|
2016-09-12 16:14:01 +00:00
|
|
|
insertMany(docArrayArg: T[]): plugins.q.Promise<void> {
|
|
|
|
let done = plugins.q.defer<void>()
|
|
|
|
let checkDocPromiseArray: plugins.q.Promise<void>[] = []
|
2016-11-17 21:36:12 +00:00
|
|
|
for (let docArg of docArrayArg) {
|
2016-09-12 16:14:01 +00:00
|
|
|
checkDocPromiseArray.push(this.checkDoc(docArg))
|
|
|
|
}
|
|
|
|
plugins.q.all(checkDocPromiseArray).then(() => {
|
2016-11-17 21:36:12 +00:00
|
|
|
if (this.db.dbType === 'mongodb') {
|
|
|
|
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)
|
|
|
|
}
|
2016-09-12 16:14:01 +00:00
|
|
|
})
|
|
|
|
return done.promise
|
|
|
|
}
|
2016-09-12 15:31:23 +00:00
|
|
|
|
2016-11-17 21:36:12 +00:00
|
|
|
/**
|
|
|
|
* checks a Doc for constraints
|
|
|
|
*/
|
|
|
|
private checkDoc(docArg: T): plugins.q.Promise<void> {
|
2016-09-12 16:14:01 +00:00
|
|
|
let done = plugins.q.defer<void>()
|
2016-11-17 21:36:12 +00:00
|
|
|
let validationResult = true
|
|
|
|
if (this.objectValidation) {
|
|
|
|
validationResult = this.objectValidation(docArg)
|
|
|
|
}
|
|
|
|
if (validationResult) {
|
|
|
|
done.resolve()
|
|
|
|
} else {
|
|
|
|
done.reject('validation of object did not pass')
|
|
|
|
}
|
2016-09-12 16:14:01 +00:00
|
|
|
return done.promise
|
2016-09-12 15:31:23 +00:00
|
|
|
}
|
2016-09-11 16:01:46 +00:00
|
|
|
}
|