uci-base/src/base.mjs

160 lines
4.6 KiB
JavaScript

// import { Socket, Consumer } from '@uci/socket'
import UCISocket from '../../uci-socket/src'
import EventEmitter from 'events'
import { processor, commands } from './processing.mjs'
export default class Base extends EventEmitter {
constructor(opts={}) {
super()
this.id = opts.id || opts.name || 'uci-base:'+ new Date().getTime()
this.desc = opts.desc // additional details for humans
this.socket={}
this._processors = { _default: processor }
this._defaultCmds = commands
opts.sockets.split(/[,|\s]+/).forEach( socketStr => {
let socket = {}
socketStr.split(/[>#]+/).map(function(prop,index) {
socket[SOCKET_INFO_KEYS[index]] = prop
})
if (!opts[socket.name]) opts[socket.name] = {}
if (socket.transport ==='n') opts[socket.name].np = true
opts[socket.name].id = this.id +':'+ socket.name
// console.log(TRANSLATIONS[socket.type])
this.socket[socket.name] = new UCISocket[TRANSLATE[socket.type]](opts[socket.name])
// console.log(socket.name, this.socket[socket.name].send)
Object.assign(this.socket[socket.name],socket) // copy socket info props to new socket
this.socket[socket.name]._packetProcess = this._packetProcess.bind(this,socket.name)
})
} // end constructor
async init () {
let sockets = []
for(let name of Object.keys(this.socket)){
if (this.socket[name].type ==='s') {
sockets.push(this.socket[name].create())
// setTimeout(this.socket[type].create,200) // test for consumer retry for delayed socket creation
}
else {
sockets.push(this.socket[name].connect())
}
}
await Promise.all(sockets)
} // init
async send (name, packet) {
if (typeof name === 'string') {
if (this.socket[name]) await this.socket[name].send(packet)
}
else {
packet = name
for(let name of Object.keys(this.socket)){
if (this.socket[name].type ==='c') {
await this.socket[name].send(packet)
}
}
}
this.emit('packet', packet) // emits on instance for instance use
}
getSocket(name) {return this.socket[name]}
getCmdFunc (cmd,obj) {
if (typeof cmd ==='string') {
if (typeof obj ==='string' || obj === null) cmd = obj+'.'+cmd
cmd=cmd.split(/[.:]+/)
obj = this
// console.log('===================',cmd, this.id)
}
var prop=cmd.shift()
if (cmd.length === 0) return obj[prop]
if(!obj[prop]) return null
// console.log(cmd.length,cmd,prop, obj[prop])
return this.getCmdFunc(cmd, obj[prop])
}
sendSocket(name) {}
sendTransport(trans) {}
amendConsumerProcessing(funcs,trans) {
if (trans) {
if (!this._defaultCmds.c[trans]) this._defaultCmds.c[trans] ={}
Object.assign(this._defaultCmds.c[trans],funcs)
}
Object.assign(this._defaultCmds.c,funcs)
}
amendSocketProcessing(funcs,trans) {
if (trans) {
if (!this._defaultCmds.c[trans]) this._defaultCmds.c[trans] ={}
Object.assign(this._defaultCmds.c[trans],funcs)
}
Object.assign(this._defaultCmds.c,funcs)
}
// use s: and c: keys TODO need to change this
addNamedProcessing(name,funcs,type) {
if (type){
if(!this._cmds[name][type]) this._cmds[name][type] = {}
Object.assign(this._cmds[name][type],funcs)
} else {
if(!this._cmds[name]) this._cmds[name] ={}
Object.assign(this._cmds[name],funcs)
}
}
beforeHook (type,funcs){}
afterHook(type,funcs){}
// here you can add namespaced functions for packet commands
consumersProcessor(func) {
for(let name of Object.keys(this.socket)){
if (this.socket[name].type ==='c') {
this.socketNamedProcessor(func,name)
}
}
}
socketsProcessor(func) {
for(let name of Object.keys(this.socket)){
if (this.socket[name].type ==='s') {
this.socketNamedProcessor(func,name)
}
}
}
socketNameProcessor(func,socket_name) {
socket_name = socket_name || '_default'
this._processors[socket_name]._process = func
}
packetProcessor(func) {
this._packetProcess = func
}
/*
*
* Private Methods
*
*/
_transport(name) {return this.socket[name].transport}
_type(name) {return this.socket[name].type}
/*
**********default packet processor for all sockets
*/
async _packetProcess (socket_name,packet) {
let processor = packet._processor || this._processors[socket_name] || '_default'
return await this._processors[processor].bind(this)(packet,socket_name,this._processors[processor])
}
} // end class
const SOCKET_INFO_KEYS = ['name','type','transport']
const TRANSLATE= {n:'Named Pipe',t:'TCP',s:'Socket',c:'Consumer'}