smartdata/ts/smartdata.classes.dbcollection.ts

118 lines
3.0 KiB
TypeScript
Raw Normal View History

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