xuanxuan
Version:
企业即时通讯平台
343 lines (312 loc) • 9.66 kB
JavaScript
import {Entity} from './entities';
import R from '../resource';
import PouchDB from '../assets/pouchdb';
import Member from 'Models/member';
if(DEBUG && process.type !== 'renderer') {
console.error('DAO must run in renderer process.');
}
/**
* The DAO handler
*/
class DAO {
/**
* Get database version
* @return {number}
*/
static get version() {
return 0; // change at 2017-01-12 16:27:15
}
/**
* Database access object constructor
* @param {User} user
* @return {Void}
*/
constructor(user, emiter) {
this.user = user;
this.emiter = emiter;
this._createDatabase();
/**
* Set or get inner values stored in this.$
* @return {Object}
*/
this.$ = function() {
let argumentsLength = arguments.length;
if(argumentsLength === 1) {
let arg = arguments[0];
if(typeof(arg) === 'object') {
Object.assign(this.$, arg);
} else {
return this.$[arg];
}
} else if(argumentsLength === 2) {
this.$[arguments[0]] = arguments[1];
}
return this;
};
this.$.members = [];
}
/**
* Emit event with given emiter
* @param {...Any} params
* @return {Void}
*/
_emit(...params) {
if(this.emiter && this.emiter.emit) {
this.emiter.emit(...params);
}
}
/**
* Set inner values
* @param {String|Object} key
* @param {Any} val
*/
$set(key, val) {
if(typeof(key) === 'object') {
Object.assign(this.$, key);
} else {
this.$[key] = val;
}
}
/**
* Get inner value
* @param {String} key
* @return {any}
*/
$get(key) {
return this.$[key];
}
/**
* Create database with PouchDB
* @return {PouchDB}
*/
_createDatabase() {
let dbName = this.user.identify;
this.db = new PouchDB(dbName, {
adapter: 'websql',
auto_compaction: true
});
let rebuildDb = (callback) => {
this.db.destroy().then(() => {
this.db = new PouchDB(dbName, {
adapter: 'websql',
auto_compaction: true
});
this.db.put({_id: '_local/config', version: DAO.version});
(typeof callback === 'function') && callback();
});
};
this.db.get('_local/config').then(config => {
if(config.version !== DAO.version) {
rebuildDb(() => {
this._emit(R.event.database_rebuild, {newVersion: DAO.version, oldVersion: config.version});
});
}
}).catch(rebuildDb);
this.db.info().then(result => {
console.groupCollapsed('%c DATABASE ' + dbName, 'display: inline-block; font-size: 10px; color: #fff; background: #3F51B5; padding: 1px 5px; border-radius: 2px;');
console.log(result);
console.groupEnd();
}).catch(err => {
console.groupCollapsed('%c DATABASE ' + dbName + ' with error', 'display: inline-block; font-size: 10px; color: #fff; background: #E91E63; padding: 1px 5px; border-radius: 2px;');
console.log(err);
console.groupEnd();
});
this.dbName = dbName;
return this.db;
}
/**
* Update or insert entities to database
* @param {Entity} entity
* @return {Promise}
*/
upsert(entities) {
if(Array.isArray(entities)) {
return Promise.all(entities.map(entity => this.upsert(entity)));
}
let entity = entities;
return new Promise((resolve, reject) => {
this.db.put(entity).then(resolve).catch(error => {
if(error.status === 409) {
this.db.get(entity._id).then(dbEntity => {
entity._rev = dbEntity._rev;
return this.db.put(entity);
}).then(response => {
resolve(response);
}).catch(reject);
} else {
// if(DEBUG) {
console.error('Database upsert error', error, entity, JSON.stringify(entity));
// }
reject(error)
}
});
});
}
/**
* Delete entity in local database
* @param {Entity} entity
* @return {Promise}
*/
delete(entity) {
entity._deleted = true;
if(!entity._rev) {
return this.db.get(entity._id).then(dbEntity => {
entity._rev = dbEntity._rev;
return this.db.remove(entity);
});
}
return this.db.remove(entity);
}
/**
* Get all entities
* @param {String} entityName
* @param {Object} options
* @return {Entity}
*/
all(entityName, options) {
return new Promise((resolve, reject) => {
this.db.allDocs(Object.assign({
include_docs: true,
startkey: entityName + '/',
endkey: entityName + '/\uffff',
}, options)).then(data => {
let indexOf = entityName.indexOf('/');
if(indexOf > -1) {
entityName = entityName.substring(0, indexOf);
}
resolve(data.rows.map(row => Entity.create(entityName, row.doc)));
}).catch(reject);
});
}
/**
* Get entity by given id
* @param {String} entityName/_id
* @param [Number] id entity remote id
* @return {Entity}
*/
get(/*(entityName, id) or (_id)*/) {
let _id = arguments.length > 1 ? (arguments[0] + '/' + arguments[1]) : arguments[0];
return new Promise((resolve, reject) => {
this.db.get(_id).then(data => {
resolve(Entity.create(data.typeName, data));
}).catch(reject);
});
}
/**
* Get members
* @param {Function | Array} condition optional
* @return {Array[Member]}
*/
getMembers(condition, sortList) {
if(typeof(condition) === 'function') {
let result = [];
Object.keys(this.$.members).forEach(x => {
let member = this.$.members[x];
if(condition(member)) {
result.push(member);
}
});
return result;
} else if(Array.isArray(condition)) {
let result = [];
condition.forEach(x => {
let member = this.getMember(x, true);
if(member) {
result.push(member);
}
});
return result;
}
let members = Object.keys(this.$.members).map(x => this.$.members[x]);
if(condition === true || sortList) members = Member.sort(members);
return members;
}
/**
* Get all members
* @return {Array}
*/
get members() {
return this.$.members;
}
/**
* Init members
* @param {Array} members
* @return {Void}
*/
initMembers(members) {
this.$.members = {};
members.forEach(member => {
member.isMyself = member.id === this.user.id;
this.$.members[member.id] = member;
});
this.upsert(members);
this._emit(R.event.data_change, {members: members});
}
/**
* Update members
* @param {Array} members
* @return {Void}
*/
updateMembers(members) {
if(!Array.isArray(members)) {
members = [members];
}
members.forEach(member => {
let savedMember = this.$.members[member.id];
if(savedMember) {
savedMember.assign(member);
} else {
this.$.members[member.id] = member;
}
});
this.upsert(members);
this._emit(R.event.data_change, {members: members});
}
/**
* Get member by id
* @param {number} id
* @return {Member}
*/
getMemberById(id) {
return this.$.members[id];
}
/**
* Get member
* @param {String | Number} idOrAccount
* @return {Member}
*/
getMember(idOrAccount) {
let member = this.$.members[idOrAccount];
if(!member) {
let findId = Object.keys(this.$.members).find(x => {
return this.$.members[x].account === idOrAccount;
});
if(findId) member = this.$.members[findId]
else {
member = new Member({
id: idOrAccount,
account: idOrAccount,
realname: '用户-' + idOrAccount
});
}
}
return member;
}
/**
* Guess member from id, account or realname
* @param {any} guess
* @return {Member}
*/
guessMember(guess) {
let member = this.getMemberById(guess);
if(!member) {
let findId = Object.keys(this.$.members).find(x => {
const xMember = this.$.members[x];
return xMember.account === guess || xMember.realname === guess;
});
if(findId) member = this.$.members[findId]
}
return member;
}
}
export default DAO;