// import RxClass from '@uci-utils/rx-class' import path from 'path' import { path as root } from 'app-root-path' import json from 'jsonfile' import to from 'await-to-js' const internal = Symbol('token for Notifier Instance') let inst class Notifier { constructor(token,opts={}){ if(token !== internal) { throw new Error('\'new Notifer\' not supported. Use the \'await Notifier.create()\' async static method') } // super(opts) this._services = {} this._disabled = [] this.services = opts.services || {} } // end constructor static async create(opts){ inst = new Notifier(internal,opts) console.log('notifcation service registrations:', await Promise.all( Object.entries(inst.services).map(async service => { return await inst.registerService.call(inst,service[0],service[1]) } ) ) ) return inst } async registerService(name,opts) { let mod; let file let dir = `${root}/node_modules/${opts.module || name}` let [err,pkg] = await to(json.readFile(dir+'/package.json')) if (!err) { file = (dir + '/' + (pkg.main ? pkg.main : 'index.js')) // eslint-disable-next-line let [err,res] = await to(import(file)) if (err) return `${name} failed - no file at ${file}` mod = res } else { // try in service directory for baked in plugins console.log(opts.module||name, ': no plugin found in node_modules, looking for internal module') let file = (`${path.dirname(__dirname)}/services/${name}.js`) // eslint-disable-next-line let [err,res] = await to(import(file)) if (err) return `${name} failed - no file at ${file}` mod = res } // delete opts.module const Service = mod.Service || mod.default if (!Service.prototype.constructor) { console.log('no default or "Service" class was exported from plugin') return `${name} failed` } else this._services[name] = new Service(opts) return `${name} registered` } disableService(name) { this._disabled.push(name) } enableService(name) { this._disabled= this._disabled.filter(service=>service!==name) } async send (msg,service,opts={}) { if (service) { if (this._services[service]) return await this._services[service].send(msg,opts) } let response = {} await Promise.all( Object.entries(this._services).map(async service => { let res = this._disabled.includes(service[0]) ? 'disabled' : await service[1].send(msg,opts[service[0]]) if (res.error) response.error ? response.error[service[0]] = res.error : response = { error:{[service[0]]:res.error}} response[service[0]]=res } ) ) return response } getService(name) { return this._services[name]} } // end Notifier class export default Notifier export { Notifier }