UNPKG

blow-data

Version:
187 lines (186 loc) 6.2 kB
'use strict'; const util_1 = require('util'); const rxjs_1 = require('rxjs'); const mongodb = require('mongodb'); const blow_query_1 = require('blow-query'); const Adapter_1 = require('./Adapter'); const DEFAULT_ID_PROPERTY_NAME = '_id'; const DEFAULT_ID_PROPERTY_TYPE = 'string'; function connect(url) { return rxjs_1.Observable.create(observer => { mongodb.MongoClient.connect(url, (err, db) => { if (err) { observer.error(err); } else { observer.next(db); } }); }); } class MongoDBAdapter extends Adapter_1.Adapter { get idPropertyName() { return DEFAULT_ID_PROPERTY_NAME; } get idPropertyType() { return DEFAULT_ID_PROPERTY_TYPE; } _connect() { return connect(MongoDBAdapter.getConnectionUrl(this._options)) .map(db => { this._db = db; return this; }); } _collection(metadata) { return this._db.collection(metadata.pluralName); } _prepareQuery(query) { if (query) { if (query instanceof blow_query_1.Query) { query = query.toJSON(); } } return query; } count(metadata, where) { return rxjs_1.Observable.from(this._collection(metadata).count(where)); } create(metadata, data) { return rxjs_1.Observable.from(this._collection(metadata).insertOne(MongoDBAdapter.toDB(metadata, data))) .map(result => MongoDBAdapter.fromDB(metadata, result['ops'][0])); } destroy(metadata, where) { return rxjs_1.Observable.from(this._collection(metadata).deleteMany(where)) .map(result => result['deletedCount']); } destroyById(metadata, id) { return this.destroy(metadata, MongoDBAdapter.buildWhereWithId(metadata, id)).map(count => !!count); } exists(metadata, id) { return this.findById(metadata, id).map(row => !!row); } find(metadata, query) { const q = this._prepareQuery(query); let exec = this._collection(metadata).find(q.where); if (q.limit) { exec = exec.limit(q.limit); } if (q.skip) { exec = exec.skip(q.skip); } if (q.sort) { exec = exec.sort(q.sort); } return rxjs_1.Observable.from(exec.toArray()) .mergeMap(rows => rxjs_1.Observable.from(rows)) .map(row => MongoDBAdapter.fromDB(metadata, row)); } findOne(metadata, query) { query = this._prepareQuery(query); query['limit'] = 1; return this.find(metadata, query); } findById(metadata, id) { const where = MongoDBAdapter.buildWhereWithId(metadata, id); return this.find(metadata, { where: where, limit: 1 }); } findOrCreate(metadata, where, data) { return rxjs_1.Observable.create(observer => { const emit = row => { observer.next(row); observer.complete(); }; this.findOne(metadata, { where: where }) .subscribe(emit, err => observer.error(err), () => { this.create(metadata, MongoDBAdapter.toDB(metadata, data)) .subscribe(emit); }); }); } update(metadata, where, data) { return rxjs_1.Observable.from(this._collection(metadata).updateMany(where, { $set: data })) .map(result => result['modifiedCount']); } updateOrCreate(metadata, data) { const idName = metadata.idProperty.name; if (data[idName]) { return this.exists(metadata, data[idName]).mergeMap(exists => { if (exists) { return this.update(metadata, { _id: data[idName] }, data).mapTo(data); } else { return this.create(metadata, data); } }); } else { return this.create(metadata, data); } } static toDB(metadata, data) { const idName = metadata.idProperty.name; const idValue = data[idName]; if (util_1.isNull(idValue)) { delete data[idName]; } else { data[DEFAULT_ID_PROPERTY_NAME] = this.buildId(idValue); if (idName !== DEFAULT_ID_PROPERTY_NAME) { delete data[idName]; } } return data; } static fromDB(metadata, data) { const idName = metadata.idProperty.name; if (!data) { return null; } if (data[DEFAULT_ID_PROPERTY_NAME]) { data[idName] = data[DEFAULT_ID_PROPERTY_NAME].toHexString(); if (idName !== DEFAULT_ID_PROPERTY_NAME) { delete data[DEFAULT_ID_PROPERTY_NAME]; } } return data; } static buildWhereWithId(metadata, id) { const idKey = metadata.idProperty.name; const where = {}; where[idKey] = id; return this.buildWhere(metadata, where); } static buildWhere(metadata, where) { where = where || {}; const idKey = metadata.idProperty.name; return Object.keys(where).reduce((w, k) => { if (k === idKey) { w[DEFAULT_ID_PROPERTY_NAME] = this.buildId(where[k]); if (idKey !== DEFAULT_ID_PROPERTY_NAME) { delete w[idKey]; } } else { w[k] = where[k]; } return w; }, {}); } static buildId(id) { if (id instanceof mongodb.ObjectID) { return id; } return new mongodb.ObjectID(id); } static getConnectionUrl(options) { if (!util_1.isUndefined(options.url)) { return options.url; } else { const auth = (options.user && options.password) ? [options.user, options.password].join(':') : ''; return 'mongodb://' + (auth ? auth + '@' : '') + options.host + ':' + options.port + '/' + options.dbname; } } } exports.MongoDBAdapter = MongoDBAdapter;