0.1.38
processing.js added default ready command for socket removed arrow functions from socket cmd functions must Always be regular functions for setting context base.js better validation and defaults for options to registerSocket add by default a ready observer for when socket starts listeningmaster
parent
a47144606a
commit
a6d928bf56
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@uci/base",
|
"name": "@uci/base",
|
||||||
"version": "0.1.37",
|
"version": "0.1.38",
|
||||||
"description": "Multi type and transport JSON packet communication base class. Used in UCI extended classes",
|
"description": "Multi type and transport JSON packet communication base class. Used in UCI extended classes",
|
||||||
"main": "src/base",
|
"main": "src/base",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
64
src/base.js
64
src/base.js
|
@ -62,7 +62,8 @@ const TRANSLATE = {
|
||||||
class Base extends EventEmitter {
|
class Base extends EventEmitter {
|
||||||
constructor(opts = {}) {
|
constructor(opts = {}) {
|
||||||
super()
|
super()
|
||||||
this.id = opts.id || opts.name || 'uci-base:' + new Date().getTime()
|
this.name = opts.name || opts.appName || 'a base class instance'
|
||||||
|
this.id = opts.id || 'uci-base:' + new Date().getTime()
|
||||||
log = logger({ name: 'base', id: this.id })
|
log = logger({ name: 'base', id: this.id })
|
||||||
this.desc = opts.desc // additional details for humans
|
this.desc = opts.desc // additional details for humans
|
||||||
this._socket = {} // holds all the various communication sockets
|
this._socket = {} // holds all the various communication sockets
|
||||||
|
@ -71,37 +72,31 @@ class Base extends EventEmitter {
|
||||||
this.retryWait = opts.retryWait
|
this.retryWait = opts.retryWait
|
||||||
this.defaultReturnCmd = opts.defaultReturnCmd
|
this.defaultReturnCmd = opts.defaultReturnCmd
|
||||||
this._cmdProcessors = { _default: cmdProcessor }
|
this._cmdProcessors = { _default: cmdProcessor }
|
||||||
|
this.ready = new Ready({emitter: this})
|
||||||
// _c and _s are the default namespaces
|
// _c and _s are the default namespaces
|
||||||
this._namespaces =Object.assign({},namespaces)
|
this._namespaces =Object.assign({},namespaces)
|
||||||
this._c = Object.assign({},defaultCmds.c)
|
this._c = Object.assign({},defaultCmds.c)
|
||||||
this._s = Object.assign({},defaultCmds.s)
|
this._s = Object.assign({},defaultCmds.s)
|
||||||
|
// make available a method that will bind a whole object tree of functions
|
||||||
|
// Note: functions called via a command namespace are called by base connext by default
|
||||||
|
// if called directlly/locally they should be bound to base context if desired
|
||||||
|
this.bindFuncs = bindFuncs
|
||||||
if (opts.useRootNS) {
|
if (opts.useRootNS) {
|
||||||
// add root of instance to checking for command functions - not recommended!
|
// add root of instance to checking for command functions - not recommended!
|
||||||
this._namespaces.s.splice(-1, 0, null)
|
this._namespaces.s.splice(-1, 0, null)
|
||||||
this._namespaces.c.splice(-1, 0, null)
|
this._namespaces.c.splice(-1, 0, null)
|
||||||
}
|
}
|
||||||
// method that will bind a whole object tree of functions
|
// this.bindFuncs = bindFuncs // make available a method that will bind a whole object tree of functions
|
||||||
this.bindFuncs = bindFuncs
|
this._socket = {} // where all sockets are stored
|
||||||
// predefined sockets:
|
// at creation defined sockets:
|
||||||
// comma delimited list of this form '<name>#<c/p/s>><n=np/t=tcp/m=mqtt/w=web>'
|
if (opts.port) this.registerSocket(`${opts.name||'base'}${opts.port&&opts.path ? ':t':''}`,'s','t',{port:opts.port})
|
||||||
this._socket = {}
|
if (opts.path) this.registerSocket(`${opts.name||'base'}${opts.port&&opts.path ? ':n':''}`,'s','n',{path: opts.path})
|
||||||
if (opts.sockets) {
|
if (opts.sockets) {
|
||||||
opts.sockets.split(/[,|\s]+/).forEach(socketStr => {
|
let sockets = opts.sockets
|
||||||
let socket = {}
|
sockets = Array.isArray(sockets) ? sockets:[sockets]
|
||||||
socketStr.split(/[>#]+/).map(function(prop, index) {
|
sockets.forEach(socket => this.registerSocket(socket))
|
||||||
socket[SOCKET_INFO_KEYS[index]] = prop
|
|
||||||
})
|
|
||||||
this.registerSocket(
|
|
||||||
socket.name,
|
|
||||||
socket.type,
|
|
||||||
socket.transport,
|
|
||||||
opts[socket.name]
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ready = new Ready({emitter: this, verbose:process.env.UCI_READY_VERBOSE})
|
|
||||||
|
|
||||||
} // end constructor
|
} // end constructor
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -187,16 +182,23 @@ class Base extends EventEmitter {
|
||||||
* @returns {function} if called before base initialzation it can be ignored as all added sockets will be initialized. After through it be called to initialize that socket
|
* @returns {function} if called before base initialzation it can be ignored as all added sockets will be initialized. After through it be called to initialize that socket
|
||||||
*/
|
*/
|
||||||
registerSocket(name, type = 'c', transport = 'n', options = {}) {
|
registerSocket(name, type = 'c', transport = 'n', options = {}) {
|
||||||
|
// console.log('=========================================REGISTER=========',name)
|
||||||
|
if (isPlainObject(name)) ({name, type = 'c', transport = 'n', options = {}} = name)
|
||||||
|
if (typeof name !=='string') return null
|
||||||
transport = this._validateTransport(transport)
|
transport = this._validateTransport(transport)
|
||||||
log.debug({ socketName: name, type: type, tranport: transport, options: options, method:'addSocket', line:147, msg:`adding socket ${name}`})
|
// console.log({ socketName: name, type: type, tranport: transport, options: options, method:'addSocket', line:198, msg:`adding socket ${name}`})
|
||||||
options.id = options.id || this.id + ':' + name
|
options.id = options.id || name
|
||||||
if (type==='c') options = Object.assign({initTimeout:this.initTimeout, retryWait:this.retryWait},options)
|
options.name = options.name || name
|
||||||
if (type==='s') options = Object.assign({defaultReturnCmd:this.defaultReturnCmd},options)
|
// TODO add a 'd' type for duplex which creates an 's' first and waits on connect to make a 'c'
|
||||||
|
if (type==='c') options = Object.assign({initTimeout:this.initTimeout, retryWait:this.retryWait},options) // outbound
|
||||||
|
if (type==='s') options = Object.assign({defaultReturnCmd:this.defaultReturnCmd},options) // inbound
|
||||||
|
// TODO get rid of hard coded transports and use registered transports (t and n being default)
|
||||||
switch (transport) {
|
switch (transport) {
|
||||||
case 'n':
|
case 'n':
|
||||||
options.path = options.path || true
|
options.path = options.path || true
|
||||||
// falls through
|
// falls through
|
||||||
case 't':
|
case 't':
|
||||||
|
// console.log('==========socket options==========\n',name,type,transport,options)
|
||||||
this._socket[name] = new Socket[TRANSLATE[type]](options)
|
this._socket[name] = new Socket[TRANSLATE[type]](options)
|
||||||
break
|
break
|
||||||
case 'm':
|
case 'm':
|
||||||
|
@ -232,16 +234,20 @@ class Base extends EventEmitter {
|
||||||
this.emit(event,obj)
|
this.emit(event,obj)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
if (type==='c') {
|
if (type==='c') {
|
||||||
|
this.ready.addObserver(name,this._socket[name],{event:'connection:socket',condition:ev=>{return ev.state==='connected'}})
|
||||||
this.ready.addObserver(name,this.getSocket(name),{event:'connection:socket',condition:ev=>{return ev.state==='connected'}})
|
|
||||||
|
|
||||||
this._socket[name].on('pushed', packet => {
|
this._socket[name].on('pushed', packet => {
|
||||||
packet._header.socketName=name
|
packet._header.socketName=name
|
||||||
this.emit('pushed', packet)
|
this.emit('pushed', packet)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type==='s') {
|
||||||
|
// this._socket[name].on('socket',ev=>console.log(ev))
|
||||||
|
this.ready.addObserver(name,this._socket[name],{ event:'socket', condition: ev => (ev || {}).state ==='listening' })
|
||||||
|
}
|
||||||
|
|
||||||
return this.getSocketInit(name) // returns the init function (e.g. connect or create) for the socket
|
return this.getSocketInit(name) // returns the init function (e.g. connect or create) for the socket
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -634,12 +640,12 @@ class Base extends EventEmitter {
|
||||||
packet.cmd,
|
packet.cmd,
|
||||||
this._namespaces[this._type(socket) + this._transport(socket)]
|
this._namespaces[this._type(socket) + this._transport(socket)]
|
||||||
)
|
)
|
||||||
if (cmd_func) return await cmd_func.bind(this)(packet) // todo try .call
|
if (cmd_func) return await cmd_func.call(this,packet) // todo try .call
|
||||||
cmd_func = this._getCmdFuncNamespace(
|
cmd_func = this._getCmdFuncNamespace(
|
||||||
packet.cmd,
|
packet.cmd,
|
||||||
this._namespaces[this._type(socket)]
|
this._namespaces[this._type(socket)]
|
||||||
)
|
)
|
||||||
if (cmd_func) return await cmd_func.bind(this)(packet)
|
if (cmd_func) return await cmd_func.call(this,packet)
|
||||||
return 'failed'
|
return 'failed'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ let log = logger({ package: 'base',file:'processing.js'})
|
||||||
|
|
||||||
// common processor, will call based on type s or c the ones below
|
// common processor, will call based on type s or c the ones below
|
||||||
const cmdProcessor = async function (packet,socket) {
|
const cmdProcessor = async function (packet,socket) {
|
||||||
let [err,res] = await to(_process[this.getSocket(socket).type].bind(this)(packet,socket))
|
let [err,res] = await to(_process[this.getSocket(socket).type].call(this,packet,socket))
|
||||||
if (err) {
|
if (err) {
|
||||||
let error = {cmd:'error', error:err, packet:packet, socket:socket, function:'processor', line: 15, msg:`'unhandled error in packet command function ${packet.cmd}`}
|
let error = {cmd:'error', error:err, packet:packet, socket:socket, function:'processor', line: 15, msg:`'unhandled error in packet command function ${packet.cmd}`}
|
||||||
log.error(error)
|
log.error(error)
|
||||||
|
@ -21,8 +21,6 @@ const cmdProcessor = async function (packet,socket) {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
export { cmdProcessor, defaultCmds, namespaces }
|
|
||||||
|
|
||||||
// default processors for socket/server and consumer/client
|
// default processors for socket/server and consumer/client
|
||||||
const _process = {
|
const _process = {
|
||||||
s: async function (packet,socket) {
|
s: async function (packet,socket) {
|
||||||
|
@ -64,17 +62,23 @@ const namespaces = {
|
||||||
|
|
||||||
const defaultCmds ={
|
const defaultCmds ={
|
||||||
s:{
|
s:{
|
||||||
echo: async packet => {
|
echo: function (packet) {
|
||||||
packet.processed = true
|
packet.processed = true
|
||||||
packet.msg = 'default socket echo'
|
packet.msg = 'default socket echo'
|
||||||
return packet
|
return packet
|
||||||
},
|
},
|
||||||
// add sedning along an ack to any consumers and or pushing to other sockets on this device
|
// add sedning along an ack to any consumers and or pushing to other sockets on this device
|
||||||
ack: async packet => {
|
ack: async function (packet) {
|
||||||
packet.cmd = 'reply'
|
packet.cmd = 'reply'
|
||||||
packet.ack = true
|
packet.ack = true
|
||||||
packet.msg = 'this is the base default ack, superceed in your instance or extended class'
|
packet.msg = 'this is the base default ack, superceed in your instance or extended class'
|
||||||
return packet
|
return packet
|
||||||
|
},
|
||||||
|
ready: async function (packet) {
|
||||||
|
console.log('=========================READY RECEIVED AND EMITTED ======================================\n',packet)
|
||||||
|
packet.msg = 'ready state was emitted on receiving process'
|
||||||
|
this.emit(packet.event || packet.name || packet.id, !!(packet.ready || packet.value || packet.state))
|
||||||
|
return packet
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
c:{
|
c:{
|
||||||
|
@ -88,3 +92,5 @@ const defaultCmds ={
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { cmdProcessor, defaultCmds, namespaces }
|
||||||
|
|
Loading…
Reference in New Issue