meses-messaging
Version:
Meses messaging SDK in JavaScript
225 lines (202 loc) • 7.68 kB
JavaScript
import MesesMessagingService from './services/MesesMessagingService'
import Conversation from './classes/Conversation'
import PreviousConversationListQuery from './classes/PreviousConversationListQuery'
import ConversationUpdateHandler from './classes/ConversationUpdateHandler'
import NewMessageUpdateHandler from './classes/NewMessageUpdateHandler'
class MesesMessagingApp {
constructor(uri, applicationId) {
this._service = new MesesMessagingService(uri, applicationId)
this._user = null
this._updateHandlers = []
}
onBeforeDisconnect() { }
/**
* Connect client app with a user
*
* @param {String} username - an entity name
* @return {Promise} user and its properties if connect succeeded (fulfilled).
*/
connect(username) {
if (this._user && this._user.username != username) {
this.onBeforeDisconnect()
this.detachAllUpdateHandlers()
}
const service = this._service
return new Promise(function(resolve, reject) {
service.getEntity(username)
.then(function(result) {
this._user = Object.assign({ username: username }, result)
resolve(this._user)
}.bind(this))
.catch(err => reject(err))
}.bind(this))
}
/**
* Disconnect client app from the connected user
* This method will also detach all update handlers
*
* @return {Promise} fulfilled if disconnect succeeded.
*/
disconnect() {
return new Promise(function(resolve, reject) {
if (this._user == null) reject('USER_NOT_CONNECTED')
else {
this.onBeforeDisconnect()
this.detachAllUpdateHandlers()
this._user = null; resolve()
}
}.bind(this))
}
/**
* Create a new entity with the specified properties
*
* @param {String} username - entity name of the new user
* @param {String} displayName - name that will be displayed in messaging UI
* @param {Object} properties
* @return {Promise} new user and its properties if user creation succeeded (fulfilled).
*/
createUser(username, displayName, properties) {
const service = this._service
return new Promise(function(resolve, reject) {
service.checkEntityNotExists(username)
.then(result => { service.createEntity(username, displayName, properties) })
.then(() => { resolve(Object.assign({ username: username }, properties)) })
.catch(err => reject(err))
})
}
/**
* Append/update properties of the currently connected user.
* This method will also update the connected user with new properties.
*
* @param {Object} properties
* @return {Promise} new user state if update user succeeded (fulfilled).
*/
updateUserInfo(properties) {
return new Promise(function(resolve, reject) {
if (this._user == null) {
reject('USER_NOT_CONNECTED')
} else {
const username = this._user.username
const service = this._service
service.upsertEntityProperties(username, properties)
.then(function() {
this._user = Object.assign(this._user, properties)
resolve(this._user)
}.bind(this))
.catch(err => reject(err))
}
}.bind(this))
}
/**
* Retrieve a conversation object of the specified conversation name.
*
* @param {String} conversationName
* @return {Promise} Conversation and its properties if retrieval succeeded (fulfilled).
*/
getConversation(conversationName) {
if (this._user == null)
return new Promise(function(resolve, reject) { reject('USER_NOT_CONNECTED')} )
const username = this._user.username
const service = this._service
return new Promise(function(resolve, reject) {
service.getConversation(conversationName)
.then(properties => resolve(new Conversation(service, conversationName, username, properties)))
.catch(err => reject(err))
})
}
/**
* Create a new conversation with specified properties and subscribers
*
* @param {String} conversationName
* @param {String} title
* @param {Object} properties
* @param {Array.<String>} subscribers - array of subscriber names
* @return {Promise} Conversation and its properties if creation succeeded (fulfilled).
*/
createConversation(conversationName, title, properties, subscribers) {
if (this._user == null)
return new Promise(function(resolve, reject) { reject('USER_NOT_CONNECTED') })
const username = this._user.username
const service = this._service
return new Promise(function(resolve, reject) {
service.checkConversationNotExists(conversationName)
.then(() => service.createConversation(conversationName, title, properties))
.then(() => {
let found = subscribers.find(name => name === username)
if (!found) subscribers.push(username)
return service.createSubscriptions(conversationName, subscribers)
})
.then(() => service.getConversation(conversationName))
.then(result => { resolve(new Conversation(service, conversationName, username, result)) })
.catch(err => reject(err))
})
}
/**
* Create a previous conversation list query.
*
* @param {Number} start - query param for first conversation's message time
* @return {PreviousConversationListQuery}
* @throws {Error} if user is not connected
*/
createPreviousConversationListQuery(start) {
if (this._user == null) throw new Error('USER_NOT_CONNECTED')
start = start ? start : null
const service = this._service
const username = this._user.username
return new PreviousConversationListQuery(service, username, start)
}
/**
* Create a conversation update handler.
*
* @param {String} identifier - unique identifier of update handler
* @param {Function(err, result)} callback function for conversation updates
* @param {Number} timeout - refresh rate (in milliseconds)
* @return {ConversationUpdateHandler}
* @throws {Error} if user is not connected
*/
createConversationUpdateHandler(identifier, callback, timeout) {
if (this._user == null) throw new Error('USER_NOT_CONNECTED')
const service = this._service
const username = this._user.username
return new ConversationUpdateHandler(service, username, identifier, callback, timeout)
}
/**
* Attach an update handler
*
* @param {ConversationUpdateHandler | NewMessageUpdateHandler} handler - update handler
* @return {Void}
* @throws {Error} if invalid handler type
*/
attachUpdateHandler(handler) {
if (handler instanceof ConversationUpdateHandler || handler instanceof NewMessageUpdateHandler) {
let found = this._updateHandlers.find(x => {
return x._identifier === handler._identifier && x.constructor.name === handler.constructor.name
})
if (found == null) {
this._updateHandlers.push(handler)
handler.activate()
}
} else throw new Error('INVALID_HANDLER_TYPE')
}
/**
* Detach all update handlers
*
* @return {Void}
*/
detachAllUpdateHandlers() { this._updateHandlers.map(x => x.destroy()); this._updateHandlers = [] }
/**
* Detach update handler with specified identifier
*
* @param {String} identifier
* @return {Void}
*/
detachUpdateHandler(identifier) {
let indexes = []
this._updateHandlers.map(function(x, i) {
if (x._identifier === identifier) { x.destroy(); indexes.push(i) }
})
indexes.reverse()
indexes.map(function(x) { this._updateHandlers.splice(x, 1) } .bind(this))
}
}
export default MesesMessagingApp