blow-data-service
Version:
Observable data service for Blow.
164 lines (163 loc) • 5.03 kB
JavaScript
'use strict';
const rxjs_1 = require('rxjs');
const mongodb = require('mongodb');
const DataConnector_1 = require('./DataConnector');
class MongoClient {
static connect(url, options) {
return rxjs_1.Observable.from(mongodb.MongoClient.connect(url, options))
.map(db => new Db(db));
}
}
exports.MongoClient = MongoClient;
class Db {
constructor(db) {
this._db = db;
}
collection(name) {
return new Collection(this._db.collection(name));
}
delete() {
return rxjs_1.Observable.from(this._db.dropDatabase())
.mergeMap(() => this.close());
}
close() {
return rxjs_1.Observable.from(this._db.close());
}
}
exports.Db = Db;
class Collection {
constructor(collection) {
this._collection = collection;
}
find(query) {
query = Object.assign({}, { where: {} }, query || {});
let cursor = this._collection.find(query.where);
Object.keys(query).forEach(key => {
if (key !== 'where') {
cursor = cursor[key](query[key]);
}
});
return rxjs_1.Observable.create(subscriber => {
cursor.forEach(document => {
subscriber.next(document);
}, error => {
if (error) {
subscriber.error(error);
}
subscriber.complete();
});
});
}
count(query) {
query = query || {};
return rxjs_1.Observable.from(this._collection.count(query));
}
delete(query) {
query = query || {};
return rxjs_1.Observable.from(this._collection.deleteMany(query));
}
insert(doc) {
return rxjs_1.Observable.from(this._collection.insertOne(doc))
.map(response => response['ops'][0]);
}
update(query, doc, options) {
return rxjs_1.Observable.from(this._collection.updateOne(query, { $set: doc }, options))
.map(response => {
if (response['modifiedCount']) {
doc._id = query._id.toString();
return doc;
}
else {
return null;
}
});
}
}
exports.Collection = Collection;
class MongoDBConnector extends DataConnector_1.DataConnector {
_buildQueryWhereForId(id) {
return this._prepareQueryWhere({
_id: id
});
}
_normalizeId(value) {
let id;
try {
id = new mongodb.ObjectID(value);
}
catch (e) {
id = value;
}
return id;
}
_prepareQueryWhere(queryWhere) {
const where = {};
Object.keys(queryWhere).forEach(key => {
let value = queryWhere[key];
if (key === '_id') {
value = this._normalizeId(value);
}
where[key] = value;
});
return where;
}
_collection(collectionName) {
return this._db.collection(collectionName);
}
connect() {
this._state.connecting();
return rxjs_1.Observable.from(MongoClient.connect(this._settings['url']))
.do(db => {
this._db = db;
this._state.connected();
})
.mapTo(this);
}
disconnect() {
this._state.disconnecting();
return rxjs_1.Observable.from(this._db.close())
.do(() => this._state.disconnected())
.mapTo(this);
}
destroyDb() {
return this._db.delete();
}
find(collectionName, query) {
return this._collection(collectionName)
.find(this._prepareQuery(query));
}
count(collectionName, query) {
return this._collection(collectionName)
.count(this._prepareQuery(query).where);
}
delete(collectionName, query) {
return this._collection(collectionName)
.delete(this._prepareQuery(query).where)
.map(response => response['result'].n);
}
deleteById(collectionName, id) {
return this._collection(collectionName)
.delete(this._buildQueryWhereForId(id))
.map(response => response['result'].n === 1);
}
get(collectionName, id) {
return this._collection(collectionName)
.find({ where: this._buildQueryWhereForId(id) });
}
save(collectionName, doc) {
const hasId = Object.keys(doc).indexOf('_id') > -1 && doc['_id'];
if (!hasId) {
return this._collection(collectionName).insert(doc);
}
else {
return this._collection(collectionName).update(this._buildQueryWhereForId(doc['_id']), doc, { upsert: true });
}
}
updateAttributes(collectionName, id, attributes) {
delete attributes['_id'];
return this.get(collectionName, id)
.map(result => Object.assign(result, attributes))
.mergeMap(doc => this.save(collectionName, doc));
}
}
exports.MongoDBConnector = MongoDBConnector;