0.1.3 basic working version with example using two service plugins (email and pushsafer)
commit
1fa512da93
|
@ -0,0 +1,38 @@
|
|||
module.exports = {
|
||||
"ecmaFeatures": {
|
||||
"modules": true,
|
||||
"spread" : true,
|
||||
"restParams" : true
|
||||
},
|
||||
// "plugins": [
|
||||
// "unicorn"
|
||||
// ],
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parser": 'babel-eslint',
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
2
|
||||
],
|
||||
// "unicorn/no-array-instanceof": "error",
|
||||
"no-console": 0,
|
||||
"semi": ["error", "never"],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/node_modules/
|
||||
.yalc
|
||||
/example/node_modules/
|
||||
*.lock
|
|
@ -0,0 +1,5 @@
|
|||
tests/
|
||||
test/
|
||||
*.test.js
|
||||
testing/
|
||||
example/
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Appzer.de Kevin Siml
|
||||
*
|
||||
* Forked from and original created by: Copyright (c) 2012 Aaron Bieber <deftly@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# UCI Notify
|
||||
|
||||
A live application notification system supporting notificaiton service plugins
|
||||
|
||||
## Quick Example App
|
||||
|
||||
* clone this repo
|
||||
* cd to example folder
|
||||
* `npm install` the pushsafter plugin and the email plugin (support smtp from gmail or aws/ses) will be loaded
|
||||
* modify options of the two services and choose some default message to send by uncommenting
|
||||
* `npm start`
|
||||
|
||||
## Usage
|
|
@ -0,0 +1,41 @@
|
|||
// import Notifier from '../src/notify.js'
|
||||
import Notifier from '@uci-utils/notify'
|
||||
|
||||
;(async () => {
|
||||
const notify = await Notifier.create({
|
||||
// one could read a file for these environment variables or hard code them here.
|
||||
services:{
|
||||
pushsafer:{
|
||||
module: '@uci-utils/notify-pushsafer-plugin',
|
||||
k: process.env.PS_API_KEY,
|
||||
d: process.env.PS_DEVICE_ID // device or group id
|
||||
},
|
||||
email:{
|
||||
module: '@uci-utils/notify-email-plugin',
|
||||
credentials:
|
||||
{ user: process.env.GMAIL_SMTP_USER,
|
||||
pass:process.env.GMAIL_SMTP_PW
|
||||
},
|
||||
to: process.env.NOTIFY_EMAIL_RECIPIENTS,
|
||||
subject:'uci notification'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// console.log (notify._services.pushsafer._req)
|
||||
// notify.disableService('pushsafer')
|
||||
// notify.enableService('pushsafer')
|
||||
// console.log(await notify.send('a test message','pushsafer'))
|
||||
let res = await notify.send('simple message to all services')
|
||||
// let res = await notify.send({subject:'subject as message',text:'this details'})
|
||||
// if (res.error) console.log('errors',res)
|
||||
// else console.log(res)
|
||||
// res = await notify.send({subject:'object message',otherprop:'some object in body'})
|
||||
if (res.error) console.log('errors',res)
|
||||
// else console.log(res)
|
||||
|
||||
})().catch(err => {
|
||||
console.log('FATAL: UNABLE TO START NOTIFER! \n',err)
|
||||
process.exitCode = 1
|
||||
process.kill(process.pid, 'SIGINT')
|
||||
})
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "notify-example",
|
||||
"version": "1.0.0",
|
||||
"description": "notify example application",
|
||||
"main": "example.js",
|
||||
"scripts": {
|
||||
"start": "node -r esm example.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@uci-utils/notify": "^0.1.3",
|
||||
"@uci-utils/notify-email-plugin": "^0.1.5",
|
||||
"@uci-utils/notify-pushsafer-plugin": "^0.1.2",
|
||||
"esm": "^3.2.25"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "@uci-utils/notify",
|
||||
"version": "0.1.3",
|
||||
"description": "Integrated Notification System with service plugins",
|
||||
"main": "src/notify",
|
||||
"scripts": {
|
||||
"example:dev": "./node_modules/.bin/nodemon -r esm ./examples/example.js",
|
||||
"test": "./node_modules/.bin/mocha -r esm --timeout 30000"
|
||||
},
|
||||
"author": "David Kebler",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/uCOMmandIt/uci-utils.git"
|
||||
},
|
||||
"keywords": [
|
||||
"node.js",
|
||||
"notify",
|
||||
"notifications"
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/uCOMmandIt/uci-utils/issues"
|
||||
},
|
||||
"homepage": "https://github.com/uCOMmandIt/uci-utils#readme",
|
||||
"dependencies": {
|
||||
"app-root-path": "^3.0.0",
|
||||
"await-to-js": "^2.1.1",
|
||||
"jsonfile": "^6.0.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
// 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 }
|
Loading…
Reference in New Issue